Beispiel #1
0
    def build_dn_list(self, rdns, base, data, FixedRDN):
        fix = rdns[0]
        var = rdns[1:] if len(rdns) > 1 else []
        dns = [fix]

        # Check if we've have to use a fixed RDN.
        if FixedRDN:
            return["%s,%s" % (FixedRDN, base)]

        # Bail out if fix part is not in data
        if not fix in data:
            raise DNGeneratorError(C.make_error("ATTRIBUTE_NOT_FOUND", attribute=fix))

        # Append possible variations of RDN attributes
        if var:
            for rdn in permutations(var + [None] * (len(var) - 1), len(var)):
                dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn)))))
        dns = list(set(dns))

        # Assemble DN of RDN combinations
        dn_list = []
        for t in [tuple(d.split(",")) for d in dns]:
            ndn = []
            for k in t:
                ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0])))
            dn_list.append("+".join(ndn) + "," + base)

        return sorted(dn_list, key=len)
Beispiel #2
0
    def execute(self, connection, filterargs=()):
        """
        Executes the search on the given connection (an LDAPObject). filterargs
        is an object that will be used for expansion of the filter string.
        
        The python-ldap library returns utf8-encoded strings. For the sake of
        sanity, this method will decode all result strings and return them as
        Unicode.
        """
        try:
            filterstr = self.filterstr % filterargs
            results = connection.search_s(self.base_dn.encode('utf-8'),
                self.scope, filterstr.encode('utf-8'))

            # There's been a report of an LDAP server returning extraneous
            # entries with DNs of None. This will filter them out.
            results = filter(lambda r: r[0] is not None, results)

            results = _DeepStringCoder('utf-8').decode(results)

            result_dns = [result[0] for result in results]
            logger.debug(u"search_s('%s', %d, '%s') returned %d objects: %s" %
                (self.base_dn, self.scope, filterstr, len(result_dns), "; ".join(result_dns)))
        except self.ldap.LDAPError, e:
            results = []
            logger.error(u"search_s('%s', %d, '%s') raised %s" %
                (self.base_dn, self.scope, filterstr, pprint.pformat(e)))
Beispiel #3
0
    def build_dn_list(self, rdns, base, data, FixedRDN):
        fix = rdns[0]
        var = rdns[1:] if len(rdns) > 1 else []
        dns = [fix]

        # Check if we've have to use a fixed RDN.
        if FixedRDN:
            return["%s,%s" % (FixedRDN, base)]

        # Bail out if fix part is not in data
        if not fix in data:
            raise DNGeneratorError(C.make_error("ATTRIBUTE_NOT_FOUND", attribute=fix))

        # Append possible variations of RDN attributes
        if var:
            for rdn in permutations(var + [None] * (len(var) - 1), len(var)):
                dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn)))))
        dns = list(set(dns))

        # Assemble DN of RDN combinations
        dn_list = []
        for t in [tuple(d.split(",")) for d in dns]:
            ndn = []
            for k in t:
                ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0])))
            dn_list.append("+".join(ndn) + "," + base)

        return sorted(dn_list, key=len)
Beispiel #4
0
def dn_groups(conn: ldap.ldapobject.SimpleLDAPObject, dn: str,
              domain: str) -> List[str]:
    """
    Request group names from active directory by user DN
    2020-04-15
    :param conn: established connection to domain controller
    :type conn: ldap.ldapobject.SimpleLDAPObject
    :param dn: an active directory user DN
    :type dn: str
    :param domain: full name of active directory domain
    :type domain: str
    :return: list of group names whose user with DN is member of (SUCCESS), empty list otherwise
    :rtype: List[str]
    """
    if not conn:
        return []
    ldap_base: str = ','.join('dc=%s' % x for x in domain.split('.'))
    search_filter: str = '(|(&(objectClass=group)(member=%s)))' % ldap.filter.escape_filter_chars(
        dn)
    try:
        results: List[str] = list(
            filter(
                lambda x: x[0] is not None,
                conn.search_s(ldap_base, ldap.SCOPE_SUBTREE, search_filter,
                              ['sAMAccountName'])))
        return [item[1]['sAMAccountName'][0].decode() for item in results]
    except ldap.OPERATIONS_ERROR:
        return []
