Make sure the already existing X509_STORE->depth variable is initialized
[openssl.git] / crypto / x509 / x509_lu.c
1 /* crypto/x509/x509_lu.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include "lhash.h"
62 #include "x509.h"
63
64 static STACK *x509_store_meth=NULL;
65 static STACK *x509_store_ctx_meth=NULL;
66
67 X509_LOOKUP *X509_LOOKUP_new(method)
68 X509_LOOKUP_METHOD *method;
69         {
70         X509_LOOKUP *ret;
71
72         ret=(X509_LOOKUP *)Malloc(sizeof(X509_LOOKUP));
73         if (ret == NULL) return(NULL);
74
75         ret->init=0;
76         ret->skip=0;
77         ret->method=method;
78         ret->method_data=NULL;
79         ret->store_ctx=NULL;
80         if ((method->new_item != NULL) && !method->new_item(ret))
81                 {
82                 Free(ret);
83                 return(NULL);
84                 }
85         return(ret);
86         }
87
88 void X509_LOOKUP_free(ctx)
89 X509_LOOKUP *ctx;
90         {
91         if (ctx == NULL) return;
92         if (    (ctx->method != NULL) &&
93                 (ctx->method->free != NULL))
94                 ctx->method->free(ctx);
95         Free(ctx);
96         }
97
98 int X509_LOOKUP_init(ctx)
99 X509_LOOKUP *ctx;
100         {
101         if (ctx->method == NULL) return(0);
102         if (ctx->method->init != NULL)
103                 return(ctx->method->init(ctx));
104         else
105                 return(1);
106         }
107
108 int X509_LOOKUP_shutdown(ctx)
109 X509_LOOKUP *ctx;
110         {
111         if (ctx->method == NULL) return(0);
112         if (ctx->method->shutdown != NULL)
113                 return(ctx->method->shutdown(ctx));
114         else
115                 return(1);
116         }
117
118 int X509_LOOKUP_ctrl(ctx,cmd,argc,argl,ret)
119 X509_LOOKUP *ctx;
120 int cmd;
121 char *argc;
122 long argl;
123 char **ret;
124         {
125         if (ctx->method == NULL) return(-1);
126         if (ctx->method->ctrl != NULL)
127                 return(ctx->method->ctrl(ctx,cmd,argc,argl,ret));
128         else
129                 return(1);
130         }
131
132 int X509_LOOKUP_by_subject(ctx,type,name,ret)
133 X509_LOOKUP *ctx;
134 int type;
135 X509_NAME *name;
136 X509_OBJECT *ret;
137         {
138         if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
139                 return(X509_LU_FAIL);
140         if (ctx->skip) return(0);
141         return(ctx->method->get_by_subject(ctx,type,name,ret));
142         }
143
144 int X509_LOOKUP_by_issuer_serial(ctx,type,name,serial,ret)
145 X509_LOOKUP *ctx;
146 int type;
147 X509_NAME *name;
148 ASN1_INTEGER *serial;
149 X509_OBJECT *ret;
150         {
151         if ((ctx->method == NULL) ||
152                 (ctx->method->get_by_issuer_serial == NULL))
153                 return(X509_LU_FAIL);
154         return(ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret));
155         }
156
157 int X509_LOOKUP_by_fingerprint(ctx,type,bytes,len,ret)
158 X509_LOOKUP *ctx;
159 int type;
160 unsigned char *bytes;
161 int len;
162 X509_OBJECT *ret;
163         {
164         if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
165                 return(X509_LU_FAIL);
166         return(ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret));
167         }
168
169 int X509_LOOKUP_by_alias(ctx,type,str,len,ret)
170 X509_LOOKUP *ctx;
171 int type;
172 char *str;
173 int len;
174 X509_OBJECT *ret;
175         {
176         if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
177                 return(X509_LU_FAIL);
178         return(ctx->method->get_by_alias(ctx,str,len,ret));
179         }
180
181 static unsigned long x509_object_hash(a)
182 X509_OBJECT *a;
183         {
184         unsigned long h;
185
186         switch (a->type)
187                 {
188         case X509_LU_X509:
189                 h=X509_NAME_hash(a->data.x509->cert_info->subject);
190                 break;
191         case X509_LU_CRL:
192                 h=X509_NAME_hash(a->data.crl->crl->issuer);
193                 break;
194         default:
195                 abort();
196                 }
197         return(h);
198         }
199
200 static int x509_object_cmp(a,b)
201 X509_OBJECT *a,*b;
202         {
203         int ret;
204
205         ret=(a->type - b->type);
206         if (ret) return(ret);
207         switch (a->type)
208                 {
209         case X509_LU_X509:
210                 ret=X509_subject_name_cmp(a->data.x509,b->data.x509);
211                 break;
212         case X509_LU_CRL:
213                 ret=X509_CRL_cmp(a->data.crl,b->data.crl);
214                 break;
215         default:
216                 abort();
217                 }
218         return(ret);
219         }
220
221 X509_STORE *X509_STORE_new()
222         {
223         X509_STORE *ret;
224
225         if ((ret=(X509_STORE *)Malloc(sizeof(X509_STORE))) == NULL)
226                 return(NULL);
227         ret->certs=lh_new(x509_object_hash,x509_object_cmp);
228         ret->cache=1;
229         ret->get_cert_methods=sk_new_null();
230         ret->verify=NULL;
231         ret->verify_cb=NULL;
232         memset(&ret->ex_data,0,sizeof(CRYPTO_EX_DATA));
233         ret->references=1;
234         ret->depth=0;
235         return(ret);
236         }
237
238 static void cleanup(a)
239 X509_OBJECT *a;
240         {
241         if (a->type == X509_LU_X509)
242                 {
243                 X509_free(a->data.x509);
244                 }
245         else if (a->type == X509_LU_CRL)
246                 {
247                 X509_CRL_free(a->data.crl);
248                 }
249         else
250                 abort();
251
252         Free(a);
253         }
254
255 void X509_STORE_free(vfy)
256 X509_STORE *vfy;
257         {
258         int i;
259         STACK *sk;
260         X509_LOOKUP *lu;
261
262         sk=vfy->get_cert_methods;
263         for (i=0; i<sk_num(sk); i++)
264                 {
265                 lu=(X509_LOOKUP *)sk_value(sk,i);
266                 X509_LOOKUP_shutdown(lu);
267                 X509_LOOKUP_free(lu);
268                 }
269         sk_free(sk);
270
271         CRYPTO_free_ex_data(x509_store_meth,(char *)vfy,&vfy->ex_data);
272         lh_doall(vfy->certs,cleanup);
273         lh_free(vfy->certs);
274         Free(vfy);
275         }
276
277 X509_LOOKUP *X509_STORE_add_lookup(v,m)
278 X509_STORE *v;
279 X509_LOOKUP_METHOD *m;
280         {
281         int i;
282         STACK *sk;
283         X509_LOOKUP *lu;
284
285         sk=v->get_cert_methods;
286         for (i=0; i<sk_num(sk); i++)
287                 {
288                 lu=(X509_LOOKUP *)sk_value(sk,i);
289                 if (m == lu->method)
290                         {
291                         return(lu);
292                         }
293                 }
294         /* a new one */
295         lu=X509_LOOKUP_new(m);
296         if (lu == NULL)
297                 return(NULL);
298         else
299                 {
300                 lu->store_ctx=v;
301                 if (sk_push(v->get_cert_methods,(char *)lu))
302                         return(lu);
303                 else
304                         {
305                         X509_LOOKUP_free(lu);
306                         return(NULL);
307                         }
308                 }
309         }
310
311 int X509_STORE_get_by_subject(vs,type,name,ret)
312 X509_STORE_CTX *vs;
313 int type;
314 X509_NAME *name;
315 X509_OBJECT *ret;
316         {
317         X509_STORE *ctx=vs->ctx;
318         X509_LOOKUP *lu;
319         X509_OBJECT stmp,*tmp;
320         int i,j;
321
322         tmp=X509_OBJECT_retrieve_by_subject(ctx->certs,type,name);
323
324         if (tmp == NULL)
325                 {
326                 for (i=vs->current_method; i<sk_num(ctx->get_cert_methods); i++)
327                         {
328                         lu=(X509_LOOKUP *)sk_value(ctx->get_cert_methods,i);
329                         j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
330                         if (j < 0)
331                                 {
332                                 vs->current_method=j;
333                                 return(j);
334                                 }
335                         else if (j)
336                                 {
337                                 tmp= &stmp;
338                                 break;
339                                 }
340                         }
341                 vs->current_method=0;
342                 if (tmp == NULL)
343                         return(0);
344                 }
345
346 /*      if (ret->data.ptr != NULL)
347                 X509_OBJECT_free_contents(ret); */
348
349         ret->type=tmp->type;
350         ret->data.ptr=tmp->data.ptr;
351
352         X509_OBJECT_up_ref_count(ret);
353
354         return(1);
355         }
356
357 void X509_OBJECT_up_ref_count(a)
358 X509_OBJECT *a;
359         {
360         switch (a->type)
361                 {
362         case X509_LU_X509:
363                 CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
364                 break;
365         case X509_LU_CRL:
366                 CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
367                 break;
368                 }
369         }
370
371 void X509_OBJECT_free_contents(a)
372 X509_OBJECT *a;
373         {
374         switch (a->type)
375                 {
376         case X509_LU_X509:
377                 X509_free(a->data.x509);
378                 break;
379         case X509_LU_CRL:
380                 X509_CRL_free(a->data.crl);
381                 break;
382                 }
383         }
384
385 X509_OBJECT *X509_OBJECT_retrieve_by_subject(h,type,name)
386 LHASH *h;
387 int type;
388 X509_NAME *name;
389         {
390         X509_OBJECT stmp,*tmp;
391         X509 x509_s;
392         X509_CINF cinf_s;
393         X509_CRL crl_s;
394         X509_CRL_INFO crl_info_s;
395
396         stmp.type=type;
397         switch (type)
398                 {
399         case X509_LU_X509:
400                 stmp.data.x509= &x509_s;
401                 x509_s.cert_info= &cinf_s;
402                 cinf_s.subject=name;
403                 break;
404         case X509_LU_CRL:
405                 stmp.data.crl= &crl_s;
406                 crl_s.crl= &crl_info_s;
407                 crl_info_s.issuer=name;
408                 break;
409         default:
410                 abort();
411                 }
412
413         tmp=(X509_OBJECT *)lh_retrieve(h,(char *)&stmp);
414         return(tmp);
415         }
416
417 void X509_STORE_CTX_init(ctx,store,x509,chain)
418 X509_STORE_CTX *ctx;
419 X509_STORE *store;
420 X509 *x509;
421 STACK *chain;
422         {
423         ctx->ctx=store;
424         ctx->current_method=0;
425         ctx->cert=x509;
426         ctx->untrusted=chain;
427         ctx->last_untrusted=0;
428         ctx->valid=0;
429         ctx->chain=NULL;
430         ctx->depth=10;
431         ctx->error=0;
432         ctx->current_cert=NULL;
433         memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA));
434         }
435
436 void X509_STORE_CTX_cleanup(ctx)
437 X509_STORE_CTX *ctx;
438         {
439         if (ctx->chain != NULL)
440                 {
441                 sk_pop_free(ctx->chain,X509_free);
442                 ctx->chain=NULL;
443                 }
444         CRYPTO_free_ex_data(x509_store_ctx_meth,(char *)ctx,&(ctx->ex_data));
445         memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
446         }
447