GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/x509v3/v3_utl.c Lines: 113 592 19.1 %
Date: 2017-11-07 Branches: 73 547 13.3 %

Line Branch Exec Source
1
/* $OpenBSD: v3_utl.c,v 1.26 2017/01/29 17:49:23 beck Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 1999-2003 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
/* X509 v3 extension utilities */
59
60
#include <ctype.h>
61
#include <stdio.h>
62
#include <string.h>
63
64
#include <openssl/bn.h>
65
#include <openssl/conf.h>
66
#include <openssl/err.h>
67
#include <openssl/x509v3.h>
68
69
static char *strip_spaces(char *name);
70
static int sk_strcmp(const char * const *a, const char * const *b);
71
static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
72
    GENERAL_NAMES *gens);
73
static void str_free(OPENSSL_STRING str);
74
static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
75
76
static int ipv4_from_asc(unsigned char *v4, const char *in);
77
static int ipv6_from_asc(unsigned char *v6, const char *in);
78
static int ipv6_cb(const char *elem, int len, void *usr);
79
static int ipv6_hex(unsigned char *out, const char *in, int inlen);
80
81
/* Add a CONF_VALUE name value pair to stack */
82
83
int
84
X509V3_add_value(const char *name, const char *value,
85
    STACK_OF(CONF_VALUE) **extlist)
86
{
87
	CONF_VALUE *vtmp = NULL;
88
	char *tname = NULL, *tvalue = NULL;
89
90

300
	if (name && !(tname = strdup(name)))
91
		goto err;
92

132
	if (value && !(tvalue = strdup(value)))
93
		goto err;
94
104
	if (!(vtmp = malloc(sizeof(CONF_VALUE))))
95
		goto err;
96

168
	if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
97
		goto err;
98
104
	vtmp->section = NULL;
99
104
	vtmp->name = tname;
100
104
	vtmp->value = tvalue;
101
104
	if (!sk_CONF_VALUE_push(*extlist, vtmp))
102
		goto err;
103
104
	return 1;
104
105
err:
106
	X509V3error(ERR_R_MALLOC_FAILURE);
107
	free(vtmp);
108
	free(tname);
109
	free(tvalue);
110
	return 0;
111
104
}
112
113
int
114
X509V3_add_value_uchar(const char *name, const unsigned char *value,
115
    STACK_OF(CONF_VALUE) **extlist)
116
{
117
	return X509V3_add_value(name, (const char *)value, extlist);
118
}
119
120
/* Free function for STACK_OF(CONF_VALUE) */
121
122
void
123
X509V3_conf_free(CONF_VALUE *conf)
124
{
125
208
	if (!conf)
126
		return;
127
104
	free(conf->name);
128
104
	free(conf->value);
129
104
	free(conf->section);
130
104
	free(conf);
131
208
}
132
133
int
134
X509V3_add_value_bool(const char *name, int asn1_bool,
135
    STACK_OF(CONF_VALUE) **extlist)
136
{
137
24
	if (asn1_bool)
138
		return X509V3_add_value(name, "TRUE", extlist);
139
12
	return X509V3_add_value(name, "FALSE", extlist);
140
12
}
141
142
int
143
X509V3_add_value_bool_nf(char *name, int asn1_bool,
144
    STACK_OF(CONF_VALUE) **extlist)
145
{
146
	if (asn1_bool)
147
		return X509V3_add_value(name, "TRUE", extlist);
148
	return 1;
149
}
150
151
152
char *
153
i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
154
{
155
	BIGNUM *bntmp = NULL;
156
	char *strtmp = NULL;
157
158
	if (!a)
159
		return NULL;
160
	if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
161
	    !(strtmp = BN_bn2dec(bntmp)))
162
		X509V3error(ERR_R_MALLOC_FAILURE);
163
	BN_free(bntmp);
164
	return strtmp;
165
}
166
167
char *
168
i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
169
{
170
	BIGNUM *bntmp = NULL;
171
	char *strtmp = NULL;
172
173
4
	if (!a)
174
		return NULL;
175

4
	if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
176
2
	    !(strtmp = BN_bn2dec(bntmp)))
177
		X509V3error(ERR_R_MALLOC_FAILURE);
178
2
	BN_free(bntmp);
179
2
	return strtmp;
180
2
}
181
182
ASN1_INTEGER *
183
s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
184
{
185
	BIGNUM *bn = NULL;
186
	ASN1_INTEGER *aint;
187
	int isneg, ishex;
188
	int ret;
189
190
	if (!value) {
191
		X509V3error(X509V3_R_INVALID_NULL_VALUE);
192
		return 0;
193
	}
194
	bn = BN_new();
195
	if (value[0] == '-') {
196
		value++;
197
		isneg = 1;
198
	} else
199
		isneg = 0;
200
201
	if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
202
		value += 2;
203
		ishex = 1;
204
	} else
205
		ishex = 0;
206
207
	if (ishex)
208
		ret = BN_hex2bn(&bn, value);
209
	else
210
		ret = BN_dec2bn(&bn, value);
