x509_lu.c revision 296341
12432Sse/* crypto/x509/x509_lu.c */
22432Sse/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
32432Sse * All rights reserved.
439247Sgibbs *
52432Sse * This package is an SSL implementation written
62432Sse * by Eric Young (eay@cryptsoft.com).
72432Sse * The implementation was written so as to conform with Netscapes SSL.
82432Sse *
97228Sse * This library is free for commercial and non-commercial use as long as
103533Sse * the following conditions are aheared to.  The following conditions
112432Sse * apply to all code found in this distribution, be it the RC4, RSA,
122432Sse * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13139834Sscottl * included with this distribution is covered by the same copyright terms
14139825Simp * except that the holder is Tim Hudson (tjh@cryptsoft.com).
152432Sse *
162432Sse * Copyright remains Eric Young's, and as such any Copyright notices in
172432Sse * the code are not to be removed.
182432Sse * If this package is used in a product, Eric Young should be given attribution
192432Sse * as the author of the parts of the library used.
202432Sse * This can be in the form of a textual message at program startup or
212432Sse * in documentation (online or textual) provided with the package.
222432Sse *
232432Sse * Redistribution and use in source and binary forms, with or without
242432Sse * modification, are permitted provided that the following conditions
252432Sse * are met:
262432Sse * 1. Redistributions of source code must retain the copyright
272432Sse *    notice, this list of conditions and the following disclaimer.
282432Sse * 2. Redistributions in binary form must reproduce the above copyright
292432Sse *    notice, this list of conditions and the following disclaimer in the
302432Sse *    documentation and/or other materials provided with the distribution.
312432Sse * 3. All advertising materials mentioning features or use of this software
322432Sse *    must display the following acknowledgement:
332432Sse *    "This product includes cryptographic software written by
342432Sse *     Eric Young (eay@cryptsoft.com)"
352432Sse *    The word 'cryptographic' can be left out if the rouines from the library
362432Sse *    being used are not cryptographic related :-).
372432Sse * 4. If you include any Windows specific code (or a derivative thereof) from
382432Sse *    the apps directory (application code) you must include an acknowledgement:
393533Sse *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
402432Sse *
412432Sse * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42116192Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43116192Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44116192Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45116192Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
469429Sse * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
477228Sse * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855206Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4920535Sse * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055206Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5120517Sse * SUCH DAMAGE.
522432Sse *
532432Sse * The licence and distribution terms for any publically available version or
542432Sse * derivative of this code cannot be changed.  i.e. this code cannot simply be
552432Sse * copied and put under another distribution licence
566460Sse * [including the GNU Public Licence.]
572432Sse */
582432Sse
592432Sse#include <stdio.h>
602432Sse#include "cryptlib.h"
612432Sse#include <openssl/lhash.h>
622432Sse#include <openssl/x509.h>
632432Sse#include <openssl/x509v3.h>
642432Sse
652432SseX509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
662432Sse{
672432Sse    X509_LOOKUP *ret;
682432Sse
692432Sse    ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
702432Sse    if (ret == NULL)
712432Sse        return NULL;
7227684Sse
732432Sse    ret->init = 0;
7427684Sse    ret->skip = 0;
752432Sse    ret->method = method;
762432Sse    ret->method_data = NULL;
7727684Sse    ret->store_ctx = NULL;
782432Sse    if ((method->new_item != NULL) && !method->new_item(ret)) {
7927684Sse        OPENSSL_free(ret);
8027684Sse        return NULL;
8127684Sse    }
8227684Sse    return ret;
8327684Sse}
8427684Sse
8527684Ssevoid X509_LOOKUP_free(X509_LOOKUP *ctx)
8627684Sse{
8727684Sse    if (ctx == NULL)
8827684Sse        return;
8927684Sse    if ((ctx->method != NULL) && (ctx->method->free != NULL))
9027684Sse        (*ctx->method->free) (ctx);
9127684Sse    OPENSSL_free(ctx);
9227684Sse}
932432Sse
9427684Sseint X509_LOOKUP_init(X509_LOOKUP *ctx)
9527684Sse{
9627684Sse    if (ctx->method == NULL)
9727684Sse        return 0;
9827684Sse    if (ctx->method->init != NULL)
9927684Sse        return ctx->method->init(ctx);
10027684Sse    else
10127684Sse        return 1;
10227684Sse}
1032814Sse
1042814Sseint X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
1052814Sse{
1062814Sse    if (ctx->method == NULL)
1072814Sse        return 0;
1083939Sse    if (ctx->method->shutdown != NULL)
1092814Sse        return ctx->method->shutdown(ctx);
1102814Sse    else
1112432Sse        return 1;
1122432Sse}
1132432Sse
1142432Sseint X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
1152432Sse                     char **ret)
1162432Sse{
1172432Sse    if (ctx->method == NULL)
1182432Sse        return -1;
1192432Sse    if (ctx->method->ctrl != NULL)
1202432Sse        return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
1212432Sse    else
1222432Sse        return 1;
1232432Sse}
1242432Sse
12510605Sseint X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
1262432Sse                           X509_OBJECT *ret)
1272432Sse{
1282432Sse    if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
1292432Sse        return X509_LU_FAIL;
1302432Sse    if (ctx->skip)
1312432Sse        return 0;
1322432Sse    return ctx->method->get_by_subject(ctx, type, name, ret);
1332432Sse}
13414556Sse
13513481Sseint X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
13614556Sse                                 ASN1_INTEGER *serial, X509_OBJECT *ret)
1372432Sse{
1382432Sse    if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
1392432Sse        return X509_LU_FAIL;
1402432Sse    return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
14110605Sse}
1422432Sse
1432432Sseint X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
14439247Sgibbs                               unsigned char *bytes, int len,
1452432Sse                               X509_OBJECT *ret)
1462432Sse{
1472432Sse    if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
1482432Sse        return X509_LU_FAIL;
1492432Sse    return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
1502432Sse}
1512432Sse
1522432Sseint X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
1532432Sse                         X509_OBJECT *ret)
15415543Sphk{
1552432Sse    if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
1562432Sse        return X509_LU_FAIL;
15715543Sphk    return ctx->method->get_by_alias(ctx, type, str, len, ret);
1586526Sse}
1596526Sse
1606526Ssestatic int x509_object_cmp(const X509_OBJECT *const *a,
1616526Sse                           const X509_OBJECT *const *b)
1626526Sse{
1636526Sse    int ret;
1647228Sse
1652432Sse    ret = ((*a)->type - (*b)->type);
1662432Sse    if (ret)
1672432Sse        return ret;
1682432Sse    switch ((*a)->type) {
1692432Sse    case X509_LU_X509:
1702432Sse        ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
1712432Sse        break;
1722432Sse    case X509_LU_CRL:
1732432Sse        ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
1742432Sse        break;
17555206Speter    default:
1762432Sse        /* abort(); */
1772432Sse        return 0;
1782432Sse    }
179129878Sphk    return ret;
18012820Sphk}
181168752Sscottl
182168752SscottlX509_STORE *X509_STORE_new(void)
18360974Sdfr{
18448424Speter    X509_STORE *ret;
18560974Sdfr
18660974Sdfr    if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
18760974Sdfr        return NULL;
1882432Sse    ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
18912662Sdg    ret->cache = 1;
19010605Sse    ret->get_cert_methods = sk_X509_LOOKUP_new_null();
19155206Speter    ret->verify = 0;
1922432Sse    ret->verify_cb = 0;
193119288Simp
194119288Simp    if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
195272015Srpaulo        return NULL;
1962432Sse
19739247Sgibbs    ret->get_issuer = 0;
19839247Sgibbs    ret->check_issued = 0;
19939247Sgibbs    ret->check_revocation = 0;
20039247Sgibbs    ret->get_crl = 0;
20139247Sgibbs    ret->check_crl = 0;
2022432Sse    ret->cert_crl = 0;
20339247Sgibbs    ret->lookup_certs = 0;
20439247Sgibbs    ret->lookup_crls = 0;
2057228Sse    ret->cleanup = 0;
2062432Sse
2072432Sse    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
2082432Sse        sk_X509_OBJECT_free(ret->objs);
2092432Sse        OPENSSL_free(ret);
2102432Sse        return NULL;
2112432Sse    }
2122432Sse
2132432Sse    ret->references = 1;
2142432Sse    return ret;
2152432Sse}
2162432Sse
2172432Ssestatic void cleanup(X509_OBJECT *a)
2182432Sse{
2192432Sse    if (!a)
2202432Sse        return;
2212432Sse    if (a->type == X509_LU_X509) {
2222814Sse        X509_free(a->data.x509);
2232432Sse    } else if (a->type == X509_LU_CRL) {
2242432Sse        X509_CRL_free(a->data.crl);
2252814Sse    } else {
2262432Sse        /* abort(); */
2273552Sse    }
2283552Sse
2293552Sse    OPENSSL_free(a);
2303552Sse}
23120549Sse
2326766Ssevoid X509_STORE_free(X509_STORE *vfy)
23320549Sse{
23420549Sse    int i;
2353552Sse    STACK_OF(X509_LOOKUP) *sk;
23620549Sse    X509_LOOKUP *lu;
2372432Sse
2382432Sse    if (vfy == NULL)
2393552Sse        return;
2402432Sse
2412432Sse    sk = vfy->get_cert_methods;
2422432Sse    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
2432432Sse        lu = sk_X509_LOOKUP_value(sk, i);
2442432Sse        X509_LOOKUP_shutdown(lu);
2452432Sse        X509_LOOKUP_free(lu);
2462432Sse    }
2472432Sse    sk_X509_LOOKUP_free(sk);
2482432Sse    sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
2492432Sse
2502432Sse    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
25139247Sgibbs    if (vfy->param)
25239247Sgibbs        X509_VERIFY_PARAM_free(vfy->param);
253170027Srwatson    OPENSSL_free(vfy);
2542432Sse}
25539247Sgibbs
25639247SgibbsX509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
25739247Sgibbs{
25839247Sgibbs    int i;
25939247Sgibbs    STACK_OF(X509_LOOKUP) *sk;
26039247Sgibbs    X509_LOOKUP *lu;
26139247Sgibbs
26239247Sgibbs    sk = v->get_cert_methods;
26339247Sgibbs    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
2647228Sse        lu = sk_X509_LOOKUP_value(sk, i);
2652432Sse        if (m == lu->method) {
2662432Sse            return lu;
2672432Sse        }
2682432Sse    }
2692432Sse    /* a new one */
2702432Sse    lu = X509_LOOKUP_new(m);
2712432Sse    if (lu == NULL)
272272121Sjhb        return NULL;
273272121Sjhb    else {
274272121Sjhb        lu->store_ctx = v;
2756401Sse        if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
276272121Sjhb            return lu;
277272121Sjhb        else {
278272121Sjhb            X509_LOOKUP_free(lu);
279272121Sjhb            return NULL;
2806401Sse        }
281272121Sjhb    }
282272121Sjhb}
283272121Sjhb
2846401Sseint X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
28560974Sdfr                              X509_OBJECT *ret)
28660974Sdfr{
287272121Sjhb    X509_STORE *ctx = vs->ctx;
28827744Sse    X509_LOOKUP *lu;
28960974Sdfr    X509_OBJECT stmp, *tmp;
29060974Sdfr    int i, j;
29160974Sdfr
29260974Sdfr    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
29360974Sdfr    tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
29460974Sdfr    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
295272121Sjhb
29639532Sken    if (tmp == NULL || type == X509_LU_CRL) {
29739532Sken        for (i = vs->current_method;
29839532Sken             i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
29939532Sken            lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
30039532Sken            j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
30139532Sken            if (j < 0) {
30239532Sken                vs->current_method = j;
30339532Sken                return j;
30427684Sse            } else if (j) {
30527684Sse                tmp = &stmp;
30627684Sse                break;
30727684Sse            }
30827684Sse        }
30927684Sse        vs->current_method = 0;
31027684Sse        if (tmp == NULL)
31127684Sse            return 0;
31227684Sse    }
31327684Sse
31427684Sse/*- if (ret->data.ptr != NULL)
3152432Sse            X509_OBJECT_free_contents(ret); */
3162432Sse
3172432Sse    ret->type = tmp->type;
3182432Sse    ret->data.ptr = tmp->data.ptr;
3192432Sse
3202432Sse    X509_OBJECT_up_ref_count(ret);
3212432Sse
32210567Sse    return 1;
32310567Sse}
32410567Sse
32510567Sseint X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
3262432Sse{
32710567Sse    X509_OBJECT *obj;
32810567Sse    int ret = 1;
3297228Sse
33010567Sse    if (x == NULL)
33110567Sse        return 0;
33210567Sse    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
33310567Sse    if (obj == NULL) {
33439247Sgibbs        X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
3352432Sse        return 0;
3362814Sse    }
3372814Sse    obj->type = X509_LU_X509;
3382432Sse    obj->data.x509 = x;
3392432Sse
3406705Sse    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
3412432Sse
3422432Sse    X509_OBJECT_up_ref_count(obj);
3432432Sse
3442432Sse    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
3452814Sse        X509_OBJECT_free_contents(obj);
3462814Sse        OPENSSL_free(obj);
3472814Sse        X509err(X509_F_X509_STORE_ADD_CERT,
3482814Sse                X509_R_CERT_ALREADY_IN_HASH_TABLE);
3492814Sse        ret = 0;
3502814Sse    } else
3512814Sse        sk_X509_OBJECT_push(ctx->objs, obj);
3522814Sse
3532814Sse    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
3542814Sse
3552814Sse    return ret;
3562814Sse}
3572814Sse
3587228Sseint X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
3592814Sse{
3602814Sse    X509_OBJECT *obj;
3612814Sse    int ret = 1;
36239247Sgibbs
3632814Sse    if (x == NULL)
3642814Sse        return 0;
3652814Sse    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
3662432Sse    if (obj == NULL) {
3672814Sse        X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
3682814Sse        return 0;
3692814Sse    }
3702814Sse    obj->type = X509_LU_CRL;
3712432Sse    obj->data.crl = x;
3722432Sse
3732814Sse    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
37439247Sgibbs
3752432Sse    X509_OBJECT_up_ref_count(obj);
3762432Sse
3772432Sse    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
3782432Sse        X509_OBJECT_free_contents(obj);
3792814Sse        OPENSSL_free(obj);
3802814Sse        X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE);
3812814Sse        ret = 0;
3822814Sse    } else
3832814Sse        sk_X509_OBJECT_push(ctx->objs, obj);
38439247Sgibbs
38539247Sgibbs    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
3862814Sse
38739247Sgibbs    return ret;
38839247Sgibbs}
3892814Sse
3902814Ssevoid X509_OBJECT_up_ref_count(X509_OBJECT *a)
3912814Sse{
3922814Sse    switch (a->type) {
3932814Sse    case X509_LU_X509:
3942814Sse        CRYPTO_add(&a->data.x509->references, 1, CRYPTO_LOCK_X509);
39539247Sgibbs        break;
39639247Sgibbs    case X509_LU_CRL:
39739247Sgibbs        CRYPTO_add(&a->data.crl->references, 1, CRYPTO_LOCK_X509_CRL);
3982814Sse        break;
3992814Sse    }
4002814Sse}
4012814Sse
4022814Ssevoid X509_OBJECT_free_contents(X509_OBJECT *a)
4032814Sse{
4042814Sse    switch (a->type) {
4052814Sse    case X509_LU_X509:
4062814Sse        X509_free(a->data.x509);
4072814Sse        break;
40839247Sgibbs    case X509_LU_CRL:
4097228Sse        X509_CRL_free(a->data.crl);
4102432Sse        break;
4112432Sse    }
4122432Sse}
4132432Sse
4142432Ssestatic int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
4152432Sse                               X509_NAME *name, int *pnmatch)
4162432Sse{
41739247Sgibbs    X509_OBJECT stmp;
4187228Sse    X509 x509_s;
4192432Sse    X509_CINF cinf_s;
4202432Sse    X509_CRL crl_s;
4212432Sse    X509_CRL_INFO crl_info_s;
4222432Sse    int idx;
4232432Sse
4242432Sse    stmp.type = type;
4252432Sse    switch (type) {
4262432Sse    case X509_LU_X509:
4272432Sse        stmp.data.x509 = &x509_s;
42839247Sgibbs        x509_s.cert_info = &cinf_s;
4292432Sse        cinf_s.subject = name;
4302432Sse        break;
4312432Sse    case X509_LU_CRL:
4322432Sse        stmp.data.crl = &crl_s;
4332432Sse        crl_s.crl = &crl_info_s;
4342432Sse        crl_info_s.issuer = name;
43539247Sgibbs        break;
4362432Sse    default:
4372432Sse        /* abort(); */
43828960Sse        return -1;
43928960Sse    }
4402432Sse
4412432Sse    idx = sk_X509_OBJECT_find(h, &stmp);
4422432Sse    if (idx >= 0 && pnmatch) {
4432432Sse        int tidx;
4442432Sse        const X509_OBJECT *tobj, *pstmp;
4452432Sse        *pnmatch = 1;
4462432Sse        pstmp = &stmp;
4472432Sse        for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
4482432Sse            tobj = sk_X509_OBJECT_value(h, tidx);
4492432Sse            if (x509_object_cmp(&tobj, &pstmp))
4502432Sse                break;
4512432Sse            (*pnmatch)++;
4522432Sse        }
4532435Sse    }
4542435Sse    return idx;
4552432Sse}
4562814Sse
4572814Sseint X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
4582432Sse                               X509_NAME *name)
4592432Sse{
4602432Sse    return x509_object_idx_cnt(h, type, name, NULL);
4612432Sse}
4622432Sse
4632432SseX509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
4642432Sse                                             int type, X509_NAME *name)
46539554Sgibbs{
46639554Sgibbs    int idx;
46739554Sgibbs    idx = X509_OBJECT_idx_by_subject(h, type, name);
4682432Sse    if (idx == -1)
46939554Sgibbs        return NULL;
47039554Sgibbs    return sk_X509_OBJECT_value(h, idx);
47139554Sgibbs}
47239554Sgibbs
47339554SgibbsSTACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
47439554Sgibbs{
47539554Sgibbs    int i, idx, cnt;
4762432Sse    STACK_OF(X509) *sk;
4772432Sse    X509 *x;
4782432Sse    X509_OBJECT *obj;
4792432Sse    sk = sk_X509_new_null();
4802432Sse    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
4812432Sse    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
4822432Sse    if (idx < 0) {
4832432Sse        /*
4842432Sse         * Nothing found in cache: do lookup to possibly add new objects to
4852432Sse         * cache
4862432Sse         */
4872432Sse        X509_OBJECT xobj;
4882432Sse        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
4892432Sse        if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
4902432Sse            sk_X509_free(sk);
4912432Sse            return NULL;
4922432Sse        }
4932432Sse        X509_OBJECT_free_contents(&xobj);
4947228Sse        CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
4952432Sse        idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
4962432Sse        if (idx < 0) {
4977228Sse            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
4982432Sse            sk_X509_free(sk);
4992432Sse            return NULL;
5002432Sse        }
5012432Sse    }
50239247Sgibbs    for (i = 0; i < cnt; i++, idx++) {
50339247Sgibbs        obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
50439247Sgibbs        x = obj->data.x509;
50539247Sgibbs        CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
50639247Sgibbs        if (!sk_X509_push(sk, x)) {
50739247Sgibbs            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
50839247Sgibbs            X509_free(x);
50939247Sgibbs            sk_X509_pop_free(sk, X509_free);
51039247Sgibbs            return NULL;
51139247Sgibbs        }
51239247Sgibbs    }
51339247Sgibbs    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
51439247Sgibbs    return sk;
51539247Sgibbs
51639247Sgibbs}
51739247Sgibbs
51839247SgibbsSTACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
51939247Sgibbs{
52039247Sgibbs    int i, idx, cnt;
52139247Sgibbs    STACK_OF(X509_CRL) *sk;
52239247Sgibbs    X509_CRL *x;
52339247Sgibbs    X509_OBJECT *obj, xobj;
52439247Sgibbs    sk = sk_X509_CRL_new_null();
52539247Sgibbs    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
52639247Sgibbs    /* Check cache first */
52739247Sgibbs    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
5282432Sse
5292432Sse    /*
5302432Sse     * Always do lookup to possibly add new CRLs to cache
5317228Sse     */
5322432Sse    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
5332432Sse    if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
5342432Sse        sk_X509_CRL_free(sk);
5357228Sse        return NULL;
5362432Sse    }
5372432Sse    X509_OBJECT_free_contents(&xobj);
5382432Sse    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
5392432Sse    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
5402432Sse    if (idx < 0) {
5412432Sse        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
5422814Sse        sk_X509_CRL_free(sk);
5432814Sse        return NULL;
5442432Sse    }
5452432Sse
5462432Sse    for (i = 0; i < cnt; i++, idx++) {
5472432Sse        obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
5482814Sse        x = obj->data.crl;
5492814Sse        CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
5502814Sse        if (!sk_X509_CRL_push(sk, x)) {
5512432Sse            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
5522432Sse            X509_CRL_free(x);
5532814Sse            sk_X509_CRL_pop_free(sk, X509_CRL_free);
5542432Sse            return NULL;
5552432Sse        }
5562432Sse    }
5572432Sse    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
5582432Sse    return sk;
5592432Sse}
5602432Sse
5612432SseX509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
5622432Sse                                        X509_OBJECT *x)
5632432Sse{
5642432Sse    int idx, i;
5652432Sse    X509_OBJECT *obj;
5662432Sse    idx = sk_X509_OBJECT_find(h, x);
5672432Sse    if (idx == -1)
5682432Sse        return NULL;
5692432Sse    if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
57039247Sgibbs        return sk_X509_OBJECT_value(h, idx);
5712432Sse    for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
5722432Sse        obj = sk_X509_OBJECT_value(h, i);
5732432Sse        if (x509_object_cmp
5747228Sse            ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
5752432Sse            return NULL;
57639247Sgibbs        if (x->type == X509_LU_X509) {
5772432Sse            if (!X509_cmp(obj->data.x509, x->data.x509))
5782432Sse                return obj;
57939247Sgibbs        } else if (x->type == X509_LU_CRL) {
5802432Sse            if (!X509_CRL_match(obj->data.crl, x->data.crl))
5812432Sse                return obj;
58239247Sgibbs        } else
58327684Sse            return obj;
58427684Sse    }
58527684Sse    return NULL;
58627684Sse}
58739247Sgibbs
58827684Sse/*-
58927684Sse * Try to get issuer certificate from store. Due to limitations
5902432Sse * of the API this can only retrieve a single certificate matching
5912432Sse * a given subject name. However it will fill the cache with all
5922432Sse * matching certificates, so we can examine the cache for all
5932432Sse * matches.
5942432Sse *
5952432Sse * Return values are:
5962432Sse *  1 lookup successful.
5972432Sse *  0 certificate not found.
5982432Sse * -1 some other error.
5992432Sse */
6002432Sseint X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
60139247Sgibbs{
6022432Sse    X509_NAME *xn;
6032432Sse    X509_OBJECT obj, *pobj;
6042432Sse    int i, ok, idx, ret;
6052432Sse    xn = X509_get_issuer_name(x);
6062432Sse    ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj);
6072432Sse    if (ok != X509_LU_X509) {
6082432Sse        if (ok == X509_LU_RETRY) {
6097228Sse            X509_OBJECT_free_contents(&obj);
6102432Sse            X509err(X509_F_X509_STORE_CTX_GET1_ISSUER, X509_R_SHOULD_RETRY);
6112432Sse            return -1;
6127228Sse        } else if (ok != X509_LU_FAIL) {
6132432Sse            X509_OBJECT_free_contents(&obj);
6142432Sse            /* not good :-(, break anyway */
6152432Sse            return -1;
6162432Sse        }
6172432Sse        return 0;
6182432Sse    }
6192432Sse    /* If certificate matches all OK */
6202432Sse    if (ctx->check_issued(ctx, x, obj.data.x509)) {
6212432Sse        *issuer = obj.data.x509;
6222432Sse        return 1;
62310567Sse    }
6242432Sse    X509_OBJECT_free_contents(&obj);
6252432Sse
6262432Sse    /* Else find index of first cert accepted by 'check_issued' */
6272432Sse    ret = 0;
6282432Sse    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
6292432Sse    idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
6302432Sse    if (idx != -1) {            /* should be true as we've had at least one
6312432Sse                                 * match */
6322432Sse        /* Look through all matching certs for suitable issuer */
6332432Sse        for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
6342432Sse            pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
6352432Sse            /* See if we've run past the matches */
6362432Sse            if (pobj->type != X509_LU_X509)
6372432Sse                break;
6382432Sse            if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
6392432Sse                break;
6402432Sse            if (ctx->check_issued(ctx, x, pobj->data.x509)) {
64139247Sgibbs                *issuer = pobj->data.x509;
6422432Sse                X509_OBJECT_up_ref_count(pobj);
6432432Sse                ret = 1;
64439247Sgibbs                break;
6452432Sse            }
6462432Sse        }
64739247Sgibbs    }
6482432Sse    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
6492432Sse    return ret;
65039247Sgibbs}
6512432Sse
6522432Sseint X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
65339247Sgibbs{
6542432Sse    return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
6552432Sse}
6562432Sse
6572432Sseint X509_STORE_set_depth(X509_STORE *ctx, int depth)
6582432Sse{
65939247Sgibbs    X509_VERIFY_PARAM_set_depth(ctx->param, depth);
6602432Sse    return 1;
6612432Sse}
6622432Sse
6632432Sseint X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
6642432Sse{
6657228Sse    return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
6662432Sse}
6672432Sse
6682432Sseint X509_STORE_set_trust(X509_STORE *ctx, int trust)
6692432Sse{
6702432Sse    return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
6712432Sse}
67239247Sgibbs
6732432Sseint X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
6742432Sse{
6752432Sse    return X509_VERIFY_PARAM_set1(ctx->param, param);
6762432Sse}
6772432Sse
6782432Ssevoid X509_STORE_set_verify_cb(X509_STORE *ctx,
6792432Sse                              int (*verify_cb) (int, X509_STORE_CTX *))
6802432Sse{
6812432Sse    ctx->verify_cb = verify_cb;
6822432Sse}
68339247Sgibbs
6842432SseIMPLEMENT_STACK_OF(X509_LOOKUP)
6852432Sse
6862432SseIMPLEMENT_STACK_OF(X509_OBJECT)
6872432Sse