Ejemplo n.º 1
0
    def create_rsa_ca(self, months=VALID):
        """
        Create a self signed CA.
        """

        # Wait a second to avoid an NSS bug with serial ids based on time.
        time.sleep(1)
        # Create noise.
        self._generate_noise('%s/noise.txt' % self._certdb)
        # Now run the command. Can we do this with NSS native?
        cmd = [
            '/usr/bin/certutil',
            '-S',
            '-n',
            CA_NAME,
            '-s',
            ISSUER,
            '-x',
            '-g',
            '%s' % KEYBITS,
            '-t',
            'CT,,',
            '-v',
            '%s' % months,
            '-2',
            '--keyUsage',
            'certSigning',
            '-d',
            self._certdb,
            '-z',
            '%s/noise.txt' % self._certdb,
            '-f',
            '%s/%s' % (self._certdb, PWD_TXT),
        ]
        cmd_input = b'y\n\n'  # responses to certutil questions
        self.log.debug("nss cmd: %s", format_cmd_list(cmd))
        result = ensure_str(
            run(cmd, check=True, stderr=PIPE, stdout=PIPE,
                input=cmd_input).stdout)
        self.log.debug("nss output: %s", result)
        # Now extract the CAcert to a well know place.
        # This allows us to point the cacert dir here and it "just works"
        cmd = [
            '/usr/bin/certutil',
            '-L',
            '-n',
            CA_NAME,
            '-d',
            self._certdb,
            '-a',
        ]
        self.log.debug("nss cmd: %s", format_cmd_list(cmd))
        try:
            certdetails = check_output(cmd, stderr=subprocess.STDOUT)
        except subprocess.CalledProcessError as e:
            raise ValueError(e.output.decode('utf-8').rstrip())
        with open('%s/ca.crt' % self._certdb, 'w') as f:
            f.write(ensure_str(certdetails))
        self.openssl_rehash(self._certdb)
        return True
Ejemplo n.º 2
0
 def __getattr__(self, name):
     from lib389.utils import ensure_str
     if self._defaults_cached is False and self._islocal:
         self._read_defaults()
         self._validate_defaults()
     # Are we online? Is our key in the config map?
     if name in CONFIG_MAP and self._instance is not None and self._instance.state == DIRSRV_STATE_ONLINE:
         # Get the online value.
         (dn, attr) = CONFIG_MAP[name]
         ent = self._instance.getEntry(dn, attrlist=[
             attr,
         ])
         # If the server doesn't have it, fall back to our configuration.
         if attr is not None:
             v = ensure_str(ent.getValue(attr))
         # Do we need to post-process the value?
         if name == 'version':
             # We need to post process this - it's 389-Directory/1.4.2.2.20191031git8166d8345 B2019.304.19
             # but we need a string like: 1.4.2.2.20191031git8166d8345
             v = v.split('/')[1].split()[0]
         return v
     # Else get from the config
     if self._serverid is not None:
         return ensure_str(
             self._config.get(SECTION,
                              name).format(instance_name=self._serverid))
     else:
         return ensure_str(self._config.get(SECTION, name))
Ejemplo n.º 3
0
    def __init__(self, path, name, log):
        self.log = log
        self.log.debug(f"olDatabase path -> {path}")
        entries = ldif_parse(path, f'{name}.ldif')
        assert len(entries) == 1
        self.config = entries.pop()
        self.log.debug(f"{self.config}")

        # olcSuffix, olcDbIndex, entryUUID
        self.suffix = ensure_str(self.config[1]['olcSuffix'][0])
        self.idx = name.split('}', 1)[0].split('{', 1)[1]
        self.uuid = ensure_str(self.config[1]['entryUUID'][0])

        self.index = [
            tuple(ensure_str(x).split(' '))
            for x in self.config[1]['olcDbIndex']
        ]

        self.log.debug(
            f"settings -> {self.suffix}, {self.idx}, {self.uuid}, {self.index}"
        )

        overlay_path = os.path.join(path, name)

        self.overlays = []
        if os.path.isdir(overlay_path):
            self.overlays = [
                olOverlay(overlay_path, x, log)
                for x in sorted(os.listdir(overlay_path))
            ]
Ejemplo n.º 4
0
 def __init__(self, instance, basedn, rdn=None):
     super(CosTemplates, self).__init__(instance)
     self._objectclasses = ['cosTemplate']
     self._filterattrs = ['cn']
     self._childobject = CosTemplate
     self._basedn = basedn
     if rdn is not None:
         self._basedn = '{},{}'.format(ensure_str(rdn), ensure_str(basedn))
