Exemple #1
0
    def restart(self, instance_name="", capture_output=True, wait=True):
        ipautil.run([paths.SYSTEMCTL, "restart",
                     self.service_instance(instance_name)],
                    skip_output=not capture_output)

        if wait and self.is_running(instance_name):
            self.wait_for_open_ports(self.service_instance(instance_name))
Exemple #2
0
    def run_signtool(self, args, stdin=None):
        with open(self.passwd_fname, "r") as f:
            password = f.readline()
        new_args = [paths.SIGNTOOL, "-d", self.secdir, "-p", password]

        new_args = new_args + args
        ipautil.run(new_args, stdin)
Exemple #3
0
    def __setup_principal(self):
        try:
            api.Command.service_add(unicode(self.cifs_principal))
            # Add the principal to the 'adtrust agents' group
            # as 389-ds only operates with GroupOfNames, we have to use
            # the principal's proper dn as defined in self.cifs_agent
            try:
                current = self.admin_conn.get_entry(self.smb_dn)
                members = current.get('member', [])
                if not(self.cifs_agent in members):
                    current["member"] = members + [self.cifs_agent]
                    self.admin_conn.update_entry(self.smb_dn, current)
            except errors.NotFound:
                entry = self.admin_conn.make_entry(
                    self.smb_dn,
                    objectclass=["top", "GroupOfNames"],
                    cn=[self.smb_dn['cn']],
                    member=[self.cifs_agent],
                )
                self.admin_conn.add_entry(entry)
        except Exception:
            # CIFS principal already exists, it is not the first time
            # adtrustinstance is managed
            # That's fine, we we'll re-extract the key again.
            pass

        self.clean_samba_keytab()

        try:
            ipautil.run(["ipa-getkeytab", "--server", self.fqdn,
                                          "--principal", self.cifs_principal,
                                          "-k", self.samba_keytab])
        except ipautil.CalledProcessError:
            root_logger.critical("Failed to add key for %s"
                                 % self.cifs_principal)
Exemple #4
0
def import_key(args, tmpdir):
    """Export key and certificate from a PKCS#12 file to key and cert files.
    """
    data = json.load(args.importfile)
    password = data['export password']
    p12data = base64.b64decode(data['pkcs12 data'])

    pk12pwfile = os.path.join(tmpdir, 'passwd')
    with open(pk12pwfile, 'w') as f:
        f.write(password)

    pk12file = os.path.join(tmpdir, 'import.p12')
    with open(pk12file, 'wb') as f:
        f.write(p12data)

    # get the certificate from the file
    cmd = [
        paths.OPENSSL, 'pkcs12',
        '-in', pk12file,
        '-clcerts', '-nokeys',
        '-out', args.certfile,
        '-password', 'file:{pk12pwfile}'.format(pk12pwfile=pk12pwfile),
    ]
    ipautil.run(cmd, umask=0o027)

    # get the private key from the file
    cmd = [
        paths.OPENSSL, 'pkcs12',
        '-in', pk12file,
        '-nocerts', '-nodes',
        '-out', args.keyfile,
        '-password', 'file:{pk12pwfile}'.format(pk12pwfile=pk12pwfile),
    ]
    ipautil.run(cmd, umask=0o027)
Exemple #5
0
def export_key(args, tmpdir):
    """Export cert and private from PEM files as PKCS#12 file.

    The PKCS#12 file is encrypted with a password.
    """
    pk12file = os.path.join(tmpdir, 'export.p12')

    password = ipautil.ipa_generate_password()
    pk12pwfile = os.path.join(tmpdir, 'passwd')
    with open(pk12pwfile, 'w') as f:
        f.write(password)

    # OpenSSL does not support pkcs12 export of a cert without key
    ipautil.run([
        paths.OPENSSL, 'pkcs12', '-export',
        '-in', args.certfile,
        '-out', pk12file,
        '-inkey', args.keyfile,
        '-password', 'file:{pk12pwfile}'.format(pk12pwfile=pk12pwfile),
    ])

    with open(pk12file, 'rb') as f:
        p12data = f.read()

    data = {
        'export password': password,
        'pkcs12 data': p12data,
    }
    common.json_dump(data, args.exportfile)
Exemple #6
0
    def change_admin_password(self, password):
        root_logger.debug("Changing admin password")
        dirname = config_dirname(self.serverid)
        dmpwdfile = ""
        admpwdfile = ""

        try:
            (dmpwdfd, dmpwdfile) = tempfile.mkstemp(dir='/var/lib/ipa')
            os.write(dmpwdfd, self.dm_password)
            os.close(dmpwdfd)

            (admpwdfd, admpwdfile) = tempfile.mkstemp(dir='/var/lib/ipa')
            os.write(admpwdfd, password)
            os.close(admpwdfd)

            args = ["/usr/bin/ldappasswd", "-h", self.fqdn,
                    "-ZZ", "-x", "-D", str(DN(('cn', 'Directory Manager'))),
                    "-y", dmpwdfile, "-T", admpwdfile,
                    str(DN(('uid', 'admin'), ('cn', 'users'), ('cn', 'accounts'), self.suffix))]
            try:
                env = { 'LDAPTLS_CACERTDIR':os.path.dirname(CACERT),
                        'LDAPTLS_CACERT':CACERT }
                ipautil.run(args, env=env)
                root_logger.debug("ldappasswd done")
            except ipautil.CalledProcessError, e:
                print "Unable to set admin password", e
                root_logger.debug("Unable to set admin password %s" % e)

        finally:
            if os.path.isfile(dmpwdfile):
                os.remove(dmpwdfile)
            if os.path.isfile(admpwdfile):
                os.remove(admpwdfile)
Exemple #7
0
    def __configure_selinux_for_smbd(self):
        selinux = False
        try:
            if (os.path.exists('/usr/sbin/selinuxenabled')):
                ipautil.run(["/usr/sbin/selinuxenabled"])
                selinux = True
        except ipautil.CalledProcessError:
            # selinuxenabled returns 1 if not enabled
            pass

        if selinux:
            # Don't assume all booleans are available
            sebools = []
            for var in self.selinux_booleans:
                try:
                    (stdout, stderr, returncode) = ipautil.run(["/usr/sbin/getsebool", var])
                    if stdout and not stderr and returncode == 0:
                        self.backup_state(var, stdout.split()[2])
                        sebools.append(var)
                except:
                    pass

            if sebools:
                bools = [var + "=true" for var in sebools]
                args = ["/usr/sbin/setsebool", "-P"]
                args.extend(bools);
                try:
                    ipautil.run(args)
                except:
                    self.print_msg(SELINUX_WARNING % dict(var=','.join(sebools)))
Exemple #8
0
 def backup_and_replace_hostname(self, fstore, statestore, hostname):
     old_hostname = socket.gethostname()
     try:
         ipautil.run([paths.BIN_HOSTNAME, hostname])
     except ipautil.CalledProcessError, e:
         print >>sys.stderr, ("Failed to set this machine hostname to "
                              "%s (%s)." % (hostname, str(e)))
Exemple #9
0
    def backup_and_replace_hostname(self, fstore, statestore, hostname):
        old_hostname = socket.gethostname()
        try:
            ipautil.run([paths.BIN_HOSTNAME, hostname])
        except ipautil.CalledProcessError as e:
            print(("Failed to set this machine hostname to "
                                 "%s (%s)." % (hostname, str(e))), file=sys.stderr)

        filepath = paths.ETC_HOSTNAME
        if os.path.exists(filepath):
            # read old hostname
            with open(filepath, 'r') as f:
                for line in f.readlines():
                    line = line.strip()
                    if not line or line.startswith('#'):
                        # skip comment or empty line
                        continue
                    old_hostname = line
                    break
            fstore.backup_file(filepath)

        with open(filepath, 'w') as f:
            f.write("%s\n" % hostname)
        os.chmod(filepath,
                 stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
        os.chown(filepath, 0, 0)
        self.restore_context(filepath)

        # store old hostname
        statestore.backup_state('network', 'hostname', old_hostname)
Exemple #10
0
    def _run_getkeytab(self):
        """
        backup and remove old service keytab (if present) and fetch a new one
        using ipa-getkeytab. This assumes that the service principal is already
        created in LDAP. By default GSSAPI authentication is used unless:
            * LDAPI socket is used and effective process UID is 0, then
              autobind is used by EXTERNAL SASL mech
            * self.dm_password is not none, then DM credentials are used to
              fetch keytab
        """
        self.fstore.backup_file(self.keytab)
        try:
            os.unlink(self.keytab)
        except OSError:
            pass

        ldap_uri = self.api.env.ldap_uri
        args = [paths.IPA_GETKEYTAB,
                '-k', self.keytab,
                '-p', self.principal,
                '-H', ldap_uri]
        nolog = tuple()

        if ldap_uri.startswith("ldapi://") and os.geteuid() == 0:
            args.extend(["-Y", "EXTERNAL"])
        elif self.dm_password is not None and not self.promote:
            args.extend(
                ['-D', 'cn=Directory Manager',
                 '-w', self.dm_password])
            nolog += (self.dm_password,)

        ipautil.run(args, nolog=nolog)
Exemple #11
0
    def configure(self, sssd, mkhomedir, statestore, sudo=True):
        # In the statestore, the following keys are used for the
        # 'authselect' module:
        # profile: name of the profile configured pre-installation
        # features_list: list of features configured pre-installation
        # mkhomedir: True if installation was called with --mkhomedir
        # profile and features_list are used when reverting to the
        # pre-install state
        cfg = self._parse_authselect_output()
        if cfg:
            statestore.backup_state('authselect', 'profile', cfg[0])
            statestore.backup_state(
                    'authselect', 'features_list', " ".join(cfg[1]))
        else:
            # cfg = None means that the current conf is not managed by
            # authselect but by authconfig.
            # As we are using authselect to configure the host,
            # it will not be possible to revert to a custom authconfig
            # configuration later (during uninstall)
            # Best thing to do will be to use sssd profile at this time
            logger.warning(
                "WARNING: The configuration pre-client installation is not "
                "managed by authselect and cannot be backed up. "
                "Uninstallation may not be able to revert to the original "
                "state.")

        cmd = [paths.AUTHSELECT, "select", "sssd"]
        if mkhomedir:
            cmd.append("with-mkhomedir")
            statestore.backup_state('authselect', 'mkhomedir', True)
        if sudo:
            cmd.append("with-sudo")
        cmd.append("--force")

        ipautil.run(cmd)
Exemple #12
0
def synconce_ntp(server_fqdn, debug=False):
    """
    Syncs time with specified server using ntpd.
    Primarily designed to be used before Kerberos setup
    to get time following the KDC time

    Returns True if sync was successful
    """
    ntpd = paths.NTPD
    if not os.path.exists(ntpd):
        return False

    # The ntpd command will never exit if it is unable to reach the
    # server, so timeout after 15 seconds.
    timeout = 15

    tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn)
    args = [paths.BIN_TIMEOUT, str(timeout), ntpd, '-qgc', tmp_ntp_conf.name]
    if debug:
        args.append('-d')
    try:
        logger.info('Attempting to sync time using ntpd.  '
                    'Will timeout after %d seconds', timeout)
        ipautil.run(args)
        return True
    except ipautil.CalledProcessError as e:
        if e.returncode == 124:
            logger.debug('Process did not complete before timeout')
        return False
