9b22093277e420a8bafb4b092c268fae736bc986
[openssl.git] / crypto / x509 / x509_vpm.c
1 /* x509_vpm.c */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 2004.
4  */
5 /* ====================================================================
6  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60
61 #include "cryptlib.h"
62 #include <openssl/crypto.h>
63 #include <openssl/lhash.h>
64 #include <openssl/buffer.h>
65 #include <openssl/x509.h>
66 #include <openssl/x509v3.h>
67
68 #include "vpm_int.h"
69
70 /* X509_VERIFY_PARAM functions */
71
72 static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
73         {
74         X509_VERIFY_PARAM_ID *paramid;
75         if (!param)
76                 return;
77         param->name = NULL;
78         param->purpose = 0;
79         param->trust = 0;
80         /*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
81         param->inh_flags = 0;
82         param->flags = 0;
83         param->depth = -1;
84         if (param->policies)
85                 {
86                 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
87                 param->policies = NULL;
88                 }
89         paramid = param->id;
90         if (paramid->host)
91                 {
92                 OPENSSL_free(paramid->host);
93                 paramid->host = NULL;
94                 paramid->hostlen = 0;
95                 }
96         if (paramid->email)
97                 {
98                 OPENSSL_free(paramid->email);
99                 paramid->email = NULL;
100                 paramid->emaillen = 0;
101                 }
102         if (paramid->ip)
103                 {
104                 OPENSSL_free(paramid->ip);
105                 paramid->ip = NULL;
106                 paramid->iplen = 0;
107                 }
108
109         }
110
111 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
112         {
113         X509_VERIFY_PARAM *param;
114         X509_VERIFY_PARAM_ID *paramid;
115         param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
116         if (!param)
117                 return NULL;
118         paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
119         if (!paramid)
120                 {
121                 OPENSSL_free(param);
122                 return NULL;
123                 }
124         memset(param, 0, sizeof(X509_VERIFY_PARAM));
125         memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
126         param->id = paramid;
127         x509_verify_param_zero(param);
128         return param;
129         }
130
131 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
132         {
133         x509_verify_param_zero(param);
134         OPENSSL_free(param->id);
135         OPENSSL_free(param);
136         }
137
138 /* This function determines how parameters are "inherited" from one structure
139  * to another. There are several different ways this can happen.
140  *
141  * 1. If a child structure needs to have its values initialized from a parent
142  *    they are simply copied across. For example SSL_CTX copied to SSL.
143  * 2. If the structure should take on values only if they are currently unset.
144  *    For example the values in an SSL structure will take appropriate value
145  *    for SSL servers or clients but only if the application has not set new
146  *    ones.
147  *
148  * The "inh_flags" field determines how this function behaves. 
149  *
150  * Normally any values which are set in the default are not copied from the
151  * destination and verify flags are ORed together.
152  *
153  * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
154  * to the destination. Effectively the values in "to" become default values
155  * which will be used only if nothing new is set in "from".
156  *
157  * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
158  * they are set or not. Flags is still Ored though.
159  *
160  * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
161  * of ORed.
162  *
163  * If X509_VP_FLAG_LOCKED is set then no values are copied.
164  *
165  * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
166  * after the next call.
167  */
168
169 /* Macro to test if a field should be copied from src to dest */
170
171 #define test_x509_verify_param_copy(field, def) \
172         (to_overwrite || \
173                 ((src->field != def) && (to_default || (dest->field == def))))
174
175 /* As above but for ID fields */
176
177 #define test_x509_verify_param_copy_id(idf, def) \
178         test_x509_verify_param_copy(id->idf, def)
179
180 /* Macro to test and copy a field if necessary */
181
182 #define x509_verify_param_copy(field, def) \
183         if (test_x509_verify_param_copy(field, def)) \
184                 dest->field = src->field
185
186
187 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
188                                                 const X509_VERIFY_PARAM *src)
189         {
190         unsigned long inh_flags;
191         int to_default, to_overwrite;
192         X509_VERIFY_PARAM_ID *id;
193         if (!src)
194                 return 1;
195         id = src->id;
196         inh_flags = dest->inh_flags | src->inh_flags;
197
198         if (inh_flags & X509_VP_FLAG_ONCE)
199                 dest->inh_flags = 0;
200
201         if (inh_flags & X509_VP_FLAG_LOCKED)
202                 return 1;
203
204         if (inh_flags & X509_VP_FLAG_DEFAULT)
205                 to_default = 1;
206         else
207                 to_default = 0;
208
209         if (inh_flags & X509_VP_FLAG_OVERWRITE)
210                 to_overwrite = 1;
211         else
212                 to_overwrite = 0;
213
214         x509_verify_param_copy(purpose, 0);
215         x509_verify_param_copy(trust, 0);
216         x509_verify_param_copy(depth, -1);
217
218         /* If overwrite or check time not set, copy across */
219
220         if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME))
221                 {
222                 dest->check_time = src->check_time;
223                 dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
224                 /* Don't need to copy flag: that is done below */
225                 }
226
227         if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
228                 dest->flags = 0;
229
230         dest->flags |= src->flags;
231
232         if (test_x509_verify_param_copy(policies, NULL))
233                 {
234                 if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
235                         return 0;
236                 }
237
238         if (test_x509_verify_param_copy_id(host, NULL))
239                 {
240                 if (!X509_VERIFY_PARAM_set1_host(dest, id->host, id->hostlen))
241                         return 0;
242                 dest->id->hostflags = id->hostflags;
243                 }
244
245         if (test_x509_verify_param_copy_id(email, NULL))
246                 {
247                 if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
248                         return 0;
249                 }
250
251         if (test_x509_verify_param_copy_id(ip, NULL))
252                 {
253                 if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
254                         return 0;
255                 }
256
257         return 1;
258         }
259
260 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
261                                                 const X509_VERIFY_PARAM *from)
262         {
263         unsigned long save_flags = to->inh_flags;
264         int ret;
265         to->inh_flags |= X509_VP_FLAG_DEFAULT;
266         ret = X509_VERIFY_PARAM_inherit(to, from);
267         to->inh_flags = save_flags;
268         return ret;
269         }
270
271 static int int_x509_param_set1(unsigned char **pdest, size_t *pdestlen,
272                                 const unsigned char *src, size_t srclen)
273         {
274         void *tmp;
275         if (src)
276                 {
277                 if (srclen == 0)
278                         {
279                         tmp = BUF_strdup((char *)src);
280                         srclen = strlen((char *)src);
281                         }
282                 else
283                         tmp = BUF_memdup(src, srclen);
284                 if (!tmp)
285                         return 0;
286                 }
287         else
288                 {
289                 tmp = NULL;
290                 srclen = 0;
291                 }
292         if (*pdest)
293                 OPENSSL_free(*pdest);
294         *pdest = tmp;
295         if (pdestlen)
296                 *pdestlen = srclen;
297         return 1;
298         }
299
300 int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
301         {
302         if (param->name)
303                 OPENSSL_free(param->name);
304         param->name = BUF_strdup(name);
305         if (param->name)
306                 return 1;
307         return 0;
308         }
309
310 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
311         {
312         param->flags |= flags;
313         if (flags & X509_V_FLAG_POLICY_MASK)
314                 param->flags |= X509_V_FLAG_POLICY_CHECK;
315         return 1;
316         }
317
318 int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
319         {
320         param->flags &= ~flags;
321         return 1;
322         }
323
324 unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
325         {
326         return param->flags;
327         }
328
329 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
330         {
331         return X509_PURPOSE_set(&param->purpose, purpose);
332         }
333
334 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
335         {
336         return X509_TRUST_set(&param->trust, trust);
337         }
338
339 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
340         {
341         param->depth = depth;
342         }
343
344 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
345         {
346         param->check_time = t;
347         param->flags |= X509_V_FLAG_USE_CHECK_TIME;
348         }
349
350 int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
351         {
352         if (!param->policies)
353                 {
354                 param->policies = sk_ASN1_OBJECT_new_null();
355                 if (!param->policies)
356                         return 0;
357                 }
358         if (!sk_ASN1_OBJECT_push(param->policies, policy))
359                 return 0;
360         return 1;
361         }
362
363 int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, 
364                                         STACK_OF(ASN1_OBJECT) *policies)
365         {
366         int i;
367         ASN1_OBJECT *oid, *doid;
368         if (!param)
369                 return 0;
370         if (param->policies)
371                 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
372
373         if (!policies)
374                 {
375                 param->policies = NULL;
376                 return 1;
377                 }
378
379         param->policies = sk_ASN1_OBJECT_new_null();
380         if (!param->policies)
381                 return 0;
382
383         for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++)
384                 {
385                 oid = sk_ASN1_OBJECT_value(policies, i);
386                 doid = OBJ_dup(oid);
387                 if (!doid)
388                         return 0;
389                 if (!sk_ASN1_OBJECT_push(param->policies, doid))
390                         {
391                         ASN1_OBJECT_free(doid);
392                         return 0;
393                         }
394                 }
395         param->flags |= X509_V_FLAG_POLICY_CHECK;
396         return 1;
397         }
398
399 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
400                                 const unsigned char *name, size_t namelen)
401         {
402         return int_x509_param_set1(&param->id->host, &param->id->hostlen,
403                                         name, namelen);
404         }
405
406 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
407                                         unsigned int flags)
408         {
409         param->id->hostflags = flags;
410         }
411
412 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
413                                 const unsigned char *email, size_t emaillen)
414         {
415         return int_x509_param_set1(&param->id->email, &param->id->emaillen,
416                                         email, emaillen);
417         }
418
419 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
420                                         const unsigned char *ip, size_t iplen)
421         {
422         if (iplen != 0 && iplen != 4 && iplen != 16)
423                 return 0;
424         return int_x509_param_set1(&param->id->ip, &param->id->iplen, ip, iplen);
425         }
426
427 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
428         {
429         unsigned char ipout[16];
430         int iplen;
431         iplen = a2i_ipadd(ipout, ipasc);
432         if (iplen == 0)
433                 return 0;
434         return X509_VERIFY_PARAM_set1_ip(param, ipout, (size_t)iplen);
435         }
436
437 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
438         {
439         return param->depth;
440         }
441
442 const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
443         {
444         return param->name;
445         }
446
447 static X509_VERIFY_PARAM_ID _empty_id = {NULL, 0, 0U, NULL, 0, NULL, 0};
448
449 #define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
450
451
452 /* Default verify parameters: these are used for various
453  * applications and can be overridden by the user specified table.
454  * NB: the 'name' field *must* be in alphabetical order because it
455  * will be searched using OBJ_search.
456  */
457
458 static const X509_VERIFY_PARAM default_table[] = {
459         {
460         "default",      /* X509 default parameters */
461         0,              /* Check time */
462         0,              /* internal flags */
463         0,              /* flags */
464         0,              /* purpose */
465         0,              /* trust */
466         100,            /* depth */
467         NULL,           /* policies */
468         vpm_empty_id
469         },
470         {
471         "pkcs7",                        /* S/MIME sign parameters */
472         0,                              /* Check time */
473         0,                              /* internal flags */
474         0,                              /* flags */
475         X509_PURPOSE_SMIME_SIGN,        /* purpose */
476         X509_TRUST_EMAIL,               /* trust */
477         -1,                             /* depth */
478         NULL,                           /* policies */
479         vpm_empty_id
480         },
481         {
482         "smime_sign",                   /* S/MIME sign parameters */
483         0,                              /* Check time */
484         0,                              /* internal flags */
485         0,                              /* flags */
486         X509_PURPOSE_SMIME_SIGN,        /* purpose */
487         X509_TRUST_EMAIL,               /* trust */
488         -1,                             /* depth */
489         NULL,                           /* policies */
490         vpm_empty_id
491         },
492         {
493         "ssl_client",                   /* SSL/TLS client parameters */
494         0,                              /* Check time */
495         0,                              /* internal flags */
496         0,                              /* flags */
497         X509_PURPOSE_SSL_CLIENT,        /* purpose */
498         X509_TRUST_SSL_CLIENT,          /* trust */
499         -1,                             /* depth */
500         NULL,                           /* policies */
501         vpm_empty_id
502         },
503         {
504         "ssl_server",                   /* SSL/TLS server parameters */
505         0,                              /* Check time */
506         0,                              /* internal flags */
507         0,                              /* flags */
508         X509_PURPOSE_SSL_SERVER,        /* purpose */
509         X509_TRUST_SSL_SERVER,          /* trust */
510         -1,                             /* depth */
511         NULL,                           /* policies */
512         vpm_empty_id
513         }};
514
515 static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
516
517 static int table_cmp(const X509_VERIFY_PARAM *a, const X509_VERIFY_PARAM *b)
518
519         {
520         return strcmp(a->name, b->name);
521         }
522
523 DECLARE_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM,
524                            table);
525 IMPLEMENT_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM,
526                              table);
527
528 static int param_cmp(const X509_VERIFY_PARAM * const *a,
529                         const X509_VERIFY_PARAM * const *b)
530         {
531         return strcmp((*a)->name, (*b)->name);
532         }
533
534 int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
535         {
536         int idx;
537         X509_VERIFY_PARAM *ptmp;
538         if (!param_table)
539                 {
540                 param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
541                 if (!param_table)
542                         return 0;
543                 }
544         else
545                 {
546                 idx = sk_X509_VERIFY_PARAM_find(param_table, param);
547                 if (idx != -1)
548                         {
549                         ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
550                         X509_VERIFY_PARAM_free(ptmp);
551                         (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
552                         }
553                 }
554         if (!sk_X509_VERIFY_PARAM_push(param_table, param))
555                 return 0;
556         return 1;
557         }
558
559 int X509_VERIFY_PARAM_get_count(void)
560         {
561         int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
562         if (param_table)
563                 num += sk_X509_VERIFY_PARAM_num(param_table);
564         return num;
565         }
566
567 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
568         {
569         int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
570         if (id < num)
571                 return default_table + id;
572         return sk_X509_VERIFY_PARAM_value(param_table, id - num);
573         }
574
575 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
576         {
577         int idx;
578         X509_VERIFY_PARAM pm;
579
580         pm.name = (char *)name;
581         if (param_table)
582                 {
583                 idx = sk_X509_VERIFY_PARAM_find(param_table, &pm);
584                 if (idx != -1)
585                         return sk_X509_VERIFY_PARAM_value(param_table, idx);
586                 }
587         return OBJ_bsearch_table(&pm, default_table,
588                            sizeof(default_table)/sizeof(X509_VERIFY_PARAM));
589         }
590
591 void X509_VERIFY_PARAM_table_cleanup(void)
592         {
593         if (param_table)
594                 sk_X509_VERIFY_PARAM_pop_free(param_table,
595                                                 X509_VERIFY_PARAM_free);
596         param_table = NULL;
597         }