1*7f2fe78bSCy Schubertfrom k5test import * 2*7f2fe78bSCy Schubert 3*7f2fe78bSCy Schubert# Skip this test if we're missing proxy functionality or parts of the proxy. 4*7f2fe78bSCy Schubertif runenv.tls_impl == 'no': 5*7f2fe78bSCy Schubert skip_rest('HTTP proxy tests', 'TLS build support not enabled') 6*7f2fe78bSCy Schuberttry: 7*7f2fe78bSCy Schubert import kdcproxy 8*7f2fe78bSCy Schubertexcept: 9*7f2fe78bSCy Schubert skip_rest('HTTP proxy tests', 'Python kdcproxy module not found') 10*7f2fe78bSCy Schubert 11*7f2fe78bSCy Schubert# Construct a krb5.conf fragment configuring the client to use a local proxy 12*7f2fe78bSCy Schubert# server. 13*7f2fe78bSCy Schubertproxycerts = os.path.join(srctop, 'tests', 'proxy-certs') 14*7f2fe78bSCy Schubertproxysubjectpem = os.path.join(proxycerts, 'proxy-subject.pem') 15*7f2fe78bSCy Schubertproxysanpem = os.path.join(proxycerts, 'proxy-san.pem') 16*7f2fe78bSCy Schubertproxyidealpem = os.path.join(proxycerts, 'proxy-ideal.pem') 17*7f2fe78bSCy Schubertproxywrongpem = os.path.join(proxycerts, 'proxy-no-match.pem') 18*7f2fe78bSCy Schubertproxybadpem = os.path.join(proxycerts, 'proxy-badsig.pem') 19*7f2fe78bSCy Schubertproxyca = os.path.join(proxycerts, 'ca.pem') 20*7f2fe78bSCy Schubertproxyurl = 'https://localhost:$port5/KdcProxy' 21*7f2fe78bSCy Schubertproxyurlupcase = 'https://LocalHost:$port5/KdcProxy' 22*7f2fe78bSCy Schubertproxyurl4 = 'https://127.0.0.1:$port5/KdcProxy' 23*7f2fe78bSCy Schubertproxyurl6 = 'https://[::1]:$port5/KdcProxy' 24*7f2fe78bSCy Schubert 25*7f2fe78bSCy Schubertunanchored_krb5_conf = {'realms': {'$realm': { 26*7f2fe78bSCy Schubert 'kdc': proxyurl, 27*7f2fe78bSCy Schubert 'kpasswd_server': proxyurl}}} 28*7f2fe78bSCy Schubertanchored_name_krb5_conf = {'realms': {'$realm': { 29*7f2fe78bSCy Schubert 'kdc': proxyurl, 30*7f2fe78bSCy Schubert 'kpasswd_server': proxyurl, 31*7f2fe78bSCy Schubert 'http_anchors': 'FILE:%s' % proxyca}}} 32*7f2fe78bSCy Schubertanchored_upcasename_krb5_conf = {'realms': {'$realm': { 33*7f2fe78bSCy Schubert 'kdc': proxyurlupcase, 34*7f2fe78bSCy Schubert 'kpasswd_server': proxyurlupcase, 35*7f2fe78bSCy Schubert 'http_anchors': 'FILE:%s' % proxyca}}} 36*7f2fe78bSCy Schubertanchored_kadmin_krb5_conf = {'realms': {'$realm': { 37*7f2fe78bSCy Schubert 'kdc': proxyurl, 38*7f2fe78bSCy Schubert 'admin_server': proxyurl, 39*7f2fe78bSCy Schubert 'http_anchors': 'FILE:%s' % proxyca}}} 40*7f2fe78bSCy Schubertanchored_ipv4_krb5_conf = {'realms': {'$realm': { 41*7f2fe78bSCy Schubert 'kdc': proxyurl4, 42*7f2fe78bSCy Schubert 'kpasswd_server': proxyurl4, 43*7f2fe78bSCy Schubert 'http_anchors': 'FILE:%s' % proxyca}}} 44*7f2fe78bSCy Schubertkpasswd_input = (password('user') + '\n' + password('user') + '\n' + 45*7f2fe78bSCy Schubert password('user') + '\n') 46*7f2fe78bSCy Schubert 47*7f2fe78bSCy Schubertdef start_proxy(realm, keycertpem): 48*7f2fe78bSCy Schubert proxy_conf_path = os.path.join(realm.testdir, 'kdcproxy.conf') 49*7f2fe78bSCy Schubert proxy_exec_path = os.path.join(srctop, 'util', 'wsgiref-kdcproxy.py') 50*7f2fe78bSCy Schubert conf = open(proxy_conf_path, 'w') 51*7f2fe78bSCy Schubert conf.write('[%s]\n' % realm.realm) 52*7f2fe78bSCy Schubert conf.write('kerberos = kerberos://localhost:%d\n' % realm.portbase) 53*7f2fe78bSCy Schubert conf.write('kpasswd = kpasswd://localhost:%d\n' % (realm.portbase + 2)) 54*7f2fe78bSCy Schubert conf.close() 55*7f2fe78bSCy Schubert realm.env['KDCPROXY_CONFIG'] = proxy_conf_path 56*7f2fe78bSCy Schubert cmd = [sys.executable, proxy_exec_path, str(realm.server_port()), 57*7f2fe78bSCy Schubert keycertpem] 58*7f2fe78bSCy Schubert return realm.start_server(cmd, sentinel='proxy server ready') 59*7f2fe78bSCy Schubert 60*7f2fe78bSCy Schubert# Fail: untrusted issuer and hostname doesn't match. 61*7f2fe78bSCy Schubertmark('untrusted issuer, hostname mismatch') 62*7f2fe78bSCy Schubertoutput("running pass 1: issuer not trusted and hostname doesn't match\n") 63*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, 64*7f2fe78bSCy Schubert create_host=False) 65*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxywrongpem) 66*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 67*7f2fe78bSCy Schubertstop_daemon(proxy) 68*7f2fe78bSCy Schubertrealm.stop() 69*7f2fe78bSCy Schubert 70*7f2fe78bSCy Schubert# Fail: untrusted issuer, host name matches subject. 71*7f2fe78bSCy Schubertmark('untrusted issuer, hostname subject match') 72*7f2fe78bSCy Schubertoutput("running pass 2: subject matches, issuer not trusted\n") 73*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, 74*7f2fe78bSCy Schubert create_host=False) 75*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysubjectpem) 76*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 77*7f2fe78bSCy Schubertstop_daemon(proxy) 78*7f2fe78bSCy Schubertrealm.stop() 79*7f2fe78bSCy Schubert 80*7f2fe78bSCy Schubert# Fail: untrusted issuer, host name matches subjectAltName. 81*7f2fe78bSCy Schubertmark('untrusted issuer, hostname SAN match') 82*7f2fe78bSCy Schubertoutput("running pass 3: subjectAltName matches, issuer not trusted\n") 83*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, 84*7f2fe78bSCy Schubert create_host=False) 85*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysanpem) 86*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 87*7f2fe78bSCy Schubertstop_daemon(proxy) 88*7f2fe78bSCy Schubertrealm.stop() 89*7f2fe78bSCy Schubert 90*7f2fe78bSCy Schubert# Fail: untrusted issuer, certificate signature is bad. 91*7f2fe78bSCy Schubertmark('untrusted issuer, bad signature') 92*7f2fe78bSCy Schubertoutput("running pass 4: subject matches, issuer not trusted\n") 93*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=unanchored_krb5_conf, get_creds=False, 94*7f2fe78bSCy Schubert create_host=False) 95*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxybadpem) 96*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 97*7f2fe78bSCy Schubertstop_daemon(proxy) 98*7f2fe78bSCy Schubertrealm.stop() 99*7f2fe78bSCy Schubert 100*7f2fe78bSCy Schubert# Fail: trusted issuer but hostname doesn't match. 101*7f2fe78bSCy Schubertmark('trusted issuer, hostname mismatch') 102*7f2fe78bSCy Schubertoutput("running pass 5: issuer trusted but hostname doesn't match\n") 103*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_name_krb5_conf, get_creds=False, 104*7f2fe78bSCy Schubert create_host=False) 105*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxywrongpem) 106*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 107*7f2fe78bSCy Schubertstop_daemon(proxy) 108*7f2fe78bSCy Schubertrealm.stop() 109*7f2fe78bSCy Schubert 110*7f2fe78bSCy Schubert# Succeed: trusted issuer and host name matches subject. 111*7f2fe78bSCy Schubertmark('trusted issuer, hostname subject match') 112*7f2fe78bSCy Schubertoutput("running pass 6: issuer trusted, subject matches\n") 113*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_name_krb5_conf, start_kadmind=True, 114*7f2fe78bSCy Schubert get_creds=False) 115*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysubjectpem) 116*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user')) 117*7f2fe78bSCy Schubertrealm.run([kvno, realm.host_princ]) 118*7f2fe78bSCy Schubertrealm.run([kpasswd, realm.user_princ], input=kpasswd_input) 119*7f2fe78bSCy Schubertstop_daemon(proxy) 120*7f2fe78bSCy Schubertrealm.stop() 121*7f2fe78bSCy Schubert 122*7f2fe78bSCy Schubert# Succeed: trusted issuer and host name matches subjectAltName. 123*7f2fe78bSCy Schubertmark('trusted issuer, hostname SAN match') 124*7f2fe78bSCy Schubertoutput("running pass 7: issuer trusted, subjectAltName matches\n") 125*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_name_krb5_conf, start_kadmind=True, 126*7f2fe78bSCy Schubert get_creds=False) 127*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysanpem) 128*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user')) 129*7f2fe78bSCy Schubertrealm.run([kvno, realm.host_princ]) 130*7f2fe78bSCy Schubertrealm.run([kpasswd, realm.user_princ], input=kpasswd_input) 131*7f2fe78bSCy Schubertstop_daemon(proxy) 132*7f2fe78bSCy Schubertrealm.stop() 133*7f2fe78bSCy Schubert 134*7f2fe78bSCy Schubert# Fail: certificate signature is bad. 135*7f2fe78bSCy Schubertmark('bad signature') 136*7f2fe78bSCy Schubertoutput("running pass 8: issuer trusted and subjectAltName matches, sig bad\n") 137*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_name_krb5_conf, 138*7f2fe78bSCy Schubert get_creds=False, 139*7f2fe78bSCy Schubert create_host=False) 140*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxybadpem) 141*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 142*7f2fe78bSCy Schubertstop_daemon(proxy) 143*7f2fe78bSCy Schubertrealm.stop() 144*7f2fe78bSCy Schubert 145*7f2fe78bSCy Schubert# Fail: trusted issuer but IP doesn't match. 146*7f2fe78bSCy Schubertmark('trusted issuer, IP mismatch') 147*7f2fe78bSCy Schubertoutput("running pass 9: issuer trusted but no name matches IP\n") 148*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, get_creds=False, 149*7f2fe78bSCy Schubert create_host=False) 150*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxywrongpem) 151*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 152*7f2fe78bSCy Schubertstop_daemon(proxy) 153*7f2fe78bSCy Schubertrealm.stop() 154*7f2fe78bSCy Schubert 155*7f2fe78bSCy Schubert# Fail: trusted issuer, but subject does not match. 156*7f2fe78bSCy Schubertmark('trusted issuer, IP mismatch (hostname in subject)') 157*7f2fe78bSCy Schubertoutput("running pass 10: issuer trusted, but subject does not match IP\n") 158*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, get_creds=False, 159*7f2fe78bSCy Schubert create_host=False) 160*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysubjectpem) 161*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 162*7f2fe78bSCy Schubertstop_daemon(proxy) 163*7f2fe78bSCy Schubertrealm.stop() 164*7f2fe78bSCy Schubert 165*7f2fe78bSCy Schubert# Succeed: trusted issuer and host name matches subjectAltName. 166*7f2fe78bSCy Schubertmark('trusted issuer, IP SAN match') 167*7f2fe78bSCy Schubertoutput("running pass 11: issuer trusted, subjectAltName matches IP\n") 168*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, start_kadmind=True, 169*7f2fe78bSCy Schubert get_creds=False) 170*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysanpem) 171*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user')) 172*7f2fe78bSCy Schubertrealm.run([kvno, realm.host_princ]) 173*7f2fe78bSCy Schubertrealm.run([kpasswd, realm.user_princ], input=kpasswd_input) 174*7f2fe78bSCy Schubertstop_daemon(proxy) 175*7f2fe78bSCy Schubertrealm.stop() 176*7f2fe78bSCy Schubert 177*7f2fe78bSCy Schubert# Fail: certificate signature is bad. 178*7f2fe78bSCy Schubertmark('bad signature (IP hostname)') 179*7f2fe78bSCy Schubertoutput("running pass 12: issuer trusted, names don't match, signature bad\n") 180*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_ipv4_krb5_conf, get_creds=False, 181*7f2fe78bSCy Schubert create_host=False) 182*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxybadpem) 183*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, password=password('user'), expected_code=1) 184*7f2fe78bSCy Schubertstop_daemon(proxy) 185*7f2fe78bSCy Schubertrealm.stop() 186*7f2fe78bSCy Schubert 187*7f2fe78bSCy Schubert# Succeed: trusted issuer and host name matches subject, using kadmin 188*7f2fe78bSCy Schubert# configuration to find kpasswdd. 189*7f2fe78bSCy Schubertmark('trusted issuer, hostname subject match (kadmin)') 190*7f2fe78bSCy Schubertoutput("running pass 13: issuer trusted, subject matches\n") 191*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_kadmin_krb5_conf, start_kadmind=True, 192*7f2fe78bSCy Schubert get_creds=False, create_host=False) 193*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysubjectpem) 194*7f2fe78bSCy Schubertrealm.run([kpasswd, realm.user_princ], input=kpasswd_input) 195*7f2fe78bSCy Schubertstop_daemon(proxy) 196*7f2fe78bSCy Schubertrealm.stop() 197*7f2fe78bSCy Schubert 198*7f2fe78bSCy Schubert# Succeed: trusted issuer and host name matches subjectAltName, using 199*7f2fe78bSCy Schubert# kadmin configuration to find kpasswdd. 200*7f2fe78bSCy Schubertmark('trusted issuer, hostname SAN match (kadmin)') 201*7f2fe78bSCy Schubertoutput("running pass 14: issuer trusted, subjectAltName matches\n") 202*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_kadmin_krb5_conf, start_kadmind=True, 203*7f2fe78bSCy Schubert get_creds=False, create_host=False) 204*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysanpem) 205*7f2fe78bSCy Schubertrealm.run([kpasswd, realm.user_princ], input=kpasswd_input) 206*7f2fe78bSCy Schubertstop_daemon(proxy) 207*7f2fe78bSCy Schubertrealm.stop() 208*7f2fe78bSCy Schubert 209*7f2fe78bSCy Schubert# Succeed: trusted issuer and host name matches subjectAltName (give or take 210*7f2fe78bSCy Schubert# case). 211*7f2fe78bSCy Schubertmark('trusted issuer, hostname SAN case-insensitive match') 212*7f2fe78bSCy Schubertoutput("running pass 15: issuer trusted, subjectAltName case-insensitive\n") 213*7f2fe78bSCy Schubertrealm = K5Realm(krb5_conf=anchored_upcasename_krb5_conf, start_kadmind=True, 214*7f2fe78bSCy Schubert get_creds=False, create_host=False) 215*7f2fe78bSCy Schubertproxy = start_proxy(realm, proxysanpem) 216*7f2fe78bSCy Schubertrealm.run([kpasswd, realm.user_princ], input=kpasswd_input) 217*7f2fe78bSCy Schubertstop_daemon(proxy) 218*7f2fe78bSCy Schubertrealm.stop() 219*7f2fe78bSCy Schubert 220*7f2fe78bSCy Schubertsuccess('MS-KKDCP proxy') 221