Exemple #13
0
def sync_chrony():
    """
    This method enables chronyd service on boot and restarts it to reload
    chrony configuration file /etc/chrony.conf
    Then it tries to synchronize time with chrony's new or defaut configuration
    """
    # Set the chronyd to start on boot
    services.knownservices.chronyd.enable()

    # Restart chronyd
    services.knownservices.chronyd.restart()

    sync_attempt_count = 3
    # chrony attempt count to sync with configiured servers
    # each next attempt is tried after 10seconds of timeot
    # 3 attempts means: if first immidiate attempt fails
    # there is 10s delay between next attempts

    args = [paths.CHRONYC, 'waitsync', str(sync_attempt_count), '-d']

    try:
        logger.info('Attempting to sync time with chronyc.')
        ipautil.run(args)
        logger.info('Time synchronization was successful.')
        return True
    except ipautil.CalledProcessError:
        logger.warning('Process chronyc waitsync failed to sync time!')
        logger.warning(
            "Unable to sync time with chrony server, assuming the time "
            "is in sync. Please check that 123 UDP port is opened, "
            "and any time server is on network.")
        return False
Exemple #14
0
def export_key(args, tmpdir):
    """Export key and certificate from the NSS DB

    The private key is encrypted using key wrapping.
    """
    wrapped_key_file = os.path.join(tmpdir, 'wrapped_key')
    certificate_file = os.path.join(tmpdir, 'certificate')

    ipautil.run([
        paths.PKI,
        '-d', args.nssdb_path,
        '-C', args.nssdb_pwdfile,
        'ca-authority-key-export',
        '--wrap-nickname', args.wrap_nickname,
        '--target-nickname', args.nickname,
        '-o', wrapped_key_file
    ])

    nssdb = NSSDatabase(args.nssdb_path)
    nssdb.run_certutil([
        '-L',
        '-n', args.nickname,
        '-a',
        '-o', certificate_file,
    ])
    with open(wrapped_key_file, 'rb') as f:
        wrapped_key = f.read()
    with open(certificate_file, 'r') as f:
        certificate = f.read()

    data = {
        'wrapped_key': wrapped_key,
        'certificate': certificate
    }
    common.json_dump(data, args.exportfile)
Exemple #15
0
    def __create_instance(self):
        pent = pwd.getpwnam(DS_USER)

        self.backup_state("serverid", self.serverid)
        self.fstore.backup_file("/etc/sysconfig/dirsrv")

        self.sub_dict['BASEDC'] = self.realm.split('.')[0].lower()
        base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict)
        root_logger.debug(base_txt)

        target_fname = '/var/lib/dirsrv/boot.ldif'
        base_fd = open(target_fname, "w")
        base_fd.write(base_txt)
        base_fd.close()

        # Must be readable for dirsrv
        os.chmod(target_fname, 0440)
        os.chown(target_fname, pent.pw_uid, pent.pw_gid)

        inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict)
        root_logger.debug("writing inf template")
        inf_fd = ipautil.write_tmp_file(inf_txt)
        inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt)
        root_logger.debug(inf_txt)
        if ipautil.file_exists("/usr/sbin/setup-ds.pl"):
            args = ["/usr/sbin/setup-ds.pl", "--silent", "--logfile", "-", "-f", inf_fd.name]
            root_logger.debug("calling setup-ds.pl")
        else:
            args = ["/usr/bin/ds_newinst.pl", inf_fd.name]
            root_logger.debug("calling ds_newinst.pl")
        try:
            ipautil.run(args)
            root_logger.debug("completed creating ds instance")
        except ipautil.CalledProcessError, e:
            root_logger.critical("failed to create ds instance %s" % e)
Exemple #16
0
    def disable(self, instance_name=""):
        elements = self.systemd_name.split("@")
        if instance_name != "" and len(elements) > 1:
            # Remove instance, we need to do following:
            # Remove link from /etc/systemd/system/<service>.target.wants/
            # <service>@<instance_name>.service
            # to /lib/systemd/system/<service>@.service

            srv_tgt = os.path.join(paths.ETC_SYSTEMD_SYSTEM_DIR,
                                   self.SYSTEMD_SRV_TARGET % (elements[0]))
            srv_lnk = os.path.join(srv_tgt,
                                   self.service_instance(instance_name))

            try:
                if ipautil.dir_exists(srv_tgt):
                    if os.path.islink(srv_lnk):
                        os.unlink(srv_lnk)
                ipautil.run([paths.SYSTEMCTL, "--system", "daemon-reload"])
            except Exception:
                pass
        else:
            try:
                ipautil.run([paths.SYSTEMCTL, "disable",
                             self.service_instance(instance_name)])
            except ipautil.CalledProcessError:
                pass
Exemple #17
0
    def kinit(self, user, realm, password, ccache_name):
        # get http service ccache as an armor for FAST to enable OTP authentication
        armor_principal = str(krb5_format_service_principal_name(
            'HTTP', self.api.env.host, realm))
        keytab = paths.IPA_KEYTAB
        armor_name = "%sA_%s" % (krbccache_prefix, user)
        armor_path = os.path.join(krbccache_dir, armor_name)

        self.debug('Obtaining armor ccache: principal=%s keytab=%s ccache=%s',
                   armor_principal, keytab, armor_path)

        try:
            ipautil.kinit_keytab(armor_principal, paths.IPA_KEYTAB, armor_path)
        except gssapi.exceptions.GSSError as e:
            raise CCacheError(str(e))

        # Format the user as a kerberos principal
        principal = krb5_format_principal_name(user, realm)

        try:
            ipautil.kinit_password(principal, password, ccache_name,
                                   armor_ccache_name=armor_path)

            self.debug('Cleanup the armor ccache')
            ipautil.run(
                [paths.KDESTROY, '-A', '-c', armor_path],
                env={'KRB5CCNAME': armor_path},
                raiseonerr=False)
        except RuntimeError as e:
            if ('kinit: Cannot read password while '
                    'getting initial credentials') in str(e):
                raise PasswordExpired(principal=principal, message=unicode(e))
            raise InvalidSessionPassword(principal=principal,
                                         message=unicode(e))
Exemple #18
0
def map_Guests_to_nobody():
    env = {'LC_ALL': 'C'}
    args = [paths.NET, '-s', '/dev/null', 'groupmap', 'add',
            'sid=S-1-5-32-546', 'unixgroup=nobody', 'type=builtin']

    logger.debug("Map BUILTIN\\Guests to a group 'nobody'")
    ipautil.run(args, env=env, raiseonerr=False, capture_error=True)
Exemple #19
0
 def reload_systemwide_ca_store(self):
     try:
         ipautil.run([paths.UPDATE_CA_TRUST])
     except CalledProcessError, e:
         root_logger.error(
             "Could not update systemwide CA trust database: %s", e)
         return False
Exemple #20
0
 def remove_httpd_ccache(self):
     # Clean up existing ccache
     # Make sure that empty env is passed to avoid passing KRB5CCNAME from
     # current env
     ipautil.run(
         [paths.KDESTROY, '-A'], runas=self.service_user, raiseonerr=False,
         env={})
Exemple #21
0
    def import_key(self, value):
        v = json_decode(value)
        data = b64decode(v['pkcs12 data'])
        password = v['export password']
        try:
            _fd, tmpdata = tempfile.mkstemp(dir=paths.TMP)
            with open(tmpdata, 'w') as f:
                f.write(data)

            # get the certificate from the file
            ipautil.run([paths.OPENSSL,
                         "pkcs12",
                         "-in", tmpdata,
                         "-clcerts", "-nokeys",
                         "-out", self.certfile,
                         "-passin", "pass:{pwd}".format(pwd=password)],
                        nolog=(password, ))

            if self.keyfile is not None:
                # get the private key from the file
                ipautil.run([paths.OPENSSL,
                             "pkcs12",
                             "-in", tmpdata,
                             "-nocerts", "-nodes",
                             "-out", self.keyfile,
                             "-passin", "pass:{pwd}".format(pwd=password)],
                            nolog=(password, ))
        finally:
            os.remove(tmpdata)
Exemple #22
0
 def hsm_replica_sync(self):
     """Download keys from LDAP to local HSM."""
     if self.ismaster:
         return
     if not self.init_done:
         return
     ipautil.run([paths.IPA_DNSKEYSYNCD_REPLICA])