211
212
	if (!ret || value[ret]) {
213
		BN_free(bn);
214
		X509V3error(X509V3_R_BN_DEC2BN_ERROR);
215
		return 0;
216
	}
217
218
	if (isneg && BN_is_zero(bn))
219
		isneg = 0;
220
221
	aint = BN_to_ASN1_INTEGER(bn, NULL);
222
	BN_free(bn);
223
	if (!aint) {
224
		X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
225
		return 0;
226
	}
227
	if (isneg)
228
		aint->type |= V_ASN1_NEG;
229
	return aint;
230
}
231
232
int
233
X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
234
    STACK_OF(CONF_VALUE) **extlist)
235
{
236
	char *strtmp;
237
	int ret;
238
239
24
	if (!aint)
240
12
		return 1;
241
	if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
242
		return 0;
243
	ret = X509V3_add_value(name, strtmp, extlist);
244
	free(strtmp);
245
	return ret;
246
12
}
247
248
int
249
X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
250
{
251
	char *btmp;
252
253
8
	if (!(btmp = value->value))
254
		goto err;
255

12
	if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") ||
256

8
	    !strcmp(btmp, "Y") || !strcmp(btmp, "y") ||
257
8
	    !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
258
		*asn1_bool = 0xff;
259
		return 1;
260

4
	} else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
261
	    !strcmp(btmp, "N") || !strcmp(btmp, "n") ||
262
	    !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
263
4
		*asn1_bool = 0;
264
4
		return 1;
265
	}
266
267
err:
268
	X509V3error(X509V3_R_INVALID_BOOLEAN_STRING);
269
	X509V3_conf_err(value);
270
	return 0;
271
4
}
272
273
int
274
X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
275
{
276
	ASN1_INTEGER *itmp;
277
278
	if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
279
		X509V3_conf_err(value);
280
		return 0;
281
	}
282
	*aint = itmp;
283
	return 1;
284
}
285
286
#define HDR_NAME	1
287
#define HDR_VALUE	2
288
289
/*#define DEBUG*/
290
291
STACK_OF(CONF_VALUE) *
292
X509V3_parse_list(const char *line)
293
{
294
	char *p, *q, c;
295
	char *ntmp, *vtmp;
296
48
	STACK_OF(CONF_VALUE) *values = NULL;
297
	char *linebuf;
298
	int state;
299
300
	/* We are going to modify the line so copy it first */
301
24
	if ((linebuf = strdup(line)) == NULL) {
302
		X509V3error(ERR_R_MALLOC_FAILURE);
303
		goto err;
304
	}
305
	state = HDR_NAME;
306
	ntmp = NULL;
307
308
	/* Go through all characters */
309

1960
	for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') &&
310
944
	    (c != '\n'); p++) {
311
312
944
		switch (state) {
313
		case HDR_NAME:
314
452
			if (c == ':') {
315
				state = HDR_VALUE;
316
4
				*p = 0;
317
4
				ntmp = strip_spaces(q);
318
4
				if (!ntmp) {
319
					X509V3error(X509V3_R_INVALID_NULL_NAME);
320
					goto err;
321
				}
322
4
				q = p + 1;
323
452
			} else if (c == ',') {
324
16
				*p = 0;
325
16
				ntmp = strip_spaces(q);
326
16
				q = p + 1;
327
16
				if (!ntmp) {
328
					X509V3error(X509V3_R_INVALID_NULL_NAME);
329
					goto err;
330
				}
331
16
				X509V3_add_value(ntmp, NULL, &values);
332
16
			}
333
			break;
334
335
		case HDR_VALUE:
336
20
			if (c == ',') {
337
				state = HDR_NAME;
338
				*p = 0;
339
				vtmp = strip_spaces(q);
340
				if (!vtmp) {
341
					X509V3error(X509V3_R_INVALID_NULL_VALUE);
342
					goto err;
343
				}
344
				X509V3_add_value(ntmp, vtmp, &values);
345
				ntmp = NULL;
346
				q = p + 1;
347
			}
348
349
		}
350
	}
351
352
48
	if (state == HDR_VALUE) {
353
24
		vtmp = strip_spaces(q);
354
4
		if (!vtmp) {
355
			X509V3error(X509V3_R_INVALID_NULL_VALUE);
356
			goto err;
357
		}
358
4
		X509V3_add_value(ntmp, vtmp, &values);
359
4
	} else {
360
		ntmp = strip_spaces(q);
361
20
		if (!ntmp) {
362
			X509V3error(X509V3_R_INVALID_NULL_NAME);
363
			goto err;
364
		}
365
20
		X509V3_add_value(ntmp, NULL, &values);
366
	}
367
24
	free(linebuf);
368
24
	return values;
369
370
err:
371
	free(linebuf);
372
	sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
373
	return NULL;
