Blame src/util/princflags.py

Packit fd8b60
import re
Packit fd8b60
Packit fd8b60
# Module for translating KDB principal flags between string and
Packit fd8b60
# integer forms.
Packit fd8b60
#
Packit fd8b60
# When run as a standalone script, print out C tables to insert into
Packit fd8b60
# lib/kadm5/str_conv.c.
Packit fd8b60
Packit fd8b60
# KDB principal flag definitions copied from kdb.h
Packit fd8b60
Packit fd8b60
KRB5_KDB_DISALLOW_POSTDATED     = 0x00000001
Packit fd8b60
KRB5_KDB_DISALLOW_FORWARDABLE   = 0x00000002
Packit fd8b60
KRB5_KDB_DISALLOW_TGT_BASED     = 0x00000004
Packit fd8b60
KRB5_KDB_DISALLOW_RENEWABLE     = 0x00000008
Packit fd8b60
KRB5_KDB_DISALLOW_PROXIABLE     = 0x00000010
Packit fd8b60
KRB5_KDB_DISALLOW_DUP_SKEY      = 0x00000020
Packit fd8b60
KRB5_KDB_DISALLOW_ALL_TIX       = 0x00000040
Packit fd8b60
KRB5_KDB_REQUIRES_PRE_AUTH      = 0x00000080
Packit fd8b60
KRB5_KDB_REQUIRES_HW_AUTH       = 0x00000100
Packit fd8b60
KRB5_KDB_REQUIRES_PWCHANGE      = 0x00000200
Packit fd8b60
KRB5_KDB_DISALLOW_SVR           = 0x00001000
Packit fd8b60
KRB5_KDB_PWCHANGE_SERVICE       = 0x00002000
Packit fd8b60
KRB5_KDB_SUPPORT_DESMD5         = 0x00004000
Packit fd8b60
KRB5_KDB_NEW_PRINC              = 0x00008000
Packit fd8b60
KRB5_KDB_OK_AS_DELEGATE         = 0x00100000
Packit fd8b60
KRB5_KDB_OK_TO_AUTH_AS_DELEGATE = 0x00200000
Packit fd8b60
KRB5_KDB_NO_AUTH_DATA_REQUIRED  = 0x00400000
Packit fd8b60
KRB5_KDB_LOCKDOWN_KEYS          = 0x00800000
Packit fd8b60
Packit fd8b60
# Input tables -- list of tuples of the form (name, flag, invert)
Packit fd8b60
Packit fd8b60
# Input forms from kadmin.c
Packit fd8b60
_kadmin_pflags = [
Packit fd8b60
    ("allow_postdated",         KRB5_KDB_DISALLOW_POSTDATED,    True),
Packit fd8b60
    ("allow_forwardable",       KRB5_KDB_DISALLOW_FORWARDABLE,  True),
Packit fd8b60
    ("allow_tgs_req",           KRB5_KDB_DISALLOW_TGT_BASED,    True),
Packit fd8b60
    ("allow_renewable",         KRB5_KDB_DISALLOW_RENEWABLE,    True),
Packit fd8b60
    ("allow_proxiable",         KRB5_KDB_DISALLOW_PROXIABLE,    True),
Packit fd8b60
    ("allow_dup_skey",          KRB5_KDB_DISALLOW_DUP_SKEY,     True),
Packit fd8b60
    ("allow_tix",               KRB5_KDB_DISALLOW_ALL_TIX,      True),
Packit fd8b60
    ("requires_preauth",        KRB5_KDB_REQUIRES_PRE_AUTH,     False),
Packit fd8b60
    ("requires_hwauth",         KRB5_KDB_REQUIRES_HW_AUTH,      False),
Packit fd8b60
    ("needchange",              KRB5_KDB_REQUIRES_PWCHANGE,     False),
Packit fd8b60
    ("allow_svr",               KRB5_KDB_DISALLOW_SVR,          True),
Packit fd8b60
    ("password_changing_service", KRB5_KDB_PWCHANGE_SERVICE,    False),
Packit fd8b60
    ("support_desmd5",          KRB5_KDB_SUPPORT_DESMD5,        False),
Packit fd8b60
    ("ok_as_delegate",          KRB5_KDB_OK_AS_DELEGATE,        False),
Packit fd8b60
    ("ok_to_auth_as_delegate",  KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, False),
Packit fd8b60
    ("no_auth_data_required",   KRB5_KDB_NO_AUTH_DATA_REQUIRED, False),
Packit fd8b60
    ("lockdown_keys",           KRB5_KDB_LOCKDOWN_KEYS,         False),
Packit fd8b60
]
Packit fd8b60
Packit fd8b60
# Input forms from lib/kadm5/str_conv.c
Packit fd8b60
_strconv_pflags = [
Packit fd8b60
    ("postdateable",            KRB5_KDB_DISALLOW_POSTDATED,    True),
Packit fd8b60
    ("forwardable",             KRB5_KDB_DISALLOW_FORWARDABLE,  True),
Packit fd8b60
    ("tgt-based",               KRB5_KDB_DISALLOW_TGT_BASED,    True),
Packit fd8b60
    ("renewable",               KRB5_KDB_DISALLOW_RENEWABLE,    True),
Packit fd8b60
    ("proxiable",               KRB5_KDB_DISALLOW_PROXIABLE,    True),
Packit fd8b60
    ("dup-skey",                KRB5_KDB_DISALLOW_DUP_SKEY,     True),
Packit fd8b60
    ("allow-tickets",           KRB5_KDB_DISALLOW_ALL_TIX,      True),
Packit fd8b60
    ("preauth",                 KRB5_KDB_REQUIRES_PRE_AUTH,     False),
Packit fd8b60
    ("hwauth",                  KRB5_KDB_REQUIRES_HW_AUTH,      False),
Packit fd8b60
    ("ok-as-delegate",          KRB5_KDB_OK_AS_DELEGATE,        False),
Packit fd8b60
    ("pwchange",                KRB5_KDB_REQUIRES_PWCHANGE,     False),
Packit fd8b60
    ("service",                 KRB5_KDB_DISALLOW_SVR,          True),
Packit fd8b60
    ("pwservice",               KRB5_KDB_PWCHANGE_SERVICE,      False),
Packit fd8b60
    ("md5",                     KRB5_KDB_SUPPORT_DESMD5,        False),
Packit fd8b60
    ("ok-to-auth-as-delegate",  KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, False),
Packit fd8b60
    ("no-auth-data-required",   KRB5_KDB_NO_AUTH_DATA_REQUIRED, False),
Packit fd8b60
    ("lockdown-keys",           KRB5_KDB_LOCKDOWN_KEYS,         False),
Packit fd8b60
]
Packit fd8b60
Packit fd8b60
# kdb.h symbol prefix
Packit fd8b60
_prefix = 'KRB5_KDB_'
Packit fd8b60
_prefixlen = len(_prefix)
Packit fd8b60
Packit fd8b60
# Names of flags, as printed by kadmin (derived from kdb.h symbols).
Packit fd8b60
# To be filled in by _setup_tables().
Packit fd8b60
_flagnames = {}
Packit fd8b60
Packit fd8b60
# Translation table to map hyphens to underscores
Packit fd8b60
_squash = str.maketrans('-', '_')
Packit fd8b60
Packit fd8b60
# Combined input-to-flag lookup table, to be filled in by
Packit fd8b60
# _setup_tables()
Packit fd8b60
pflags = {}
Packit fd8b60
Packit fd8b60
# Tables of ftuples, to be filled in by _setup_tables()
Packit fd8b60
kadmin_ftuples = []
Packit fd8b60
strconv_ftuples = []
Packit fd8b60
sym_ftuples = []
Packit fd8b60
all_ftuples = []
Packit fd8b60
Packit fd8b60
# Inverted table to look up ftuples by flag value, to be filled in by
Packit fd8b60
# _setup_tables()
Packit fd8b60
kadmin_itable = {}
Packit fd8b60
strconv_itable = {}
Packit fd8b60
sym_itable = {}
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Bundle some methods that are useful for writing tests.
Packit fd8b60
class Ftuple(object):
Packit fd8b60
    def __init__(self, name, flag, invert):
