Coverage Report

Created: 2026-03-09 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/x509/x509_vpm.c
Line
Count
Source
1
/*
2
 * Copyright 2004-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
12
#include "internal/cryptlib.h"
13
#include <openssl/crypto.h>
14
#include <openssl/buffer.h>
15
#include <openssl/x509.h>
16
#include <openssl/x509v3.h>
17
18
#include "crypto/ctype.h"
19
#include "crypto/x509.h"
20
21
#include "x509_local.h"
22
23
typedef enum {
24
    OSSL_CHARSET_NONASCII,
25
    OSSL_CHARSET_ASCII,
26
    OSSL_CHARSET_ASCII_ALNUM,
27
} ossl_charset_t;
28
29
/* X509_VERIFY_PARAM functions */
30
31
#define SET_HOST 0
32
#define ADD_HOST 1
33
34
static X509_BUFFER *buffer_from_bytes(const uint8_t *bytes, size_t length)
35
0
{
36
0
    X509_BUFFER *buf;
37
38
0
    if ((buf = OPENSSL_zalloc(sizeof *buf)) != NULL
39
0
        && (buf->data = OPENSSL_memdup(bytes, length)) != NULL) {
40
0
        buf->len = length;
41
0
    } else {
42
0
        OPENSSL_free(buf);
43
0
        buf = NULL;
44
0
    }
45
0
    return buf;
46
0
}
47
48
/*
49
 * Copies |length| bytes from |bytes| to a new buffer, making the data
50
 * A C string. It is an error for the |bytes| to contain any \0 values
51
 * within |length|. |bytes| need not itself be \0 terminated, the data
52
 * in the buffer will be on success.
53
 */
54
static X509_BUFFER *buffer_from_string(const uint8_t *bytes, size_t length)
55
0
{
56
0
    X509_BUFFER *buf, *ret = NULL;
57
0
    uint8_t *data = NULL;
58
59
0
    if ((buf = OPENSSL_zalloc(sizeof *buf)) == NULL)
60
0
        goto err;
61
62
0
    if ((data = (uint8_t *)OPENSSL_strndup((char *)bytes, length)) == NULL)
63
0
        goto err;
64
65
0
    if (strlen((char *)data) != length)
66
0
        goto err;
67
68
0
    ret = buf;
69
0
    buf = NULL;
70
0
    ret->data = data;
71
0
    ret->len = length;
72
0
    data = NULL;
73
74
0
err:
75
0
    OPENSSL_free(buf);
76
0
    OPENSSL_free(data);
77
78
0
    return ret;
79
0
}
80
81
static X509_BUFFER *buffer_copy(const X509_BUFFER *b)
82
0
{
83
0
    return buffer_from_bytes(b->data, b->len);
84
0
}
85
86
static void buffer_free(X509_BUFFER *b)
87
0
{
88
0
    if (b == NULL)
89
0
        return;
90
0
    OPENSSL_free((void *)b->data);
91
0
    OPENSSL_free(b);
92
0
}
93
94
static int replace_buffer_stack(STACK_OF(X509_BUFFER) **dest,
95
    STACK_OF(X509_BUFFER) *const *src)
96
0
{
97
0
    sk_X509_BUFFER_pop_free(*dest, buffer_free);
98
0
    *dest = NULL;
99
0
    if (*src != NULL) {
100
0
        *dest = sk_X509_BUFFER_deep_copy(*src, buffer_copy, buffer_free);
101
0
        if (*dest == NULL)
102
0
            return 0;
103
0
    }
104
0
    return 1;
105
0
}
106
107
static int buffer_cmp(const X509_BUFFER *const *a, const X509_BUFFER *const *b)
108
0
{
109
0
    if ((*a)->len < (*b)->len)
110
0
        return -1;
111
0
    if ((*a)->len > (*b)->len)
112
0
        return 1;
113
0
    return memcmp((*a)->data, (*b)->data, (*b)->len);
114
0
}
115
116
static void clear_buffer_stack(STACK_OF(X509_BUFFER) **buffer_stack)
117
0
{
118
0
    sk_X509_BUFFER_pop_free(*buffer_stack, buffer_free);
119
0
    *buffer_stack = NULL;
120
0
}
121
122
static int add_bytes_to_buffer_stack(STACK_OF(X509_BUFFER) **buffer_stack,
123
    const uint8_t *name, size_t name_len)