374
375
24
}
376
377
/* Delete leading and trailing spaces from a string */
378
static char *
379
strip_spaces(char *name)
380
{
381
	char *p, *q;
382
383
	/* Skip over leading spaces */
384
	p = name;
385

252
	while (*p && isspace((unsigned char)*p))
386
8
		p++;
387
44
	if (!*p)
388
		return NULL;
389
44
	q = p + strlen(p) - 1;
390

132
	while ((q != p) && isspace((unsigned char)*q))
391
		q--;
392
44
	if (p != q)
393
44
		q[1] = 0;
394
44
	if (!*p)
395
		return NULL;
396
44
	return p;
397
44
}
398
399
/* hex string utilities */
400
401
/* Given a buffer of length 'len' return a malloc'ed string with its
402
 * hex representation
403
 */
404
char *
405
hex_to_string(const unsigned char *buffer, long len)
406
{
407
	char *tmp, *q;
408
	const unsigned char *p;
409
	int i;
410
	static const char hexdig[] = "0123456789ABCDEF";
411
412
	if (!buffer || !len)
413
		return NULL;
414
	if (!(tmp = malloc(len * 3 + 1))) {
415
		X509V3error(ERR_R_MALLOC_FAILURE);
416
		return NULL;
417
	}
418
	q = tmp;
419
	for (i = 0, p = buffer; i < len; i++, p++) {
420
		*q++ = hexdig[(*p >> 4) & 0xf];
421
		*q++ = hexdig[*p & 0xf];
422
		*q++ = ':';
423
	}
424
	q[-1] = 0;
425
	return tmp;
426
}
427
428
/* Give a string of hex digits convert to
429
 * a buffer
430
 */
431
432
unsigned char *
433
string_to_hex(const char *str, long *len)
434
{
435
	unsigned char *hexbuf, *q;
436
	unsigned char ch, cl, *p;
437
52
	if (!str) {
438
		X509V3error(X509V3_R_INVALID_NULL_ARGUMENT);
439
		return NULL;
440
	}
441
26
	if (!(hexbuf = malloc(strlen(str) >> 1)))
442
		goto err;
443
884
	for (p = (unsigned char *)str, q = hexbuf; *p; ) {
444
416
		ch = *p++;
445
416
		if (ch == ':')
446
			continue;
447
416
		cl = *p++;
448
416
		if (!cl) {
449
			X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS);
450
			free(hexbuf);
451
			return NULL;
452
		}
453
416
		ch = tolower(ch);
454
416
		cl = tolower(cl);
455
456

832
		if ((ch >= '0') && (ch <= '9'))
457
286
			ch -= '0';
458

260
		else if ((ch >= 'a') && (ch <= 'f'))
459
130
			ch -= 'a' - 10;
460
		else
461
			goto badhex;
462
463

832
		if ((cl >= '0') && (cl <= '9'))
464
286
			cl -= '0';
465

260
		else if ((cl >= 'a') && (cl <= 'f'))
466
130
			cl -= 'a' - 10;
467
		else
468
			goto badhex;
469
470
416
		*q++ = (ch << 4) | cl;
471
	}
472
473
26
	if (len)
474
26
		*len = q - hexbuf;
475
476
26
	return hexbuf;
477
478
err:
479
	free(hexbuf);
480
	X509V3error(ERR_R_MALLOC_FAILURE);
481
	return NULL;
482
483
badhex:
484
	free(hexbuf);
485
	X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT);
486
	return NULL;
487
26
}
488
489
/* V2I name comparison function: returns zero if 'name' matches
490
 * cmp or cmp.*
491
 */
492
493
int
494
name_cmp(const char *name, const char *cmp)
495
{
496
	int len, ret;
497
	char c;
498
499
	len = strlen(cmp);
500
	if ((ret = strncmp(name, cmp, len)))
501
		return ret;
502
	c = name[len];
503
	if (!c || (c=='.'))
504
		return 0;
505
	return 1;
506
}
507
508
static int
509
sk_strcmp(const char * const *a, const char * const *b)
510
{
511
	return strcmp(*a, *b);
512
}
513
514
STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
515
{
516
	GENERAL_NAMES *gens;
517
	STACK_OF(OPENSSL_STRING) *ret;
518
519
4
	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
520
2
	ret = get_email(X509_get_subject_name(x), gens);
521
2
	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
522
2
	return ret;
523
}
524
525
STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
526
{
527
	AUTHORITY_INFO_ACCESS *info;
528
36
	STACK_OF(OPENSSL_STRING) *ret = NULL;
529
	int i;
530
531
18
	info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
532
18
	if (!info)
533
18
		return NULL;
534
	for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
535
		ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
536
		if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
537
			if (ad->location->type == GEN_URI) {
538
				if (!append_ia5(&ret,
539
				    ad->location->d.uniformResourceIdentifier))
540
					break;
541
			}
542
		}
543
	}
544
	AUTHORITY_INFO_ACCESS_free(info);
545
	return ret;
