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