124
0
{
125
0
    STACK_OF(X509_BUFFER) *tmp_stack = NULL;
126
0
    X509_BUFFER *copy = NULL;
127
0
    int ret = 0;
128
129
0
    if ((copy = buffer_from_bytes(name, name_len)) == NULL)
130
0
        goto err;
131
132
0
    tmp_stack = *buffer_stack;
133
0
    if (tmp_stack == NULL && (tmp_stack = sk_X509_BUFFER_new(buffer_cmp)) == NULL)
134
0
        goto err;
135
136
0
    if (!sk_X509_BUFFER_push(tmp_stack, copy))
137
0
        goto err;
138
139
0
    ret = 1;
140
0
    copy = NULL;
141
0
    *buffer_stack = tmp_stack;
142
0
    tmp_stack = NULL;
143
144
0
err:
145
0
    sk_X509_BUFFER_pop_free(tmp_stack, buffer_free);
146
0
    buffer_free(copy);
147
148
0
    return ret;
149
0
}
150
151
static int add_string_to_buffer_stack(STACK_OF(X509_BUFFER) **buffer_stack,
152
    const uint8_t *name, size_t name_len)
153
0
{
154
0
    STACK_OF(X509_BUFFER) *tmp_stack = NULL;
155
0
    X509_BUFFER *copy = NULL;
156
0
    int ret = 0;
157
158
0
    if ((copy = buffer_from_string(name, name_len)) == NULL)
159
0
        goto err;
160
161
0
    tmp_stack = *buffer_stack;
162
0
    if (tmp_stack == NULL && (tmp_stack = sk_X509_BUFFER_new(buffer_cmp)) == NULL)
163
0
        goto err;
164
165
0
    if (!sk_X509_BUFFER_push(tmp_stack, copy))
166
0
        goto err;
167
168
0
    ret = 1;
169
0
    copy = NULL;
170
0
    *buffer_stack = tmp_stack;
171
0
    tmp_stack = NULL;
172
173
0
err:
174
0
    sk_X509_BUFFER_pop_free(tmp_stack, buffer_free);
175
0
    buffer_free(copy);
176
177
0
    return ret;
178
0
}
179
180
static int validate_string_name(const char *name, size_t *name_len)
181
0
{
182
0
    size_t len = *name_len;
183
184
0
    if (name == NULL || len == 0)
185
0
        return 0;
186
187
    /*
188
     * Accept the trailing \0 byte if this is a C string. This is to
189
     * preserver behaviour that is traditional for the
190
     * set1_[host|email] functions.
191
     */
192
0
    if (name[len - 1] == '\0')
193
0
        len--;
194
195
    /* Refuse the empty string */
196
0
    if (len == 0)
197
0
        return 0;
198
199
    /* Refuse values with embedded \0 bytes other than at the end */
200
0
    if (memchr(name, '\0', len) != NULL)
201
0
        return 0;
202
203
0
    *name_len = len;
204
0
    return 1;
205
0
}
206
207
/*
208
 * Default input validation for verification parameter names. As these
209
 * could potentially come from untrusted input, doing basic input
210
 * validation makes sense, and ensures that subsequent parsing or
211
 * comparisons do not need to handle extreme out of range input.
212
 */
213
214
/* Default ip name input validation */
215
static int validate_ip_name(const uint8_t *name, size_t len)
216
0
{
217
0
    if (name != NULL && (len == 4 || len == 16))
218
0
        return 1;
219
0
    return 0;
220
0
}
221
222
static ossl_charset_t ossl_name_charset(int c, ossl_charset_t charset)
223
0
{
224
0
    if (ossl_isalnum(c))
225
0
        return 1;
226
0
    if (ossl_isascii(c))
227
0
        return charset == OSSL_CHARSET_ASCII
228
0
            || charset == OSSL_CHARSET_NONASCII;
229
0
    return charset == OSSL_CHARSET_NONASCII;
230
0
}
231
232
static int is_label_ok(int c, ossl_charset_t charset)
233
0
{
234
0
    if (!ossl_name_charset(c, charset) && c != '_')
235
0
        return 0;
236
0
    else
237
0
        return c != '.' && c != '-';
238
0
}
239
240
/* Default host name input validation */
241
static int validate_hostname_part(const char *name, size_t len,
242
    ossl_charset_t charset)
243
0
{
244
0
    size_t i, part_len;
245
0
    char c, prev;
246
247
0
    if (len < 2 || len > 256)
248
0
        return 0;
249
250
0
    part_len = 0;
251
0
    prev = '\0';
252
0
    for (i = 0; i < len; i++) {
253
0
        c = name[i];
254
0
        if (c == '.') {
255
            /*
256
             * Can not start a label with a .
257
             * unless it is the very first character.
258
             */
259
0
            if (part_len == 0 && i != 0)
260
0
                return 0;
261
            /* Can not end a label with a - */
262
0
            if (prev == '-')
263
0
                return 0;
264
0
            part_len = 0;
265
0
        } else {
266
            /* Can not start a label with a - */
267
0
            if (part_len == 0 && c == '-') {
268
0
                return 0;
269
0
            }
270
0
            if (!is_label_ok(c, charset) && c != '-')
271
0
                return 0;
272
0
        }
273
0
        part_len++;
274
0
        if (part_len > 63)
275
0
            return 0;
276
277
0
        prev = c;
278
0
    }
279
    /* Can not end with a . or a _ */
280
0
    if (prev == '.' || prev == '-')
281
0
        return 0;
282
283
0
    return 1;
284
0
}
285
286
static int validate_local_part(const char *name, size_t len,
287
    ossl_charset_t *out_charset)
