Beispiel #1
0
    def verify_server_cert_validity(self, nickname, hostname):
        """Verify a certificate is valid for a SSL server with given hostname

        Raises a ValueError if the certificate is invalid.
        """
        certdb = cert = None
        if nss.nss_is_initialized():
            nss.nss_shutdown()
        nss.nss_init(self.secdir)
        try:
            certdb = nss.get_default_certdb()
            cert = nss.find_cert_from_nickname(nickname)
            intended_usage = nss.certificateUsageSSLServer
            try:
                approved_usage = cert.verify_now(certdb, True, intended_usage)
            except NSPRError as e:
                if e.errno != -8102:
                    raise ValueError(e.strerror)
                approved_usage = 0
            if not approved_usage & intended_usage:
                raise ValueError('invalid for a SSL server')
            if not cert.verify_hostname(hostname):
                raise ValueError('invalid for server %s' % hostname)
        finally:
            del certdb, cert
            nss.nss_shutdown()

        return None
Beispiel #2
0
    def __init__(self, work_dir, kra_host, kra_port, kra_nickname):
        # crypto
        self.sec_dir = work_dir
        self.pwd_file = work_dir + "/pwdfile.txt"
        self.transport_cert_nickname = kra_nickname
        self.mechanism = nss.CKM_DES3_CBC_PAD
        try:
            with open(self.pwd_file, "r") as f:
                self.password = f.readline().strip()
        except IOError:
            self.password = ''

        # set up key db for crypto functions
        try:
            nss.nss_init(self.sec_dir)
        except Exception as e:
            raise CertificateOperationError(
                error=_('Error in initializing certdb (%s)') % e.strerror)
        self.transport_cert = nss.find_cert_from_nickname(
            self.transport_cert_nickname)

        # DRM info
        self.kra_host = kra_host
        self.kra_agent_port = kra_port
        '''super(kra, self).__init__()'''
Beispiel #3
0
def load_certificate(data, datatype=PEM, dbdir=None):
    """
    Given a base64-encoded certificate, with or without the
    header/footer, return a request object.

    Returns a nss.Certificate type
    """
    if type(data) in (tuple, list):
        data = data[0]

    if (datatype == PEM):
        data = strip_header(data)
        data = base64.b64decode(data)

    if not nss.nss_is_initialized():
        if dbdir is None:
            if 'in_tree' in api.env:
                if api.env.in_tree:
                    dbdir = api.env.dot_ipa + os.sep + 'alias'
                else:
                    dbdir = "/etc/httpd/alias"
                nss.nss_init(dbdir)
            else:
                nss.nss_init_nodb()
        else:
            nss.nss_init(dbdir)

    return nss.Certificate(buffer(data))
Beispiel #4
0
 def verify_ca_cert_validity(self, nickname):
     certdb = cert = None
     if nss.nss_is_initialized():
         nss.nss_shutdown()
     nss.nss_init(self.secdir)
     try:
         certdb = nss.get_default_certdb()
         cert = nss.find_cert_from_nickname(nickname)
         if not cert.subject:
             raise ValueError("has empty subject")
         try:
             bc = cert.get_extension(nss.SEC_OID_X509_BASIC_CONSTRAINTS)
         except KeyError:
             raise ValueError("missing basic constraints")
         bc = nss.BasicConstraints(bc.value)
         if not bc.is_ca:
             raise ValueError("not a CA certificate")
         intended_usage = nss.certificateUsageSSLCA
         try:
             approved_usage = cert.verify_now(certdb, True, intended_usage)
         except NSPRError as e:
             if e.errno != -8102:    # SEC_ERROR_INADEQUATE_KEY_USAGE
                 raise ValueError(e.strerror)
             approved_usage = 0
         if approved_usage & intended_usage != intended_usage:
             raise ValueError('invalid for a CA')
     finally:
         del certdb, cert
         nss.nss_shutdown()
Beispiel #5
0
    def verify_server_cert_validity(self, nickname, hostname):
        """Verify a certificate is valid for a SSL server with given hostname

        Raises a ValueError if the certificate is invalid.
        """
        certdb = cert = None
        if nss.nss_is_initialized():
            nss.nss_shutdown()
        nss.nss_init(self.secdir)
        try:
            certdb = nss.get_default_certdb()
            cert = nss.find_cert_from_nickname(nickname)
            intended_usage = nss.certificateUsageSSLServer
            try:
                approved_usage = cert.verify_now(certdb, True, intended_usage)
            except NSPRError as e:
                if e.errno != -8102:
                    raise ValueError(e.strerror)
                approved_usage = 0
            if not approved_usage & intended_usage:
                raise ValueError('invalid for a SSL server')
            if not cert.verify_hostname(hostname):
                raise ValueError('invalid for server %s' % hostname)
        finally:
            del certdb, cert
            nss.nss_shutdown()

        return None
Beispiel #6
0
 def verify_ca_cert_validity(self, nickname):
     certdb = cert = None
     if nss.nss_is_initialized():
         nss.nss_shutdown()
     nss.nss_init(self.secdir)
     try:
         certdb = nss.get_default_certdb()
         cert = nss.find_cert_from_nickname(nickname)
         if not cert.subject:
             raise ValueError("has empty subject")
         try:
             bc = cert.get_extension(nss.SEC_OID_X509_BASIC_CONSTRAINTS)
         except KeyError:
             raise ValueError("missing basic constraints")
         bc = nss.BasicConstraints(bc.value)
         if not bc.is_ca:
             raise ValueError("not a CA certificate")
         intended_usage = nss.certificateUsageSSLCA
         try:
             approved_usage = cert.verify_now(certdb, True, intended_usage)
         except NSPRError as e:
             if e.errno != -8102:  # SEC_ERROR_INADEQUATE_KEY_USAGE
                 raise ValueError(e.strerror)
             approved_usage = 0
         if approved_usage & intended_usage != intended_usage:
             raise ValueError('invalid for a CA')
     finally:
         del certdb, cert
         nss.nss_shutdown()
Beispiel #7
0
 def setUp(self):
     nss.nss_init(db_name)
     nss.set_password_callback(password_callback)
     nss.pkcs12_enable_all_ciphers()
     self.cert_der = get_cert_der_from_db(cert_nickname)
     if self.cert_der is None:
         raise ValueError('cert with nickname "%s" not in database "%s"' % (cert_nickname, db_name))
Beispiel #8
0
    def __init__(self, work_dir, kra_host, kra_port, kra_nickname):
        # crypto
        self.sec_dir = work_dir
        self.pwd_file = work_dir + "/pwdfile.txt"
        self.transport_cert_nickname = kra_nickname
        self.mechanism = nss.CKM_DES3_CBC_PAD
        try:
            with open(self.pwd_file, "r") as f:
                self.password = f.readline().strip()
        except IOError:
            self.password = ''

        # set up key db for crypto functions
        try:
            nss.nss_init(self.sec_dir)
        except Exception as e:
            raise CertificateOperationError(
                error=_('Error in initializing certdb (%s)') + e.strerror)
        self.transport_cert = nss.find_cert_from_nickname(
            self.transport_cert_nickname)

        # DRM info
        self.kra_host = kra_host
        self.kra_agent_port = kra_port
        '''super(kra, self).__init__()'''
Beispiel #9
0
 def setUp(self):
     nss.nss_init(db_name)
     nss.set_password_callback(password_callback)
     nss.pkcs12_enable_all_ciphers()
     self.cert_der = get_cert_der_from_db(cert_nickname)
     if self.cert_der is None:
         raise ValueError('cert with nickname "%s" not in database "%s"' % (cert_nickname, db_name))
Beispiel #10
0
def load_certificate(data, datatype=PEM, dbdir=None):
    """
    Given a base64-encoded certificate, with or without the
    header/footer, return a request object.

    Returns a nss.Certificate type
    """
    if type(data) in (tuple, list):
        data = data[0]

    if (datatype == PEM):
        data = strip_header(data)
        data = base64.b64decode(data)

    if not nss.nss_is_initialized():
        if dbdir is None:
            if 'in_tree' in api.env:
                if api.env.in_tree:
                    dbdir = api.env.dot_ipa + os.sep + 'alias'
                else:
                    dbdir = "/etc/httpd/alias"
                nss.nss_init(dbdir)
            else:
                nss.nss_init_nodb()
        else:
            nss.nss_init(dbdir)

    return nss.Certificate(buffer(data))