Ejemplo n.º 5
0
    def _validate(self, rdn, properties, basedn):
        """
        Used to validate a create request.
        This way, it can be over-ridden without affecting
        the create types

        It also checks that all the values in _must_attribute exist
        in some form in the dictionary

        It has the useful trick of returning the dn, so subtypes
        can use extra properties to create the dn's here for this.
        """
        if properties is None:
            raise ldap.UNWILLING_TO_PERFORM('Invalid request to create. Properties cannot be None')
        if type(properties) != dict:
            raise ldap.UNWILLING_TO_PERFORM("properties must be a dictionary")

        # I think this needs to be made case insensitive
        # How will this work with the dictionary?
        for attr in self._must_attributes:
            if properties.get(attr, None) is None:
                raise ldap.UNWILLING_TO_PERFORM('Attribute %s must not be None' % attr)

        # Make sure the naming attribute is present
        if properties.get(self._rdn_attribute, None) is None and rdn is None:
            raise ldap.UNWILLING_TO_PERFORM('Attribute %s must not be None or rdn provided' % self._rdn_attribute)
        
        # This change here, means we can pre-load a full dn to _dn, or we can
        # accept based on the rdn
        tdn = self._dn

        if tdn is None:
            if basedn is None:
                raise ldap.UNWILLING_TO_PERFORM('Invalid request to create. basedn cannot be None')

            if properties.get(self._rdn_attribute, None) is not None:
                # Favour the value in the properties dictionary
                v = properties.get(self._rdn_attribute)
                if isinstance(v, list):
                    rdn = ensure_str(v[0])
                else:
                    rdn = ensure_str(v)

                tdn = '%s=%s,%s' % (self._rdn_attribute, rdn, basedn)

        # We may need to map over the data in the properties dict to satisfy python-ldap
        str_props = {}
        for k, v in properties.items():
            if isinstance(v, list):
                # str_props[k] = map(lambda v1: ensure_bytes(v1), v)
                str_props[k] = ensure_list_bytes(v)
            else:
                str_props[k] = ensure_bytes(v)
        #
        # Do we need to do extra dn validation here?
        return (tdn, str_props)
Ejemplo n.º 6
0
    def create_rsa_ca(self, months=VALID):
        """
        Create a self signed CA.
        """

        # Wait a second to avoid an NSS bug with serial ids based on time.
        time.sleep(1)
        # Create noise.
        self._generate_noise('%s/noise.txt' % self._certdb)
        # Now run the command. Can we do this with NSS native?
        cmd = [
            '/usr/bin/certutil',
            '-S',
            '-n',
            CA_NAME,
            '-s',
            ISSUER,
            '-x',
            '-g',
            '%s' % KEYBITS,
            '-t',
            'CT,,',
            '-v',
            '%s' % months,
            '--keyUsage',
            'certSigning',
            '-d',
            self._certdb,
            '-z',
            '%s/noise.txt' % self._certdb,
            '-f',
            '%s/%s' % (self._certdb, PWD_TXT),
        ]
        self.log.debug("nss cmd: %s", format_cmd_list(cmd))
        result = ensure_str(check_output(cmd, stderr=subprocess.STDOUT))
        self.log.debug("nss output: %s", result)
        # Now extract the CAcert to a well know place.
        # This allows us to point the cacert dir here and it "just works"
        cmd = [
            '/usr/bin/certutil',
            '-L',
            '-n',
            CA_NAME,
            '-d',
            self._certdb,
            '-a',
        ]
        self.log.debug("nss cmd: %s", format_cmd_list(cmd))
        certdetails = check_output(cmd, stderr=subprocess.STDOUT)
        with open('%s/ca.crt' % self._certdb, 'w') as f:
            f.write(ensure_str(certdetails))
        cmd = ['/usr/bin/c_rehash', self._certdb]
        self.log.debug("nss cmd: %s", format_cmd_list(cmd))
        check_output(cmd, stderr=subprocess.STDOUT)
        return True
