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