/* * Check if the certificate is revoked using OCSP. * Current implementation aren't using OCSP to validate the certificate. * If the OCSP server is set and the cert Key Usage is set as critical, * stop swupd operation. * * TODO: Implement proper check of OCSP. */ static int validate_authority(X509 *cert) { AUTHORITY_INFO_ACCESS *info; int n, i; // Check if Authority Information Access is critical if (!is_x509_ext_critical(cert, NID_info_access)) { return 0; } debug("Authority Information Access is critical. Checking certificate revocation method\n"); // Check if the OCSP URI is set info = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL); if (!info) { goto error; } n = sk_ACCESS_DESCRIPTION_num(info); for (i = 0; i < n; i++) { ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { error("OCSP uri found, but method not supported\n"); return -1; } } AUTHORITY_INFO_ACCESS_free(info); error: error("Supported Authority Information Access methods not found in the certificate.\n"); return -1; }
static int i2r_ocsp_serviceloc(X509V3_EXT_METHOD *method, void *in, BIO *bp, int ind) { int i; OCSP_SERVICELOC *a = in; ACCESS_DESCRIPTION *ad; if (BIO_printf(bp, "%*sIssuer: ", ind, "") <= 0) goto err; if (X509_NAME_print_ex(bp, a->issuer, 0, XN_FLAG_ONELINE) <= 0) goto err; for (i = 0; i < sk_ACCESS_DESCRIPTION_num(a->locator); i++) { ad = sk_ACCESS_DESCRIPTION_value(a->locator, i); if (BIO_printf(bp, "\n%*s", (2 * ind), "") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, ad->method) <= 0) goto err; if (BIO_puts(bp, " - ") <= 0) goto err; if (GENERAL_NAME_print(bp, ad->location) <= 0) goto err; } return 1; err: return 0; }
/* Return the responder URI specified in the given certificate, or * NULL if none specified. */ static const char *extract_responder_uri(X509 *cert, apr_pool_t *pool) { STACK_OF(ACCESS_DESCRIPTION) *values; char *result = NULL; int j; values = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL); if (!values) { return NULL; } for (j = 0; j < sk_ACCESS_DESCRIPTION_num(values) && !result; j++) { ACCESS_DESCRIPTION *value = sk_ACCESS_DESCRIPTION_value(values, j); /* Name found in extension, and is a URI: */ if (OBJ_obj2nid(value->method) == NID_ad_OCSP && value->location->type == GEN_URI) { result = apr_pstrdup(pool, (char *)value->location->d.uniformResourceIdentifier->data); } } AUTHORITY_INFO_ACCESS_free(values); return result; }
static unsigned char *my_get_ext(X509 * cert, const int type, int extensiontype) { int i; STACK_OF(ACCESS_DESCRIPTION) * accessinfo ; accessinfo = X509_get_ext_d2i(cert, extensiontype, NULL, NULL) ; if (!sk_ACCESS_DESCRIPTION_num(accessinfo)) return NULL; for (i = 0; i < sk_ACCESS_DESCRIPTION_num(accessinfo); i++) { ACCESS_DESCRIPTION * ad = sk_ACCESS_DESCRIPTION_value(accessinfo, i); if (OBJ_obj2nid(ad->method) == type) { if (ad->location->type == GEN_URI) { return i2s_ASN1_IA5STRING(ad->location->d.ia5); } return NULL; } } return NULL; }
/* * This function extracts the OCSP Responder URL * from an existing x509 certificate. */ static int ocsp_parse_cert_url(X509 *cert, char **phost, char **pport, char **ppath, int *pssl) { int i; AUTHORITY_INFO_ACCESS *aia; ACCESS_DESCRIPTION *ad; aia = X509_get_ext_d2i(cert, NID_info_access, NULL, NULL); for (i = 0; i < sk_ACCESS_DESCRIPTION_num(aia); i++) { ad = sk_ACCESS_DESCRIPTION_value(aia, 0); if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { if (ad->location->type == GEN_URI) { if(OCSP_parse_url(ad->location->d.ia5->data, phost, pport, ppath, pssl)) return 1; } } } return 0; }
static void CheckAIA(X509 *x509, CertType type) { int idx = -1; bool HaveOCSPHTTP = false; bool HaveCertHTTP = false; bool HaveAIA = false; do { int critical = -1; AUTHORITY_INFO_ACCESS *info = X509_get_ext_d2i(x509, NID_info_access, &critical, &idx); if (info == NULL) { if (critical >= 0) { /* Found but fails to parse */ SetError(ERR_INVALID); continue; } /* Not found */ break; } if (critical) { SetError(ERR_AIA_CRITICAL); } HaveAIA = true; for (int i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); if (ad->location->type == GEN_URI) { CheckValidURL(ad->location->d.uniformResourceIdentifier->data, ad->location->d.uniformResourceIdentifier->length); } if (OBJ_obj2nid(ad->method) == NID_ad_OCSP && ad->location->type == GEN_URI) { if (ad->location->d.uniformResourceIdentifier->length > 7 && strncmp((char *)ad->location->d.uniformResourceIdentifier->data, "http://", 7) == 0) { HaveOCSPHTTP = true; } } if (OBJ_obj2nid(ad->method) == NID_ad_ca_issuers && ad->location->type == GEN_URI) { if (ad->location->d.uniformResourceIdentifier->length > 7 && strncmp((char *)ad->location->d.uniformResourceIdentifier->data, "http://", 7) == 0) { HaveCertHTTP = true; } } } sk_ACCESS_DESCRIPTION_pop_free(info, ACCESS_DESCRIPTION_free); } while (1); if (type == SubscriberCertificate) { if (!HaveOCSPHTTP) { SetError(ERR_NO_OCSP_HTTP); } if (!HaveCertHTTP) { SetWarning(WARN_NO_ISSUING_CERT_HTTP); } if (!HaveAIA) { SetError(ERR_NO_AIA); } } }