Packit fd8b60
        self.name = name
Packit fd8b60
        self.flag = flag
Packit fd8b60
        self.invert = invert
Packit fd8b60
Packit fd8b60
    def __repr__(self):
Packit fd8b60
        return "Ftuple" + str((self.name, self.flag, self.invert))
Packit fd8b60
Packit fd8b60
    def flagname(self):
Packit fd8b60
        return _flagnames[self.flag]
Packit fd8b60
Packit fd8b60
    def setspec(self):
Packit fd8b60
        return ('-' if self.invert else '+') + self.name
Packit fd8b60
Packit fd8b60
    def clearspec(self):
Packit fd8b60
        return ('+' if self.invert else '-') + self.name
Packit fd8b60
Packit fd8b60
    def spec(self, doset):
Packit fd8b60
        return self.setspec() if doset else self.clearspec()
Packit fd8b60
Packit fd8b60
Packit fd8b60
def _setup_tables():
Packit fd8b60
    # Filter globals for 'KRB5_KDB_' prefix to create lookup tables.
Packit fd8b60
    # Make the reasonable assumption that the Python runtime doesn't
Packit fd8b60
    # define any names with that prefix by default.
Packit fd8b60
    global _flagnames
Packit fd8b60
    for k, v in globals().items():
Packit fd8b60
        if k.startswith(_prefix):
