X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fx509%2Fx509_vfy.c;h=1ae3675e2e753d75482869f36913eced5a468586;hp=bfb7c89bd719f785ddeef84977a2487f866c0ca5;hb=34a42e1489bf4f45bfad069eceba56315d4713be;hpb=0f113f3ee4d629ef9a4a30911b22b224772085e5 diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c index bfb7c89bd7..1ae3675e2e 100644 --- a/crypto/x509/x509_vfy.c +++ b/crypto/x509/x509_vfy.c @@ -60,7 +60,7 @@ #include #include -#include "cryptlib.h" +#include "internal/cryptlib.h" #include #include #include @@ -69,6 +69,7 @@ #include #include #include +#include "internal/x509_int.h" #include "x509_lcl.h" /* CRL score values */ @@ -138,19 +139,12 @@ static int check_crl_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *crl_path); static int internal_verify(X509_STORE_CTX *ctx); -const char X509_version[] = "X.509" OPENSSL_VERSION_PTEXT; static int null_callback(int ok, X509_STORE_CTX *e) { return ok; } -#if 0 -static int x509_subject_cmp(X509 **a, X509 **b) -{ - return X509_subject_name_cmp(*a, *b); -} -#endif /* Return 1 is a certificate is self signed */ static int cert_self_signed(X509 *x) { @@ -179,7 +173,7 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) break; } if (i < sk_X509_num(certs)) - CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(xtmp); else xtmp = NULL; sk_X509_pop_free(certs, X509_free); @@ -188,17 +182,25 @@ static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) int X509_verify_cert(X509_STORE_CTX *ctx) { - X509 *x, *xtmp, *chain_ss = NULL; + X509 *x, *xtmp, *xtmp2, *chain_ss = NULL; int bad_chain = 0; X509_VERIFY_PARAM *param = ctx->param; int depth, i, ok = 0; - int num; + int num, j, retry; int (*cb) (int xok, X509_STORE_CTX *xctx); STACK_OF(X509) *sktmp = NULL; if (ctx->cert == NULL) { X509err(X509_F_X509_VERIFY_CERT, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); return -1; } + if (ctx->chain != NULL) { + /* + * This X509_STORE_CTX has already been used to verify a cert. We + * cannot do another one. + */ + X509err(X509_F_X509_VERIFY_CERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return -1; + } cb = ctx->verify_cb; @@ -206,15 +208,13 @@ int X509_verify_cert(X509_STORE_CTX *ctx) * first we make sure the chain we are going to build is present and that * the first entry is in place */ - if (ctx->chain == NULL) { - if (((ctx->chain = sk_X509_new_null()) == NULL) || - (!sk_X509_push(ctx->chain, ctx->cert))) { - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - goto end; - } - CRYPTO_add(&ctx->cert->references, 1, CRYPTO_LOCK_X509); - ctx->last_untrusted = 1; + if (((ctx->chain = sk_X509_new_null()) == NULL) || + (!sk_X509_push(ctx->chain, ctx->cert))) { + X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + goto end; } + X509_up_ref(ctx->cert); + ctx->last_untrusted = 1; /* We use a temporary STACK so we can chop and hack at it */ if (ctx->untrusted != NULL @@ -244,7 +244,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) { ok = ctx->get_issuer(&xtmp, ctx, x); if (ok < 0) - return ok; + goto end; /* * If successful for now free up cert so it will be picked up * again later. @@ -263,7 +263,7 @@ int X509_verify_cert(X509_STORE_CTX *ctx) X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); goto end; } - CRYPTO_add(&xtmp->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(xtmp); (void)sk_X509_delete_ptr(sktmp, xtmp); ctx->last_untrusted++; x = xtmp; @@ -277,91 +277,137 @@ int X509_verify_cert(X509_STORE_CTX *ctx) break; } + /* Remember how many untrusted certs we have */ + j = num; /* * at this point, chain should contain a list of untrusted certificates. * We now need to add at least one trusted one, if possible, otherwise we * complain. */ - /* - * Examine last certificate in chain and see if it is self signed. - */ - - i = sk_X509_num(ctx->chain); - x = sk_X509_value(ctx->chain, i - 1); - if (cert_self_signed(x)) { - /* we have a self signed certificate */ - if (sk_X509_num(ctx->chain) == 1) { - /* - * We have a single self signed certificate: see if we can find - * it in the store. We must have an exact match to avoid possible - * impersonation. - */ - ok = ctx->get_issuer(&xtmp, ctx, x); - if ((ok <= 0) || X509_cmp(x, xtmp)) { - ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; - ctx->current_cert = x; - ctx->error_depth = i - 1; - if (ok == 1) - X509_free(xtmp); - bad_chain = 1; - ok = cb(0, ctx); - if (!ok) - goto end; + do { + /* + * Examine last certificate in chain and see if it is self signed. + */ + i = sk_X509_num(ctx->chain); + x = sk_X509_value(ctx->chain, i - 1); + if (cert_self_signed(x)) { + /* we have a self signed certificate */ + if (sk_X509_num(ctx->chain) == 1) { + /* + * We have a single self signed certificate: see if we can + * find it in the store. We must have an exact match to avoid + * possible impersonation. + */ + ok = ctx->get_issuer(&xtmp, ctx, x); + if ((ok <= 0) || X509_cmp(x, xtmp)) { + ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + ctx->current_cert = x; + ctx->error_depth = i - 1; + if (ok == 1) + X509_free(xtmp); + bad_chain = 1; + ok = cb(0, ctx); + if (!ok) + goto end; + } else { + /* + * We have a match: replace certificate with store + * version so we get any trust settings. + */ + X509_free(x); + x = xtmp; + (void)sk_X509_set(ctx->chain, i - 1, x); + ctx->last_untrusted = 0; + } } else { /* - * We have a match: replace certificate with store version so - * we get any trust settings. + * extract and save self signed certificate for later use */ - X509_free(x); - x = xtmp; - (void)sk_X509_set(ctx->chain, i - 1, x); - ctx->last_untrusted = 0; + chain_ss = sk_X509_pop(ctx->chain); + ctx->last_untrusted--; + num--; + j--; + x = sk_X509_value(ctx->chain, num - 1); } - } else { - /* - * extract and save self signed certificate for later use - */ - chain_ss = sk_X509_pop(ctx->chain); - ctx->last_untrusted--; - num--; - x = sk_X509_value(ctx->chain, num - 1); } - } - - /* We now lookup certs from the certificate store */ - for (;;) { - /* If we have enough, we break */ - if (depth < num) - break; + /* We now lookup certs from the certificate store */ + for (;;) { + /* If we have enough, we break */ + if (depth < num) + break; + /* If we are self signed, we break */ + if (cert_self_signed(x)) + break; + ok = ctx->get_issuer(&xtmp, ctx, x); - /* If we are self signed, we break */ - if (cert_self_signed(x)) - break; + if (ok < 0) + goto end; + if (ok == 0) + break; + x = xtmp; + if (!sk_X509_push(ctx->chain, x)) { + X509_free(xtmp); + X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); + ok = 0; + goto done; + } + num++; + } - ok = ctx->get_issuer(&xtmp, ctx, x); + /* we now have our chain, lets check it... */ + i = check_trust(ctx); - if (ok < 0) - return ok; - if (ok == 0) - break; + /* If explicitly rejected error */ + if (i == X509_TRUST_REJECTED) + goto end; + /* + * If it's not explicitly trusted then check if there is an alternative + * chain that could be used. We only do this if we haven't already + * checked via TRUSTED_FIRST and the user hasn't switched off alternate + * chain checking + */ + retry = 0; + if (i != X509_TRUST_TRUSTED + && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) + && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) { + while (j-- > 1) { + STACK_OF(X509) *chtmp = ctx->chain; + xtmp2 = sk_X509_value(ctx->chain, j - 1); + /* + * Temporarily set chain to NULL so we don't discount + * duplicates: the same certificate could be an untrusted + * CA found in the trusted store. + */ + ctx->chain = NULL; + ok = ctx->get_issuer(&xtmp, ctx, xtmp2); + ctx->chain = chtmp; + if (ok < 0) + goto end; + /* Check if we found an alternate chain */ + if (ok > 0) { + /* + * Free up the found cert we'll add it again later + */ + X509_free(xtmp); - x = xtmp; - if (!sk_X509_push(ctx->chain, x)) { - X509_free(xtmp); - X509err(X509_F_X509_VERIFY_CERT, ERR_R_MALLOC_FAILURE); - return 0; + /* + * Dump all the certs above this point - we've found an + * alternate chain + */ + while (num > j) { + xtmp = sk_X509_pop(ctx->chain); + X509_free(xtmp); + num--; + } + ctx->last_untrusted = sk_X509_num(ctx->chain); + retry = 1; + break; + } + } } - num++; - } - - /* we now have our chain, lets check it... */ + } while (retry); - i = check_trust(ctx); - - /* If explicitly rejected error */ - if (i == X509_TRUST_REJECTED) - goto end; /* * If not explicitly trusted then indicate error unless it's a single * self signed certificate in which case we've indicated an error already @@ -452,16 +498,14 @@ int X509_verify_cert(X509_STORE_CTX *ctx) /* If we get this far evaluate policies */ if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK)) ok = ctx->check_policy(ctx); - if (!ok) - goto end; - if (0) { + if (ok) + goto done; + end: - X509_get_pubkey_parameters(NULL, ctx->chain); - } - if (sktmp != NULL) - sk_X509_free(sktmp); - if (chain_ss != NULL) - X509_free(chain_ss); + X509_get_pubkey_parameters(NULL, ctx->chain); + done: + sk_X509_free(sktmp); + X509_free(chain_ss); return ok; } @@ -525,7 +569,7 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) { *issuer = find_issuer(ctx, ctx->other_ctx, x); if (*issuer) { - CRYPTO_add(&(*issuer)->references, 1, CRYPTO_LOCK_X509); + X509_up_ref(*issuer); return 1; } else return 0; @@ -538,9 +582,6 @@ static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) static int check_chain_extensions(X509_STORE_CTX *ctx) { -#ifdef OPENSSL_NO_CHAIN_VERIFY - return 1; -#else int i, ok = 0, must_be_ca, plen = 0; X509 *x; int (*cb) (int xok, X509_STORE_CTX *xctx); @@ -549,15 +590,15 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) int allow_proxy_certs; cb = ctx->verify_cb; - /*- - * must_be_ca can have 1 of 3 values: - * -1: we accept both CA and non-CA certificates, to allow direct - * use of self-signed certificates (which are marked as CA). - * 0: we only accept non-CA certificates. This is currently not - * used, but the possibility is present for future extensions. - * 1: we only accept CA certificates. This is currently used for - * all certificates in the chain except the leaf certificate. - */ + /*- + * must_be_ca can have 1 of 3 values: + * -1: we accept both CA and non-CA certificates, to allow direct + * use of self-signed certificates (which are marked as CA). + * 0: we only accept non-CA certificates. This is currently not + * used, but the possibility is present for future extensions. + * 1: we only accept CA certificates. This is currently used for + * all certificates in the chain except the leaf certificate. + */ must_be_ca = -1; /* CRL path validation */ @@ -680,7 +721,6 @@ static int check_chain_extensions(X509_STORE_CTX *ctx) ok = 1; end: return ok; -#endif } static int check_name_constraints(X509_STORE_CTX *ctx) @@ -730,6 +770,10 @@ static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id) int n = sk_OPENSSL_STRING_num(id->hosts); char *name; + if (id->peername != NULL) { + OPENSSL_free(id->peername); + id->peername = NULL; + } for (i = 0; i < n; ++i) { name = sk_OPENSSL_STRING_value(id->hosts, i); if (X509_check_host(x, name, 0, id->hostflags, &id->peername) > 0) @@ -811,7 +855,7 @@ static int check_trust(X509_STORE_CTX *ctx) static int check_revocation(X509_STORE_CTX *ctx) { - int i, last, ok; + int i = 0, last = 0, ok = 0; if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) return 1; if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) @@ -834,9 +878,9 @@ static int check_revocation(X509_STORE_CTX *ctx) static int check_cert(X509_STORE_CTX *ctx) { X509_CRL *crl = NULL, *dcrl = NULL; - X509 *x; - int ok, cnum; - unsigned int last_reasons; + X509 *x = NULL; + int ok = 0, cnum = 0; + unsigned int last_reasons = 0; cnum = ctx->error_depth; x = sk_X509_value(ctx->chain, cnum); ctx->current_cert = x; @@ -913,6 +957,8 @@ static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) ctx->current_crl = crl; if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; else ptime = NULL; @@ -983,17 +1029,14 @@ static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl, } if (best_crl) { - if (*pcrl) - X509_CRL_free(*pcrl); + X509_CRL_free(*pcrl); *pcrl = best_crl; *pissuer = best_crl_issuer; *pscore = best_score; *preasons = best_reasons; - CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509_CRL); - if (*pdcrl) { - X509_CRL_free(*pdcrl); - *pdcrl = NULL; - } + X509_CRL_up_ref(best_crl); + X509_CRL_free(*pdcrl); + *pdcrl = NULL; get_delta_sk(ctx, pdcrl, pscore, best_crl, crls); } @@ -1089,7 +1132,7 @@ static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore, if (check_delta_base(delta, base)) { if (check_crl_time(ctx, delta, 0)) *pscore |= CRL_SCORE_TIME_DELTA; - CRYPTO_add(&delta->references, 1, CRYPTO_LOCK_X509_CRL); + X509_CRL_up_ref(delta); *dcrl = delta; return; } @@ -1636,6 +1679,8 @@ int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet) if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) ptime = &ctx->param->check_time; + else if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) + return 1; else ptime = NULL; @@ -1780,47 +1825,84 @@ int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) ASN1_TIME atm; long offset; char buff1[24], buff2[24], *p; - int i, j; + int i, j, remaining; p = buff1; - i = ctm->length; + remaining = ctm->length; str = (char *)ctm->data; + /* + * Note that the following (historical) code allows much more slack in the + * time format than RFC5280. In RFC5280, the representation is fixed: + * UTCTime: YYMMDDHHMMSSZ + * GeneralizedTime: YYYYMMDDHHMMSSZ + */ if (ctm->type == V_ASN1_UTCTIME) { - if ((i < 11) || (i > 17)) + /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */ + int min_length = sizeof("YYMMDDHHMMZ") - 1; + int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1; + if (remaining < min_length || remaining > max_length) return 0; memcpy(p, str, 10); p += 10; str += 10; + remaining -= 10; } else { - if (i < 13) + /* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */ + int min_length = sizeof("YYYYMMDDHHMMZ") - 1; + int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1; + if (remaining < min_length || remaining > max_length) return 0; memcpy(p, str, 12); p += 12; str += 12; + remaining -= 12; } if ((*str == 'Z') || (*str == '-') || (*str == '+')) { *(p++) = '0'; *(p++) = '0'; } else { + /* SS (seconds) */ + if (remaining < 2) + return 0; *(p++) = *(str++); *(p++) = *(str++); - /* Skip any fractional seconds... */ - if (*str == '.') { + remaining -= 2; + /* + * Skip any (up to three) fractional seconds... + * TODO(emilia): in RFC5280, fractional seconds are forbidden. + * Can we just kill them altogether? + */ + if (remaining && *str == '.') { str++; - while ((*str >= '0') && (*str <= '9')) - str++; + remaining--; + for (i = 0; i < 3 && remaining; i++, str++, remaining--) { + if (*str < '0' || *str > '9') + break; + } } } *(p++) = 'Z'; *(p++) = '\0'; - if (*str == 'Z') + /* We now need either a terminating 'Z' or an offset. */ + if (!remaining) + return 0; + if (*str == 'Z') { + if (remaining != 1) + return 0; offset = 0; - else { + } else { + /* (+-)HHMM */ if ((*str != '+') && (*str != '-')) return 0; + /* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */ + if (remaining != 5) + return 0; + if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' || + str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9') + return 0; offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; offset += (str[3] - '0') * 10 + (str[4] - '0'); if (*str == '-') @@ -1900,10 +1982,8 @@ int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain) } if (!EVP_PKEY_missing_parameters(ktmp)) break; - else { - EVP_PKEY_free(ktmp); - ktmp = NULL; - } + EVP_PKEY_free(ktmp); + ktmp = NULL; } if (ktmp == NULL) { X509err(X509_F_X509_GET_PUBKEY_PARAMETERS, @@ -2008,7 +2088,7 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, * Add only if not also in base. TODO: need something cleverer here * for some more complex CRLs covering multiple CAs. */ - if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) { + if (!X509_CRL_get0_by_serial(base, &rvtmp, &rvn->serialNumber)) { rvtmp = X509_REVOKED_dup(rvn); if (!rvtmp) goto memerr; @@ -2027,8 +2107,7 @@ X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer, memerr: X509err(X509_F_X509_CRL_DIFF, ERR_R_MALLOC_FAILURE); - if (crl) - X509_CRL_free(crl); + X509_CRL_free(crl); return NULL; } @@ -2186,18 +2265,19 @@ int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose, X509_STORE_CTX *X509_STORE_CTX_new(void) { - X509_STORE_CTX *ctx; - ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX)); + X509_STORE_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + if (!ctx) { X509err(X509_F_X509_STORE_CTX_NEW, ERR_R_MALLOC_FAILURE); return NULL; } - memset(ctx, 0, sizeof(X509_STORE_CTX)); return ctx; } void X509_STORE_CTX_free(X509_STORE_CTX *ctx) { + if (!ctx) + return; X509_STORE_CTX_cleanup(ctx); OPENSSL_free(ctx); } @@ -2206,6 +2286,7 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, STACK_OF(X509) *chain) { int ret = 1; + ctx->ctx = store; ctx->current_method = 0; ctx->cert = x509; @@ -2226,37 +2307,12 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->tree = NULL; ctx->parent = NULL; - ctx->param = X509_VERIFY_PARAM_new(); - - if (!ctx->param) { - X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - return 0; - } - - /* - * Inherit callbacks and flags from X509_STORE if not set use defaults. - */ - - if (store) - ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); - else - ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; - if (store) { ctx->verify_cb = store->verify_cb; ctx->cleanup = store->cleanup; } else ctx->cleanup = 0; - if (ret) - ret = X509_VERIFY_PARAM_inherit(ctx->param, - X509_VERIFY_PARAM_lookup("default")); - - if (ret == 0) { - X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - return 0; - } - if (store && store->check_issued) ctx->check_issued = store->check_issued; else @@ -2310,18 +2366,46 @@ int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509, ctx->check_policy = check_policy; /* - * This memset() can't make any sense anyway, so it's removed. As - * X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we put a - * corresponding "new" here and remove this bogus initialisation. + * For ctx->cleanup running well in X509_STORE_CTX_cleanup , + * initial all ctx before exceptional handling. + */ + ctx->param = X509_VERIFY_PARAM_new(); + if (ctx->param == NULL) { + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * Inherit callbacks and flags from X509_STORE if not set use defaults. + */ + if (store) + ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param); + else + ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE; + + if (ret) + ret = X509_VERIFY_PARAM_inherit(ctx->param, + X509_VERIFY_PARAM_lookup("default")); + + if (ret == 0) { + X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); + goto err; + } + + /* + * Since X509_STORE_CTX_cleanup does a proper "free" on the ex_data, we + * put a corresponding "new" here. */ - /* memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA)); */ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data))) { - OPENSSL_free(ctx); X509err(X509_F_X509_STORE_CTX_INIT, ERR_R_MALLOC_FAILURE); - return 0; + goto err; } return 1; + +err: + X509_STORE_CTX_cleanup(ctx); + return 0; } /* @@ -2344,16 +2428,12 @@ void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) X509_VERIFY_PARAM_free(ctx->param); ctx->param = NULL; } - if (ctx->tree != NULL) { - X509_policy_tree_free(ctx->tree); - ctx->tree = NULL; - } - if (ctx->chain != NULL) { - sk_X509_pop_free(ctx->chain, X509_free); - ctx->chain = NULL; - } + X509_policy_tree_free(ctx->tree); + ctx->tree = NULL; + sk_X509_pop_free(ctx->chain, X509_free); + ctx->chain = NULL; CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data)); - memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA)); + memset(&ctx->ex_data, 0, sizeof(ctx->ex_data)); } void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) @@ -2388,6 +2468,11 @@ int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx) return ctx->explicit_policy; } +int X509_STORE_CTX_get_num_untrusted(X509_STORE_CTX *ctx) +{ + return ctx->last_untrusted; +} + int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) { const X509_VERIFY_PARAM *param; @@ -2404,17 +2489,6 @@ X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) { - if (ctx->param) - X509_VERIFY_PARAM_free(ctx->param); + X509_VERIFY_PARAM_free(ctx->param); ctx->param = param; } - -IMPLEMENT_STACK_OF(X509) - -IMPLEMENT_ASN1_SET_OF(X509) - -IMPLEMENT_STACK_OF(X509_NAME) - -IMPLEMENT_STACK_OF(X509_ATTRIBUTE) - -IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)