Path: blob/main/crypto/krb5/src/tests/t_authdata.py
34878 views
from k5test import *12# Load the sample KDC authdata module. Allow renewable tickets.3greet_path = os.path.join(buildtop, 'plugins', 'authdata', 'greet_server',4'greet_server.so')5conf = {'realms': {'$realm': {'max_life': '20h', 'max_renewable_life': '20h'}},6'plugins': {'kdcauthdata': {'module': 'greet:' + greet_path}}}7realm = K5Realm(krb5_conf=conf)89# With no requested authdata, we expect to see PAC (128) in an10# if-relevant container and the greet authdata in a kdc-issued11# container.12mark('baseline authdata')13out = realm.run(['./adata', realm.host_princ])14if '?128: [6, 7, 10, 16, 19]' not in out or '^-42: Hello' not in out:15fail('expected authdata not seen for basic request')1617# Requested authdata is copied into the ticket, with KDC-only types18# filtered out. (128 is win2k-pac, which should be filtered.)19mark('request authdata')20out = realm.run(['./adata', realm.host_princ, '-5', 'test1', '?-6', 'test2',21'128', 'fakepac', '?128', 'ifrelfakepac',22'^-8', 'fakekdcissued', '?^-8', 'ifrelfakekdcissued'])23if ' -5: test1' not in out or '?-6: test2' not in out:24fail('expected authdata not seen for request with authdata')25if 'fake' in out:26fail('KDC-only authdata not filtered for request with authdata')2728mark('AD-MANDATORY-FOR-KDC')29realm.run(['./adata', realm.host_princ, '!-1', 'mandatoryforkdc'],30expected_code=1, expected_msg='KDC policy rejects request')3132# The no_auth_data_required server flag should suppress the PAC, but33# not module or request authdata.34mark('no_auth_data_required server flag')35realm.run([kadminl, 'ank', '-randkey', '+no_auth_data_required', 'noauth'])36realm.extract_keytab('noauth', realm.keytab)37out = realm.run(['./adata', 'noauth', '-2', 'test'])38if '^-42: Hello' not in out or ' -2: test' not in out:39fail('expected authdata not seen for no_auth_data_required request')40if '128: ' in out:41fail('PAC authdata seen for no_auth_data_required request')4243# Cross-realm TGT requests should not suppress PAC or request44# authdata.45mark('cross-realm')46realm.addprinc('krbtgt/XREALM')47realm.extract_keytab('krbtgt/XREALM', realm.keytab)48out = realm.run(['./adata', 'krbtgt/XREALM', '-3', 'test'])49if '128:' not in out or '^-42: Hello' not in out or ' -3: test' not in out:50fail('expected authdata not seen for cross-realm TGT request')5152mark('pac_privsvr_enctype')53# Change the privsvr enctype and make sure we can still verify the PAC54# on a service ticket in a TGS request.55realm.run([kadminl, 'setstr', realm.host_princ,56'pac_privsvr_enctype', 'aes128-sha1'])57realm.kinit(realm.user_princ, password('user'),58['-S', realm.host_princ, '-r', '1h'])59realm.kinit(realm.user_princ, None, ['-S', realm.host_princ, '-R'])60# Remove the attribute and make sure the previously-issued service61# ticket PAC no longer verifies.62realm.run([kadminl, 'delstr', realm.host_princ, 'pac_privsvr_enctype'])63realm.kinit(realm.user_princ, None, ['-S', realm.host_princ, '-R'],64expected_code=1, expected_msg='Message stream modified')6566realm.stop()6768if not pkinit_enabled:69skipped('anonymous ticket authdata tests', 'PKINIT not built')70else:71# Set up a realm with PKINIT support and get anonymous tickets.72realm = K5Realm(krb5_conf=conf, get_creds=False, pkinit=True)73realm.addprinc('WELLKNOWN/ANONYMOUS')74realm.kinit('@%s' % realm.realm, flags=['-n'])7576# PAC and module authdata should be suppressed for anonymous77# tickets, but not request authdata.78mark('anonymous')79out = realm.run(['./adata', realm.host_princ, '-4', 'test'])80if ' -4: test' not in out:81fail('expected authdata not seen for anonymous request')82if '128: ' in out or '-42: ' in out:83fail('PAC or greet authdata seen for anonymous request')8485realm.stop()8687# Test authentication indicators. Load the test preauth module so we88# can control the indicators asserted.89testpreauth = os.path.join(buildtop, 'plugins', 'preauth', 'test', 'test.so')90krb5conf = {'plugins': {'kdcpreauth': {'module': 'test:' + testpreauth},91'clpreauth': {'module': 'test:' + testpreauth}}}92realm, realm2 = cross_realms(2, args=({'realm': 'LOCAL'},93{'realm': 'FOREIGN'}),94krb5_conf=krb5conf, get_creds=False)95realm.run([kadminl, 'modprinc', '+requires_preauth', '-maxrenewlife', '2 days',96realm.user_princ])97realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.host_princ])98realm.run([kadminl, 'modprinc', '-maxrenewlife', '2 days', realm.krbtgt_princ])99realm.extract_keytab(realm.krbtgt_princ, realm.keytab)100realm.extract_keytab(realm.host_princ, realm.keytab)101realm.extract_keytab('krbtgt/FOREIGN', realm.keytab)102realm2.extract_keytab(realm2.krbtgt_princ, realm.keytab)103realm2.extract_keytab(realm2.host_princ, realm.keytab)104realm2.extract_keytab('krbtgt/LOCAL', realm.keytab)105106# AS request to local-realm service107mark('AS-REQ to local service auth indicator')108realm.kinit(realm.user_princ, password('user'),109['-X', 'indicators=indcl', '-r', '2d', '-S', realm.host_princ])110realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]')111112# Ticket modification request113mark('ticket modification auth indicator')114realm.kinit(realm.user_princ, None, ['-R', '-S', realm.host_princ])115realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]')116117# AS request to cross TGT118mark('AS-REQ to cross TGT auth indicator')119realm.kinit(realm.user_princ, password('user'),120['-X', 'indicators=indcl', '-S', 'krbtgt/FOREIGN'])121realm.run(['./adata', 'krbtgt/FOREIGN'], expected_msg='+97: [indcl]')122123# Multiple indicators124mark('AS multiple indicators')125realm.kinit(realm.user_princ, password('user'),126['-X', 'indicators=indcl indcl2 indcl3'])127realm.run(['./adata', realm.krbtgt_princ],128expected_msg='+97: [indcl, indcl2, indcl3]')129130# AS request to local TGT (resulting creds are used for TGS tests)131mark('AS-REQ to local TGT auth indicator')132realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=indcl'])133realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [indcl]')134135# Local TGS request for local realm service136mark('TGS-REQ to local service auth indicator')137realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]')138139# Local TGS request for cross TGT service140mark('TGS-REQ to cross TGT auth indicator')141realm.run(['./adata', 'krbtgt/FOREIGN'], expected_msg='+97: [indcl]')142143# We don't yet have support for passing auth indicators across realms,144# so just verify that indicators don't survive cross-realm requests.145mark('TGS-REQ to foreign service auth indicator')146out = realm.run(['./adata', realm2.krbtgt_princ])147if '97:' in out:148fail('auth-indicator seen in cross TGT request to local TGT')149out = realm.run(['./adata', 'krbtgt/LOCAL@FOREIGN'])150if '97:' in out:151fail('auth-indicator seen in cross TGT request to cross TGT')152out = realm.run(['./adata', realm2.host_princ])153if '97:' in out:154fail('auth-indicator seen in cross TGT request to service')155156# Test that the CAMMAC signature still works during a krbtgt rollover.157mark('CAMMAC signature across krbtgt rollover')158realm.run([kadminl, 'cpw', '-randkey', '-keepold', realm.krbtgt_princ])159realm.run(['./adata', realm.host_princ], expected_msg='+97: [indcl]')160161# Test indicator enforcement.162mark('auth indicator enforcement')163realm.addprinc('restricted')164realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'superstrong'])165realm.kinit(realm.user_princ, password('user'), ['-S', 'restricted'],166expected_code=1, expected_msg='KDC policy rejects request')167realm.run([kvno, 'restricted'], expected_code=1,168expected_msg='KDC policy rejects request')169realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'indcl'])170realm.run([kvno, 'restricted'])171realm.kinit(realm.user_princ, password('user'), ['-X', 'indicators=ind1 ind2'])172realm.run([kvno, 'restricted'], expected_code=1)173realm.run([kadminl, 'setstr', 'restricted', 'require_auth', 'a b c ind2'])174realm.run([kvno, 'restricted'])175176# Regression test for one manifestation of #8139: ensure that177# forwarded TGTs obtained across a TGT re-key still work when the178# preferred krbtgt enctype changes.179mark('#8139 regression test')180realm.kinit(realm.user_princ, password('user'), ['-f'])181realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'des3-cbc-sha1',182realm.krbtgt_princ])183realm.run(['./forward'])184realm.run([kvno, realm.host_princ])185186# Repeat the above test using a renewed TGT.187mark('#8139 regression test (renewed TGT)')188realm.kinit(realm.user_princ, password('user'), ['-r', '2d'])189realm.run([kadminl, 'cpw', '-randkey', '-keepold', '-e', 'aes128-cts',190realm.krbtgt_princ])191realm.kinit(realm.user_princ, None, ['-R'])192realm.run([kvno, realm.host_princ])193194realm.stop()195realm2.stop()196197# Load the test KDB module to allow successful S4U2Proxy198# auth-indicator requests and to detect whether replaced_reply_key is199# set.200testprincs = {'krbtgt/KRBTEST.COM': {'keys': 'aes128-cts'},201'krbtgt/FOREIGN': {'keys': 'aes128-cts'},202'user': {'keys': 'aes128-cts', 'flags': '+preauth'},203'user2': {'keys': 'aes128-cts', 'flags': '+preauth'},204'rservice': {'keys': 'aes128-cts',205'strings': 'require_auth:strong'},206'service/1': {'keys': 'aes128-cts',207'flags': '+ok_to_auth_as_delegate'},208'service/2': {'keys': 'aes128-cts'},209'noauthdata': {'keys': 'aes128-cts',210'flags': '+no_auth_data_required'}}211kdcconf = {'realms': {'$realm': {'database_module': 'test'}},212'dbmodules': {'test': {'db_library': 'test',213'princs': testprincs,214'delegation': {'service/1': 'service/2'}}}}215realm = K5Realm(krb5_conf=krb5conf, kdc_conf=kdcconf, create_kdb=False,216pkinit=True)217usercache = 'FILE:' + os.path.join(realm.testdir, 'usercache')218realm.extract_keytab(realm.krbtgt_princ, realm.keytab)219realm.extract_keytab('krbtgt/FOREIGN', realm.keytab)220realm.extract_keytab(realm.user_princ, realm.keytab)221realm.extract_keytab('ruser', realm.keytab)222realm.extract_keytab('service/1', realm.keytab)223realm.extract_keytab('service/2', realm.keytab)224realm.extract_keytab('noauthdata', realm.keytab)225realm.start_kdc()226227if not pkinit_enabled:228skipped('replaced_reply_key test', 'PKINIT not built')229else:230# Check that replaced_reply_key is set in issue_pac() when PKINIT231# is used. The test KDB module will indicate this by including a232# fake PAC_CREDENTIAL_INFO(2) buffer in the PAC.233mark('PKINIT (replaced_reply_key set)')234realm.pkinit(realm.user_princ)235realm.run(['./adata', realm.krbtgt_princ],236expected_msg='?128: [1, 2, 6, 7, 10]')237238# S4U2Self (should have no indicators since client did not authenticate)239mark('S4U2Self (no auth indicators expected)')240realm.kinit('service/1', None, ['-k', '-f', '-X', 'indicators=inds1'])241realm.run([kvno, '-U', 'user', 'service/1'])242out = realm.run(['./adata', '-p', realm.user_princ, 'service/1'])243if '97:' in out:244fail('auth-indicator present in S4U2Self response')245246# Get another S4U2Self ticket with requested authdata.247realm.run(['./s4u2self', 'user', 'service/1', '-', '-2', 'self_ad'])248realm.run(['./adata', '-p', realm.user_princ, 'service/1', '-2', 'self_ad'],249expected_msg=' -2: self_ad')250251# S4U2Proxy (indicators should come from evidence ticket, not TGT)252mark('S4U2Proxy (auth indicators from evidence ticket expected)')253realm.kinit(realm.user_princ, None, ['-k', '-f', '-X', 'indicators=indcl',254'-S', 'service/1', '-c', usercache])255realm.run(['./s4u2proxy', usercache, 'service/2'])256out = realm.run(['./adata', '-p', realm.user_princ, 'service/2'])257if '+97: [indcl]' not in out or '[inds1]' in out:258fail('correct auth-indicator not seen for S4U2Proxy req')259# Make sure a PAC with an S4U_DELEGATION_INFO(11) buffer is included.260if '?128: [1, 6, 7, 10, 11, 16, 19]' not in out:261fail('PAC with delegation info not seen for S4U2Proxy req')262263# Get another S4U2Proxy ticket including request-authdata.264realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad'])265realm.run(['./adata', '-p', realm.user_princ, 'service/2', '-2', 'proxy_ad'],266expected_msg=' -2: proxy_ad')267268# Get an S4U2Proxy ticket using an evidence ticket obtained by S4U2Self,269# with request authdata in both steps.270realm.run(['./s4u2self', 'user2', 'service/1', usercache, '-2', 'self_ad'])271realm.run(['./s4u2proxy', usercache, 'service/2', '-2', 'proxy_ad'])272out = realm.run(['./adata', '-p', 'user2', 'service/2', '-2', 'proxy_ad'])273if ' -2: self_ad' not in out or ' -2: proxy_ad' not in out:274fail('expected authdata not seen in S4U2Proxy ticket')275276# Test alteration of auth indicators by KDB module (AS and TGS).277realm.kinit(realm.user_princ, None, ['-k', '-X', 'indicators=dummy dbincr1'])278realm.run(['./adata', realm.krbtgt_princ], expected_msg='+97: [dbincr2]')279realm.run(['./adata', 'service/1'], expected_msg='+97: [dbincr3]')280realm.kinit(realm.user_princ, None,281['-k', '-X', 'indicators=strong', '-S', 'rservice'])282# Test enforcement of altered indicators during AS request.283realm.kinit(realm.user_princ, None,284['-k', '-X', 'indicators=strong dbincr1', '-S', 'rservice'],285expected_code=1)286287# Test that the PAC is suppressed in an AS request by a negative PAC288# request.289mark('AS-REQ PAC client supression')290realm.kinit(realm.user_princ, None, ['-k', '--no-request-pac'])291out = realm.run(['./adata', realm.krbtgt_princ])292if '128:' in out:293fail('PAC not suppressed by --no-request-pac')294295mark('S4U2Proxy with a foreign client')296297a_princs = {'krbtgt/A': {'keys': 'aes128-cts'},298'krbtgt/B': {'keys': 'aes128-cts'},299'impersonator': {'keys': 'aes128-cts'},300'impersonator2': {'keys': 'aes128-cts'},301'resource': {'keys': 'aes128-cts'}}302a_kconf = {'realms': {'$realm': {'database_module': 'test'}},303'dbmodules': {'test': {'db_library': 'test',304'delegation': {'impersonator' : 'resource'},305'princs': a_princs,306'alias': {'service/rb.b': '@B'}}}}307308b_princs = {'krbtgt/B': {'keys': 'aes128-cts'},309'krbtgt/A': {'keys': 'aes128-cts'},310'user': {'keys': 'aes128-cts', 'flags': '+preauth'},311'rb': {'keys': 'aes128-cts'}}312b_kconf = {'realms': {'$realm': {'database_module': 'test'}},313'dbmodules': {'test': {'db_library': 'test',314'princs': b_princs,315'rbcd': {'rb@B': 'impersonator2@A'},316'alias': {'service/rb.b': 'rb',317'impersonator2@A': '@A'}}}}318319ra, rb = cross_realms(2, xtgts=(),320args=({'realm': 'A', 'kdc_conf': a_kconf},321{'realm': 'B', 'kdc_conf': b_kconf}),322create_kdb=False)323324ra.start_kdc()325rb.start_kdc()326327ra.extract_keytab('impersonator@A', ra.keytab)328ra.extract_keytab('impersonator2@A', ra.keytab)329rb.extract_keytab('user@B', rb.keytab)330331usercache = 'FILE:' + os.path.join(rb.testdir, 'usercache')332rb.kinit(rb.user_princ, None, ['-k', '-f', '-c', usercache])333rb.run([kvno, '-C', 'impersonator@A', '-c', usercache])334335ra.kinit('impersonator@A', None, ['-f', '-k', '-t', ra.keytab])336ra.run(['./s4u2proxy', usercache, 'resource@A'])337338mark('Cross realm S4U authdata tests')339340ra.kinit('impersonator2@A', None, ['-f', '-k', '-t', ra.keytab])341ra.run(['./s4u2self', rb.user_princ, 'impersonator2@A', usercache, '-2',342'cross_s4u_self_ad'])343out = ra.run(['./adata', '-c', usercache, '-p', rb.user_princ,344'impersonator2@A', '-2', 'cross_s4u_self_ad'])345if out.count(' -2: cross_s4u_self_ad') != 1:346fail('expected one cross_s4u_self_ad, got: %s' % count)347348ra.run(['./s4u2proxy', usercache, 'service/rb.b', '-2',349'cross_s4u_proxy_ad'])350rb.extract_keytab('service/rb.b', ra.keytab)351out = ra.run(['./adata', '-p', rb.user_princ, 'service/rb.b', '-2',352'cross_s4u_proxy_ad'])353if out.count(' -2: cross_s4u_self_ad') != 1:354fail('expected one cross_s4u_self_ad, got: %s' % count)355if out.count(' -2: cross_s4u_proxy_ad') != 1:356fail('expected one cross_s4u_proxy_ad, got: %s' % count)357358ra.stop()359rb.stop()360361success('Authorization data tests')362363364