Beispiel #11
0
def run_server():
    pid = os.fork()
    if pid == 0:
        nss.nss_init(db_name)
        server()
        nss.nss_shutdown()
    time.sleep(sleep_time)
    return pid
Beispiel #12
0
def run_server():
    pid = os.fork()
    if pid == 0:
        nss.nss_init(certdir)
        server()
        nss.nss_shutdown()
    time.sleep(sleep_time)
    return pid
Beispiel #13
0
    def init(self):
        if nss.nss_is_initialized():
            return

        if _password_callback is not None:
            nss.set_password_callback(_password_callback)

        nss.nss_init(_certdb)
        ssl.set_domestic_policy()
Beispiel #14
0
    def init(self):
        if nss.nss_is_initialized():
            return

        if _password_callback is not None:
            nss.set_password_callback(_password_callback)

        nss.nss_init(_certdb)
        ssl.set_domestic_policy()
Beispiel #15
0
    def __init__(self, host, port=None, strict=None, dbdir=None):
        six.moves.http_client.HTTPConnection.__init__(self, host, port, strict)

        if not dbdir:
            raise RuntimeError("dbdir is required")

        logging.debug('%s init host=%s dbdir=%s', self.__class__.__name__, host, dbdir)
        if not nss.nss_is_initialized(): nss.nss_init(dbdir)
        self.sock = None
        ssl.set_domestic_policy()
        nss.set_password_callback(password_callback)
Beispiel #16
0
def initialize_nss(dbdir):
    """Initialize NSS

    nss_init() initializes NSS and the DB globally.
    """
    # global settings
    nss.nss_init(dbdir)
    ssl.set_domestic_policy()
    ssl.clear_session_cache()
    # thread local callback
    nss.set_password_callback(password_callback)
Beispiel #17
0
 def setUp(self):
     nss.nss_init(db_name)
     nss.set_password_callback(password_callback)
     # XXX: error in NSS prevents enabling ciphers
     # nss.pkcs12_enable_all_ciphers()
     self.cert_der = get_cert_der_from_db(cert_nickname)
     if self.cert_der is None:
         raise ValueError(
             "cert with nickname '%s' not in database '%s'"
             % (cert_nickname, db_name)
         )
    def __init__(self, host, port=None, strict=None, dbdir=None):
        httplib.HTTPConnection.__init__(self, host, port, strict)

        if not dbdir:
            raise RuntimeError("dbdir is required")

        logging.debug('%s init %s', self.__class__.__name__, host)
        if not nss.nss_is_initialized(): nss.nss_init(dbdir)
        self.sock = None
        ssl.set_domestic_policy()
        nss.set_password_callback(password_callback)
Beispiel #19
0
    def __init__(self,
                 host,
                 port=None,
                 strict=None,
                 dbdir=None,
                 family=socket.AF_UNSPEC,
                 no_init=False,
                 tls_version_min='tls1.1',
                 tls_version_max='tls1.2'):
        """
        :param host: the server to connect to
        :param port: the port to use (default is set in HTTPConnection)
        :param dbdir: the NSS database directory
        :param family: network family to use (default AF_UNSPEC)
        :param no_init: do not initialize the NSS database. This requires
                        that the database has already been initialized or
                        the request will fail.
        :param tls_min_version: mininum version of SSL/TLS supported
        :param tls_max_version: maximum version of SSL/TLS supported.
        """
        httplib.HTTPConnection.__init__(self, host, port, strict)
        NSSAddressFamilyFallback.__init__(self, family)

        root_logger.debug('%s init %s', self.__class__.__name__, host)

        # If initialization is requested, initialize the new database.
        if not no_init:

            if nss.nss_is_initialized():
                ssl.clear_session_cache()
                try:
                    nss.nss_shutdown()
                except NSPRError as e:
                    if e.errno != error.SEC_ERROR_NOT_INITIALIZED:
                        raise e

            if not dbdir:
                raise RuntimeError("dbdir is required")

            nss.nss_init(dbdir)

            global current_dbdir
            current_dbdir = dbdir

        ssl.set_domestic_policy()
        nss.set_password_callback(self.password_callback)
        tls_versions = get_proper_tls_version_span(tls_version_min,
                                                   tls_version_max)
        self.tls_version_min = tls_versions[0]
        self.tls_version_max = tls_versions[-1]
Beispiel #20
0
    def __init__(
        self,
        host,
        port=None,
        strict=None,
        dbdir=None,
        family=socket.AF_UNSPEC,
        no_init=False,
        tls_version_min="tls1.1",
        tls_version_max="tls1.2",
    ):
        """
        :param host: the server to connect to
        :param port: the port to use (default is set in HTTPConnection)
        :param dbdir: the NSS database directory
        :param family: network family to use (default AF_UNSPEC)
        :param no_init: do not initialize the NSS database. This requires
                        that the database has already been initialized or
                        the request will fail.
        :param tls_min_version: mininum version of SSL/TLS supported
        :param tls_max_version: maximum version of SSL/TLS supported.
        """
        httplib.HTTPConnection.__init__(self, host, port, strict)
        NSSAddressFamilyFallback.__init__(self, family)

        root_logger.debug("%s init %s", self.__class__.__name__, host)

        # If initialization is requested, initialize the new database.
        if not no_init:

            if nss.nss_is_initialized():
                ssl.clear_session_cache()
                try:
                    nss.nss_shutdown()
                except NSPRError as e:
                    if e.errno != error.SEC_ERROR_NOT_INITIALIZED:
                        raise e

            if not dbdir:
                raise RuntimeError("dbdir is required")

            nss.nss_init(dbdir)

            global current_dbdir
            current_dbdir = dbdir

        ssl.set_domestic_policy()
        nss.set_password_callback(self.password_callback)
        self.tls_version_min = str(tls_version_min)
        self.tls_version_max = str(tls_version_max)
Beispiel #21
0
 def test_nss(self):
     '''References:
     github.com/tiran/python-nss/blob/master/doc/examples/ssl_example.py
     - Get certificates
     certutil -L -d sql:$HOME/.pki/nssdb/
     - Get one certificate by nickname
     certutil -L -d sql:$HOME/.pki/nssdb/ -a -n my-nickname
     - Rename nickname of certificate
     certutil --rename -n my-nicname --new-n my-new-nicname
         -d sql:/home/javierroman/.pki/nssdb/
     - Change NSS db password (new empty erase password)
     certutil -W -d sql:$HOME/.pki/nssdb/ -f old.txt [email protected]
     '''
     print("called query")
     db_name = 'sql:' + os.getenv('HOME') + '/.pki/nssdb'
     nss.nss_init(db_name)
Beispiel #22
0
def initialize_nss_database(dbdir=None):
    """
    Initializes NSS database, if not initialized yet. Uses a proper database
    directory (.ipa/alias or HTTPD_ALIAS_DIR), depending on the value of
    api.env.in_tree.
    """

    if not nss.nss_is_initialized():
        if dbdir is None:
            if 'in_tree' in api.env:
                if api.env.in_tree:
                    dbdir = api.env.dot_ipa + os.sep + 'alias'
                else:
                    dbdir = paths.HTTPD_ALIAS_DIR
                nss.nss_init(dbdir)
            else:
                nss.nss_init_nodb()
        else:
            nss.nss_init(dbdir)
Beispiel #23
0
def initialize_nss_database(dbdir=None):
    """
    Initializes NSS database, if not initialized yet. Uses a proper database
    directory (.ipa/alias or HTTPD_ALIAS_DIR), depending on the value of
    api.env.in_tree.
    """

    if not nss.nss_is_initialized():
        if dbdir is None:
            if 'in_tree' in api.env:
                if api.env.in_tree:
                    dbdir = api.env.dot_ipa + os.sep + 'alias'
                else:
                    dbdir = paths.HTTPD_ALIAS_DIR
                nss.nss_init(dbdir)
            else:
                nss.nss_init_nodb()
        else:
            nss.nss_init(dbdir)
Beispiel #24
0
 def test_ssl(self):
     request = "foo"
     nss.nss_init(certdir)
     reply = client(request)
     nss.nss_shutdown()
     self.assertEqual("{%s}" % request, reply)