Exemple #23
0
    def setup_firefox_extension(self, realm, domain):
        """Set up the signed browser configuration extension
        """

        target_fname = paths.KRB_JS
        sub_dict = dict(REALM=realm, DOMAIN=domain)
        db = certs.CertDB(realm)
        with open(db.passwd_fname) as pwdfile:
            pwd = pwdfile.read()

        ipautil.copy_template_file(ipautil.SHARE_DIR + "krb.js.template",
            target_fname, sub_dict)
        os.chmod(target_fname, 0o644)

        # Setup extension
        tmpdir = tempfile.mkdtemp(prefix="tmp-")
        extdir = tmpdir + "/ext"
        target_fname = paths.KERBEROSAUTH_XPI
        shutil.copytree(paths.FFEXTENSION, extdir)
        if db.has_nickname('Signing-Cert'):
            db.run_signtool(["-k", "Signing-Cert",
                                "-p", pwd,
                                "-X", "-Z", target_fname,
                                extdir])
        else:
            root_logger.warning('Object-signing certificate was not found. '
                'Creating unsigned Firefox configuration extension.')
            filenames = os.listdir(extdir)
            ipautil.run([paths.ZIP, '-r', target_fname] + filenames,
                cwd=extdir)
        shutil.rmtree(tmpdir)
        os.chmod(target_fname, 0o644)
Exemple #24
0
    def __create_instance(self):
        pent = pwd.getpwnam(DS_USER)

        self.backup_state("serverid", self.serverid)
        self.fstore.backup_file(paths.SYSCONFIG_DIRSRV)

        self.sub_dict['BASEDC'] = self.realm.split('.')[0].lower()
        base_txt = ipautil.template_str(BASE_TEMPLATE, self.sub_dict)
        root_logger.debug(base_txt)

        target_fname = paths.DIRSRV_BOOT_LDIF
        base_fd = open(target_fname, "w")
        base_fd.write(base_txt)
        base_fd.close()

        # Must be readable for dirsrv
        os.chmod(target_fname, 0440)
        os.chown(target_fname, pent.pw_uid, pent.pw_gid)

        inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict)
        root_logger.debug("writing inf template")
        inf_fd = ipautil.write_tmp_file(inf_txt)
        inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt)
        root_logger.debug(inf_txt)
        if ipautil.file_exists(paths.SETUP_DS_PL):
            args = [paths.SETUP_DS_PL, "--silent", "--logfile", "-", "-f", inf_fd.name]
            root_logger.debug("calling setup-ds.pl")
        else:
            args = [paths.DS_NEWINST_PL, inf_fd.name]
            root_logger.debug("calling ds_newinst.pl")
        try:
            ipautil.run(args)
            root_logger.debug("completed creating ds instance")
        except ipautil.CalledProcessError, e:
            root_logger.critical("failed to create ds instance %s" % e)
Exemple #25
0
 def export_key(self):
     tdir = tempfile.mkdtemp(dir=paths.TMP)
     try:
         nsspwfile = os.path.join(tdir, 'nsspwfile')
         with open(nsspwfile, 'w+') as f:
             f.write(self.nssdb_password)
         wrapped_key_file = os.path.join(tdir, 'wrapped_key')
         certificate_file = os.path.join(tdir, 'certificate')
         ipautil.run([
             paths.PKI, '-d', self.nssdb_path, '-C', nsspwfile,
             'ca-authority-key-export',
             '--wrap-nickname', self.wrap_nick,
             '--target-nickname', self.target_nick,
             '-o', wrapped_key_file])
         ipautil.run([
             paths.CERTUTIL, '-d', self.nssdb_path,
             '-L', '-n', self.target_nick,
             '-a', '-o', certificate_file])
         with open(wrapped_key_file, 'r') as f:
             wrapped_key = f.read()
         with open(certificate_file, 'r') as f:
             certificate = f.read()
     finally:
         shutil.rmtree(tdir)
     return json_encode({
         'wrapped_key': b64encode(wrapped_key),
         'certificate': certificate})
Exemple #26
0
def verify_kdc_cert_validity(kdc_cert, ca_certs, realm):
    with NamedTemporaryFile() as kdc_file, NamedTemporaryFile() as ca_file:
        kdc_file.write(kdc_cert.public_bytes(x509.Encoding.PEM))
        kdc_file.flush()
        x509.write_certificate_list(ca_certs, ca_file.name)
        ca_file.flush()

        try:
            ipautil.run(
                [paths.OPENSSL, 'verify', '-CAfile', ca_file.name,
                 kdc_file.name],
                capture_output=True)
        except ipautil.CalledProcessError as e:
            raise ValueError(e.output)

        try:
            eku = kdc_cert.extensions.get_extension_for_class(
                cryptography.x509.ExtendedKeyUsage)
            list(eku.value).index(
                cryptography.x509.ObjectIdentifier(x509.EKU_PKINIT_KDC))
        except (cryptography.x509.ExtensionNotFound,
                ValueError):
            raise ValueError("invalid for a KDC")

        principal = str(Principal(['krbtgt', realm], realm))
        gns = x509.process_othernames(kdc_cert.san_general_names)
        for gn in gns:
            if isinstance(gn, x509.KRB5PrincipalName) and gn.name == principal:
                break
        else:
            raise ValueError("invalid for realm %s" % realm)
Exemple #27
0
 def export_key(self):
     tdir = tempfile.mkdtemp(dir=paths.TMP)
     try:
         wrapped_key_file = os.path.join(tdir, 'wrapped_key')
         certificate_file = os.path.join(tdir, 'certificate')
         ipautil.run([
             paths.PKI, '-d', self.nssdb_path, '-C', self.nssdb_pwdfile,
             'ca-authority-key-export',
             '--wrap-nickname', self.wrap_nick,
             '--target-nickname', self.target_nick,
             '-o', wrapped_key_file])
         nssdb = NSSDatabase(self.nssdb_path)
         nssdb.run_certutil([
             '-L', '-n', self.target_nick,
             '-a', '-o', certificate_file,
         ])
         with open(wrapped_key_file, 'rb') as f:
             wrapped_key = f.read()
         with open(certificate_file, 'r') as f:
             certificate = f.read()
     finally:
         shutil.rmtree(tdir)
     return json_encode({
         'wrapped_key': b64encode(wrapped_key).decode('ascii'),
         'certificate': certificate})
Exemple #28
0
    def spawn_instance(self, cfg_file, nolog_list=None):
        """
        Create and configure a new Dogtag instance using pkispawn.
        Passes in a configuration file with IPA-specific
        parameters.
        """
        subsystem = self.subsystem

        # Define the things we don't want logged
        if nolog_list is None:
            nolog_list = []
        nolog = tuple(nolog_list) + (self.admin_password, self.dm_password)

        args = [paths.PKISPAWN,
                "-s", subsystem,
                "-f", cfg_file]

        with open(cfg_file) as f:
            self.log.debug(
                'Contents of pkispawn configuration file (%s):\n%s',
                cfg_file, ipautil.nolog_replace(f.read(), nolog))

        try:
            ipautil.run(args, nolog=nolog)
        except ipautil.CalledProcessError as e:
            self.handle_setup_error(e)
Exemple #29
0
    def run_getkeytab(self, ldap_uri, keytab, principal, retrieve=False):
        """
        retrieve service keytab using ipa-getkeytab. This assumes that the
        service principal is already created in LDAP. By default GSSAPI
        authentication is used unless:
            * LDAPI socket is used and effective process UID is 0, then
              autobind is used by EXTERNAL SASL mech
            * self.dm_password is not none, then DM credentials are used to
              fetch keytab
        """
        args = [paths.IPA_GETKEYTAB,
                '-k', keytab,
                '-p', principal,
                '-H', ldap_uri]
        nolog = tuple()

        if ldap_uri.startswith("ldapi://") and os.geteuid() == 0:
            args.extend(["-Y", "EXTERNAL"])
        elif self.dm_password is not None and not self.promote:
            args.extend(
                ['-D', 'cn=Directory Manager',
                 '-w', self.dm_password])
            nolog += (self.dm_password,)

        if retrieve:
            args.extend(['-r'])

        ipautil.run(args, nolog=nolog)
Exemple #30
0
    def tune_nofile_platform(self, num=8192, fstore=None):
        """
        Increase the number of files descriptors available to directory server
        from the default 1024 to 8192. This will allow to support a greater
        number of clients out of the box.

        This is a part of the implementation that is systemd-specific.

        Returns False if the setting of the nofile limit needs to be skipped.
        """

        if os.path.exists(paths.SYSCONFIG_DIRSRV_SYSTEMD):
            # We need to enable LimitNOFILE=8192 in the [email protected]
            # Since 389-ds-base-1.2.10-0.8.a7 the configuration of the
            # service parameters is performed via
            # /etc/sysconfig/dirsrv.systemd file which is imported by systemd
            # into [email protected] unit

            replacevars = {'LimitNOFILE': str(num)}
            ipautil.inifile_replace_variables(paths.SYSCONFIG_DIRSRV_SYSTEMD,
                                              'service',
                                              replacevars=replacevars)
            tasks.restore_context(paths.SYSCONFIG_DIRSRV_SYSTEMD)
            ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],
                        raiseonerr=False)

        return True