288
0
{
289
0
    ossl_charset_t charset = OSSL_CHARSET_ASCII;
290
0
    size_t i;
291
292
0
    for (i = 0; i < len; i++) {
293
0
        if (name[i] == '\0')
294
0
            return 0;
295
0
        if (!ossl_isascii(name[i]))
296
0
            charset = OSSL_CHARSET_NONASCII;
297
0
    }
298
299
0
    *out_charset = charset;
300
0
    return 1;
301
0
}
302
303
/* Default email name input validation */
304
static int validate_email_name(const char *name, size_t len, int rfc822)
305
0
{
306
0
    size_t dns_len, local_len;
307
0
    char *at, *next, *dnsname;
308
0
    ossl_charset_t local_charset;
309
310
    /*
311
     * 64 for local part, 1 for @, 255 for domain name
312
     */
313
0
    if (len > 320)
314
0
        goto err;
315
316
    /* Reject it if there is no @ */
317
0
    if ((at = memchr(name, '@', len)) == NULL)
318
0
        goto err;
319
320
    /* Go to the last @ */
321
0
    while ((next = memchr(at + 1, '@', len - (at - name + 1))) != NULL)
322
0
        at = next;
323
324
    /* Ensure the local part is not oversize */
325
0
    local_len = len - (at - name);
326
0
    if (local_len > 64)
327
0
        goto err;
328
329
0
    if (!validate_local_part(name, len, &local_charset))
330
0
        goto err;
331
332
0
    if (rfc822 && local_charset == OSSL_CHARSET_NONASCII)
333
0
        goto err;
334
335
0
    if (!rfc822 && local_charset == OSSL_CHARSET_ASCII)
336
0
        goto err;
337
338
    /* What is after the @ must be valid as a dns name */
339
0
    dnsname = at + 1;
340
0
    dns_len = len - local_len - 1;
341
342
0
    if (rfc822)
343
0
        return validate_hostname_part(dnsname, dns_len, OSSL_CHARSET_ASCII_ALNUM);
344
345
0
    return validate_hostname_part(dnsname, dns_len, OSSL_CHARSET_NONASCII);
346
347
0
err:
348
0
    ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT);
349
0
    return 0;
350
0
}
351
352
X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
353
0
{
354
0
    X509_VERIFY_PARAM *param;
355
356
0
    param = OPENSSL_zalloc(sizeof(*param));
357
0
    if (param == NULL)
358
0
        return NULL;
359
0
    param->trust = X509_TRUST_DEFAULT;
360
    /* param->inh_flags = X509_VP_FLAG_DEFAULT; */
361
0
    param->depth = -1;
362
0
    param->auth_level = -1; /* -1 means unset, 0 is explicit */
363
0
    return param;
364
0
}
365
366
void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
367
0
{
368
0
    if (param == NULL)
369
0
        return;
370
0
    sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
371
0
    clear_buffer_stack(&param->hosts);
372
0
    clear_buffer_stack(&param->ips);
373
0
    clear_buffer_stack(&param->rfc822s);
374
0
    clear_buffer_stack(&param->smtputf8s);
375
0
    OPENSSL_free(param->peername);
376
0
    OPENSSL_free(param);
377
0
}
378
379
/*-
380
 * This function determines how parameters are "inherited" from one structure
381
 * to another. There are several different ways this can happen.
382
 *
383
 * 1. If a child structure needs to have its values initialized from a parent
384
 *    they are simply copied across. For example SSL_CTX copied to SSL.
385
 * 2. If the structure should take on values only if they are currently unset.
386
 *    For example the values in an SSL structure will take appropriate value
387
 *    for SSL servers or clients but only if the application has not set new
388
 *    ones.
389
 *
390
 * The "inh_flags" field determines how this function behaves.
391
 *
392
 * Normally any values which are set in the default are not copied from the
393
 * destination and verify flags are ORed together.
394
 *
395
 * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
396
 * to the destination. Effectively the values in "to" become default values
397
 * which will be used only if nothing new is set in "from".
398
 *
399
 * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
400
 * they are set or not. Flags is still Ored though.
401
 *
402
 * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
403
 * of ORed.
404
 *
405
 * If X509_VP_FLAG_LOCKED is set then no values are copied.
406
 *
407
 * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
408
 * after the next call.
409
 */
