1/*
2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3 * 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#include <string.h>
58
59#include <openssl/buf.h>
60#include <openssl/lhash.h>
61#include <openssl/mem.h>
62#include <openssl/obj.h>
63#include <openssl/stack.h>
64#include <openssl/x509.h>
65#include <openssl/x509v3.h>
66
67#include "vpm_int.h"
68#include "../internal.h"
69
70
71/* X509_VERIFY_PARAM functions */
72
73#define SET_HOST 0
74#define ADD_HOST 1
75
76static char *str_copy(char *s)
77{
78    return OPENSSL_strdup(s);
79}
80
81static void str_free(char *s)
82{
83    OPENSSL_free(s);
84}
85
86#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
87
88static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
89                                    const char *name, size_t namelen)
90{
91    char *copy;
92
93    /*
94     * Refuse names with embedded NUL bytes.
95     * XXX: Do we need to push an error onto the error stack?
96     */
97    if (name && OPENSSL_memchr(name, '\0', namelen))
98        return 0;
99
100    if (mode == SET_HOST && id->hosts) {
101        string_stack_free(id->hosts);
102        id->hosts = NULL;
103    }
104    if (name == NULL || namelen == 0)
105        return 1;
106
107    copy = BUF_strndup(name, namelen);
108    if (copy == NULL)
109        return 0;
110
111    if (id->hosts == NULL &&
112        (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
113        OPENSSL_free(copy);
114        return 0;
115    }
116
117    if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
118        OPENSSL_free(copy);
119        if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
120            sk_OPENSSL_STRING_free(id->hosts);
121            id->hosts = NULL;
122        }
123        return 0;
124    }
125
126    return 1;
127}
128
129static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
130{
131    X509_VERIFY_PARAM_ID *paramid;
132    if (!param)
133        return;
134    param->name = NULL;
135    param->purpose = 0;
136    param->trust = 0;
137    /*
138     * param->inh_flags = X509_VP_FLAG_DEFAULT;
139     */
140    param->inh_flags = 0;
141    param->flags = 0;
142    param->depth = -1;
143    if (param->policies) {
144        sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
145        param->policies = NULL;
146    }
147    paramid = param->id;
148    if (paramid->hosts) {
149        string_stack_free(paramid->hosts);
150        paramid->hosts = NULL;
151    }
152    if (paramid->peername) {
153        OPENSSL_free(paramid->peername);
154        paramid->peername = NULL;
155    }
156    if (paramid->email) {
157        OPENSSL_free(paramid->email);
158        paramid->email = NULL;
159        paramid->emaillen = 0;
160    }
161    if (paramid->ip) {
162        OPENSSL_free(paramid->ip);
163        paramid->ip = NULL;
164        paramid->iplen = 0;
165    }
166
167}
168
169X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
170{
171    X509_VERIFY_PARAM *param;
172    X509_VERIFY_PARAM_ID *paramid;
173    param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
174    if (!param)
175        return NULL;
176    paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
177    if (!paramid) {
178        OPENSSL_free(param);
179        return NULL;
180    }
181    OPENSSL_memset(param, 0, sizeof(X509_VERIFY_PARAM));
182    OPENSSL_memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
183    param->id = paramid;
184    x509_verify_param_zero(param);
185    return param;
186}
187
188void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
189{
190    if (param == NULL)
191        return;
192    x509_verify_param_zero(param);
193    OPENSSL_free(param->id);
194    OPENSSL_free(param);
195}
196
197/*-
198 * This function determines how parameters are "inherited" from one structure
199 * to another. There are several different ways this can happen.
200 *
201 * 1. If a child structure needs to have its values initialized from a parent
202 *    they are simply copied across. For example SSL_CTX copied to SSL.
203 * 2. If the structure should take on values only if they are currently unset.
204 *    For example the values in an SSL structure will take appropriate value
205 *    for SSL servers or clients but only if the application has not set new
206 *    ones.
207 *
208 * The "inh_flags" field determines how this function behaves.
209 *
210 * Normally any values which are set in the default are not copied from the
211 * destination and verify flags are ORed together.
212 *
213 * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
214 * to the destination. Effectively the values in "to" become default values
215 * which will be used only if nothing new is set in "from".
216 *
217 * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
218 * they are set or not. Flags is still Ored though.
219 *
220 * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
221 * of ORed.
222 *
223 * If X509_VP_FLAG_LOCKED is set then no values are copied.
224 *
225 * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
226 * after the next call.
227 */
228
229/* Macro to test if a field should be copied from src to dest */
230
231#define test_x509_verify_param_copy(field, def) \
232  (to_overwrite ||                              \
233   ((src->field != (def)) && (to_default || (dest->field == (def)))))
234
235/* As above but for ID fields */
236
237#define test_x509_verify_param_copy_id(idf, def) \
238        test_x509_verify_param_copy(id->idf, def)
239
240/* Macro to test and copy a field if necessary */
241
242#define x509_verify_param_copy(field, def) \
243        if (test_x509_verify_param_copy(field, def)) \
244                dest->field = src->field
245
246int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
247                              const X509_VERIFY_PARAM *src)
248{
249    unsigned long inh_flags;
250    int to_default, to_overwrite;
251    X509_VERIFY_PARAM_ID *id;
252    if (!src)
253        return 1;
254    id = src->id;
255    inh_flags = dest->inh_flags | src->inh_flags;
256
257    if (inh_flags & X509_VP_FLAG_ONCE)
258        dest->inh_flags = 0;
259
260    if (inh_flags & X509_VP_FLAG_LOCKED)
261        return 1;
262
263    if (inh_flags & X509_VP_FLAG_DEFAULT)
264        to_default = 1;
265    else
266        to_default = 0;
267
268    if (inh_flags & X509_VP_FLAG_OVERWRITE)
269        to_overwrite = 1;
270    else
271        to_overwrite = 0;
272
273    x509_verify_param_copy(purpose, 0);
274    x509_verify_param_copy(trust, 0);
275    x509_verify_param_copy(depth, -1);
276
277    /* If overwrite or check time not set, copy across */
278
279    if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
280        dest->check_time = src->check_time;
281        dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
282        /* Don't need to copy flag: that is done below */
283    }
284
285    if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
286        dest->flags = 0;
287
288    dest->flags |= src->flags;
289
290    if (test_x509_verify_param_copy(policies, NULL)) {
291        if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
292            return 0;
293    }
294
295    /* Copy the host flags if and only if we're copying the host list */
296    if (test_x509_verify_param_copy_id(hosts, NULL)) {
297        if (dest->id->hosts) {
298            string_stack_free(dest->id->hosts);
299            dest->id->hosts = NULL;
300        }
301        if (id->hosts) {
302            dest->id->hosts =
303                sk_OPENSSL_STRING_deep_copy(id->hosts, str_copy, str_free);
304            if (dest->id->hosts == NULL)
305                return 0;
306            dest->id->hostflags = id->hostflags;
307        }
308    }
309
310    if (test_x509_verify_param_copy_id(email, NULL)) {
311        if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
312            return 0;
313    }
314
315    if (test_x509_verify_param_copy_id(ip, NULL)) {
316        if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
317            return 0;
318    }
319
320    return 1;
321}
322
323int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
324                           const X509_VERIFY_PARAM *from)
325{
326    unsigned long save_flags = to->inh_flags;
327    int ret;
328    to->inh_flags |= X509_VP_FLAG_DEFAULT;
329    ret = X509_VERIFY_PARAM_inherit(to, from);
330    to->inh_flags = save_flags;
331    return ret;
332}
333
334static int int_x509_param_set1(char **pdest, size_t *pdestlen,
335                               const char *src, size_t srclen)
336{
337    void *tmp;
338    if (src) {
339        if (srclen == 0) {
340            tmp = BUF_strdup(src);
341            srclen = strlen(src);
342        } else
343            tmp = BUF_memdup(src, srclen);
344        if (!tmp)
345            return 0;
346    } else {
347        tmp = NULL;
348        srclen = 0;
349    }
350    if (*pdest)
351        OPENSSL_free(*pdest);
352    *pdest = tmp;
353    if (pdestlen)
354        *pdestlen = srclen;
355    return 1;
356}
357
358int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
359{
360    if (param->name)
361        OPENSSL_free(param->name);
362    param->name = BUF_strdup(name);
363    if (param->name)
364        return 1;
365    return 0;
366}
367
368int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
369{
370    param->flags |= flags;
371    if (flags & X509_V_FLAG_POLICY_MASK)
372        param->flags |= X509_V_FLAG_POLICY_CHECK;
373    return 1;
374}
375
376int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
377                                  unsigned long flags)
378{
379    param->flags &= ~flags;
380    return 1;
381}
382
383unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
384{
385    return param->flags;
386}
387
388int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
389{
390    return X509_PURPOSE_set(&param->purpose, purpose);
391}
392
393int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
394{
395    return X509_TRUST_set(&param->trust, trust);
396}
397
398void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
399{
400    param->depth = depth;
401}
402
403void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
404{
405    param->check_time = t;
406    param->flags |= X509_V_FLAG_USE_CHECK_TIME;
407}
408
409int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
410                                  ASN1_OBJECT *policy)
411{
412    if (!param->policies) {
413        param->policies = sk_ASN1_OBJECT_new_null();
414        if (!param->policies)
415            return 0;
416    }
417    if (!sk_ASN1_OBJECT_push(param->policies, policy))
418        return 0;
419    return 1;
420}
421
422int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
423                                    STACK_OF(ASN1_OBJECT) *policies)
424{
425    size_t i;
426    ASN1_OBJECT *oid, *doid;
427    if (!param)
428        return 0;
429    if (param->policies)
430        sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
431
432    if (!policies) {
433        param->policies = NULL;
434        return 1;
435    }
436
437    param->policies = sk_ASN1_OBJECT_new_null();
438    if (!param->policies)
439        return 0;
440
441    for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
442        oid = sk_ASN1_OBJECT_value(policies, i);
443        doid = OBJ_dup(oid);
444        if (!doid)
445            return 0;
446        if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
447            ASN1_OBJECT_free(doid);
448            return 0;
449        }
450    }
451    param->flags |= X509_V_FLAG_POLICY_CHECK;
452    return 1;
453}
454
455int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
456                                const char *name, size_t namelen)
457{
458    return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
459}
460
461int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
462                                const char *name, size_t namelen)
463{
464    return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
465}
466
467void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
468                                     unsigned int flags)
469{
470    param->id->hostflags = flags;
471}
472
473char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
474{
475    return param->id->peername;
476}
477
478int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
479                                 const char *email, size_t emaillen)
480{
481    return int_x509_param_set1(&param->id->email, &param->id->emaillen,
482                               email, emaillen);
483}
484
485int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
486                              const unsigned char *ip, size_t iplen)
487{
488    if (iplen != 0 && iplen != 4 && iplen != 16)
489        return 0;
490    return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
491                               (char *)ip, iplen);
492}
493
494int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
495{
496    unsigned char ipout[16];
497    size_t iplen;
498
499    iplen = (size_t)a2i_ipadd(ipout, ipasc);
500    if (iplen == 0)
501        return 0;
502    return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
503}
504
505int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
506{
507    return param->depth;
508}
509
510const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
511{
512    return param->name;
513}
514
515static const X509_VERIFY_PARAM_ID _empty_id =
516    { NULL, 0U, NULL, NULL, 0, NULL, 0 };
517
518#define vpm_empty_id ((X509_VERIFY_PARAM_ID *)&_empty_id)
519
520/*
521 * Default verify parameters: these are used for various applications and can
522 * be overridden by the user specified table. NB: the 'name' field *must* be
523 * in alphabetical order because it will be searched using OBJ_search.
524 */
525
526static const X509_VERIFY_PARAM default_table[] = {
527    {
528     (char *)"default",         /* X509 default parameters */
529     0,                         /* Check time */
530     0,                         /* internal flags */
531     0,                         /* flags */
532     0,                         /* purpose */
533     0,                         /* trust */
534     100,                       /* depth */
535     NULL,                      /* policies */
536     vpm_empty_id},
537    {
538     (char *)"pkcs7",           /* S/MIME sign parameters */
539     0,                         /* Check time */
540     0,                         /* internal flags */
541     0,                         /* flags */
542     X509_PURPOSE_SMIME_SIGN,   /* purpose */
543     X509_TRUST_EMAIL,          /* trust */
544     -1,                        /* depth */
545     NULL,                      /* policies */
546     vpm_empty_id},
547    {
548     (char *)"smime_sign",      /* S/MIME sign parameters */
549     0,                         /* Check time */
550     0,                         /* internal flags */
551     0,                         /* flags */
552     X509_PURPOSE_SMIME_SIGN,   /* purpose */
553     X509_TRUST_EMAIL,          /* trust */
554     -1,                        /* depth */
555     NULL,                      /* policies */
556     vpm_empty_id},
557    {
558     (char *)"ssl_client",      /* SSL/TLS client parameters */
559     0,                         /* Check time */
560     0,                         /* internal flags */
561     0,                         /* flags */
562     X509_PURPOSE_SSL_CLIENT,   /* purpose */
563     X509_TRUST_SSL_CLIENT,     /* trust */
564     -1,                        /* depth */
565     NULL,                      /* policies */
566     vpm_empty_id},
567    {
568     (char *)"ssl_server",      /* SSL/TLS server parameters */
569     0,                         /* Check time */
570     0,                         /* internal flags */
571     0,                         /* flags */
572     X509_PURPOSE_SSL_SERVER,   /* purpose */
573     X509_TRUST_SSL_SERVER,     /* trust */
574     -1,                        /* depth */
575     NULL,                      /* policies */
576     vpm_empty_id}
577};
578
579static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
580
581static int param_cmp(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b)
582{
583    return strcmp((*a)->name, (*b)->name);
584}
585
586int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
587{
588    X509_VERIFY_PARAM *ptmp;
589    if (!param_table) {
590        param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
591        if (!param_table)
592            return 0;
593    } else {
594        size_t idx;
595
596        if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) {
597            ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
598            X509_VERIFY_PARAM_free(ptmp);
599            (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
600        }
601    }
602    if (!sk_X509_VERIFY_PARAM_push(param_table, param))
603        return 0;
604    return 1;
605}
606
607int X509_VERIFY_PARAM_get_count(void)
608{
609    int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
610    if (param_table)
611        num += sk_X509_VERIFY_PARAM_num(param_table);
612    return num;
613}
614
615const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
616{
617    int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
618    if (id < num)
619        return default_table + id;
620    return sk_X509_VERIFY_PARAM_value(param_table, id - num);
621}
622
623const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
624{
625    X509_VERIFY_PARAM pm;
626    unsigned i, limit;
627
628    pm.name = (char *)name;
629    if (param_table) {
630        size_t idx;
631        if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
632            return sk_X509_VERIFY_PARAM_value(param_table, idx);
633    }
634
635    limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
636    for (i = 0; i < limit; i++) {
637        if (strcmp(default_table[i].name, name) == 0) {
638            return &default_table[i];
639        }
640    }
641    return NULL;
642}
643
644void X509_VERIFY_PARAM_table_cleanup(void)
645{
646    if (param_table)
647        sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free);
648    param_table = NULL;
649}
650