Beispiel #1
0
    def add_s(self, dn, modlist):
        """Add an object with the specified attributes at dn."""
        if server_fail:
            raise ldap.SERVER_DOWN

        id_attr_in_modlist = False
        id_attr = self._dn_to_id_attr(dn)
        id_value = self._dn_to_id_value(dn)

        # The LDAP API raises a TypeError if attr name is None.
        for k, dummy_v in modlist:
            if k is None:
                raise TypeError('must be string, not None. modlist=%s' %
                                modlist)

            if k == id_attr:
                for val in dummy_v:
                    if common.utf8_decode(val) == id_value:
                        id_attr_in_modlist = True

        if not id_attr_in_modlist:
            LOG.debug('id_attribute=%(attr)s missing, attributes=%(attrs)s' %
                      {'attr': id_attr, 'attrs': modlist})
            raise ldap.NAMING_VIOLATION
        key = self.key(dn)
        LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', {
            'dn': common.utf8_decode(dn), 'attrs': modlist})
        if key in self.db:
            LOG.debug('add item failed: dn=%s is already in store.',
                      common.utf8_decode(dn))
            raise ldap.ALREADY_EXISTS(dn)

        self.db[key] = {k: _internal_attr(k, v) for k, v in modlist}
        self.db.sync()
    def _create(self, rdn=None, properties=None, basedn=None, ensure=False):
        """Internal implementation of create. This is used by ensure
        and create, to prevent code duplication. You should *never* call
        this method directly.
        """
        assert (len(self._create_objectclasses) > 0)
        basedn = ensure_str(basedn)
        self._log.debug('Checking "%s" under %s : %s' %
                        (rdn, basedn, properties))
        # Add the objectClasses to the properties
        (dn, valid_props) = self._validate(rdn, properties, basedn)
        # Check if the entry exists or not? .add_s is going to error anyway ...
        self._log.debug('Validated dn %s : valid_props %s' % (dn, valid_props))

        exists = False

        try:
            self._instance.search_ext_s(dn,
                                        ldap.SCOPE_BASE,
                                        self._object_filter,
                                        attrsonly=1,
                                        serverctrls=self._server_controls,
                                        clientctrls=self._client_controls)
            exists = True
        except ldap.NO_SUCH_OBJECT:
            pass

        if exists and ensure:
            # update properties
            self._log.debug('Exists %s' % dn)
            self._dn = dn
            # Now use replace_many to setup our values
            mods = []
            for k, v in valid_props.items():
                mods.append((ldap.MOD_REPLACE, k, v))
            self._instance.modify_ext_s(self._dn,
                                        mods,
                                        serverctrls=self._server_controls,
                                        clientctrls=self._client_controls)
        elif exists and not ensure:
            # raise "already exists."
            raise ldap.ALREADY_EXISTS("Entry %s already exists" % dn)
        if not exists:
            self._log.debug('Creating %s' % dn)
            e = Entry(dn)
            e.update(
                {'objectclass': ensure_list_bytes(self._create_objectclasses)})
            e.update(valid_props)
            # We rely on exceptions here to indicate failure to the parent.
            self._log.debug('Creating entry %s : %s' % (dn, e))
            self._instance.add_ext_s(e,
                                     serverctrls=self._server_controls,
                                     clientctrls=self._client_controls)
            # If it worked, we need to fix our instance dn
            self._dn = dn
        return self
def pta_add(inst, basedn, log, args):
    log = log.getChild('pta_add')
    new_url_l = _validate_url(args.URL.lower())
    plugin = PassThroughAuthenticationPlugin(inst)
    url_attrs = plugin.get_urls()
    urls = list(map(lambda url: url.lower(),
                    [i for _, i in url_attrs.items()]))
    next_num = _get_url_next_num(url_attrs)
    if new_url_l in urls:
        raise ldap.ALREADY_EXISTS("Entry %s already exists" % args.URL)
    plugin.add("nsslapd-pluginarg%s" % next_num, args.URL)