Beispiel #5
0
def user_dn(conn: ldap.ldapobject.SimpleLDAPObject, username: str,
            domain: str) -> str:
    """
    Requests user DN from active directory by username
    :param conn: established connection to domain controller
    :type conn: ldap.ldapobject.SimpleLDAPObject
    :param username: an active directory username
    :type username: str
    :return: DN for username if success, empty string otherwise
    :param domain: full name of active directory domain
    :type domain: str
    :rtype: str
    """
    if not conn:
        return ''
    ldap_base: str = ','.join('dc=%s' % x for x in domain.split('.'))
    search_filter: str = '(|(&(objectClass=person)(sAMAccountName=%s)))' % ad_clear_username(
        username)
    try:
        results: List[str] = list(
            filter(
                lambda x: x[0] is not None,
                conn.search_s(ldap_base, ldap.SCOPE_SUBTREE, search_filter,
                              [''])))
        if not len(results):
            return ''
        return results[0][0]
    except ldap.OPERATIONS_ERROR:
        return ''
Beispiel #6
0
def parse_ldap_base(ldap_conf):
    """Parse LDAP base from ldap.conf(5)."""
    # pylint: disable-msg=W0141
    ldap_conf = open(ldap_conf, 'rb')
    pattern = re.compile(r'''^\s*[bB][aA][sS][eE]\s+(.+)\s*$''')
    matches = [pattern.search(x) for x in ldap_conf.readlines()]
    base = filter(None, matches)[0].group(1)
    return base
Beispiel #7
0
    def _process_results(self, results):
        """
        Returns a sanitized copy of raw LDAP results. This scrubs out
        references, decodes utf8, etc.
        """
        results = filter(lambda r: r[0] is not None, results)
        results = _DeepStringCoder('utf-8').decode(results)

        result_dns = [result[0] for result in results]
        logger.debug(u"search_s('%s', %d, '%s') returned %d objects: %s" %
            (self.base_dn, self.scope, self.filterstr, len(result_dns), "; ".join(result_dns)))

        return results
Beispiel #8
0
    def _process_results(self, results):
        """
        Returns a sanitized copy of raw LDAP results. This scrubs out
        references, decodes utf8, etc.
        """
        results = filter(lambda r: r[0] is not None, results)
        results = _DeepStringCoder('utf-8').decode(results)

        result_dns = [result[0] for result in results]
        logger.debug(u"search_s('%s', %d, '%s') returned %d objects: %s" %
                     (self.base_dn, self.scope, self.filterstr,
                      len(result_dns), "; ".join(result_dns)))

        return results
Beispiel #9
0
def dn_groups(conn: ldap.ldapobject.SimpleLDAPObject, dn: str,
              domain: str) -> List[str]:
    """
    Request group names from active directory by user DN

    :param conn: established connection to domain controller
    :type conn: ldap.ldapobject.SimpleLDAPObject
    :param dn: an active directory user DN
    :type dn: str
    :param domain: full name of active directory domain
    :type domain: str
    :return: list of group names whose user with DN is member of (SUCCESS), empty list otherwise
    :rtype: List[str]
    """
    if not conn:
        logger.error(
            f'django_adtool.ad.ad_tools dn_groups failed. "conn" is null. dn={dn}, domain={domain}'
        )
        return []
    ldap_base: str = ','.join('dc=%s' % x for x in domain.split('.'))
    search_filter: str = '(|(&(objectClass=group)(member=%s)))' % ldap.filter.escape_filter_chars(
        dn)
    try:
        results: LdapSearchResult = list(
            filter(
                lambda x: x[0] is not None,
                conn.search_s(ldap_base, ldap.SCOPE_SUBTREE, search_filter,
                              ['sAMAccountName'])))
        if not results:
            logger.error(
                f'{__package__} dn_group failed. results is empty, dn={dn}, domain={domain}'
            )
        return [item[1]['sAMAccountName'][0].decode() for item in results]
    except ldap.OPERATIONS_ERROR as e:
        logger.error(
            f'{__package__} dn_group failed: {str(e)}, dn={dn}, domain={domain}'
        )
        return []
