]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509v3/v3_utl.c
Copyright consolidation 07/10
[thirdparty/openssl.git] / crypto / x509v3 / v3_utl.c
CommitLineData
0f113f3e
MC
1/*
2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
4e5d3a7f 3 * project.
9aeaf1b4
DSH
4 */
5/* ====================================================================
4e5d3a7f 6 * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved.
9aeaf1b4
DSH
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
0f113f3e 13 * notice, this list of conditions and the following disclaimer.
9aeaf1b4
DSH
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
e527ba09 60#include <stdio.h>
9aeaf1b4 61#include <ctype.h>
b39fc560 62#include "internal/cryptlib.h"
ec577822
BM
63#include <openssl/conf.h>
64#include <openssl/x509v3.h>
124055a9 65#include "internal/x509_int.h"
0f814687 66#include <openssl/bn.h>
9021a5df 67#include "ext_dat.h"
9aeaf1b4 68
9aeaf1b4 69static char *strip_spaces(char *name);
0f113f3e
MC
70static int sk_strcmp(const char *const *a, const char *const *b);
71static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
72 GENERAL_NAMES *gens);
c869da88
DSH
73static void str_free(OPENSSL_STRING str);
74static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
9aeaf1b4 75
4e5d3a7f
DSH
76static int ipv4_from_asc(unsigned char *v4, const char *in);
77static int ipv6_from_asc(unsigned char *v6, const char *in);
78static int ipv6_cb(const char *elem, int len, void *usr);
79static int ipv6_hex(unsigned char *out, const char *in, int inlen);
80
9aeaf1b4
DSH
81/* Add a CONF_VALUE name value pair to stack */
82
ba404b5e 83int X509V3_add_value(const char *name, const char *value,
0f113f3e 84 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4 85{
0f113f3e
MC
86 CONF_VALUE *vtmp = NULL;
87 char *tname = NULL, *tvalue = NULL;
75ebbd9a 88
7644a9ae 89 if (name && (tname = OPENSSL_strdup(name)) == NULL)
0f113f3e 90 goto err;
7644a9ae 91 if (value && (tvalue = OPENSSL_strdup(value)) == NULL)
0f113f3e 92 goto err;
75ebbd9a 93 if ((vtmp = OPENSSL_malloc(sizeof(*vtmp))) == NULL)
0f113f3e 94 goto err;
75ebbd9a 95 if (*extlist == NULL && (*extlist = sk_CONF_VALUE_new_null()) == NULL)
0f113f3e
MC
96 goto err;
97 vtmp->section = NULL;
98 vtmp->name = tname;
99 vtmp->value = tvalue;
100 if (!sk_CONF_VALUE_push(*extlist, vtmp))
101 goto err;
102 return 1;
103 err:
104 X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE);
b548a1f1
RS
105 OPENSSL_free(vtmp);
106 OPENSSL_free(tname);
107 OPENSSL_free(tvalue);
0f113f3e 108 return 0;
9aeaf1b4
DSH
109}
110
61f5b6f3 111int X509V3_add_value_uchar(const char *name, const unsigned char *value,
0f113f3e
MC
112 STACK_OF(CONF_VALUE) **extlist)
113{
114 return X509V3_add_value(name, (const char *)value, extlist);
115}
61f5b6f3 116
66ab08b1 117/* Free function for STACK_OF(CONF_VALUE) */
9aeaf1b4 118
6b691a5c 119void X509V3_conf_free(CONF_VALUE *conf)
9aeaf1b4 120{
0f113f3e
MC
121 if (!conf)
122 return;
b548a1f1
RS
123 OPENSSL_free(conf->name);
124 OPENSSL_free(conf->value);
125 OPENSSL_free(conf->section);
0f113f3e 126 OPENSSL_free(conf);
9aeaf1b4
DSH
127}
128
ba404b5e 129int X509V3_add_value_bool(const char *name, int asn1_bool,
0f113f3e 130 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4 131{
0f113f3e
MC
132 if (asn1_bool)
133 return X509V3_add_value(name, "TRUE", extlist);
134 return X509V3_add_value(name, "FALSE", extlist);
9aeaf1b4
DSH
135}
136
ba404b5e 137int X509V3_add_value_bool_nf(char *name, int asn1_bool,
0f113f3e 138 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4 139{
0f113f3e
MC
140 if (asn1_bool)
141 return X509V3_add_value(name, "TRUE", extlist);
142 return 1;
9aeaf1b4
DSH
143}
144
6b691a5c 145char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
c74f1eb9 146{
0f113f3e
MC
147 BIGNUM *bntmp = NULL;
148 char *strtmp = NULL;
75ebbd9a 149
0f113f3e
MC
150 if (!a)
151 return NULL;
75ebbd9a
RS
152 if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL
153 || (strtmp = BN_bn2dec(bntmp)) == NULL)
0f113f3e
MC
154 X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
155 BN_free(bntmp);
156 return strtmp;
c74f1eb9
DSH
157}
158
6b691a5c 159char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
0ca5f8b1 160{
0f113f3e
MC
161 BIGNUM *bntmp = NULL;
162 char *strtmp = NULL;
75ebbd9a 163
0f113f3e
MC
164 if (!a)
165 return NULL;
75ebbd9a
RS
166 if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL
167 || (strtmp = BN_bn2dec(bntmp)) == NULL)
0f113f3e
MC
168 X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
169 BN_free(bntmp);
170 return strtmp;
0ca5f8b1
DSH
171}
172
6b691a5c 173ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
28a98809 174{
0f113f3e
MC
175 BIGNUM *bn = NULL;
176 ASN1_INTEGER *aint;
177 int isneg, ishex;
178 int ret;
90945fa3 179 if (value == NULL) {
0f113f3e 180 X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE);
90945fa3 181 return NULL;
0f113f3e
MC
182 }
183 bn = BN_new();
90945fa3
MC
184 if (bn == NULL) {
185 X509V3err(X509V3_F_S2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
186 return NULL;
187 }
0f113f3e
MC
188 if (value[0] == '-') {
189 value++;
190 isneg = 1;
191 } else
192 isneg = 0;
193
194 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
195 value += 2;
196 ishex = 1;
197 } else
198 ishex = 0;
199
200 if (ishex)
201 ret = BN_hex2bn(&bn, value);
202 else
203 ret = BN_dec2bn(&bn, value);
204
205 if (!ret || value[ret]) {
206 BN_free(bn);
207 X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
90945fa3 208 return NULL;
0f113f3e
MC
209 }
210
211 if (isneg && BN_is_zero(bn))
212 isneg = 0;
213
214 aint = BN_to_ASN1_INTEGER(bn, NULL);
215 BN_free(bn);
216 if (!aint) {
217 X509V3err(X509V3_F_S2I_ASN1_INTEGER,
218 X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
90945fa3 219 return NULL;
0f113f3e
MC
220 }
221 if (isneg)
222 aint->type |= V_ASN1_NEG;
223 return aint;
28a98809
DSH
224}
225
6b691a5c 226int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
0f113f3e 227 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4 228{
0f113f3e
MC
229 char *strtmp;
230 int ret;
75ebbd9a 231
0f113f3e
MC
232 if (!aint)
233 return 1;
75ebbd9a 234 if ((strtmp = i2s_ASN1_INTEGER(NULL, aint)) == NULL)
0f113f3e
MC
235 return 0;
236 ret = X509V3_add_value(name, strtmp, extlist);
237 OPENSSL_free(strtmp);
238 return ret;
9aeaf1b4
DSH
239}
240
6b691a5c 241int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
9aeaf1b4 242{
0f113f3e 243 char *btmp;
75ebbd9a
RS
244
245 if ((btmp = value->value) == NULL)
0f113f3e 246 goto err;
86885c28
RS
247 if (strcmp(btmp, "TRUE") == 0
248 || strcmp(btmp, "true") == 0
249 || strcmp(btmp, "Y") == 0
250 || strcmp(btmp, "y") == 0
251 || strcmp(btmp, "YES") == 0
252 || strcmp(btmp, "yes") == 0) {
0f113f3e
MC
253 *asn1_bool = 0xff;
254 return 1;
86885c28
RS
255 }
256 if (strcmp(btmp, "FALSE") == 0
257 || strcmp(btmp, "false") == 0
258 || strcmp(btmp, "N") == 0
259 || strcmp(btmp, "n") == 0
260 || strcmp(btmp, "NO") == 0
261 || strcmp(btmp, "no") == 0) {
0f113f3e
MC
262 *asn1_bool = 0;
263 return 1;
264 }
265 err:
266 X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
267 X509V3_R_INVALID_BOOLEAN_STRING);
268 X509V3_conf_err(value);
269 return 0;
9aeaf1b4
DSH
270}
271
6b691a5c 272int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
9aeaf1b4 273{
0f113f3e 274 ASN1_INTEGER *itmp;
75ebbd9a
RS
275
276 if ((itmp = s2i_ASN1_INTEGER(NULL, value->value)) == NULL) {
0f113f3e
MC
277 X509V3_conf_err(value);
278 return 0;
279 }
280 *aint = itmp;
281 return 1;
9aeaf1b4
DSH
282}
283
0f113f3e
MC
284#define HDR_NAME 1
285#define HDR_VALUE 2
9aeaf1b4 286
0f113f3e
MC
287/*
288 * #define DEBUG
289 */
9aeaf1b4 290
535d79da 291STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
9aeaf1b4 292{
0f113f3e
MC
293 char *p, *q, c;
294 char *ntmp, *vtmp;
295 STACK_OF(CONF_VALUE) *values = NULL;
296 char *linebuf;
297 int state;
298 /* We are going to modify the line so copy it first */
7644a9ae 299 linebuf = OPENSSL_strdup(line);
344c271e
KC
300 if (linebuf == NULL) {
301 X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE);
302 goto err;
303 }
0f113f3e
MC
304 state = HDR_NAME;
305 ntmp = NULL;
306 /* Go through all characters */
307 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
308 p++) {
309
310 switch (state) {
311 case HDR_NAME:
312 if (c == ':') {
313 state = HDR_VALUE;
314 *p = 0;
315 ntmp = strip_spaces(q);
316 if (!ntmp) {
317 X509V3err(X509V3_F_X509V3_PARSE_LIST,
318 X509V3_R_INVALID_NULL_NAME);
319 goto err;
320 }
321 q = p + 1;
322 } else if (c == ',') {
323 *p = 0;
324 ntmp = strip_spaces(q);
325 q = p + 1;
0f113f3e
MC
326 if (!ntmp) {
327 X509V3err(X509V3_F_X509V3_PARSE_LIST,
328 X509V3_R_INVALID_NULL_NAME);
329 goto err;
330 }
331 X509V3_add_value(ntmp, NULL, &values);
332 }
333 break;
334
335 case HDR_VALUE:
336 if (c == ',') {
337 state = HDR_NAME;
338 *p = 0;
339 vtmp = strip_spaces(q);
0f113f3e
MC
340 if (!vtmp) {
341 X509V3err(X509V3_F_X509V3_PARSE_LIST,
342 X509V3_R_INVALID_NULL_VALUE);
343 goto err;
344 }
345 X509V3_add_value(ntmp, vtmp, &values);
346 ntmp = NULL;
347 q = p + 1;
348 }
349
350 }
351 }
352
353 if (state == HDR_VALUE) {
354 vtmp = strip_spaces(q);
0f113f3e
MC
355 if (!vtmp) {
356 X509V3err(X509V3_F_X509V3_PARSE_LIST,
357 X509V3_R_INVALID_NULL_VALUE);
358 goto err;
359 }
360 X509V3_add_value(ntmp, vtmp, &values);
361 } else {
362 ntmp = strip_spaces(q);
0f113f3e
MC
363 if (!ntmp) {
364 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
365 goto err;
366 }
367 X509V3_add_value(ntmp, NULL, &values);
368 }
369 OPENSSL_free(linebuf);
370 return values;
371
372 err:
373 OPENSSL_free(linebuf);
374 sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
375 return NULL;
9aeaf1b4
DSH
376
377}
378
379/* Delete leading and trailing spaces from a string */
6b691a5c 380static char *strip_spaces(char *name)
9aeaf1b4 381{
0f113f3e
MC
382 char *p, *q;
383 /* Skip over leading spaces */
384 p = name;
385 while (*p && isspace((unsigned char)*p))
386 p++;
387 if (!*p)
388 return NULL;
389 q = p + strlen(p) - 1;
390 while ((q != p) && isspace((unsigned char)*q))
391 q--;
392 if (p != q)
393 q[1] = 0;
394 if (!*p)
395 return NULL;
396 return p;
9aeaf1b4 397}
175b0942 398
d08d8da4 399
0f113f3e
MC
400/*
401 * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
d08d8da4
DSH
402 */
403
6b691a5c 404int name_cmp(const char *name, const char *cmp)
d08d8da4 405{
0f113f3e
MC
406 int len, ret;
407 char c;
408 len = strlen(cmp);
409 if ((ret = strncmp(name, cmp, len)))
410 return ret;
411 c = name[len];
412 if (!c || (c == '.'))
413 return 0;
414 return 1;
d08d8da4 415}
a91dedca 416
0f113f3e 417static int sk_strcmp(const char *const *a, const char *const *b)
a91dedca 418{
0f113f3e 419 return strcmp(*a, *b);
a91dedca
DSH
420}
421
c869da88 422STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
a91dedca 423{
0f113f3e
MC
424 GENERAL_NAMES *gens;
425 STACK_OF(OPENSSL_STRING) *ret;
5ce278a7 426
0f113f3e
MC
427 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
428 ret = get_email(X509_get_subject_name(x), gens);
429 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
430 return ret;
a91dedca
DSH
431}
432
c869da88 433STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
67c8e7f4 434{
0f113f3e
MC
435 AUTHORITY_INFO_ACCESS *info;
436 STACK_OF(OPENSSL_STRING) *ret = NULL;
437 int i;
438
439 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
440 if (!info)
441 return NULL;
442 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
443 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
444 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
445 if (ad->location->type == GEN_URI) {
446 if (!append_ia5
447 (&ret, ad->location->d.uniformResourceIdentifier))
448 break;
449 }
450 }
451 }
452 AUTHORITY_INFO_ACCESS_free(info);
453 return ret;
67c8e7f4
DSH
454}
455
c869da88 456STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
a91dedca 457{
0f113f3e
MC
458 GENERAL_NAMES *gens;
459 STACK_OF(X509_EXTENSION) *exts;
460 STACK_OF(OPENSSL_STRING) *ret;
461
462 exts = X509_REQ_get_extensions(x);
463 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
464 ret = get_email(X509_REQ_get_subject_name(x), gens);
465 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
466 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
467 return ret;
a91dedca
DSH
468}
469
0f113f3e
MC
470static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
471 GENERAL_NAMES *gens)
a91dedca 472{
0f113f3e
MC
473 STACK_OF(OPENSSL_STRING) *ret = NULL;
474 X509_NAME_ENTRY *ne;
475 ASN1_IA5STRING *email;
476 GENERAL_NAME *gen;
477 int i;
478 /* Now add any email address(es) to STACK */
479 i = -1;
480 /* First supplied X509_NAME */
481 while ((i = X509_NAME_get_index_by_NID(name,
482 NID_pkcs9_emailAddress, i)) >= 0) {
483 ne = X509_NAME_get_entry(name, i);
484 email = X509_NAME_ENTRY_get_data(ne);
485 if (!append_ia5(&ret, email))
486 return NULL;
487 }
488 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
489 gen = sk_GENERAL_NAME_value(gens, i);
490 if (gen->type != GEN_EMAIL)
491 continue;
492 if (!append_ia5(&ret, gen->d.ia5))
493 return NULL;
494 }
495 return ret;
a91dedca
DSH
496}
497
c869da88 498static void str_free(OPENSSL_STRING str)
a91dedca 499{
0f113f3e 500 OPENSSL_free(str);
a91dedca
DSH
501}
502
c869da88 503static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
a91dedca 504{
0f113f3e
MC
505 char *emtmp;
506 /* First some sanity checks */
507 if (email->type != V_ASN1_IA5STRING)
508 return 1;
509 if (!email->data || !email->length)
510 return 1;
90945fa3 511 if (*sk == NULL)
0f113f3e 512 *sk = sk_OPENSSL_STRING_new(sk_strcmp);
90945fa3 513 if (*sk == NULL)
0f113f3e
MC
514 return 0;
515 /* Don't add duplicates */
516 if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
517 return 1;
7644a9ae 518 emtmp = OPENSSL_strdup((char *)email->data);
90945fa3 519 if (emtmp == NULL || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
0f113f3e
MC
520 X509_email_free(*sk);
521 *sk = NULL;
522 return 0;
523 }
524 return 1;
a91dedca
DSH
525}
526
c869da88 527void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
a91dedca 528{
0f113f3e 529 sk_OPENSSL_STRING_pop_free(sk, str_free);
a91dedca 530}
4e5d3a7f 531
0f113f3e
MC
532typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
533 const unsigned char *subject, size_t subject_len,
534 unsigned int flags);
d88926f1 535
a09e4d24
VD
536/* Skip pattern prefix to match "wildcard" subject */
537static void skip_prefix(const unsigned char **p, size_t *plen,
a773b52a 538 size_t subject_len,
0f113f3e
MC
539 unsigned int flags)
540{
541 const unsigned char *pattern = *p;
542 size_t pattern_len = *plen;
543
544 /*
545 * If subject starts with a leading '.' followed by more octets, and
546 * pattern is longer, compare just an equal-length suffix with the
547 * full subject (starting at the '.'), provided the prefix contains
548 * no NULs.
549 */
550 if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
551 return;
552
553 while (pattern_len > subject_len && *pattern) {
554 if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
555 *pattern == '.')
556 break;
557 ++pattern;
558 --pattern_len;
559 }
560
561 /* Skip if entire prefix acceptable */
562 if (pattern_len == subject_len) {
563 *p = pattern;
564 *plen = pattern_len;
565 }
566}
a09e4d24 567
d88926f1
DSH
568/* Compare while ASCII ignoring case. */
569static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
0f113f3e
MC
570 const unsigned char *subject, size_t subject_len,
571 unsigned int flags)
572{
a773b52a 573 skip_prefix(&pattern, &pattern_len, subject_len, flags);
0f113f3e
MC
574 if (pattern_len != subject_len)
575 return 0;
576 while (pattern_len) {
577 unsigned char l = *pattern;
578 unsigned char r = *subject;
579 /* The pattern must not contain NUL characters. */
580 if (l == 0)
581 return 0;
582 if (l != r) {
583 if ('A' <= l && l <= 'Z')
584 l = (l - 'A') + 'a';
585 if ('A' <= r && r <= 'Z')
586 r = (r - 'A') + 'a';
587 if (l != r)
588 return 0;
589 }
590 ++pattern;
591 ++subject;
592 --pattern_len;
593 }
594 return 1;
595}
d88926f1
DSH
596
597/* Compare using memcmp. */
598static int equal_case(const unsigned char *pattern, size_t pattern_len,
0f113f3e
MC
599 const unsigned char *subject, size_t subject_len,
600 unsigned int flags)
d88926f1 601{
a773b52a 602 skip_prefix(&pattern, &pattern_len, subject_len, flags);
0f113f3e
MC
603 if (pattern_len != subject_len)
604 return 0;
605 return !memcmp(pattern, subject, pattern_len);
d88926f1
DSH
606}
607
0f113f3e
MC
608/*
609 * RFC 5280, section 7.5, requires that only the domain is compared in a
610 * case-insensitive manner.
611 */
d88926f1 612static int equal_email(const unsigned char *a, size_t a_len,
0f113f3e
MC
613 const unsigned char *b, size_t b_len,
614 unsigned int unused_flags)
615{
616 size_t i = a_len;
617 if (a_len != b_len)
618 return 0;
619 /*
620 * We search backwards for the '@' character, so that we do not have to
621 * deal with quoted local-parts. The domain part is compared in a
622 * case-insensitive manner.
623 */
624 while (i > 0) {
625 --i;
626 if (a[i] == '@' || b[i] == '@') {
627 if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0))
628 return 0;
629 break;
630 }
631 }
632 if (i == 0)
633 i = a_len;
634 return equal_case(a, i, b, i, 0);
635}
636
637/*
638 * Compare the prefix and suffix with the subject, and check that the
639 * characters in-between are valid.
640 */
d88926f1 641static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
0f113f3e
MC
642 const unsigned char *suffix, size_t suffix_len,
643 const unsigned char *subject, size_t subject_len,
644 unsigned int flags)
645{
646 const unsigned char *wildcard_start;
647 const unsigned char *wildcard_end;
648 const unsigned char *p;
649 int allow_multi = 0;
650 int allow_idna = 0;
651
652 if (subject_len < prefix_len + suffix_len)
653 return 0;
654 if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
655 return 0;
656 wildcard_start = subject + prefix_len;
657 wildcard_end = subject + (subject_len - suffix_len);
658 if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
659 return 0;
660 /*
661 * If the wildcard makes up the entire first label, it must match at
662 * least one character.
663 */
664 if (prefix_len == 0 && *suffix == '.') {
665 if (wildcard_start == wildcard_end)
666 return 0;
667 allow_idna = 1;
668 if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
669 allow_multi = 1;
670 }
671 /* IDNA labels cannot match partial wildcards */
672 if (!allow_idna &&
673 subject_len >= 4 && strncasecmp((char *)subject, "xn--", 4) == 0)
674 return 0;
675 /* The wildcard may match a literal '*' */
676 if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
677 return 1;
678 /*
679 * Check that the part matched by the wildcard contains only
680 * permitted characters and only matches a single label unless
681 * allow_multi is set.
682 */
683 for (p = wildcard_start; p != wildcard_end; ++p)
684 if (!(('0' <= *p && *p <= '9') ||
685 ('A' <= *p && *p <= 'Z') ||
686 ('a' <= *p && *p <= 'z') ||
687 *p == '-' || (allow_multi && *p == '.')))
688 return 0;
689 return 1;
690}
691
692#define LABEL_START (1 << 0)
693#define LABEL_END (1 << 1)
694#define LABEL_HYPHEN (1 << 2)
695#define LABEL_IDNA (1 << 3)
d88926f1 696
397a8e74 697static const unsigned char *valid_star(const unsigned char *p, size_t len,
0f113f3e
MC
698 unsigned int flags)
699{
700 const unsigned char *star = 0;
701 size_t i;
702 int state = LABEL_START;
703 int dots = 0;
704 for (i = 0; i < len; ++i) {
705 /*
706 * Locate first and only legal wildcard, either at the start
707 * or end of a non-IDNA first and not final label.
708 */
709 if (p[i] == '*') {
710 int atstart = (state & LABEL_START);
9a3bf973 711 int atend = (i == len - 1 || p[i + 1] == '.');
35a1cc90
MC
712 /*-
713 * At most one wildcard per pattern.
714 * No wildcards in IDNA labels.
715 * No wildcards after the first label.
716 */
0f113f3e
MC
717 if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
718 return NULL;
719 /* Only full-label '*.example.com' wildcards? */
720 if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
721 && (!atstart || !atend))
722 return NULL;
723 /* No 'foo*bar' wildcards */
724 if (!atstart && !atend)
725 return NULL;
726 star = &p[i];
727 state &= ~LABEL_START;
728 } else if (('a' <= p[i] && p[i] <= 'z')
729 || ('A' <= p[i] && p[i] <= 'Z')
730 || ('0' <= p[i] && p[i] <= '9')) {
731 if ((state & LABEL_START) != 0
732 && len - i >= 4 && strncasecmp((char *)&p[i], "xn--", 4) == 0)
733 state |= LABEL_IDNA;
734 state &= ~(LABEL_HYPHEN | LABEL_START);
735 } else if (p[i] == '.') {
736 if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
737 return NULL;
738 state = LABEL_START;
739 ++dots;
740 } else if (p[i] == '-') {
9f9a3926
ZL
741 /* no domain/subdomain starts with '-' */
742 if ((state & LABEL_START) != 0)
0f113f3e
MC
743 return NULL;
744 state |= LABEL_HYPHEN;
745 } else
746 return NULL;
747 }
748
749 /*
750 * The final label must not end in a hyphen or ".", and
751 * there must be at least two dots after the star.
752 */
753 if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
754 return NULL;
755 return star;
756}
d88926f1
DSH
757
758/* Compare using wildcards. */
759static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
0f113f3e
MC
760 const unsigned char *subject, size_t subject_len,
761 unsigned int flags)
762{
763 const unsigned char *star = NULL;
764
765 /*
766 * Subject names starting with '.' can only match a wildcard pattern
767 * via a subject sub-domain pattern suffix match.
768 */
769 if (!(subject_len > 1 && subject[0] == '.'))
770 star = valid_star(pattern, pattern_len, flags);
771 if (star == NULL)
772 return equal_nocase(pattern, pattern_len,
773 subject, subject_len, flags);
774 return wildcard_match(pattern, star - pattern,
775 star + 1, (pattern + pattern_len) - star - 1,
776 subject, subject_len, flags);
777}
778
779/*
780 * Compare an ASN1_STRING to a supplied string. If they match return 1. If
781 * cmp_type > 0 only compare if string matches the type, otherwise convert it
782 * to UTF8.
a70da5b3
DSH
783 */
784
d88926f1 785static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
0f113f3e
MC
786 unsigned int flags, const char *b, size_t blen,
787 char **peername)
788{
789 int rv = 0;
790
791 if (!a->data || !a->length)
792 return 0;
793 if (cmp_type > 0) {
794 if (cmp_type != a->type)
795 return 0;
796 if (cmp_type == V_ASN1_IA5STRING)
797 rv = equal(a->data, a->length, (unsigned char *)b, blen, flags);
798 else if (a->length == (int)blen && !memcmp(a->data, b, blen))
799 rv = 1;
800 if (rv > 0 && peername)
7644a9ae 801 *peername = OPENSSL_strndup((char *)a->data, a->length);
0f113f3e
MC
802 } else {
803 int astrlen;
804 unsigned char *astr;
805 astrlen = ASN1_STRING_to_UTF8(&astr, a);
0923e7df
EK
806 if (astrlen < 0) {
807 /*
808 * -1 could be an internal malloc failure or a decoding error from
809 * malformed input; we can't distinguish.
810 */
0f113f3e 811 return -1;
0923e7df 812 }
0f113f3e
MC
813 rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
814 if (rv > 0 && peername)
7644a9ae 815 *peername = OPENSSL_strndup((char *)astr, astrlen);
0f113f3e
MC
816 OPENSSL_free(astr);
817 }
818 return rv;
819}
a70da5b3 820
297c67fc 821static int do_x509_check(X509 *x, const char *chk, size_t chklen,
0f113f3e
MC
822 unsigned int flags, int check_type, char **peername)
823{
824 GENERAL_NAMES *gens = NULL;
825 X509_NAME *name = NULL;
826 int i;
fffc2fae 827 int cnid = NID_undef;
0f113f3e
MC
828 int alt_type;
829 int san_present = 0;
830 int rv = 0;
831 equal_fn equal;
832
833 /* See below, this flag is internal-only */
834 flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
835 if (check_type == GEN_EMAIL) {
836 cnid = NID_pkcs9_emailAddress;
837 alt_type = V_ASN1_IA5STRING;
838 equal = equal_email;
839 } else if (check_type == GEN_DNS) {
840 cnid = NID_commonName;
841 /* Implicit client-side DNS sub-domain pattern */
842 if (chklen > 1 && chk[0] == '.')
843 flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
844 alt_type = V_ASN1_IA5STRING;
845 if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
846 equal = equal_nocase;
847 else
848 equal = equal_wildcard;
849 } else {
0f113f3e
MC
850 alt_type = V_ASN1_OCTET_STRING;
851 equal = equal_case;
852 }
853
854 if (chklen == 0)
855 chklen = strlen(chk);
856
857 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
858 if (gens) {
859 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
860 GENERAL_NAME *gen;
861 ASN1_STRING *cstr;
862 gen = sk_GENERAL_NAME_value(gens, i);
863 if (gen->type != check_type)
864 continue;
865 san_present = 1;
866 if (check_type == GEN_EMAIL)
867 cstr = gen->d.rfc822Name;
868 else if (check_type == GEN_DNS)
869 cstr = gen->d.dNSName;
870 else
871 cstr = gen->d.iPAddress;
872 /* Positive on success, negative on error! */
873 if ((rv = do_check_string(cstr, alt_type, equal, flags,
874 chk, chklen, peername)) != 0)
875 break;
876 }
877 GENERAL_NAMES_free(gens);
878 if (rv != 0)
879 return rv;
dd60efea 880 if (san_present && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))
0f113f3e
MC
881 return 0;
882 }
fffc2fae
VD
883
884 /* We're done if CN-ID is not pertinent */
dd60efea 885 if (cnid == NID_undef || (flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT))
fffc2fae
VD
886 return 0;
887
0f113f3e
MC
888 i = -1;
889 name = X509_get_subject_name(x);
890 while ((i = X509_NAME_get_index_by_NID(name, cnid, i)) >= 0) {
891 X509_NAME_ENTRY *ne;
892 ASN1_STRING *str;
893 ne = X509_NAME_get_entry(name, i);
894 str = X509_NAME_ENTRY_get_data(ne);
895 /* Positive on success, negative on error! */
896 if ((rv = do_check_string(str, -1, equal, flags,
897 chk, chklen, peername)) != 0)
898 return rv;
899 }
900 return 0;
901}
a70da5b3 902
297c67fc 903int X509_check_host(X509 *x, const char *chk, size_t chklen,
0f113f3e
MC
904 unsigned int flags, char **peername)
905{
906 if (chk == NULL)
907 return -2;
908 /*
909 * Embedded NULs are disallowed, except as the last character of a
910 * string of length 2 or more (tolerate caller including terminating
911 * NUL in string length).
912 */
913 if (chklen == 0)
914 chklen = strlen(chk);
915 else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
916 return -2;
917 if (chklen > 1 && chk[chklen - 1] == '\0')
918 --chklen;
919 return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
920}
a70da5b3 921
297c67fc 922int X509_check_email(X509 *x, const char *chk, size_t chklen,
0f113f3e
MC
923 unsigned int flags)
924{
925 if (chk == NULL)
926 return -2;
927 /*
928 * Embedded NULs are disallowed, except as the last character of a
929 * string of length 2 or more (tolerate caller including terminating
930 * NUL in string length).
931 */
932 if (chklen == 0)
933 chklen = strlen((char *)chk);
934 else if (memchr(chk, '\0', chklen > 1 ? chklen - 1 : chklen))
935 return -2;
936 if (chklen > 1 && chk[chklen - 1] == '\0')
937 --chklen;
938 return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
939}
a70da5b3
DSH
940
941int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
0f113f3e
MC
942 unsigned int flags)
943{
944 if (chk == NULL)
945 return -2;
946 return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
947}
a70da5b3
DSH
948
949int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
0f113f3e
MC
950{
951 unsigned char ipout[16];
952 size_t iplen;
953
954 if (ipasc == NULL)
955 return -2;
956 iplen = (size_t)a2i_ipadd(ipout, ipasc);
957 if (iplen == 0)
958 return -2;
959 return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
960}
961
962/*
963 * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
964 * with RFC3280.
4e5d3a7f
DSH
965 */
966
967ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
0f113f3e
MC
968{
969 unsigned char ipout[16];
970 ASN1_OCTET_STRING *ret;
971 int iplen;
4e5d3a7f 972
0f113f3e 973 /* If string contains a ':' assume IPv6 */
4e5d3a7f 974
0f113f3e 975 iplen = a2i_ipadd(ipout, ipasc);
520b76ff 976
0f113f3e
MC
977 if (!iplen)
978 return NULL;
4e5d3a7f 979
0f113f3e 980 ret = ASN1_OCTET_STRING_new();
90945fa3 981 if (ret == NULL)
0f113f3e
MC
982 return NULL;
983 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
984 ASN1_OCTET_STRING_free(ret);
985 return NULL;
986 }
987 return ret;
988}
4e5d3a7f 989
520b76ff 990ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
0f113f3e
MC
991{
992 ASN1_OCTET_STRING *ret = NULL;
993 unsigned char ipout[32];
994 char *iptmp = NULL, *p;
995 int iplen1, iplen2;
996 p = strchr(ipasc, '/');
997 if (!p)
998 return NULL;
7644a9ae 999 iptmp = OPENSSL_strdup(ipasc);
0f113f3e
MC
1000 if (!iptmp)
1001 return NULL;
1002 p = iptmp + (p - ipasc);
1003 *p++ = 0;
1004
1005 iplen1 = a2i_ipadd(ipout, iptmp);
1006
1007 if (!iplen1)
1008 goto err;
1009
1010 iplen2 = a2i_ipadd(ipout + iplen1, p);
1011
1012 OPENSSL_free(iptmp);
1013 iptmp = NULL;
1014
1015 if (!iplen2 || (iplen1 != iplen2))
1016 goto err;
1017
1018 ret = ASN1_OCTET_STRING_new();
90945fa3 1019 if (ret == NULL)
0f113f3e
MC
1020 goto err;
1021 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1022 goto err;
1023
1024 return ret;
1025
1026 err:
b548a1f1 1027 OPENSSL_free(iptmp);
2ace7450 1028 ASN1_OCTET_STRING_free(ret);
0f113f3e
MC
1029 return NULL;
1030}
520b76ff 1031
96ea4ae9 1032int a2i_ipadd(unsigned char *ipout, const char *ipasc)
0f113f3e
MC
1033{
1034 /* If string contains a ':' assume IPv6 */
1035
1036 if (strchr(ipasc, ':')) {
1037 if (!ipv6_from_asc(ipout, ipasc))
1038 return 0;
1039 return 16;
1040 } else {
1041 if (!ipv4_from_asc(ipout, ipasc))
1042 return 0;
1043 return 4;
1044 }
1045}
520b76ff 1046
4e5d3a7f 1047static int ipv4_from_asc(unsigned char *v4, const char *in)
0f113f3e
MC
1048{
1049 int a0, a1, a2, a3;
1050 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1051 return 0;
1052 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
1053 || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1054 return 0;
1055 v4[0] = a0;
1056 v4[1] = a1;
1057 v4[2] = a2;
1058 v4[3] = a3;
1059 return 1;
1060}
4e5d3a7f
DSH
1061
1062typedef struct {
0f113f3e
MC
1063 /* Temporary store for IPV6 output */
1064 unsigned char tmp[16];
1065 /* Total number of bytes in tmp */
1066 int total;
1067 /* The position of a zero (corresponding to '::') */
1068 int zero_pos;
1069 /* Number of zeroes */
1070 int zero_cnt;
1071} IPV6_STAT;
4e5d3a7f
DSH
1072
1073static int ipv6_from_asc(unsigned char *v6, const char *in)
0f113f3e
MC
1074{
1075 IPV6_STAT v6stat;
1076 v6stat.total = 0;
1077 v6stat.zero_pos = -1;
1078 v6stat.zero_cnt = 0;
1079 /*
1080 * Treat the IPv6 representation as a list of values separated by ':'.
1081 * The presence of a '::' will parse as one, two or three zero length
1082 * elements.
1083 */
1084 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1085 return 0;
1086
1087 /* Now for some sanity checks */
1088
1089 if (v6stat.zero_pos == -1) {
1090 /* If no '::' must have exactly 16 bytes */
1091 if (v6stat.total != 16)
1092 return 0;
1093 } else {
1094 /* If '::' must have less than 16 bytes */
1095 if (v6stat.total == 16)
1096 return 0;
1097 /* More than three zeroes is an error */
1098 if (v6stat.zero_cnt > 3)
1099 return 0;
1100 /* Can only have three zeroes if nothing else present */
1101 else if (v6stat.zero_cnt == 3) {
1102 if (v6stat.total > 0)
1103 return 0;
1104 }
1105 /* Can only have two zeroes if at start or end */
1106 else if (v6stat.zero_cnt == 2) {
1107 if ((v6stat.zero_pos != 0)
1108 && (v6stat.zero_pos != v6stat.total))
1109 return 0;
1110 } else
1111 /* Can only have one zero if *not* start or end */
1112 {
1113 if ((v6stat.zero_pos == 0)
1114 || (v6stat.zero_pos == v6stat.total))
1115 return 0;
1116 }
1117 }
1118
1119 /* Format result */
1120
1121 if (v6stat.zero_pos >= 0) {
1122 /* Copy initial part */
1123 memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1124 /* Zero middle */
1125 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1126 /* Copy final part */
1127 if (v6stat.total != v6stat.zero_pos)
1128 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1129 v6stat.tmp + v6stat.zero_pos,
1130 v6stat.total - v6stat.zero_pos);
1131 } else
1132 memcpy(v6, v6stat.tmp, 16);
1133
1134 return 1;
1135}
4e5d3a7f
DSH
1136
1137static int ipv6_cb(const char *elem, int len, void *usr)
0f113f3e
MC
1138{
1139 IPV6_STAT *s = usr;
1140 /* Error if 16 bytes written */
1141 if (s->total == 16)
1142 return 0;
1143 if (len == 0) {
1144 /* Zero length element, corresponds to '::' */
1145 if (s->zero_pos == -1)
1146 s->zero_pos = s->total;
1147 /* If we've already got a :: its an error */
1148 else if (s->zero_pos != s->total)
1149 return 0;
1150 s->zero_cnt++;
1151 } else {
1152 /* If more than 4 characters could be final a.b.c.d form */
1153 if (len > 4) {
1154 /* Need at least 4 bytes left */
1155 if (s->total > 12)
1156 return 0;
1157 /* Must be end of string */
1158 if (elem[len])
1159 return 0;
1160 if (!ipv4_from_asc(s->tmp + s->total, elem))
1161 return 0;
1162 s->total += 4;
1163 } else {
1164 if (!ipv6_hex(s->tmp + s->total, elem, len))
1165 return 0;
1166 s->total += 2;
1167 }
1168 }
1169 return 1;
1170}
1171
1172/*
1173 * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
4e5d3a7f
DSH
1174 */
1175
1176static int ipv6_hex(unsigned char *out, const char *in, int inlen)
0f113f3e
MC
1177{
1178 unsigned char c;
1179 unsigned int num = 0;
49445f21
RS
1180 int x;
1181
0f113f3e
MC
1182 if (inlen > 4)
1183 return 0;
1184 while (inlen--) {
1185 c = *in++;
1186 num <<= 4;
49445f21
RS
1187 x = OPENSSL_hexchar2int(c);
1188 if (x < 0)
0f113f3e 1189 return 0;
49445f21 1190 num |= (char)x;
0f113f3e
MC
1191 }
1192 out[0] = num >> 8;
1193 out[1] = num & 0xff;
1194 return 1;
1195}
f0dc08e6 1196
a7b1eed5 1197int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
0f113f3e
MC
1198 unsigned long chtype)
1199{
1200 CONF_VALUE *v;
b5292f7b 1201 int i, mval, spec_char, plus_char;
0f113f3e
MC
1202 char *p, *type;
1203 if (!nm)
1204 return 0;
1205
1206 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1207 v = sk_CONF_VALUE_value(dn_sk, i);
1208 type = v->name;
1209 /*
1210 * Skip past any leading X. X: X, etc to allow for multiple instances
1211 */
b5292f7b 1212 for (p = type; *p; p++) {
f0dc08e6 1213#ifndef CHARSET_EBCDIC
b5292f7b 1214 spec_char = ((*p == ':') || (*p == ',') || (*p == '.'));
f0dc08e6 1215#else
b5292f7b
FM
1216 spec_char = ((*p == os_toascii[':']) || (*p == os_toascii[','])
1217 || (*p == os_toascii['.']));
f0dc08e6 1218#endif
b5292f7b 1219 if (spec_char) {
0f113f3e
MC
1220 p++;
1221 if (*p)
1222 type = p;
1223 break;
1224 }
b5292f7b 1225 }
1a15c899 1226#ifndef CHARSET_EBCDIC
b5292f7b 1227 plus_char = (*type == '+');
1a15c899 1228#else
b5292f7b 1229 plus_char = (*type == os_toascii['+']);
1a15c899 1230#endif
b5292f7b 1231 if (plus_char) {
0f113f3e
MC
1232 mval = -1;
1233 type++;
1234 } else
1235 mval = 0;
1236 if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1237 (unsigned char *)v->value, -1, -1,
1238 mval))
1239 return 0;
1240
1241 }
1242 return 1;
1243}