546
18
}
547
548
STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
549
{
550
	GENERAL_NAMES *gens;
551
	STACK_OF(X509_EXTENSION) *exts;
552
	STACK_OF(OPENSSL_STRING) *ret;
553
554
	exts = X509_REQ_get_extensions(x);
555
	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
556
	ret = get_email(X509_REQ_get_subject_name(x), gens);
557
	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
558
	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
559
	return ret;
560
}
561
562
563
static
564
STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens)
565
{
566
4
	STACK_OF(OPENSSL_STRING) *ret = NULL;
567
	X509_NAME_ENTRY *ne;
568
	ASN1_IA5STRING *email;
569
	GENERAL_NAME *gen;
570
	int i;
571
572
	/* Now add any email address(es) to STACK */
573
	i = -1;
574
575
	/* First supplied X509_NAME */
576
6
	while ((i = X509_NAME_get_index_by_NID(name,
577
2
	    NID_pkcs9_emailAddress, i)) >= 0) {
578
		ne = X509_NAME_get_entry(name, i);
579
		email = X509_NAME_ENTRY_get_data(ne);
580
		if (!append_ia5(&ret, email))
581
			return NULL;
582
	}
583
4
	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
584
		gen = sk_GENERAL_NAME_value(gens, i);
585
		if (gen->type != GEN_EMAIL)
586
			continue;
587
		if (!append_ia5(&ret, gen->d.ia5))
588
			return NULL;
589
	}
590
2
	return ret;
591
2
}
592
593
static void
594
str_free(OPENSSL_STRING str)
595
{
596
	free(str);
597
}
598
599
static int
600
append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
601
{
602
	char *emtmp;
603
604
	/* First some sanity checks */
605
	if (email->type != V_ASN1_IA5STRING)
606
		return 1;
607
	if (!email->data || !email->length)
608
		return 1;
609
	if (!*sk)
610
		*sk = sk_OPENSSL_STRING_new(sk_strcmp);
611
	if (!*sk)
612
		return 0;
613
	/* Don't add duplicates */
614
	if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
615
		return 1;
616
	emtmp = strdup((char *)email->data);
617
	if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
618
		X509_email_free(*sk);
619
		*sk = NULL;
620
		return 0;
621
	}
622
	return 1;
623
}
624
625
void
626
X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
627
{
628
72
	sk_OPENSSL_STRING_pop_free(sk, str_free);
629
36
}
630
631
typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
632
    const unsigned char *subject, size_t subject_len, unsigned int flags);
633
634
/* Skip pattern prefix to match "wildcard" subject */
635
static void skip_prefix(const unsigned char **p, size_t *plen,
636
    const unsigned char *subject, size_t subject_len, unsigned int flags)
637
{
638
	const unsigned char *pattern = *p;
639
	size_t pattern_len = *plen;
640
641
	/*
642
	 * If subject starts with a leading '.' followed by more octets, and
643
	 * pattern is longer, compare just an equal-length suffix with the
644
	 * full subject (starting at the '.'), provided the prefix contains
645
	 * no NULs.
646
	 */
647
	if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
648
		return;
649
650
	while (pattern_len > subject_len && *pattern) {
651
		if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
652
		    *pattern == '.')
653
			break;
654
		++pattern;
655
		--pattern_len;
656
	}
657
658
	/* Skip if entire prefix acceptable */
659
	if (pattern_len == subject_len) {
660
		*p = pattern;
661
		*plen = pattern_len;
662
	}
663
}
664
665
/*
666
 * Open/BoringSSL uses memcmp for "equal_case" while their
667
 * "equal_nocase" function is a hand-rolled strncasecmp that does not
668
 * allow \0 in the pattern. Since an embedded \0 is likely a sign of
669
 * problems, we simply don't allow it in either case, and then we use
670
 * standard libc funcitons.
671
 */
672
673
/* Compare using strncasecmp */
674
static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
675
    const unsigned char *subject, size_t subject_len,
676
    unsigned int flags)
677
{
678
	if (memchr(pattern, '\0', pattern_len) != NULL)
679
		return 0;
680
	if (memchr(subject, '\0', subject_len) != NULL)
681
		return 0;
682
	skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
683
	if (pattern_len != subject_len)
684
		return 0;
685
	return (strncasecmp(pattern, subject, pattern_len) == 0);
686
}
687
688
/* Compare using strncmp. */
689
static int equal_case(const unsigned char *pattern, size_t pattern_len,
690
    const unsigned char *subject, size_t subject_len,
691
    unsigned int flags)
692
{
693
	if (memchr(pattern, 0, pattern_len) != NULL)
694
		return 0;
695
	if (memchr(subject, 0, subject_len) != NULL)
696
		return 0;
697
	skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
698
	if (pattern_len != subject_len)
699
		return 0;
700
	return (strncmp(pattern, subject, pattern_len) == 0);
701
}
702
703
/*
704
 * RFC 5280, section 7.5, requires that only the domain is compared in a
705
 * case-insensitive manner.
706
 */
707
static int equal_email(const unsigned char *a, size_t a_len,
708
    const unsigned char *b, size_t b_len,
709
    unsigned int unused_flags)
