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