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