Beispiel #1
0
    def enroll(self, csr):
        """ enroll certificate from via MS certsrv """
        self.logger.debug('CAhandler.enroll({0})'.format(self.template))
        cert_bundle = None
        error = None
        cert_raw = None

        if self.host and self.user and self.password and self.template:
            # setup certserv
            ca_server = Certsrv(self.host, self.user, self.password, self.auth_method, self.ca_bundle, proxies=self.proxy)

            # check connection and credentials
            auth_check = self._check_credentials(ca_server)
            if auth_check:
                # recode csr
                csr = textwrap.fill(b64_url_recode(self.logger, csr), 64) + '\n'

                # get ca_chain
                try:
                    ca_pkcs7 = convert_byte_to_string(ca_server.get_chain(encoding='b64'))
                    ca_pem = self._pkcs7_to_pem(ca_pkcs7)
                    # replace crlf with lf
                    # ca_pem = ca_pem.replace('\r\n', '\n')
                except BaseException as err_:
                    ca_pem = None
                    self.logger.error('ca_server.get_chain() failed with error: {0}'.format(err_))

                try:
                    cert_raw = convert_byte_to_string(ca_server.get_cert(csr, self.template))
                    # replace crlf with lf
                    cert_raw = cert_raw.replace('\r\n', '\n')
                except BaseException as err_:
                    cert_raw = None
                    self.logger.error('ca_server.get_cert() failed with error: {0}'.format(err_))

                if ca_pem and cert_raw:
                    cert_bundle = cert_raw + ca_pem
                    cert_raw = cert_raw.replace('-----BEGIN CERTIFICATE-----\n', '')
                    cert_raw = cert_raw.replace('-----END CERTIFICATE-----\n', '')
                    cert_raw = cert_raw.replace('\n', '')
                else:
                    self.logger.error('cert bundling failed')
                    error = 'cert bundling failed'
            else:
                self.logger.error('Connection or Credentialcheck failed')
                error = 'Connection or Credentialcheck failed.'
        else:
            self.logger.error('Config incomplete')
            error = 'Config incomplete'

        self.logger.debug('Certificate.enroll() ended')
        return(error, cert_bundle, cert_raw, None)
Beispiel #2
0
    def _pkcs7_to_pem(self, pkcs7_content, outform='string'):
        """ convert pkcs7 to pem """
        self.logger.debug('CAhandler._pkcs7_to_pem()')
        for filetype in (crypto.FILETYPE_PEM, crypto.FILETYPE_ASN1):
            try:
                pkcs7 = crypto.load_pkcs7_data(filetype, pkcs7_content)
                break
            except BaseException as err:
                self.logger.error('CAhandler._pkcs7_to_pem() failed with error: {0}'.format(err))
                pkcs7 = None

        cert_pem_list = []
        if pkcs7:
            # convert cert pkcs#7 to pem
            cert_list = _get_certificates(pkcs7)
            for cert in cert_list:
                cert_pem_list.append(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)))

        # define output format
        if outform == 'string':
            result = ''.join(cert_pem_list)
        elif outform == 'list':
            result = cert_pem_list
        else:
            result = None

        self.logger.debug('Certificate._pkcs7_to_pem() ended')
        return result
Beispiel #3
0
    def _payload_process(self, payload):
        """ process payload """
        self.logger.debug('Trigger._payload_process()')
        with self.cahandler(self.debug, self.logger) as ca_handler:
            if payload:
                (error, cert_bundle, cert_raw) = ca_handler.trigger(payload)
                if cert_bundle and cert_raw:
                    # returned cert_raw is in dear format, convert to pem to lookup the pubic key
                    cert_pem = convert_byte_to_string(
                        cert_der2pem(b64_decode(self.logger, cert_raw)))

                    # lookup certificate_name by comparing public keys
                    cert_name_list = self._certname_lookup(cert_pem)

                    if cert_name_list:
                        for cert in cert_name_list:
                            data_dic = {
                                'cert': cert_bundle,
                                'name': cert['cert_name'],
                                'cert_raw': cert_raw
                            }
                            try:
                                self.dbstore.certificate_add(data_dic)
                            except BaseException as err_:
                                self.logger.critical(
                                    'acme2certifier database error in trigger._payload_process() add: {0}'
                                    .format(err_))
                            if 'order_name' in cert and cert['order_name']:
                                try:
                                    # update order status to 5 (valid)
                                    self.dbstore.order_update({
                                        'name':
                                        cert['order_name'],
                                        'status':
                                        'valid'
                                    })
                                except BaseException as err_:
                                    self.logger.critical(
                                        'acme2certifier database error in trigger._payload_process() upd: {0}'
                                        .format(err_))
                        code = 200
                        message = 'OK'
                        detail = None
                    else:
                        code = 400
                        message = 'certificate_name lookup failed'
                        detail = None
                else:
                    code = 400
                    message = error
                    detail = None
            else:
                code = 400
                message = 'payload malformed'
                detail = None

        self.logger.debug(
            'Trigger._payload_process() ended with: {0} {1}'.format(
                code, message))
        return (code, message, detail)
