From bab9947c6ff927e07c3befaf0862be6d6c6e4eec Mon Sep 17 00:00:00 2001 From: Nalin Dahyabhai Date: Tue, 28 Sep 2010 15:49:11 -0400 Subject: [PATCH 016/150] - implement the EKU check --- src/plugins/preauth/pkinit/pkinit_crypto_nss.c | 63 ++++++++++++++++++------ 1 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c index eae3724..38b3fba 100644 --- a/src/plugins/preauth/pkinit/pkinit_crypto_nss.c +++ b/src/plugins/preauth/pkinit/pkinit_crypto_nss.c @@ -314,6 +314,9 @@ pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx) if (req_cryptoctx->client_seckey != NULL) { SECKEY_DestroyPrivateKey(req_cryptoctx->client_seckey); } + if (req_cryptoctx->peer_cert != NULL) { + CERT_DestroyCertificate(req_cryptoctx->peer_cert); + } PORT_FreeArena(req_cryptoctx->pool, PR_TRUE); } @@ -1091,13 +1094,13 @@ cert_get_ext_by_tag(CERTCertificate *cert, SECOidTag tag) return NULL; } static unsigned int -cert_get_ku_bits(krb5_context context, pkinit_cert_handle cert_handle) +cert_get_ku_bits(krb5_context context, CERTCertificate *cert) { unsigned int ku = 0; - if (cert_handle->cert->keyUsage & KU_DIGITAL_SIGNATURE) { + if (cert->keyUsage & KU_DIGITAL_SIGNATURE) { ku |= PKINIT_KU_DIGITALSIGNATURE; } - if (cert_handle->cert->keyUsage & KU_KEY_ENCIPHERMENT) { + if (cert->keyUsage & KU_KEY_ENCIPHERMENT) { ku |= PKINIT_KU_KEYENCIPHERMENT; } return ku; @@ -1121,20 +1124,20 @@ static SECItem pkinit_kp_mssclogin = { .len = 10, }; static unsigned int -cert_get_eku_bits(krb5_context context, pkinit_cert_handle cert_handle, int kdc) +cert_get_eku_bits(krb5_context context, CERTCertificate *cert, int kdc) { PLArenaPool *pool; SECItem *ext, **oids; - SECOidData *clientauth, *email; + SECOidData *clientauth, *serverauth, *email; int i; unsigned int eku; /* Pull out the extension. */ - ext = cert_get_ext_by_tag(cert_handle->cert, - SEC_OID_X509_EXT_KEY_USAGE); + ext = cert_get_ext_by_tag(cert, SEC_OID_X509_EXT_KEY_USAGE); /* Look up the well-known OIDs. */ clientauth = SECOID_FindOIDByTag(SEC_OID_EXT_KEY_USAGE_CLIENT_AUTH); + serverauth = SECOID_FindOIDByTag(SEC_OID_EXT_KEY_USAGE_SERVER_AUTH); email = SECOID_FindOIDByTag(SEC_OID_EXT_KEY_USAGE_EMAIL_PROTECT); /* Decode the list of OIDs. */ @@ -1147,9 +1150,6 @@ cert_get_eku_bits(krb5_context context, pkinit_cert_handle cert_handle, int kdc) } eku = 0; for (i = 0; (oids != NULL) && (oids[i] != NULL); i++) { - if (SECITEM_ItemsAreEqual(oids[i], &clientauth->oid)) { - eku |= PKINIT_EKU_CLIENTAUTH; - } if (SECITEM_ItemsAreEqual(oids[i], &email->oid)) { eku |= PKINIT_EKU_EMAILPROTECTION; } @@ -1157,10 +1157,16 @@ cert_get_eku_bits(krb5_context context, pkinit_cert_handle cert_handle, int kdc) if (SECITEM_ItemsAreEqual(oids[i], &pkinit_kp_kdc)) { eku |= PKINIT_EKU_PKINIT; } + if (SECITEM_ItemsAreEqual(oids[i], &serverauth->oid)) { + eku |= PKINIT_EKU_CLIENTAUTH; + } } else { if (SECITEM_ItemsAreEqual(oids[i], &pkinit_kp_client)) { eku |= PKINIT_EKU_PKINIT; } + if (SECITEM_ItemsAreEqual(oids[i], &clientauth->oid)) { + eku |= PKINIT_EKU_CLIENTAUTH; + } } if (SECITEM_ItemsAreEqual(oids[i], &pkinit_kp_mssclogin)) { eku |= PKINIT_EKU_MSSCLOGIN; @@ -1186,8 +1192,8 @@ crypto_cert_get_matching_data(krb5_context context, /* FIXME: not RFC2253 */ md->issuer_dn = strdup(cert->cert->issuerName); /* FIXME: not RFC2253 */ - md->ku_bits = cert_get_ku_bits(context, cert_handle); - md->eku_bits = cert_get_eku_bits(context, cert_handle, 0); + md->ku_bits = cert_get_ku_bits(context, cert_handle->cert); + md->eku_bits = cert_get_eku_bits(context, cert_handle->cert, 0); md->sans = NULL; /* FIXME */ *ret_data = md; return 0; @@ -1362,7 +1368,33 @@ crypto_check_cert_eku(krb5_context context, int allow_secondary_usage, int *eku_valid) { - return ENOSYS; + int ku, eku; + + *eku_valid = 0; + + ku = cert_get_ku_bits(context, req_cryptoctx->peer_cert); + if (!(ku & PKINIT_KU_DIGITALSIGNATURE)) { + return 0; + } + + eku = cert_get_eku_bits(context, req_cryptoctx->peer_cert, + checking_kdc_cert); + if (checking_kdc_cert) { + if (eku & PKINIT_EKU_PKINIT) { + *eku_valid = 1; + } else + if (allow_secondary_usage && (eku & PKINIT_EKU_CLIENTAUTH)) { + *eku_valid = 1; + } + } else { + if (eku & PKINIT_EKU_PKINIT) { + *eku_valid = 1; + } else + if (allow_secondary_usage && (eku & PKINIT_EKU_MSSCLOGIN)) { + *eku_valid = 1; + } + } + return 0; } krb5_error_code @@ -1700,7 +1732,7 @@ cms_signeddata_verify(krb5_context context, return ENOMEM; } /* Verify the signer's certificate. */ - usage = certUsageSSLServer; + usage = certUsageSSLServer; /* FIXME */ status = NSS_CMSSignedData_VerifySignerInfo(sdata, 0, certdb, usage); if (status != SECSuccess) { @@ -1716,7 +1748,7 @@ cms_signeddata_verify(krb5_context context, return ENOMEM; } plain = NSS_CMSContentInfo_GetContent(info); - /* Save the peer cert. */ + /* Save the peer cert -- we'll need it later. */ if (req_cryptoctx->peer_cert != NULL) { CERT_DestroyCertificate(req_cryptoctx->peer_cert); } @@ -1724,6 +1756,7 @@ cms_signeddata_verify(krb5_context context, req_cryptoctx->peer_cert = CERT_DupCertificate(cert); break; case SEC_OID_PKCS7_DATA: + /* Pull out the payload. */ *is_signed = 0; plain = NSS_CMSContentInfo_GetContent(info); break; -- 1.7.6.4