410
411
/* Macro to test if a field should be copied from src to dest */
412
413
#define test_x509_verify_param_copy(field, def) \
414
0
    (to_overwrite || (src->field != def && (to_default || dest->field == def)))
415
416
/* Macro to test and copy a field if necessary */
417
418
#define x509_verify_param_copy(field, def)       \
419
0
    if (test_x509_verify_param_copy(field, def)) \
420
0
        dest->field = src->field;
421
422
int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
423
    const X509_VERIFY_PARAM *src)
424
0
{
425
0
    unsigned long inh_flags;
426
0
    int to_default, to_overwrite;
427
428
0
    if (src == NULL)
429
0
        return 1;
430
0
    inh_flags = dest->inh_flags | src->inh_flags;
431
432
0
    if ((inh_flags & X509_VP_FLAG_ONCE) != 0)
433
0
        dest->inh_flags = 0;
434
435
0
    if ((inh_flags & X509_VP_FLAG_LOCKED) != 0)
436
0
        return 1;
437
438
0
    to_default = (inh_flags & X509_VP_FLAG_DEFAULT) != 0;
439
0
    to_overwrite = (inh_flags & X509_VP_FLAG_OVERWRITE) != 0;
440
441
0
    x509_verify_param_copy(purpose, 0);
442
0
    x509_verify_param_copy(trust, X509_TRUST_DEFAULT);
443
0
    x509_verify_param_copy(depth, -1);
444
0
    x509_verify_param_copy(auth_level, -1);
445
446
    /* If overwrite or check time not set, copy across */
447
448
0
    if (to_overwrite || (dest->flags & X509_V_FLAG_USE_CHECK_TIME) == 0) {
449
0
        dest->check_time = src->check_time;
450
0
        dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
451
        /* Don't need to copy flag: that is done below */
452
0
    }
453
454
0
    if ((inh_flags & X509_VP_FLAG_RESET_FLAGS) != 0)
455
0
        dest->flags = 0;
456
457
0
    dest->flags |= src->flags;
458
459
0
    if (test_x509_verify_param_copy(policies, NULL)) {
460
0
        if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
461
0
            return 0;
462
0
    }
463
464
0
    x509_verify_param_copy(hostflags, 0);
465
466
0
    if (test_x509_verify_param_copy(hosts, NULL)) {
467
0
        if (!replace_buffer_stack(&dest->hosts, &src->hosts))
468
0
            return 0;
469
0
    }
470
0
    x509_verify_param_copy(validate_host, NULL);
471
472
0
    if (test_x509_verify_param_copy(ips, NULL)) {
473
0
        if (!replace_buffer_stack(&dest->ips, &src->ips))
474
0
            return 0;
475
0
    }
476
0
    x509_verify_param_copy(validate_ip, NULL);
477
478
0
    if (test_x509_verify_param_copy(rfc822s, NULL)) {
479
0
        if (!replace_buffer_stack(&dest->rfc822s, &src->rfc822s))
480
0
            return 0;
481
0
    }
482
0
    x509_verify_param_copy(validate_rfc822, NULL);
483
484
0
    if (test_x509_verify_param_copy(smtputf8s, NULL)) {
485
0
        if (!replace_buffer_stack(&dest->smtputf8s, &src->smtputf8s))
486
0
            return 0;
487
0
    }
488
0
    x509_verify_param_copy(validate_smtputf8, NULL);
489
490
0
    return 1;
491
0
}
492
493
int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
494
    const X509_VERIFY_PARAM *from)
495
0
{
496
0
    unsigned long save_flags;
497
0
    int ret;
498
499
0
    if (to == NULL) {
500
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
501
0
        return 0;
502
0
    }
503
0
    save_flags = to->inh_flags;
504
0
    to->inh_flags |= X509_VP_FLAG_DEFAULT;
505
0
    ret = X509_VERIFY_PARAM_inherit(to, from);
506
0
    to->inh_flags = save_flags;
507
0
    return ret;
508
0
}
509
510
int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
511
0
{
512
0
    OPENSSL_free(param->name);
513
0
    param->name = OPENSSL_strdup(name);
514
0
    return param->name != NULL;
515
0
}
516
517
int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
518
0
{
519
0
    param->flags |= flags;
520
0
    if ((flags & X509_V_FLAG_POLICY_MASK) != 0)
521
0
        param->flags |= X509_V_FLAG_POLICY_CHECK;
522
0
    return 1;
523
0
}
524
525
int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
526
    unsigned long flags)