Beispiel #25
0
    def forward(self, *args, **options):
        data = options.get('data')
        input_file = options.get('in')

        password = options.get('password')
        password_file = options.get('password_file')

        override_password = options.pop('override_password', False)

        # don't send these parameters to server
        if 'data' in options:
            del options['data']
        if 'in' in options:
            del options['in']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']

        # get data
        if data and input_file:
            raise errors.MutuallyExclusiveError(
                reason=_('Input data specified multiple times'))

        elif data:
            if len(data) > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="data", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})

        elif input_file:
            try:
                stat = os.stat(input_file)
            except OSError as exc:
                raise errors.ValidationError(name="in", error=_(
                    "Cannot read file '%(filename)s': %(exc)s")
                    % {'filename': input_file, 'exc': exc.args[1]})
            if stat.st_size > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="in", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})
            data = validated_read('in', input_file, mode='rb')

        else:
            data = ''

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect()

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        if vault_type == u'standard':

            encrypted_key = None

        elif vault_type == u'symmetric':

            # get password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                if override_password:
                    password = get_new_password()
                else:
                    password = get_existing_password()

            if not override_password:
                # verify password by retrieving existing data
                opts = options.copy()
                opts['password'] = password
                try:
                    self.api.Command.vault_retrieve(*args, **opts)
                except errors.NotFound:
                    pass

            salt = vault['ipavaultsalt'][0]

            # generate encryption key from vault password
            encryption_key = generate_symmetric_key(password, salt)

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            encrypted_key = None

        elif vault_type == u'asymmetric':

            public_key = vault['ipavaultpublickey'][0].encode('utf-8')

            # generate encryption key
            encryption_key = base64.b64encode(os.urandom(32))

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            # encrypt encryption key with public key
            encrypted_key = encrypt(encryption_key, public_key=public_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        # initialize NSS database
        nss.nss_init(api.env.nss_dir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        # pylint: disable=no-member
        public_key = nss_transport_cert.subject_public_key_info.public_key
        # pylint: enable=no-member
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        options['session_key'] = wrapped_session_key.data

        nonce_length = nss.get_iv_length(mechanism)
        nonce = nss.generate_random(nonce_length)
        options['nonce'] = nonce

        vault_data = {}
        vault_data[u'data'] = base64.b64encode(data).decode('utf-8')

        if encrypted_key:
            vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\
                .decode('utf-8')

        json_vault_data = json.dumps(vault_data)

        # wrap vault_data with session key
        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT,
                                                     session_key,
                                                     iv_param)

        wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\
            + encoding_ctx.digest_final()

        options['vault_data'] = wrapped_vault_data

        return self.api.Command.vault_archive_internal(*args, **options)
                               ["help", "certdir=", "hostname=",
                                "port=",
                                ])
except getopt.GetoptError:
    # print help information and exit:
    usage()
    sys.exit(2)


for o, a in opts:
    if o in ("-d", "--certdir"):
        certdir = a
    if o in ("-h", "--hostname"):
        hostname = a
    if o in ("-p", "--port"):
        port = int(a)
    if o in ("-H", "--help"):
        usage()
        sys.exit()

# Perform basic configuration and setup
try:
    nss.nss_init(certdir)
    ssl.set_domestic_policy()
except Exception, e:
    print >>sys.stderr, e.strerror
    sys.exit(1)

client()

Beispiel #27
0
)

parser.set_defaults(
    db_name='sql:pki',
    hostname='www.verisign.com',
    port=443,
    enumerate_cipher_suites=True,
    ssl_connect=True,
    use_properties=False,
)

options = parser.parse_args()

# Perform basic configuration and setup
try:
    nss.nss_init(options.db_name)
    ssl.set_domestic_policy()

except Exception as e:
    print(str(e), file=sys.stderr)
    sys.exit(1)

if options.enumerate_cipher_suites:
    suite_info = ssl.get_cipher_suite_info(ssl.ssl_implemented_ciphers[0])

    print("There are %d implemented ciphers" %
          (len(ssl.ssl_implemented_ciphers)))

    for cipher in ssl.ssl_implemented_ciphers:
        suite_info = ssl.get_cipher_suite_info(cipher)
        print(suite_info)
Beispiel #28
0
    def execute(self, argv):

        try:
            opts, args = getopt.getopt(argv, 'i:v',
                                       ['instance=', 'verbose', 'help'])

        except getopt.GetoptError as e:
            print('ERROR: ' + str(e))
            self.usage()
            sys.exit(1)

        if len(args) < 1:
            print('ERROR: missing subsystem ID')
            self.usage()
            sys.exit(1)

        if len(args) < 2:
            print('ERROR: missing cert ID')
            self.usage()
            sys.exit(1)

        subsystem_name = args[0]
        cert_id = args[1]
        instance_name = 'pki-tomcat'

        for o, a in opts:
            if o in ('-i', '--instance'):
                instance_name = a

            elif o in ('-v', '--verbose'):
                self.set_verbose(True)

            elif o == '--help':
                self.print_help()
                sys.exit()

            else:
                print('ERROR: unknown option ' + o)
                self.usage()
                sys.exit(1)

        instance = pki.server.PKIInstance(instance_name)
        instance.load()

        subsystem = instance.get_subsystem(subsystem_name)
        subsystem_cert = subsystem.get_subsystem_cert(cert_id)

        # get cert data from NSS database
        nss.nss_init(instance.nssdb_dir)
        nss_cert = nss.find_cert_from_nickname(subsystem_cert['nickname'])
        data = base64.b64encode(nss_cert.der_data)
        del nss_cert
        nss.nss_shutdown()
        subsystem_cert['data'] = data

        # format cert data for LDAP database
        lines = [data[i:i + 64] for i in range(0, len(data), 64)]
        data = string.join(lines, '\r\n') + '\r\n'

        # get cert request from local CA
        # TODO: add support for remote CA
        ca = instance.get_subsystem('ca')
        results = ca.find_cert_requests(cert=data)
        cert_request = results[-1]
        request = cert_request['request']

        # format cert request for CS.cfg
        lines = request.splitlines()
        if lines[0] == '-----BEGIN CERTIFICATE REQUEST-----':
            lines = lines[1:]
        if lines[-1] == '-----END CERTIFICATE REQUEST-----':
            lines = lines[:-1]
        request = string.join(lines, '')
        subsystem_cert['request'] = request

        # store cert data and request in CS.cfg
        subsystem.update_subsystem_cert(subsystem_cert)
        subsystem.save()

        self.print_message('Updated "%s" subsystem certificate' % cert_id)

        SubsystemCertCLI.print_subsystem_cert(subsystem_cert)
Beispiel #29
0
 def __init__(self):
     self.certdb_dir = os.path.expanduser(config.NSS_DB_DIR)
     nss.nss_init(self.certdb_dir)
     nss.enable_ocsp_checking()
     self.certdb = nss.get_default_certdb()
Beispiel #30
0
 def initialize(self):
     """
     Initialize the nss db. Must be done before any crypto operations
     """
     nss.nss_init(self.certdb_dir)
Beispiel #31
0
 def setUp(self):
     nss.nss_init(certdir)
     nss.set_password_callback(password_callback)
     nss.pkcs12_enable_all_ciphers()
Beispiel #32
0
    def renew_external_step_2(self, ca, old_cert):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(conn, api.env.basedn, ca_cert,
                                          nickname, ',,')

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [cert]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[cert])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request(ca, 'ipaRetrieval')

        print("CA certificate successfully renewed")
Beispiel #33
0
                    use_ssl = True,
                    client_cert_action = NO_CLIENT_CERT,
                   )

options = parser.parse_args()

if options.client and options.server:
    print("can't be both client and server")
    sys.exit(1)
if not (options.client or options.server):
    print("must be one of client or server")
    sys.exit(1)

# Perform basic configuration and setup
if options.use_ssl:
    nss.nss_init(options.db_name)
else:
    nss.nss_init_nodb()

ssl.set_domestic_policy()
nss.set_password_callback(password_callback)

min_ssl_version, max_ssl_version = \
    ssl.get_supported_ssl_version_range(repr_kind=nss.AsString)
