Add type-safe STACKs and SETs.
[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,type,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         if(vfy == NULL)
263             return;
264
265         sk=vfy->get_cert_methods;
266         for (i=0; i<sk_num(sk); i++)
267                 {
268                 lu=(X509_LOOKUP *)sk_value(sk,i);
269                 X509_LOOKUP_shutdown(lu);
270                 X509_LOOKUP_free(lu);
271                 }
272         sk_free(sk);
273
274         CRYPTO_free_ex_data(x509_store_meth,(char *)vfy,&vfy->ex_data);
275         lh_doall(vfy->certs,cleanup);
276         lh_free(vfy->certs);
277         Free(vfy);
278         }
279
280 X509_LOOKUP *X509_STORE_add_lookup(v,m)
281 X509_STORE *v;
282 X509_LOOKUP_METHOD *m;
283         {
284         int i;
285         STACK *sk;
286         X509_LOOKUP *lu;
287
288         sk=v->get_cert_methods;
289         for (i=0; i<sk_num(sk); i++)
290                 {
291                 lu=(X509_LOOKUP *)sk_value(sk,i);
292                 if (m == lu->method)
293                         {
294                         return(lu);
295                         }
296                 }
297         /* a new one */
298         lu=X509_LOOKUP_new(m);
299         if (lu == NULL)
300                 return(NULL);
301         else
302                 {
303                 lu->store_ctx=v;
304                 if (sk_push(v->get_cert_methods,(char *)lu))
305                         return(lu);
306                 else
307                         {
308                         X509_LOOKUP_free(lu);
309                         return(NULL);
310                         }
311                 }
312         }
313
314 int X509_STORE_get_by_subject(vs,type,name,ret)
315 X509_STORE_CTX *vs;
316 int type;
317 X509_NAME *name;
318 X509_OBJECT *ret;
319         {
320         X509_STORE *ctx=vs->ctx;
321         X509_LOOKUP *lu;
322         X509_OBJECT stmp,*tmp;
323         int i,j;
324
325         tmp=X509_OBJECT_retrieve_by_subject(ctx->certs,type,name);
326
327         if (tmp == NULL)
328                 {
329                 for (i=vs->current_method; i<sk_num(ctx->get_cert_methods); i++)
330                         {
331                         lu=(X509_LOOKUP *)sk_value(ctx->get_cert_methods,i);
332                         j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
333                         if (j < 0)
334                                 {
335                                 vs->current_method=j;
336                                 return(j);
337                                 }
338                         else if (j)
339                                 {
340                                 tmp= &stmp;
341                                 break;
342                                 }
343                         }
344                 vs->current_method=0;
345                 if (tmp == NULL)
346                         return(0);
347                 }
348
349 /*      if (ret->data.ptr != NULL)
350                 X509_OBJECT_free_contents(ret); */
351
352         ret->type=tmp->type;
353         ret->data.ptr=tmp->data.ptr;
354
355         X509_OBJECT_up_ref_count(ret);
356
357         return(1);
358         }
359
360 void X509_OBJECT_up_ref_count(a)
361 X509_OBJECT *a;
362         {
363         switch (a->type)
364                 {
365         case X509_LU_X509:
366                 CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
367                 break;
368         case X509_LU_CRL:
369                 CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
370                 break;
371                 }
372         }
373
374 void X509_OBJECT_free_contents(a)
375 X509_OBJECT *a;
376         {
377         switch (a->type)
378                 {
379         case X509_LU_X509:
380                 X509_free(a->data.x509);
381                 break;
382         case X509_LU_CRL:
383                 X509_CRL_free(a->data.crl);
384                 break;
385                 }
386         }
387
388 X509_OBJECT *X509_OBJECT_retrieve_by_subject(h,type,name)
389 LHASH *h;
390 int type;
391 X509_NAME *name;
392         {
393         X509_OBJECT stmp,*tmp;
394         X509 x509_s;
395         X509_CINF cinf_s;
396         X509_CRL crl_s;
397         X509_CRL_INFO crl_info_s;
398
399         stmp.type=type;
400         switch (type)
401                 {
402         case X509_LU_X509:
403                 stmp.data.x509= &x509_s;
404                 x509_s.cert_info= &cinf_s;
405                 cinf_s.subject=name;
406                 break;
407         case X509_LU_CRL:
408                 stmp.data.crl= &crl_s;
409                 crl_s.crl= &crl_info_s;
410                 crl_info_s.issuer=name;
411                 break;
412         default:
413                 abort();
414                 }
415
416         tmp=(X509_OBJECT *)lh_retrieve(h,(char *)&stmp);
417         return(tmp);
418         }
419
420 void X509_STORE_CTX_init(ctx,store,x509,chain)
421 X509_STORE_CTX *ctx;
422 X509_STORE *store;
423 X509 *x509;
424 STACK_OF(X509) *chain;
425         {
426         ctx->ctx=store;
427         ctx->current_method=0;
428         ctx->cert=x509;
429         ctx->untrusted=chain;
430         ctx->last_untrusted=0;
431         ctx->valid=0;
432         ctx->chain=NULL;
433         ctx->depth=10;
434         ctx->error=0;
435         ctx->current_cert=NULL;
436         memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA));
437         }
438
439 void X509_STORE_CTX_cleanup(ctx)
440 X509_STORE_CTX *ctx;
441         {
442         if (ctx->chain != NULL)
443                 {
444                 sk_pop_free(ctx->chain,X509_free);
445                 ctx->chain=NULL;
446                 }
447         CRYPTO_free_ex_data(x509_store_ctx_meth,(char *)ctx,&(ctx->ex_data));
448         memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
449         }
450