Packit fd8b60
            _flagnames[v] = k[_prefixlen:]
Packit fd8b60
Packit fd8b60
    # Construct an input table based on kdb.h constant names by
Packit fd8b60
    # truncating the "KRB5_KDB_" prefix and downcasing.
Packit fd8b60
    sym_pflags = []
Packit fd8b60
    for v, k in sorted(_flagnames.items()):
Packit fd8b60
        sym_pflags.append((k.lower(), v, False))
Packit fd8b60
Packit fd8b60
    global kadmin_ftuples, strconv_ftuples, sym_ftuples, all_ftuples
Packit fd8b60
    for x in _kadmin_pflags:
Packit fd8b60
        kadmin_ftuples.append(Ftuple(*x))
Packit fd8b60
    for x in _strconv_pflags:
Packit fd8b60
        strconv_ftuples.append(Ftuple(*x))
Packit fd8b60
    for x in sym_pflags:
Packit fd8b60
        sym_ftuples.append(Ftuple(*x))
Packit fd8b60
    all_ftuples = kadmin_ftuples + strconv_ftuples + sym_ftuples
Packit fd8b60
Packit fd8b60
    # Populate combined input-to-flag lookup table.  This will
Packit fd8b60
    # eliminate some duplicates.
Packit fd8b60
    global pflags
Packit fd8b60
    for x in all_ftuples:
Packit fd8b60
        name = x.name.translate(_squash)
Packit fd8b60
        pflags[name] = x
Packit fd8b60
Packit fd8b60
    global kadmin_itable, strconv_itable, sym_itable
Packit fd8b60
    for x in kadmin_ftuples:
Packit fd8b60
        kadmin_itable[x.flag] = x
Packit fd8b60
    for x in strconv_ftuples:
Packit fd8b60
        strconv_itable[x.flag] = x
Packit fd8b60
    for x in sym_ftuples:
Packit fd8b60
        sym_itable[x.flag] = x
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Convert the bit number of a flag to a string.  Remove the
Packit fd8b60
# 'KRB5_KDB_' prefix.  Give an 8-digit hexadecimal number if the flag
Packit fd8b60
# is unknown.
Packit fd8b60
def flagnum2str(n):
Packit fd8b60
    s = _flagnames.get(1 << n)
Packit fd8b60
    if s is None:
Packit fd8b60
        return "0x%08x" % ((1 << n) & 0xffffffff)
Packit fd8b60
    return s
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Return a list of flag names from a flag word.
Packit fd8b60
def flags2namelist(flags):
Packit fd8b60
    a = []
Packit fd8b60
    for n in range(32):
Packit fd8b60
        if flags & (1 << n):
Packit fd8b60
            a.append(flagnum2str(n))
