Add include dir
[openssl.git] / ssl / ssl_cert.c
1 /* ssl/ssl_cert.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 "objects.h"
61 #include "bio.h"
62 #include "pem.h"
63 #include "ssl_locl.h"
64
65 int SSL_get_ex_data_X509_STORE_CTX_idx()
66         {
67         static int ssl_x509_store_ctx_idx= -1;
68
69         if (ssl_x509_store_ctx_idx < 0)
70                 {
71                 ssl_x509_store_ctx_idx=X509_STORE_CTX_get_ex_new_index(
72                         0,"SSL for verify callback",NULL,NULL,NULL);
73                 }
74         return(ssl_x509_store_ctx_idx);
75         }
76
77 CERT *ssl_cert_new()
78         {
79         CERT *ret;
80
81         ret=(CERT *)Malloc(sizeof(CERT));
82         if (ret == NULL)
83                 {
84                 SSLerr(SSL_F_SSL_CERT_NEW,ERR_R_MALLOC_FAILURE);
85                 return(NULL);
86                 }
87         memset(ret,0,sizeof(CERT));
88 /*
89         ret->valid=0;
90         ret->mask=0;
91         ret->export_mask=0;
92         ret->cert_type=0;
93         ret->key->x509=NULL;
94         ret->key->publickey=NULL;
95         ret->key->privatekey=NULL; */
96
97         ret->key= &(ret->pkeys[SSL_PKEY_RSA_ENC]);
98         ret->references=1;
99
100         return(ret);
101         }
102
103 void ssl_cert_free(c)
104 CERT *c;
105         {
106         int i;
107
108         i=CRYPTO_add(&c->references,-1,CRYPTO_LOCK_SSL_CERT);
109 #ifdef REF_PRINT
110         REF_PRINT("CERT",c);
111 #endif
112         if (i > 0) return;
113 #ifdef REF_CHECK
114         if (i < 0)
115                 {
116                 fprintf(stderr,"ssl_cert_free, bad reference count\n");
117                 abort(); /* ok */
118                 }
119 #endif
120
121 #ifndef NO_RSA
122         if (c->rsa_tmp) RSA_free(c->rsa_tmp);
123 #endif
124 #ifndef NO_DH
125         if (c->dh_tmp) DH_free(c->dh_tmp);
126 #endif
127
128         for (i=0; i<SSL_PKEY_NUM; i++)
129                 {
130                 if (c->pkeys[i].x509 != NULL)
131                         X509_free(c->pkeys[i].x509);
132                 if (c->pkeys[i].privatekey != NULL)
133                         EVP_PKEY_free(c->pkeys[i].privatekey);
134 #if 0
135                 if (c->pkeys[i].publickey != NULL)
136                         EVP_PKEY_free(c->pkeys[i].publickey);
137 #endif
138                 }
139         if (c->cert_chain != NULL)
140                 sk_pop_free(c->cert_chain,X509_free);
141         Free(c);
142         }
143
144 int ssl_set_cert_type(c, type)
145 CERT *c;
146 int type;
147         {
148         c->cert_type=type;
149         return(1);
150         }
151
152 int ssl_verify_cert_chain(s,sk)
153 SSL *s;
154 STACK *sk;
155         {
156         X509 *x;
157         int i;
158         X509_STORE_CTX ctx;
159
160         if ((sk == NULL) || (sk_num(sk) == 0))
161                 return(0);
162
163         x=(X509 *)sk_value(sk,0);
164         X509_STORE_CTX_init(&ctx,s->ctx->cert_store,x,sk);
165         X509_STORE_CTX_set_ex_data(&ctx,SSL_get_ex_data_X509_STORE_CTX_idx(),
166                 (char *)s);
167
168         if (s->ctx->app_verify_callback != NULL)
169                 i=s->ctx->app_verify_callback(&ctx);
170         else
171                 {
172 #ifndef NO_X509_VERIFY
173                 i=X509_verify_cert(&ctx);
174 #else
175                 i=0;
176                 ctx.error=X509_V_ERR_APPLICATION_VERIFICATION;
177                 SSLerr(SSL_F_SSL_VERIFY_CERT_CHAIN,SSL_R_NO_VERIFY_CALLBACK);
178 #endif
179                 }
180
181         s->verify_result=ctx.error;
182         X509_STORE_CTX_cleanup(&ctx);
183
184         return(i);
185         }
186
187 static void set_client_CA_list(ca_list,list)
188 STACK **ca_list;
189 STACK *list;
190         {
191         if (*ca_list != NULL)
192                 sk_pop_free(*ca_list,X509_NAME_free);
193
194         *ca_list=list;
195         }
196
197 STACK *SSL_dup_CA_list(sk)
198 STACK *sk;
199         {
200         int i;
201         STACK *ret;
202         X509_NAME *name;
203
204         ret=sk_new_null();
205         for (i=0; i<sk_num(sk); i++)
206                 {
207                 name=X509_NAME_dup((X509_NAME *)sk_value(sk,i));
208                 if ((name == NULL) || !sk_push(ret,(char *)name))
209                         {
210                         sk_pop_free(ret,X509_NAME_free);
211                         return(NULL);
212                         }
213                 }
214         return(ret);
215         }
216
217 void SSL_set_client_CA_list(s,list)
218 SSL *s;
219 STACK *list;
220         {
221         set_client_CA_list(&(s->client_CA),list);
222         }
223
224 void SSL_CTX_set_client_CA_list(ctx,list)
225 SSL_CTX *ctx;
226 STACK *list;
227         {
228         set_client_CA_list(&(ctx->client_CA),list);
229         }
230
231 STACK *SSL_CTX_get_client_CA_list(ctx)
232 SSL_CTX *ctx;
233         {
234         return(ctx->client_CA);
235         }
236
237 STACK *SSL_get_client_CA_list(s)
238 SSL *s;
239         {
240         if (s->type == SSL_ST_CONNECT)
241                 { /* we are in the client */
242                 if (((s->version>>8) == SSL3_VERSION_MAJOR) &&
243                         (s->s3 != NULL))
244                         return(s->s3->tmp.ca_names);
245                 else
246                         return(NULL);
247                 }
248         else
249                 {
250                 if (s->client_CA != NULL)
251                         return(s->client_CA);
252                 else
253                         return(s->ctx->client_CA);
254                 }
255         }
256
257 static int add_client_CA(sk,x)
258 STACK **sk;
259 X509 *x;
260         {
261         X509_NAME *name;
262
263         if (x == NULL) return(0);
264         if ((*sk == NULL) && ((*sk=sk_new_null()) == NULL))
265                 return(0);
266                 
267         if ((name=X509_NAME_dup(X509_get_subject_name(x))) == NULL)
268                 return(0);
269
270         if (!sk_push(*sk,(char *)name))
271                 {
272                 X509_NAME_free(name);
273                 return(0);
274                 }
275         return(1);
276         }
277
278 int SSL_add_client_CA(ssl,x)
279 SSL *ssl;
280 X509 *x;
281         {
282         return(add_client_CA(&(ssl->client_CA),x));
283         }
284
285 int SSL_CTX_add_client_CA(ctx,x)
286 SSL_CTX *ctx;
287 X509 *x;
288         {
289         return(add_client_CA(&(ctx->client_CA),x));
290         }
291
292 static int name_cmp(a,b)
293 X509_NAME **a,**b;
294         {
295         return(X509_NAME_cmp(*a,*b));
296         }
297
298 #ifndef NO_STDIO
299 STACK *SSL_load_client_CA_file(file)
300 char *file;
301         {
302         BIO *in;
303         X509 *x=NULL;
304         X509_NAME *xn=NULL;
305         STACK *ret,*sk;
306
307         ret=sk_new(NULL);
308         sk=sk_new(name_cmp);
309
310         in=BIO_new(BIO_s_file_internal());
311
312         if ((ret == NULL) || (sk == NULL) || (in == NULL))
313                 {
314                 SSLerr(SSL_F_SSL_LOAD_CLIENT_CA_FILE,ERR_R_MALLOC_FAILURE);
315                 goto err;
316                 }
317         
318         if (!BIO_read_filename(in,file))
319                 goto err;
320
321         for (;;)
322                 {
323                 if (PEM_read_bio_X509(in,&x,NULL) == NULL)
324                         break;
325                 if ((xn=X509_get_subject_name(x)) == NULL) goto err;
326                 /* check for duplicates */
327                 xn=X509_NAME_dup(xn);
328                 if (xn == NULL) goto err;
329                 if (sk_find(sk,(char *)xn) >= 0)
330                         X509_NAME_free(xn);
331                 else
332                         {
333                         sk_push(sk,(char *)xn);
334                         sk_push(ret,(char *)xn);
335                         }
336                 }
337
338         if (0)
339                 {
340 err:
341                 if (ret != NULL) sk_pop_free(ret,X509_NAME_free);
342                 ret=NULL;
343                 }
344         if (sk != NULL) sk_free(sk);
345         if (in != NULL) BIO_free(in);
346         if (x != NULL) X509_free(x);
347         return(ret);
348         }
349 #endif
350