710
{
711
	size_t pos = a_len;
712
	if (a_len != b_len)
713
		return 0;
714
	/*
715
	 * We search backwards for the '@' character, so that we do not have to
716
	 * deal with quoted local-parts.  The domain part is compared in a
717
	 * case-insensitive manner.
718
	 */
719
	while (pos > 0) {
720
		pos--;
721
		if (a[pos] == '@' || b[pos] == '@') {
722
			if (!equal_nocase(a + pos, a_len - pos, b + pos, a_len - pos, 0))
723
				return 0;
724
			break;
725
		}
726
	}
727
	if (pos == 0)
728
		pos = a_len;
729
	return equal_case(a, pos, b, pos, 0);
730
}
731
732
/*
733
 * Compare the prefix and suffix with the subject, and check that the
734
 * characters in-between are valid.
735
 */
736
static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
737
    const unsigned char *suffix, size_t suffix_len,
738
    const unsigned char *subject, size_t subject_len, unsigned int flags)
739
{
740
	const unsigned char *wildcard_start;
741
	const unsigned char *wildcard_end;
742
	const unsigned char *p;
743
	int allow_multi = 0;
744
	int allow_idna = 0;
745
746
	if (subject_len < prefix_len + suffix_len)
747
		return 0;
748
	if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
749
		return 0;
750
	wildcard_start = subject + prefix_len;
751
	wildcard_end = subject + (subject_len - suffix_len);
752
	if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
753
		return 0;
754
	/*
755
	 * If the wildcard makes up the entire first label, it must match at
756
	 * least one character.
757
	 */
758
	if (prefix_len == 0 && *suffix == '.') {
759
		if (wildcard_start == wildcard_end)
760
			return 0;
761
		allow_idna = 1;
762
		if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
763
			allow_multi = 1;
764
	}
765
	/* IDNA labels cannot match partial wildcards */
766
	if (!allow_idna &&
767
	    subject_len >= 4
768
	    && strncasecmp((char *)subject, "xn--", 4) == 0)
769
		return 0;
770
	/* The wildcard may match a literal '*' */
771
	if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
772
		return 1;
773
	/*
774
	 * Check that the part matched by the wildcard contains only
775
	 * permitted characters and only matches a single label unless
776
	 * allow_multi is set.
777
	 */
778
	for (p = wildcard_start; p != wildcard_end; ++p)
779
		if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
780
		    ('a' <= *p && *p <= 'z') || *p == '-' ||
781
		    (allow_multi && *p == '.')))
782
			return 0;
783
	return 1;
784
}
785
786
#define LABEL_START     (1 << 0)
787
#define LABEL_END       (1 << 1)
788
#define LABEL_HYPHEN    (1 << 2)
789
#define LABEL_IDNA      (1 << 3)
790
791
static const unsigned char *valid_star(const unsigned char *p, size_t len,
792
    unsigned int flags)
793
{
794
	const unsigned char *star = 0;
795
	size_t i;
796
	int state = LABEL_START;
797
	int dots = 0;
798
	for (i = 0; i < len; ++i) {
799
		/*
800
		 * Locate first and only legal wildcard, either at the start
801
		 * or end of a non-IDNA first and not final label.
802
		 */
803
		if (p[i] == '*') {
804
			int atstart = (state & LABEL_START);
805
			int atend = (i == len - 1 || p[i + 1] == '.');
806
			/*
807
			 * At most one wildcard per pattern.
808
			 * No wildcards in IDNA labels.
809
			 * No wildcards after the first label.
810
			 */
811
			if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
812
				return NULL;
813
			/* Only full-label '*.example.com' wildcards? */
814
			if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
815
			    && (!atstart || !atend))
816
				return NULL;
817
			/* No 'foo*bar' wildcards */
818
			if (!atstart && !atend)
819
				return NULL;
820
			star = &p[i];
821
			state &= ~LABEL_START;
822
		} else if ((state & LABEL_START) != 0) {
823
			/*
824
			 * At the start of a label, skip any "xn--" and
825
			 * remain in the LABEL_START state, but set the
826
			 * IDNA label state
827
			 */
828
			if ((state & LABEL_IDNA) == 0 && len - i >= 4
829
			    && strncasecmp((char *)&p[i], "xn--", 4) == 0) {
830
				i += 3;
831
				state |= LABEL_IDNA;
832
				continue;
833
			}
834
			/* Labels must start with a letter or digit */
835
			state &= ~LABEL_START;
836
			if (('a' <= p[i] && p[i] <= 'z')
837
			    || ('A' <= p[i] && p[i] <= 'Z')
838
			    || ('0' <= p[i] && p[i] <= '9'))
839
				continue;
840
			return NULL;
841
		} else if (('a' <= p[i] && p[i] <= 'z')
842
		    || ('A' <= p[i] && p[i] <= 'Z')
843
		    || ('0' <= p[i] && p[i] <= '9')) {
844
			state &= LABEL_IDNA;
845
			continue;
846
		} else if (p[i] == '.') {
847
			if (state & (LABEL_HYPHEN | LABEL_START))
848
				return NULL;
849
			state = LABEL_START;
850
			++dots;
851
		} else if (p[i] == '-') {
852
			/* no domain/subdomain starts with '-' */
853
			if ((state & LABEL_START) != 0)
854
				return NULL;
855
			state |= LABEL_HYPHEN;
856
		} else
857
			return NULL;
858
	}
859
860
	/*
861
	 * The final label must not end in a hyphen or ".", and
862
	 * there must be at least two dots after the star.
863
	 */
