1# Copyright (C) 2011 by the Massachusetts Institute of Technology. 2# All rights reserved. 3 4# Export of this software from the United States of America may 5# require a specific license from the United States Government. 6# It is the responsibility of any person or organization contemplating 7# export to obtain such a license before exporting. 8# 9# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 10# distribute this software and its documentation for any purpose and 11# without fee is hereby granted, provided that the above copyright 12# notice appear in all copies and that both that copyright notice and 13# this permission notice appear in supporting documentation, and that 14# the name of M.I.T. not be used in advertising or publicity pertaining 15# to distribution of the software without specific, written prior 16# permission. Furthermore if you modify this software you must label 17# your software as modified software and not distribute it in such a 18# fashion that it might be confused with the original M.I.T. software. 19# M.I.T. makes no representations about the suitability of 20# this software for any purpose. It is provided "as is" without express 21# or implied warranty. 22 23from k5test import * 24 25kcm_socket_path = os.path.join(os.getcwd(), 'testdir', 'kcm') 26conf = {'libdefaults': {'kcm_socket': kcm_socket_path, 27 'kcm_mach_service': '-'}} 28realm = K5Realm(create_host=False, krb5_conf=conf) 29 30keyctl = which('keyctl') 31out = realm.run([klist, '-c', 'KEYRING:process:abcd'], expected_code=1) 32test_keyring = (keyctl is not None and 33 'Unknown credential cache type' not in out) 34if not test_keyring: 35 skipped('keyring ccache tests', 'keyring support not built') 36 37# Test kdestroy and klist of a non-existent ccache. 38mark('no ccache') 39realm.run([kdestroy]) 40realm.run([klist], expected_code=1, expected_msg='No credentials cache found') 41 42# Test kinit with an inaccessible ccache. 43mark('inaccessible ccache') 44realm.kinit(realm.user_princ, password('user'), flags=['-c', 'testdir/xx/yy'], 45 expected_code=1, expected_msg='Failed to store credentials') 46 47# Test klist -s with a single ccache. 48mark('klist -s single ccache') 49realm.run([klist, '-s'], expected_code=1) 50realm.kinit(realm.user_princ, password('user')) 51realm.run([klist, '-s']) 52realm.kinit(realm.user_princ, password('user'), ['-l', '-1s']) 53realm.run([klist, '-s'], expected_code=1) 54realm.kinit(realm.user_princ, password('user'), ['-S', 'kadmin/admin']) 55realm.run([klist, '-s']) 56realm.run([kdestroy]) 57realm.run([klist, '-s'], expected_code=1) 58 59realm.addprinc('alice', password('alice')) 60realm.addprinc('bob', password('bob')) 61realm.addprinc('carol', password('carol')) 62realm.addprinc('doug', password('doug')) 63 64def collection_test(realm, ccname): 65 cctype = ccname.partition(':')[0] 66 oldccname = realm.env['KRB5CCNAME'] 67 realm.env['KRB5CCNAME'] = ccname 68 69 mark('%s collection, single cache' % cctype) 70 realm.run([klist, '-A', '-s'], expected_code=1) 71 realm.kinit('alice', password('alice')) 72 realm.run([klist], expected_msg='Default principal: alice@') 73 realm.run([klist, '-A', '-s']) 74 realm.run([kdestroy]) 75 output = realm.run([klist], expected_code=1) 76 if 'No credentials cache' not in output and 'not found' not in output: 77 fail('Initial kdestroy failed to destroy primary cache.') 78 output = realm.run([klist, '-l'], expected_code=1) 79 if not output.endswith('---\n') or output.count('\n') != 2: 80 fail('Initial kdestroy failed to empty cache collection.') 81 realm.run([klist, '-A', '-s'], expected_code=1) 82 83 mark('%s collection, multiple caches' % cctype) 84 realm.kinit('alice', password('alice')) 85 realm.kinit('carol', password('carol')) 86 output = realm.run([klist, '-l']) 87 if '---\ncarol@' not in output or '\nalice@' not in output: 88 fail('klist -l did not show expected output after two kinits.') 89 realm.kinit('alice', password('alice')) 90 output = realm.run([klist, '-l']) 91 if '---\nalice@' not in output or output.count('\n') != 4: 92 fail('klist -l did not show expected output after re-kinit for alice.') 93 realm.kinit('doug', password('doug')) 94 realm.kinit('bob', password('bob')) 95 output = realm.run([klist, '-A', ccname]) 96 if 'bob@' not in output.splitlines()[1] or 'alice@' not in output or \ 97 'carol@' not in output or 'doug@' not in output or \ 98 output.count('Default principal:') != 4: 99 fail('klist -A did not show expected output after kinit doug+bob.') 100 realm.run([kswitch, '-p', 'carol']) 101 output = realm.run([klist, '-l']) 102 if '---\ncarol@' not in output or output.count('\n') != 6: 103 fail('klist -l did not show expected output after kswitch to carol.') 104 105 # Switch to specifying the collection name on the command line 106 # (only works with klist/kdestroy for now, not kinit/kswitch). 107 realm.env['KRB5CCNAME'] = oldccname 108 109 mark('%s collection, command-line specifier' % cctype) 110 realm.run([kdestroy, '-c', ccname]) 111 output = realm.run([klist, '-l', ccname]) 112 if 'carol@' in output or 'bob@' not in output or output.count('\n') != 5: 113 fail('kdestroy failed to remove only primary ccache.') 114 realm.run([klist, '-s', ccname], expected_code=1) 115 realm.run([klist, '-A', '-s', ccname]) 116 realm.run([kdestroy, '-p', 'alice', '-c', ccname]) 117 output = realm.run([klist, '-l', ccname]) 118 if 'alice@' in output or 'bob@' not in output or output.count('\n') != 4: 119 fail('kdestroy -p failed to remove alice') 120 realm.run([kdestroy, '-A', '-c', ccname]) 121 output = realm.run([klist, '-l', ccname], expected_code=1) 122 if not output.endswith('---\n') or output.count('\n') != 2: 123 fail('kdestroy -a failed to empty cache collection.') 124 realm.run([klist, '-A', '-s', ccname], expected_code=1) 125 126 127collection_test(realm, 'DIR:' + os.path.join(realm.testdir, 'cc')) 128kcmserver_path = os.path.join(srctop, 'tests', 'kcmserver.py') 129realm.start_server([sys.executable, kcmserver_path, kcm_socket_path], 130 'starting...') 131collection_test(realm, 'KCM:') 132if test_keyring: 133 def cleanup_keyring(anchor, name): 134 out = realm.run(['keyctl', 'list', anchor]) 135 if ('keyring: ' + name + '\n') in out: 136 keyid = realm.run(['keyctl', 'search', anchor, 'keyring', name]) 137 realm.run(['keyctl', 'unlink', keyid.strip(), anchor]) 138 139 # Use realm.testdir as the collection name to avoid conflicts with 140 # other build trees. 141 cname = realm.testdir 142 col_ringname = '_krb_' + cname 143 144 cleanup_keyring('@s', col_ringname) 145 collection_test(realm, 'KEYRING:session:' + cname) 146 cleanup_keyring('@s', col_ringname) 147 148 # Test legacy keyring cache linkage. 149 mark('legacy keyring cache linkage') 150 realm.env['KRB5CCNAME'] = 'KEYRING:' + cname 151 realm.run([kdestroy, '-A']) 152 realm.kinit(realm.user_princ, password('user')) 153 msg = 'KEYRING:legacy:' + cname + ':' + cname 154 realm.run([klist, '-l'], expected_msg=msg) 155 # Make sure this cache is linked to the session keyring. 156 id = realm.run([keyctl, 'search', '@s', 'keyring', cname]) 157 realm.run([keyctl, 'list', id.strip()], 158 expected_msg='user: __krb5_princ__') 159 # Remove the collection keyring. When the collection is 160 # reinitialized, the legacy cache should reappear inside it 161 # automatically as the primary cache. 162 cleanup_keyring('@s', col_ringname) 163 realm.run([klist], expected_msg=realm.user_princ) 164 coll_id = realm.run([keyctl, 'search', '@s', 'keyring', '_krb_' + cname]) 165 msg = id.strip() + ':' 166 realm.run([keyctl, 'list', coll_id.strip()], expected_msg=msg) 167 # Destroy the cache and check that it is unlinked from the session keyring. 168 realm.run([kdestroy]) 169 realm.run([keyctl, 'search', '@s', 'keyring', cname], expected_code=1) 170 cleanup_keyring('@s', col_ringname) 171 172# Test parameter expansion in default_ccache_name 173mark('default_ccache_name parameter expansion') 174realm.stop() 175conf = {'libdefaults': {'default_ccache_name': 'testdir/%{null}abc%{uid}'}} 176realm = K5Realm(krb5_conf=conf, create_kdb=False) 177del realm.env['KRB5CCNAME'] 178uidstr = str(os.getuid()) 179msg = 'testdir/abc%s' % uidstr 180realm.run([klist], expected_code=1, expected_msg=msg) 181 182success('Credential cache tests') 183