Ejemplo n.º 7
0
    def __getattr__(self, name):
        from lib389.utils import ensure_str
        if self._defaults_cached is False and self._islocal:
            self._read_defaults()
            self._validate_defaults()
        # Are we online? Is our key in the config map?
        while name in CONFIG_MAP and self._instance is not None and self._instance.state == DIRSRV_STATE_ONLINE:
            # Get the online value.
            err = None
            try:
                (dn, attr) = CONFIG_MAP[name]
                ent = self._instance.getEntry(dn, attrlist=[
                    attr,
                ])
            except ldap.LDAPError as e:
                err = e
            if isinstance(err, ldap.NO_SUCH_OBJECT) and name in CONFIG_MAP2:
                try:
                    (dn, attr) = CONFIG_MAP2[name]
                    ent = self._instance.getEntry(dn, attrlist=[
                        attr,
                    ])
                    err = None
                except ldap.LDAPError as e:
                    err = e
            if isinstance(err, ldap.SERVER_DOWN):
                # Search in config.
                break
            if err is not None:
                raise _pretty_exception(
                    err,
                    f"while searching attribute {attr} in entry {dn} on server {self.serverid}"
                )
            # If the server doesn't have it, fall back to our configuration.
            if attr is not None:
                v = ensure_str(ent.getValue(attr))
            # Do we need to post-process the value?
            if name == 'version':
                # We need to post process this - it's 389-Directory/1.4.2.2.20191031git8166d8345 B2019.304.19
                # but we need a string like: 1.4.2.2.20191031git8166d8345
                v = v.split('/')[1].split()[0]
            return v
        # Else get from the config
        if self._config:
            if self._serverid is not None:
                return ensure_str(
                    self._config.get(
                        SECTION, name).format(instance_name=self._serverid))
            else:
                return ensure_str(self._config.get(SECTION, name))
        else:
            raise LookupError("""Invalid state
No paths config (defaults.inf) could be found.
This may be because the remote instance is offline, or your /etc/hosts is misconfigured for a local instance
""")
Ejemplo n.º 8
0
 def __init__(self, instance, basedn, rdn='ou=Groups'):
     super(Groups, self).__init__(instance)
     self._objectclasses = [
         'groupOfNames',
     ]
     self._filterattrs = [RDN]
     self._childobject = Group
     if rdn is None:
         self._basedn = ensure_str(basedn)
     else:
         self._basedn = '{},{}'.format(ensure_str(rdn), ensure_str(basedn))
Ejemplo n.º 9
0
 def __init__(self, instance, basedn, rdn=None):
     super(CosIndirectDefinitions, self).__init__(instance)
     self._objectclasses = [
         'cosSuperDefinition',
         'cosIndirectDefinition',
     ]
     self._filterattrs = ['cn']
     self._childobject = CosIndirectDefinition
     self._basedn = basedn
     if rdn is not None:
         self._basedn = '{},{}'.format(ensure_str(rdn), ensure_str(basedn))
    def _jsonify(self, fn, *args, **kwargs):
        # This needs to map all the values to ensure_str
        attrs = fn(*args, **kwargs)
        str_attrs = {}
        for k in attrs:
            str_attrs[ensure_str(k)] = ensure_list_str(attrs[k])

        response = {"dn": ensure_str(self._dn), "attrs": str_attrs}
        print('json response')
        print(response)

        return response
Ejemplo n.º 11
0
    def detect_alt_names(self, alt_names=[]):
        """Attempt to determine appropriate subject alternate names for a host.
        Returns the list of names we derive.

        :param alt_names: A list of alternate names.
        :type alt_names: list[str]
        :returns: list[str]
        """
        if self.dirsrv and self.dirsrv.host not in alt_names:
            alt_names.append(ensure_str(self.dirsrv.host))
        if len(alt_names) == 0:
            alt_names.append(ensure_str(socket.gethostname()))
        return alt_names
Ejemplo n.º 12
0
    def _jsonify(self, fn, *args, **kwargs):
        # This needs to map all the values to ensure_str
        attrs = fn(use_json=True, *args, **kwargs)
        str_attrs = {}
        for k in attrs:
            str_attrs[ensure_str(k)] = ensure_list_str(attrs[k])

        # ensure all the keys are lowercase
        str_attrs = dict((k.lower(), v) for k, v in list(str_attrs.items()))

        response = json.dumps({"type": "entry", "dn": ensure_str(self._dn), "attrs": str_attrs}, indent=4)

        return response
Ejemplo n.º 13
0
    def _jsonify(self, fn, *args, **kwargs):
        # This needs to map all the values to ensure_str
        attrs = fn(*args, **kwargs)
        str_attrs = {}
        for k in attrs:
            str_attrs[ensure_str(k)] = ensure_list_str(attrs[k])

        response = json.dumps({
            "type": "entry",
            "dn": ensure_str(self._dn),
            "attrs": str_attrs
        })

        return response
Ejemplo n.º 14
0
    def _rsa_cert_list(self):
        cmd = [
            '/usr/bin/certutil',
            '-L',
            '-d',
            self._certdb,
            '-f',
            '%s/%s' % (self._certdb, PWD_TXT),
        ]
        try:
            result = ensure_str(check_output(cmd, stderr=subprocess.STDOUT))
        except subprocess.CalledProcessError as e:
            raise ValueError(e.output.decode('utf-8').rstrip())

        # We can skip the first few lines. They are junk
        # IE ['',
        #     'Certificate Nickname                                         Trust Attributes',
        #     '                                                             SSL,S/MIME,JAR/XPI',
        #     '',
        #     'Self-Signed-CA                                               CTu,u,u',
        #     '']
        lines = result.split('\n')[4:-1]
        # Now make the lines usable
        cert_values = []
        for line in lines:
            if line == '':
                continue
            if line == 'Database needs user init':
                # There are no certs, abort...
                return []
            cert_values.append(
                re.match(r'^(.+[^\s])[\s]+([^\s]+)$', line.rstrip()).groups())
        return cert_values
