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