527
0
{
528
0
    param->flags &= ~flags;
529
0
    return 1;
530
0
}
531
532
unsigned long X509_VERIFY_PARAM_get_flags(const X509_VERIFY_PARAM *param)
533
0
{
534
0
    return param->flags;
535
0
}
536
537
uint32_t X509_VERIFY_PARAM_get_inh_flags(const X509_VERIFY_PARAM *param)
538
0
{
539
0
    return param->inh_flags;
540
0
}
541
542
int X509_VERIFY_PARAM_set_inh_flags(X509_VERIFY_PARAM *param, uint32_t flags)
543
0
{
544
0
    param->inh_flags = flags;
545
0
    return 1;
546
0
}
547
548
/* resets to default (any) purpose if |purpose| == X509_PURPOSE_DEFAULT_ANY */
549
int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
550
0
{
551
0
    return X509_PURPOSE_set(&param->purpose, purpose);
552
0
}
553
554
int X509_VERIFY_PARAM_get_purpose(const X509_VERIFY_PARAM *param)
555
0
{
556
0
    return param->purpose;
557
0
}
558
559
int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
560
0
{
561
0
    return X509_TRUST_set(&param->trust, trust);
562
0
}
563
564
void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
565
0
{
566
0
    param->depth = depth;
567
0
}
568
569
void X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
570
0
{
571
0
    param->auth_level = auth_level;
572
0
}
573
574
time_t X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
575
0
{
576
    /* This will be in the time_t range, because the only setter uses time_t */
577
0
    return (time_t)param->check_time;
578
0
}
579
580
void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
581
0
{
582
0
    param->check_time = (int64_t)t;
583
0
    param->flags |= X509_V_FLAG_USE_CHECK_TIME;
584
0
}
585
586
void ossl_x509_verify_param_set_time_posix(X509_VERIFY_PARAM *param, int64_t t)
587
0
{
588
0
    param->check_time = t;
589
0
    param->flags |= X509_V_FLAG_USE_CHECK_TIME;
590
0
}
591
592
int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
593
    ASN1_OBJECT *policy)
594
0
{
595
0
    if (param->policies == NULL) {
596
0
        param->policies = sk_ASN1_OBJECT_new_null();
597
0
        if (param->policies == NULL)
598
0
            return 0;
599
0
    }
600
601
0
    if (sk_ASN1_OBJECT_push(param->policies, policy) <= 0)
602
0
        return 0;
603
0
    return 1;
604
0
}
605
606
int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
607
    STACK_OF(ASN1_OBJECT) *policies)
608
0
{
609
0
    int i;
610
0
    ASN1_OBJECT *oid, *doid;
611
612
0
    if (param == NULL) {
613
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
614
0
        return 0;
615
0
    }
616
0
    sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
617
618
0
    if (policies == NULL) {
619
0
        param->policies = NULL;
620
0
        return 1;
621
0
    }
622
623
0
    param->policies = sk_ASN1_OBJECT_new_null();
624
0
    if (param->policies == NULL)
625
0
        return 0;
626
627
0
    for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
628
0
        oid = sk_ASN1_OBJECT_value(policies, i);
629
0
        doid = OBJ_dup(oid);
630
0
        if (doid == NULL)
631
0
            return 0;
632
0
        if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
633
0
            ASN1_OBJECT_free(doid);
634
0
            return 0;
635
0
        }
636
0
    }
637
0
    param->flags |= X509_V_FLAG_POLICY_CHECK;
638
0
    return 1;
639
0
}
640
641
char *X509_VERIFY_PARAM_get0_host(X509_VERIFY_PARAM *param, int idx)
642
0
{
643
0
    X509_BUFFER *buf = sk_X509_BUFFER_value(param->hosts, idx);
644
645
0
    return (buf != NULL) ? (char *)buf->data : NULL;
646
0
}
647
648
int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
649
    const char *dnsname, size_t len)
650
0
{
651
0
    clear_buffer_stack(&param->hosts);
652
0
    if (dnsname == NULL)
653
0
        return 1;
654
0
    if (len == 0)
655
0
        len = strlen(dnsname);
656
0
    if (len == 0)
657
0
        return 1;
658
0
    return X509_VERIFY_PARAM_add1_host(param, dnsname, len);
659
0
}
660
661
int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
662
    const char *dnsname, size_t len)
