xref: /freebsd/crypto/krb5/src/tests/t_renew.py (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubertfrom k5test import *
2*7f2fe78bSCy Schubertfrom datetime import datetime
3*7f2fe78bSCy Schubertimport re
4*7f2fe78bSCy Schubert
5*7f2fe78bSCy Schubertconf = {'realms': {'$realm': {'max_life': '20h', 'max_renewable_life': '20h'}}}
6*7f2fe78bSCy Schubertrealm = K5Realm(create_host=False, get_creds=False, kdc_conf=conf)
7*7f2fe78bSCy Schubert
8*7f2fe78bSCy Schubert# We will be scraping timestamps from klist to compute lifetimes, so
9*7f2fe78bSCy Schubert# use a time zone with no daylight savings time.
10*7f2fe78bSCy Schubertrealm.env['TZ'] = 'UTC'
11*7f2fe78bSCy Schubert
12*7f2fe78bSCy Schubertdef test(testname, life, rlife, exp_life, exp_rlife, env=None):
13*7f2fe78bSCy Schubert    global realm
14*7f2fe78bSCy Schubert    flags = ['-l', life]
15*7f2fe78bSCy Schubert    if rlife is not None:
16*7f2fe78bSCy Schubert        flags += ['-r', rlife]
17*7f2fe78bSCy Schubert    realm.kinit(realm.user_princ, password('user'), flags=flags, env=env)
18*7f2fe78bSCy Schubert    out = realm.run([klist, '-f'])
19*7f2fe78bSCy Schubert
20*7f2fe78bSCy Schubert    if ('Default principal: %s\n' % realm.user_princ) not in out:
21*7f2fe78bSCy Schubert        fail('%s: did not get tickets' % testname)
22*7f2fe78bSCy Schubert
23*7f2fe78bSCy Schubert    # Extract flags and check the renewable flag against expectations.
24*7f2fe78bSCy Schubert    flags = re.findall(r'Flags: ([a-zA-Z]*)', out)[0]
25*7f2fe78bSCy Schubert    if exp_rlife is None and 'R' in flags:
26*7f2fe78bSCy Schubert        fail('%s: ticket unexpectedly renewable' % testname)
27*7f2fe78bSCy Schubert    if exp_rlife is not None and 'R' not in flags:
28*7f2fe78bSCy Schubert        fail('%s: ticket unexpectedly non-renewable' % testname)
29*7f2fe78bSCy Schubert
30*7f2fe78bSCy Schubert    # Extract the start time, end time, and renewable end time if present.
31*7f2fe78bSCy Schubert    times = re.findall(r'\d\d/\d\d/\d\d \d\d:\d\d:\d\d', out)
32*7f2fe78bSCy Schubert    times = [datetime.strptime(t, '%m/%d/%y %H:%M:%S') for t in times]
33*7f2fe78bSCy Schubert    starttime = times[0]
34*7f2fe78bSCy Schubert    endtime = times[1]
35*7f2fe78bSCy Schubert    rtime = times[2] if len(times) >= 3 else None
36*7f2fe78bSCy Schubert
37*7f2fe78bSCy Schubert    # Check the ticket lifetime against expectations.  If the lifetime
38*7f2fe78bSCy Schubert    # was determined by the request, there may be a small error
39*7f2fe78bSCy Schubert    # because KDC requests contain an end time rather than a lifetime.
40*7f2fe78bSCy Schubert    life = (endtime - starttime).seconds
41*7f2fe78bSCy Schubert    if abs(life - exp_life) > 5:
42*7f2fe78bSCy Schubert        fail('%s: expected life %d, got %d' % (testname, exp_life, life))
43*7f2fe78bSCy Schubert
44*7f2fe78bSCy Schubert    # Check the ticket renewable lifetime against expectations.
45*7f2fe78bSCy Schubert    if exp_rlife is None and rtime is not None:
46*7f2fe78bSCy Schubert        fail('%s: ticket has unexpected renew_till' % testname)
47*7f2fe78bSCy Schubert    if exp_rlife is not None and rtime is None:
48*7f2fe78bSCy Schubert        fail('%s: ticket is renewable but has no renew_till' % testname)
49*7f2fe78bSCy Schubert    if rtime is not None:
50*7f2fe78bSCy Schubert        rlife = (rtime - starttime).seconds
51*7f2fe78bSCy Schubert        if abs(rlife - exp_rlife) > 5:
52*7f2fe78bSCy Schubert            fail('%s: expected rlife %d, got %d' %
53*7f2fe78bSCy Schubert                 (testname, exp_rlife, rlife))
54*7f2fe78bSCy Schubert
55*7f2fe78bSCy Schubert# Get renewable tickets.
56*7f2fe78bSCy Schuberttest('simple', '1h', '2h', 3600, 7200)
57*7f2fe78bSCy Schubert
58*7f2fe78bSCy Schubert# Renew twice, to test that renewed tickets are renewable.
59*7f2fe78bSCy Schubertmark('renew twice')
60*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, flags=['-R'])
61*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, flags=['-R'])
62*7f2fe78bSCy Schubertrealm.klist(realm.user_princ)
63*7f2fe78bSCy Schubert
64*7f2fe78bSCy Schubert# Make sure we can use a renewed ticket.
65*7f2fe78bSCy Schubertrealm.run([kvno, realm.user_princ])
66*7f2fe78bSCy Schubert
67*7f2fe78bSCy Schubert# Make sure we can't renew non-renewable tickets.
68*7f2fe78bSCy Schubertmark('non-renewable')
69*7f2fe78bSCy Schuberttest('non-renewable', '1h', None, 3600, None)
70*7f2fe78bSCy Schubertrealm.kinit(realm.user_princ, flags=['-R'], expected_code=1,
71*7f2fe78bSCy Schubert            expected_msg="KDC can't fulfill requested option")
72*7f2fe78bSCy Schubert
73*7f2fe78bSCy Schubert# Test that -allow_renewable on the client principal works.
74*7f2fe78bSCy Schubertmark('allow_renewable (client)')
75*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-allow_renewable', 'user'])
76*7f2fe78bSCy Schuberttest('disallowed client', '1h', '2h', 3600, None)
77*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '+allow_renewable', 'user'])
78*7f2fe78bSCy Schubert
79*7f2fe78bSCy Schubert# Test that -allow_renewable on the server principal works.
80*7f2fe78bSCy Schubertmark('allow_renewable (server)')
81*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-allow_renewable',  realm.krbtgt_princ])
82*7f2fe78bSCy Schuberttest('disallowed server', '1h', '2h', 3600, None)
83*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '+allow_renewable', realm.krbtgt_princ])
84*7f2fe78bSCy Schubert
85*7f2fe78bSCy Schubert# Test that trivially renewable tickets are issued if renew_till <=
86*7f2fe78bSCy Schubert# till.  (Our client code bumps up the requested renewable life to the
87*7f2fe78bSCy Schubert# requested life.)
88*7f2fe78bSCy Schubertmark('trivially renewable')
89*7f2fe78bSCy Schuberttest('short', '2h', '1h', 7200, 7200)
90*7f2fe78bSCy Schubert
91*7f2fe78bSCy Schubert# Test that renewable tickets are issued if till > max life by
92*7f2fe78bSCy Schubert# default, but not if we configure away the RENEWABLE-OK option.
93*7f2fe78bSCy Schubertmark('renewable-ok')
94*7f2fe78bSCy Schubertno_opts_conf = {'libdefaults': {'kdc_default_options': '0'}}
95*7f2fe78bSCy Schubertno_opts = realm.special_env('no_opts', False, krb5_conf=no_opts_conf)
96*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-maxlife', '10 hours', 'user'])
97*7f2fe78bSCy Schuberttest('long', '15h', None, 10 * 3600, 15 * 3600)
98*7f2fe78bSCy Schuberttest('long noopts', '15h', None, 10 * 3600, None, env=no_opts)
99*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-maxlife', '20 hours', 'user'])
100*7f2fe78bSCy Schubert
101*7f2fe78bSCy Schubert# Test maximum renewable life on the client principal.
102*7f2fe78bSCy Schubertmark('maxrenewlife (client)')
103*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-maxrenewlife', '5 hours', 'user'])
104*7f2fe78bSCy Schuberttest('maxrenewlife client 1', '4h', '5h', 4 * 3600, 5 * 3600)
105*7f2fe78bSCy Schuberttest('maxrenewlife client 2', '6h', '10h', 6 * 3600, 5 * 3600)
106*7f2fe78bSCy Schubert
107*7f2fe78bSCy Schubert# Test maximum renewable life on the server principal.
108*7f2fe78bSCy Schubertmark('maxrenewlife (server)')
109*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-maxrenewlife', '3 hours',
110*7f2fe78bSCy Schubert           realm.krbtgt_princ])
111*7f2fe78bSCy Schuberttest('maxrenewlife server 1', '2h', '3h', 2 * 3600, 3 * 3600)
112*7f2fe78bSCy Schuberttest('maxrenewlife server 2', '4h', '8h', 4 * 3600, 3 * 3600)
113*7f2fe78bSCy Schubert
114*7f2fe78bSCy Schubert# Test realm maximum life.
115*7f2fe78bSCy Schubertmark('realm maximum life')
116*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-maxrenewlife', '40 hours', 'user'])
117*7f2fe78bSCy Schubertrealm.run([kadminl, 'modprinc', '-maxrenewlife', '40 hours',
118*7f2fe78bSCy Schubert           realm.krbtgt_princ])
119*7f2fe78bSCy Schuberttest('maxrenewlife realm 1', '10h', '20h', 10 * 3600, 20 * 3600)
120*7f2fe78bSCy Schuberttest('maxrenewlife realm 2', '21h', '40h', 20 * 3600, 20 * 3600)
121*7f2fe78bSCy Schubert
122*7f2fe78bSCy Schubertsuccess('Renewing credentials')
123