def __call__(self, form, field): username = self.username_value_or_field if self.username_value_or_field in form.data: username = form.data[self.username_value_or_field] if app.config["LDAP_DEBUG_MODE"]: if username != app.config["LDAP_DEBUG_DATA"]["uid"] or app.config["LDAP_DEBUG_PASSWORD"] != field.data: raise ValidationError("LDAP_DEBUG_PASSWORD set but incorrect, log in as %s, password %s." % (app.config["LDAP_DEBUG_DATA"]["uid"], app.config["LDAP_DEBUG_PASSWORD"])) else: update_user_data(username, app.config["LDAP_DEBUG_DATA"]) return try: connection = ldap.initialize(app.config["LDAP_SERVER"]) # At this point, we update the user info (since we already have # a connection to LDAP) #connection.start_tls_s() escaped_username = escape_dn_chars(username) connection.simple_bind_s(app.config["LDAP_BIND_DN"].format(uid=escaped_username), field.data) filter = app.config["LDAP_FILTER"].format(uid=escaped_username) base_dn = app.config["LDAP_BASE_DN"].format(uid=escaped_username) results = connection.search_s(base_dn, ldap.SCOPE_SUBTREE, filter) results = {k:(v if len(v)>1 else v[0]) for k,v in results[0][1].iteritems()} connection.unbind_s() update_user_data(username, results) except ldap.INVALID_CREDENTIALS: raise ValidationError(self.message) except ldap.LDAPError, e: raise ValidationError("LDAP Error: " + (e.message["desc"] if e.message else "%s (%s)"%(e[1],e[0])))
def create_user(connection): form = UserCreateForm() if form.validate_on_submit(): uid = form.uid.data.encode('utf8') sn = form.sn.data.encode('utf8') givenName = form.givenName.data.encode('utf8') cn = '{0} {1}'.format(givenName, sn) password = encrypt_password(form.userPassword.data.encode('utf8')) entry = { 'objectClass': ['inetOrgPerson'], 'uid': uid, 'sn': sn, 'givenName': givenName, 'cn': cn, 'userPassword': password, 'mail': form.mail.data.encode('utf8'), 'mobile': form.mobile.data.encode('utf8'), } dn_template = app.config['USER_DN_TEMPLATE'].encode('utf8') dn = dn_template % {'uid': escape_dn_chars(uid)} try: connection.add_s(dn, ldap.modlist.addModlist(entry)) except ldap.ALREADY_EXISTS: raise LDAPError(u"Benutzer mit Login '{0}' " u"bereits vorhanden.".format(uid)) return redirect(url_for('.edit_user', uid=uid)) return render_template('user_create.html', form=form)
def from_student_dn(cls, lo, school, dn): examUserPrefix = ucr.get('ucsschool/ldap/default/userprefix/exam', 'exam-') dn = 'uid=%s%s,%s' % (escape_dn_chars(examUserPrefix), explode_dn(dn, True)[0], cls.get_container(school)) return cls.from_dn(dn, school, lo)
def auth_user(ldap_config, username=None, credentials=None): """ Authenticate a user. """ if not username or not credentials: LOG.warning('No username or credential is provided for' ' authentication.') return False account_base = ldap_config.get('accountBase') if account_base is None: LOG.warning('Account base needs to be configured to query users') return False account_pattern = ldap_config.get('accountPattern') if account_pattern is None: LOG.warning('No account pattern is defined to search for users.') LOG.warning('Please configure one.') return False username = escape_dn_chars(username) account_pattern = account_pattern.replace('$USN$', username) account_scope = ldap_config.get('accountScope', '') account_scope = get_ldap_query_scope(account_scope) service_user = ldap_config.get('username') service_cred = ldap_config.get('password') # Service user is not configured try to authenticate # with the given username and credentials. if not service_user: service_user = username service_cred = credentials LOG.debug("Creating SERVICE connection...") with LDAPConnection(ldap_config, service_user, service_cred) as connection: if connection is None: LOG.error('Please check your LDAP server ' 'authentication credentials.') LOG.error('Configured username: %s', service_user) return False user_dn = get_user_dn(connection, account_base, account_pattern, account_scope) if user_dn is None: LOG.warning("DN lookup failed for user name: '%s'!", username) if service_user is None: LOG.warning('Anonymous bind might not be enabled.') return False # Bind with the user's DN to check the password given by the user. # If bind is successful the user has given the right password. LOG.debug("Creating USER connection...") with LDAPConnection(ldap_config, user_dn, credentials) as connection: if not connection: LOG.info("User: %s cannot be authenticated.", username) return connection is not None
def modify(self, name, old_value, new_value): try: self.lo.modify( "cn={},{}".format(escape_dn_chars(name), self.ldap_base), [("ucsschoolUsernameNextNumber", str(old_value), str(new_value))] ) except noObject: raise NoValueStored("Name {!r} not found.".format(name))
def __init__(self, app, **kwargs): kwargs.setdefault( 'position', 'cn=%s,cn=custom attributes,cn=univention' % escape_dn_chars(app.id)) kwargs.setdefault('description', app.name) kwargs['module'] = re.split(r'\s*,\s*', kwargs.get('module', 'users/user')) super(ExtendedOption, self).__init__(app, **kwargs)
def join_sync_mode(): """ Join in bi-directional sync mode via UMC requests """ # check domain / get configuration: print '=== AD-JOIN STARTED ===' request_options = { "ad_server_address": options.domain_host, "username": options.domain_admin, "password": options.domain_password, "mode": "adconnector" } result = client.umc_command("adconnector/check_domain", request_options).result # configure / save options: print '=== AD-JOIN CONFIGURATION ===' try: kerberos_domain = result['Domain'] ad_ldap_base = result['LDAP_Base'] ad_dc_name = result['DC_DNS_Name'] except KeyError as exc: print "\nAn Error while reading the AD Domain configuration: %r" % exc exit(1) request_options = { 'Host_IP': options.domain_host, 'KerberosDomain': kerberos_domain, 'LDAP_Base': ad_ldap_base, 'LDAP_BindDN': "cn=" + escape_dn_chars(options.domain_admin) + ",cn=users," + ad_ldap_base, 'LDAP_Host': ad_dc_name, 'LDAP_Password': options.domain_password, 'MappingSyncMode': "sync" } conf_result = client.umc_command("adconnector/adconnector/save", request_options).result if not conf_result['success']: print "\nThe AD Connector configuration was not saved successfully: %s" % conf_result exit(1) # start AD connector: print '=== AD-JOIN STARTING CONNECTOR ===' start_result = client.umc_command("adconnector/service", { 'action': "start" }).result if not start_result['success']: print "\nThe AD Connector was not started successfully: %s" % start_result exit(1) print '=== AD-JOIN FINISHED ==='
def test_replica_install_after_restore(self): master = self.master replica1 = self.replicas[0] replica2 = self.replicas[1] tasks.install_master(master) tasks.install_replica(master, replica1) check_replication(master, replica1, "testuser1") # backup master. backup_path = backup(master) suffix = ipautil.realm_to_suffix(master.domain.realm) suffix = escape_dn_chars(str(suffix)) entry_ldif = ( "dn: cn=meTo{hostname},cn=replica," "cn={suffix}," "cn=mapping tree,cn=config\n" "changetype: modify\n" "replace: nsds5ReplicaEnabled\n" "nsds5ReplicaEnabled: off\n\n" "dn: cn=caTo{hostname},cn=replica," "cn=o\\3Dipaca,cn=mapping tree,cn=config\n" "changetype: modify\n" "replace: nsds5ReplicaEnabled\n" "nsds5ReplicaEnabled: off").format( hostname=replica1.hostname, suffix=suffix) # disable replication agreement tasks.ldapmodify_dm(master, entry_ldif) # uninstall master. tasks.uninstall_master(master, clean=False) # master restore. dirman_password = master.config.dirman_password master.run_command(['ipa-restore', backup_path], stdin_text=dirman_password + '\nyes') # re-initialize topology after restore. topo_name = "{}-to-{}".format(master.hostname, replica1.hostname) for topo_suffix in 'domain', 'ca': arg = ['ipa', 'topologysegment-reinitialize', topo_suffix, topo_name, '--left'] replica1.run_command(arg) # wait sometime for re-initialization tasks.wait_for_replication(replica1.ldap_connect()) # install second replica after restore tasks.install_replica(master, replica2) check_replication(master, replica2, "testuser2")
def test_replica_install_after_restore(self): master = self.master replica1 = self.replicas[0] replica2 = self.replicas[1] tasks.install_master(master) tasks.install_replica(master, replica1) check_replication(master, replica1, "testuser1") # backup master. backup_path = tasks.get_backup_dir(self.master) suffix = ipautil.realm_to_suffix(master.domain.realm) suffix = escape_dn_chars(str(suffix)) entry_ldif = ( "dn: cn=meTo{hostname},cn=replica," "cn={suffix}," "cn=mapping tree,cn=config\n" "changetype: modify\n" "replace: nsds5ReplicaEnabled\n" "nsds5ReplicaEnabled: off\n\n" "dn: cn=caTo{hostname},cn=replica," "cn=o\\3Dipaca,cn=mapping tree,cn=config\n" "changetype: modify\n" "replace: nsds5ReplicaEnabled\n" "nsds5ReplicaEnabled: off").format( hostname=replica1.hostname, suffix=suffix) # disable replication agreement tasks.ldapmodify_dm(master, entry_ldif) # uninstall master. tasks.uninstall_master(master, clean=False) # master restore. dirman_password = master.config.dirman_password master.run_command(['ipa-restore', backup_path], stdin_text=dirman_password + '\nyes') # re-initialize topology after restore. topo_name = "{}-to-{}".format(master.hostname, replica1.hostname) for topo_suffix in 'domain', 'ca': arg = ['ipa', 'topologysegment-reinitialize', topo_suffix, topo_name, '--left'] replica1.run_command(arg) # wait sometime for re-initialization tasks.wait_for_replication(replica1.ldap_connect()) # install second replica after restore tasks.install_replica(master, replica2) check_replication(master, replica2, "testuser2")
def lookup(cls, value, connection='default'): dn = cls.lookup_dn.format(escape_dn_chars(value)) conn = connections[connection] try: result = conn.search_s(dn, ldap.SCOPE_BASE)[0][1] except ldap.NO_SUCH_OBJECT: raise cls.DoesNotExist(dn) instance = cls(result) instance._fetched = True return instance
def __init__(self, app, lo, pos, create_if_not_exists=False): self._localhost = '%s.%s' % (ucr_get('hostname'), ucr_get('domainname')) self._udm_obj = None self._rdn = '%s_%s' % (app.id, app.version) self._container = 'cn=%s,cn=apps,cn=univention,%s' % (escape_dn_chars( app.id), ucr_get('ldap/base')) self._lo = lo self._pos = pos self._reload(app, create_if_not_exists)
def dn(self): '''Generates a DN where the lib would assume this instance to be. Changing name or school of self will most likely change the outcome of self.dn as well ''' if self.name and self.position: name = self._meta.ldap_map_function(self.name) return '%s=%s,%s' % (self._meta.ldap_name_part, escape_dn_chars(name), self.position) return self.old_dn
def _add_self_to_portal(self, portal_obj): if isinstance(portal_obj, basestring): portal_mod = univention.admin.modules.get('settings/portal') portal_obj = univention.admin.objects.get(portal_mod, None, self.lo, position='', dn=portal_obj) portal_obj.open() old_content = portal_obj.info.get('content', []) if self.dn in [ entry for category, entries in old_content for entry in entries ]: return new_content = None portal_category_dn = 'cn=%s,cn=categories,cn=portal,cn=univention,%s' % ( escape_dn_chars(self['category']), self.lo.base, ) category_already_in_old_content = any( self.lo.compare_dn(portal_category_dn, category) for category, entries in old_content) if category_already_in_old_content: new_content = [[ category, entries + ([self.dn] if self.lo.compare_dn( category, portal_category_dn) else []) ] for category, entries in old_content] else: new_content = [[portal_category_dn, [self.dn]]] + old_content if new_content != old_content: try: portal_category_mod = univention.admin.modules.get( 'settings/portal_category') univention.admin.objects.get(portal_category_mod, None, self.lo, position='', dn=portal_category_dn) except univention.admin.uexceptions.noObject: # if the settings/portal_category object for the category string does not exist anymore create it portal_category_pos = univention.admin.uldap.position( self.lo.parentDn(portal_category_dn)) portal_category_obj = portal_category_mod.object( None, self.lo, portal_category_pos) portal_category_obj['name'] = self['category'] portal_category_obj['displayName'] = { 'admin': [('en_US', 'Administration'), ('de_DE', 'Verwaltung')], 'service': [('en_US', 'Applications'), ('de_DE', 'Applikationen')] }.get(self['category'], []) portal_category_obj.create() portal_obj['content'] = new_content portal_obj.modify()
def create(self, name, value): try: self.lo.add( "cn={},{}".format(escape_dn_chars(name), self.ldap_base), [ ("objectClass", "ucsschoolUsername"), ("ucsschoolUsernameNextNumber", str(value)) ] ) except objectExists: raise NameKeyExists("Cannot create key {!r} - already exists.".format(name))
def update_details(self): self.details_form.process(formdata=request.form, obj=self.group) if self.details_form.validate_on_submit(): mod_list = mod_list_from_form(self.group, self.details_form, ['description']) self.connection.modify_s(self.group.dn.encode('utf8'), mod_list) cn = self.details_form.cn.data.encode('utf8') if cn != self.group.cn: self.connection.rename_s(self.group.dn.encode('utf8'), "cn=" + escape_dn_chars(cn)) flash(u"Details erfolgreich geändert.", "success")
def retrieve(self, name): try: res = self.lo.get( "cn={},{}".format(escape_dn_chars(name), self.ldap_base), attr=["ucsschoolUsernameNextNumber"])["ucsschoolUsernameNextNumber"][0] except (KeyError, noObject): raise NoValueStored("Name {!r} not found.".format(name)) try: return int(res) except ValueError as exc: raise BadValueStored("Value for name {!r} has wrong format: {}".format(name, exc))
def ldap(self, command, attrs): self.logger.debug('received command %s %s', command, attrs) if command == 'SEARCH': out = StringIO() ldif_writer = LDIFWriter(out) qs = get_user_model().objects.all() if attrs['filter'] != '(objectClass=*)': m = re.match(r'\((\w*)=(.*)\)', attrs['filter']) if not m: print 'RESULT' print 'code: 1' print 'info: invalid filter' print return for user_attribute, ldap_attribute in MAPPING.iteritems(): if ldap_attribute == m.group(1): break else: print 'RESULT' print 'code: 1' print 'info: unknown attribute in filter' print return value = m.group(2) if value.endswith('*') and value.startswith('*'): user_attribute += '__icontains' value = value[1:-1] elif value.endswith('*'): user_attribute += '__istartswith' value = value[:-1] elif value.startswith('*'): user_attribute += '__iendswith' value = value[1:] else: user_attribute += '__iexact' value = unescape_filter_chars(value) qs = qs.filter(**{user_attribute: value.decode('utf-8')}) for user in qs: o = {} for user_attribute, ldap_attribute in MAPPING.iteritems(): o[ldap_attribute] = [ unicode(getattr(user, user_attribute)).encode('utf-8') ] o['objectClass'] = ['inetOrgPerson'] dn = 'uid=%s,%s' % (escape_dn_chars( o['uid'][0]), attrs['suffix']) self.logger.debug(u'sending entry %s %s', dn, o) ldif_writer.unparse(dn, o) print out.getvalue(), out.close() print 'RESULT' print 'code: 0' print 'info: RockNRoll' print
def _clean_rdn(self, rdn): """ Escape all characters that need escaping for a DN, see RFC 2253 """ if rdn.find('\\') != -1: # already escaped, disregard return rdn try: key, val = rdn.split('=') val = val.lstrip() return '%s=%s' % (key, escape_dn_chars(val)) except ValueError: return rdn
def cleanup(self): lo, po = getAdminConnection() self.log.info("Removing new unique-usernames,cn=ucsschool entries...") for username in self.unique_basenames_to_remove: dn = "cn={},cn=unique-usernames,cn=ucsschool,cn=univention,{}".format(escape_dn_chars(username), lo.base) self.log.debug("Removing %r", dn) try: lo.delete(dn) except noObject: pass except ldapError as exc: self.log.error("DN %r -> %s", dn, exc) super(UniqueObjectTester, self).cleanup()
def ldap(self, command, attrs): self.logger.debug('received command %s %s', command, attrs) if command == 'SEARCH': out = StringIO() ldif_writer = LDIFWriter(out) qs = get_user_model().objects.all() if attrs['filter'] != '(objectClass=*)': m = re.match(r'\((\w*)=(.*)\)', attrs['filter']) if not m: print 'RESULT' print 'code: 1' print 'info: invalid filter' print return for user_attribute, ldap_attribute in MAPPING.iteritems(): if ldap_attribute == m.group(1): break else: print 'RESULT' print 'code: 1' print 'info: unknown attribute in filter' print return value = m.group(2) if value.endswith('*') and value.startswith('*'): user_attribute += '__icontains' value = value[1:-1] elif value.endswith('*'): user_attribute += '__istartswith' value = value[:-1] elif value.startswith('*'): user_attribute += '__iendswith' value = value[1:] else: user_attribute += '__iexact' value = unescape_filter_chars(value) qs = qs.filter(**{user_attribute: value.decode('utf-8')}) for user in qs: o = {} for user_attribute, ldap_attribute in MAPPING.iteritems(): o[ldap_attribute] = [unicode(getattr(user, user_attribute)).encode('utf-8')] o['objectClass'] = ['inetOrgPerson'] dn = 'uid=%s,%s' % (escape_dn_chars(o['uid'][0]), attrs['suffix']) self.logger.debug(u'sending entry %s %s', dn, o) ldif_writer.unparse(dn, o) print out.getvalue(), out.close() print 'RESULT' print 'code: 0' print 'info: RockNRoll' print
def create_group(connection): form = GroupForm() if form.validate_on_submit(): cn = form.cn.data.encode('utf8') entry = { 'objectClass': ['groupOfMembers'], 'cn': cn, 'description': form.description.data.encode('utf8'), } dn_template = app.config['GROUP_DN_TEMPLATE'].encode('utf8') dn = dn_template % {'cn': escape_dn_chars(cn)} try: connection.add_s(dn, ldap.modlist.addModlist(entry)) except ldap.ALREADY_EXISTS: raise LDAPError(u"Gruppe mit Name '{0}' " u"bereits vorhanden.".format(cn)) return redirect(url_for('.edit_group', cn=cn)) return render_template('group_create.html', form=form)
def authenticate(self, conf, login, password): """ Set the login credentials before the superclass authenticates. We use the login credentials provided by the user to bind to the LDAP server. """ # The login name is untrusted and must be escaped to prevent # LDAP-injection attacks. escaped_login = escape_dn_chars(login) # Use %-formatting to be consistent with ldap_filter, as we don't # want to change python-ldap. binddn = conf["u_ldap_binddn_fmt"] % escaped_login conf["ldap_binddn"] = binddn conf["ldap_password"] = password # We don't pass the escaped login because it gets escaped when the # filter is created. # TODO Does user creation work if login contains exotic characters? return super().authenticate(conf, login, password)
def authenticate_block(self, block, username, password): utf8_username = username.encode('utf-8') utf8_password = password.encode('utf-8') for conn in get_connections(block): authz_ids = [] user_basedn = block.get('user_basedn') or block['basedn'] try: if block['user_dn_template']: template = str(block['user_dn_template']) escaped_username = escape_dn_chars(utf8_username) authz_ids.append(template.format(username=escaped_username)) else: try: if block.get('bind_with_username'): authz_ids.append(utf8_username) elif block['user_filter']: # allow multiple occurences of the username in the filter user_filter = block['user_filter'] n = len(user_filter.split('%s')) - 1 try: query = filter_format(user_filter, (utf8_username,) * n) except TypeError, e: log.error('user_filter syntax error %r: %s', block['user_filter'], e) return log.debug('looking up dn for username %r using ' 'query %r', username, query) results = conn.search_s(user_basedn, ldap.SCOPE_SUBTREE, query) # remove search references results = [ result for result in results if result[0] is not None] log.debug('found dns %r', results) if len(results) == 0: log.debug('user lookup failed: no entry found, %s' % query) elif not block['multimatch'] and len(results) > 1: log.error('user lookup failed: too many (%d) ' 'entries found: %s', len(results), query) else: authz_ids.extend(result[0] for result in results) else: raise NotImplementedError
def check_correct_domain_admin(): """Check domain administrator saved for ucs-test and correct if needed""" print('=== Checking / Correcting ucs-test domain administrator ===') ucr.load() ucr_domain_admin = ucr['tests/domainadmin/account'] if ucr_domain_admin: ucr_domain_admin_parts = str2dn(ucr_domain_admin) if ucr_domain_admin_parts[0][0][1] != options.domain_admin: ucr_domain_admin_parts[0][0] = ('uid', options.domain_admin, ucr_domain_admin_parts[0][0][2]) ucr['tests/domainadmin/account'] = dn2str(ucr_domain_admin_parts) else: print( "=== tests/domainadmin/account is not set, trying to create it ===" ) ucr['tests/domainadmin/account'] = 'uid=%s,cn=users,%s' % ( escape_dn_chars(options.domain_admin), ucr['ldap/base']) ucr.save()
def load_user(req): auth = req.authorization if not auth or not auth.password: return None uid = escape_dn_chars(auth.username) bind_dn = app.config['BIND_DN'] bind_pw = app.config['BIND_PW'] with pool.connection(bind_dn, bind_pw) as conn: try: dn = get_user_dn(conn, uid) except ldap.INVALID_CREDENTIALS: return LDAPError(u"Falsche Zugangsdaten für DN-Suche.") except NoResults: return None # Bind as user try: with pool.connection(dn, auth.password) as conn: user = get_user(conn, uid)._asdict() user['userPassword'] = auth.password return AppUser(**user) except ldap.INVALID_CREDENTIALS: return None
def __init__(self, app, **kwargs): kwargs.setdefault('belongs_to', '%sUser' % (app.id, )) kwargs.setdefault( 'position', 'cn=%s,cn=custom attributes,cn=univention' % escape_dn_chars(app.id)) kwargs.setdefault('tab_name', app.name) kwargs.setdefault('ldap_mapping', kwargs['name']) kwargs['module'] = re.split(r'\s*,\s*', kwargs.get('module', 'users/user')) if 'options' in kwargs: kwargs['options'] = re.split(r'\s*,\s*', kwargs.get('options', [])) kwargs.setdefault('options', []) super(ExtendedAttribute, self).__init__(app, **kwargs) if self.syntax == 'Boolean': self._syntax = '1.3.6.1.4.1.1466.115.121.1.7' self._equality = 'booleanMatch' self._substr = None if not self.udm_syntax: self.udm_syntax = 'TrueFalseUp' elif self.syntax == 'BooleanString': self._syntax = '1.3.6.1.4.1.1466.115.121.1.15' self._equality = 'caseIgnoreMatch' self._substr = 'caseIgnoreSubstringsMatch' if not self.udm_syntax: self.udm_syntax = 'TrueFalseUp' elif self.syntax == 'String': self._syntax = '1.3.6.1.4.1.1466.115.121.1.15' self._equality = 'caseIgnoreMatch' self._substr = 'caseIgnoreSubstringsMatch' #self._syntax = '1.3.6.1.4.1.1466.115.121.1.26' #self._equality = 'caseIgnoreIA5Match' #self._substr = None if not self.udm_syntax: self.udm_syntax = 'string' else: attribute_logger.warn('Ignoring unknown syntax %r' % (self.syntax, ))
def rdn_value_to_dn(keyword, account_type='user'): """Convert keyword and account type to DN.""" keyword = web.safestr(keyword).strip().replace(' ', '') keyword = escape_dn_chars(keyword) account_type = web.safestr(account_type) # No matter what account type is, try to get a domain name. domain = keyword.split('@', 1)[-1] # Validate account type. if account_type not in attrs.ACCOUNT_TYPES_ALL: return 'INVALID_ACCOUNT_TYPE' # Validate keyword. # Keyword is email address. if account_type in attrs.ACCOUNT_TYPES_EMAIL and \ not iredutils.is_email(keyword): return 'INVALID_MAIL' # Keyword is domain name. if account_type in attrs.ACCOUNT_TYPES_DOMAIN and \ not iredutils.is_domain(keyword): return 'INVALID_DOMAIN_NAME' # Convert keyword to DN. if account_type == 'user': dn = '{}={},{}{}={},{}'.format(attrs.RDN_USER, keyword, attrs.DN_BETWEEN_USER_AND_DOMAIN, attrs.RDN_DOMAIN, domain, settings.ldap_basedn) elif account_type == 'admin': dn = '{}={},{}'.format(attrs.RDN_ADMIN, keyword, settings.ldap_domainadmin_dn) elif account_type == 'domain': dn = '{}={},{}'.format(attrs.RDN_DOMAIN, keyword, settings.ldap_basedn) return dn
def do_query_ipaddr(name): return query_ipaddr(qtype, remote, tags, fmt % escape_dn_chars(name))
def _build_dn_with_config(self, login): login_esc = escape_dn_chars(login) return '{}={},{}'.format(self.user_login_attribute, login_esc, self.user_base_dn)
def convert_keyword_to_dn(keyword, accountType='user'): '''Convert keyword and account type to DN.''' keyword = web.safestr(keyword).strip().replace(' ', '') keyword = escape_dn_chars(keyword) accountType == web.safestr(accountType) # No matter what account type is, try to get a domain name. domain = keyword.split('@', 1)[-1] # Validate account type. if accountType not in attrs.ACCOUNT_TYPES_ALL: return 'INVALID_ACCOUNT_TYPE' # Validate keyword. # Keyword is email address. if accountType in attrs.ACCOUNT_TYPES_EMAIL and \ not iredutils.is_email(keyword): return 'INVALID_MAIL' # Keyword is domain name. if accountType in attrs.ACCOUNT_TYPES_DOMAIN and \ not iredutils.is_domain(keyword): return 'INVALID_DOMAIN_NAME' # Convert keyword to DN. if accountType == 'user': dn = '%s=%s,%s%s=%s,%s' % ( attrs.RDN_USER, keyword, attrs.DN_BETWEEN_USER_AND_DOMAIN, attrs.RDN_DOMAIN, domain, settings.ldap_basedn, ) elif accountType == 'maillist': dn = '%s=%s,%s%s=%s,%s' % ( attrs.RDN_MAILLIST, keyword, attrs.DN_BETWEEN_MAILLIST_AND_DOMAIN, attrs.RDN_DOMAIN, domain, settings.ldap_basedn, ) elif accountType == 'maillistExternal': dn = '%s=%s,%s%s=%s,%s' % ( attrs.RDN_MAILLIST_EXTERNAL, keyword, attrs.DN_BETWEEN_MAILLIST_EXTERNAL_AND_DOMAIN, attrs.RDN_DOMAIN, domain, settings.ldap_basedn, ) elif accountType == 'alias': dn = '%s=%s,%s%s=%s,%s' % ( attrs.RDN_ALIAS, keyword, attrs.DN_BETWEEN_ALIAS_AND_DOMAIN, attrs.RDN_DOMAIN, domain, settings.ldap_basedn, ) elif accountType == 'admin': dn = '%s=%s,%s' % ( attrs.RDN_ADMIN, keyword, settings.ldap_domainadmin_dn, ) elif accountType == 'catchall': dn = '%s=@%s,%s%s=%s,%s' % ( attrs.RDN_CATCHALL, domain, attrs.DN_BETWEEN_CATCHALL_AND_DOMAIN, attrs.RDN_DOMAIN, domain, settings.ldap_basedn, ) elif accountType == 'domain': dn = '%s=%s,%s' % ( attrs.RDN_DOMAIN, keyword, settings.ldap_basedn, ) return dn
def get_own_container(self): district = self.get_district() if district: return 'ou=%s,%s' % (escape_dn_chars(district), self.get_container()) return self.get_container()
from django.utils.encoding import force_text from authentic2.a2_rbac.utils import get_default_ou from django_rbac.utils import get_ou_model from authentic2.backends import ldap_backend from authentic2 import crypto import utils pytestmark = pytest.mark.skipunless(has_slapd(), reason='slapd is not installed') USERNAME = u'etienne.michu' UID = 'etienne.michu' CN = 'Étienne Michu' DN = 'cn=%s,o=ôrga' % escape_dn_chars(CN) PASS = '******' EMAIL = '*****@*****.**' @pytest.fixture def slapd(request): slapd = Slapd() slapd.add_db('o=ôrga') slapd.add_ldif('''dn: o=ôrga objectClass: organization o: ôrga dn: {dn} objectClass: inetOrgPerson userPassword: {password}
def dn(unique_id): params = (escape_dn_chars(unique_id), settings.LDAP_USERS_GROUP) return 'uniqueIdentifier=%s,%s' % params
def get_dn(self): dn_primary = getattr(self, self.primary_key) return self.lookup_dn.format(escape_dn_chars(dn_primary))
def _handler(ucr, changes): changed_entries = set() for key in changes.keys(): match = re.match('ucs/web/overview/entries/(admin|service)/([^/]+)/.*', key) if match: changed_entries.add(match.group(2)) changed_entries -= set( ['umc', 'invalid-certificate-list', 'root-certificate', 'ldap-master']) portal_logger.debug('Changed: %r' % changed_entries) if not changed_entries: return lo, pos = get_machine_connection() pos.setDn('cn=entry,cn=portals,cn=univention,%s' % ucr.get('ldap/base')) hostname = '%s.%s' % (ucr.get('hostname'), ucr.get('domainname')) # iterate over all ipv4 and ipv6 addresses and append them to the link local_hosts = [hostname] interfaces = Interfaces(ucr) for idev, iconf in interfaces.all_interfaces: # get ipv4 address of device if iconf.ipv4_address(): local_hosts.append(str(iconf.ipv4_address().ip)) # get ipv6 addresses of device for iname in iconf.ipv6_names: local_hosts.append('[%s]' % (iconf.ipv6_address(iname).ip, )) portal_logger.debug('Local hosts are: %r' % local_hosts) attr_entries = {} for changed_entry in changed_entries: attr_entries[changed_entry] = {} for ucr_key in ucr.keys(): match = re.match('ucs/web/overview/entries/([^/]+)/([^/]+)/(.*)', ucr_key) if not match: continue category = match.group(1) cn = match.group(2) key = match.group(3) value = ucr.get(ucr_key) if cn in attr_entries: portal_logger.debug('Matched %r -> %r' % (ucr_key, value)) entry = attr_entries[cn] entry['name'] = cn if '_links' not in entry: links = [] for host in local_hosts: if host: links.append(_Link(host=host)) entry['_links'] = links if key == 'link': for link in entry['_links']: if value.startswith('http'): link.full = value else: link.path = value elif key == 'port_http': if value: for link in entry['_links'][:]: if link.protocol == 'https': link = copy(link) entry['_links'].append(link) link.protocol = 'http' link.port = value elif key == 'port_https': if value: for link in entry['_links'][:]: if link.protocol == 'http': link = copy(link) entry['_links'].append(link) link.protocol = 'https' link.port = value elif key == 'icon': try: if value.startswith('/univention-management-console'): value = '/univention%s' % value[30:] with open('/var/www/%s' % value, 'rb') as fd: entry['icon'] = b64encode(fd.read()).decode('ASCII') except EnvironmentError: pass elif key == 'label': entry.setdefault('displayName', []) entry['displayName'].append(('en_US', value)) elif key == 'label/de': entry.setdefault('displayName', []) entry['displayName'].append(('de_DE', value)) elif key == 'label/fr': entry.setdefault('displayName', []) entry['displayName'].append(('fr_FR', value)) elif key == 'description': entry.setdefault('description', []) entry['description'].append(('en_US', value)) elif key == 'description/de': entry.setdefault('description', []) entry['description'].append(('de_DE', value)) elif key == 'description/fr': entry.setdefault('description', []) entry['description'].append(('fr_FR', value)) elif key == 'link-target': entry['linkTarget'] = value elif key == 'background-color': entry['backgroundColor'] = value else: portal_logger.info('Don\'t know how to handle UCR key %s' % ucr_key) for cn, attrs in attr_entries.items(): dn = 'cn=%s,%s' % (escape_dn_chars(cn), pos.getDn()) unprocessed_links = attrs.pop('_links', []) my_links = set() no_ports = all(not link.port for link in unprocessed_links) for link in unprocessed_links: if no_ports: if link.protocol == 'http': link.port = '80' elif link.protocol == 'https': link.port = '443' if link: my_links.add(('en_US', str(link))) if not link.protocol: link.protocol = 'http' if link: my_links.add(('en_US', str(link))) link.protocol = 'https' if link: my_links.add(('en_US', str(link))) my_links = list(my_links) portal_logger.debug('Processing %s' % dn) portal_logger.debug('Attrs: %r' % attrs) portal_logger.debug('Links: %r' % my_links) try: obj = init_object('portals/entry', lo, pos, dn) except AttributeError: portal_logger.error( 'The handler is not ready yet. Portal modules are not installed. You may have to set the variables again.' ) return except udm_errors.noObject: portal_logger.debug('DN not found...') if my_links: portal_logger.debug('... creating') attrs['link'] = my_links attrs['activated'] = True try: create_object_if_not_exists('portals/entry', lo, pos, **attrs) except udm_errors.insufficientInformation as exc: portal_logger.info('Cannot create: %s' % exc) try: category_pos = position(ucr.get('ldap/base')) category_pos.setDn('cn=category,cn=portals,cn=univention') category_dn = 'cn=domain-%s,%s' % ( escape_dn_chars(category), category_pos.getDn(), ) portal_logger.debug('Adding entry to %s' % (category_dn, )) obj = init_object('portals/category', lo, category_pos, category_dn) entries = obj['entries'] entries.append(dn) modify_object('portals/category', lo, category_pos, category_dn, entries=entries) except udm_errors.noObject: portal_logger.debug('DN not found...') continue links = obj['link'] portal_logger.debug('Existing links: %r' % links) links = [ _link for _link in links if urlsplit(_link[1]).hostname not in local_hosts ] links.extend(my_links) portal_logger.debug('New links: %r' % links) if not links: portal_logger.debug('Removing DN') remove_object_if_exists('portals/entry', lo, pos, dn) else: portal_logger.debug('Modifying DN') attrs['link'] = links modify_object('portals/entry', lo, pos, dn, **attrs)
def dn(unique_id): """Formats a unique_id into a DN.""" params = (escape_dn_chars(unique_id), settings.LDAP_USERS_GROUP) return 'uniqueIdentifier=%s,%s' % params
def dn(self): return 'univentionAppID=%s,%s' % (escape_dn_chars( self._rdn), self._container)
def dn(person_unique_id, unique_id): """ Formats an LDAP distinguished name for a remote system id """ params = (escape_dn_chars(unique_id), Person.dn(person_unique_id)) return 'uniqueIdentifier=%s,%s' % params
def query(qname, qclass, qtype, id_, remote): """ Answers a DNS query. """ if qclass != 'IN': raise DNSError('Unsupported qclass: %s (expceted "IN")' % qclass) domain = Domain(qname.lower()) edu_domain = None tags = set() if not hasattr(config, '_zone_domains'): config._zone_domains = [Domain(z) for z in config.zones] if not hasattr(config, '_edu_zone_domains'): config._edu_zone_domains = [Domain(z) for z in config.edu_zones] for zone in config._zone_domains: if domain <= zone: relative = domain[:-len(zone)] while relative and relative[-1] in known_tags: tags.add(relative.pop()) break else: for zone in config._edu_zone_domains: if domain <= zone: edu_domain = domain[-3] relative = domain[:-len(zone)] while relative and relative[-1] in known_tags: tags.add(relative.pop()) break else: raise DNSError('Not in my zones: %s' % qname) answers = [] searches = config.searches if edu_domain is None \ else [config.edu_search(edu_domain)] raw_search = config.raw_search if edu_domain is None \ else config.edu_raw_search(edu_domain) if qtype in ('A', 'AAAA', 'ANY'): def do_query_ipaddr(name): return query_ipaddr(qtype, remote, tags, fmt % escape_dn_chars(name)) for fmt in searches: ips = do_query_ipaddr(str(relative) or '@') if not ips and len(relative) > 0: # Wildcard support. # Currently only cn=**.<dc> elements in the LDAP tree are # respected. <dc> is a single domain component, and the ** # matches an arbitrary number of domain components. wild_relative = relative[-1:] wild_relative.appendleft('**') ips = do_query_ipaddr(str(wild_relative)) if ips: more = [make_answer(qname, qtype_, ip) for ip, qtype_ in ips] answers.extend(more) break base = raw_search % escape_dn_chars(str(relative) or '@') more = [make_answer(qname, t, a % dict(zone=zone)) for a, t in query_raw(qtype, remote, tags, base)] answers.extend(more) if len(relative) == 0 and qtype in ('SOA', 'ANY'): extra = make_answer(qname, 'SOA', compose_soa(str(zone))) answers.append(extra) return answers
def _build_dn_with_config(self, login, user_login_attribute, user_base_dn): login_esc = escape_dn_chars(login) return f'{user_login_attribute}={login_esc},{user_base_dn}'