663
0
{
664
0
    if (dnsname == NULL)
665
0
        return 1;
666
0
    if (len == 0)
667
0
        len = strlen(dnsname);
668
0
    if (len == 0)
669
0
        return 1;
670
0
    if (!validate_string_name(dnsname, &len))
671
0
        return 0;
672
0
    if (param->validate_host != NULL) {
673
0
        if (!param->validate_host(dnsname, len))
674
0
            return 0;
675
0
    } else {
676
0
        if (!validate_hostname_part(dnsname, len, OSSL_CHARSET_ASCII_ALNUM))
677
0
            return 0;
678
0
    }
679
0
    return add_string_to_buffer_stack(&param->hosts, (const uint8_t *)dnsname, len);
680
0
}
681
682
void X509_VERIFY_PARAM_set1_host_input_validation(X509_VERIFY_PARAM *param,
683
    int (*validate_host)(const char *name, size_t len))
684
0
{
685
0
    param->validate_host = validate_host;
686
0
}
687
688
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
689
    const uint8_t *ip, size_t len)
690
0
{
691
0
    clear_buffer_stack(&param->ips);
692
0
    if (ip == NULL)
693
0
        return 1;
694
0
    return X509_VERIFY_PARAM_add1_ip(param, ip, len);
695
0
}
696
697
int X509_VERIFY_PARAM_add1_ip(X509_VERIFY_PARAM *param,
698
    const uint8_t *ip, size_t len)
699
0
{
700
0
    if (param->validate_ip != NULL) {
701
0
        if (!param->validate_ip(ip, len))
702
0
            return 0;
703
0
    } else {
704
0
        if (!validate_ip_name(ip, len))
705
0
            return 0;
706
0
    }
707
0
    return add_bytes_to_buffer_stack(&param->ips, ip, len);
708
0
}
709
710
void X509_VERIFY_PARAM_set1_ip_input_validation(X509_VERIFY_PARAM *param,
711
    int (*validate_ip)(const uint8_t *name, size_t len))
712
0
{
713
0
    param->validate_ip = validate_ip;
714
0
}
715
716
char *X509_VERIFY_PARAM_get0_email(X509_VERIFY_PARAM *param)
717
0
{
718
0
    X509_BUFFER *buf = sk_X509_BUFFER_value(param->rfc822s, 0);
719
720
0
    if ((buf = sk_X509_BUFFER_value(param->rfc822s, 0)) != NULL
721
0
        || (buf = sk_X509_BUFFER_value(param->smtputf8s, 0)) != NULL)
722
0
        return (char *)buf->data;
723
724
0
    return NULL;
725
0
}
726
727
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
728
    const char *email, size_t len)
729
0
{
730
0
    int ret = 0;
731
732
0
    if (X509_VERIFY_PARAM_set1_smtputf8(param, email, len))
733
0
        ret = 1;
734
0
    if (X509_VERIFY_PARAM_set1_rfc822(param, email, len))
735
0
        ret = 1;
736
737
0
    return ret;
738
0
}
739
740
int X509_VERIFY_PARAM_set1_smtputf8(X509_VERIFY_PARAM *param,
741
    const char *email, size_t len)
742
0
{
743
0
    clear_buffer_stack(&param->smtputf8s);
744
0
    if (email == NULL)
745
0
        return 1;
746
0
    return X509_VERIFY_PARAM_add1_smtputf8(param, email, len);
747
0
}
748
749
int X509_VERIFY_PARAM_add1_smtputf8(X509_VERIFY_PARAM *param,
750
    const char *email, size_t len)
751
0
{
752
0
    if (len == 0)
753
0
        len = strlen(email);
754
0
    if (!validate_string_name(email, &len))
755
0
        return 0;
756
0
    if (param->validate_smtputf8 != NULL) {
757
0
        if (!param->validate_smtputf8(email, len))
758
0
            return 0;
759
0
    } else {
760
0
        if (!validate_email_name(email, len, /*rfc822 =*/0))
761
0
            return 0;
762
0
    }
763
764
0
    return add_string_to_buffer_stack(&param->smtputf8s,
765
0
        (const uint8_t *)email, len);
766
0
}
767
768
void X509_VERIFY_PARAM_set1_smtputf8_input_validation(X509_VERIFY_PARAM *param,
769
    int (*validate_smtputf8)(const char *name, size_t len))
770
0
{
771
0
    param->validate_smtputf8 = validate_smtputf8;
772
0
}
773
774
int X509_VERIFY_PARAM_set1_rfc822(X509_VERIFY_PARAM *param,
775
    const char *email, size_t len)
776
0
{
777
0
    clear_buffer_stack(&param->rfc822s);
778
0
    if (email == NULL)
779
0
        return 1;
780
0
    return X509_VERIFY_PARAM_add1_rfc822(param, email, len);
781
0
}
782
783
int X509_VERIFY_PARAM_add1_rfc822(X509_VERIFY_PARAM *param,
784
    const char *email, size_t len)
