/* * Open the inner, decrypted PKCS7 and try to write CA/RA certificates */ int write_ca_ra(struct http_reply *s) { BIO *bio; PKCS7 *p7; STACK_OF(X509) *certs = NULL; X509 *cert = NULL; FILE *fp = NULL; int c, i, index; unsigned int n; unsigned char md[EVP_MAX_MD_SIZE]; X509_EXTENSION *ext; /* Create read-only memory bio */ bio = BIO_new_mem_buf(s->payload, s->bytes); p7 = d2i_PKCS7_bio(bio, NULL); if (p7 == NULL) { fprintf(stderr, "%s: error reading PKCS#7 data\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_FILE); } /* Get certs */ i = OBJ_obj2nid(p7->type); switch (i) { case NID_pkcs7_signed: certs = p7->d.sign->cert; break; default: printf("%s: wrong PKCS#7 type\n", pname); exit (SCEP_PKISTATUS_FILE); } /* Check */ if (certs == NULL) { fprintf(stderr, "%s: cannot find certificates\n", pname); exit (SCEP_PKISTATUS_FILE); } /* Verify the chain * XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ /* Find cert */ for (i = 0; i < sk_X509_num(certs); i++) { char buffer[1024]; char name[1024]; memset(buffer, 0, 1024); memset(name, 0, 1024); cert = sk_X509_value(certs, i); /* Create name */ snprintf(name, 1024, "%s-%d", c_char, i); /* Read and print certificate information */ printf("\n%s: found certificate with\n subject: %s\n", pname, X509_NAME_oneline(X509_get_subject_name(cert), buffer, sizeof(buffer))); printf(" issuer: %s\n", X509_NAME_oneline(X509_get_issuer_name(cert), buffer, sizeof(buffer))); if (!X509_digest(cert, fp_alg, md, &n)) { ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_FILE); } /* Print key usage: */ index = X509_get_ext_by_NID(cert, NID_key_usage, -1); if (index < 0) { if (v_flag) fprintf(stderr, "%s: cannot find key usage\n", pname); /* exit (SCEP_PKISTATUS_FILE); */ } else { ext = X509_get_ext(cert, index); printf(" usage: "); X509V3_EXT_print_fp(stdout, ext, 0, 0); printf("\n"); } printf(" %s fingerprint: ", OBJ_nid2sn(EVP_MD_type(fp_alg))); for (c = 0; c < (int)n; c++) { printf("%02X%c",md[c], (c + 1 == (int)n) ?'\n':':'); } /* Write PEM-formatted file: */ if (!(fp = fopen(name, "w"))) { fprintf(stderr, "%s: cannot open cert file for " "writing\n", pname); exit (SCEP_PKISTATUS_FILE); } if (v_flag) printf("%s: writing cert\n", pname); if (d_flag) PEM_write_X509(stdout, cert); if (PEM_write_X509(fp, cert) != 1) { fprintf(stderr, "%s: error while writing certificate " "file\n", pname); ERR_print_errors_fp(stderr); exit (SCEP_PKISTATUS_FILE); } printf("%s: certificate written as %s\n", pname, name); } (void)fclose(fp); exit (SCEP_PKISTATUS_SUCCESS); }
static void x509v3_cache_extensions(X509 *x) { BASIC_CONSTRAINTS *bs; PROXY_CERT_INFO_EXTENSION *pci; ASN1_BIT_STRING *usage; ASN1_BIT_STRING *ns; EXTENDED_KEY_USAGE *extusage; X509_EXTENSION *ex; int i; if (x->ex_flags & EXFLAG_SET) return; #ifndef OPENSSL_NO_SHA X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); #endif /* V1 should mean no extensions ... */ if (!X509_get_version(x)) x->ex_flags |= EXFLAG_V1; /* Handle basic constraints */ if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { if (bs->ca) x->ex_flags |= EXFLAG_CA; if (bs->pathlen) { if ((bs->pathlen->type == V_ASN1_NEG_INTEGER) || !bs->ca) { x->ex_flags |= EXFLAG_INVALID; x->ex_pathlen = 0; } else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); } else x->ex_pathlen = -1; BASIC_CONSTRAINTS_free(bs); x->ex_flags |= EXFLAG_BCONS; } /* Handle proxy certificates */ if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { if (x->ex_flags & EXFLAG_CA || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { x->ex_flags |= EXFLAG_INVALID; } if (pci->pcPathLengthConstraint) { x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); } else x->ex_pcpathlen = -1; PROXY_CERT_INFO_EXTENSION_free(pci); x->ex_flags |= EXFLAG_PROXY; } /* Handle key usage */ if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { if (usage->length > 0) { x->ex_kusage = usage->data[0]; if (usage->length > 1) x->ex_kusage |= usage->data[1] << 8; } else x->ex_kusage = 0; x->ex_flags |= EXFLAG_KUSAGE; ASN1_BIT_STRING_free(usage); } x->ex_xkusage = 0; if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { x->ex_flags |= EXFLAG_XKUSAGE; for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) { case NID_server_auth: x->ex_xkusage |= XKU_SSL_SERVER; break; case NID_client_auth: x->ex_xkusage |= XKU_SSL_CLIENT; break; case NID_email_protect: x->ex_xkusage |= XKU_SMIME; break; case NID_code_sign: x->ex_xkusage |= XKU_CODE_SIGN; break; case NID_ms_sgc: case NID_ns_sgc: x->ex_xkusage |= XKU_SGC; break; case NID_OCSP_sign: x->ex_xkusage |= XKU_OCSP_SIGN; break; case NID_time_stamp: x->ex_xkusage |= XKU_TIMESTAMP; break; case NID_dvcs: x->ex_xkusage |= XKU_DVCS; break; case NID_anyExtendedKeyUsage: x->ex_xkusage |= XKU_ANYEKU; break; } } sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); } if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { if (ns->length > 0) x->ex_nscert = ns->data[0]; else x->ex_nscert = 0; x->ex_flags |= EXFLAG_NSCERT; ASN1_BIT_STRING_free(ns); } x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); /* Does subject name match issuer ? */ if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { x->ex_flags |= EXFLAG_SI; /* If SKID matches AKID also indicate self signed */ if (X509_check_akid(x, x->akid) == X509_V_OK) x->ex_flags |= EXFLAG_SS; } x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); x->nc = X509_get_ext_d2i(x, NID_name_constraints, &i, NULL); if (!x->nc && (i != -1)) x->ex_flags |= EXFLAG_INVALID; setup_crldp(x); #ifndef OPENSSL_NO_RFC3779 x->rfc3779_addr = X509_get_ext_d2i(x, NID_sbgp_ipAddrBlock, NULL, NULL); x->rfc3779_asid = X509_get_ext_d2i(x, NID_sbgp_autonomousSysNum, NULL, NULL); #endif for (i = 0; i < X509_get_ext_count(x); i++) { ex = X509_get_ext(x, i); if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_freshest_crl) x->ex_flags |= EXFLAG_FRESHEST; if (!X509_EXTENSION_get_critical(ex)) continue; if (!X509_supported_extension(ex)) { x->ex_flags |= EXFLAG_CRITICAL; break; } } x->ex_flags |= EXFLAG_SET; }
/** Determines if the specified EKU represented in ASN1 form is present in a given certificate. @param[in] Cert The certificate to check. @param[in] Asn1ToFind The EKU to look for. @retval EFI_SUCCESS We successfully identified the signing type. @retval EFI_INVALID_PARAMETER A parameter was invalid. @retval EFI_NOT_FOUND One or more EKU's were not found in the signature. **/ EFI_STATUS IsEkuInCertificate ( IN CONST X509 *Cert, IN ASN1_OBJECT *Asn1ToFind ) { EFI_STATUS Status; X509 *ClonedCert; X509_EXTENSION *Extension; EXTENDED_KEY_USAGE *Eku; INT32 ExtensionIndex; INTN NumExtensions; ASN1_OBJECT *Asn1InCert; INTN Index; Status = EFI_NOT_FOUND; ClonedCert = NULL; Extension = NULL; Eku = NULL; ExtensionIndex = -1; NumExtensions = 0; Asn1InCert = NULL; if (Cert == NULL || Asn1ToFind == NULL) { Status = EFI_INVALID_PARAMETER; goto Exit; } // // Clone the certificate. This is required because the Extension API's // only work once per instance of an X509 object. // ClonedCert = X509_dup ((X509*)Cert); if (ClonedCert == NULL) { // // Fail to duplicate cert. // Status = EFI_INVALID_PARAMETER; goto Exit; } // // Look for the extended key usage. // ExtensionIndex = X509_get_ext_by_NID (ClonedCert, NID_ext_key_usage, -1); if (ExtensionIndex < 0) { // // Fail to find 'NID_ext_key_usage' in Cert. // goto Exit; } Extension = X509_get_ext (ClonedCert, ExtensionIndex); if (Extension == NULL) { // // Fail to get Extension form cert. // goto Exit; } Eku = (EXTENDED_KEY_USAGE*)X509V3_EXT_d2i (Extension); if (Eku == NULL) { // // Fail to get Eku from extension. // goto Exit; } NumExtensions = sk_ASN1_OBJECT_num (Eku); // // Now loop through the extensions, looking for the specified Eku. // for (Index = 0; Index < NumExtensions; Index++) { Asn1InCert = sk_ASN1_OBJECT_value (Eku, (INT32)Index); if (Asn1InCert == NULL) { // // Fail to get ASN object from Eku. // goto Exit; } if (Asn1InCert->length == Asn1ToFind->length && CompareMem (Asn1InCert->data, Asn1ToFind->data, Asn1InCert->length) == 0) { // // Found Eku in certificate. // Status = EFI_SUCCESS; goto Exit; } } Exit: // // Release Resources // if (ClonedCert) { X509_free (ClonedCert); } if (Eku) { sk_ASN1_OBJECT_pop_free (Eku, ASN1_OBJECT_free); } return Status; }
gboolean z_proxy_ssl_host_iface_check_name_method(ZProxyHostIface *s, const gchar *host_name, gchar *reason_buf, gsize reason_len) { ZProxySslHostIface *self = Z_CAST(s, ZProxySslHostIface); gint ext_ndx; gboolean found = FALSE, result = FALSE; gchar pattern_buf[256]; if (self->hostname_checked) return self->hostname_check_result; pattern_buf[0] = 0; ext_ndx = X509_get_ext_by_NID(self->server_cert, NID_subject_alt_name, -1); if (ext_ndx >= 0) { /* ok, there's a subjectAltName extension, check that */ X509_EXTENSION *ext; STACK_OF(GENERAL_NAME) *alt_names; GENERAL_NAME *gen_name; ext = X509_get_ext(self->server_cert, ext_ndx); alt_names = X509V3_EXT_d2i(ext); if (alt_names) { gint num, i; num = sk_GENERAL_NAME_num(alt_names); for (i = 0; i < num; i++) { gen_name = sk_GENERAL_NAME_value(alt_names, i); if (gen_name->type == GEN_DNS) { guchar *dnsname = ASN1_STRING_data(gen_name->d.dNSName); guint dnsname_len = ASN1_STRING_length(gen_name->d.dNSName); if (dnsname_len > sizeof(pattern_buf) - 1) { found = TRUE; result = FALSE; break; } memcpy(pattern_buf, dnsname, dnsname_len); pattern_buf[dnsname_len] = 0; /* we have found a DNS name as alternative subject name */ found = TRUE; result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf); break; } else if (gen_name->type == GEN_IPADD) { z_inet_ntoa(pattern_buf, sizeof(pattern_buf), *(struct in_addr *) gen_name->d.iPAddress->data); found = TRUE; result = strcmp(host_name, pattern_buf) == 0; break; } } sk_GENERAL_NAME_free(alt_names); } } if (!found) { /* hmm. there was no subjectAltName (this is deprecated, but still * widely used), look up the Subject, most specific CN */ X509_NAME *name; name = X509_get_subject_name(self->server_cert); if (X509_NAME_get_text_by_NID(name, NID_commonName, pattern_buf, sizeof(pattern_buf)) != -1) { result = z_proxy_ssl_host_iface_check_wildcard(s->owner, host_name, pattern_buf); } } if (!result && reason_buf) { g_snprintf(reason_buf, reason_len, "Certificate does not belong to target host (certificate: %s, host %s)", pattern_buf, host_name); } self->hostname_checked = TRUE; self->hostname_check_result = result; return result; }
int ca_x509_subjectaltname(X509 *cert, struct iked_id *id) { X509_EXTENSION *san; u_int8_t sanhdr[4], *data; int ext, santype, sanlen; char idstr[IKED_ID_SIZE]; if ((ext = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) == -1 || ((san = X509_get_ext(cert, ext)) == NULL)) { log_debug("%s: did not find subjectAltName in certificate", __func__); return (-1); } if (san->value == NULL || san->value->data == NULL || san->value->length < (int)sizeof(sanhdr)) { log_debug("%s: invalid subjectAltName in certificate", __func__); return (-1); } /* This is partially based on isakmpd's x509 subjectaltname code */ data = (u_int8_t *)san->value->data; memcpy(&sanhdr, data, sizeof(sanhdr)); santype = sanhdr[2] & 0x3f; sanlen = sanhdr[3]; if ((sanlen + (int)sizeof(sanhdr)) > san->value->length) { log_debug("%s: invalid subjectAltName length", __func__); return (-1); } switch (santype) { case GEN_DNS: id->id_type = IKEV2_ID_FQDN; break; case GEN_EMAIL: id->id_type = IKEV2_ID_UFQDN; break; case GEN_IPADD: if (sanlen == 4) id->id_type = IKEV2_ID_IPV4; else if (sanlen == 16) id->id_type = IKEV2_ID_IPV6; else { log_debug("%s: invalid subjectAltName IP address", __func__); return (-1); } break; default: log_debug("%s: unsupported subjectAltName type %d", __func__, santype); return (-1); } ibuf_release(id->id_buf); if ((id->id_buf = ibuf_new(data + sizeof(sanhdr), sanlen)) == NULL) { log_debug("%s: failed to get id buffer", __func__); return (-1); } id->id_offset = 0; ikev2_print_id(id, idstr, sizeof(idstr)); log_debug("%s: %s", __func__, idstr); return (0); }