Exemple #31
0
def kinit_password(principal,
                   password,
                   ccache_name,
                   config=None,
                   armor_ccache_name=None,
                   canonicalize=False,
                   enterprise=False):
    """
    perform interactive kinit as principal using password. If using FAST for
    web-based authentication, use armor_ccache_path to specify http service
    ccache.
    """
    root_logger.debug("Initializing principal %s using password" % principal)
    args = [paths.KINIT, principal, '-c', ccache_name]
    if armor_ccache_name is not None:
        root_logger.debug("Using armor ccache %s for FAST webauth" %
                          armor_ccache_name)
        args.extend(['-T', armor_ccache_name])

    if canonicalize:
        root_logger.debug("Requesting principal canonicalization")
        args.append('-C')

    if enterprise:
        root_logger.debug("Using enterprise principal")
        args.append('-E')

    env = {'LC_ALL': 'C'}
    if config is not None:
        env['KRB5_CONFIG'] = config

    # this workaround enables us to capture stderr and put it
    # into the raised exception in case of unsuccessful authentication
    result = run(args,
                 stdin=password,
                 env=env,
                 raiseonerr=False,
                 capture_error=True)
    if result.returncode:
        raise RuntimeError(result.error_output)
Exemple #32
0
    def db2bak(self, instance, online=True):
        '''
        Create a BAK backup of the data and changelog in this instance.

        If executed online create a task and wait for it to complete.
        '''
        logger.info('Backing up %s', instance)
        cn = time.strftime('backup_%Y_%m_%d_%H_%M_%S')
        dn = DN(('cn', cn), ('cn', 'backup'), ('cn', 'tasks'),
                ('cn', 'config'))

        bakdir = os.path.join(paths.SLAPD_INSTANCE_BACKUP_DIR_TEMPLATE %
                              (instance, instance))

        if online:
            conn = self.get_connection()
            ent = conn.make_entry(
                dn, {
                    'objectClass': ['top', 'extensibleObject'],
                    'cn': [cn],
                    'nsInstance': ['userRoot'],
                    'nsArchiveDir': [bakdir],
                    'nsDatabaseType': ['ldbm database'],
                })

            try:
                conn.add_entry(ent)
            except Exception as e:
                raise admintool.ScriptError(
                    'Unable to to add backup task: %s' % e)

            logger.info("Waiting for BAK to finish")
            wait_for_task(conn, dn)
        else:
            args = [paths.DB2BAK, bakdir, '-Z', instance]
            result = run(args, raiseonerr=False)
            if result.returncode != 0:
                logger.critical('db2bak failed: %s', result.error_log)

        shutil.move(bakdir, self.dir)
Exemple #33
0
    def is_running(self, instance_name="", wait=True):
        instance = self.service_instance(instance_name, 'is-active')

        while True:
            try:
                result = ipautil.run([paths.SYSTEMCTL, "is-active", instance],
                                     capture_output=True)
            except ipautil.CalledProcessError as e:
                if e.returncode == 3 and 'activating' in str(e.output):
                    time.sleep(SERVICE_POLL_INTERVAL)
                    continue
                return False
            else:
                # activating
                if result.returncode == 3 and 'activating' in result.output:
                    time.sleep(SERVICE_POLL_INTERVAL)
                    continue
                # active
                if result.returncode == 0:
                    return True
                # not active
                return False
Exemple #34
0
def decrypt_file(tmpdir, filename):
    source = filename
    (dest, ext) = os.path.splitext(filename)

    if ext != '.gpg':
        raise admintool.ScriptError('Trying to decrypt a non-gpg file')

    dest = os.path.basename(dest)
    dest = os.path.join(tmpdir, dest)

    args = [
        paths.GPG2,
        '--batch',
        '--output', dest,
        '--decrypt', source,
    ]

    result = run(args, raiseonerr=False)
    if result.returncode != 0:
        raise admintool.ScriptError('gpg failed: %s' % result.error_log)

    return dest
Exemple #35
0
def encrypt_file(filename, remove_original=True):
    source = filename
    dest = filename + '.gpg'

    args = [
        paths.GPG2,
        '--batch',
        '--default-recipient-self',
        '--output',
        dest,
        '--encrypt',
        source,
    ]

    result = run(args, raiseonerr=False)
    if result.returncode != 0:
        raise admintool.ScriptError('gpg failed: %s' % result.error_log)

    if remove_original:
        os.unlink(source)

    return dest
Exemple #36
0
    def restore_default_conf(self):
        '''
        Restore paths.IPA_DEFAULT_CONF to temporary directory.

        Primary purpose of this method is to get cofiguration for api
        finalization when restoring ipa after uninstall.
        '''
        cwd = os.getcwd()
        os.chdir(self.dir)
        args = ['tar',
                '--xattrs',
                '--selinux',
                '-xzf',
                os.path.join(self.dir, 'files.tar'),
                paths.IPA_DEFAULT_CONF[1:],
               ]

        result = run(args, raiseonerr=False)
        if result.returncode != 0:
            logger.critical('Restoring %s failed: %s',
                            paths.IPA_DEFAULT_CONF, result.error_log)
        os.chdir(cwd)
Exemple #37
0
def check_inst():
    """
    We now allow mod_ssl to be installed so don't automatically disable it.
    However it can't share the same listen port as mod_nss, so check for that.

    Returns True if something other than mod_nss is listening on 443.
    False otherwise.
    """
    (stdout, stderr,
     rc) = ipautil.run(['/usr/sbin/httpd', '-t', '-D', 'DUMP_VHOSTS'],
                       raiseonerr=False)
    if rc == 0:
        lines = stdout.split('\n')
        for line in lines:
            if ':443 ' in line:
                if not 'nss.conf' in line:
                    print "Apache is already configured with a listener on port 443:"
                    print line
                    print "IPA requires that mod_nss be used for port 443."
                    return True

    return False
Exemple #38
0
    def run_ods_manager(self, params, **kwargs):
        """Run OpenDNSSEC manager command (ksmutil, enforcer)

        :param params: parameter for ODS command
        :param kwargs: additional arguments for ipautil.run()
        :return: result from ipautil.run()
        """
        assert params[0] != 'setup'

        if paths.ODS_KSMUTIL is not None:
            # OpenDNSSEC 1.4
            cmd = [paths.ODS_KSMUTIL]
        else:
            # OpenDNSSEC 2.x
            cmd = [paths.ODS_ENFORCER]
        cmd.extend(params)

        # run commands as ODS user
        if os.geteuid() == 0:
            kwargs['runas'] = constants.ODS_USER

        return ipautil.run(cmd, **kwargs)
Exemple #39
0
    def run_handler(self, extra_args=(), stdin=None):
        """Run handler script to export / import key material
        """
        args = [self.command]
        args.extend(extra_args)
        kwargs = dict(
            runas=self.runas,
            encoding='utf-8',
        )

        if stdin:
            args.extend(['--import', '-'])
            kwargs.update(stdin=stdin)
        else:
            args.extend(['--export', '-'])
            kwargs.update(capture_output=True)

        result = ipautil.run(args, **kwargs)

        if stdin is None:
            return result.output
        else:
            return None
Exemple #40
0
    def file_restore(self, nologs=False):
        '''
        Restore all the files in the tarball.

        This MUST be done offline because we directly backup the 389-ds
        databases.
        '''
        logger.info("Restoring files")
        cwd = os.getcwd()
        os.chdir('/')
        args = [
            'tar', '--xattrs', '--selinux', '-xzf',
            os.path.join(self.dir, 'files.tar')
        ]
        if nologs:
            args.append('--exclude')
            args.append('var/log')

        result = run(args, raiseonerr=False)
        if result.returncode != 0:
            logger.critical('Restoring files failed: %s', result.error_log)

        os.chdir(cwd)
Exemple #41
0
    def file_restore(self, nologs=False):
        '''
        Restore all the files in the tarball.

        This MUST be done offline because we directly backup the 389-ds
        databases.
        '''
        self.log.info("Restoring files")
        cwd = os.getcwd()
        os.chdir('/')
        args = [
            'tar', '--xattrs', '--selinux', '-xzf',
            os.path.join(self.dir, 'files.tar')
        ]
        if nologs:
            args.append('--exclude')
            args.append('var/log')

        (stdout, stderr, rc) = run(args, raiseonerr=False)
        if rc != 0:
            self.log.critical('Restoring files failed: %s', stderr)

        os.chdir(cwd)
Exemple #42
0
    def check(self):

        rval = constants.SUCCESS
        if not os.path.exists(paths.FIPS_MODE_SETUP):
            fips = "missing {}".format(paths.FIPS_MODE_SETUP)
            logger.debug('%s is not installed, skipping',
                         paths.FIPS_MODE_SETUP)
        else:
            try:
                result = ipautil.run(
                    [paths.FIPS_MODE_SETUP, '--is-enabled'],
                    capture_output=True,
                    raiseonerr=False,
                )
            except Exception as e:
                logger.debug('fips-mode-setup failed: %s', e)
                fips = "failed to check"
                rval = constants.ERROR
            else:
                logger.debug(result.raw_output.decode('utf-8'))
                if result.returncode == 0:
                    fips = "enabled"
                elif result.returncode == 1:
                    fips = "inconsistent"
                elif result.returncode == 2:
                    fips = "disabled"
                else:
                    fips = "unknown"

        yield Result(
            self,
            rval,
            fqdn=socket.getfqdn(),
            fips=fips,
            ipa_version=VERSION,
            ipa_api_version=API_VERSION,
        )
Exemple #43
0
def stop_tracking(secdir, request_id=None, nickname=None):
    """
    Stop tracking the current request using either the request_id or nickname.

    This assumes that the certmonger service is running.
    """
    if request_id is None and nickname is None:
        raise RuntimeError('Both request_id and nickname are missing.')
    if nickname:
        # Using the nickname find the certmonger request_id
        criteria = (('cert_storage_location', os.path.abspath(secdir), NPATH),
                    ('cert_nickname', nickname, None))
        try:
            request_id = get_request_id(criteria)
            if request_id is None:
                return ('', '', 0)
        except RuntimeError:
            # This means that multiple requests matched, skip it for now
            # Fall back to trying to stop tracking using nickname
            pass

    args = [
        '/usr/bin/getcert',
        'stop-tracking',
    ]
    if request_id:
        args.append('-i')
        args.append(request_id)
    else:
        args.append('-n')
        args.append(nickname)
        args.append('-d')
        args.append(os.path.abspath(secdir))

    (stdout, stderr, returncode) = ipautil.run(args)

    return (stdout, stderr, returncode)