Beispiel #4
0
    def add_s(self, dn, attrs):
        """Add an object with the specified attributes at dn."""
        if server_fail:
            raise ldap.SERVER_DOWN

        key = "%s%s" % (self.__prefix, dn)
        LOG.debug("FakeLDAP add item: dn=%s, attrs=%s" % (dn, attrs))
        if key in self.db:
            LOG.error(
                "FakeLDAP add item failed: dn '%s' is already in store." % dn)
            raise ldap.ALREADY_EXISTS(dn)
        self.db[key] = dict([(k, v if isinstance(v, list) else [v])
                             for k, v in attrs])
        self.db.sync()
    def modrdn_s(self, dn, new_rdn, *ign):
        elems = explode_dn(dn)
        rdn = elems[0]
        tree_pos = TREE.getElementByDN(elems[1:])

        if rdn not in tree_pos:
            raise ldap.NO_SUCH_OBJECT(rdn)

        if new_rdn in tree_pos:
            raise ldap.ALREADY_EXISTS(new_rdn)

        rec = tree_pos.get(rdn)

        del tree_pos[rdn]
        tree_pos[new_rdn] = rec
Beispiel #6
0
    def add_s(self, dn, attrs):
        """Add an object with the specified attributes at dn."""
        if server_fail:
            raise ldap.SERVER_DOWN

        key = '%s%s' % (self.__prefix, dn)
        LOG.debug(
            _('FakeLdap add item: dn=%(dn)s, attrs=%(attrs)s') % {
                'dn': dn,
                'attrs': attrs
            })
        if key in self.db:
            LOG.debug(
                _('FakeLdap add item failed: dn=%s is'
                  ' already in store.'), dn)
            raise ldap.ALREADY_EXISTS(dn)

        self.db[key] = dict([(k, v if isinstance(v, list) else [v])
                             for k, v in attrs])
        self.db.sync()
Beispiel #7
0
    def add_s(self, dn, attrs):
        """Add an object with the specified attributes at dn."""
        if server_fail:
            raise ldap.SERVER_DOWN

        # The LDAP API raises a TypeError if attr name is None.
        for k, dummy_v in attrs:
            if k is None:
                raise TypeError('must be string, not None. attrs=%s' % attrs)

        key = '%s%s' % (self.__prefix, dn)
        LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', {
            'dn': dn,
            'attrs': attrs
        })
        if key in self.db:
            LOG.debug('add item failed: dn=%s is already in store.', dn)
            raise ldap.ALREADY_EXISTS(dn)

        self.db[key] = dict([(k, _process_attr(k, v)) for k, v in attrs])
        self.db.sync()
Beispiel #8
0
    def add_s(self, dn, modlist):
        """Add an object with the specified attributes at dn."""
        if server_fail:
            raise ldap.SERVER_DOWN

        # The LDAP API raises a TypeError if attr name is None.
        for k, dummy_v in modlist:
            if k is None:
                raise TypeError('must be string, not None. modlist=%s' %
                                modlist)

        key = self.key(dn)
        LOG.debug('add item: dn=%(dn)s, attrs=%(attrs)s', {
            'dn': core.utf8_decode(dn), 'attrs': modlist})
        if key in self.db:
            LOG.debug('add item failed: dn=%s is already in store.',
                      core.utf8_decode(dn))
            raise ldap.ALREADY_EXISTS(dn)

        self.db[key] = dict([(k, _internal_attr(k, v))
                             for k, v in modlist])
        self.db.sync()
    def add_s(self, dn, attr_list):
        elems = explode_dn(dn)
        rdn = elems[0]
        tree_pos = TREE.getElementByDN(elems[1:])

        if rdn in tree_pos:
            raise ldap.ALREADY_EXISTS(rdn)

        # Add rdn to attributes as well.
        rdn_key, rdn_value = rdn.split(b'=')
        tree_pos[rdn] = {rdn_key: [rdn_value]}
        record = tree_pos[rdn]

        for key, value in attr_list:
            record[key] = value

            # Maintain memberOf
            if self.maintain_memberof:
                if key == self.member_attr:
                    for v in value:
                        self.modify_s(v,
                                      [(ldap.MOD_ADD,
                                        self.memberof_attr,
                                        [dn])])