Ejemplo n.º 15
0
    def __init__(self, path, name, log):
        self.log = log
        self.log.debug(f"olOverlay path -> {path}/{name}")
        entries = ldif_parse(path, name)
        assert len(entries) == 1
        self.config = entries.pop()
        self.log.debug(f"{self.config}")

        # olcOverlay

        self.name = ensure_str(self.config[1]['olcOverlay'][0]).split('}',
                                                                      1)[1]
        self.classes = ensure_list_str(self.config[1]['objectClass'])
        self.log.debug(f"{self.name} {self.classes}")

        if 'olcMemberOf' in self.classes:
            self.otype = olOverlayType.MEMBEROF
            #
        elif 'olcRefintConfig' in self.classes:
            self.otype = olOverlayType.REFINT
            # olcRefintAttribute
            self.attrs = ensure_list_str(self.config[1]['olcRefintAttribute'])
        elif 'olcUniqueConfig' in self.classes:
            self.otype = olOverlayType.UNIQUE
            # olcUniqueURI
            self.attrs = ensure_list_str([
                # This is a ldap:///?uid?sub, so split ? [1] will give uid.
                attr.split('?')[1]
                for attr in ensure_list_str(self.config[1]['olcUniqueURI'])
            ])
        else:
            self.otype = olOverlayType.UNKNOWN
Ejemplo n.º 16
0
    def reinit(self):
        """
        Re-init (create) the nss db.
        """
        # 48886: The DB that DS ships with is .... well, broken. Purge it!
        for f in ('key3.db', 'cert8.db', 'key4.db', 'cert9.db', 'secmod.db', 'pkcs11.txt'):
            try:
                # Perhaps we should be backing these up instead ...
                os.remove("%s/%s" % (self._certdb, f ))
            except:
                pass

        try:
            os.makedirs(self._certdb)
        except FileExistsError:
            pass

        # In the future we may add the needed option to avoid writing the pin
        # files.
        # Write the pin.txt, and the pwdfile.txt
        if not os.path.exists('%s/%s' % (self._certdb, PIN_TXT)):
            with open('%s/%s' % (self._certdb, PIN_TXT), 'w') as f:
                f.write('Internal (Software) Token:%s' % self.dbpassword)
        if not os.path.exists('%s/%s' % (self._certdb, PWD_TXT)):
            with open('%s/%s' % (self._certdb, PWD_TXT), 'w') as f:
                f.write('%s' % self.dbpassword)

        # Init the db.
        # 48886; This needs to be sql format ...
        cmd = ['/usr/bin/certutil', '-N', '-d', self._certdb, '-f', '%s/%s' % (self._certdb, PWD_TXT)]
        self._generate_noise('%s/noise.txt' % self._certdb)
        self.log.debug("nss cmd: %s" % cmd)
        result = ensure_str(check_output(cmd, stderr=subprocess.STDOUT))
        self.log.debug("nss output: %s" % result)
        return True
Ejemplo n.º 17
0
    def resume(self, agmtdn, interval=ALWAYS):
        """Resume a paused replication agreement, paused with the "pause" method.
        It tries to enabled the replica agreement. If it fails
        (not implemented in all versions)
        It uses the schedule() with interval '0000-2359 0123456'.

        :param agmtdn: agreement dn
        :type agmtdn: str
        :param interval: - 'HHMM-HHMM D+' With D=[0123456]+
                          - Agreement.ALWAYS
                          - Agreement.NEVER
                          - Default is NEVER
        :type interval: str

        :returns: None
        :raises: - ValueError - if interval is not valid
                  - ldap.NO_SUCH_OBJECT - if agmtdn does not exist
        """

        self.log.info("Resuming replication %s" % agmtdn)
        mod = [(ldap.MOD_REPLACE, 'nsds5ReplicaEnabled', [b'on'])]
        self.conn.modify_s(ensure_str(agmtdn), mod)

        # Allow a little time for the repl agmt thread to start
        time.sleep(2)