Exemple #44
0
    def wait_until_running(self):
        root_logger.debug('Waiting until the CA is running')
        timeout = float(api.env.startup_timeout)
        op_timeout = time.time() + timeout
        while time.time() < op_timeout:
            try:
                # FIXME https://fedorahosted.org/freeipa/ticket/4716
                # workaround
                #
                # status = dogtag.ca_status(use_proxy=use_proxy)
                #
                port = 8443

                url = "https://%(host_port)s%(path)s" % {
                    "host_port": ipautil.format_netloc(api.env.ca_host, port),
                    "path": "/ca/admin/ca/getStatus"
                }

                args = [
                    paths.BIN_CURL, '-o', '-', '--connect-timeout', '30', '-k',
                    url
                ]

                result = ipautil.run(args, capture_output=True)

                status = dogtag._parse_ca_status(result.output)
                # end of workaround
            except Exception as e:
                status = 'check interrupted due to error: %s' % e
            root_logger.debug('The CA status is: %s' % status)
            if status == 'running':
                break
            root_logger.debug('Waiting for CA to start...')
            time.sleep(1)
        else:
            raise RuntimeError('CA did not start in %ss' % timeout)
Exemple #45
0
def request_cert(nssdb, nickname, subject, principal, passwd_fname=None):
    """
    Execute certmonger to request a server certificate
    """
    args = [
        '/usr/bin/ipa-getcert',
        'request',
        '-d',
        nssdb,
        '-n',
        nickname,
        '-N',
        subject,
        '-K',
        principal,
    ]
    if passwd_fname:
        args.append('-p')
        args.append(os.path.abspath(passwd_fname))
    (stdout, stderr, returncode) = ipautil.run(args)
    # FIXME: should be some error handling around this
    m = re.match('New signing request "(\d+)" added', stdout)
    request_id = m.group(1)
    return request_id
Exemple #46
0
def encrypt_file(filename, keyring, remove_original=True):
    source = filename
    dest = filename + '.gpg'

    args = [paths.GPG, '--batch', '--default-recipient-self', '-o', dest]

    if keyring is not None:
        args.append('--no-default-keyring')
        args.append('--keyring')
        args.append(keyring + '.pub')
        args.append('--secret-keyring')
        args.append(keyring + '.sec')

    args.append('-e')
    args.append(source)

    result = run(args, raiseonerr=False)
    if result.returncode != 0:
        raise admintool.ScriptError('gpg failed: %s' % result.error_log)

    if remove_original:
        os.unlink(source)

    return dest
Exemple #47
0
    def copy_key(self, keytab, keyentry):
        # keyentry.key is a hex value of the actual key
        # prefixed with 0x, as produced by klist -K -k.
        # However, ktutil accepts hex value without 0x, so
        # we should strip first two characters.
        stdin = dedent("""\
        rkt {keytab}
        addent -key -p {principal} -k {kvno} -e {etype}
        {key}
        wkt {keytab}
        """).format(keytab=keytab,
                    principal=keyentry.principal,
                    kvno=keyentry.kvno,
                    etype=keyentry.etype,
                    key=keyentry.key[2:])

        result = ipautil.run([paths.KTUTIL],
                             stdin=stdin,
                             raiseonerr=False,
                             umask=0o077,
                             nolog_output=True)

        if result.returncode != 0:
            logger.warning('Unable to update %s with new keys', keytab)
Exemple #48
0
def install_pem_from_p12(p12_fname, p12_passwd, pem_fname):
    pwd = ipautil.write_tmp_file(p12_passwd)
    ipautil.run([
        paths.OPENSSL, "pkcs12", "-nokeys", "-clcerts", "-in", p12_fname,
        "-out", pem_fname, "-passin", "file:" + pwd.name
    ])
Exemple #49
0
def export_pem_p12(pkcs12_fname, pkcs12_pwd_fname, nickname, pem_fname):
    ipautil.run([
        paths.OPENSSL, "pkcs12", "-export", "-name", nickname, "-in",
        pem_fname, "-out", pkcs12_fname, "-passout", "file:" + pkcs12_pwd_fname
    ])
Exemple #50
0
def install(installer):
    options = installer
    fstore = installer._fstore
    sstore = installer._sstore
    dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
    http_pkcs12_info = installer._http_pkcs12_info
    pkinit_pkcs12_info = installer._pkinit_pkcs12_info
    http_ca_cert = installer._ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_addresses
    setup_ca = options.setup_ca

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installer._installation_cleanup = False

    if installer.interactive:
        print("")
        print("The following operations may take some minutes to complete.")
        print("Please wait until the prompt is returned.")
        print("")

    # set hostname (transient and static) if user instructed us to do so
    if options._host_name_overridden:
        tasks.backup_hostname(fstore, sstore)
        tasks.set_hostname(host_name)

    if installer._update_hosts_file:
        update_hosts_file(ip_addresses, host_name, fstore)

    # Make sure tmpfiles dir exist before installing components
    tasks.create_tmpfiles_dirs()

    # Create a directory server instance
    if not options.external_cert_files:
        # Configure ntpd
        if not options.no_ntp:
            ipaclient.install.ntpconf.force_ntpd(sstore)
            ntp = ntpinstance.NTPInstance(fstore)
            if not ntp.is_configured():
                ntp.create_instance()

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name,
                               host_name,
                               domain_name,
                               dm_password,
                               dirsrv_pkcs12_info,
                               idstart=options.idstart,
                               idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name,
                               host_name,
                               domain_name,
                               dm_password,
                               idstart=options.idstart,
                               idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow)

        ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name)

    else:
        api.Backend.ldap2.connect()
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        installer._ds = ds
        ds.init_info(realm_name, host_name, domain_name, dm_password,
                     options.subject_base, options.ca_subject, 1101, 1100,
                     None)

    krb = krbinstance.KrbInstance(fstore)
    krb.create_instance(realm_name,
                        host_name,
                        domain_name,
                        dm_password,
                        master_password,
                        setup_pkinit=not options.no_pkinit,
                        pkcs12_info=pkinit_pkcs12_info,
                        subject_base=options.subject_base)

    if setup_ca:
        if not options.external_cert_files and options.external_ca:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.reverse_zones = dns.reverse_zones
            cache_vars = {
                n: options.__dict__[n]
                for o, n in installer.knobs() if n in options.__dict__
            }
            write_cache(cache_vars)

        ca.install_step_0(False, None, options)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
        os.chmod(paths.IPA_CA_CRT, 0o444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    if setup_ca:
        ca.install_step_1(False, None, options)

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name,
                         ipautil.realm_to_suffix(realm_name))

    custodia = custodiainstance.CustodiaInstance(host_name, realm_name)
    custodia.create_instance()

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(realm_name,
                             host_name,
                             domain_name,
                             pkcs12_info=http_pkcs12_info,
                             subject_base=options.subject_base,
                             auto_redirect=not options.no_ui_redirect,
                             ca_is_configured=setup_ca)
    else:
        http.create_instance(realm_name,
                             host_name,
                             domain_name,
                             subject_base=options.subject_base,
                             auto_redirect=not options.no_ui_redirect,
                             ca_is_configured=setup_ca)
    tasks.restore_context(paths.CACHE_IPA_SESSIONS)

    ca.set_subject_base_in_config(options.subject_base)

    # configure PKINIT now that all required services are in place
    krb.enable_ssl()

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created. DS is restarted in the process.
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart krb after configurations have been changed
    service.print_msg("Restarting the KDC")
    krb.restart()

    if options.setup_kra:
        kra.install(api, None, options)

    if options.setup_dns:
        dns.install(False, False, options)
    else:
        # Create a BIND instance
        bind = bindinstance.BindInstance(fstore)
        bind.setup(host_name,
                   ip_addresses,
                   realm_name,
                   domain_name, (),
                   'first', (),
                   zonemgr=options.zonemgr,
                   no_dnssec_validation=options.no_dnssec_validation)
        bind.create_file_with_system_records()

    if options.setup_adtrust:
        adtrust.install(False, options, fstore, api)

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    service.print_msg("Configuring client side components")
    try:
        args = [
            paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
            "--domain", domain_name, "--server", host_name, "--realm",
            realm_name, "--hostname", host_name
        ]
        if options.no_dns_sshfp:
            args.append("--no-dns-sshfp")
        if options.ssh_trust_dns:
            args.append("--ssh-trust-dns")
        if options.no_ssh:
            args.append("--no-ssh")
        if options.no_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        run(args, redirect_output=True)
        print()
    except Exception:
        raise ScriptError("Configuration of client side components failed!")

    # Make sure the files we crated in /var/run are recreated at startup
    tasks.configure_tmpfiles()

    # Everything installed properly, activate ipa service.
    services.knownservices.ipa.enable()

    print("======================================="
          "=======================================")
    print("Setup complete")
    print("")
    print("Next steps:")
    print("\t1. You must make sure these network ports are open:")
    print("\t\tTCP Ports:")
    print("\t\t  * 80, 443: HTTP/HTTPS")
    print("\t\t  * 389, 636: LDAP/LDAPS")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    print("\t\tUDP Ports:")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    if not options.no_ntp:
        print("\t\t  * 123: ntp")
    print("")
    print("\t2. You can now obtain a kerberos ticket using the command: "
          "'kinit admin'")
    print("\t   This ticket will allow you to use the IPA tools (e.g., ipa "
          "user-add)")
    print("\t   and the web user interface.")

    if not services.knownservices.ntpd.is_running():
        print("\t3. Kerberos requires time synchronization between clients")
        print("\t   and servers for correct operation. You should consider "
              "enabling ntpd.")

    print("")
    if setup_ca:
        print(("Be sure to back up the CA certificates stored in " +
               paths.CACERT_P12))
        print("These files are required to create replicas. The password for "
              "these")
        print("files is the Directory Manager password")
    else:
        print(
            "In order for Firefox autoconfiguration to work you will need to")
        print("use a SSL signing certificate. See the IPA documentation for "
              "more details.")

    if ipautil.file_exists(paths.ROOT_IPA_CACHE):
        os.remove(paths.ROOT_IPA_CACHE)