Beispiel #10
0
    def build_dn_list(self, rdns, base, data):
        fix = rdns[0]
        var = rdns[1:] if len(rdns) > 1 else []
        dns = [fix]

        # Bail out if fix part is not in data
        if not fix in data:
            raise DNGeneratorError("fix attribute '%s' is not in the entry" % fix)

        # Append possible variations of RDN attributes
        if var:
            for rdn in permutations(var + [None] * (len(var) - 1), len(var)):
                dns.append("%s,%s" % (fix, ",".join(filter(lambda x: x and x in data and data[x], list(rdn)))))
        dns = list(set(dns))

        # Assemble DN of RDN combinations
        dn_list = []
        for t in [tuple(d.split(",")) for d in dns]:
            ndn = []
            for k in t:
                ndn.append("%s=%s" % (k, ldap.dn.escape_dn_chars(data[k]['value'][0])))
            dn_list.append("+".join(ndn) + "," + base)

        return sorted(dn_list, key=len)
Beispiel #11
0
 def _college_group_names(self):
     return filter(College.is_valid_college_name, self._groups)
Beispiel #12
0
 def _team_group_names(self):
     return filter(Team.valid_team_name, self._groups)
Beispiel #13
0
    def getBootParams(self, address):
        #syslog.syslog(syslog.LOG_DEBUG, "Searching for {address}".format(address=address))
        with self.ldap.get_handle() as conn:
            res = conn.search_s(
                self.ldap.get_base(),
                ldap.SCOPE_SUBTREE,
                ldap.filter.filter_format("(&(macAddress=%s)(objectClass=FAIobject))", [address]),
                ['FAIstate', 'gotoBootKernel', 'gotoKernelParameters', 'gotoLdapServer', 'cn', 'ipHostNumber'])

            if res is not None:
                count = len(res)
                if count > 1:
                    syslog.syslog("[fai] ignoring %s - LDAP search is not unique (%d entries match)" % (address, res.count()))
                    return None

                if count == 1:
                    dn, attributes = res[0]
                    hostname = attributes.get('cn', [''])[0]
                    status = attributes.get('FAIstate', [''])[0]
                    if not status:
                        if self.default_init == 'fallback':
                            syslog.syslog(syslog.LOG_DEBUG, "[fai] No FAI Status for {hostname} - continue PXE boot".format(hostname=hostname))
                            return None
                        else:
                            status = self.default_init

                    syslog.syslog(syslog.LOG_DEBUG, "[fai] Found {hostname}, FAI Status is '{status}'".format(hostname=hostname, status=status))
                    kernel = attributes.get('gotoBootKernel', [''])[0]
                    ldap_server = attributes.get('gotoLdapServer', [''])[0]
                    cmdline = attributes.get('gotoKernelParameters', [''])[0]

                    if not kernel or not ldap_server or not cmdline:
                        # Check group membership
                        member_res = conn.search_s(
                            self.ldap.get_base(),
                            ldap.SCOPE_SUBTREE,
                            ldap.filter.filter_format("(&(member=%s)(objectClass=gosaGroupOfNames)(gosaGroupObjects=[W]))", [dn]),
                            ['FAIstate', 'gotoBootKernel', 'gotoKernelParameters', 'gotoLdapServer', 'cn', 'ipHostNumber'])
                        if member_res is not None:
                            group_count = len(member_res)
                            if group_count > 1:
                                syslog.syslog(syslog.LOG_ERR, "[fai] Found more than one group for host {hostname}!")
                                return None

                            if group_count == 1:
                                group_dn, group_attributes = member_res[0]

                                if not kernel:
                                    kernel = group_attributes.get('gotoBootKernel', [''])[0]

                                if not ldap_server:
                                    ldap_server = group_attributes.get('gotoLdapServer', [''])[0]

                                if not cmdline:
                                    cmdline = group_attributes.get('gotoKernelParameters', [''])[0]

                            if group_count == 0:
                                syslog.syslog(syslog.LOG_INFO, "[fai] {hostname} - no group membership found - aborting".format(hostname=hostname))

                    if not kernel or not ldap_server:
                        line = "[fai] {hostname} - missing attribute(s) -".format(hostname=hostname)
                        if not kernel:
                            line = line + " gotoBootKernel"
                        if not ldap_server:
                            line = line + " gotoLdapServer"
                        syslog.syslog(syslog.LOG_ERR, line)
                        return None

                    # Strip ldap parameter and all multiple and trailing spaces
                    cmdline = re.sub(r'ldap(=[^\s]*[\s]*|[\s]*$|\s+)', '', cmdline)
                    cmdline = re.sub(r'\s[\s]+', '', cmdline.strip())

                    # Get kernel and initrd from TFTP root
                    kernel='vmlinuz-install'
                    initrd='initrd.img-install'

                    # - guess filename for kernel
                    if not os.access(self.tftp_root + os.sep + kernel, os.F_OK):
                        syslog.syslog(syslog.LOG_ERR, "[fai] {hostname} - specified kernel {kernel} does not exist!".format(hostname=hostname, kernel=kernel))
                        return None

                    # - try to find the initrd
                    path = self.tftp_root + os.sep + initrd
                    if os.access(path, os.F_OK):
                        cmdline = cmdline + " initrd={initrd}".format(initrd=initrd)
                        cmdline = cmdline.strip()

                    # Add NFS options
                    cmdline = cmdline + " nfsroot=" + self.nfs_root
                    cmdline = cmdline.strip()

                    # Add FAI options
                    if status in ['install', 'install-init']:
                        cmdline = cmdline + " FAI_ACTION=install FAI_FLAGS={fai_flags} ip=dhcp".format(fai_flags=self.fai_flags) \
                                 + " devfs=nomount root=/dev/nfs boot=live union={union}".format(union=self.union)
                    elif status.startswith('error:') or status.startswith('installing:'):
                        faierror = ""
                        if status.startswith("installing:"):
                            faierror = "inst-"
                        faierror = faierror + status.split(":", 1)[1]
                        cmdline = cmdline + " FAI_ACTION=install FAI_FLAGS={fai_flags} ip=dhcp".format(fai_flags=self.fai_flags) \
                                + " devfs=nomount root=/dev/nfs boot=live union={union} faierror:{faierror}".format(union=self.union, faierror=faierror)
                    elif status in ['softupdate', 'localboot']:
                        kernel = 'localboot'

                    elif status == 'sysinfo':
                        sysflags = ','.join(filter(lambda x: x.strip() != "reboot", self.fai_flags.split(',')))
                        cmdline = cmdline + " FAI_ACTION=sysinfo FAI_FLAGS={fai_flags} ip=dhcp".format(fai_flags=sysflags) \
                                 + " devfs=nomount root=/dev/nfs boot=live union={union}".format(union=self.union)
                    else:
                        # Unknown status
                        syslog.syslog(syslog.LOG_ERR, "[fai] {hostname} - unknown FAIstate: {status}".format(hostname=hostname, status=status))
                        return None

                    return self.make_pxe_entry(kernel, cmdline, label="FAI - powered by FTS")

        return None
Beispiel #14
0
 def _college_group_names(self):
     return filter(College.is_valid_college_name, self._groups)
Beispiel #15
0
 def _team_group_names(self):
     return filter(Team.valid_team_name, self._groups)