print("Supported SSL version range: min=%s, max=%s" % \
    (min_ssl_version, max_ssl_version))

min_ssl_version, max_ssl_version = \
    ssl.get_default_ssl_version_range(repr_kind=nss.AsString)
print("Default SSL version range: min=%s, max=%s" % \
    (min_ssl_version, max_ssl_version))
Beispiel #34
0
 def initialize(self):
     """
     Initialize the nss db. Must be done before any crypto operations
     """
     nss.nss_init(self.certdb_dir)
Beispiel #35
0
    def execute(self, argv):

        try:
            opts, args = getopt.getopt(argv, 'i:v', [
                'instance=',
                'verbose', 'help'])

        except getopt.GetoptError as e:
            print('ERROR: ' + str(e))
            self.usage()
            sys.exit(1)

        if len(args) < 1:
            print('ERROR: missing subsystem ID')
            self.usage()
            sys.exit(1)

        if len(args) < 2:
            print('ERROR: missing cert ID')
            self.usage()
            sys.exit(1)

        subsystem_name = args[0]
        cert_id = args[1]
        instance_name = 'pki-tomcat'

        for o, a in opts:
            if o in ('-i', '--instance'):
                instance_name = a

            elif o in ('-v', '--verbose'):
                self.set_verbose(True)

            elif o == '--help':
                self.print_help()
                sys.exit()

            else:
                print('ERROR: unknown option ' + o)
                self.usage()
                sys.exit(1)

        instance = pki.server.PKIInstance(instance_name)
        instance.load()

        subsystem = instance.get_subsystem(subsystem_name)
        subsystem_cert = subsystem.get_subsystem_cert(cert_id)

        # get cert data from NSS database
        nss.nss_init(instance.nssdb_dir)
        nss_cert = nss.find_cert_from_nickname(subsystem_cert['nickname'])
        data = base64.b64encode(nss_cert.der_data)
        del nss_cert
        nss.nss_shutdown()
        subsystem_cert['data'] = data

        # format cert data for LDAP database
        lines = [data[i:i + 64] for i in range(0, len(data), 64)]
        data = string.join(lines, '\r\n') + '\r\n'

        # get cert request from local CA
        # TODO: add support for remote CA
        ca = instance.get_subsystem('ca')
        results = ca.find_cert_requests(cert=data)
        cert_request = results[-1]
        request = cert_request['request']

        # format cert request for CS.cfg
        lines = request.splitlines()
        if lines[0] == '-----BEGIN CERTIFICATE REQUEST-----':
            lines = lines[1:]
        if lines[-1] == '-----END CERTIFICATE REQUEST-----':
            lines = lines[:-1]
        request = string.join(lines, '')
        subsystem_cert['request'] = request

        # store cert data and request in CS.cfg
        subsystem.update_subsystem_cert(subsystem_cert)
        subsystem.save()

        self.print_message('Updated "%s" subsystem certificate' % cert_id)

        SubsystemCertCLI.print_subsystem_cert(subsystem_cert)
Beispiel #36
0
    def forward(self, *args, **options):

        name = args[-1]

        output_file = options.get('out')

        password = options.get('password')
        password_file = options.get('password_file')
        private_key = options.get('private_key')
        private_key_file = options.get('private_key_file')

        # don't send these parameters to server
        if 'out' in options:
            del options['out']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']
        if 'private_key' in options:
            del options['private_key']
        if 'private_key_file' in options:
            del options['private_key_file']

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect(ccache=krbV.default_context().default_ccache())

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        # initialize NSS database
        current_dbdir = paths.IPA_NSSDB_DIR
        nss.nss_init(current_dbdir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        public_key = nss_transport_cert.subject_public_key_info.public_key
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        # send retrieval request to server
        options['session_key'] = wrapped_session_key.data

        response = self.api.Command.vault_retrieve_internal(*args, **options)

        result = response['result']
        nonce = result['nonce']

        # unwrap data with session key
        wrapped_vault_data = result['vault_data']

        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT,
                                                     session_key,
                                                     iv_param)

        json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\
            + decoding_ctx.digest_final()

        vault_data = json.loads(json_vault_data)
        data = base64.b64decode(vault_data[u'data'].encode('utf-8'))

        encrypted_key = None

        if 'encrypted_key' in vault_data:
            encrypted_key = base64.b64decode(vault_data[u'encrypted_key']
                                             .encode('utf-8'))

        if vault_type == u'standard':

            pass

        elif vault_type == u'symmetric':

            salt = vault['ipavaultsalt'][0]

            # get encryption key from vault password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                password = self.obj.get_existing_password()

            # generate encryption key from password
            encryption_key = self.obj.generate_symmetric_key(password, salt)

            # decrypt data with encryption key
            data = self.obj.decrypt(data, symmetric_key=encryption_key)

        elif vault_type == u'asymmetric':

            # get encryption key with vault private key
            if private_key and private_key_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Private key specified multiple times'))

            elif private_key:
                pass

            elif private_key_file:
                private_key = validated_read('private-key-file',
                                             private_key_file,
                                             mode='rb')

            else:
                raise errors.ValidationError(
                    name='private_key',
                    error=_('Missing vault private key'))

            # decrypt encryption key with private key
            encryption_key = self.obj.decrypt(
                encrypted_key, private_key=private_key)

            # decrypt data with encryption key
            data = self.obj.decrypt(data, symmetric_key=encryption_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        if output_file:
            with open(output_file, 'w') as f:
                f.write(data)

        else:
            response['result'] = {'data': data}

        return response
Beispiel #37
0
    def renew_external_step_2(self, ca, old_cert):
        print("Importing the renewed CA certificate, please wait")

        options = self.options
        conn = api.Backend.ldap2
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError as e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError as e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)

            trust_chain = tmpdb.get_trust_chain('IPA CA')[:-1]
            for nickname in trust_chain:
                try:
                    ca_cert = tmpdb.get_cert(nickname)
                except RuntimeError:
                    break
                certstore.put_ca_cert_nss(
                    conn, api.env.basedn, ca_cert, nickname, ',,')

        dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'),
                ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
        try:
            entry = conn.get_entry(dn, ['usercertificate'])
            entry['usercertificate'] = [cert]
            conn.update_entry(entry)
        except errors.NotFound:
            entry = conn.make_entry(
                dn,
                objectclass=['top', 'pkiuser', 'nscontainer'],
                cn=[self.cert_nickname],
                usercertificate=[cert])
            conn.add_entry(entry)
        except errors.EmptyModlist:
            pass

        try:
            ca.set_renewal_master()
        except errors.NotFound:
            raise admintool.ScriptError("CA renewal master not found")

        self.resubmit_request(ca, 'ipaRetrieval')

        print("CA certificate successfully renewed")