Exemple #51
0
    def ldif2db(self, instance, backend, online=True):
        '''
        Restore a LDIF backup of the data in this instance.

        If executed online create a task and wait for it to complete.
        '''
        logger.info('Restoring from %s in %s', backend, instance)

        cn = time.strftime('import_%Y_%m_%d_%H_%M_%S')
        dn = DN(('cn', cn), ('cn', 'import'), ('cn', 'tasks'), ('cn', 'config'))

        ldifdir = paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance
        ldifname = '%s-%s.ldif' % (instance, backend)
        ldiffile = os.path.join(ldifdir, ldifname)
        srcldiffile = os.path.join(self.dir, ldifname)

        if not os.path.exists(ldifdir):
            pent = pwd.getpwnam(constants.DS_USER)
            os.mkdir(ldifdir)
            os.chmod(ldifdir, 0o770)
            os.chown(ldifdir, pent.pw_uid, pent.pw_gid)

        ipautil.backup_file(ldiffile)
        with open(ldiffile, 'w') as out_file:
            ldif_writer = ldif.LDIFWriter(out_file)
            with open(srcldiffile, 'rb') as in_file:
                ldif_parser = RemoveRUVParser(in_file, ldif_writer)
                ldif_parser.parse()

        # Make sure the modified ldiffile is owned by DS_USER
        pent = pwd.getpwnam(constants.DS_USER)
        os.chown(ldiffile, pent.pw_uid, pent.pw_gid)

        if online:
            conn = self.get_connection()
            ent = conn.make_entry(
                dn,
                {
                    'objectClass': ['top', 'extensibleObject'],
                    'cn': [cn],
                    'nsFilename': [ldiffile],
                    'nsUseOneFile': ['true'],
                }
            )
            ent['nsInstance'] = [backend]

            try:
                conn.add_entry(ent)
            except Exception as e:
                logger.error("Unable to bind to LDAP server: %s", e)
                return

            logger.info("Waiting for LDIF to finish")
            wait_for_task(conn, dn)
        else:
            try:
                os.makedirs(paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance)
            except OSError as e:
                pass

            args = [paths.LDIF2DB,
                    '-Z', instance,
                    '-i', ldiffile,
                    '-n', backend]
            result = run(args, raiseonerr=False)
            if result.returncode != 0:
                logger.critical("ldif2db failed: %s", result.error_log)
Exemple #52
0
 def run_pk12util(self, args, stdin=None, **kwargs):
     new_args = [
         paths.PK12UTIL, "-d", '{}:{}'.format(self.dbtype, self.secdir)
     ]
     new_args.extend(args)
     return ipautil.run(new_args, stdin, **kwargs)
Exemple #53
0
def uninstall(installer):
    fstore = installer._fstore
    sstore = installer._sstore

    rv = 0

    # further steps assumes that temporary directories exists so rather
    # ensure they are created
    tasks.create_tmpfiles_dirs()

    print("Shutting down all IPA services")
    try:
        services.knownservices.ipa.stop()
    except Exception:
        # Fallback to direct ipactl stop only if system command fails
        try:
            run([paths.IPACTL, "stop"], raiseonerr=False)
        except Exception:
            pass

    ntpinstance.NTPInstance(fstore).uninstall()

    kra.uninstall()

    ca.uninstall()

    dns.uninstall()

    httpinstance.HTTPInstance(fstore).uninstall()
    krbinstance.KrbInstance(fstore).uninstall()
    dsinstance.DsInstance(fstore=fstore).uninstall()
    if _server_trust_ad_installed:
        adtrustinstance.ADTRUSTInstance(fstore).uninstall()
    custodiainstance.CustodiaInstance().uninstall()
    otpdinstance.OtpdInstance().uninstall()
    tasks.restore_hostname(fstore, sstore)
    fstore.restore_all_files()
    try:
        os.remove(paths.ROOT_IPA_CACHE)
    except Exception:
        pass
    try:
        os.remove(paths.ROOT_IPA_CSR)
    except Exception:
        pass

    # ipa-client-install removes /etc/ipa/default.conf

    sstore._load()

    ipaclient.install.ntpconf.restore_forced_ntpd(sstore)

    # Clean up group_exists (unused since IPA 2.2, not being set since 4.1)
    sstore.restore_state("install", "group_exists")

    services.knownservices.ipa.disable()

    # remove upgrade state file
    sysupgrade.remove_upgrade_file()

    if fstore.has_files():
        root_logger.error('Some files have not been restored, see '
                          '%s/sysrestore.index' % SYSRESTORE_DIR_PATH)
    has_state = False
    for module in IPA_MODULES:  # from installutils
        if sstore.has_state(module):
            root_logger.error('Some installation state for %s has not been '
                              'restored, see %s/sysrestore.state' %
                              (module, SYSRESTORE_DIR_PATH))
            has_state = True
            rv = 1

    if has_state:
        root_logger.error('Some installation state has not been restored.\n'
                          'This may cause re-installation to fail.\n'
                          'It should be safe to remove %s/sysrestore.state '
                          'but it may\n'
                          'mean your system hasn\'t be restored to its '
                          'pre-installation state.' % SYSRESTORE_DIR_PATH)

    # Note that this name will be wrong after the first uninstall.
    dirname = dsinstance.config_dirname(
        installutils.realm_to_serverid(api.env.realm))
    dirs = [dirname, paths.PKI_TOMCAT_ALIAS_DIR, paths.HTTPD_ALIAS_DIR]
    ids = certmonger.check_state(dirs)
    if ids:
        root_logger.error('Some certificates may still be tracked by '
                          'certmonger.\n'
                          'This will cause re-installation to fail.\n'
                          'Start the certmonger service and list the '
                          'certificates being tracked\n'
                          ' # getcert list\n'
                          'These may be untracked by executing\n'
                          ' # getcert stop-tracking -i <request_id>\n'
                          'for each id in: %s' % ', '.join(ids))

    # Remove the cert renewal lock file
    try:
        os.remove(paths.IPA_RENEWAL_LOCK)
    except OSError as e:
        if e.errno != errno.ENOENT:
            root_logger.warning("Failed to remove file %s: %s",
                                paths.IPA_RENEWAL_LOCK, e)

    print("Removing IPA client configuration")
    try:
        result = run([
            paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
            "--uninstall"
        ],
                     raiseonerr=False,
                     redirect_output=True)
        if result.returncode not in [0, 2]:
            raise RuntimeError("Failed to configure the client")
    except Exception:
        rv = 1
        print("Uninstall of client side components failed!")

    sys.exit(rv)