864
	if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
865
		return NULL;
866
	return star;
867
}
868
869
/* Compare using wildcards. */
870
static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
871
    const unsigned char *subject, size_t subject_len, unsigned int flags)
872
{
873
	const unsigned char *star = NULL;
874
875
	/*
876
	 * Subject names starting with '.' can only match a wildcard pattern
877
	 * via a subject sub-domain pattern suffix match.
878
	 */
879
	if (!(subject_len > 1 && subject[0] == '.'))
880
		star = valid_star(pattern, pattern_len, flags);
881
	if (star == NULL)
882
		return equal_nocase(pattern, pattern_len,
883
		    subject, subject_len, flags);
884
	return wildcard_match(pattern, star - pattern,
885
	    star + 1, (pattern + pattern_len) - star - 1,
886
	    subject, subject_len, flags);
887
}
888
889
/*
890
 * Compare an ASN1_STRING to a supplied string. If they match return 1. If
891
 * cmp_type > 0 only compare if string matches the type, otherwise convert it
892
 * to UTF8.
893
 */
894
895
static int
896
do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
897
    unsigned int flags, const char *b, size_t blen, char **peername)
898
{
899
	int rv = 0;
900
901
	if (!a->data || !a->length)
902
		return 0;
903
	if (cmp_type > 0) {
904
		if (cmp_type != a->type)
905
			return 0;
906
		if (cmp_type == V_ASN1_IA5STRING)
907
			rv = equal(a->data, a->length, (unsigned char *)b,
908
			    blen, flags);
909
		else if (a->length == (int)blen && !memcmp(a->data, b, blen))
910
			rv = 1;
911
		if (rv > 0 && peername &&
912
		    (*peername = strndup((char *)a->data, a->length)) == NULL)
913
			rv = -1;
914
	} else {
915
		int astrlen;
916
		unsigned char *astr;
917
		astrlen = ASN1_STRING_to_UTF8(&astr, a);
918
		if (astrlen < 0)
919
			return -1;
920
		rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
921
		if (rv > 0 && peername &&
922
		    (*peername = strndup((char *)astr, astrlen)) == NULL)
923
			rv = -1;
924
		free(astr);
925
	}
926
	return rv;
927
}
928
929
static int do_x509_check(X509 *x, const char *chk, size_t chklen,
930
    unsigned int flags, int check_type, char **peername)
931
{
932
	GENERAL_NAMES *gens = NULL;
933
	X509_NAME *name = NULL;
934
	size_t i;
935
	int j;
936
	int cnid = NID_undef;
937
	int alt_type;
938
	int san_present = 0;
939
	int rv = 0;
940
	equal_fn equal;
941
942
	/* See below, this flag is internal-only */
943
	flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
944
	if (check_type == GEN_EMAIL) {
945
		cnid = NID_pkcs9_emailAddress;
946
		alt_type = V_ASN1_IA5STRING;
947
		equal = equal_email;
948
	} else if (check_type == GEN_DNS) {
949
		cnid = NID_commonName;
950
		/* Implicit client-side DNS sub-domain pattern */
951
		if (chklen > 1 && chk[0] == '.')
952
			flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
953
		alt_type = V_ASN1_IA5STRING;
954
		if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
955
			equal = equal_nocase;
956
		else
957
			equal = equal_wildcard;
958
	} else {
959
		alt_type = V_ASN1_OCTET_STRING;
960
		equal = equal_case;
961
	}
962
963
	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
964
	if (gens != NULL) {
965
		for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
966
			GENERAL_NAME *gen;
967
			ASN1_STRING *cstr;
968
			gen = sk_GENERAL_NAME_value(gens, i);
969
			if (gen->type != check_type)
970
				continue;
971
			san_present = 1;
972
			if (check_type == GEN_EMAIL)
973
				cstr = gen->d.rfc822Name;
974
			else if (check_type == GEN_DNS)
975
				cstr = gen->d.dNSName;
976
			else
977
				cstr = gen->d.iPAddress;
978
			/* Positive on success, negative on error! */
979
			if ((rv = do_check_string(cstr, alt_type, equal, flags,
980
			    chk, chklen, peername)) != 0)
981
				break;
982
		}
983
		GENERAL_NAMES_free(gens);
984
		if (rv != 0)
985
			return rv;
986
		if (cnid == NID_undef ||
987
		    (san_present &&
988
		    !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
989
			return 0;
990
	}
991
992
	/* We're done if CN-ID is not pertinent */
993
	if (cnid == NID_undef)
994
		return 0;
995
996
	j = -1;
997
	name = X509_get_subject_name(x);
998
	while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
999
		X509_NAME_ENTRY *ne;
1000
		ASN1_STRING *str;
1001
		if ((ne = X509_NAME_get_entry(name, j)) == NULL)
1002
			return -1;
1003
		if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL)
1004
			return -1;
1005
		/* Positive on success, negative on error! */
1006
		if ((rv = do_check_string(str, -1, equal, flags,
1007
			 chk, chklen, peername)) != 0)
1008
			return rv;
1009
	}