Beispiel #38
0
    def forward(self, *args, **options):

        name = args[-1]

        data = options.get('data')
        input_file = options.get('in')

        password = options.get('password')
        password_file = options.get('password_file')

        # don't send these parameters to server
        if 'data' in options:
            del options['data']
        if 'in' in options:
            del options['in']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']

        # get data
        if data and input_file:
            raise errors.MutuallyExclusiveError(
                reason=_('Input data specified multiple times'))

        elif input_file:
            data = validated_read('in', input_file, mode='rb')

        elif not data:
            data = ''

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect(ccache=krbV.default_context().default_ccache())

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        if vault_type == u'standard':

            encrypted_key = None

        elif vault_type == u'symmetric':

            # get password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                password = self.obj.get_existing_password()

            # verify password by retrieving existing data
            opts = options.copy()
            opts['password'] = password
            try:
                self.api.Command.vault_retrieve(*args, **opts)
            except errors.NotFound:
                pass

            salt = vault['ipavaultsalt'][0]

            # generate encryption key from vault password
            encryption_key = self.obj.generate_symmetric_key(
                password, salt)

            # encrypt data with encryption key
            data = self.obj.encrypt(data, symmetric_key=encryption_key)

            encrypted_key = None

        elif vault_type == u'asymmetric':

            public_key = vault['ipavaultpublickey'][0].encode('utf-8')

            # generate encryption key
            encryption_key = base64.b64encode(os.urandom(32))

            # encrypt data with encryption key
            data = self.obj.encrypt(data, symmetric_key=encryption_key)

            # encrypt encryption key with public key
            encrypted_key = self.obj.encrypt(
                encryption_key, public_key=public_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        # initialize NSS database
        current_dbdir = paths.IPA_NSSDB_DIR
        nss.nss_init(current_dbdir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        public_key = nss_transport_cert.subject_public_key_info.public_key
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        options['session_key'] = wrapped_session_key.data

        nonce_length = nss.get_iv_length(mechanism)
        nonce = nss.generate_random(nonce_length)
        options['nonce'] = nonce

        vault_data = {}
        vault_data[u'data'] = base64.b64encode(data).decode('utf-8')

        if encrypted_key:
            vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\
                .decode('utf-8')

        json_vault_data = json.dumps(vault_data)

        # wrap vault_data with session key
        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT,
                                                     session_key,
                                                     iv_param)

        wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\
            + encoding_ctx.digest_final()

        options['vault_data'] = wrapped_vault_data

        return self.api.Command.vault_archive_internal(*args, **options)
Beispiel #39
0
if __name__ == '__main__':
    parser = optparse.OptionParser(
        "usage: %prog -f <folder with certificates> ")
    parser.add_option('-f',
                      '--folder',
                      dest='folder',
                      help="Directory that holds certificates")

    (opts, args) = parser.parse_args()
    if opts.folder is None:
        parser.error("Specify the name of directory")

    path = os.path.expanduser(opts.folder)

    certdb_dir = os.path.expanduser(config.NSS_DB_DIR)
    nss.nss_init(certdb_dir)
    certdb = nss.get_default_certdb()
    db = PinDB("pfc", "keycontinuity")

    for i in os.listdir(path):
        file = os.path.join(path, i)
        if os.path.isfile(file):
            # f = open(file).readlines()
            # f =  ''.join(f)
            try:
                a = M2Crypto.X509.load_cert(file, format=FORMAT_DER)
            except:
                # we should transform PEM encoding to DER
                cmdstr = [
                    "openssl", "x509", "-in", file, "-inform", "PEM", "-out",
                    file, "-outform", "DER"
Beispiel #40
0
 def setUp(self):
     nss.nss_init(certdir)
     nss.set_password_callback(password_callback)
     nss.pkcs12_enable_all_ciphers()
Beispiel #41
0
 def __init__(self):
     self.certdb_dir = os.path.expanduser(config.NSS_DB_DIR)
     nss.nss_init(self.certdb_dir)
     nss.enable_ocsp_checking()
     self.certdb = nss.get_default_certdb()
Beispiel #42
0
    def renew_external_step_2(self, ca, old_cert):
        print "Importing the renewed CA certificate, please wait"

        options = self.options
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(ca.dogtag_constants.ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError, e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError, e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)
Beispiel #43
0
    def forward(self, *args, **options):
        data = options.get('data')
        input_file = options.get('in')

        password = options.get('password')
        password_file = options.get('password_file')

        override_password = options.pop('override_password', False)

        # don't send these parameters to server
        if 'data' in options:
            del options['data']
        if 'in' in options:
            del options['in']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']

        # get data
        if data and input_file:
            raise errors.MutuallyExclusiveError(
                reason=_('Input data specified multiple times'))

        elif data:
            if len(data) > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="data", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})

        elif input_file:
            try:
                stat = os.stat(input_file)
            except OSError as exc:
                raise errors.ValidationError(name="in", error=_(
                    "Cannot read file '%(filename)s': %(exc)s")
                    % {'filename': input_file, 'exc': exc.args[1]})
            if stat.st_size > MAX_VAULT_DATA_SIZE:
                raise errors.ValidationError(name="in", error=_(
                    "Size of data exceeds the limit. Current vault data size "
                    "limit is %(limit)d B")
                    % {'limit': MAX_VAULT_DATA_SIZE})
            data = validated_read('in', input_file, mode='rb')

        else:
            data = ''

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect()

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        if vault_type == u'standard':

            encrypted_key = None

        elif vault_type == u'symmetric':

            # get password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                if override_password:
                    password = get_new_password()
                else:
                    password = get_existing_password()

            if not override_password:
                # verify password by retrieving existing data
                opts = options.copy()
                opts['password'] = password
                try:
                    self.api.Command.vault_retrieve(*args, **opts)
                except errors.NotFound:
                    pass

            salt = vault['ipavaultsalt'][0]

            # generate encryption key from vault password
            encryption_key = generate_symmetric_key(password, salt)

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            encrypted_key = None

        elif vault_type == u'asymmetric':

            public_key = vault['ipavaultpublickey'][0].encode('utf-8')

            # generate encryption key
            encryption_key = base64.b64encode(os.urandom(32))

            # encrypt data with encryption key
            data = encrypt(data, symmetric_key=encryption_key)

            # encrypt encryption key with public key
            encrypted_key = encrypt(encryption_key, public_key=public_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        # initialize NSS database
        nss.nss_init(api.env.nss_dir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        # pylint: disable=no-member
        public_key = nss_transport_cert.subject_public_key_info.public_key
        # pylint: enable=no-member
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        options['session_key'] = wrapped_session_key.data

        nonce_length = nss.get_iv_length(mechanism)
        nonce = nss.generate_random(nonce_length)
        options['nonce'] = nonce

        vault_data = {}
        vault_data[u'data'] = base64.b64encode(data).decode('utf-8')

        if encrypted_key:
            vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\
                .decode('utf-8')

        json_vault_data = json.dumps(vault_data)

        # wrap vault_data with session key
        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        encoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_ENCRYPT,
                                                     session_key,
                                                     iv_param)

        wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\
            + encoding_ctx.digest_final()

        options['vault_data'] = wrapped_vault_data

        return self.api.Command.vault_archive_internal(*args, **options)
Beispiel #44
0
def main():
    global options

    parser = argparse.ArgumentParser(description='certificate validation example')

    # === NSS Database Group ===
    group = parser.add_argument_group('NSS Database',
                                      'Specify & control the NSS Database')
    group.add_argument('-d', '--db-name',
                       help='NSS database name (e.g. "sql:pki")')

    group.add_argument('-P', '--db-passwd',
                       help='NSS database password')

    # === Certificate Group ===
    group = parser.add_argument_group('Certificate',
                                      'Specify how the certificate is loaded')

    group.add_argument('-f', '--file', dest='cert_filename',
                       help='read cert from file')

    group.add_argument('-F', '--input-format', choices=['pem', 'der'],
                       help='format of input cert')

    group.add_argument('-n', '--nickname', dest='cert_nickname',
                       help='load cert from NSS database by looking it up under this nickname')

    # === Validation Group ===
    group = parser.add_argument_group('Validation',
                                      'Control the validation')

    group.add_argument('-u', '--usage', dest='cert_usage', action='append', choices=list(cert_usage_map.keys()),
                           help='certificate usage flags, may be specified multiple times')
    group.add_argument('-c', '--check-sig', action='store_true', dest='check_sig',
                           help='check signature')
    group.add_argument('-C', '--no-check-sig', action='store_false', dest='check_sig',
                           help='do not check signature')
    group.add_argument('-l', '--log', action='store_true', dest='with_log',
                           help='use verify log')
    group.add_argument('-L', '--no-log', action='store_false', dest='with_log',
                           help='do not use verify log')
    group.add_argument('-a', '--check-ca', action='store_true', dest='check_ca',
                           help='check if cert is CA')
    group.add_argument('-A', '--no-check-ca', action='store_false', dest='check_ca',
                           help='do not check if cert is CA')

    # === Miscellaneous Group ===
    group = parser.add_argument_group('Miscellaneous',
                                      'Miscellaneous options')

    group.add_argument('-p', '--print-cert', action='store_true', dest='print_cert',
                       help='print the certificate in a friendly fashion')


    parser.set_defaults(db_name = 'sql:pki',
                        db_passwd = 'db_passwd',
                        input_format = 'pem',
                        check_sig = True,
                        with_log = True,
                        check_ca = True,
                        print_cert = False,
                        )

    options = parser.parse_args()

    # Process the command line arguments

    # Get usage bitmask
    if options.cert_usage:
        intended_usage = 0
        for usage in options.cert_usage:
            try:
                flag = cert_usage_map[usage]
            except KeyError:
                print("Unknown usage '%s', valid values: %s" % (usage, ', '.join(sorted(cert_usage_map.keys()))))
                return 1
            else:
                intended_usage |= flag
    else:
        # We can't use nss.certificateUsageCheckAllUsages here because
        # it's a special value of zero instead of being the bitwise OR
        # of all the certificateUsage* flags (go figure!)
        intended_usage = 0
        for usage in list(cert_usage_map.values()):
            intended_usage |= usage

    if options.cert_filename and options.cert_nickname:
        print("You may not specify both a cert filename and a nickname, only one or the other", file=sys.stderr)
        return 1

    if not options.cert_filename and not options.cert_nickname:
        print("You must specify either a cert filename or a nickname to load", file=sys.stderr)
        return 1

    # Initialize NSS.
    print(indented_output('NSS Database', options.db_name))
    print()
    nss.nss_init(options.db_name)
    certdb = nss.get_default_certdb()
    nss.set_password_callback(password_callback)

    # Load the cert
    if options.cert_filename:
        # Read the certificate as DER encoded data then initialize a Certificate from the DER data
        filename = options.cert_filename
        si = nss.read_der_from_file(filename, options.input_format.lower() == 'pem')
        # Parse the DER encoded data returning a Certificate object
        cert = nss.Certificate(si)
    else:
        try:
            cert = nss.find_cert_from_nickname(options.cert_nickname)
        except Exception as e:
            print(e)
            print('Unable to load cert nickname "%s" from database "%s"' % \
                (options.cert_nickname, options.db_name), file=sys.stderr)
            return 1

    # Dump the cert if the user wants to see it
    if options.print_cert:
        print(cert)
    else:
        print(indented_output('cert subject', cert.subject))
    print()

    # Dump the usages attached to the cert
    print(indented_output('cert has these usages', nss.cert_type_flags(cert.cert_type)))

    # Should we check if the cert is a CA cert?
    if options.check_ca:
        # CA Cert?
        is_ca, cert_type = cert.is_ca_cert(True)
        print()
        print(indented_output('is CA cert boolean', is_ca))
        print(indented_output('is CA cert returned usages', nss.cert_type_flags(cert_type)))

    print()
    print(indented_output('verifying usages for', nss.cert_usage_flags(intended_usage)))
    print()

    # Use the log or non-log variant to verify the cert
    #
    # Note: Anytime a NSPR or NSS function returns an error in python-nss it
    # raises a NSPRError exception. When an exception is raised the normal
    # return values are discarded because the flow of control continues at
    # the first except block prepared to catch the exception. Normally this
    # is what is desired because the return values would be invalid due to
    # the error. However the certificate verification functions are an
    # exception (no pun intended). An error might be returned indicating the
    # cert failed verification but you may still need access to the returned
    # usage bitmask and the log (if using the log variant). To handle this a
    # special error exception `CertVerifyError` (derived from `NSPRError`)
    # is defined which in addition to the normal NSPRError fields will also
    # contain the returned usages and optionally the CertVerifyLog
    # object. If no exception is raised these are returned as normal return
    # values.

    approved_usage = 0
    if options.with_log:
        try:
            approved_usage, log = cert.verify_with_log(certdb, options.check_sig, intended_usage, None)
        except nss_error.CertVerifyError as e:
            # approved_usage and log available in CertVerifyError exception on failure.
            print(e)
            print()
            print(indented_obj('log', e.log))
            print()
            print(indented_output('approved usages from exception', nss.cert_usage_flags(e.usages)))
            approved_usage = e.usages # Get the returned usage bitmask from the exception
        except Exception as e:
            print(e)
        else:
            print(indented_output('approved usages', nss.cert_usage_flags(approved_usage)))
            if log.count:
                print()
                print(indented_obj('log', log))
    else:
        try:
            approved_usage = cert.verify(certdb, options.check_sig, intended_usage, None)
        except nss_error.CertVerifyError as e:
            # approved_usage available in CertVerifyError exception on failure.
            print(e)
            print(indented_output('approved usages from exception', nss.cert_usage_flags(e.usages)))
            approved_usage = e.usages # Get the returned usage bitmask from the exception
        except Exception as e:
            print(e)
        else:
            print(indented_output('approved usages', nss.cert_usage_flags(approved_usage)))

    # The cert is valid if all the intended usages are in the approved usages
    valid = (intended_usage & approved_usage) == intended_usage

    print()
    if valid:
        print(indented_output('SUCCESS: cert is approved for', nss.cert_usage_flags(intended_usage)))
        return 0
    else:
        print(indented_output('FAIL: cert not approved for', nss.cert_usage_flags(intended_usage ^ approved_usage)))
        return 1
Beispiel #45
0
 def test_ssl(self):
     request = "foo"
     nss.nss_init(db_name)
     reply = client(request)
     nss.nss_shutdown()
     self.assertEqual("{%s}" % request, reply)
Beispiel #46
0
from db.database import PinDB
from conf import config


if __name__ == "__main__":
    parser = optparse.OptionParser("usage: %prog -f <folder with certificates> ")
    parser.add_option("-f", "--folder", dest="folder", help="Directory that holds certificates")

    (opts, args) = parser.parse_args()
    if opts.folder is None:
        parser.error("Specify the name of directory")

    path = os.path.expanduser(opts.folder)

    certdb_dir = os.path.expanduser(config.NSS_DB_DIR)
    nss.nss_init(certdb_dir)
    certdb = nss.get_default_certdb()
    db = PinDB("pfc", "keycontinuity")

    for i in os.listdir(path):
        file = os.path.join(path, i)
        if os.path.isfile(file):
            # f = open(file).readlines()
            # f =  ''.join(f)
            try:
                a = M2Crypto.X509.load_cert(file, format=FORMAT_DER)
            except:
                # we should transform PEM encoding to DER
                cmdstr = ["openssl", "x509", "-in", file, "-inform", "PEM", "-out", file, "-outform", "DER"]
                subprocess.call(cmdstr)
                a = M2Crypto.X509.load_cert(file, format=FORMAT_DER)
def main():
    # Command line argument processing
    parser = optparse.OptionParser()

    parser.set_defaults(dbdir = '/etc/pki/nssdb',
                        db_passwd = 'db_passwd',
                        input_format = 'pem',
                        check_sig = True,
                        print_cert = False,
                        with_log = True,
                        check_ca = True,
                        )

    param_group = optparse.OptionGroup(parser, 'NSS Database',
                                       'Specify & control the NSS Database')

    param_group.add_option('-d', '--dbdir', dest='dbdir',
                           help='NSS database directory, default="%default"')
    param_group.add_option('-P', '--db-passwd', dest='db_passwd',
                           help='NSS database password, default="%default"')

    parser.add_option_group(param_group)

    param_group = optparse.OptionGroup(parser, 'Certificate',
                                       'Specify how the certificate is loaded')

    param_group.add_option('-f', '--file', dest='cert_filename',
                           help='read cert from file')
    param_group.add_option('--format', dest='input_format', choices=['pem', 'der'],
                           help='import format for certificate (der|pem) default="%default"')
    param_group.add_option('-n', '--nickname', dest='cert_nickname',
                           help='load cert from NSS database by looking it up under this nickname')


    parser.add_option_group(param_group)

    param_group = optparse.OptionGroup(parser, 'Validation',
                                       'Control the validation')

    param_group.add_option('-u', '--usage', dest='cert_usage', action='append', choices=cert_usage_map.keys(),
                           help='may be specified multiple times, default="CheckAllUsages", may be one of: %s' % ', '.join(sorted(cert_usage_map.keys())))
    param_group.add_option('-c', '--check-sig', action='store_true', dest='check_sig',
                           help='check signature default=%default')
    param_group.add_option('-C', '--no-check-sig', action='store_false', dest='check_sig',
                           help='check signature')
    param_group.add_option('-l', '--log', action='store_true', dest='with_log',
                           help='use verify log, default=%default')
    param_group.add_option('-L', '--no-log', action='store_false', dest='with_log',
                           help='use verify log, default=%default')
    param_group.add_option('-a', '--check-ca', action='store_true', dest='check_ca',
                           help='check if cert is CA, default=%default')
    param_group.add_option('-A', '--no-check-ca', action='store_false', dest='check_ca',
                           help='check if cert is CA, default=%default')

    parser.add_option_group(param_group)

    param_group = optparse.OptionGroup(parser, 'Miscellaneous',
                                       'Miscellaneous options')

    param_group.add_option('-p', '--print-cert', action='store_true', dest='print_cert',
                           help='print the certificate in a friendly fashion, default=%default')

    parser.add_option_group(param_group)

    options, args = parser.parse_args()

    # Process the command line arguments

    # Get usage bitmask
    if options.cert_usage:
        intended_usage = 0
        for usage in options.cert_usage:
            try:
                flag = cert_usage_map[usage]
            except KeyError:
                print "Unknown usage '%s', valid values: %s" % (usage, ', '.join(sorted(cert_usage_map.keys())))
                return 1
            else:
                intended_usage |= flag
    else:
        # We can't use nss.certificateUsageCheckAllUsages here because
        # it's a special value of zero instead of being the bitwise OR
        # of all the certificateUsage* flags (go figure!)
        intended_usage = 0
        for usage in cert_usage_map.values():
            intended_usage |= usage

    if options.cert_filename and options.cert_nickname:
        print >>sys.stderr, "You may not specify both a cert filename and a nickname, only one or the other"
        return 1

    if not options.cert_filename and not options.cert_nickname:
        print >>sys.stderr, "You must specify either a cert filename or a nickname to load"
        return 1

    # Initialize NSS.
    print indented_output('NSS Database', options.dbdir)
    print
    nss.nss_init(options.dbdir)
    certdb = nss.get_default_certdb()
    nss.set_password_callback(password_callback)

    # Load the cert
    if options.cert_filename:
        # Read the certificate as DER encoded data then initialize a Certificate from the DER data
        filename = options.cert_filename
        si = nss.read_der_from_file(filename, options.input_format.lower() == 'pem')
        # Parse the DER encoded data returning a Certificate object
        cert = nss.Certificate(si)
    else:
        try:
            cert = nss.find_cert_from_nickname(options.cert_nickname)
        except Exception, e:
            print e
            print >>sys.stderr, 'Unable to load cert nickname "%s" from database "%s"' % \
                (options.cert_nickname, options.dbdir)
            return 1
Beispiel #48
0
    def forward(self, *args, **options):
        output_file = options.get('out')

        password = options.get('password')
        password_file = options.get('password_file')
        private_key = options.get('private_key')
        private_key_file = options.get('private_key_file')

        # don't send these parameters to server
        if 'out' in options:
            del options['out']
        if 'password' in options:
            del options['password']
        if 'password_file' in options:
            del options['password_file']
        if 'private_key' in options:
            del options['private_key']
        if 'private_key_file' in options:
            del options['private_key_file']

        if self.api.env.in_server:
            backend = self.api.Backend.ldap2
        else:
            backend = self.api.Backend.rpcclient
        if not backend.isconnected():
            backend.connect()

        # retrieve vault info
        vault = self.api.Command.vault_show(*args, **options)['result']

        vault_type = vault['ipavaulttype'][0]

        # initialize NSS database
        nss.nss_init(api.env.nss_dir)

        # retrieve transport certificate
        config = self.api.Command.vaultconfig_show()['result']
        transport_cert_der = config['transport_cert']
        nss_transport_cert = nss.Certificate(transport_cert_der)

        # generate session key
        mechanism = nss.CKM_DES3_CBC_PAD
        slot = nss.get_best_slot(mechanism)
        key_length = slot.get_best_key_length(mechanism)
        session_key = slot.key_gen(mechanism, None, key_length)

        # wrap session key with transport certificate
        # pylint: disable=no-member
        public_key = nss_transport_cert.subject_public_key_info.public_key
        # pylint: enable=no-member
        wrapped_session_key = nss.pub_wrap_sym_key(mechanism,
                                                   public_key,
                                                   session_key)

        # send retrieval request to server
        options['session_key'] = wrapped_session_key.data

        response = self.api.Command.vault_retrieve_internal(*args, **options)

        result = response['result']
        nonce = result['nonce']

        # unwrap data with session key
        wrapped_vault_data = result['vault_data']

        iv_si = nss.SecItem(nonce)
        iv_param = nss.param_from_iv(mechanism, iv_si)

        decoding_ctx = nss.create_context_by_sym_key(mechanism,
                                                     nss.CKA_DECRYPT,
                                                     session_key,
                                                     iv_param)

        json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\
            + decoding_ctx.digest_final()

        vault_data = json.loads(json_vault_data.decode('utf-8'))
        data = base64.b64decode(vault_data[u'data'].encode('utf-8'))

        encrypted_key = None

        if 'encrypted_key' in vault_data:
            encrypted_key = base64.b64decode(vault_data[u'encrypted_key']
                                             .encode('utf-8'))

        if vault_type == u'standard':

            pass

        elif vault_type == u'symmetric':

            salt = vault['ipavaultsalt'][0]

            # get encryption key from vault password
            if password and password_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Password specified multiple times'))

            elif password:
                pass

            elif password_file:
                password = validated_read('password-file',
                                          password_file,
                                          encoding='utf-8')
                password = password.rstrip('\n')

            else:
                password = get_existing_password()

            # generate encryption key from password
            encryption_key = generate_symmetric_key(password, salt)

            # decrypt data with encryption key
            data = decrypt(data, symmetric_key=encryption_key)

        elif vault_type == u'asymmetric':

            # get encryption key with vault private key
            if private_key and private_key_file:
                raise errors.MutuallyExclusiveError(
                    reason=_('Private key specified multiple times'))

            elif private_key:
                pass

            elif private_key_file:
                private_key = validated_read('private-key-file',
                                             private_key_file,
                                             mode='rb')

            else:
                raise errors.ValidationError(
                    name='private_key',
                    error=_('Missing vault private key'))

            # decrypt encryption key with private key
            encryption_key = decrypt(encrypted_key, private_key=private_key)

            # decrypt data with encryption key
            data = decrypt(data, symmetric_key=encryption_key)

        else:
            raise errors.ValidationError(
                name='vault_type',
                error=_('Invalid vault type'))

        if output_file:
            with open(output_file, 'w') as f:
                f.write(data)

        else:
            response['result'] = {'data': data}

        return response
Beispiel #49
0
        "help",
        "certdir=",
        "hostname=",
        "port=",
    ])
