def _storeConfigDB(key, val, typ=None, desc=None): """ insert or update the entry with key, value, type and description in the config DB """ value = val log_value = val if typ == 'password': log_value = "XXXXXXX" log.debug('key %r : value %r', key, log_value) if (not key.startswith("linotp.")): key = "linotp." + key if typ and typ == 'password': value = encryptPassword(val) en = decryptPassword(value) if (en != val): raise Exception("Error during encoding password type!") if type(value) not in [str, unicode]: return _storeConfigEntryDB(key, value, typ=typ, desc=desc) # for strings or unicode, we support continued entries # check if we have to split the value number_of_chunks = (len(value) / MAX_VALUE_LEN) if number_of_chunks == 0: return _storeConfigEntryDB(key, value, typ=typ, desc=desc) # the continuous type is a split over multiple entries: # * every entry will have an enumerated key but the first one which has the # original one. # * For all the type is 'C', but the last one which contains the original # type. # * For description all entries contains the enumeration, but the last the # original description for i in range(number_of_chunks + 1): # iterate through the chunks, the last one might be empty though cont_value = value[i * MAX_VALUE_LEN: (i + 1) * MAX_VALUE_LEN] cont_typ = "C" cont_desc = "%d:%d" % (i, number_of_chunks) cont_key = "%s__[%d:%d]" % (key, i, number_of_chunks) if i == 0: # first one will contain the correct key, but type is continuous cont_key = key elif i == number_of_chunks: # the last one will contain the type and the description cont_typ = typ cont_desc = desc res = _storeConfigEntryDB(cont_key, cont_value, typ=cont_typ, desc=cont_desc) return res
def getResolverInfo(resolvername): ''' return the resolver info of the given resolvername :param resolvername: the requested resolver :type resolvername: string :return : dict of resolver description ''' resolver_dict = {} typ = "" resolvertypes = get_resolver_types() descr = {} conf = context.get('Config') # conf = getLinotpConfig() for entry in conf: for typ in resolvertypes: if entry.startswith("linotp." + typ) and entry.endswith(resolvername): # the realm might contain dots "." # so take all after the 3rd dot for realm resolver = entry.split(".", 3) # An old entry without resolver name if len(resolver) <= 3: break # get the typed values of the descriptor! resolver_conf = get_resolver_class_config(typ) if typ in resolver_conf: descr = resolver_conf.get(typ).get('config', {}) else: descr = resolver_conf value = conf.get(entry) if resolver[2] in descr: configEntry = resolver[2] if descr.get(configEntry) == 'password': # do we already have the decrypted pass? if 'enc' + entry in conf: value = conf.get('enc' + entry) else: # if no, we take the encpass and decrypt it value = conf.get(entry) try: en = decryptPassword(value) value = en except: log.info("Decryption of resolver passwd failed: compatibility issue?") resolver_dict[resolver[2]] = value # Dont check the other resolver types break return {"type": typ, "data": resolver_dict, "resolver": resolvername}
def getResolverInfo(resolvername): ''' return the resolver info of the given resolvername :param resolvername: the requested resolver :type resolvername: string :return : dict of resolver description ''' resolver_dict = {} typ = "" resolvertypes = get_resolver_types() descr = {} conf = context.get('Config') # conf = getLinotpConfig() for entry in conf: for typ in resolvertypes: # get the typed values of the descriptor! resolver_conf = get_resolver_classConfig(typ) if typ in resolver_conf: descr = resolver_conf.get(typ).get('config', {}) else: descr = resolver_conf if entry.startswith("linotp." + typ) and entry.endswith(resolvername): # the realm might contain dots "." # so take all after the 3rd dot for realm resolver = entry.split(".", 3) # An old entry without resolver name if len(resolver) <= 3: break value = conf.get(entry) if resolver[2] in descr: configEntry = resolver[2] if descr.get(configEntry) == 'password': # do we already have the decrypted pass? if 'enc' + entry in conf: value = conf.get('enc' + entry) else: # if no, we take the encpass and decrypt it value = conf.get(entry) try: en = decryptPassword(value) value = en except: log.info("Decryption of resolver passwd failed: compatibility issue?") resolver_dict[ resolver[2] ] = value # Dont check the other resolver types break return {"type": typ, "data": resolver_dict, "resolver": resolvername}
def _retrieveAllConfigDB(): config = {} delay = False for conf in Session.query(Config).all(): log.debug("[retrieveAllConfigDB] key %r:%r" % (conf.Key, conf.Value)) key = conf.Key if (not key.startswith("linotp.")): key = "linotp." + conf.Key nVal = _expandHere(conf.Value) config[key] = nVal myTyp = conf.Type if myTyp is not None: if myTyp == 'password': if hasattr(c, 'hsm') == True and isinstance(c.hsm, dict): hsm = c.hsm.get('obj') if hsm is not None and hsm.isReady() == True: config['enc' + key] = decryptPassword(conf.Value) else: delay = True return (config, delay)
def _storeConfigDB(key, val, typ=None, desc=None): value = val log.debug('storeConfigDB: key %r : value %r' % (key, value)) if (not key.startswith("linotp.")): key = "linotp." + key confEntries = Session.query(Config).filter(Config.Key == unicode(key)) theConf = None if typ is not None and typ == 'password': value = encryptPassword(val) en = decryptPassword(value) if (en != val): raise Exception("StoreConfig: Error during encoding password type!") # # update if confEntries.count() == 1: theConf = confEntries[0] theConf.Value = unicode(value) if (typ is not None): theConf.Type = unicode(typ) if (desc is not None): theConf.Description = unicode(desc) # # insert elif confEntries.count() == 0: theConf = Config( Key=unicode(key), Value=unicode(value), Type=unicode(typ), Description=unicode(desc) ) if theConf is not None: Session.add(theConf) return 101
def _storeConfigDB(key, val, typ=None, desc=None): value = val log.debug('storeConfigDB: key %r : value %r' % (key, value)) if (not key.startswith("linotp.")): key = "linotp." + key confEntries = Session.query(Config).filter(Config.Key == unicode(key)) theConf = None if typ is not None and typ == 'password': value = encryptPassword(val) en = decryptPassword(value) if (en != val): raise Exception( "StoreConfig: Error during encoding password type!") # # update if confEntries.count() == 1: theConf = confEntries[0] theConf.Value = unicode(value) if (typ is not None): theConf.Type = unicode(typ) if (desc is not None): theConf.Description = unicode(desc) # # insert elif confEntries.count() == 0: theConf = Config(Key=unicode(key), Value=unicode(value), Type=unicode(typ), Description=unicode(desc)) if theConf is not None: Session.add(theConf) return 101
def _retrieveAllConfigDB(): """ get the server config from database with one call remark: for support for continous entries dedicated dicts for description and type are used for interim processing :return: config dict """ config = {} delay = False conf_dict = {} type_dict = {} desc_dict = {} cont_dict = {} # put all information in the dicts for later processing for conf in Session.query(Config).all(): log.debug("[retrieveAllConfigDB] key %r:%r" % (conf.Key, conf.Value)) conf_dict[conf.Key] = conf.Value type_dict[conf.Key] = conf.Type desc_dict[conf.Key] = conf.Description # a continous entry is indicated by the type 'C' and the description # starting with '0:' if conf.Type == 'C' and conf.Description[:len('0:')] == '0:': _start, num = conf.Description.split(':') cont_dict[conf.Key] = int(num) # cleanup the config from contious entries for key, number in cont_dict.items(): value = conf_dict[key] for i in range(number + 1): search_key = "%s__[%d:%d]" % (key, i, number) if search_key in conf_dict: value = value + conf_dict[search_key] del conf_dict[search_key] conf_dict[key] = value search_key = "%s__[%d:%d]" % (key, number, number) type_dict[key] = type_dict[search_key] desc_dict[key] = desc_dict[search_key] # normal processing as before continous here for key, value in conf_dict.items(): if key.startswith("linotp.") is False: key = "linotp." + key nVal = _expandHere(value) config[key] = nVal for key, value in config.items(): myTyp = type_dict.get(key) if myTyp is not None: if myTyp == 'password': if hasattr(c, 'hsm') == True and isinstance(c.hsm, dict): hsm = c.hsm.get('obj') if hsm is not None and hsm.isReady() == True: config['enc' + key] = decryptPassword(value) else: delay = True return (config, delay)
def _retrieveAllConfigDB(): """ get the server config from database with one call remark: for support for continous entries dedicated dicts for description and type are used for interim processing :return: config dict """ config = {} delay = False conf_dict = {} type_dict = {} desc_dict = {} cont_dict = {} # put all information in the dicts for later processing for conf in Session.query(Config).all(): log.debug("[retrieveAllConfigDB] key %r:%r" % (conf.Key, conf.Value)) conf_dict[conf.Key] = conf.Value type_dict[conf.Key] = conf.Type desc_dict[conf.Key] = conf.Description # a continous entry is indicated by the type 'C' and the description # starting with '0:' if conf.Type == 'C' and conf.Description[:len('0:')] == '0:': _start, num = conf.Description.split(':') cont_dict[conf.Key] = int(num) # cleanup the config from contious entries for key, number in cont_dict.items(): value = conf_dict[key] for i in range(number + 1): search_key = "%s__[%d:%d]" % (key, i, number) if search_key in conf_dict: value = value + conf_dict[search_key] del conf_dict[search_key] conf_dict[key] = value search_key = "%s__[%d:%d]" % (key, number, number) type_dict[key] = type_dict[search_key] desc_dict[key] = desc_dict[search_key] # normal processing as before continous here for key, value in conf_dict.items(): if key.startswith("linotp.") is False: key = "linotp." + key nVal = _expandHere(value) config[key] = nVal for key, value in config.items(): myTyp = type_dict.get(key) if myTyp is not None: if myTyp == 'password': if hasattr(c, 'hsm') is True and isinstance(c.hsm, dict): hsm = c.hsm.get('obj') if hsm is not None and hsm.isReady() is True: config['enc' + key] = decryptPassword(value) else: delay = True return (config, delay)
def _storeConfigDB(key, val, typ=None, desc=None): """ insert or update the entry with key, value, type and description in the config DB """ value = val log_value = val if typ == 'password': log_value = "XXXXXXX" log.debug('key %r : value %r', key, log_value) if (not key.startswith("linotp.")): key = "linotp." + key if typ and typ == 'password': value = encryptPassword(val) en = decryptPassword(value) if (en != val): raise Exception("Error during encoding password type!") if type(value) not in [str, unicode]: return _storeConfigEntryDB(key, value, typ=typ, desc=desc) # for strings or unicode, we support continued entries # check if we have to split the value # the continuous type is a split over multiple entries: # * every entry will have an enumerated key but the first one which has the # original one. # * For all the type is 'C', but the last one which contains the original # type. # * For description all entries contains the enumeration, but the last the # original description # # we check the split algorithm depending on the value data - # in case of only ascii, we can use the much faster simple algorithm # in case of unicode characters we have to take the much slower one # chunks = [] if len(value) < len(value.encode('utf-8')): text_slice = utf8_slice else: text_slice = simple_slice # the number of chunks is oriented toward the max length defined # by utf8 in bytes + the clipping of 6 bytes each. But as this could # vary, we could not calculate the number of chunks and thus benefit # from the iterator for cont_value in text_slice(value, MAX_VALUE_LEN): chunks.append(cont_value) number_of_chunks = len(chunks) # special simple case: either empty value or single entry if number_of_chunks == 1: return _storeConfigEntryDB(key, value, typ=typ, desc=desc) for i, cont_value in enumerate(chunks): cont_typ = "C" cont_desc = "%d:%d" % (i, number_of_chunks) cont_key = "%s__[%d:%d]" % (key, i, number_of_chunks) if i == 0: # first one will contain the correct key, but type is continuous cont_key = key elif i == number_of_chunks: # the last one will contain the type and the description cont_typ = typ cont_desc = desc res = _storeConfigEntryDB(cont_key, cont_value, typ=cont_typ, desc=cont_desc) return res
def getResolverInfo(resolvername, passwords=False): ''' return the resolver info of the given resolvername :param resolvername: the requested resolver :type resolvername: string :return : dict of resolver description ''' result = {"type": None, "data": {}, "resolver": resolvername} resolver_dict = {} descr = {} resolver_entries = {} resolvertypes = get_resolver_types() linotp_config = context.get('Config') for typ in resolvertypes: for config_entry in linotp_config: if (config_entry.startswith("linotp." + typ) and config_entry.endswith(resolvername)): resolver_entries[config_entry] = linotp_config.get( config_entry) if not resolver_entries: return result resolver_parts = resolver_entries.keys()[0].split('.') # # TODO: remove legacy code: An old entry without resolver name # if len(resolver_parts) <= 3: return result # # get the type descriptions for the resolver type # resolver_type = resolver_parts[1] resolver_conf = get_resolver_class_config(resolver_type) if resolver_type in resolver_conf: resolver_descr = resolver_conf.get(resolver_type).get('config', {}) else: resolver_descr = resolver_conf # # build up the resolver dictionary # for key, value in resolver_entries.items(): resolver_key = key.split(".")[2] if resolver_key in resolver_descr: if (resolver_descr.get(resolver_key) == 'password' and passwords is True): # do we already have the decrypted pass? if 'enc%s' % key in linotp_config: value = linotp_config.get('enc%s' % key) else: # if no, we take the entry and try to de crypt it value = linotp_config.get(key) try: value = decryptPassword(value) except Exception as exc: log.exception( "Decryption of resolver entry " "failed: %r", exc) resolver_dict[resolver_key] = value result["type"] = resolver_type result["data"] = resolver_dict return result
def _retrieveAllConfigDB(): """ get the server config from database with one call remark: for support for continous entries dedicated dicts for description and type are used for interim processing :return: config dict """ config = {} delay = False conf_dict = {} type_dict = {} desc_dict = {} cont_dict = {} # ---------------------------------------------------------------------- -- # first read all config db information into dicts for later processing for conf in Session.query(Config).all(): conf_dict[conf.Key] = conf.Value type_dict[conf.Key] = conf.Type desc_dict[conf.Key] = conf.Description # a continuous entry is indicated by the type 'C' and the description # search for the entry which starts with '0:' as it will provide the # number of continuous entries if conf.Type == 'C' and conf.Description[:len('0:')] == '0:': _start, num = conf.Description.split(':') cont_dict[conf.Key] = int(num) # ---------------------------------------------------------------------- -- # cleanup the config from continuous entries for key, number in cont_dict.items(): value = conf_dict[key] for i in range(number + 1): search_key = "%s__[%d:%d]" % (key, i, number) if search_key in conf_dict: value = value + conf_dict[search_key] del conf_dict[search_key] conf_dict[key] = value search_key = "%s__[%d:%d]" % (key, number, number) type_dict[key] = type_dict[search_key] desc_dict[key] = desc_dict[search_key] # ---------------------------------------------------------------------- -- # finally put the entries into the to be returned config dictionary # caring for the linotp. prefix and the exanding of config values for key, value in conf_dict.items(): if key.startswith("linotp.") is False: key = "linotp." + key nVal = _expandHere(value) config[key] = nVal # ---------------------------------------------------------------------- -- # special treatment of passwords, which are provided decrypted as # 'enclinotp.' linotp-config entries # # TODO: here will be the hook for the replacement of decrpyted values # with a password object in the linotp_config for key, value in config.items(): myTyp = type_dict.get(key) if not myTyp or myTyp != 'password': continue # ------------------------------------------------------------------ -- # for password decryption we require an working hsm or we # will delay the decoding of the config entries if not hasattr(c, 'hsm') or not isinstance(c.hsm, dict): delay = True continue hsm = c.hsm.get('obj') if not hsm or not hsm.isReady(): delay = True continue # # !!! dont try to utf-8 decode the passwords as they # are already "magically" correct: # - when retrieved from DB, they are already in unicode format, # which is sufficient for further processing :) # config['enc' + key] = decryptPassword(value) return (config, delay)
def getResolverInfo(resolvername, passwords=False): ''' return the resolver info of the given resolvername :param resolvername: the requested resolver :type resolvername: string :return : dict of resolver description ''' result = {"type": None, "data": {}, "resolver": resolvername} linotp_config = context.get('Config') resolver_types = context.get('resolver_types').values() # --------------------------------------------------------------------- -- # lookup, which resolver type is associated with this resolver name for config_entry in linotp_config: if config_entry.endswith("." + resolvername): # check if this is a resolver definition, starting with linotp. # and continuing with a resolver type part = config_entry.split('.') if (len(part) > 3 and part[0] == 'linotp' and part[1] in resolver_types): resolver_type = part[1] break else: return result # now we can load the resolver config unsing the resolver class resolver_cls = getResolverClass(resolver_type) res_conf, _missing = resolver_cls.filter_config(linotp_config, resolvername) # --------------------------------------------------------------------- -- # now prepare the resolver config output, which should contain # # - no global entries, starting with 'linotp.' # - adjusted passwords # - all values as text for key in res_conf.keys(): # suppress global config entries if key.startswith("linotp."): del res_conf[key] continue # should passwords be displayed? if passwords and key in resolver_cls.crypted_parameters: try: res_conf[key] = decryptPassword(res_conf[key]) except Exception as exc: log.exception("Decryption of resolver entry " "failed: %r", exc) # as we have in the resolver config typed values, this might # lead to some trouble. so we prepare for output comparison # the string representation if (not isinstance(res_conf[key], str) and not isinstance(res_conf[key], unicode)): res_conf[key] = "%r" % res_conf[key] result["type"] = resolver_type result["data"] = res_conf return result