Exemple #54
0
def install(installer):
    options = installer
    fstore = installer._fstore
    sstore = installer._sstore
    dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
    http_pkcs12_info = installer._http_pkcs12_info
    pkinit_pkcs12_info = installer._pkinit_pkcs12_info
    http_ca_cert = installer._ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_addresses
    setup_ca = options.setup_ca

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installer._installation_cleanup = False

    if installer.interactive:
        print("")
        print("The following operations may take some minutes to complete.")
        print("Please wait until the prompt is returned.")
        print("")

    # set hostname (transient and static) if user instructed us to do so
    if options._host_name_overridden:
        tasks.backup_hostname(fstore, sstore)
        tasks.set_hostname(host_name)

    if installer._update_hosts_file:
        update_hosts_file(ip_addresses, host_name, fstore)

    if tasks.configure_pkcs11_modules(fstore):
        print("Disabled p11-kit-proxy")

    # Create a directory server instance
    if not options.external_cert_files:
        # We have to sync time before certificate handling on master.
        # As chrony configuration is moved from client here, unconfiguration of
        # chrony will be handled here in uninstall() method as well by invoking
        # the ipa-server-install --uninstall
        if not options.no_ntp and not sync_time(
                options.ntp_servers, options.ntp_pool, fstore, sstore):
            print("Warning: IPA was unable to sync time with chrony!")
            print("         Time synchronization is required for IPA "
                  "to work correctly")

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password, dirsrv_pkcs12_info,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow,
                               setup_pkinit=not options.no_pkinit)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow,
                               setup_pkinit=not options.no_pkinit)

    else:
        api.Backend.ldap2.connect()
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        installer._ds = ds
        ds.init_info(
            realm_name, host_name, domain_name, dm_password,
            options.subject_base, options.ca_subject, 1101, 1100, None,
            setup_pkinit=not options.no_pkinit)

    krb = krbinstance.KrbInstance(fstore)
    if not options.external_cert_files:
        krb.create_instance(realm_name, host_name, domain_name,
                            dm_password, master_password,
                            setup_pkinit=not options.no_pkinit,
                            pkcs12_info=pkinit_pkcs12_info,
                            subject_base=options.subject_base)
    else:
        krb.init_info(realm_name, host_name,
                      setup_pkinit=not options.no_pkinit,
                      subject_base=options.subject_base)

    custodia = custodiainstance.get_custodia_instance(
        options, custodiainstance.CustodiaModes.FIRST_MASTER)
    custodia.create_instance()

    if setup_ca:
        if not options.external_cert_files and options.external_ca:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.reverse_zones = dns.reverse_zones
            cache_vars = {n: options.__dict__[n] for o, n in installer.knobs()
                          if n in options.__dict__}
            write_cache(cache_vars)

        ca.install_step_0(False, None, options, custodia=custodia)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
        os.chmod(paths.IPA_CA_CRT, 0o444)

        if not options.no_pkinit:
            x509.write_certificate(http_ca_cert, paths.KDC_CA_BUNDLE_PEM)
        else:
            with open(paths.KDC_CA_BUNDLE_PEM, 'w'):
                pass
        os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444)

        x509.write_certificate(http_ca_cert, paths.CA_BUNDLE_PEM)
        os.chmod(paths.CA_BUNDLE_PEM, 0o444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    if setup_ca:
        ca.install_step_1(False, None, options, custodia=custodia)

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name,
                         ipautil.realm_to_suffix(realm_name))

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            pkcs12_info=http_pkcs12_info, subject_base=options.subject_base,
            auto_redirect=not options.no_ui_redirect,
            ca_is_configured=setup_ca)
    else:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            subject_base=options.subject_base,
            auto_redirect=not options.no_ui_redirect,
            ca_is_configured=setup_ca)

    ca.set_subject_base_in_config(options.subject_base)

    # configure PKINIT now that all required services are in place
    krb.enable_ssl()

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created. DS is restarted in the process.
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart krb after configurations have been changed
    service.print_msg("Restarting the KDC")
    krb.restart()

    if options.setup_kra:
        kra.install(api, None, options, custodia=custodia)

    if options.setup_dns:
        dns.install(False, False, options)

    if options.setup_adtrust:
        adtrust.install(False, options, fstore, api)

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    service.print_msg("Configuring client side components")
    try:
        args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
                "--domain", domain_name, "--server", host_name,
                "--realm", realm_name, "--hostname", host_name, "--no-ntp"]
        if options.no_dns_sshfp:
            args.append("--no-dns-sshfp")
        if options.ssh_trust_dns:
            args.append("--ssh-trust-dns")
        if options.no_ssh:
            args.append("--no-ssh")
        if options.no_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        start = time.time()
        run(args, redirect_output=True)
        dur = time.time() - start
        logger.debug("Client install duration: %0.3f", dur,
                     extra={'timing': ('clientinstall', None, None, dur)})
        print()
    except Exception:
        raise ScriptError("Configuration of client side components failed!")

    # Enable configured services and update DNS SRV records
    service.enable_services(host_name)
    api.Command.dns_update_system_records()

    if not options.setup_dns:
        # After DNS and AD trust are configured and services are
        # enabled, create a dummy instance to dump DNS configuration.
        bind = bindinstance.BindInstance(fstore)
        bind.create_file_with_system_records()

    # Everything installed properly, activate ipa service.
    services.knownservices.ipa.enable()

    print("======================================="
          "=======================================")
    print("Setup complete")
    print("")
    print("Next steps:")
    print("\t1. You must make sure these network ports are open:")
    print("\t\tTCP Ports:")
    print("\t\t  * 80, 443: HTTP/HTTPS")
    print("\t\t  * 389, 636: LDAP/LDAPS")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    print("\t\tUDP Ports:")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    if not options.no_ntp:
        print("\t\t  * 123: ntp")
    print("")
    print("\t2. You can now obtain a kerberos ticket using the command: "
          "'kinit admin'")
    print("\t   This ticket will allow you to use the IPA tools (e.g., ipa "
          "user-add)")
    print("\t   and the web user interface.")

    if not services.knownservices.chronyd.is_running():
        print("\t3. Kerberos requires time synchronization between clients")
        print("\t   and servers for correct operation. You should consider "
              "enabling chronyd.")

    print("")
    if setup_ca:
        print(("Be sure to back up the CA certificates stored in " +
              paths.CACERT_P12))
        print("These files are required to create replicas. The password for "
              "these")
        print("files is the Directory Manager password")

    if os.path.isfile(paths.ROOT_IPA_CACHE):
        os.remove(paths.ROOT_IPA_CACHE)
Exemple #55
0
def test_delete_cert_and_key():
    """Test that delete_cert + delete_key always deletes everything

    Test with a NSSDB that contains:
    - cert + key
    - key only
    - cert only
    - none of them
    """
    cmd = ipautil.run(['mktemp'], capture_output=True)
    p12file = cmd.output.strip()

    try:
        with NSSDatabase() as nssdb:
            nssdb.create_db()

            # 1. Test delete_key_and_cert when cert + key are present
            # Create a NSS DB with cert + key
            create_selfsigned(nssdb)
            # Save both in a p12 file for latter use
            ipautil.run([
                'pk12util', '-o', p12file, '-n', CERTNICK, '-d', nssdb.secdir,
                '-k', nssdb.pwd_file, '-w', nssdb.pwd_file
            ])
            # Delete cert and key
            nssdb.delete_key_and_cert(CERTNICK)
            # make sure that everything was deleted
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 0

            # 2. Test delete_key_and_cert when only key is present
            # Import cert and key then remove cert
            import_args = [
                'pk12util', '-i', p12file, '-d', nssdb.secdir, '-k',
                nssdb.pwd_file, '-w', nssdb.pwd_file
            ]
            ipautil.run(import_args)
            nssdb.delete_cert(CERTNICK)
            # Delete cert and key
            nssdb.delete_key_and_cert(CERTNICK)
            # make sure that everything was deleted
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 0

            # 3. Test delete_key_and_cert when only cert is present
            # Import cert and key then remove key
            ipautil.run(import_args)
            nssdb.delete_key_only(CERTNICK)
            # make sure the db contains only the cert
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 1

            # Delete cert and key when key is not present
            nssdb.delete_key_and_cert(CERTNICK)
            # make sure that everything was deleted
            assert len(nssdb.list_keys()) == 0
            assert len(nssdb.list_certs()) == 0

            # 4. Test delete_key_and_cert with a wrong nickname
            # Import cert and key
            ipautil.run(import_args)
            # Delete cert and key
            nssdb.delete_key_and_cert('wrongnick')
            # make sure that nothing was deleted
            assert len(nssdb.list_keys()) == 1
            assert len(nssdb.list_certs()) == 1
    finally:
        os.unlink(p12file)
Exemple #56
0
    def import_files(self, files, import_keys=False, key_password=None,
                     key_nickname=None):
        """
        Import certificates and a single private key from multiple files

        The files may be in PEM and DER certificate, PKCS#7 certificate chain,
        PKCS#8 and raw private key and PKCS#12 formats.

        :param files: Names of files to import
        :param import_keys: Whether to import private keys
        :param key_password: Password to decrypt private keys
        :param key_nickname: Nickname of the private key to import from PKCS#12
            files
        """
        key_file = None
        extracted_key = None
        extracted_certs = []

        for filename in files:
            try:
                with open(filename, 'rb') as f:
                    data = f.read()
            except IOError as e:
                raise RuntimeError(
                    "Failed to open %s: %s" % (filename, e.strerror))

            # Try to parse the file as PEM file
            matches = list(
                re.finditer(
                    br'-----BEGIN (.+?)-----(.*?)-----END \1-----',
                    data, re.DOTALL
                )
            )
            if matches:
                loaded = False
                for match in matches:
                    body = match.group()
                    label = match.group(1)
                    line = len(data[:match.start() + 1].splitlines())

                    if label in (b'CERTIFICATE', b'X509 CERTIFICATE',
                                 b'X.509 CERTIFICATE'):
                        try:
                            cert = x509.load_pem_x509_certificate(body)
                        except ValueError as e:
                            if label != b'CERTIFICATE':
                                logger.warning(
                                    "Skipping certificate in %s at line %s: "
                                    "%s",
                                    filename, line, e)
                                continue
                        else:
                            extracted_certs.append(cert)
                            loaded = True
                            continue

                    if label in (b'PKCS7', b'PKCS #7 SIGNED DATA',
                                 b'CERTIFICATE'):
                        try:
                            certs = x509.pkcs7_to_certs(body)
                        except ipautil.CalledProcessError as e:
                            if label == b'CERTIFICATE':
                                logger.warning(
                                    "Skipping certificate in %s at line %s: "
                                    "%s",
                                    filename, line, e)
                            else:
                                logger.warning(
                                    "Skipping PKCS#7 in %s at line %s: %s",
                                    filename, line, e)
                            continue
                        else:
                            extracted_certs.extend(certs)
                            loaded = True
                            continue

                    if label in (b'PRIVATE KEY', b'ENCRYPTED PRIVATE KEY',
                                 b'RSA PRIVATE KEY', b'DSA PRIVATE KEY',
                                 b'EC PRIVATE KEY'):
                        if not import_keys:
                            continue

                        if key_file:
                            raise RuntimeError(
                                "Can't load private key from both %s and %s" %
                                (key_file, filename))

                        # the args -v2 aes256 -v2prf hmacWithSHA256 are needed
                        # on OpenSSL 1.0.2 (fips mode). As soon as FreeIPA
                        # requires OpenSSL 1.1.0 we'll be able to drop them
                        args = [
                            paths.OPENSSL, 'pkcs8',
                            '-topk8',
                            '-v2', 'aes256', '-v2prf', 'hmacWithSHA256',
                            '-passout', 'file:' + self.pwd_file,
                        ]
                        if ((label != b'PRIVATE KEY' and key_password) or
                                label == b'ENCRYPTED PRIVATE KEY'):
                            key_pwdfile = ipautil.write_tmp_file(key_password)
                            args += [
                                '-passin', 'file:' + key_pwdfile.name,
                            ]
                        try:
                            result = ipautil.run(
                                args, stdin=body, capture_output=True)
                        except ipautil.CalledProcessError as e:
                            logger.warning(
                                "Skipping private key in %s at line %s: %s",
                                filename, line, e)
                            continue
                        else:
                            extracted_key = result.raw_output
                            key_file = filename
                            loaded = True
                            continue
                if loaded:
                    continue
                raise RuntimeError("Failed to load %s" % filename)

            # Try to load the file as DER certificate
            try:
                cert = x509.load_der_x509_certificate(data)
            except ValueError:
                pass
            else:
                extracted_certs.append(cert)
                continue

            # Try to import the file as PKCS#12 file
            if import_keys:
                try:
                    self.import_pkcs12(filename, key_password)
                except Pkcs12ImportUnknownError:
                    # the file may not be a PKCS#12 file,
                    # go to the generic error about unrecognized format
                    pass
                except RuntimeError as e:
                    raise RuntimeError("Failed to load %s: %s" %
                                       (filename, str(e)))
                else:
                    if key_file:
                        raise RuntimeError(
                            "Can't load private key from both %s and %s" %
                            (key_file, filename))
                    key_file = filename

                    server_certs = self.find_server_certs()
                    if key_nickname:
                        for nickname, _trust_flags in server_certs:
                            if nickname == key_nickname:
                                break
                        else:
                            raise RuntimeError(
                                "Server certificate \"%s\" not found in %s" %
                                (key_nickname, filename))
                    else:
                        if len(server_certs) > 1:
                            raise RuntimeError(
                                "%s server certificates found in %s, "
                                "expecting only one" %
                                (len(server_certs), filename))

                    continue

            # Supported formats were tried but none succeeded
            raise RuntimeError("Failed to load %s: unrecognized format" %
                               filename)

        if import_keys and not key_file:
            raise RuntimeError(
                "No server certificates found in %s" % (', '.join(files)))

        for cert in extracted_certs:
            nickname = str(DN(cert.subject))
            self.add_cert(cert, nickname, EMPTY_TRUST_FLAGS)

        if extracted_key:
            with tempfile.NamedTemporaryFile() as in_file, \
                    tempfile.NamedTemporaryFile() as out_file:
                for cert in extracted_certs:
                    in_file.write(cert.public_bytes(x509.Encoding.PEM))
                in_file.write(extracted_key)
                in_file.flush()
                out_password = ipautil.ipa_generate_password()
                out_pwdfile = ipautil.write_tmp_file(out_password)
                args = [
                    paths.OPENSSL, 'pkcs12',
                    '-export',
                    '-in', in_file.name,
                    '-out', out_file.name,
                    '-passin', 'file:' + self.pwd_file,
                    '-passout', 'file:' + out_pwdfile.name,
                    '-certpbe', 'aes-128-cbc',
                    '-keypbe', 'aes-128-cbc',
                ]
                try:
                    ipautil.run(args)
                except ipautil.CalledProcessError as e:
                    raise RuntimeError(
                        "No matching certificate found for private key from "
                        "%s" % key_file)

                self.import_pkcs12(out_file.name, out_password)
