155714Skris/* crypto/x509/x509_lu.c */
255714Skris/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
355714Skris * All rights reserved.
455714Skris *
555714Skris * This package is an SSL implementation written
655714Skris * by Eric Young (eay@cryptsoft.com).
755714Skris * The implementation was written so as to conform with Netscapes SSL.
8296341Sdelphij *
955714Skris * This library is free for commercial and non-commercial use as long as
1055714Skris * the following conditions are aheared to.  The following conditions
1155714Skris * apply to all code found in this distribution, be it the RC4, RSA,
1255714Skris * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
1355714Skris * included with this distribution is covered by the same copyright terms
1455714Skris * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15296341Sdelphij *
1655714Skris * Copyright remains Eric Young's, and as such any Copyright notices in
1755714Skris * the code are not to be removed.
1855714Skris * If this package is used in a product, Eric Young should be given attribution
1955714Skris * as the author of the parts of the library used.
2055714Skris * This can be in the form of a textual message at program startup or
2155714Skris * in documentation (online or textual) provided with the package.
22296341Sdelphij *
2355714Skris * Redistribution and use in source and binary forms, with or without
2455714Skris * modification, are permitted provided that the following conditions
2555714Skris * are met:
2655714Skris * 1. Redistributions of source code must retain the copyright
2755714Skris *    notice, this list of conditions and the following disclaimer.
2855714Skris * 2. Redistributions in binary form must reproduce the above copyright
2955714Skris *    notice, this list of conditions and the following disclaimer in the
3055714Skris *    documentation and/or other materials provided with the distribution.
3155714Skris * 3. All advertising materials mentioning features or use of this software
3255714Skris *    must display the following acknowledgement:
3355714Skris *    "This product includes cryptographic software written by
3455714Skris *     Eric Young (eay@cryptsoft.com)"
3555714Skris *    The word 'cryptographic' can be left out if the rouines from the library
3655714Skris *    being used are not cryptographic related :-).
37296341Sdelphij * 4. If you include any Windows specific code (or a derivative thereof) from
3855714Skris *    the apps directory (application code) you must include an acknowledgement:
3955714Skris *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40296341Sdelphij *
4155714Skris * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
4255714Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4355714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4455714Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
4555714Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4655714Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4755714Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4955714Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5055714Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5155714Skris * SUCH DAMAGE.
52296341Sdelphij *
5355714Skris * The licence and distribution terms for any publically available version or
5455714Skris * derivative of this code cannot be changed.  i.e. this code cannot simply be
5555714Skris * copied and put under another distribution licence
5655714Skris * [including the GNU Public Licence.]
5755714Skris */
5855714Skris
5955714Skris#include <stdio.h>
6055714Skris#include "cryptlib.h"
6155714Skris#include <openssl/lhash.h>
6255714Skris#include <openssl/x509.h>
63109998Smarkm#include <openssl/x509v3.h>
6455714Skris
6555714SkrisX509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
66296341Sdelphij{
67296341Sdelphij    X509_LOOKUP *ret;
6855714Skris
69296341Sdelphij    ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
70296341Sdelphij    if (ret == NULL)
71296341Sdelphij        return NULL;
7255714Skris
73296341Sdelphij    ret->init = 0;
74296341Sdelphij    ret->skip = 0;
75296341Sdelphij    ret->method = method;
76296341Sdelphij    ret->method_data = NULL;
77296341Sdelphij    ret->store_ctx = NULL;
78296341Sdelphij    if ((method->new_item != NULL) && !method->new_item(ret)) {
79296341Sdelphij        OPENSSL_free(ret);
80296341Sdelphij        return NULL;
81296341Sdelphij    }
82296341Sdelphij    return ret;
83296341Sdelphij}
8455714Skris
8555714Skrisvoid X509_LOOKUP_free(X509_LOOKUP *ctx)
86296341Sdelphij{
87296341Sdelphij    if (ctx == NULL)
88296341Sdelphij        return;
89296341Sdelphij    if ((ctx->method != NULL) && (ctx->method->free != NULL))
90296341Sdelphij        (*ctx->method->free) (ctx);
91296341Sdelphij    OPENSSL_free(ctx);
92296341Sdelphij}
9355714Skris
9455714Skrisint X509_LOOKUP_init(X509_LOOKUP *ctx)
95296341Sdelphij{
96296341Sdelphij    if (ctx->method == NULL)
97296341Sdelphij        return 0;
98296341Sdelphij    if (ctx->method->init != NULL)
99296341Sdelphij        return ctx->method->init(ctx);
100296341Sdelphij    else
101296341Sdelphij        return 1;
102296341Sdelphij}
10355714Skris
10455714Skrisint X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
105296341Sdelphij{
106296341Sdelphij    if (ctx->method == NULL)
107296341Sdelphij        return 0;
108296341Sdelphij    if (ctx->method->shutdown != NULL)
109296341Sdelphij        return ctx->method->shutdown(ctx);
110296341Sdelphij    else
111296341Sdelphij        return 1;
112296341Sdelphij}
11355714Skris
11455714Skrisint X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
115296341Sdelphij                     char **ret)
116296341Sdelphij{
117296341Sdelphij    if (ctx->method == NULL)
118296341Sdelphij        return -1;
119296341Sdelphij    if (ctx->method->ctrl != NULL)
120296341Sdelphij        return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
121296341Sdelphij    else
122296341Sdelphij        return 1;
123296341Sdelphij}
12455714Skris
12555714Skrisint X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
126296341Sdelphij                           X509_OBJECT *ret)
127296341Sdelphij{
128296341Sdelphij    if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
129296341Sdelphij        return X509_LU_FAIL;
130296341Sdelphij    if (ctx->skip)
131296341Sdelphij        return 0;
132296341Sdelphij    return ctx->method->get_by_subject(ctx, type, name, ret);
133296341Sdelphij}
13455714Skris
13555714Skrisint X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
136296341Sdelphij                                 ASN1_INTEGER *serial, X509_OBJECT *ret)
137296341Sdelphij{
138296341Sdelphij    if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
139296341Sdelphij        return X509_LU_FAIL;
140296341Sdelphij    return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
141296341Sdelphij}
14255714Skris
14355714Skrisint X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
144296341Sdelphij                               unsigned char *bytes, int len,
145296341Sdelphij                               X509_OBJECT *ret)
146296341Sdelphij{
147296341Sdelphij    if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
148296341Sdelphij        return X509_LU_FAIL;
149296341Sdelphij    return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
150296341Sdelphij}
15155714Skris
15255714Skrisint X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
153296341Sdelphij                         X509_OBJECT *ret)
154296341Sdelphij{
155296341Sdelphij    if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
156296341Sdelphij        return X509_LU_FAIL;
157296341Sdelphij    return ctx->method->get_by_alias(ctx, type, str, len, ret);
158296341Sdelphij}
15955714Skris
160296341Sdelphijstatic int x509_object_cmp(const X509_OBJECT *const *a,
161296341Sdelphij                           const X509_OBJECT *const *b)
162296341Sdelphij{
163296341Sdelphij    int ret;
16455714Skris
165296341Sdelphij    ret = ((*a)->type - (*b)->type);
166296341Sdelphij    if (ret)
167296341Sdelphij        return ret;
168296341Sdelphij    switch ((*a)->type) {
169296341Sdelphij    case X509_LU_X509:
170296341Sdelphij        ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
171296341Sdelphij        break;
172296341Sdelphij    case X509_LU_CRL:
173296341Sdelphij        ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
174296341Sdelphij        break;
175296341Sdelphij    default:
176296341Sdelphij        /* abort(); */
177296341Sdelphij        return 0;
178296341Sdelphij    }
179296341Sdelphij    return ret;
180296341Sdelphij}
18155714Skris
18255714SkrisX509_STORE *X509_STORE_new(void)
183296341Sdelphij{
184296341Sdelphij    X509_STORE *ret;
18555714Skris
186296341Sdelphij    if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
187296341Sdelphij        return NULL;
188296341Sdelphij    ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
189296341Sdelphij    ret->cache = 1;
190296341Sdelphij    ret->get_cert_methods = sk_X509_LOOKUP_new_null();
191296341Sdelphij    ret->verify = 0;
192296341Sdelphij    ret->verify_cb = 0;
193109998Smarkm
194296341Sdelphij    if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
195296341Sdelphij        return NULL;
196109998Smarkm
197296341Sdelphij    ret->get_issuer = 0;
198296341Sdelphij    ret->check_issued = 0;
199296341Sdelphij    ret->check_revocation = 0;
200296341Sdelphij    ret->get_crl = 0;
201296341Sdelphij    ret->check_crl = 0;
202296341Sdelphij    ret->cert_crl = 0;
203296341Sdelphij    ret->lookup_certs = 0;
204296341Sdelphij    ret->lookup_crls = 0;
205296341Sdelphij    ret->cleanup = 0;
206109998Smarkm
207296341Sdelphij    if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
208296341Sdelphij        sk_X509_OBJECT_free(ret->objs);
209296341Sdelphij        OPENSSL_free(ret);
210296341Sdelphij        return NULL;
211296341Sdelphij    }
212205128Ssimon
213296341Sdelphij    ret->references = 1;
214296341Sdelphij    return ret;
215296341Sdelphij}
21655714Skris
21755714Skrisstatic void cleanup(X509_OBJECT *a)
218296341Sdelphij{
219296341Sdelphij    if (!a)
220296341Sdelphij        return;
221296341Sdelphij    if (a->type == X509_LU_X509) {
222296341Sdelphij        X509_free(a->data.x509);
223296341Sdelphij    } else if (a->type == X509_LU_CRL) {
224296341Sdelphij        X509_CRL_free(a->data.crl);
225296341Sdelphij    } else {
226296341Sdelphij        /* abort(); */
227296341Sdelphij    }
22855714Skris
229296341Sdelphij    OPENSSL_free(a);
230296341Sdelphij}
23155714Skris
23255714Skrisvoid X509_STORE_free(X509_STORE *vfy)
233296341Sdelphij{
234296341Sdelphij    int i;
235296341Sdelphij    STACK_OF(X509_LOOKUP) *sk;
236296341Sdelphij    X509_LOOKUP *lu;
23755714Skris
238296341Sdelphij    if (vfy == NULL)
239296341Sdelphij        return;
24055714Skris
241296341Sdelphij    sk = vfy->get_cert_methods;
242296341Sdelphij    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
243296341Sdelphij        lu = sk_X509_LOOKUP_value(sk, i);
244296341Sdelphij        X509_LOOKUP_shutdown(lu);
245296341Sdelphij        X509_LOOKUP_free(lu);
246296341Sdelphij    }
247296341Sdelphij    sk_X509_LOOKUP_free(sk);
248296341Sdelphij    sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
24955714Skris
250296341Sdelphij    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
251296341Sdelphij    if (vfy->param)
252296341Sdelphij        X509_VERIFY_PARAM_free(vfy->param);
253296341Sdelphij    OPENSSL_free(vfy);
254296341Sdelphij}
25555714Skris
25655714SkrisX509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
257296341Sdelphij{
258296341Sdelphij    int i;
259296341Sdelphij    STACK_OF(X509_LOOKUP) *sk;
260296341Sdelphij    X509_LOOKUP *lu;
26155714Skris
262296341Sdelphij    sk = v->get_cert_methods;
263296341Sdelphij    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
264296341Sdelphij        lu = sk_X509_LOOKUP_value(sk, i);
265296341Sdelphij        if (m == lu->method) {
266296341Sdelphij            return lu;
267296341Sdelphij        }
268296341Sdelphij    }
269296341Sdelphij    /* a new one */
270296341Sdelphij    lu = X509_LOOKUP_new(m);
271296341Sdelphij    if (lu == NULL)
272296341Sdelphij        return NULL;
273296341Sdelphij    else {
274296341Sdelphij        lu->store_ctx = v;
275296341Sdelphij        if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
276296341Sdelphij            return lu;
277296341Sdelphij        else {
278296341Sdelphij            X509_LOOKUP_free(lu);
279296341Sdelphij            return NULL;
280296341Sdelphij        }
281296341Sdelphij    }
282296341Sdelphij}
28355714Skris
28455714Skrisint X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
285296341Sdelphij                              X509_OBJECT *ret)
286296341Sdelphij{
287296341Sdelphij    X509_STORE *ctx = vs->ctx;
288296341Sdelphij    X509_LOOKUP *lu;
289296341Sdelphij    X509_OBJECT stmp, *tmp;
290296341Sdelphij    int i, j;
29155714Skris
292296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
293296341Sdelphij    tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
294296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
29555714Skris
296296341Sdelphij    if (tmp == NULL || type == X509_LU_CRL) {
297296341Sdelphij        for (i = vs->current_method;
298296341Sdelphij             i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
299296341Sdelphij            lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
300296341Sdelphij            j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
301296341Sdelphij            if (j < 0) {
302296341Sdelphij                vs->current_method = j;
303296341Sdelphij                return j;
304296341Sdelphij            } else if (j) {
305296341Sdelphij                tmp = &stmp;
306296341Sdelphij                break;
307296341Sdelphij            }
308296341Sdelphij        }
309296341Sdelphij        vs->current_method = 0;
310296341Sdelphij        if (tmp == NULL)
311296341Sdelphij            return 0;
312296341Sdelphij    }
31355714Skris
314296341Sdelphij/*- if (ret->data.ptr != NULL)
315296341Sdelphij            X509_OBJECT_free_contents(ret); */
31655714Skris
317296341Sdelphij    ret->type = tmp->type;
318296341Sdelphij    ret->data.ptr = tmp->data.ptr;
31955714Skris
320296341Sdelphij    X509_OBJECT_up_ref_count(ret);
32155714Skris
322296341Sdelphij    return 1;
323296341Sdelphij}
32455714Skris
32568651Skrisint X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
326296341Sdelphij{
327296341Sdelphij    X509_OBJECT *obj;
328296341Sdelphij    int ret = 1;
32968651Skris
330296341Sdelphij    if (x == NULL)
331296341Sdelphij        return 0;
332296341Sdelphij    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
333296341Sdelphij    if (obj == NULL) {
334296341Sdelphij        X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
335296341Sdelphij        return 0;
336296341Sdelphij    }
337296341Sdelphij    obj->type = X509_LU_X509;
338296341Sdelphij    obj->data.x509 = x;
33968651Skris
340296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
34168651Skris
342296341Sdelphij    X509_OBJECT_up_ref_count(obj);
34368651Skris
344296341Sdelphij    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
345296341Sdelphij        X509_OBJECT_free_contents(obj);
346296341Sdelphij        OPENSSL_free(obj);
347296341Sdelphij        X509err(X509_F_X509_STORE_ADD_CERT,
348296341Sdelphij                X509_R_CERT_ALREADY_IN_HASH_TABLE);
349296341Sdelphij        ret = 0;
350296341Sdelphij    } else
351296341Sdelphij        sk_X509_OBJECT_push(ctx->objs, obj);
35268651Skris
353296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
35468651Skris
355296341Sdelphij    return ret;
356296341Sdelphij}
35768651Skris
35868651Skrisint X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
359296341Sdelphij{
360296341Sdelphij    X509_OBJECT *obj;
361296341Sdelphij    int ret = 1;
36268651Skris
363296341Sdelphij    if (x == NULL)
364296341Sdelphij        return 0;
365296341Sdelphij    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
366296341Sdelphij    if (obj == NULL) {
367296341Sdelphij        X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
368296341Sdelphij        return 0;
369296341Sdelphij    }
370296341Sdelphij    obj->type = X509_LU_CRL;
371296341Sdelphij    obj->data.crl = x;
37268651Skris
373296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
37468651Skris
375296341Sdelphij    X509_OBJECT_up_ref_count(obj);
37668651Skris
377296341Sdelphij    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
378296341Sdelphij        X509_OBJECT_free_contents(obj);
379296341Sdelphij        OPENSSL_free(obj);
380296341Sdelphij        X509err(X509_F_X509_STORE_ADD_CRL, X509_R_CERT_ALREADY_IN_HASH_TABLE);
381296341Sdelphij        ret = 0;
382296341Sdelphij    } else
383296341Sdelphij        sk_X509_OBJECT_push(ctx->objs, obj);
38468651Skris
385296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
38668651Skris
387296341Sdelphij    return ret;
388296341Sdelphij}
38968651Skris
39055714Skrisvoid X509_OBJECT_up_ref_count(X509_OBJECT *a)
391296341Sdelphij{
392296341Sdelphij    switch (a->type) {
393296341Sdelphij    case X509_LU_X509:
394296341Sdelphij        CRYPTO_add(&a->data.x509->references, 1, CRYPTO_LOCK_X509);
395296341Sdelphij        break;
396296341Sdelphij    case X509_LU_CRL:
397296341Sdelphij        CRYPTO_add(&a->data.crl->references, 1, CRYPTO_LOCK_X509_CRL);
398296341Sdelphij        break;
399296341Sdelphij    }
400296341Sdelphij}
40155714Skris
40255714Skrisvoid X509_OBJECT_free_contents(X509_OBJECT *a)
403296341Sdelphij{
404296341Sdelphij    switch (a->type) {
405296341Sdelphij    case X509_LU_X509:
406296341Sdelphij        X509_free(a->data.x509);
407296341Sdelphij        break;
408296341Sdelphij    case X509_LU_CRL:
409296341Sdelphij        X509_CRL_free(a->data.crl);
410296341Sdelphij        break;
411296341Sdelphij    }
412296341Sdelphij}
41355714Skris
414238405Sjkimstatic int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
415296341Sdelphij                               X509_NAME *name, int *pnmatch)
416296341Sdelphij{
417296341Sdelphij    X509_OBJECT stmp;
418296341Sdelphij    X509 x509_s;
419296341Sdelphij    X509_CINF cinf_s;
420296341Sdelphij    X509_CRL crl_s;
421296341Sdelphij    X509_CRL_INFO crl_info_s;
422296341Sdelphij    int idx;
42355714Skris
424296341Sdelphij    stmp.type = type;
425296341Sdelphij    switch (type) {
426296341Sdelphij    case X509_LU_X509:
427296341Sdelphij        stmp.data.x509 = &x509_s;
428296341Sdelphij        x509_s.cert_info = &cinf_s;
429296341Sdelphij        cinf_s.subject = name;
430296341Sdelphij        break;
431296341Sdelphij    case X509_LU_CRL:
432296341Sdelphij        stmp.data.crl = &crl_s;
433296341Sdelphij        crl_s.crl = &crl_info_s;
434296341Sdelphij        crl_info_s.issuer = name;
435296341Sdelphij        break;
436296341Sdelphij    default:
437296341Sdelphij        /* abort(); */
438296341Sdelphij        return -1;
439296341Sdelphij    }
44055714Skris
441296341Sdelphij    idx = sk_X509_OBJECT_find(h, &stmp);
442296341Sdelphij    if (idx >= 0 && pnmatch) {
443296341Sdelphij        int tidx;
444296341Sdelphij        const X509_OBJECT *tobj, *pstmp;
445296341Sdelphij        *pnmatch = 1;
446296341Sdelphij        pstmp = &stmp;
447296341Sdelphij        for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
448296341Sdelphij            tobj = sk_X509_OBJECT_value(h, tidx);
449296341Sdelphij            if (x509_object_cmp(&tobj, &pstmp))
450296341Sdelphij                break;
451296341Sdelphij            (*pnmatch)++;
452296341Sdelphij        }
453296341Sdelphij    }
454296341Sdelphij    return idx;
455296341Sdelphij}
45655714Skris
457238405Sjkimint X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
458296341Sdelphij                               X509_NAME *name)
459296341Sdelphij{
460296341Sdelphij    return x509_object_idx_cnt(h, type, name, NULL);
461296341Sdelphij}
462238405Sjkim
463296341SdelphijX509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
464296341Sdelphij                                             int type, X509_NAME *name)
465296341Sdelphij{
466296341Sdelphij    int idx;
467296341Sdelphij    idx = X509_OBJECT_idx_by_subject(h, type, name);
468296341Sdelphij    if (idx == -1)
469296341Sdelphij        return NULL;
470296341Sdelphij    return sk_X509_OBJECT_value(h, idx);
471296341Sdelphij}
47259191Skris
473296341SdelphijSTACK_OF(X509) *X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
474296341Sdelphij{
475296341Sdelphij    int i, idx, cnt;
476296341Sdelphij    STACK_OF(X509) *sk;
477296341Sdelphij    X509 *x;
478296341Sdelphij    X509_OBJECT *obj;
479296341Sdelphij    sk = sk_X509_new_null();
480296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
481296341Sdelphij    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
482296341Sdelphij    if (idx < 0) {
483296341Sdelphij        /*
484296341Sdelphij         * Nothing found in cache: do lookup to possibly add new objects to
485296341Sdelphij         * cache
486296341Sdelphij         */
487296341Sdelphij        X509_OBJECT xobj;
488296341Sdelphij        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
489296341Sdelphij        if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
490296341Sdelphij            sk_X509_free(sk);
491296341Sdelphij            return NULL;
492296341Sdelphij        }
493296341Sdelphij        X509_OBJECT_free_contents(&xobj);
494296341Sdelphij        CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
495296341Sdelphij        idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
496296341Sdelphij        if (idx < 0) {
497296341Sdelphij            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
498296341Sdelphij            sk_X509_free(sk);
499296341Sdelphij            return NULL;
500296341Sdelphij        }
501296341Sdelphij    }
502296341Sdelphij    for (i = 0; i < cnt; i++, idx++) {
503296341Sdelphij        obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
504296341Sdelphij        x = obj->data.x509;
505296341Sdelphij        CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
506296341Sdelphij        if (!sk_X509_push(sk, x)) {
507296341Sdelphij            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
508296341Sdelphij            X509_free(x);
509296341Sdelphij            sk_X509_pop_free(sk, X509_free);
510296341Sdelphij            return NULL;
511296341Sdelphij        }
512296341Sdelphij    }
513296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
514296341Sdelphij    return sk;
515238405Sjkim
516296341Sdelphij}
517238405Sjkim
518296341SdelphijSTACK_OF(X509_CRL) *X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
519296341Sdelphij{
520296341Sdelphij    int i, idx, cnt;
521296341Sdelphij    STACK_OF(X509_CRL) *sk;
522296341Sdelphij    X509_CRL *x;
523296341Sdelphij    X509_OBJECT *obj, xobj;
524296341Sdelphij    sk = sk_X509_CRL_new_null();
525296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
526296341Sdelphij    /* Check cache first */
527296341Sdelphij    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
528238405Sjkim
529296341Sdelphij    /*
530296341Sdelphij     * Always do lookup to possibly add new CRLs to cache
531296341Sdelphij     */
532296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
533296341Sdelphij    if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
534296341Sdelphij        sk_X509_CRL_free(sk);
535296341Sdelphij        return NULL;
536296341Sdelphij    }
537296341Sdelphij    X509_OBJECT_free_contents(&xobj);
538296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
539296341Sdelphij    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
540296341Sdelphij    if (idx < 0) {
541296341Sdelphij        CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
542296341Sdelphij        sk_X509_CRL_free(sk);
543296341Sdelphij        return NULL;
544296341Sdelphij    }
545238405Sjkim
546296341Sdelphij    for (i = 0; i < cnt; i++, idx++) {
547296341Sdelphij        obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
548296341Sdelphij        x = obj->data.crl;
549296341Sdelphij        CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
550296341Sdelphij        if (!sk_X509_CRL_push(sk, x)) {
551296341Sdelphij            CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
552296341Sdelphij            X509_CRL_free(x);
553296341Sdelphij            sk_X509_CRL_pop_free(sk, X509_CRL_free);
554296341Sdelphij            return NULL;
555296341Sdelphij        }
556296341Sdelphij    }
557296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
558296341Sdelphij    return sk;
559296341Sdelphij}
560238405Sjkim
561296341SdelphijX509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
562296341Sdelphij                                        X509_OBJECT *x)
563296341Sdelphij{
564296341Sdelphij    int idx, i;
565296341Sdelphij    X509_OBJECT *obj;
566296341Sdelphij    idx = sk_X509_OBJECT_find(h, x);
567296341Sdelphij    if (idx == -1)
568296341Sdelphij        return NULL;
569296341Sdelphij    if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
570296341Sdelphij        return sk_X509_OBJECT_value(h, idx);
571296341Sdelphij    for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
572296341Sdelphij        obj = sk_X509_OBJECT_value(h, i);
573296341Sdelphij        if (x509_object_cmp
574296341Sdelphij            ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
575296341Sdelphij            return NULL;
576296341Sdelphij        if (x->type == X509_LU_X509) {
577296341Sdelphij            if (!X509_cmp(obj->data.x509, x->data.x509))
578296341Sdelphij                return obj;
579296341Sdelphij        } else if (x->type == X509_LU_CRL) {
580296341Sdelphij            if (!X509_CRL_match(obj->data.crl, x->data.crl))
581296341Sdelphij                return obj;
582296341Sdelphij        } else
583296341Sdelphij            return obj;
584296341Sdelphij    }
585296341Sdelphij    return NULL;
586296341Sdelphij}
58759191Skris
588296341Sdelphij/*-
589296341Sdelphij * Try to get issuer certificate from store. Due to limitations
59068651Skris * of the API this can only retrieve a single certificate matching
59168651Skris * a given subject name. However it will fill the cache with all
592205128Ssimon * matching certificates, so we can examine the cache for all
59368651Skris * matches.
59468651Skris *
59568651Skris * Return values are:
59668651Skris *  1 lookup successful.
59768651Skris *  0 certificate not found.
59868651Skris * -1 some other error.
59968651Skris */
60068651Skrisint X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
601296341Sdelphij{
602296341Sdelphij    X509_NAME *xn;
603296341Sdelphij    X509_OBJECT obj, *pobj;
604296341Sdelphij    int i, ok, idx, ret;
605296341Sdelphij    xn = X509_get_issuer_name(x);
606296341Sdelphij    ok = X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj);
607296341Sdelphij    if (ok != X509_LU_X509) {
608296341Sdelphij        if (ok == X509_LU_RETRY) {
609296341Sdelphij            X509_OBJECT_free_contents(&obj);
610296341Sdelphij            X509err(X509_F_X509_STORE_CTX_GET1_ISSUER, X509_R_SHOULD_RETRY);
611296341Sdelphij            return -1;
612296341Sdelphij        } else if (ok != X509_LU_FAIL) {
613296341Sdelphij            X509_OBJECT_free_contents(&obj);
614296341Sdelphij            /* not good :-(, break anyway */
615296341Sdelphij            return -1;
616296341Sdelphij        }
617296341Sdelphij        return 0;
618296341Sdelphij    }
619296341Sdelphij    /* If certificate matches all OK */
620296341Sdelphij    if (ctx->check_issued(ctx, x, obj.data.x509)) {
621296341Sdelphij        *issuer = obj.data.x509;
622296341Sdelphij        return 1;
623296341Sdelphij    }
624296341Sdelphij    X509_OBJECT_free_contents(&obj);
625205128Ssimon
626296341Sdelphij    /* Else find index of first cert accepted by 'check_issued' */
627296341Sdelphij    ret = 0;
628296341Sdelphij    CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
629296341Sdelphij    idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
630296341Sdelphij    if (idx != -1) {            /* should be true as we've had at least one
631296341Sdelphij                                 * match */
632296341Sdelphij        /* Look through all matching certs for suitable issuer */
633296341Sdelphij        for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
634296341Sdelphij            pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
635296341Sdelphij            /* See if we've run past the matches */
636296341Sdelphij            if (pobj->type != X509_LU_X509)
637296341Sdelphij                break;
638296341Sdelphij            if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
639296341Sdelphij                break;
640296341Sdelphij            if (ctx->check_issued(ctx, x, pobj->data.x509)) {
641296341Sdelphij                *issuer = pobj->data.x509;
642296341Sdelphij                X509_OBJECT_up_ref_count(pobj);
643296341Sdelphij                ret = 1;
644296341Sdelphij                break;
645296341Sdelphij            }
646296341Sdelphij        }
647296341Sdelphij    }
648296341Sdelphij    CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
649296341Sdelphij    return ret;
650296341Sdelphij}
65168651Skris
652160814Ssimonint X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
653296341Sdelphij{
654296341Sdelphij    return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
655296341Sdelphij}
656109998Smarkm
657160814Ssimonint X509_STORE_set_depth(X509_STORE *ctx, int depth)
658296341Sdelphij{
659296341Sdelphij    X509_VERIFY_PARAM_set_depth(ctx->param, depth);
660296341Sdelphij    return 1;
661296341Sdelphij}
662160814Ssimon
663109998Smarkmint X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
664296341Sdelphij{
665296341Sdelphij    return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
666296341Sdelphij}
667109998Smarkm
668109998Smarkmint X509_STORE_set_trust(X509_STORE *ctx, int trust)
669296341Sdelphij{
670296341Sdelphij    return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
671296341Sdelphij}
672109998Smarkm
673160814Ssimonint X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
674296341Sdelphij{
675296341Sdelphij    return X509_VERIFY_PARAM_set1(ctx->param, param);
676296341Sdelphij}
677160814Ssimon
678238405Sjkimvoid X509_STORE_set_verify_cb(X509_STORE *ctx,
679296341Sdelphij                              int (*verify_cb) (int, X509_STORE_CTX *))
680296341Sdelphij{
681296341Sdelphij    ctx->verify_cb = verify_cb;
682296341Sdelphij}
683238405Sjkim
68455714SkrisIMPLEMENT_STACK_OF(X509_LOOKUP)
685296341Sdelphij
68668651SkrisIMPLEMENT_STACK_OF(X509_OBJECT)
687