From: Dr. Stephen Henson Date: Sun, 10 Sep 2006 12:38:37 +0000 (+0000) Subject: Add verify callback functions to lookup a STACK of matching certs or CRLs X-Git-Tag: OpenSSL_0_9_8k^2~1150 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=4d50a2b4d6ae7618844380c1ebd5437226286db7 Add verify callback functions to lookup a STACK of matching certs or CRLs based on subject name. New thread safe functions to retrieve matching STACK from X509_STORE. Cache some IDP components. --- diff --git a/crypto/asn1/x_crl.c b/crypto/asn1/x_crl.c index 8943b84373..f8ad1f3417 100644 --- a/crypto/asn1/x_crl.c +++ b/crypto/asn1/x_crl.c @@ -64,6 +64,7 @@ static int X509_REVOKED_cmp(const X509_REVOKED * const *a, const X509_REVOKED * const *b); +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp); ASN1_SEQUENCE(X509_REVOKED) = { ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER), @@ -116,6 +117,8 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, case ASN1_OP_NEW_POST: crl->idp = NULL; crl->akid = NULL; + crl->flags = 0; + crl->idp_flags = 0; break; case ASN1_OP_D2I_POST: @@ -124,6 +127,9 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, #endif crl->idp = X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, NULL, NULL); + if (crl->idp) + setup_idp(crl, crl->idp); + crl->akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL); break; @@ -138,6 +144,46 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, return 1; } +/* Convert IDP into a more convenient form */ + +static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp) + { + int idp_only = 0; + /* Set various flags according to IDP */ + crl->idp_flags |= IDP_PRESENT; + if (idp->onlyuser > 0) + { + idp_only++; + crl->idp_flags |= IDP_ONLYUSER; + } + if (idp->onlyCA > 0) + { + idp_only++; + crl->idp_flags |= IDP_ONLYCA; + } + if (idp->onlyattr > 0) + { + idp_only++; + crl->idp_flags |= IDP_ONLYATTR; + } + + if (idp_only > 1) + crl->idp_flags |= IDP_INVALID; + + if (idp->indirectCRL > 0) + crl->idp_flags |= IDP_INDIRECT; + + if (idp->onlysomereasons) + { + crl->idp_flags |= IDP_REASONS; + if (idp->onlysomereasons->length > 0) + crl->idp_reasons = idp->onlysomereasons->data[0]; + if (idp->onlysomereasons->length > 1) + crl->idp_reasons |= + (idp->onlysomereasons->data[1] << 8); + } + } + ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = { ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO), ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR), diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index 31bc7539bf..de93bf9005 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -454,6 +454,9 @@ struct X509_crl_st /* Copies of various extensions */ AUTHORITY_KEYID *akid; ISSUING_DIST_POINT *idp; + /* Convenient breakdown of IDP */ + int idp_flags; + int idp_reasons; #ifndef OPENSSL_NO_SHA unsigned char sha1_hash[SHA_DIGEST_LENGTH]; #endif diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c index fbb1497fe2..35a8e351c0 100644 --- a/crypto/x509/x509_lu.c +++ b/crypto/x509/x509_lu.c @@ -414,14 +414,15 @@ void X509_OBJECT_free_contents(X509_OBJECT *a) } } -int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, - X509_NAME *name) +static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name, int *pnmatch) { X509_OBJECT stmp; X509 x509_s; X509_CINF cinf_s; X509_CRL crl_s; X509_CRL_INFO crl_info_s; + int idx; stmp.type=type; switch (type) @@ -441,7 +442,29 @@ int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, return -1; } - return sk_X509_OBJECT_find(h,&stmp); + idx = sk_X509_OBJECT_find(h,&stmp); + if (idx >= 0 && pnmatch) + { + int tidx; + const X509_OBJECT *tobj, *pstmp; + *pnmatch = 1; + pstmp = &stmp; + for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) + { + tobj = sk_X509_OBJECT_value(h, tidx); + if (!x509_object_cmp(&tobj, &pstmp)) + break; + *pnmatch++; + } + } + return idx; + } + + +int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type, + X509_NAME *name) + { + return x509_object_idx_cnt(h, type, name, NULL); } X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type, @@ -453,6 +476,72 @@ X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type, return sk_X509_OBJECT_value(h, idx); } +STACK_OF(X509)* X509_STORE_get_certs(X509_STORE *st, X509_NAME *nm) + { + int i, idx, cnt; + STACK_OF(X509) *sk; + X509 *x; + X509_OBJECT *obj; + sk = sk_X509_new_null(); + CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); + idx = x509_object_idx_cnt(st->objs, X509_LU_X509, nm, &cnt); + if (idx < 0) + { + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + sk_X509_free(sk); + return NULL; + } + for (i = 0; i < cnt; i++, idx++) + { + obj = sk_X509_OBJECT_value(st->objs, i); + x = obj->data.x509; + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); + if (!sk_X509_push(sk, x)) + { + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + X509_free(x); + sk_X509_pop_free(sk, X509_free); + return NULL; + } + } + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + return sk; + + } + +STACK_OF(X509_CRL)* X509_STORE_get_crls(X509_STORE *st, X509_NAME *nm) + { + int i, idx, cnt; + STACK_OF(X509_CRL) *sk; + X509_CRL *x; + X509_OBJECT *obj; + sk = sk_X509_CRL_new_null(); + CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE); + idx = x509_object_idx_cnt(st->objs, X509_LU_CRL, nm, &cnt); + if (idx < 0) + { + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + sk_X509_CRL_free(sk); + return NULL; + } + for (i = 0; i < cnt; i++, idx++) + { + obj = sk_X509_OBJECT_value(st->objs, i); + x = obj->data.crl; + CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL); + if (!sk_X509_CRL_push(sk, x)) + { + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + X509_CRL_free(x); + sk_X509_CRL_pop_free(sk, X509_CRL_free); + return NULL; + } + } + CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE); + return sk; + + } + X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x) { int idx, i; diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index e2109a4c35..51db63101f 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -79,6 +79,8 @@ static int check_revocation(X509_STORE_CTX *ctx); static int check_cert(X509_STORE_CTX *ctx); static int check_policy(X509_STORE_CTX *ctx); static int internal_verify(X509_STORE_CTX *ctx); +static STACK_OF(X509) * lookup_certs(X509_STORE_CTX *ctx, X509_NAME *nm); +static STACK_OF(X509_CRL) * lookup_crls(X509_STORE_CTX *ctx, X509_NAME *nm); const char *X509_version="X.509" OPENSSL_VERSION_PTEXT; @@ -669,7 +671,7 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, if (check_crl_time(ctx, crl, 0)) { *pcrl = crl; - CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509); + CRYPTO_add(&crl->references, 1, CRYPTO_LOCK_X509_CRL); return 1; } best_crl = crl; @@ -874,6 +876,16 @@ static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) return 1; } +static STACK_OF(X509) * lookup_certs(X509_STORE_CTX *ctx, X509_NAME *nm) + { + return X509_STORE_get_certs(ctx->ctx, nm); + } + +static STACK_OF(X509_CRL) * lookup_crls(X509_STORE_CTX *ctx, X509_NAME *nm) + { + return X509_STORE_get_crls(ctx->ctx, nm); + } + static int check_policy(X509_STORE_CTX *ctx) { int ret; @@ -1461,6 +1473,16 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, else ctx->cert_crl = cert_crl; + if (store && store->lookup_certs) + ctx->lookup_certs = store->lookup_certs; + else + ctx->lookup_certs = lookup_certs; + + if (store && store->lookup_crls) + ctx->lookup_crls = store->lookup_crls; + else + ctx->lookup_crls = lookup_crls; + ctx->check_policy = check_policy; diff --git a/crypto/x509/x509_vfy.h b/crypto/x509/x509_vfy.h index 3f16330444..3c550e1433 100644 --- a/crypto/x509/x509_vfy.h +++ b/crypto/x509/x509_vfy.h @@ -198,6 +198,8 @@ struct x509_store_st int (*get_crl)(X509_STORE_CTX *ctx, X509_CRL **crl, X509 *x); /* retrieve CRL */ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ + STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); int (*cleanup)(X509_STORE_CTX *ctx); CRYPTO_EX_DATA ex_data; @@ -246,6 +248,8 @@ struct x509_store_ctx_st /* X509_STORE_CTX */ int (*check_crl)(X509_STORE_CTX *ctx, X509_CRL *crl); /* Check CRL validity */ int (*cert_crl)(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x); /* Check certificate against CRL */ int (*check_policy)(X509_STORE_CTX *ctx); + STACK_OF(X509) * (*lookup_certs)(X509_STORE_CTX *ctx, X509_NAME *nm); + STACK_OF(X509_CRL) * (*lookup_crls)(X509_STORE_CTX *ctx, X509_NAME *nm); int (*cleanup)(X509_STORE_CTX *ctx); /* The following is built up */ @@ -383,6 +387,8 @@ void X509_OBJECT_free_contents(X509_OBJECT *a); X509_STORE *X509_STORE_new(void ); void X509_STORE_free(X509_STORE *v); +STACK_OF(X509)* X509_STORE_get_certs(X509_STORE *st, X509_NAME *nm); +STACK_OF(X509_CRL)* X509_STORE_get_crls(X509_STORE *st, X509_NAME *nm); int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags); int X509_STORE_set_purpose(X509_STORE *ctx, int purpose); int X509_STORE_set_trust(X509_STORE *ctx, int trust); diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h index 1e2f00ab24..da349e51f5 100644 --- a/crypto/x509v3/x509v3.h +++ b/crypto/x509v3/x509v3.h @@ -339,6 +339,22 @@ struct ISSUING_DIST_POINT_st int onlyattr; }; +/* Values in idp_flags field */ +/* IDP present */ +#define IDP_PRESENT 0x1 +/* IDP values inconsistent */ +#define IDP_INVALID 0x2 +/* onlyuser true */ +#define IDP_ONLYUSER 0x4 +/* onlyCA true */ +#define IDP_ONLYCA 0x8 +/* onlyattr true */ +#define IDP_ONLYATTR 0x10 +/* indirectCRL true */ +#define IDP_INDIRECT 0x20 +/* onlysomereasons present */ +#define IDP_REASONS 0x40 + #define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \ ",name:", val->name, ",value:", val->value);