except getopt.GetoptError:
    # print help information and exit:
    usage()
    sys.exit(2)

for o, a in opts:
    if o in ("-d", "--certdir"):
        certdir = a
    if o in ("-h", "--hostname"):
        hostname = a
    if o in ("-p", "--port"):
        port = int(a)
    if o in ("-H", "--help"):
        usage()
        sys.exit()

# Perform basic configuration and setup
try:
    nss.nss_init(certdir)
    ssl.set_domestic_policy()
except Exception, e:
    print >> sys.stderr, e.strerror
    sys.exit(1)

client()
Beispiel #50
0
def main():
    global options

    parser = argparse.ArgumentParser(
        description='certificate validation example')

    # === NSS Database Group ===
    group = parser.add_argument_group('NSS Database',
                                      'Specify & control the NSS Database')
    group.add_argument('-d',
                       '--db-name',
                       help='NSS database name (e.g. "sql:pki")')

    group.add_argument('-P', '--db-passwd', help='NSS database password')

    # === Certificate Group ===
    group = parser.add_argument_group('Certificate',
                                      'Specify how the certificate is loaded')

    group.add_argument('-f',
                       '--file',
                       dest='cert_filename',
                       help='read cert from file')

    group.add_argument('-F',
                       '--input-format',
                       choices=['pem', 'der'],
                       help='format of input cert')

    group.add_argument(
        '-n',
        '--nickname',
        dest='cert_nickname',
        help='load cert from NSS database by looking it up under this nickname'
    )

    # === Validation Group ===
    group = parser.add_argument_group('Validation', 'Control the validation')

    group.add_argument(
        '-u',
        '--usage',
        dest='cert_usage',
        action='append',
        choices=list(cert_usage_map.keys()),
        help='certificate usage flags, may be specified multiple times')
    group.add_argument('-c',
                       '--check-sig',
                       action='store_true',
                       dest='check_sig',
                       help='check signature')
    group.add_argument('-C',
                       '--no-check-sig',
                       action='store_false',
                       dest='check_sig',
                       help='do not check signature')
    group.add_argument('-l',
                       '--log',
                       action='store_true',
                       dest='with_log',
                       help='use verify log')
    group.add_argument('-L',
                       '--no-log',
                       action='store_false',
                       dest='with_log',
                       help='do not use verify log')
    group.add_argument('-a',
                       '--check-ca',
                       action='store_true',
                       dest='check_ca',
                       help='check if cert is CA')
    group.add_argument('-A',
                       '--no-check-ca',
                       action='store_false',
                       dest='check_ca',
                       help='do not check if cert is CA')

    # === Miscellaneous Group ===
    group = parser.add_argument_group('Miscellaneous', 'Miscellaneous options')

    group.add_argument('-p',
                       '--print-cert',
                       action='store_true',
                       dest='print_cert',
                       help='print the certificate in a friendly fashion')

    parser.set_defaults(
        db_name='sql:pki',
        db_passwd='db_passwd',
        input_format='pem',
        check_sig=True,
        with_log=True,
        check_ca=True,
        print_cert=False,
    )

    options = parser.parse_args()

    # Process the command line arguments

    # Get usage bitmask
    if options.cert_usage:
        intended_usage = 0
        for usage in options.cert_usage:
            try:
                flag = cert_usage_map[usage]
            except KeyError:
                print("Unknown usage '%s', valid values: %s" %
                      (usage, ', '.join(sorted(cert_usage_map.keys()))))
                return 1
            else:
                intended_usage |= flag
    else:
        # We can't use nss.certificateUsageCheckAllUsages here because
        # it's a special value of zero instead of being the bitwise OR
        # of all the certificateUsage* flags (go figure!)
        intended_usage = 0
        for usage in list(cert_usage_map.values()):
            intended_usage |= usage

    if options.cert_filename and options.cert_nickname:
        print(
            "You may not specify both a cert filename and a nickname, only one or the other",
            file=sys.stderr)
        return 1

    if not options.cert_filename and not options.cert_nickname:
        print("You must specify either a cert filename or a nickname to load",
              file=sys.stderr)
        return 1

    # Initialize NSS.
    print(indented_output('NSS Database', options.db_name))
    print()
    nss.nss_init(options.db_name)
    certdb = nss.get_default_certdb()
    nss.set_password_callback(password_callback)

    # Load the cert
    if options.cert_filename:
        # Read the certificate as DER encoded data then initialize a Certificate from the DER data
        filename = options.cert_filename
        si = nss.read_der_from_file(filename,
                                    options.input_format.lower() == 'pem')
        # Parse the DER encoded data returning a Certificate object
        cert = nss.Certificate(si)
    else:
        try:
            cert = nss.find_cert_from_nickname(options.cert_nickname)
        except Exception as e:
            print(e)
            print('Unable to load cert nickname "%s" from database "%s"' % \
                (options.cert_nickname, options.db_name), file=sys.stderr)
            return 1

    # Dump the cert if the user wants to see it
    if options.print_cert:
        print(cert)
    else:
        print(indented_output('cert subject', cert.subject))
    print()

    # Dump the usages attached to the cert
    print(
        indented_output('cert has these usages',
                        nss.cert_type_flags(cert.cert_type)))

    # Should we check if the cert is a CA cert?
    if options.check_ca:
        # CA Cert?
        is_ca, cert_type = cert.is_ca_cert(True)
        print()
        print(indented_output('is CA cert boolean', is_ca))
        print(
            indented_output('is CA cert returned usages',
                            nss.cert_type_flags(cert_type)))

    print()
    print(
        indented_output('verifying usages for',
                        nss.cert_usage_flags(intended_usage)))
    print()

    # Use the log or non-log variant to verify the cert
    #
    # Note: Anytime a NSPR or NSS function returns an error in python-nss it
    # raises a NSPRError exception. When an exception is raised the normal
    # return values are discarded because the flow of control continues at
    # the first except block prepared to catch the exception. Normally this
    # is what is desired because the return values would be invalid due to
    # the error. However the certificate verification functions are an
    # exception (no pun intended). An error might be returned indicating the
    # cert failed verification but you may still need access to the returned
    # usage bitmask and the log (if using the log variant). To handle this a
    # special error exception `CertVerifyError` (derived from `NSPRError`)
    # is defined which in addition to the normal NSPRError fields will also
    # contain the returned usages and optionally the CertVerifyLog
    # object. If no exception is raised these are returned as normal return
    # values.

    approved_usage = 0
    if options.with_log:
        try:
            approved_usage, log = cert.verify_with_log(certdb,
                                                       options.check_sig,
                                                       intended_usage, None)
        except nss_error.CertVerifyError as e:
            # approved_usage and log available in CertVerifyError exception on failure.
            print(e)
            print()
            print(indented_obj('log', e.log))
            print()
            print(
                indented_output('approved usages from exception',
                                nss.cert_usage_flags(e.usages)))
            approved_usage = e.usages  # Get the returned usage bitmask from the exception
        except Exception as e:
            print(e)
        else:
            print(
                indented_output('approved usages',
                                nss.cert_usage_flags(approved_usage)))
            if log.count:
                print()
                print(indented_obj('log', log))
    else:
        try:
            approved_usage = cert.verify(certdb, options.check_sig,
                                         intended_usage, None)
        except nss_error.CertVerifyError as e:
            # approved_usage available in CertVerifyError exception on failure.
            print(e)
            print(
                indented_output('approved usages from exception',
                                nss.cert_usage_flags(e.usages)))
            approved_usage = e.usages  # Get the returned usage bitmask from the exception
        except Exception as e:
            print(e)
        else:
            print(
                indented_output('approved usages',
                                nss.cert_usage_flags(approved_usage)))

    # The cert is valid if all the intended usages are in the approved usages
    valid = (intended_usage & approved_usage) == intended_usage

    print()
    if valid:
        print(
            indented_output('SUCCESS: cert is approved for',
                            nss.cert_usage_flags(intended_usage)))
        return 0
    else:
        print(
            indented_output(
                'FAIL: cert not approved for',
                nss.cert_usage_flags(intended_usage ^ approved_usage)))
        return 1