Ejemplo n.º 18
0
    def changes(self, agmnt_dn):
        """Get a number of changes sent by this agreement.

        :param agmtdn: agreement dn
        :type agmtdn: str

        :returns: Number of changes
        :raises: NoSuchEntryError - if agreement entry with changes
                  attribute is not found
        """

        retval = 0
        try:
            ent = self.conn.getEntry(ensure_str(agmnt_dn), ldap.SCOPE_BASE,
                                     "(objectclass=*)",
                                     [RA_PROPNAME_TO_ATTRNAME[RA_CHANGES]])
        except:
            raise NoSuchEntryError("Error reading status from agreement",
                                   agmnt_dn)

        if ent.nsds5replicaChangesSentSinceStartup:
            val = ent.nsds5replicaChangesSentSinceStartup
            items = val.split(ensure_bytes(' '))
            if len(items) == 1:
                retval = int(items[0])
            else:
                for item in items:
                    ary = item.split(ensure_bytes(":"))
                    if ary and len(ary) > 1:
                        retval = retval + int(ary[1].split(
                            ensure_bytes("/"))[0])
        return retval
Ejemplo n.º 19
0
    def _rsa_cert_list(self):
        cmd = [
            '/usr/bin/certutil',
            '-L',
            '-d',
            self._certdb,
            '-f',
            '%s/%s' % (self._certdb, PWD_TXT),
        ]
        result = ensure_str(check_output(cmd, stderr=subprocess.STDOUT))

        # We can skip the first few lines. They are junk
        # IE ['',
        #     'Certificate Nickname                                         Trust Attributes',
        #     '                                                             SSL,S/MIME,JAR/XPI',
        #     '',
        #     'Self-Signed-CA                                               CTu,u,u',
        #     '']
        lines = result.split('\n')[4:-1]
        # Now make the lines usable
        cert_values = []
        for line in lines:
            data = line.split()
            cert_values.append((data[0], data[1]))
        return cert_values
Ejemplo n.º 20
0
    def pause(self, agmtdn, interval=NEVER):
        """Pause this replication agreement.  This replication agreement
        will send no more changes.  Use the resume() method to "unpause".

        It tries to disable the replica agreement. If it fails (not
        implemented in all version),

        It uses the schedule() with interval '2358-2359 0'

        :param agmtdn: agreement dn
        :type agmtdn: str
        :param interval: - 'HHMM-HHMM D+' With D=[0123456]+
                          - Agreement.ALWAYS
                          - Agreement.NEVER
                          - Default is NEVER
        :type interval: str

        :returns: None
        :raises: ValueError - if interval is not valid
        """

        self.log.info("Pausing replication %s" % agmtdn)
        mod = [(ldap.MOD_REPLACE, 'nsds5ReplicaEnabled', [b'off'])]
        self.conn.modify_s(ensure_str(agmtdn), mod)

        # Allow a little time for repl agmt thread to stop
        time.sleep(5)
Ejemplo n.º 21
0
 def __init__(self, entry, rawaci, verbose=False):
     """
     """
     self.verbose = verbose
     self.entry = entry
     self._rawaci = ensure_str(rawaci)
     self.acidata = self._parse_aci(self._rawaci)
Ejemplo n.º 22
0
 def _run_ldclt(self, cmd):
     result = None
     self.log.debug("ldclt loadtest ...")
     self.log.debug(format_cmd_list(cmd))
     try:
         result = ensure_str(subprocess.check_output(cmd))
     # If verbose, capture / log the output.
     except subprocess.CalledProcessError as e:
         print(format_cmd_list(cmd))
         print(result)
         raise (e)
     self.log.debug(result)
     # The output looks like:
     # ldclt[44308]: Average rate: 4017.60/thr  (4017.60/sec), total:  40176
     # ldclt[44308]: Number of samples achieved. Bye-bye...
     # ldclt[44308]: All threads are dead - exit.
     # ldclt[44308]: Global average rate: 40604.00/thr  (4060.40/sec), total: 406040
     # ldclt[44308]: Global number times "no activity" reports: never
     # ldclt[44308]: Global no error occurs during this session.
     # So we want the "global avg rate" per second.
     section = None
     for line in result.splitlines():
         if 'Global average rate' in line:
             section = line.split('(')[1].split(')')[0].split('/')[0]
     return section
Ejemplo n.º 23
0
def _get_pw_policy(inst, targetdn, log, use_json=None):
    pwp_manager = PwPolicyManager(inst)
    policy_type = _get_policy_type(inst, targetdn)
    attr_list = pwp_manager.get_attr_list()
    if "global" in policy_type.lower():
        targetdn = 'cn=config'
        attr_list.extend(['passwordIsGlobalPolicy', 'nsslapd-pwpolicy_local'])
        attrs = inst.config.get_attrs_vals_utf8(attr_list)
    else:
        policy = pwp_manager.get_pwpolicy_entry(targetdn)
        targetdn = policy.dn
        attrs = policy.get_attrs_vals_utf8(attr_list)

    if use_json:
        print(json.dumps({"type": "entry", "pwp_type": policy_type, "dn": ensure_str(targetdn), "attrs": attrs}))
    else:
        if "global" in policy_type.lower():
            response = "Global Password Policy: cn=config\n------------------------------------\n"
        else:
            response = "Local {} Policy: {}\n------------------------------------\n".format(policy_type, targetdn)
        for key, value in list(attrs.items()):
            if len(value) == 0:
                value = ""
            else:
                value = value[0]
            response += "{}: {}\n".format(key, value)
        print(response)
