68f26f149bb467ca60ab57e999cb091819dcec03
[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_OF(CRYPTO_EX_DATA_FUNCS) *x509_store_meth=NULL;
65 static STACK_OF(CRYPTO_EX_DATA_FUNCS) *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 *)OPENSSL_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                 OPENSSL_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         OPENSSL_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                 return 0;
173                 }
174         return(h);
175         }
176
177 static int x509_object_cmp(X509_OBJECT *a, X509_OBJECT *b)
178         {
179         int ret;
180
181         ret=(a->type - b->type);
182         if (ret) return(ret);
183         switch (a->type)
184                 {
185         case X509_LU_X509:
186                 ret=X509_subject_name_cmp(a->data.x509,b->data.x509);
187                 break;
188         case X509_LU_CRL:
189                 ret=X509_CRL_cmp(a->data.crl,b->data.crl);
190                 break;
191         default:
192                 /* abort(); */
193                 return 0;
194                 }
195         return(ret);
196         }
197
198 X509_STORE *X509_STORE_new(void)
199         {
200         X509_STORE *ret;
201
202         if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
203                 return(NULL);
204         ret->certs=lh_new(x509_object_hash,x509_object_cmp);
205         ret->cache=1;
206         ret->get_cert_methods=sk_X509_LOOKUP_new_null();
207         ret->verify=NULL;
208         ret->verify_cb=NULL;
209         memset(&ret->ex_data,0,sizeof(CRYPTO_EX_DATA));
210         ret->references=1;
211         ret->depth=0;
212         return(ret);
213         }
214
215 static void cleanup(X509_OBJECT *a)
216         {
217         if (a->type == X509_LU_X509)
218                 {
219                 X509_free(a->data.x509);
220                 }
221         else if (a->type == X509_LU_CRL)
222                 {
223                 X509_CRL_free(a->data.crl);
224                 }
225         else
226                 {
227                 /* abort(); */
228                 }
229
230         OPENSSL_free(a);
231         }
232
233 void X509_STORE_free(X509_STORE *vfy)
234         {
235         int i;
236         STACK_OF(X509_LOOKUP) *sk;
237         X509_LOOKUP *lu;
238
239         if(vfy == NULL)
240             return;
241
242         sk=vfy->get_cert_methods;
243         for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
244                 {
245                 lu=sk_X509_LOOKUP_value(sk,i);
246                 X509_LOOKUP_shutdown(lu);
247                 X509_LOOKUP_free(lu);
248                 }
249         sk_X509_LOOKUP_free(sk);
250
251         CRYPTO_free_ex_data(x509_store_meth,vfy,&vfy->ex_data);
252         lh_doall(vfy->certs,cleanup);
253         lh_free(vfy->certs);
254         OPENSSL_free(vfy);
255         }
256
257 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
258         {
259         int i;
260         STACK_OF(X509_LOOKUP) *sk;
261         X509_LOOKUP *lu;
262
263         sk=v->get_cert_methods;
264         for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
265                 {
266                 lu=sk_X509_LOOKUP_value(sk,i);
267                 if (m == lu->method)
268                         {
269                         return(lu);
270                         }
271                 }
272         /* a new one */
273         lu=X509_LOOKUP_new(m);
274         if (lu == NULL)
275                 return(NULL);
276         else
277                 {
278                 lu->store_ctx=v;
279                 if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
280                         return(lu);
281                 else
282                         {
283                         X509_LOOKUP_free(lu);
284                         return(NULL);
285                         }
286                 }
287         }
288
289 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
290              X509_OBJECT *ret)
291         {
292         X509_STORE *ctx=vs->ctx;
293         X509_LOOKUP *lu;
294         X509_OBJECT stmp,*tmp;
295         int i,j;
296
297         tmp=X509_OBJECT_retrieve_by_subject(ctx->certs,type,name);
298
299         if (tmp == NULL)
300                 {
301                 for (i=vs->current_method; i<sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
302                         {
303                         lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
304                         j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
305                         if (j < 0)
306                                 {
307                                 vs->current_method=j;
308                                 return(j);
309                                 }
310                         else if (j)
311                                 {
312                                 tmp= &stmp;
313                                 break;
314                                 }
315                         }
316                 vs->current_method=0;
317                 if (tmp == NULL)
318                         return(0);
319                 }
320
321 /*      if (ret->data.ptr != NULL)
322                 X509_OBJECT_free_contents(ret); */
323
324         ret->type=tmp->type;
325         ret->data.ptr=tmp->data.ptr;
326
327         X509_OBJECT_up_ref_count(ret);
328
329         return(1);
330         }
331
332 void X509_OBJECT_up_ref_count(X509_OBJECT *a)
333         {
334         switch (a->type)
335                 {
336         case X509_LU_X509:
337                 CRYPTO_add(&a->data.x509->references,1,CRYPTO_LOCK_X509);
338                 break;
339         case X509_LU_CRL:
340                 CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
341                 break;
342                 }
343         }
344
345 void X509_OBJECT_free_contents(X509_OBJECT *a)
346         {
347         switch (a->type)
348                 {
349         case X509_LU_X509:
350                 X509_free(a->data.x509);
351                 break;
352         case X509_LU_CRL:
353                 X509_CRL_free(a->data.crl);
354                 break;
355                 }
356         }
357
358 X509_OBJECT *X509_OBJECT_retrieve_by_subject(LHASH *h, int type,
359              X509_NAME *name)
360         {
361         X509_OBJECT stmp,*tmp;
362         X509 x509_s;
363         X509_CINF cinf_s;
364         X509_CRL crl_s;
365         X509_CRL_INFO crl_info_s;
366
367         stmp.type=type;
368         switch (type)
369                 {
370         case X509_LU_X509:
371                 stmp.data.x509= &x509_s;
372                 x509_s.cert_info= &cinf_s;
373                 cinf_s.subject=name;
374                 break;
375         case X509_LU_CRL:
376                 stmp.data.crl= &crl_s;
377                 crl_s.crl= &crl_info_s;
378                 crl_info_s.issuer=name;
379                 break;
380         default:
381                 /* abort(); */
382                 return NULL;
383                 }
384
385         tmp=(X509_OBJECT *)lh_retrieve(h,&stmp);
386         return(tmp);
387         }
388
389 X509_STORE_CTX *X509_STORE_CTX_new(void)
390 {
391         X509_STORE_CTX *ctx;
392         ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
393         if(ctx) memset(ctx, 0, sizeof(X509_STORE_CTX));
394         return ctx;
395 }
396
397 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
398 {
399         X509_STORE_CTX_cleanup(ctx);
400         OPENSSL_free(ctx);
401 }
402
403 void X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
404              STACK_OF(X509) *chain)
405         {
406         ctx->ctx=store;
407         ctx->current_method=0;
408         ctx->cert=x509;
409         ctx->untrusted=chain;
410         ctx->last_untrusted=0;
411         ctx->purpose=0;
412         ctx->trust=0;
413         ctx->valid=0;
414         ctx->chain=NULL;
415         ctx->depth=9;
416         ctx->error=0;
417         ctx->current_cert=NULL;
418         memset(&(ctx->ex_data),0,sizeof(CRYPTO_EX_DATA));
419         }
420
421 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
422         {
423         if (ctx->chain != NULL)
424                 {
425                 sk_X509_pop_free(ctx->chain,X509_free);
426                 ctx->chain=NULL;
427                 }
428         CRYPTO_free_ex_data(x509_store_ctx_meth,ctx,&(ctx->ex_data));
429         memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
430         }
431
432 IMPLEMENT_STACK_OF(X509_LOOKUP)