Beispiel #51
0
    def renew_external_step_2(self, ca, old_cert):
        print "Importing the renewed CA certificate, please wait"

        options = self.options
        cert_file, ca_file = installutils.load_external_cert(
            options.external_cert_files, x509.subject_base())

        nss_cert = None
        nss.nss_init(ca.dogtag_constants.ALIAS_DIR)
        try:
            nss_cert = x509.load_certificate(old_cert, x509.DER)
            subject = nss_cert.subject
            der_subject = x509.get_der_subject(old_cert, x509.DER)
            #pylint: disable=E1101
            pkinfo = nss_cert.subject_public_key_info.format()
            #pylint: enable=E1101

            nss_cert = x509.load_certificate_from_file(cert_file.name)
            cert = nss_cert.der_data
            if nss_cert.subject != subject:
                raise admintool.ScriptError(
                    "Subject name mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            if x509.get_der_subject(cert, x509.DER) != der_subject:
                raise admintool.ScriptError(
                    "Subject name encoding mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: disable=E1101
            if nss_cert.subject_public_key_info.format() != pkinfo:
                raise admintool.ScriptError(
                    "Subject public key info mismatch (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)")
            #pylint: enable=E1101
        finally:
            del nss_cert
            nss.nss_shutdown()

        with certs.NSSDatabase() as tmpdb:
            pw = ipautil.write_tmp_file(ipautil.ipa_generate_password())
            tmpdb.create_db(pw.name)
            tmpdb.add_cert(old_cert, 'IPA CA', 'C,,')

            try:
                tmpdb.add_cert(cert, 'IPA CA', 'C,,')
            except ipautil.CalledProcessError, e:
                raise admintool.ScriptError(
                    "Not compatible with the current CA certificate: %s" % e)

            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
            for ca_cert in ca_certs:
                tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
            del ca_certs
            del ca_cert

            try:
                tmpdb.verify_ca_cert_validity('IPA CA')
            except ValueError, e:
                raise admintool.ScriptError(
                    "Not a valid CA certificate: %s (visit "
                    "http://www.freeipa.org/page/Troubleshooting for "
                    "troubleshooting guide)" % e)