static int add_to_req(hx509_context context, void *ptr, hx509_cert cert) { struct ocsp_add_ctx *ctx = ptr; OCSPInnerRequest *one; hx509_cert parent = NULL; Certificate *p, *c = _hx509_get_cert(cert); heim_octet_string os; int ret; hx509_query q; void *d; d = realloc(ctx->req->requestList.val, sizeof(ctx->req->requestList.val[0]) * (ctx->req->requestList.len + 1)); if (d == NULL) return ENOMEM; ctx->req->requestList.val = d; one = &ctx->req->requestList.val[ctx->req->requestList.len]; memset(one, 0, sizeof(*one)); _hx509_query_clear(&q); q.match |= HX509_QUERY_FIND_ISSUER_CERT; q.subject = c; ret = hx509_certs_find(context, ctx->certs, &q, &parent); if (ret) goto out; if (ctx->parent) { if (hx509_cert_cmp(ctx->parent, parent) != 0) { ret = HX509_REVOKE_NOT_SAME_PARENT; hx509_set_error_string(context, 0, ret, "Not same parent certifate as " "last certificate in request"); goto out; } } else ctx->parent = hx509_cert_ref(parent); p = _hx509_get_cert(parent); ret = copy_AlgorithmIdentifier(ctx->digest, &one->reqCert.hashAlgorithm); if (ret) goto out; ret = _hx509_create_signature(context, NULL, &one->reqCert.hashAlgorithm, &c->tbsCertificate.issuer._save, NULL, &one->reqCert.issuerNameHash); if (ret) goto out; os.data = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data; os.length = p->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8; ret = _hx509_create_signature(context, NULL, &one->reqCert.hashAlgorithm, &os, NULL, &one->reqCert.issuerKeyHash); if (ret) goto out; ret = copy_CertificateSerialNumber(&c->tbsCertificate.serialNumber, &one->reqCert.serialNumber); if (ret) goto out; ctx->req->requestList.len++; out: hx509_cert_free(parent); if (ret) { free_OCSPInnerRequest(one); memset(one, 0, sizeof(*one)); } return ret; }
krb5_error_code _kdc_pk_check_client(krb5_context context, krb5_kdc_configuration *config, HDB *clientdb, hdb_entry_ex *client, pk_client_params *cp, char **subject_name) { const HDB_Ext_PKINIT_acl *acl; const HDB_Ext_PKINIT_cert *pc; krb5_error_code ret; hx509_name name; size_t i; if (cp->cert == NULL) { *subject_name = strdup("anonymous client client"); if (*subject_name == NULL) return ENOMEM; return 0; } ret = hx509_cert_get_base_subject(context->hx509ctx, cp->cert, &name); if (ret) return ret; ret = hx509_name_to_string(name, subject_name); hx509_name_free(&name); if (ret) return ret; kdc_log(context, config, 0, "Trying to authorize PK-INIT subject DN %s", *subject_name); ret = hdb_entry_get_pkinit_cert(&client->entry, &pc); if (ret == 0 && pc) { hx509_cert cert; size_t j; for (j = 0; j < pc->len; j++) { cert = hx509_cert_init_data(context->hx509ctx, pc->val[j].cert.data, pc->val[j].cert.length, NULL); if (cert == NULL) continue; ret = hx509_cert_cmp(cert, cp->cert); hx509_cert_free(cert); if (ret == 0) { kdc_log(context, config, 5, "Found matching PK-INIT cert in hdb"); return 0; } } } if (config->pkinit_princ_in_cert) { ret = match_rfc_san(context, config, context->hx509ctx, cp->cert, client->entry.principal); if (ret == 0) { kdc_log(context, config, 5, "Found matching PK-INIT SAN in certificate"); return 0; } ret = match_ms_upn_san(context, config, context->hx509ctx, cp->cert, clientdb, client); if (ret == 0) { kdc_log(context, config, 5, "Found matching MS UPN SAN in certificate"); return 0; } } ret = hdb_entry_get_pkinit_acl(&client->entry, &acl); if (ret == 0 && acl != NULL) { /* * Cheat here and compare the generated name with the string * and not the reverse. */ for (i = 0; i < acl->len; i++) { if (strcmp(*subject_name, acl->val[0].subject) != 0) continue; /* Don't support isser and anchor checking right now */ if (acl->val[0].issuer) continue; if (acl->val[0].anchor) continue; kdc_log(context, config, 5, "Found matching PK-INIT database ACL"); return 0; } } for (i = 0; i < principal_mappings.len; i++) { krb5_boolean b; b = krb5_principal_compare(context, client->entry.principal, principal_mappings.val[i].principal); if (b == FALSE) continue; if (strcmp(principal_mappings.val[i].subject, *subject_name) != 0) continue; kdc_log(context, config, 5, "Found matching PK-INIT FILE ACL"); return 0; } ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; krb5_set_error_message(context, ret, "PKINIT no matching principals for %s", *subject_name); kdc_log(context, config, 5, "PKINIT no matching principals for %s", *subject_name); free(*subject_name); *subject_name = NULL; return ret; }
static int verify_ocsp(hx509_context context, struct revoke_ocsp *ocsp, time_t time_now, hx509_certs certs, hx509_cert parent) { hx509_cert signer = NULL; hx509_query q; int ret; _hx509_query_clear(&q); /* * Need to match on issuer too in case there are two CA that have * issued the same name to a certificate. One example of this is * the www.openvalidation.org test's ocsp validator. */ q.match = HX509_QUERY_MATCH_ISSUER_NAME; q.issuer_name = &_hx509_get_cert(parent)->tbsCertificate.issuer; switch(ocsp->ocsp.tbsResponseData.responderID.element) { case choice_OCSPResponderID_byName: q.match |= HX509_QUERY_MATCH_SUBJECT_NAME; q.subject_name = &ocsp->ocsp.tbsResponseData.responderID.u.byName; break; case choice_OCSPResponderID_byKey: q.match |= HX509_QUERY_MATCH_KEY_HASH_SHA1; q.keyhash_sha1 = &ocsp->ocsp.tbsResponseData.responderID.u.byKey; break; } ret = hx509_certs_find(context, certs, &q, &signer); if (ret && ocsp->certs) ret = hx509_certs_find(context, ocsp->certs, &q, &signer); if (ret) goto out; /* * If signer certificate isn't the CA certificate, lets check the * it is the CA that signed the signer certificate and the OCSP EKU * is set. */ if (hx509_cert_cmp(signer, parent) != 0) { Certificate *p = _hx509_get_cert(parent); Certificate *s = _hx509_get_cert(signer); ret = _hx509_cert_is_parent_cmp(s, p, 0); if (ret != 0) { ret = HX509_PARENT_NOT_CA; hx509_set_error_string(context, 0, ret, "Revoke OCSP signer is " "doesn't have CA as signer certificate"); goto out; } ret = _hx509_verify_signature_bitstring(context, parent, &s->signatureAlgorithm, &s->tbsCertificate._save, &s->signatureValue); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "OCSP signer signature invalid"); goto out; } ret = hx509_cert_check_eku(context, signer, &asn1_oid_id_pkix_kp_OCSPSigning, 0); if (ret) goto out; } ret = _hx509_verify_signature_bitstring(context, signer, &ocsp->ocsp.signatureAlgorithm, &ocsp->ocsp.tbsResponseData._save, &ocsp->ocsp.signature); if (ret) { hx509_set_error_string(context, HX509_ERROR_APPEND, ret, "OCSP signature invalid"); goto out; } ocsp->signer = signer; signer = NULL; out: if (signer) hx509_cert_free(signer); return ret; }