Ejemplo n.º 24
0
 def __init__(self, instance, basedn):
     super(UnsafeExtensibleObjects, self).__init__(instance)
     self._objectclasses = [
         'extensibleObject',
     ]
     self._filterattrs = ["cn"]
     self._childobject = UnsafeExtensibleObject
     self._basedn = ensure_str(basedn)
Ejemplo n.º 25
0
    def rdn(self):
        """Get an object RDN

        :returns: RDN
        """

        # How can we be sure this returns the primary one?
        return ensure_str(self.get_attr_val(self._rdn_attribute))
Ejemplo n.º 26
0
    def reinit(self):
        """
        Re-init (create) the nss db.
        """
        # 48886: The DB that DS ships with is .... well, broken. Purge it!
        assert self.remove_db()

        try:
            os.makedirs(self._certdb)
        except FileExistsError:
            pass

        if self.dirsrv is None:
            # Write a README to let people know what this is
            readme_file = '%s/%s' % (self._certdb, 'README.txt')
            if not os.path.exists(readme_file):
                with open(readme_file, 'w') as f:
                    f.write("""
SSCA - Simple Self-Signed Certificate Authority

This is part of the 389 Directory Server project's lib389 toolkit. It
creates a simple, standalone certificate authority for testing and
development purposes. It's suitable for evaluation and testing purposes
only.
                    """)

        # In the future we may add the needed option to avoid writing the pin
        # files.
        # Write the pin.txt, and the pwdfile.txt
        prv_mask = os.umask(0o177)
        try:
            pin_file = '%s/%s' % (self._certdb, PIN_TXT)
            if not os.path.exists(pin_file):
                with open(pin_file, 'w') as f:
                    f.write('Internal (Software) Token:%s' % self.dbpassword)

            pwd_text_file = '%s/%s' % (self._certdb, PWD_TXT)
            if not os.path.exists(pwd_text_file):
                with open(pwd_text_file, 'w') as f:
                    f.write('%s' % self.dbpassword)
        finally:
            prv_mask = os.umask(prv_mask)

        # Init the db.
        # 48886; This needs to be sql format ...
        cmd = [
            '/usr/bin/certutil', '-N', '-d', self._certdb, '-f',
            '%s/%s' % (self._certdb, PWD_TXT), '-@',
            '%s/%s' % (self._certdb, PWD_TXT)
        ]
        self._generate_noise('%s/noise.txt' % self._certdb)
        self.log.debug("nss cmd: %s", format_cmd_list(cmd))
        try:
            result = ensure_str(check_output(cmd, stderr=subprocess.STDOUT))
        except subprocess.CalledProcessError as e:
            raise ValueError(e.output.decode('utf-8').rstrip())
        self.log.debug("nss output: %s", result)
        return True
Ejemplo n.º 27
0
def finalize_ldif_file(instance, ldif_file):
    # Make the file owned by dirsrv
    os.chmod(ldif_file, 0o644)
    if os.getuid() == 0:
        # root user - chown the ldif to the server user
        userid = ensure_str(instance.userid)
        uid = pwd.getpwnam(userid).pw_uid
        gid = grp.getgrnam(userid).gr_gid
        os.chown(ldif_file, uid, gid)
Ejemplo n.º 28
0
def test_status(topology):
    """Test that status is returned from agreement"""

    topology.supplier.log.info("\n\n###########\n## STATUS\n##########")
    ents = topology.supplier.agreement.list(suffix=SUFFIX)
    for ent in ents:
        ra_status = topology.supplier.agreement.status(ensure_str(ent.dn))
        assert ra_status
        topology.supplier.log.info("Status of %s: %s" % (ent.dn, ra_status))
Ejemplo n.º 29
0
    def __init__(self, instance, basedn, rdn=None):
        """The set of costemplates that exist for direct and indirect
        implementations.

        :param instance: A dirsrv instance
        :type instance: DirSrv
        :param basedn: The basedn of the templates
        :type basedn: str
        :param rdn: The rdn of the templates
        :type rdn: str
        """
        super(CosTemplates, self).__init__(instance)
        self._objectclasses = ['cosTemplate']
        self._filterattrs = ['cn']
        self._childobject = CosTemplate
        self._basedn = basedn
        if rdn is not None:
            self._basedn = '{},{}'.format(ensure_str(rdn), ensure_str(basedn))
    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