Exemple #57
0
    def create_db(self, user=None, group=None, mode=None, backup=False):
        """Create cert DB

        :param user: User owner the secdir
        :param group: Group owner of the secdir
        :param mode: Mode of the secdir
        :param backup: Backup the sedir files
        """
        if mode is not None:
            dirmode = mode
            filemode = mode & 0o666
            pwdfilemode = mode & 0o660
        else:
            dirmode = 0o750
            filemode = 0o640
            pwdfilemode = 0o640

        uid = -1
        gid = -1
        if user is not None:
            uid = pwd.getpwnam(user).pw_uid
        if group is not None:
            gid = grp.getgrnam(group).gr_gid

        if backup:
            for filename in self.backup_filenames:
                ipautil.backup_file(filename)

        if not os.path.exists(self.secdir):
            os.makedirs(self.secdir, dirmode)

        if not os.path.exists(self.pwd_file):
            # Create the password file for this db
            with io.open(os.open(self.pwd_file,
                                 os.O_CREAT | os.O_WRONLY,
                                 pwdfilemode), 'w', closefd=True) as f:
                f.write(ipautil.ipa_generate_password())
                # flush and sync tempfile inode
                f.flush()
                os.fsync(f.fileno())

        # In case dbtype is auto, let certutil decide which type of DB
        # to create.
        if self.dbtype == 'auto':
            dbdir = self.secdir
        else:
            dbdir = '{}:{}'.format(self.dbtype, self.secdir)
        args = [
            paths.CERTUTIL,
            '-d', dbdir,
            '-N',
            '-f', self.pwd_file,
            # -@ in case it's an old db and it must be migrated
            '-@', self.pwd_file,
        ]
        ipautil.run(args, stdin=None, cwd=self.secdir)
        self._set_filenames(self._detect_dbtype())
        if self.filenames is None:
            # something went wrong...
            raise ValueError(
                "Failed to create NSSDB at '{}'".format(self.secdir)
            )

        # Finally fix up perms
        os.chown(self.secdir, uid, gid)
        os.chmod(self.secdir, dirmode)
        tasks.restore_context(self.secdir, force=True)
        for filename in self.filenames:
            if os.path.exists(filename):
                os.chown(filename, uid, gid)
                if filename == self.pwd_file:
                    new_mode = pwdfilemode
                else:
                    new_mode = filemode
                os.chmod(filename, new_mode)
                tasks.restore_context(filename, force=True)
Exemple #58
0
    def run(self):
        if not is_ipa_configured():
            print("IPA is not configured.")
            return 2

        if not cainstance.is_ca_installed_locally():
            print("CA is not installed on this server.")
            return 1

        try:
            ipautil.run(['pki-server', 'cert-fix', '--help'], raiseonerr=True)
        except ipautil.CalledProcessError:
            print(
                "The 'pki-server cert-fix' command is not available; "
                "cannot proceed."
            )
            return 1

        api.bootstrap(in_server=True, confdir=paths.ETC_IPA)
        api.finalize()
        api.Backend.ldap2.connect()  # ensure DS is up

        subject_base = dsinstance.DsInstance().find_subject_base()
        if not subject_base:
            raise RuntimeError("Cannot determine certificate subject base.")

        ca_subject_dn = ca.lookup_ca_subject(api, subject_base)

        now = datetime.datetime.now() + datetime.timedelta(weeks=2)
        certs, extra_certs = expired_certs(now)

        if not certs and not extra_certs:
            print("Nothing to do.")
            return 0

        print(msg)

        print_intentions(certs, extra_certs)

        response = ipautil.user_input('Enter "yes" to proceed')
        if response.lower() != 'yes':
            print("Not proceeding.")
            return 0
        print("Proceeding.")

        try:
            run_cert_fix(certs, extra_certs)
        except ipautil.CalledProcessError:
            if any(x[0] is IPACertType.LDAPS for x in extra_certs):
                # The DS cert was expired.  This will cause
                # 'pki-server cert-fix' to fail at the final
                # restart.  Therefore ignore the CalledProcessError
                # and proceed to installing the IPA-specific certs.
                pass
            else:
                raise  # otherwise re-raise

        replicate_dogtag_certs(subject_base, ca_subject_dn, certs)
        install_ipa_certs(subject_base, ca_subject_dn, extra_certs)

        if any(x[0] != 'sslserver' for x in certs) \
                or any(x[0] is IPACertType.IPARA for x in extra_certs):
            # we renewed a "shared" certificate, therefore we must
            # become the renewal master
            print("Becoming renewal master.")
            cainstance.CAInstance().set_renewal_master()

        ipautil.run(['ipactl', 'restart'], raiseonerr=True)

        return 0
Exemple #59
0
    def test_join_host(self, host, keytabname):
        """
        Create a test host and join it into IPA.

        This test must not run remotely.
        """

        if not os.path.isfile(paths.SBIN_IPA_JOIN):
            pytest.skip("Command '%s' not found. "
                        "The test must not run remotely." %
                        paths.SBIN_IPA_JOIN)

        # create a test host with bulk enrollment password
        host.track_create()

        # manipulate host.attrs to correspond with real attributes of host
        # after creating it with random password
        del host.attrs['krbprincipalname']
        del host.attrs['krbcanonicalname']
        host.attrs['has_password'] = True
        objclass = list(
            set(host.attrs['objectclass']) -
            {u'krbprincipal', u'krbprincipalaux'})
        host.attrs['objectclass'] = objclass

        command = host.make_create_command(force=True)
        result = command(random=True)
        random_pass = result['result']['randompassword']

        host.attrs['randompassword'] = random_pass
        host.check_create(result)

        del host.attrs['randompassword']

        # joint the host with the bulk password
        new_args = [
            paths.SBIN_IPA_JOIN,
            "-s",
            host.api.env.host,
            "-h",
            host.fqdn,
            "-k",
            keytabname,
            "-w",
            random_pass,
            "-q",
        ]

        try:
            ipautil.run(new_args)
        except ipautil.CalledProcessError as e:
            # join operation may fail on 'adding key into keytab', but
            # the keytab is not necessary for further tests
            print(e)

        # fix host.attrs again to correspond with current state
        host.attrs['has_keytab'] = True
        host.attrs['has_password'] = False
        host.attrs['krbprincipalname'] = [
            u'host/%s@%s' % (host.fqdn, host.api.env.realm)
        ]
        host.attrs['krbcanonicalname'] = [
            u'host/%s@%s' % (host.fqdn, host.api.env.realm)
        ]
        host.retrieve()

        # Try to change the password of enrolled host with specified password
        command = host.make_update_command(updates=dict(
            userpassword=u'pass_123'))
        with pytest.raises(errors.ValidationError):
            command()

        # Try to change the password of enrolled host with random password
        command = host.make_update_command(updates=dict(random=True))
        with pytest.raises(errors.ValidationError):
            command()
Exemple #60
0
 def set_hostname(self, hostname):
     ipautil.run([paths.BIN_HOSTNAMECTL, 'set-hostname', hostname])