Beispiel #10
0
    def create(self, suffix=None, properties=None):
        """
            Creates backend entry and returns its dn.

            If the properties 'chain-bind-pwd' and 'chain-bind-dn' and
            'chain-urls' are specified the backend is a chained backend.  A
            chaining backend is created under
                'cn=chaining database,cn=plugins,cn=config'.

            A local backend is created under
                'cn=ldbm database,cn=plugins,cn=config'

            @param suffix - suffix stored in the backend
            @param properties - dictionary with properties values
            supported properties are
                BACKEND_NAME          = 'name'
                BACKEND_READONLY      = 'read-only'
                BACKEND_REQ_INDEX     = 'require-index'
                BACKEND_CACHE_ENTRIES = 'entry-cache-number'
                BACKEND_CACHE_SIZE    = 'entry-cache-size'
                BACKEND_DNCACHE_SIZE  = 'dn-cache-size'
                BACKEND_DIRECTORY     = 'directory'
                BACKEND_DB_DEADLOCK   = 'db-deadlock'
                BACKEND_CHAIN_BIND_DN = 'chain-bind-dn'
                BACKEND_CHAIN_BIND_PW = 'chain-bind-pw'
                BACKEND_CHAIN_URLS    = 'chain-urls'
                BACKEND_SUFFIX        = 'suffix'
                BACKEND_SAMPLE_ENTRIES = 'sample_entries'

            @return backend DN of the created backend

            @raise LDAPError

        """
        def _getBackendName(parent):
            '''
                Use to build a backend name that is not already used
            '''
            index = 1
            while True:
                bename = "local%ddb" % index
                base = ("%s=%s,%s" %
                        (BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME], bename,
                         parent))
                filt = "(objectclass=%s)" % BACKEND_OBJECTCLASS_VALUE
                self.log.debug("_getBackendName: baser=%s : fileter=%s", base,
                               filt)
                try:
                    self.conn.getEntry(base, ldap.SCOPE_BASE, filt)
                except (NoSuchEntryError, ldap.NO_SUCH_OBJECT):
                    self.log.info("backend name will be %s", bename)
                    return bename
                index += 1

        # suffix is mandatory. If may be in the properties
        if isinstance(properties, dict) and properties.get(
                BACKEND_SUFFIX, None) is not None:
            suffix = properties.get(BACKEND_SUFFIX)
        if not suffix:
            raise ldap.UNWILLING_TO_PERFORM('Missing Suffix')
        else:
            nsuffix = normalizeDN(suffix)

        # Check it does not already exist a backend for that suffix
        if self.conn.verbose:
            self.log.info("Checking suffix %s for existence", suffix)
        ents = self.conn.backend.list(suffix=suffix)
        if len(ents) != 0:
            raise ldap.ALREADY_EXISTS
        # Check if we are creating a local/chained backend
        chained_suffix = (properties and (BACKEND_CHAIN_BIND_DN in properties)
                          and (BACKEND_CHAIN_BIND_PW in properties)
                          and (BACKEND_CHAIN_URLS in properties))
        if chained_suffix:
            self.log.info("Creating a chaining backend")
            dnbase = DN_CHAIN
        else:
            self.log.info("Creating a local backend")
            dnbase = DN_LDBM

        # Get the future backend name
        if properties and BACKEND_NAME in properties:
            cn = properties[BACKEND_NAME]
        else:
            cn = _getBackendName(dnbase)

        # Check the future backend name does not already exists
        # we can imagine having no backends for 'suffix' but having a backend
        # with the same name
        dn = "%s=%s,%s" % (BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME], cn,
                           dnbase)
        ents = self.conn.backend.list(backend_dn=dn)
        if ents:
            raise ldap.ALREADY_EXISTS(
                "Backend already exists with that DN: %s" % ents[0].dn)

        # All checks are done, Time to create the backend
        try:
            entry = Entry(dn)
            entry.update({
                'objectclass':
                ['top', 'extensibleObject', BACKEND_OBJECTCLASS_VALUE],
                BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_NAME]:
                cn,
                BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_SUFFIX]:
                nsuffix,
            })

            if chained_suffix:
                entry.update({
                    BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_URLS]:
                    properties[BACKEND_CHAIN_URLS],
                    BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_BIND_DN]:
                    properties[BACKEND_CHAIN_BIND_DN],
                    BACKEND_PROPNAME_TO_ATTRNAME[BACKEND_CHAIN_BIND_PW]:
                    properties[BACKEND_CHAIN_BIND_PW]
                })

            self.log.debug("adding entry: %r", entry)
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS as e:
            self.log.error("Entry already exists: %r", dn)
            raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn))
        except ldap.LDAPError as e:
            self.log.error("Could not add backend entry: %r", dn)
            raise e

        backend_entry = self.conn._test_entry(dn, ldap.SCOPE_BASE)

        return backend_entry