Packit fd8b60
    return a
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Given a single specifier in the form {+|-}flagname, return a tuple
Packit fd8b60
# of the form (flagstoset, flagstoclear).
Packit fd8b60
def flagspec2mask(s):
Packit fd8b60
    req_neg = False
Packit fd8b60
    if s[0] == '-':
Packit fd8b60
        req_neg = True
Packit fd8b60
        s = s[1:]
Packit fd8b60
    elif s[0] == '+':
Packit fd8b60
        s = s[1:]
Packit fd8b60
Packit fd8b60
    s = s.lower().translate(_squash)
Packit fd8b60
    x = pflags.get(s)
Packit fd8b60
    if x is not None:
Packit fd8b60
        flag, invert = x.flag, x.invert
Packit fd8b60
    else:
Packit fd8b60
        # Maybe it's a hex number.
Packit fd8b60
        if not s.startswith('0x'):
Packit fd8b60
            raise ValueError
Packit fd8b60
        flag, invert = int(s, 16), False
Packit fd8b60
Packit fd8b60
    if req_neg:
Packit fd8b60
        invert = not invert
Packit fd8b60
    return (0, ~flag) if invert else (flag, ~0)
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Given a string containing a space/comma separated list of specifiers
Packit fd8b60
# of the form {+|-}flagname, return a tuple of the form (flagstoset,
Packit fd8b60
# flagstoclear).  This shares the same limitation as
Packit fd8b60
# kadm5int_acl_parse_restrictions() of losing the distinction between
Packit fd8b60
# orderings when the same flag bit appears in both the positive and
Packit fd8b60
# the negative sense.
Packit fd8b60
def speclist2mask(s):
Packit fd8b60
    toset, toclear = (0, ~0)
Packit fd8b60
    for x in re.split('[\t, ]+', s):
Packit fd8b60
        fset, fclear = flagspec2mask(x)
Packit fd8b60
        toset |= fset
Packit fd8b60
        toclear &= fclear
Packit fd8b60
Packit fd8b60
    return toset, toclear
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Print C table of input flag specifiers for lib/kadm5/str_conv.c.
Packit fd8b60
def _print_ftbl():
Packit fd8b60
    print('static const struct flag_table_row ftbl[] = {')
Packit fd8b60
    a = sorted(pflags.items(), key=lambda k, v: (v.flag, -v.invert, k))
Packit fd8b60
    for k, v in a:
Packit fd8b60
        s1 = '    {"%s",' % k
Packit fd8b60
        s2 = '%-31s KRB5_KDB_%s,' % (s1, v.flagname())
Packit fd8b60
        print('%-63s %d},' % (s2, 1 if v.invert else 0))
Packit fd8b60
Packit fd8b60
    print('};')
Packit fd8b60
    print('#define NFTBL (sizeof(ftbl) / sizeof(ftbl[0]))')
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Print C table of output flag names for lib/kadm5/str_conv.c.
Packit fd8b60
def _print_outflags():
Packit fd8b60
    print('static const char *outflags[] = {')
Packit fd8b60
    for i in range(32):
Packit fd8b60
        flag = 1 << i
Packit fd8b60
        if flag > max(_flagnames.keys()):
Packit fd8b60
            break
Packit fd8b60
        try:
Packit fd8b60
            s = '    "%s",' % _flagnames[flag]
Packit fd8b60
        except KeyError:
Packit fd8b60
            s = '    NULL,'
Packit fd8b60
        print('%-32s/* 0x%08x */' % (s, flag))
Packit fd8b60
Packit fd8b60
    print('};')
Packit fd8b60
    print('#define NOUTFLAGS (sizeof(outflags) / sizeof(outflags[0]))')
Packit fd8b60
Packit fd8b60
Packit fd8b60
# Print out C tables to insert into lib/kadm5/str_conv.c.
Packit fd8b60
def _main():
Packit fd8b60
    _print_ftbl()
Packit fd8b60
    print
Packit fd8b60
    _print_outflags()
Packit fd8b60
Packit fd8b60
Packit fd8b60
_setup_tables()
Packit fd8b60
Packit fd8b60
Packit fd8b60
if __name__ == '__main__':
Packit fd8b60
    _main()