1010
	return 0;
1011
}
1012
1013
int X509_check_host(X509 *x, const char *chk, size_t chklen,
1014
    unsigned int flags, char **peername)
1015
{
1016
	if (chk == NULL)
1017
		return -2;
1018
	if (memchr(chk, '\0', chklen))
1019
		return -2;
1020
	return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
1021
}
1022
1023
int X509_check_email(X509 *x, const char *chk, size_t chklen,
1024
    unsigned int flags)
1025
{
1026
	if (chk == NULL)
1027
		return -2;
1028
	if (memchr(chk, '\0', chklen))
1029
		return -2;
1030
	return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
1031
}
1032
1033
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
1034
    unsigned int flags)
1035
{
1036
	if (chk == NULL)
1037
		return -2;
1038
	return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
1039
}
1040
1041
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
1042
{
1043
	unsigned char ipout[16];
1044
	size_t iplen;
1045
1046
	if (ipasc == NULL)
1047
		return -2;
1048
	iplen = (size_t)a2i_ipadd(ipout, ipasc);
1049
	if (iplen == 0)
1050
		return -2;
1051
	return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
1052
}
1053
1054
/* Convert IP addresses both IPv4 and IPv6 into an
1055
 * OCTET STRING compatible with RFC3280.
1056
 */
1057
1058
ASN1_OCTET_STRING *
1059
a2i_IPADDRESS(const char *ipasc)
1060
{
1061
	unsigned char ipout[16];
1062
	ASN1_OCTET_STRING *ret;
1063
	int iplen;
1064
1065
	/* If string contains a ':' assume IPv6 */
1066
1067
	iplen = a2i_ipadd(ipout, ipasc);
1068
1069
	if (!iplen)
1070
		return NULL;
1071
1072
	ret = ASN1_OCTET_STRING_new();
1073
	if (!ret)
1074
		return NULL;
1075
	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
1076
		ASN1_OCTET_STRING_free(ret);
1077
		return NULL;
1078
	}
1079
	return ret;
1080
}
1081
1082
ASN1_OCTET_STRING *
1083
a2i_IPADDRESS_NC(const char *ipasc)
1084
{
1085
	ASN1_OCTET_STRING *ret = NULL;
1086
	unsigned char ipout[32];
1087
	char *iptmp = NULL, *p;
1088
	int iplen1, iplen2;
1089
1090
	p = strchr(ipasc, '/');
1091
	if (!p)
1092
		return NULL;
1093
	iptmp = strdup(ipasc);
1094
	if (!iptmp)
1095
		return NULL;
1096
	p = iptmp + (p - ipasc);
1097
	*p++ = 0;
1098
1099
	iplen1 = a2i_ipadd(ipout, iptmp);
1100
1101
	if (!iplen1)
1102
		goto err;
1103
1104
	iplen2 = a2i_ipadd(ipout + iplen1, p);
1105
1106
	free(iptmp);
1107
	iptmp = NULL;
1108
1109
	if (!iplen2 || (iplen1 != iplen2))
1110
		goto err;
1111
1112
	ret = ASN1_OCTET_STRING_new();
1113
	if (!ret)
1114
		goto err;
1115
	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1116
		goto err;
1117
1118
	return ret;
1119
1120
err:
1121
	free(iptmp);
1122
	if (ret)
1123
		ASN1_OCTET_STRING_free(ret);
1124
	return NULL;
1125
}
1126
1127
1128
int
1129
a2i_ipadd(unsigned char *ipout, const char *ipasc)
1130
{
1131
	/* If string contains a ':' assume IPv6 */
1132
1133
	if (strchr(ipasc, ':')) {
1134
		if (!ipv6_from_asc(ipout, ipasc))
1135
			return 0;
1136
		return 16;
1137
	} else {
1138
		if (!ipv4_from_asc(ipout, ipasc))
1139
			return 0;
1140
		return 4;
1141
	}
1142
}
1143
1144
static int
1145
ipv4_from_asc(unsigned char *v4, const char *in)
1146
{
1147
	int a0, a1, a2, a3;
1148
	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1149
		return 0;
1150
	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) ||