785
0
{
786
0
    if (len == 0)
787
0
        len = strlen(email);
788
0
    if (!validate_string_name(email, &len))
789
0
        return 0;
790
0
    if (param->validate_rfc822 != NULL) {
791
0
        if (!param->validate_rfc822(email, len))
792
0
            return 0;
793
0
    } else {
794
0
        if (!validate_email_name(email, len, /*rfc822 =*/1))
795
0
            return 0;
796
0
    }
797
798
0
    return add_string_to_buffer_stack(&param->rfc822s,
799
0
        (const uint8_t *)email, len);
800
0
}
801
802
void X509_VERIFY_PARAM_set1_rfc822_input_validation(X509_VERIFY_PARAM *param,
803
    int (*validate_rfc822)(const char *name, size_t len))
804
0
{
805
0
    param->validate_rfc822 = validate_rfc822;
806
0
}
807
808
void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
809
    unsigned int flags)
810
0
{
811
0
    param->hostflags = flags;
812
0
}
813
814
unsigned int X509_VERIFY_PARAM_get_hostflags(const X509_VERIFY_PARAM *param)
815
0
{
816
0
    return param->hostflags;
817
0
}
818
819
char *X509_VERIFY_PARAM_get0_peername(const X509_VERIFY_PARAM *param)
820
0
{
821
0
    return param->peername;
822
0
}
823
824
/*
825
 * Move peername from one param structure to another, freeing any name present
826
 * at the target.  If the source is a NULL parameter structure, free and zero
827
 * the target peername.
828
 */
829
void X509_VERIFY_PARAM_move_peername(X509_VERIFY_PARAM *to,
830
    X509_VERIFY_PARAM *from)
831
0
{
832
0
    char *peername = (from != NULL) ? from->peername : NULL;
833
834
0
    if (to->peername != peername) {
835
0
        OPENSSL_free(to->peername);
836
0
        to->peername = peername;
837
0
    }
838
0
    if (from != NULL)
839
0
        from->peername = NULL;
840
0
}
841
842
static const unsigned char *int_X509_VERIFY_PARAM_get0_ip(X509_VERIFY_PARAM *param, size_t *plen, size_t idx)
843
0
{
844
0
    X509_BUFFER *buf;
845
846
0
    if (idx > INT_MAX)
847
0
        return NULL;
848
849
0
    if (param == NULL || param->ips == NULL) {
850
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
851
0
        return NULL;
852
0
    }
853
854
0
    buf = sk_X509_BUFFER_value(param->ips, (int)idx);
855
856
0
    if (buf != NULL) {
857
0
        if (plen != NULL)
858
0
            *plen = buf->len;
859
0
        return (unsigned char *)buf->data;
860
0
    }
861
0
    return NULL;
862
0
}
863
864
char *X509_VERIFY_PARAM_get1_ip_asc(X509_VERIFY_PARAM *param)
865
0
{
866
0
    size_t iplen;
867
    /* XXX casts away const */
868
0
    unsigned char *ip = (unsigned char *)int_X509_VERIFY_PARAM_get0_ip(param, &iplen, 0);
869
870
0
    return ip == NULL ? NULL : ossl_ipaddr_to_asc(ip, (int)iplen);
871
0
}
872
873
int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
874
0
{
875
0
    unsigned char ipout[16];
876
0
    size_t iplen;
877
878
0
    if (ipasc == NULL)
879
0
        return X509_VERIFY_PARAM_set1_ip(param, NULL, 0);
880
0
    if ((iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc)) == 0)
881
0
        return 0;
882
0
    return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
883
0
}
884
885
int X509_VERIFY_PARAM_add1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
886
0
{
887
0
    unsigned char ipout[16];
888
0
    size_t iplen;
889
890
0
    if ((iplen = (size_t)ossl_a2i_ipadd(ipout, ipasc)) == 0)
891
0
        return 0;
892
0
    return X509_VERIFY_PARAM_add1_ip(param, ipout, iplen);
893
0
}
894
895
int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
896
0
{
897
0
    return param->depth;
898
0
}
899
900
int X509_VERIFY_PARAM_get_auth_level(const X509_VERIFY_PARAM *param)
901
0
{
902
0
    return param->auth_level;
903
0
}
904
905
const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
906
0
{
907
0
    return param->name;
908
0
}
909
910
/*
911
 * Default verify parameters: these are used for various applications and can
912
 * be overridden by the user specified table. NB: the 'name' field *must* be
913
 * in alphabetical order because it will be searched using OBJ_search.
914
 */
