def getRawEntry(self, dn): " return raw entry from LDAP module " if getattr(self, '_v_add', {}).has_key(dn): return (dn, self._v_add[dn]._data) elif dn in getattr(self, '_v_delete', ()): raise ldap.NO_SUCH_OBJECT("Entry '%s' has been deleted" % dn) try: e = self._connection().search_s(dn, ldap.SCOPE_BASE, 'objectclass=*') if e: return e[0] except: raise ldap.NO_SUCH_OBJECT("Cannot retrieve entry '%s'" % dn)
def modify_s(self, dn, modlist): if dn not in self.entries: raise ldap.NO_SUCH_OBJECT() for operation, attribute, value in modlist: if operation == ldap.MOD_ADD: self.entries[dn].append((attribute, value)) continue
def toSuffix(self, entry=None, name=None): ''' Return, for a given backend entry, the suffix values. Suffix values are identical from a LDAP point of views. Suffix values may be surrounded by ", or containing '\' escape characters. @param entry - LDAP entry of the backend @param name - backend DN @result list of values of suffix attribute (aka 'cn') @raise ldap.NO_SUCH_OBJECT - in name is invalid DN ValueError - entry does not contains the suffix attribute InvalidArgumentError - if both entry/name are missing ''' attr_suffix = BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_SUFFIX] if entry: if not entry.hasValue(attr_suffix): raise ValueError("Entry has no %s attribute %r" % (attr_suffix, entry)) return entry.getValues(attr_suffix) elif name: filt = "(objectclass=%s)" % BACKEND_OBJECTCLASS_VALUE try: attrs = [attr_suffix] ent = self.conn.getEntry(name, ldap.SCOPE_BASE, filt, attrs) self.log.debug("toSuffix: %s found by its DN" % ent.dn) except NoSuchEntryError: raise ldap.NO_SUCH_OBJECT("Backend DN not found: %s" % name) if not ent.hasValue(attr_suffix): raise ValueError("Entry has no %s attribute %r" % (attr_suffix, ent)) return ent.getValues(attr_suffix) else: raise InvalidArgumentError("entry or name are mandatory")
def read_s(self, dn, filterstr=None, attrlist=None, serverctrls=None, clientctrls=None, timeout=-1): """ Reads and returns a single entry specified by `dn'. Other attributes just like those passed to `search_ext_s()' """ r = self.search_ext_s( dn, ldap.SCOPE_BASE, filterstr or '(objectClass=*)', attrlist=attrlist, serverctrls=serverctrls, clientctrls=clientctrls, timeout=timeout, ) if r: return r[0][1] else: raise ldap.NO_SUCH_OBJECT('Empty search result reading entry %s' % (repr(dn)))
def search_ldap(self, ucs_dns=None, ldapfilter=None, ldapbase=None): attr = ('*', '+') if ucs_dns: if not ldapfilter: ldapfilter = '(objectClass=*)' ldap_result = [] missing_dns = [] for targetdn in ucs_dns: try: result = self.lo.search(base=targetdn, scope='base', filter=ldapfilter, attr=attr) ldap_result.extend(result) except ldap.NO_SUCH_OBJECT: missing_dns.append(targetdn) if missing_dns: raise ldap.NO_SUCH_OBJECT(1, 'No object: %s' % (missing_dns, ), [r[0] for r in ldap_result]) else: if not ldapfilter: ldapfilter = '(objectClass=*)' if not ldapbase: ldapbase = self.configRegistry['ldap/base'] ldap_result = self.lo.search(base=ldapbase, filter=ldapfilter, attr=attr) return ldap_result
def getAttr(self, dn, attr, required=False): # type: (str, str, bool) -> List[str] """ Return a single attribute of a single LDAP object. :param str dn: The distinguished name of the object to lookup. :param str attr: The attribute to fetch. :param bool required: Raise an exception instead of returning an empty dictionary. :returns: A list of values. :rtype: list[str] :raises ldap.NO_SUCH_OBJECT: If the LDAP object is not accessible. .. warning:: the attribute name is currently case sensitive and must be given as in the LDAP schema .. warning:: when `required=True` it raises `ldap.NO_SUCH_OBJECT` even if the object exists but the attribute is not set """ _d = univention.debug.function('uldap.getAttr %s %s' % (dn, attr)) # noqa F841 if dn: try: result = self.lo.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)', [attr]) except ldap.NO_SUCH_OBJECT: result = [] if result and attr in result[0][1]: return result[0][1][attr] if required: raise ldap.NO_SUCH_OBJECT({'desc': 'no object'}) return []
def get_root_suffix_by_entry(self, entry_dn): """Get the root suffix to which the entry belongs :param entry_dn: An entry DN :type entry_dn: str :returns: str """ mapping_tree_list = sorted(self.list(), key=lambda b: len(b.dn), reverse=True) entry_dn_parts = str2dn(entry_dn) processing = True while processing: compare_dn = dn2str(entry_dn_parts) for mapping_tree in mapping_tree_list: if str.lower(compare_dn) == str.lower(mapping_tree.rdn): processing = False return mapping_tree.rdn if entry_dn_parts: entry_dn_parts.pop(0) else: processing = False raise ldap.NO_SUCH_OBJECT(f"{entry_dn} doesn't belong to any suffix")
def search(self, filter='(objectClass=*)', base='', scope='sub', attr=[], unique=False, required=False, timeout=-1, sizelimit=0, serverctrls=None): '''do ldap search''' univention.debug.debug(univention.debug.LDAP, univention.debug.INFO, 'uldap.search filter=%s base=%s scope=%s attr=%s unique=%d required=%d timeout=%d sizelimit=%d' % (filter, base, scope, attr, unique, required, timeout, sizelimit)) if not base: base = self.base if scope == 'base+one': res = self.lo.search_ext_s(base, ldap.SCOPE_BASE, filter, attr, serverctrls=serverctrls, clientctrls=None, timeout=timeout, sizelimit=sizelimit) + \ self.lo.search_ext_s(base, ldap.SCOPE_ONELEVEL, filter, attr, serverctrls=serverctrls, clientctrls=None, timeout=timeout, sizelimit=sizelimit) else: if scope == 'sub' or scope == 'domain': ldap_scope = ldap.SCOPE_SUBTREE elif scope == 'one': ldap_scope = ldap.SCOPE_ONELEVEL else: ldap_scope = ldap.SCOPE_BASE res = self.lo.search_ext_s(base, ldap_scope, filter, attr, serverctrls=serverctrls, clientctrls=None, timeout=timeout, sizelimit=sizelimit) if unique and len(res) > 1: raise ldap.INAPPROPRIATE_MATCHING({'desc': 'more than one object'}) if required and len(res) < 1: raise ldap.NO_SUCH_OBJECT({'desc': 'no object'}) return res
def get(self, dn, attr=[], required=False ): # type: (str, List[str], bool) -> Dict[str, List[str]] """ Return multiple attributes of a single LDAP object. :param str dn: The distinguished name of the object to lookup. :param attr: The list of attributes to fetch. :type attr: list[str] :param bool required: Raise an exception instead of returning an empty dictionary. :returns: A dictionary mapping the requested attributes to a list of their values. :rtype: dict[str, list[str]] :raises ldap.NO_SUCH_OBJECT: If the LDAP object is not accessible. """ if dn: try: result = self.lo.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)', attr) except ldap.NO_SUCH_OBJECT: result = [] if result: return self.__decode_entry(result[0][1]) if required: raise ldap.NO_SUCH_OBJECT({'desc': 'no object'}) return {}
def _lint_mappingtree(self): """Backend lint This should check for: * missing mapping tree entries for the backend * missing indices if we are local and have log access? """ # Check for the missing mapping tree. suffix = self.get_attr_val_utf8('nsslapd-suffix') bename = self.lint_uid() try: mt = self._mts.get(suffix) if mt.get_attr_val_utf8( 'nsslapd-backend') != bename and mt.get_attr_val_utf8( 'nsslapd-state') != 'backend': raise ldap.NO_SUCH_OBJECT( "We have a matching suffix, but not a backend or correct database name." ) except ldap.NO_SUCH_OBJECT: result = DSBLE0001 result['check'] = f'backends:{bename}:mappingtree' result['items'] = [ bename, ] yield result
def get_with_type(self, selector=[], dn=None): """Get the correct role type :param dn: DN of wanted entry :type dn: str :param selector: An additional filter to search for, i.e. 'backend_name'. The attributes selected are based on object type, ie user will search for uid and cn. :type dn: str :returns: FilteredRole, ManagedRole or NestedRole """ ROLE_OBJECTCLASSES = { FilteredRole: ['nscomplexroledefinition', 'nsfilteredroledefinition'], ManagedRole: ['nssimpleroledefinition', 'nsmanagedroledefinition'], NestedRole: ['nscomplexroledefinition', 'nsnestedroledefinition'] } entry = self.get(selector=selector, dn=dn, json=False) entry_objectclasses = entry.get_attr_vals_utf8_l("objectClass") role_found = False for role, objectclasses in ROLE_OBJECTCLASSES.items(): role_found = all(oc in entry_objectclasses for oc in objectclasses) if role_found: return role(self._instance, entry.dn) if not role_found: raise ldap.NO_SUCH_OBJECT("Role definition was not found")
def get(self, selector=[], dn=None, json=False): """Get a child entry (DSLdapObject, Replica, etc.) with dn or selector using a base DN and objectClasses of our object (DSLdapObjects, Replicas, etc.) Note that * is not a valid selector, you should use "list()" instead. :param dn: DN of wanted entry :type dn: str :param selector: An additional filter to search for, i.e. 'backend_name'. The attributes selected are based on object type, ie user will search for uid and cn. :type dn: str :returns: A child entry """ results = [] if dn is not None: results = self._get_dn(dn) else: results = self._get_selector(selector) if len(results) == 0: raise ldap.NO_SUCH_OBJECT("No object exists given the filter criteria %s" % selector) if len(results) > 1: raise ldap.UNWILLING_TO_PERFORM("Too many objects matched selection criteria %s" % selector) if json: return self._entry_to_instance(results[0].dn, results[0]).get_all_attrs_json() else: return self._entry_to_instance(results[0].dn, results[0])
def authenticate_ldap(self, username, password): """ Authenticate a user via LDAP and return his/her LDAP properties. Raises AuthenticationError if the credentials are rejected, or EnvironmentError if the LDAP server can't be reached. :param username: username :param password: password """ uid = self.get_uid(username) if not password: msg = "Authenticating user %s with blank password not allowed" log.warning(msg, username) raise LdapPasswordError(msg) if "," in username: raise LdapUsernameError("invalid character in username: ,") try: server = self._get_ldap_server() filter_ = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login, username) log.debug("Authenticating %r filter %s at %s", self.BASE_DN, filter_, self.LDAP_SERVER) lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE, filter_) if not lobjects: raise ldap.NO_SUCH_OBJECT() for (dn, _attrs) in lobjects: if dn is None: continue user_attrs = self.fetch_attrs_from_simple_bind( server, dn, username, password) if user_attrs: break else: log.debug( "No matching LDAP objects for authentication " "of '%s' (%s)", uid, username) raise LdapPasswordError('Failed to authenticate user ' 'with given password') except ldap.NO_SUCH_OBJECT: log.debug("LDAP says no such user '%s' (%s), org_exc:", uid, username, exc_info=True) raise LdapUsernameError() except ldap.SERVER_DOWN: org_exc = traceback.format_exc() raise LdapConnectionError("LDAP can't access authentication " "server, org_exc:%s" % org_exc) return dn, user_attrs
def pta_del(inst, basedn, log, args): log = log.getChild('pta_del') plugin = PassThroughAuthenticationPlugin(inst) urls = list(map(lambda url: url.lower(), [i for _, i in plugin.get_urls().items()])) old_url_l = args.URL.lower() if old_url_l not in urls: raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.URL) plugin.remove_all("nsslapd-pluginarg%s" % urls.index(old_url_l)) log.info("Successfully deleted %s", args.URL)
def attruniq_show(inst, basedn, log, args): log = log.getChild('attruniq_show') plugins = AttributeUniquenessPlugins(inst) plugin = plugins.get(args.NAME) if not plugin.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.name) if args and args.json: log.info(plugin.get_all_attrs_json()) else: log.info(plugin.display())
def simple_bind_s(self, who, passwd): if who not in self.users: raise ldap.NO_SUCH_OBJECT(who) user = self.users[who] pass_ = user['userPassword'][0] if not validate_password(passwd, pass_): raise ldap.INVALID_CREDENTIALS(who, passwd) self.connected = True self.who = who self.cred = passwd
def memberof_show_config(inst, basedn, log, args): log = log.getChild('memberof_show_config') targetdn = args.DN config = MemberOfSharedConfig(inst, targetdn) if not config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % targetdn) if args and args.json: o_str = config.get_all_attrs_json() log.info(o_str) else: log.info(config.display())
def definition_show(inst, basedn, log, args): log = log.getChild('definition_show') definitions = AutoMembershipDefinitions(inst) definition = definitions.get(args.DEFNAME) if not definition.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.DEFNAME) if args and args.json: o_str = definition.get_all_attrs_json() log.info(o_str) else: log.info(definition.display())
def referint_show_config(inst, basedn, log, args): log = log.getChild('referint_show_config') targetdn = args.DN config = ReferentialIntegrityConfig(inst, targetdn) if not config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % targetdn) if args and args.json: o_str = config.get_all_attrs_json() log.info(o_str) else: log.info(config.display())
def pam_pta_show(inst, basedn, log, args): log = log.getChild('pam_pta_show') configs = PAMPassThroughAuthConfigs(inst) config = configs.get(args.NAME) if not config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.name) if args and args.json: o_str = config.get_all_attrs_json() log.info(o_str) else: log.info(config.display())
def linkedattr_show(inst, basedn, log, args): log = log.getChild('linkedattr_show') configs = LinkedAttributesConfigs(inst) config = configs.get(args.NAME) if not config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.name) if args and args.json: o_str = config.get_all_attrs_json() log.info(o_str) else: log.info(config.display())
def dna_show(inst, basedn, log, args): log = log.getChild('dna_show') configs = DNAPluginConfigs(inst) config = configs.get(args.NAME) if not config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.NAME) if args and args.json: o_str = config.get_all_attrs_json() log.info(o_str) else: log.info(config.display())
def search_s(self, req_dn, flag, req_search, attrs): print "LDAP_REQS: " + str(LDAP_REQS) for req in LDAP_REQS.keys(): (dn, search) = LDAP_REQS[req]['req'] print("req : %s/%s" % (dn, search)) print("params: %s/%s" % (req_dn, req_search)) if dn == req_dn and search == req_search: print("match %s!" % (req)) return LDAP_REQS[req]['res'] raise ldap.NO_SUCH_OBJECT('mock fail')
def get(self, dn, attr=[], required=False): '''returns ldap object''' if dn: try: result = self.lo.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)', attr) except ldap.NO_SUCH_OBJECT: result = [] if result: return self.__decode_entry(result[0][1]) if required: raise ldap.NO_SUCH_OBJECT({'desc': 'no object'}) return {}
def dna_config_show(inst, basedn, log, args): log = log.getChild('dna_config_show') targetdn = _get_shared_config_dn(inst, args) shared_config = DNAPluginSharedConfig(inst, targetdn) if not shared_config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % targetdn) if args and args.json: o_str = shared_config.get_all_attrs_json() log.info(o_str) else: log.info(shared_config.display())
def authenticate(binddn, password): # open a new connection conn = search.Connection() # bind using the specified credentials serverctrls = [] if cfg.pam_authc_ppolicy: serverctrls.append(PasswordPolicyControl()) res, data, msgid, ctrls = conn.simple_bind_s(binddn, password, serverctrls=serverctrls) # go over bind result server controls for ctrl in ctrls: if ctrl.controlType == PasswordPolicyControl.controlType: # found a password policy control logging.debug( 'PasswordPolicyControl found: error=%s (%s), ' 'timeBeforeExpiration=%s, graceAuthNsRemaining=%s', 'None' if ctrl.error is None else PasswordPolicyError(ctrl.error).prettyPrint(), ctrl.error, ctrl.timeBeforeExpiration, ctrl.graceAuthNsRemaining) if ctrl.error == 0: # passwordExpired return ( conn, constants.NSLCD_PAM_AUTHTOK_EXPIRED, PasswordPolicyError(ctrl.error).prettyPrint()) elif ctrl.error == 1: # accountLocked return ( conn, constants.NSLCD_PAM_ACCT_EXPIRED, PasswordPolicyError(ctrl.error).prettyPrint()) elif ctrl.error == 2: # changeAfterReset return ( conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password change is needed after reset') elif ctrl.error: return ( conn, constants.NSLCD_PAM_PERM_DENIED, PasswordPolicyError(ctrl.error).prettyPrint()) elif ctrl.timeBeforeExpiration is not None: return ( conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password will expire in %d seconds' % ctrl.timeBeforeExpiration) elif ctrl.graceAuthNsRemaining is not None: return ( conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password expired, %d grace logins left' % ctrl.graceAuthNsRemaining) # perform search for own object (just to do any kind of search) results = search.LDAPSearch( conn, base=binddn, scope=ldap.SCOPE_BASE, filter='(objectClass=*)', attributes=['dn']) for entry in results: if entry[0] == binddn: return conn, constants.NSLCD_PAM_SUCCESS, '' # if our DN wasn't found raise an error to signal bind failure raise ldap.NO_SUCH_OBJECT()
def getAttr(self, dn, attr, required=False): '''return attribute of ldap object''' _d = univention.debug.function('uldap.getAttr %s %s' % (dn, attr)) if dn: try: result = self.lo.search_s(dn, ldap.SCOPE_BASE, '(objectClass=*)', [attr]) except ldap.NO_SUCH_OBJECT: result = [] if result and attr in result[0][1]: return result[0][1][attr] if required: raise ldap.NO_SUCH_OBJECT({'desc': 'no object'}) return []
def regex_show(inst, basedn, log, args): log = log.getChild('regex_show') definitions = AutoMembershipDefinitions(inst) definition = definitions.get(args.DEFNAME) regexes = AutoMembershipRegexRules(inst, definition.dn) regex = regexes.get(args.REGEXNAME) if not regex.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.REGEXNAME) if args and args.json: o_str = regex.get_all_attrs_json() log.info(o_str) else: log.info(regex.display())
def mep_template_show(inst, basedn, log, args): log = log.getChild('mep_template_show') targetdn = args.DN if not ldap.dn.is_dn(targetdn): raise ValueError("Specified DN is not a valid DN") template = MEPTemplate(inst, targetdn) if not template.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % targetdn) if args and args.json: o_str = template.get_all_attrs_json() log.info(o_str) else: log.info(template.display())
def mep_config_show(inst, basedn, log, args): log = log.getChild('mep_config_show') plugin = ManagedEntriesPlugin(inst) config_area = plugin.get_attr_val_utf8_l('nsslapd-pluginConfigArea') configs = MEPConfigs(inst, config_area) config = configs.get(args.NAME) if not config.exists(): raise ldap.NO_SUCH_OBJECT("Entry %s doesn't exists" % args.name) if args and args.json: o_str = config.get_all_attrs_json() log.info(o_str) else: log.info(config.display())