Beispiel #11
0
    def add(self, suffix, binddn=None, bindpw=None, urls=None, attrvals=None, benamebase='localdb', setupmt=False, parent=None):
        """Setup a backend and return its dn. Blank on error XXX should RAISE!
            @param suffix
            @param benamebase   -   the backend common name
            @param setupmt  - eventually setup Mapping Tree entry
            @param urls - a string of ldapurl - create a chaining backend
            @oaram binddn   -   chaining proxy user
            @param bindpw   -   chaining proxy password
            @param attrvals: a dict with further params like
                for ldbm    {
                                'nsslapd-cachememsize': '1073741824',
                                'nsslapd-cachesize': '-1',
                            }
                for chain   {
                                'nsmaxresponsedelay': '60',
                                'nsslapd-sizelimit': '-1'
                            }
                            
            ex.
            benamebase="Isle0-0"
            urls=[ 
                "ldaps://f0-ldap-vip.example.it:636/",
                "ldaps://ldap-18.example.it:636/",
                "ldaps://ldap-19.example.it:636/"
                ]
            
            NOTE: The suffix attribute is a mere string for the backend.
                the following action will work nicely:
                c.backend.add(suffix="foo=example,dc=com",benamebase="db1")
                    
            TODO: rename benamebase with cn
            TODO: split CHAIN and LDBM ? eg. backend.add_chain
        """
        attrvals = attrvals or {}
        dnbase = ""

        # figure out what type of be based on args
        if binddn and bindpw and urls:  # its a chaining be
            dnbase = DN_CHAIN
        else:  # its a ldbm be
            dnbase = DN_LDBM

        nsuffix = normalizeDN(suffix)
        try:
            cn = benamebase 
            self.log.debug("create backend with cn: %s" % cn)
            dn = "cn=" + cn + "," + dnbase
            entry = Entry(dn)
            entry.update({
                'objectclass': ['top', 'extensibleObject', 'nsBackendInstance'],
                'cn': cn,
                'nsslapd-suffix': nsuffix
            })

            if binddn and bindpw and urls:  # its a chaining be
                entry.update({
                             'nsfarmserverurl': urls,
                             'nsmultiplexorbinddn': binddn,
                             'nsmultiplexorcredentials': bindpw
                             })

            # set attrvals (but not cn, because it's in dn)
            # TODO do it in Entry
            if attrvals:
                entry.update(attrvals)

            self.log.debug("adding entry: %r" % entry)
            self.conn.add_s(entry)
        except ldap.ALREADY_EXISTS, e:
            self.log.error("Entry already exists: %r" % dn)
            raise ldap.ALREADY_EXISTS("%s : %r" % (e, dn))