summaryrefslogtreecommitdiffstats
path: root/src/tests/gssapi/t_enctypes.py
blob: d7577bfcabe44bfc88cbc976fd7594e61da72fbd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/python
from k5test import *

# Define some convenience abbreviations for enctypes we will see in
# test program output.  For background, aes256 and aes128 are "CFX
# enctypes", meaning that they imply support for RFC 4121, while des3
# and rc4 are not.  DES3 keys will appear as 'des3-cbc-raw' in
# t_enctypes output because that's how GSSAPI does raw triple-DES
# encryption without the RFC3961 framing.
aes256 = 'aes256-cts-hmac-sha1-96'
aes128 = 'aes128-cts-hmac-sha1-96'
des3 = 'des3-cbc-sha1'
des3raw = 'des3-cbc-raw'
rc4 = 'arcfour-hmac'

# These tests make assumptions about the default enctype lists, so set
# them explicitly rather than relying on the library defaults.
enctypes='aes des3 rc4'
supp='aes256-cts:normal aes128-cts:normal des3-cbc-sha1:normal rc4-hmac:normal'
conf = {'libdefaults': {
        'default_tgs_enctypes': enctypes,
        'default_tkt_enctypes': enctypes,
        'permitted_enctypes': enctypes},
        'realms': {'$realm': {'supported_enctypes': supp}}}
realm = K5Realm(krb5_conf=conf)
shutil.copyfile(realm.ccache, os.path.join(realm.testdir, 'save'))

# Return an argument list for running t_enctypes with optional initiator
# and acceptor enctype lists.
def cmdline(ienc, aenc):
    iflags = ienc and ['-i', ienc] or []
    aflags = aenc and ['-a', aenc] or []
    return ['./t_enctypes'] + iflags + aflags + ['p:' + realm.host_princ]


# Run t_enctypes with optional initiator and acceptor enctype lists,
# and check that it succeeds with the expected output.  Also check
# that the ticket we got has the expected encryption key and session
# key.
def test(msg, ienc, aenc, tktenc='', tktsession='', proto='', isubkey='',
         asubkey=None):
    shutil.copyfile(os.path.join(realm.testdir, 'save'), realm.ccache)
    # Run the test program and check its output.
    out = realm.run(cmdline(ienc, aenc)).split()
    if out[0] != proto or out[1] != isubkey:
        fail(msg)
    if asubkey is not None and (len(out) < 3 or out[2] != asubkey):
        fail(msg)
    lines = realm.run([klist, '-e']).splitlines()
    for ind, line in enumerate(lines):
        if realm.host_princ in line:
            if lines[ind + 1].strip() != ('Etype (skey, tkt): %s, %s' %
                                          (tktsession, tktenc)):
                fail(msg)
            break

# Run t_enctypes with optional initiator and acceptor enctype lists,
# and check that it fails with the expected error message.
def test_err(msg, ienc, aenc, expected_err):
    shutil.copyfile(os.path.join(realm.testdir, 'save'), realm.ccache)
    out = realm.run(cmdline(ienc, aenc), expected_code=1)
    if expected_err not in out:
        fail(msg)


# By default, all of the key enctypes should be aes256.
test('noargs', None, None,
     tktenc=aes256, tktsession=aes256,
     proto='cfx', isubkey=aes256, asubkey=aes256)

# When the initiator constrains the permitted session enctypes to
# aes128, the ticket encryption key should remain aes256.  The client
# initiator will not send an RFC 4537 upgrade list because it sees no
# other permitted enctypes, so the acceptor subkey will not be
# upgraded from aes128.
test('init aes128', 'aes128-cts', None,
     tktenc=aes256, tktsession=aes128,
     proto='cfx', isubkey=aes128, asubkey=aes128)

# If the initiator and acceptor both constrain the permitted session
# enctypes to aes128, we should see the same keys as above.  This
# tests that the acceptor does not mistakenly contrain the ticket
# encryption key.
test('both aes128', 'aes128-cts', 'aes128-cts',
     tktenc=aes256, tktsession=aes128,
     proto='cfx', isubkey=aes128, asubkey=aes128)

# If only the acceptor constrains the permitted session enctypes to
# aes128, subkey negotiation fails because the acceptor considers the
# aes256 session key to be non-permitted.
test_err('acc aes128', None, 'aes128-cts', 'Encryption type not permitted')

# If the initiator constrains the permitted session enctypes to des3,
# no acceptor subkey will be generated because we can't upgrade to a
# CFX enctype.
test('init des3', 'des3', None,
     tktenc=aes256, tktsession=des3,
     proto='rfc1964', isubkey=des3raw, asubkey=None)

# Force the ticket session key to be rc4, so we can test some subkey
# upgrade cases.  The ticket encryption key remains aes256.
realm.run_kadminl('setstr %s session_enctypes rc4' % realm.host_princ)

# With no arguments, the initiator should send an upgrade list of
# [aes256 aes128 des3] and the acceptor should upgrade to an aes256
# subkey.
test('upgrade noargs', None, None,
     tktenc=aes256, tktsession=rc4,
     proto='cfx', isubkey=rc4, asubkey=aes256)

# If the initiator won't permit rc4 as a session key, it won't be able
# to get a ticket.
test_err('upgrade init aes', 'aes', None, 'no support for encryption type')

# If the initiator permits rc4 but prefers aes128, it will send an
# upgrade list of [aes128] and the acceptor will upgrade to aes128.
test('upgrade init aes128+rc4', 'aes128-cts rc4', None,
     tktenc=aes256, tktsession=rc4,
     proto='cfx', isubkey=rc4, asubkey=aes128)

# If the initiator permits rc4 but prefers des3, it will send an
# upgrade list of [des3], but the acceptor won't generate a subkey
# because des3 isn't a CFX enctype.
test('upgrade init des3+rc4', 'des3 rc4', None,
     tktenc=aes256, tktsession=rc4,
     proto='rfc1964', isubkey=rc4, asubkey=None)

# If the acceptor permits only aes128, subkey negotiation will fail
# because the ticket session key and initiator subkey are
# non-permitted.  (This is unfortunate if the acceptor's restriction
# is only for the sake of the kernel, since we could upgrade to an
# aes128 subkey, but it's the current semantics.)
test_err('upgrade acc aes128', None, 'aes128-cts',
         'Encryption type ArcFour with HMAC/md5 not permitted')

# If the acceptor permits rc4 but prefers aes128, it will negotiate an
# upgrade to aes128.
test('upgrade acc aes128 rc4', None, 'aes128-cts rc4',
     tktenc=aes256, tktsession=rc4,
     proto='cfx', isubkey=rc4, asubkey=aes128)

# In this test, the initiator and acceptor each prefer an AES enctype
# to rc4, but they can't agree on which one, so no subkey is
# generated.
test('upgrade mismatch', 'aes128-cts rc4', 'aes256-cts rc4',
     tktenc=aes256, tktsession=rc4,
     proto='rfc1964', isubkey=rc4, asubkey=None)

success('gss_krb5_set_allowable_enctypes tests')