Ejemplo n.º 31
0
 def __init__(self, entry, rawaci, verbose=False):
     """
     Breaks down an aci attribute string from 389, into a dictionary
     of terms and values. These values can then be manipulated, and
     subsequently rebuilt into an aci string.
     """
     self.verbose = verbose
     self.entry = entry
     self._rawaci = ensure_str(rawaci)
     self.acidata = self._parse_aci(self._rawaci)
Ejemplo n.º 32
0
    def delete_all(self, benamebase):
        benamebase = ensure_str(benamebase)
        dn = "cn=index,cn=" + benamebase + "," + DN_LDBM

        # delete each defined index
        self.conn.delete_branch_s(dn, ldap.SCOPE_ONELEVEL)

        # Then delete the top index entry
        self.log.debug("Delete head index entry %s" % (dn))
        self.conn.delete_s(dn)
Ejemplo n.º 33
0
    def get_attr_val_utf8(self, key, use_json=False):
        """Get a single attribute value from the entry in utf8 type

        :param key: An attribute name
        :type key: str
        :returns: A single bytes value
        :raises: ValueError - if instance is offline
        """

        return ensure_str(self.get_attr_val(key))
Ejemplo n.º 34
0
def complex_aci(topology):
    ACI_TARGET = ('(targetfilter ="(ou=groups)")(targetattr ="uniqueMember '
                  '|| member")')
    ACI_ALLOW = ('(version 3.0; acl "Allow test aci";allow (read, search, '
                 'write)')
    ACI_SUBJECT = ('(userdn="ldap:///dc=example,dc=com??sub?(ou=engineering)" '
                   'and userdn="ldap:///dc=example,dc=com??sub?(manager=uid='
                   'wbrown,ou=managers,dc=example,dc=com) || ldap:///dc=examp'
                   'le,dc=com??sub?(manager=uid=tbrown,ou=managers,dc=exampl'
                   'e,dc=com)" );)')
    ACI_BODY = ACI_TARGET + ACI_ALLOW + ACI_SUBJECT

    gentry = Entry('cn=testgroup,%s' % DEFAULT_SUFFIX)
    gentry.setValues('objectclass', 'top', 'extensibleobject')
    gentry.setValues('cn', 'testgroup')
    gentry.setValues('aci', ACI_BODY)

    topology.standalone.add_s(gentry)

    return ensure_str(ACI_BODY)
Ejemplo n.º 35
0
 def runInfProg(prog, content, verbose, prefix=None):
     """run a program that takes an .inf style file on stdin"""
     cmd = [prog]
     if verbose:
         cmd.append('-ddd')
     else:
         cmd.extend(['-l', '/dev/null'])
     cmd.extend(['-s', '-f', '-'])
     log.debug("running: %s " % cmd)
     if HASPOPEN:
         pipe = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
         child_stdin = pipe.stdin
         child_stdout = pipe.stdout
     else:
         pipe = popen2.Popen4(cmd)
         child_stdin = pipe.tochild
         child_stdout = pipe.fromchild
     child_stdin.write(ensure_bytes(content))
     child_stdin.close()
     if verbose:
         log.debug("PID %s" % pipe.pid)
     while pipe.poll() is None:
         (rr, wr, xr) = select.select([child_stdout], [], [], 1.0)
         if rr and len(rr) > 0:
             line = rr[0].readline()
             if not line:
                 break
             if verbose:
                 sys.stdout.write(ensure_str(line))
         elif verbose:
             print("timed out waiting to read from pid %s : %s " % (pipe.pid, cmd))
     child_stdout.close()
     exitCode = pipe.wait()
     # if verbose:
     log.debug("%s returned exit code %s" % (prog, exitCode))
     return exitCode