Beispiel #4
0
    def parse(self, content):
        """ new oder request """
        self.logger.debug('Trigger.parse()')

        # convert to json structure
        try:
            payload = json.loads(convert_byte_to_string(content))
        except BaseException:
            payload = {}

        if 'payload' in payload:
            if payload['payload']:
                (code, message,
                 detail) = self._payload_process(payload['payload'])
            else:
                code = 400
                message = 'malformed'
                detail = 'payload empty'
        else:
            code = 400
            message = 'malformed'
            detail = 'payload missing'
        response_dic = {}
        # check message

        # prepare/enrich response
        response_dic['header'] = {}
        response_dic['code'] = code
        response_dic['data'] = {'status': code, 'message': message}
        if detail:
            response_dic['data']['detail'] = detail

        self.logger.debug('Trigger.parse() returns: {0}'.format(
            json.dumps(response_dic)))
        return response_dic
    def _extension_list_generate(self, template_dic, cert, ca_cert, csr_extensions_list):
        """ set extension list """
        self.logger.debug('CAhandler._extension_list_generate()')

        csr_extensions_dic = {}
        for ext in csr_extensions_list:
            csr_extensions_dic[convert_byte_to_string(ext.get_short_name())] = ext

        if template_dic:
            extension_list = [
                crypto.X509Extension(convert_string_to_byte('subjectKeyIdentifier'), False, convert_string_to_byte('hash'), subject=cert),
                crypto.X509Extension(convert_string_to_byte('authorityKeyIdentifier'), False, convert_string_to_byte('keyid:always'), issuer=ca_cert),
            ]

            # key_usage
            (kuc, ku_string) = self._keyusage_generate(template_dic, csr_extensions_dic)
            extension_list.append(crypto.X509Extension(convert_string_to_byte('keyUsage'), kuc, convert_string_to_byte(ku_string)))

            # extended key_usage
            (ekuc, eku_string) = self._extended_keyusage_generate(template_dic, csr_extensions_dic)
            if eku_string:
                extension_list.append(crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), ekuc, convert_string_to_byte(eku_string)))

            # add cdp
            if 'crlDist' in template_dic and template_dic['crlDist']:
                extension_list.append(crypto.X509Extension(convert_string_to_byte('crlDistributionPoints'), False, convert_string_to_byte(template_dic['crlDist'])))

            # add basicConstraints
            if 'ca' in template_dic:
                if 'bcCritical' in template_dic:
                    try:
                        bcc = bool(int(template_dic['bcCritical']))
                    except BaseException:
                        bcc = False
                else:
                    bcc = False
                if template_dic['ca'] == '1':
                    extension_list.append(crypto.X509Extension(convert_string_to_byte('basicConstraints'), bcc, convert_string_to_byte('CA:TRUE')))
                elif template_dic['ca'] == '2':
                    extension_list.append(crypto.X509Extension(convert_string_to_byte('basicConstraints'), bcc, convert_string_to_byte('CA:FALSE')))

        else:
            default_extension_list = [
                crypto.X509Extension(convert_string_to_byte('subjectKeyIdentifier'), False, convert_string_to_byte('hash'), subject=cert),
                crypto.X509Extension(convert_string_to_byte('authorityKeyIdentifier'), False, convert_string_to_byte('keyid:always'), issuer=ca_cert),
                crypto.X509Extension(convert_string_to_byte('keyUsage'), True, convert_string_to_byte('digitalSignature,keyEncipherment')),
                crypto.X509Extension(convert_string_to_byte('basicConstraints'), True, convert_string_to_byte('CA:FALSE')),
                crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('serverAuth')),
                # crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('clientAuth,serverAuth')),
            ]
            extension_list = default_extension_list

        # add subjectAltName(s)
        if 'subjectAltName' in csr_extensions_dic:
            self.logger.debug('CAhandler._extension_list_generate(): adding subAltNames: {0}'.format(csr_extensions_dic['subjectAltName'].__str__()))
            extension_list.append(csr_extensions_dic['subjectAltName'])

        self.logger.debug('CAhandler._extension_list_generate() ended')
        return extension_list
    def _pemcertchain_generate(self, ee_cert, issuer_cert):
        """ build pem chain """
        self.logger.debug('CAhandler._pemcertchain_generate()')

        if issuer_cert:
            pem_chain = '{0}{1}'.format(ee_cert, issuer_cert)
        else:
            pem_chain = ee_cert

        for cert in self.ca_cert_chain_list:
            cert_dic = self._cert_search('items.name', cert)
            if cert_dic and 'cert' in cert_dic:
                ca_cert = crypto.load_certificate(crypto.FILETYPE_ASN1, b64_decode(self.logger, cert_dic['cert']))
                pem_chain = '{0}{1}'.format(pem_chain, convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, ca_cert)))

        self.logger.debug('CAhandler._pemcertchain_generate() ended')
        return pem_chain
    def enroll(self, csr):
        """enroll certificate via MS-WCCE"""
        self.logger.debug("CAhandler.enroll({0})".format(self.template))
        cert_bundle = None
        error = None
        cert_raw = None

        if not (self.host and self.user and self.password and self.template):
            self.logger.error("Config incomplete")
            return ("Config incomplete", None, None, None)

        # create request
        request = self.request_create()

        # recode csr
        csr = build_pem_file(self.logger, None, csr, 64, True)

        # TODO: currently getting certificate chain is not supported
        ca_pem = self._file_load(self.ca_bundle)

        try:
            # request certificate
            cert_raw = convert_byte_to_string(
                request.get_cert(convert_string_to_byte(csr))
            )
            # replace crlf with lf
            cert_raw = cert_raw.replace("\r\n", "\n")
        except Exception as err_:
            cert_raw = None
            self.logger.error("ca_server.get_cert() failed with error: {0}".format(err_))

        if cert_raw:
            if ca_pem:
                cert_bundle = cert_raw + ca_pem
            else:
                cert_bundle = cert_raw

            cert_raw = cert_raw.replace("-----BEGIN CERTIFICATE-----\n", "")
            cert_raw = cert_raw.replace("-----END CERTIFICATE-----\n", "")
            cert_raw = cert_raw.replace("\n", "")
        else:
            self.logger.error("cert bundling failed")
            error = "cert bundling failed"

        self.logger.debug("Certificate.enroll() ended")
        return (error, cert_bundle, cert_raw, None)
    def enroll(self, csr):
        """ enroll certificate """
        self.logger.debug('CAhandler.enroll()')

        cert_bundle = None
        cert_raw = None

        error = self._config_check()

        if not error:
            try:
                # check CN and SAN against black/whitlist
                (result, enforce_cn) = self._csr_check(csr)

                if result:
                    # prepare the CSR
                    csr = build_pem_file(self.logger, None, b64_url_recode(self.logger, csr), None, True)

                    # load ca cert and key
                    (ca_key, ca_cert) = self._ca_load()

                    # load certificate_profile (if applicable)
                    if self.openssl_conf:
                        cert_extension_dic = self._certificate_extensions_load()
                    else:
                        cert_extension_dic = []

                    # creating a rest form CSR
                    req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr)
                    subject = req.get_subject()
                    if self.cn_enforce and enforce_cn:
                        self.logger.info('CAhandler.enroll(): overwrite CN with {0}'.format(enforce_cn))
                        setattr(subject, 'CN', enforce_cn)

                    # sign csr
                    cert = crypto.X509()
                    cert.gmtime_adj_notBefore(0)
                    cert.gmtime_adj_notAfter(self.cert_validity_days * 86400)
                    cert.set_issuer(ca_cert.get_subject())
                    cert.set_subject(subject)
                    cert.set_pubkey(req.get_pubkey())
                    cert.set_serial_number(uuid.uuid4().int)
                    cert.set_version(2)
                    cert.add_extensions(req.get_extensions())

                    default_extension_list = [
                        crypto.X509Extension(convert_string_to_byte('subjectKeyIdentifier'), False, convert_string_to_byte('hash'), subject=cert),
                        crypto.X509Extension(convert_string_to_byte('authorityKeyIdentifier'), False, convert_string_to_byte('keyid:always'), issuer=ca_cert),
                        crypto.X509Extension(convert_string_to_byte('basicConstraints'), True, convert_string_to_byte('CA:FALSE')),
                        crypto.X509Extension(convert_string_to_byte('extendedKeyUsage'), False, convert_string_to_byte('clientAuth,serverAuth')),
                    ]

                    if cert_extension_dic:
                        try:
                            cert.add_extensions(self._certificate_extensions_add(cert_extension_dic, cert, ca_cert))
                        except BaseException as err_:
                            self.logger.error('CAhandler.enroll() error while loading extensions form file. Use default set.\nerror: {0}'.format(err_))
                            cert.add_extensions(default_extension_list)
                    else:
                        # add keyUsage if it does not exist in CSR
                        ku_is_in = False
                        for ext in req.get_extensions():
                            if convert_byte_to_string(ext.get_short_name()) == 'keyUsage':
                                ku_is_in = True
                        if not ku_is_in:
                            default_extension_list.append(crypto.X509Extension(convert_string_to_byte('keyUsage'), True, convert_string_to_byte('digitalSignature,keyEncipherment')))

                        # add default extensions
                        cert.add_extensions(default_extension_list)

                    cert.sign(ca_key, 'sha256')

                    # store certifiate
                    self._certificate_store(cert)
                    # create bundle and raw cert
                    cert_bundle = self._pemcertchain_generate(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)), open(self.issuer_dict['issuing_ca_cert']).read())
                    cert_raw = convert_byte_to_string(base64.b64encode(crypto.dump_certificate(crypto.FILETYPE_ASN1, cert)))
                else:
                    error = 'urn:ietf:params:acme:badCSR'

            except BaseException as err:
                self.logger.error('CAhandler.enroll() error: {0}'.format(err))
                error = 'Unknown exception'

        self.logger.debug('CAhandler.enroll() ended')
        return(error, cert_bundle, cert_raw, None)
    def enroll(self, csr):
        """ enroll certificate  """
        # pylint: disable=R0914
        self.logger.debug('CAhandler.enroll()')

        cert_bundle = None
        cert_raw = None
        error = self._config_check()

        if not error:
            request_name = self._requestname_get(csr)
            if request_name:
                # import CSR to database
                _csr_info = self._csr_import(csr, request_name)

                # prepare the CSR to be signed
                csr = build_pem_file(self.logger, None, b64_url_recode(self.logger, csr), None, True)

                # load ca cert and key
                (ca_key, ca_cert, ca_id) = self._ca_load()

                if ca_key and ca_cert and ca_id:
                    # load request
                    req = crypto.load_certificate_request(crypto.FILETYPE_PEM, csr)

                    # copy cn of request
                    subject = req.get_subject()
                    # rewrite CN if required
                    if not subject.CN:
                        self.logger.info('rewrite CN to {0}'.format(request_name))
                        subject.CN = request_name

                    # create certificate object
                    cert = crypto.X509()
                    cert.set_pubkey(req.get_pubkey())
                    cert.set_version(2)
                    cert.set_serial_number(uuid.uuid4().int & (1<<63)-1)
                    cert.set_issuer(ca_cert.get_subject())

                    # load template if configured
                    if self.template_name:
                        (dn_dic, template_dic) = self._template_load()
                    else:
                        dn_dic = {}
                        template_dic = {}

                    # set cert_validity
                    if 'validity' in template_dic:
                        self.logger.info('take validity from template: {0}'.format(template_dic['validity']))
                        # take validity from template
                        cert_validity = template_dic['validity']
                    else:
                        cert_validity = self.cert_validity_days
                    cert.gmtime_adj_notBefore(0)
                    cert.gmtime_adj_notAfter(cert_validity * 86400)

                    # get extension list from CSR
                    csr_extensions_list = req.get_extensions()
                    extension_list = self._extension_list_generate(template_dic, cert, ca_cert, csr_extensions_list)

                    # add extensions (copy from CSR and take the ones we constructed)
                    # cert.add_extensions(csr_extensions_list)
                    cert.add_extensions(extension_list)

                    if dn_dic:
                        self.logger.info('modify subject with template data')
                        subject = self._subject_modify(subject, dn_dic)
                    cert.set_subject(subject)

                    # sign csr
                    cert.sign(ca_key, 'sha256')
                    serial = cert.get_serial_number()

                    # get hsshes
                    issuer_hash = ca_cert.subject_name_hash() & 0x7fffffff
                    name_hash = cert.subject_name_hash() & 0x7fffffff

                    # store certificate
                    self._store_cert(ca_id, request_name, '{:X}'.format(serial), convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert))), name_hash, issuer_hash)

                    cert_bundle = self._pemcertchain_generate(convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, cert)), convert_byte_to_string(crypto.dump_certificate(crypto.FILETYPE_PEM, ca_cert)))
                    cert_raw = convert_byte_to_string(b64_encode(self.logger, crypto.dump_certificate(crypto.FILETYPE_ASN1, cert)))
                else:
                    error = 'ca lookup failed'
            else:
                error = 'request_name lookup failed'
        self.logger.debug('Certificate.enroll() ended')
        return(error, cert_bundle, cert_raw, None)