Import of old SSLeay release: SSLeay 0.8.1b
[openssl.git] / crypto / x509 / x509_lu.c
1 /* crypto/x509/x509_lu.c */
2 /* Copyright (C) 1995-1997 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 X509_LOOKUP *X509_LOOKUP_new(method)
65 X509_LOOKUP_METHOD *method;
66         {
67         X509_LOOKUP *ret;
68
69         ret=(X509_LOOKUP *)Malloc(sizeof(X509_LOOKUP));
70         if (ret == NULL) return(NULL);
71
72         ret->init=0;
73         ret->skip=0;
74         ret->method=method;
75         ret->method_data=NULL;
76         ret->store_ctx=NULL;
77         if ((method->new_item != NULL) && !method->new_item(ret))
78                 {
79                 Free(ret);
80                 return(NULL);
81                 }
82         return(ret);
83         }
84
85 void X509_LOOKUP_free(ctx)
86 X509_LOOKUP *ctx;
87         {
88         if (ctx == NULL) return;
89         if (    (ctx->method != NULL) &&
90                 (ctx->method->free != NULL))
91                 ctx->method->free(ctx);
92         Free(ctx);
93         }
94
95 int X509_LOOKUP_init(ctx)
96 X509_LOOKUP *ctx;
97         {
98         if (ctx->method == NULL) return(0);
99         if (ctx->method->init != NULL)
100                 return(ctx->method->init(ctx));
101         else
102                 return(1);
103         }
104
105 int X509_LOOKUP_shutdown(ctx)
106 X509_LOOKUP *ctx;
107         {
108         if (ctx->method == NULL) return(0);
109         if (ctx->method->init != NULL)
110                 return(ctx->method->shutdown(ctx));
111         else
112                 return(1);
113         }
114
115 int X509_LOOKUP_ctrl(ctx,cmd,argc,argl,ret)
116 X509_LOOKUP *ctx;
117 int cmd;
118 char *argc;
119 long argl;
120 char **ret;
121         {
122         if (ctx->method == NULL) return(-1);
123         if (ctx->method->ctrl != NULL)
124                 return(ctx->method->ctrl(ctx,cmd,argc,argl,ret));
125         else
126                 return(1);
127         }
128
129 int X509_LOOKUP_by_subject(ctx,type,name,ret)
130 X509_LOOKUP *ctx;
131 int type;
132 X509_NAME *name;
133 X509_OBJECT *ret;
134         {
135         if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
136                 return(X509_LU_FAIL);
137         if (ctx->skip) return(0);
138         return(ctx->method->get_by_subject(ctx,type,name,ret));
139         }
140
141 int X509_LOOKUP_by_issuer_serial(ctx,type,name,serial,ret)
142 X509_LOOKUP *ctx;
143 int type;
144 X509_NAME *name;
145 ASN1_INTEGER *serial;
146 X509_OBJECT *ret;
147         {
148         if ((ctx->method == NULL) ||
149                 (ctx->method->get_by_issuer_serial == NULL))
150                 return(X509_LU_FAIL);
151         return(ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret));
152         }
153
154 int X509_LOOKUP_by_fingerprint(ctx,type,bytes,len,ret)
155 X509_LOOKUP *ctx;
156 int type;
157 unsigned char *bytes;
158 int len;
159 X509_OBJECT *ret;
160         {
161         if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
162                 return(X509_LU_FAIL);
163         return(ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret));
164         }
165
166 int X509_LOOKUP_by_alias(ctx,type,str,len,ret)
167 X509_LOOKUP *ctx;
168 int type;
169 char *str;
170 int len;
171 X509_OBJECT *ret;
172         {
173         if ((ctx->method == NULL) || (ctx->method->get_by_alias))
174                 return(X509_LU_FAIL);
175         return(ctx->method->get_by_alias(ctx,str,len,ret));
176         }
177
178 static unsigned long x509_object_hash(a)
179 X509_OBJECT *a;
180         {
181         unsigned long h;
182
183         switch (a->type)
184                 {
185         case X509_LU_X509:
186                 h=X509_NAME_hash(a->data.x509->cert_info->subject);
187                 break;
188         case X509_LU_CRL:
189                 h=X509_NAME_hash(a->data.crl->crl->issuer);
190                 break;
191         default:
192                 abort();
193                 }
194         return(h);
195         }
196
197 static int x509_object_cmp(a,b)
198 X509_OBJECT *a,*b;
199         {
200         int ret;
201
202         ret=(a->type - b->type);
203         if (ret) return(ret);
204         switch (a->type)
205                 {
206         case X509_LU_X509:
207                 ret=X509_subject_name_cmp(a->data.x509,b->data.x509);
208                 break;
209         case X509_LU_CRL:
210                 ret=X509_CRL_cmp(a->data.crl,b->data.crl);
211                 break;
212         default:
213                 abort();
214                 }
215         return(ret);
216         }
217
218 X509_STORE *X509_STORE_new()
219         {
220         X509_STORE *ret;
221
222         if ((ret=(X509_STORE *)Malloc(sizeof(X509_STORE))) == NULL)
223                 return(NULL);
224         ret->certs=lh_new(x509_object_hash,x509_object_cmp);
225         ret->cache=1;
226         ret->get_cert_methods=sk_new_null();
227         ret->verify=NULL;
228         ret->verify_cb=NULL;
229         ret->app_data=NULL;
230         ret->references=1;
231         return(ret);
232         }
233
234 static void cleanup(a)
235 X509_OBJECT *a;
236         {
237         if (a->type == X509_LU_X509)
238                 {
239                 X509_free(a->data.x509);
240                 }
241         else if (a->type == X509_LU_CRL)
242                 {
243                 X509_CRL_free(a->data.crl);
244                 }
245         else
246                 abort();
247
248         Free(a);
249         }
250
251 void X509_STORE_free(vfy)
252 X509_STORE *vfy;
253         {
254         int i;
255         STACK *sk;
256         X509_LOOKUP *lu;
257
258         sk=vfy->get_cert_methods;
259         for (i=0; i<sk_num(sk); i++)
260                 {
261                 lu=(X509_LOOKUP *)sk_value(sk,i);
262                 X509_LOOKUP_shutdown(lu);
263                 X509_LOOKUP_free(lu);
264                 }
265         sk_free(sk);
266
267         lh_doall(vfy->certs,cleanup);
268         lh_free(vfy->certs);
269         Free(vfy);
270         }
271
272 X509_LOOKUP *X509_STORE_add_lookup(v,m)
273 X509_STORE *v;
274 X509_LOOKUP_METHOD *m;
275         {
276         int i;
277         STACK *sk;
278         X509_LOOKUP *lu;
279
280         sk=v->get_cert_methods;
281         for (i=0; i<sk_num(sk); i++)
282                 {
283                 lu=(X509_LOOKUP *)sk_value(sk,i);
284                 if (m == lu->method)
285                         {
286                         return(lu);
287                         }
288                 }
289         /* a new one */
290         lu=X509_LOOKUP_new(m);
291         if (lu == NULL)
292                 return(NULL);
293         else
294                 {
295                 lu->store_ctx=v;
296                 if (sk_push(v->get_cert_methods,(char *)lu))
297                         return(lu);
298                 else
299                         {
300                         X509_LOOKUP_free(lu);
301                         return(NULL);
302                         }
303                 }
304         }
305
306 int X509_STORE_get_by_subject(vs,type,name,ret)
307 X509_STORE_CTX *vs;
308 int type;
309 X509_NAME *name;
310 X509_OBJECT *ret;
311         {
312         X509_STORE *ctx=vs->ctx;
313         X509_LOOKUP *lu;
314         X509_OBJECT stmp,*tmp;
315         int i,j;
316
317         tmp=X509_OBJECT_retrive_by_subject(ctx->certs,type,name);
318
319         if (tmp == NULL)
320                 {
321                 for (i=vs->current_method; i<sk_num(ctx->get_cert_methods); i++)
322                         {
323                         lu=(X509_LOOKUP *)sk_value(ctx->get_cert_methods,i);
324                         j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
325                         if (j < 0)
326                                 {
327                                 vs->current_method=j;
328                                 return(j);
329                                 }
330                         else if (j)
331                                 {
332                                 tmp= &stmp;
333                                 break;
334                                 }
335                         }
336                 vs->current_method=0;
337                 if (tmp == NULL)
338                         return(0);
339                 }
340
341 /*      if (ret->data.ptr != NULL)
342                 X509_OBJECT_free_contents(ret); */
343
344         ret->type=tmp->type;
345         ret->data.ptr=tmp->data.ptr;
346
347         X509_OBJECT_up_ref_count(ret);
348
349         return(1);
350         }
351
352 void X509_OBJECT_up_ref_count(a)
353 X509_OBJECT *a;
354         {
355         switch (a->type)
356                 {
357         case X509_LU_X509:
358                 CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
359                 break;
360         case X509_LU_CRL:
361                 CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
362                 break;
363                 }
364         }
365
366 void X509_OBJECT_free_contents(a)
367 X509_OBJECT *a;
368         {
369         switch (a->type)
370                 {
371         case X509_LU_X509:
372                 X509_free(a->data.x509);
373                 break;
374         case X509_LU_CRL:
375                 X509_CRL_free(a->data.crl);
376                 break;
377                 }
378         }
379
380 X509_OBJECT *X509_OBJECT_retrive_by_subject(h,type,name)
381 LHASH *h;
382 int type;
383 X509_NAME *name;
384         {
385         X509_OBJECT stmp,*tmp;
386         X509 x509_s;
387         X509_CINF cinf_s;
388         X509_CRL crl_s;
389         X509_CRL_INFO crl_info_s;
390
391         stmp.type=type;
392         switch (type)
393                 {
394         case X509_LU_X509:
395                 stmp.data.x509= &x509_s;
396                 x509_s.cert_info= &cinf_s;
397                 cinf_s.subject=name;
398                 break;
399         case X509_LU_CRL:
400                 stmp.data.crl= &crl_s;
401                 crl_s.crl= &crl_info_s;
402                 crl_info_s.issuer=name;
403                 break;
404         default:
405                 abort();
406                 }
407
408         tmp=(X509_OBJECT *)lh_retrieve(h,(char *)&stmp);
409         return(tmp);
410         }
411
412 void X509_STORE_CTX_init(ctx,store,x509,chain)
413 X509_STORE_CTX *ctx;
414 X509_STORE *store;
415 X509 *x509;
416 STACK *chain;
417         {
418         ctx->ctx=store;
419         ctx->current_method=0;
420         ctx->cert=x509;
421         ctx->untrusted=chain;
422         ctx->last_untrusted=0;
423         ctx->valid=0;
424         ctx->chain=NULL;
425         ctx->depth=10;
426         ctx->error=0;
427         ctx->current_cert=NULL;
428         }
429
430 void X509_STORE_CTX_cleanup(ctx)
431 X509_STORE_CTX *ctx;
432         {
433         if (ctx->chain != NULL)
434                 {
435                 sk_pop_free(ctx->chain,X509_free);
436                 ctx->chain=NULL;
437                 }
438         }
439