1151
	    (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1152
		return 0;
1153
	v4[0] = a0;
1154
	v4[1] = a1;
1155
	v4[2] = a2;
1156
	v4[3] = a3;
1157
	return 1;
1158
}
1159
1160
typedef struct {
1161
	/* Temporary store for IPV6 output */
1162
	unsigned char tmp[16];
1163
	/* Total number of bytes in tmp */
1164
	int total;
1165
	/* The position of a zero (corresponding to '::') */
1166
	int zero_pos;
1167
	/* Number of zeroes */
1168
	int zero_cnt;
1169
} IPV6_STAT;
1170
1171
1172
static int
1173
ipv6_from_asc(unsigned char *v6, const char *in)
1174
{
1175
	IPV6_STAT v6stat;
1176
1177
	v6stat.total = 0;
1178
	v6stat.zero_pos = -1;
1179
	v6stat.zero_cnt = 0;
1180
1181
	/* Treat the IPv6 representation as a list of values
1182
	 * separated by ':'. The presence of a '::' will parse
1183
 	 * as one, two or three zero length elements.
1184
	 */
1185
	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1186
		return 0;
1187
1188
	/* Now for some sanity checks */
1189
1190
	if (v6stat.zero_pos == -1) {
1191
		/* If no '::' must have exactly 16 bytes */
1192
		if (v6stat.total != 16)
1193
			return 0;
1194
	} else {
1195
		/* If '::' must have less than 16 bytes */
1196
		if (v6stat.total == 16)
1197
			return 0;
1198
		/* More than three zeroes is an error */
1199
		if (v6stat.zero_cnt > 3)
1200
			return 0;
1201
		/* Can only have three zeroes if nothing else present */
1202
		else if (v6stat.zero_cnt == 3) {
1203
			if (v6stat.total > 0)
1204
				return 0;
1205
		}
1206
		/* Can only have two zeroes if at start or end */
1207
		else if (v6stat.zero_cnt == 2) {
1208
			if ((v6stat.zero_pos != 0) &&
1209
			    (v6stat.zero_pos != v6stat.total))
1210
				return 0;
1211
		} else
1212
			/* Can only have one zero if *not* start or end */
1213
		{
1214
			if ((v6stat.zero_pos == 0) ||
1215
			    (v6stat.zero_pos == v6stat.total))
1216
				return 0;
1217
		}
1218
	}
1219
1220
	/* Format result */
1221
1222
	if (v6stat.zero_pos >= 0) {
1223
		/* Copy initial part */
1224
		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1225
		/* Zero middle */
1226
		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1227
		/* Copy final part */
1228
		if (v6stat.total != v6stat.zero_pos)
1229
			memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1230
			    v6stat.tmp + v6stat.zero_pos,
1231
			    v6stat.total - v6stat.zero_pos);
1232
	} else
1233
		memcpy(v6, v6stat.tmp, 16);
1234
1235
	return 1;
1236
}
1237
1238
static int
1239
ipv6_cb(const char *elem, int len, void *usr)
1240
{
1241
	IPV6_STAT *s = usr;
1242
1243
	/* Error if 16 bytes written */
1244
	if (s->total == 16)
1245
		return 0;
1246
	if (len == 0) {
1247
		/* Zero length element, corresponds to '::' */
1248
		if (s->zero_pos == -1)
1249
			s->zero_pos = s->total;
1250
		/* If we've already got a :: its an error */
1251
		else if (s->zero_pos != s->total)
1252
			return 0;
1253
		s->zero_cnt++;
1254
	} else {
1255
		/* If more than 4 characters could be final a.b.c.d form */
1256
		if (len > 4) {
1257
			/* Need at least 4 bytes left */
1258
			if (s->total > 12)
1259
				return 0;
1260
			/* Must be end of string */
1261
			if (elem[len])
1262
				return 0;
1263
			if (!ipv4_from_asc(s->tmp + s->total, elem))
1264
				return 0;
1265
			s->total += 4;
1266
		} else {
1267
			if (!ipv6_hex(s->tmp + s->total, elem, len))
1268
				return 0;
1269
			s->total += 2;
1270
		}
1271
	}
1272
	return 1;
1273
}
1274
1275
/* Convert a string of up to 4 hex digits into the corresponding
1276
 * IPv6 form.
1277
 */
1278
1279
static int
1280
ipv6_hex(unsigned char *out, const char *in, int inlen)
1281
{
1282
	unsigned char c;
1283
	unsigned int num = 0;
1284
1285
	if (inlen > 4)
1286
		return 0;
1287
	while (inlen--) {
1288
		c = *in++;
1289
		num <<= 4;
1290
		if ((c >= '0') && (c <= '9'))
1291
			num |= c - '0';
1292
		else if ((c >= 'A') && (c <= 'F'))
1293
			num |= c - 'A' + 10;
1294
		else if ((c >= 'a') && (c <= 'f'))
1295
			num |=  c - 'a' + 10;
1296
		else
1297
			return 0;
1298
	}
1299
	out[0] = num >> 8;
1300
	out[1] = num & 0xff;
1301
	return 1;
1302
}
1303
1304
int
1305
X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
1306
    unsigned long chtype)
1307
{
1308
	CONF_VALUE *v;
1309
	int i, mval;
1310
	char *p, *type;
1311
1312
	if (!nm)
1313
		return 0;
1314
1315
	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1316
		v = sk_CONF_VALUE_value(dn_sk, i);
1317
		type = v->name;
1318
		/* Skip past any leading X. X: X, etc to allow for
1319
		 * multiple instances
1320
		 */
1321
		for (p = type; *p; p++)
1322
			if ((*p == ':') || (*p == ',') || (*p == '.')) {
1323
				p++;
1324
				if (*p)
1325
					type = p;
1326
				break;
1327
			}
1328
		if (*type == '+') {
1329
			mval = -1;
1330
			type++;
1331
		} else
1332
			mval = 0;
1333
		if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1334
		    (unsigned char *) v->value, -1, -1, mval))
1335
			return 0;
1336
	}
1337
	return 1;
1338
}