915
916
static const X509_VERIFY_PARAM default_table[] = {
917
    {
918
        .name = "code_sign", /* Code sign parameters */
919
        .purpose = X509_PURPOSE_CODE_SIGN,
920
        .trust = X509_TRUST_OBJECT_SIGN,
921
        .depth = -1,
922
        .auth_level = -1,
923
    },
924
    {
925
        .name = "default", /* X509 default parameters */
926
        .flags = X509_V_FLAG_TRUSTED_FIRST,
927
        .depth = 100,
928
        .auth_level = -1,
929
    },
930
    {
931
        .name = "pkcs7", /* S/MIME sign parameters */
932
        .purpose = X509_PURPOSE_SMIME_SIGN,
933
        .trust = X509_TRUST_EMAIL,
934
        .depth = -1,
935
        .auth_level = -1,
936
    },
937
    {
938
        .name = "smime_sign", /* S/MIME sign parameters */
939
        .purpose = X509_PURPOSE_SMIME_SIGN,
940
        .trust = X509_TRUST_EMAIL,
941
        .depth = -1,
942
        .auth_level = -1,
943
    },
944
    {
945
        .name = "ssl_client", /* SSL/TLS client parameters */
946
        .purpose = X509_PURPOSE_SSL_CLIENT,
947
        .trust = X509_TRUST_SSL_CLIENT,
948
        .depth = -1,
949
        .auth_level = -1,
950
    },
951
    {
952
        .name = "ssl_server", /* SSL/TLS server parameters */
953
        .purpose = X509_PURPOSE_SSL_SERVER,
954
        .trust = X509_TRUST_SSL_SERVER,
955
        .depth = -1,
956
        .auth_level = -1,
957
    }
958
};
959
960
static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
961
962
static int table_cmp(const X509_VERIFY_PARAM *a, const X509_VERIFY_PARAM *b)
963
0
{
964
0
    return strcmp(a->name, b->name);
965
0
}
966
967
DECLARE_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table);
968
IMPLEMENT_OBJ_BSEARCH_CMP_FN(X509_VERIFY_PARAM, X509_VERIFY_PARAM, table);
969
970
static int param_cmp(const X509_VERIFY_PARAM *const *a,
971
    const X509_VERIFY_PARAM *const *b)
972
0
{
973
0
    return strcmp((*a)->name, (*b)->name);
974
0
}
975
976
int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
977
0
{
978
0
    int idx;
979
0
    X509_VERIFY_PARAM *ptmp;
980
981
0
    if (param_table == NULL) {
982
0
        param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
983
0
        if (param_table == NULL)
984
0
            return 0;
985
0
    } else {
986
0
        idx = sk_X509_VERIFY_PARAM_find(param_table, param);
987
0
        if (idx >= 0) {
988
0
            ptmp = sk_X509_VERIFY_PARAM_delete(param_table, idx);
989
0
            X509_VERIFY_PARAM_free(ptmp);
990
0
        }
991
0
    }
992
993
0
    if (sk_X509_VERIFY_PARAM_push(param_table, param) <= 0)
994
0
        return 0;
995
0
    return 1;
996
0
}
997
998
int X509_VERIFY_PARAM_get_count(void)
999
0
{
1000
0
    int num = OSSL_NELEM(default_table);
1001
1002
0
    if (param_table != NULL)
1003
0
        num += sk_X509_VERIFY_PARAM_num(param_table);
1004
0
    return num;
1005
0
}
1006
1007
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
1008
0
{
1009
0
    int num = OSSL_NELEM(default_table);
1010
1011
0
    if (id < 0) {
1012
0
        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_INVALID_ARGUMENT);
1013
0
        return NULL;
1014
0
    }
1015
1016
0
    if (id < num)
1017
0
        return default_table + id;
1018
0
    return sk_X509_VERIFY_PARAM_value(param_table, id - num);
1019
0
}
1020
1021
const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
1022
0
{
1023
0
    int idx;
1024
0
    X509_VERIFY_PARAM pm;
1025
1026
0
    pm.name = (char *)name;
1027
0
    if (param_table != NULL) {
1028
        /* Ideally, this would be done under a lock */
1029
0
        sk_X509_VERIFY_PARAM_sort(param_table);
1030
0
        idx = sk_X509_VERIFY_PARAM_find(param_table, &pm);
1031
0
        if (idx >= 0)
1032
0
            return sk_X509_VERIFY_PARAM_value(param_table, idx);
1033
0
    }
1034
0
    return OBJ_bsearch_table(&pm, default_table, OSSL_NELEM(default_table));
1035
0
}
1036
1037
void X509_VERIFY_PARAM_table_cleanup(void)
1038
0
{
1039
0
    sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free);
1040
    param_table = NULL;
1041
0
}