Ejemplo n.º 36
0
    def _install_ds(self, general, slapd, backends):
        """
        Actually install the Ds from the dicts provided.

        You should never call this directly, as it bypasses assertions.
        """
        # register the instance to /etc/sysconfig
        # We do this first so that we can trick remove-ds.pl if needed.
        # There may be a way to create this from template like the dse.ldif ...
        initconfig = ""
        with open("%s/dirsrv/config/template-initconfig" % slapd['sysconf_dir']) as template_init:
            for line in template_init.readlines():
                initconfig += line.replace('{{', '{', 1).replace('}}', '}', 1).replace('-', '_')
        with open("%s/sysconfig/dirsrv-%s" % (slapd['sysconf_dir'], slapd['instance_name']), 'w') as f:
            f.write(initconfig.format(
                SERVER_DIR=slapd['lib_dir'],
                SERVERBIN_DIR=slapd['sbin_dir'],
                CONFIG_DIR=slapd['config_dir'],
                INST_DIR=slapd['inst_dir'],
                RUN_DIR=slapd['run_dir'],
                DS_ROOT='',
                PRODUCT_NAME='slapd',
            ))

        # Create all the needed paths
        # we should only need to make bak_dir, cert_dir, config_dir, db_dir, ldif_dir, lock_dir, log_dir, run_dir? schema_dir,
        for path in ('backup_dir', 'cert_dir', 'config_dir', 'db_dir', 'ldif_dir', 'lock_dir', 'log_dir', 'run_dir'):
            if self.verbose:
                self.log.info("ACTION: creating %s" % slapd[path])
            try:
                os.makedirs(slapd[path], mode=0o775)
            except OSError:
                pass
            os.chown(slapd[path], slapd['user_uid'], slapd['group_gid'])

        # Copy correct data to the paths.
        # Copy in the schema
        #  This is a little fragile, make it better.
        # It won't matter when we move schema to usr anyway ...

        _ds_shutil_copytree(os.path.join(slapd['sysconf_dir'], 'dirsrv/schema'), slapd['schema_dir'])
        os.chown(slapd['schema_dir'], slapd['user_uid'], slapd['group_gid'])

        # Copy in the collation
        srcfile = os.path.join(slapd['sysconf_dir'], 'dirsrv/config/slapd-collations.conf')
        dstfile = os.path.join(slapd['config_dir'], 'slapd-collations.conf')
        shutil.copy2(srcfile, dstfile)
        os.chown(slapd['schema_dir'], slapd['user_uid'], slapd['group_gid'])

        # Selinux fixups?
        # Restorecon of paths?
        # Bind sockets to our type?

        # Create certdb in sysconfidir
        if self.verbose:
            self.log.info("ACTION: Creating certificate database is %s" % slapd['cert_dir'])
        # nss_create_new_database(slapd['cert_dir'])

        # Create dse.ldif with a temporary root password.
        # The template is in slapd['data_dir']/dirsrv/data/template-dse.ldif
        # Variables are done with %KEY%.
        # You could cheat and read it in, do a replace of % to { and } then use format?
        if self.verbose:
            self.log.info("ACTION: Creating dse.ldif")
        dse = ""
        with open(os.path.join(slapd['data_dir'], 'dirsrv', 'data', 'template-dse.ldif')) as template_dse:
            for line in template_dse.readlines():
                dse += line.replace('%', '{', 1).replace('%', '}', 1)

        with open(os.path.join(slapd['config_dir'], 'dse.ldif'), 'w') as file_dse:
            file_dse.write(dse.format(
                schema_dir=slapd['schema_dir'],
                lock_dir=slapd['lock_dir'],
                tmp_dir=slapd['tmp_dir'],
                cert_dir=slapd['cert_dir'],
                ldif_dir=slapd['ldif_dir'],
                bak_dir=slapd['backup_dir'],
                run_dir=slapd['run_dir'],
                inst_dir="",
                log_dir=slapd['log_dir'],
                fqdn=general['full_machine_name'],
                ds_port=slapd['port'],
                ds_user=slapd['user'],
                rootdn=slapd['root_dn'],
                # ds_passwd=slapd['root_password'],
                ds_passwd=self._secure_password,  # We set our own password here, so we can connect and mod.
                ds_suffix='',
                config_dir=slapd['config_dir'],
                db_dir=slapd['db_dir'],
            ))

        # open the connection to the instance.

        # Should I move this import? I think this prevents some recursion
        from lib389 import DirSrv
        ds_instance = DirSrv(self.verbose)
        ds_instance.containerised = self.containerised
        args = {
            SER_PORT: slapd['port'],
            SER_SERVERID_PROP: slapd['instance_name'],
            SER_ROOT_DN: slapd['root_dn'],
            SER_ROOT_PW: self._raw_secure_password,
            SER_DEPLOYED_DIR: slapd['prefix']
        }

        ds_instance.allocate(args)
        # Does this work?
        assert(ds_instance.exists())
        # Start the server
        ds_instance.start(timeout=60)
        ds_instance.open()

        # Create the backends as listed
        # Load example data if needed.
        for backend in backends:
            ds_instance.backends.create(properties=backend)

        # Make changes using the temp root
        # Change the root password finally

        # Complete.
        ds_instance.config.set('nsslapd-rootpw',
                               ensure_str(slapd['root_password']))
Ejemplo n.º 37
0
 def __unicode__(self):
     val = self._dn
     if self._rdn_attribute:
         # What if the rdn is multi value and we don't get the primary .... ARGHHH
         val = self.get_attr_val(self._rdn_attribute)
     return ensure_str(val)