xref: /freebsd/crypto/krb5/src/util/princflags.py (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubertimport re
2*7f2fe78bSCy Schubert
3*7f2fe78bSCy Schubert# Module for translating KDB principal flags between string and
4*7f2fe78bSCy Schubert# integer forms.
5*7f2fe78bSCy Schubert#
6*7f2fe78bSCy Schubert# When run as a standalone script, print out C tables to insert into
7*7f2fe78bSCy Schubert# lib/kadm5/str_conv.c.
8*7f2fe78bSCy Schubert
9*7f2fe78bSCy Schubert# KDB principal flag definitions copied from kdb.h
10*7f2fe78bSCy Schubert
11*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_POSTDATED     = 0x00000001
12*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_FORWARDABLE   = 0x00000002
13*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_TGT_BASED     = 0x00000004
14*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_RENEWABLE     = 0x00000008
15*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_PROXIABLE     = 0x00000010
16*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_DUP_SKEY      = 0x00000020
17*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_ALL_TIX       = 0x00000040
18*7f2fe78bSCy SchubertKRB5_KDB_REQUIRES_PRE_AUTH      = 0x00000080
19*7f2fe78bSCy SchubertKRB5_KDB_REQUIRES_HW_AUTH       = 0x00000100
20*7f2fe78bSCy SchubertKRB5_KDB_REQUIRES_PWCHANGE      = 0x00000200
21*7f2fe78bSCy SchubertKRB5_KDB_DISALLOW_SVR           = 0x00001000
22*7f2fe78bSCy SchubertKRB5_KDB_PWCHANGE_SERVICE       = 0x00002000
23*7f2fe78bSCy SchubertKRB5_KDB_SUPPORT_DESMD5         = 0x00004000
24*7f2fe78bSCy SchubertKRB5_KDB_NEW_PRINC              = 0x00008000
25*7f2fe78bSCy SchubertKRB5_KDB_OK_AS_DELEGATE         = 0x00100000
26*7f2fe78bSCy SchubertKRB5_KDB_OK_TO_AUTH_AS_DELEGATE = 0x00200000
27*7f2fe78bSCy SchubertKRB5_KDB_NO_AUTH_DATA_REQUIRED  = 0x00400000
28*7f2fe78bSCy SchubertKRB5_KDB_LOCKDOWN_KEYS          = 0x00800000
29*7f2fe78bSCy Schubert
30*7f2fe78bSCy Schubert# Input tables -- list of tuples of the form (name, flag, invert)
31*7f2fe78bSCy Schubert
32*7f2fe78bSCy Schubert# Input forms from kadmin.c
33*7f2fe78bSCy Schubert_kadmin_pflags = [
34*7f2fe78bSCy Schubert    ("allow_postdated",         KRB5_KDB_DISALLOW_POSTDATED,    True),
35*7f2fe78bSCy Schubert    ("allow_forwardable",       KRB5_KDB_DISALLOW_FORWARDABLE,  True),
36*7f2fe78bSCy Schubert    ("allow_tgs_req",           KRB5_KDB_DISALLOW_TGT_BASED,    True),
37*7f2fe78bSCy Schubert    ("allow_renewable",         KRB5_KDB_DISALLOW_RENEWABLE,    True),
38*7f2fe78bSCy Schubert    ("allow_proxiable",         KRB5_KDB_DISALLOW_PROXIABLE,    True),
39*7f2fe78bSCy Schubert    ("allow_dup_skey",          KRB5_KDB_DISALLOW_DUP_SKEY,     True),
40*7f2fe78bSCy Schubert    ("allow_tix",               KRB5_KDB_DISALLOW_ALL_TIX,      True),
41*7f2fe78bSCy Schubert    ("requires_preauth",        KRB5_KDB_REQUIRES_PRE_AUTH,     False),
42*7f2fe78bSCy Schubert    ("requires_hwauth",         KRB5_KDB_REQUIRES_HW_AUTH,      False),
43*7f2fe78bSCy Schubert    ("needchange",              KRB5_KDB_REQUIRES_PWCHANGE,     False),
44*7f2fe78bSCy Schubert    ("allow_svr",               KRB5_KDB_DISALLOW_SVR,          True),
45*7f2fe78bSCy Schubert    ("password_changing_service", KRB5_KDB_PWCHANGE_SERVICE,    False),
46*7f2fe78bSCy Schubert    ("support_desmd5",          KRB5_KDB_SUPPORT_DESMD5,        False),
47*7f2fe78bSCy Schubert    ("ok_as_delegate",          KRB5_KDB_OK_AS_DELEGATE,        False),
48*7f2fe78bSCy Schubert    ("ok_to_auth_as_delegate",  KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, False),
49*7f2fe78bSCy Schubert    ("no_auth_data_required",   KRB5_KDB_NO_AUTH_DATA_REQUIRED, False),
50*7f2fe78bSCy Schubert    ("lockdown_keys",           KRB5_KDB_LOCKDOWN_KEYS,         False),
51*7f2fe78bSCy Schubert]
52*7f2fe78bSCy Schubert
53*7f2fe78bSCy Schubert# Input forms from lib/kadm5/str_conv.c
54*7f2fe78bSCy Schubert_strconv_pflags = [
55*7f2fe78bSCy Schubert    ("postdateable",            KRB5_KDB_DISALLOW_POSTDATED,    True),
56*7f2fe78bSCy Schubert    ("forwardable",             KRB5_KDB_DISALLOW_FORWARDABLE,  True),
57*7f2fe78bSCy Schubert    ("tgt-based",               KRB5_KDB_DISALLOW_TGT_BASED,    True),
58*7f2fe78bSCy Schubert    ("renewable",               KRB5_KDB_DISALLOW_RENEWABLE,    True),
59*7f2fe78bSCy Schubert    ("proxiable",               KRB5_KDB_DISALLOW_PROXIABLE,    True),
60*7f2fe78bSCy Schubert    ("dup-skey",                KRB5_KDB_DISALLOW_DUP_SKEY,     True),
61*7f2fe78bSCy Schubert    ("allow-tickets",           KRB5_KDB_DISALLOW_ALL_TIX,      True),
62*7f2fe78bSCy Schubert    ("preauth",                 KRB5_KDB_REQUIRES_PRE_AUTH,     False),
63*7f2fe78bSCy Schubert    ("hwauth",                  KRB5_KDB_REQUIRES_HW_AUTH,      False),
64*7f2fe78bSCy Schubert    ("ok-as-delegate",          KRB5_KDB_OK_AS_DELEGATE,        False),
65*7f2fe78bSCy Schubert    ("pwchange",                KRB5_KDB_REQUIRES_PWCHANGE,     False),
66*7f2fe78bSCy Schubert    ("service",                 KRB5_KDB_DISALLOW_SVR,          True),
67*7f2fe78bSCy Schubert    ("pwservice",               KRB5_KDB_PWCHANGE_SERVICE,      False),
68*7f2fe78bSCy Schubert    ("md5",                     KRB5_KDB_SUPPORT_DESMD5,        False),
69*7f2fe78bSCy Schubert    ("ok-to-auth-as-delegate",  KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, False),
70*7f2fe78bSCy Schubert    ("no-auth-data-required",   KRB5_KDB_NO_AUTH_DATA_REQUIRED, False),
71*7f2fe78bSCy Schubert    ("lockdown-keys",           KRB5_KDB_LOCKDOWN_KEYS,         False),
72*7f2fe78bSCy Schubert]
73*7f2fe78bSCy Schubert
74*7f2fe78bSCy Schubert# kdb.h symbol prefix
75*7f2fe78bSCy Schubert_prefix = 'KRB5_KDB_'
76*7f2fe78bSCy Schubert_prefixlen = len(_prefix)
77*7f2fe78bSCy Schubert
78*7f2fe78bSCy Schubert# Names of flags, as printed by kadmin (derived from kdb.h symbols).
79*7f2fe78bSCy Schubert# To be filled in by _setup_tables().
80*7f2fe78bSCy Schubert_flagnames = {}
81*7f2fe78bSCy Schubert
82*7f2fe78bSCy Schubert# Translation table to map hyphens to underscores
83*7f2fe78bSCy Schubert_squash = str.maketrans('-', '_')
84*7f2fe78bSCy Schubert
85*7f2fe78bSCy Schubert# Combined input-to-flag lookup table, to be filled in by
86*7f2fe78bSCy Schubert# _setup_tables()
87*7f2fe78bSCy Schubertpflags = {}
88*7f2fe78bSCy Schubert
89*7f2fe78bSCy Schubert# Tables of ftuples, to be filled in by _setup_tables()
90*7f2fe78bSCy Schubertkadmin_ftuples = []
91*7f2fe78bSCy Schubertstrconv_ftuples = []
92*7f2fe78bSCy Schubertsym_ftuples = []
93*7f2fe78bSCy Schubertall_ftuples = []
94*7f2fe78bSCy Schubert
95*7f2fe78bSCy Schubert# Inverted table to look up ftuples by flag value, to be filled in by
96*7f2fe78bSCy Schubert# _setup_tables()
97*7f2fe78bSCy Schubertkadmin_itable = {}
98*7f2fe78bSCy Schubertstrconv_itable = {}
99*7f2fe78bSCy Schubertsym_itable = {}
100*7f2fe78bSCy Schubert
101*7f2fe78bSCy Schubert
102*7f2fe78bSCy Schubert# Bundle some methods that are useful for writing tests.
103*7f2fe78bSCy Schubertclass Ftuple(object):
104*7f2fe78bSCy Schubert    def __init__(self, name, flag, invert):
105*7f2fe78bSCy Schubert        self.name = name
106*7f2fe78bSCy Schubert        self.flag = flag
107*7f2fe78bSCy Schubert        self.invert = invert
108*7f2fe78bSCy Schubert
109*7f2fe78bSCy Schubert    def __repr__(self):
110*7f2fe78bSCy Schubert        return "Ftuple" + str((self.name, self.flag, self.invert))
111*7f2fe78bSCy Schubert
112*7f2fe78bSCy Schubert    def flagname(self):
113*7f2fe78bSCy Schubert        return _flagnames[self.flag]
114*7f2fe78bSCy Schubert
115*7f2fe78bSCy Schubert    def setspec(self):
116*7f2fe78bSCy Schubert        return ('-' if self.invert else '+') + self.name
117*7f2fe78bSCy Schubert
118*7f2fe78bSCy Schubert    def clearspec(self):
119*7f2fe78bSCy Schubert        return ('+' if self.invert else '-') + self.name
120*7f2fe78bSCy Schubert
121*7f2fe78bSCy Schubert    def spec(self, doset):
122*7f2fe78bSCy Schubert        return self.setspec() if doset else self.clearspec()
123*7f2fe78bSCy Schubert
124*7f2fe78bSCy Schubert
125*7f2fe78bSCy Schubertdef _setup_tables():
126*7f2fe78bSCy Schubert    # Filter globals for 'KRB5_KDB_' prefix to create lookup tables.
127*7f2fe78bSCy Schubert    # Make the reasonable assumption that the Python runtime doesn't
128*7f2fe78bSCy Schubert    # define any names with that prefix by default.
129*7f2fe78bSCy Schubert    global _flagnames
130*7f2fe78bSCy Schubert    for k, v in globals().items():
131*7f2fe78bSCy Schubert        if k.startswith(_prefix):
132*7f2fe78bSCy Schubert            _flagnames[v] = k[_prefixlen:]
133*7f2fe78bSCy Schubert
134*7f2fe78bSCy Schubert    # Construct an input table based on kdb.h constant names by
135*7f2fe78bSCy Schubert    # truncating the "KRB5_KDB_" prefix and downcasing.
136*7f2fe78bSCy Schubert    sym_pflags = []
137*7f2fe78bSCy Schubert    for v, k in sorted(_flagnames.items()):
138*7f2fe78bSCy Schubert        sym_pflags.append((k.lower(), v, False))
139*7f2fe78bSCy Schubert
140*7f2fe78bSCy Schubert    global kadmin_ftuples, strconv_ftuples, sym_ftuples, all_ftuples
141*7f2fe78bSCy Schubert    for x in _kadmin_pflags:
142*7f2fe78bSCy Schubert        kadmin_ftuples.append(Ftuple(*x))
143*7f2fe78bSCy Schubert    for x in _strconv_pflags:
144*7f2fe78bSCy Schubert        strconv_ftuples.append(Ftuple(*x))
145*7f2fe78bSCy Schubert    for x in sym_pflags:
146*7f2fe78bSCy Schubert        sym_ftuples.append(Ftuple(*x))
147*7f2fe78bSCy Schubert    all_ftuples = kadmin_ftuples + strconv_ftuples + sym_ftuples
148*7f2fe78bSCy Schubert
149*7f2fe78bSCy Schubert    # Populate combined input-to-flag lookup table.  This will
150*7f2fe78bSCy Schubert    # eliminate some duplicates.
151*7f2fe78bSCy Schubert    global pflags
152*7f2fe78bSCy Schubert    for x in all_ftuples:
153*7f2fe78bSCy Schubert        name = x.name.translate(_squash)
154*7f2fe78bSCy Schubert        pflags[name] = x
155*7f2fe78bSCy Schubert
156*7f2fe78bSCy Schubert    global kadmin_itable, strconv_itable, sym_itable
157*7f2fe78bSCy Schubert    for x in kadmin_ftuples:
158*7f2fe78bSCy Schubert        kadmin_itable[x.flag] = x
159*7f2fe78bSCy Schubert    for x in strconv_ftuples:
160*7f2fe78bSCy Schubert        strconv_itable[x.flag] = x
161*7f2fe78bSCy Schubert    for x in sym_ftuples:
162*7f2fe78bSCy Schubert        sym_itable[x.flag] = x
163*7f2fe78bSCy Schubert
164*7f2fe78bSCy Schubert
165*7f2fe78bSCy Schubert# Convert the bit number of a flag to a string.  Remove the
166*7f2fe78bSCy Schubert# 'KRB5_KDB_' prefix.  Give an 8-digit hexadecimal number if the flag
167*7f2fe78bSCy Schubert# is unknown.
168*7f2fe78bSCy Schubertdef flagnum2str(n):
169*7f2fe78bSCy Schubert    s = _flagnames.get(1 << n)
170*7f2fe78bSCy Schubert    if s is None:
171*7f2fe78bSCy Schubert        return "0x%08x" % ((1 << n) & 0xffffffff)
172*7f2fe78bSCy Schubert    return s
173*7f2fe78bSCy Schubert
174*7f2fe78bSCy Schubert
175*7f2fe78bSCy Schubert# Return a list of flag names from a flag word.
176*7f2fe78bSCy Schubertdef flags2namelist(flags):
177*7f2fe78bSCy Schubert    a = []
178*7f2fe78bSCy Schubert    for n in range(32):
179*7f2fe78bSCy Schubert        if flags & (1 << n):
180*7f2fe78bSCy Schubert            a.append(flagnum2str(n))
181*7f2fe78bSCy Schubert    return a
182*7f2fe78bSCy Schubert
183*7f2fe78bSCy Schubert
184*7f2fe78bSCy Schubert# Given a single specifier in the form {+|-}flagname, return a tuple
185*7f2fe78bSCy Schubert# of the form (flagstoset, flagstoclear).
186*7f2fe78bSCy Schubertdef flagspec2mask(s):
187*7f2fe78bSCy Schubert    req_neg = False
188*7f2fe78bSCy Schubert    if s[0] == '-':
189*7f2fe78bSCy Schubert        req_neg = True
190*7f2fe78bSCy Schubert        s = s[1:]
191*7f2fe78bSCy Schubert    elif s[0] == '+':
192*7f2fe78bSCy Schubert        s = s[1:]
193*7f2fe78bSCy Schubert
194*7f2fe78bSCy Schubert    s = s.lower().translate(_squash)
195*7f2fe78bSCy Schubert    x = pflags.get(s)
196*7f2fe78bSCy Schubert    if x is not None:
197*7f2fe78bSCy Schubert        flag, invert = x.flag, x.invert
198*7f2fe78bSCy Schubert    else:
199*7f2fe78bSCy Schubert        # Maybe it's a hex number.
200*7f2fe78bSCy Schubert        if not s.startswith('0x'):
201*7f2fe78bSCy Schubert            raise ValueError
202*7f2fe78bSCy Schubert        flag, invert = int(s, 16), False
203*7f2fe78bSCy Schubert
204*7f2fe78bSCy Schubert    if req_neg:
205*7f2fe78bSCy Schubert        invert = not invert
206*7f2fe78bSCy Schubert    return (0, ~flag) if invert else (flag, ~0)
207*7f2fe78bSCy Schubert
208*7f2fe78bSCy Schubert
209*7f2fe78bSCy Schubert# Given a string containing a space/comma separated list of specifiers
210*7f2fe78bSCy Schubert# of the form {+|-}flagname, return a tuple of the form (flagstoset,
211*7f2fe78bSCy Schubert# flagstoclear).  This shares the same limitation as
212*7f2fe78bSCy Schubert# kadm5int_acl_parse_restrictions() of losing the distinction between
213*7f2fe78bSCy Schubert# orderings when the same flag bit appears in both the positive and
214*7f2fe78bSCy Schubert# the negative sense.
215*7f2fe78bSCy Schubertdef speclist2mask(s):
216*7f2fe78bSCy Schubert    toset, toclear = (0, ~0)
217*7f2fe78bSCy Schubert    for x in re.split('[\t, ]+', s):
218*7f2fe78bSCy Schubert        fset, fclear = flagspec2mask(x)
219*7f2fe78bSCy Schubert        toset |= fset
220*7f2fe78bSCy Schubert        toclear &= fclear
221*7f2fe78bSCy Schubert
222*7f2fe78bSCy Schubert    return toset, toclear
223*7f2fe78bSCy Schubert
224*7f2fe78bSCy Schubert
225*7f2fe78bSCy Schubert# Print C table of input flag specifiers for lib/kadm5/str_conv.c.
226*7f2fe78bSCy Schubertdef _print_ftbl():
227*7f2fe78bSCy Schubert    print('static const struct flag_table_row ftbl[] = {')
228*7f2fe78bSCy Schubert    a = sorted(pflags.items(), key=lambda k, v: (v.flag, -v.invert, k))
229*7f2fe78bSCy Schubert    for k, v in a:
230*7f2fe78bSCy Schubert        s1 = '    {"%s",' % k
231*7f2fe78bSCy Schubert        s2 = '%-31s KRB5_KDB_%s,' % (s1, v.flagname())
232*7f2fe78bSCy Schubert        print('%-63s %d},' % (s2, 1 if v.invert else 0))
233*7f2fe78bSCy Schubert
234*7f2fe78bSCy Schubert    print('};')
235*7f2fe78bSCy Schubert    print('#define NFTBL (sizeof(ftbl) / sizeof(ftbl[0]))')
236*7f2fe78bSCy Schubert
237*7f2fe78bSCy Schubert
238*7f2fe78bSCy Schubert# Print C table of output flag names for lib/kadm5/str_conv.c.
239*7f2fe78bSCy Schubertdef _print_outflags():
240*7f2fe78bSCy Schubert    print('static const char *outflags[] = {')
241*7f2fe78bSCy Schubert    for i in range(32):
242*7f2fe78bSCy Schubert        flag = 1 << i
243*7f2fe78bSCy Schubert        if flag > max(_flagnames.keys()):
244*7f2fe78bSCy Schubert            break
245*7f2fe78bSCy Schubert        try:
246*7f2fe78bSCy Schubert            s = '    "%s",' % _flagnames[flag]
247*7f2fe78bSCy Schubert        except KeyError:
248*7f2fe78bSCy Schubert            s = '    NULL,'
249*7f2fe78bSCy Schubert        print('%-32s/* 0x%08x */' % (s, flag))
250*7f2fe78bSCy Schubert
251*7f2fe78bSCy Schubert    print('};')
252*7f2fe78bSCy Schubert    print('#define NOUTFLAGS (sizeof(outflags) / sizeof(outflags[0]))')
253*7f2fe78bSCy Schubert
254*7f2fe78bSCy Schubert
255*7f2fe78bSCy Schubert# Print out C tables to insert into lib/kadm5/str_conv.c.
256*7f2fe78bSCy Schubertdef _main():
257*7f2fe78bSCy Schubert    _print_ftbl()
258*7f2fe78bSCy Schubert    print
259*7f2fe78bSCy Schubert    _print_outflags()
260*7f2fe78bSCy Schubert
261*7f2fe78bSCy Schubert
262*7f2fe78bSCy Schubert_setup_tables()
263*7f2fe78bSCy Schubert
264*7f2fe78bSCy Schubert
265*7f2fe78bSCy Schubertif __name__ == '__main__':
266*7f2fe78bSCy Schubert    _main()
267