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