summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/x509v3/v3_utl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_utl.c')
-rw-r--r--src/lib/libcrypto/x509v3/v3_utl.c925
1 files changed, 0 insertions, 925 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c
deleted file mode 100644
index ee135a0b52..0000000000
--- a/src/lib/libcrypto/x509v3/v3_utl.c
+++ /dev/null
@@ -1,925 +0,0 @@
1/* $OpenBSD: v3_utl.c,v 1.24 2015/02/07 13:19:15 doug 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
69static char *strip_spaces(char *name);
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);
73static void str_free(OPENSSL_STRING str);
74static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
75
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
81/* Add a CONF_VALUE name value pair to stack */
82
83int
84X509V3_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 if (name && !(tname = strdup(name)))
91 goto err;
92 if (value && !(tvalue = strdup(value)))
93 goto err;
94 if (!(vtmp = malloc(sizeof(CONF_VALUE))))
95 goto err;
96 if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
97 goto err;
98 vtmp->section = NULL;
99 vtmp->name = tname;
100 vtmp->value = tvalue;
101 if (!sk_CONF_VALUE_push(*extlist, vtmp))
102 goto err;
103 return 1;
104
105err:
106 X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE);
107 free(vtmp);
108 free(tname);
109 free(tvalue);
110 return 0;
111}
112
113int
114X509V3_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
122void
123X509V3_conf_free(CONF_VALUE *conf)
124{
125 if (!conf)
126 return;
127 free(conf->name);
128 free(conf->value);
129 free(conf->section);
130 free(conf);
131}
132
133int
134X509V3_add_value_bool(const char *name, int asn1_bool,
135 STACK_OF(CONF_VALUE) **extlist)
136{
137 if (asn1_bool)
138 return X509V3_add_value(name, "TRUE", extlist);
139 return X509V3_add_value(name, "FALSE", extlist);
140}
141
142int
143X509V3_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
152char *
153i2s_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 X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE);
163 BN_free(bntmp);
164 return strtmp;
165}
166
167char *
168i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
169{
170 BIGNUM *bntmp = NULL;
171 char *strtmp = NULL;
172
173 if (!a)
174 return NULL;
175 if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
176 !(strtmp = BN_bn2dec(bntmp)))
177 X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE);
178 BN_free(bntmp);
179 return strtmp;
180}
181
182ASN1_INTEGER *
183s2i_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 X509V3err(X509V3_F_S2I_ASN1_INTEGER,
192 X509V3_R_INVALID_NULL_VALUE);
193 return 0;
194 }
195 bn = BN_new();
196 if (value[0] == '-') {
197 value++;
198 isneg = 1;
199 } else
200 isneg = 0;
201
202 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
203 value += 2;
204 ishex = 1;
205 } else
206 ishex = 0;
207
208 if (ishex)
209 ret = BN_hex2bn(&bn, value);
210 else
211 ret = BN_dec2bn(&bn, value);
212
213 if (!ret || value[ret]) {
214 BN_free(bn);
215 X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR);
216 return 0;
217 }
218
219 if (isneg && BN_is_zero(bn))
220 isneg = 0;
221
222 aint = BN_to_ASN1_INTEGER(bn, NULL);
223 BN_free(bn);
224 if (!aint) {
225 X509V3err(X509V3_F_S2I_ASN1_INTEGER,
226 X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
227 return 0;
228 }
229 if (isneg)
230 aint->type |= V_ASN1_NEG;
231 return aint;
232}
233
234int
235X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
236 STACK_OF(CONF_VALUE) **extlist)
237{
238 char *strtmp;
239 int ret;
240
241 if (!aint)
242 return 1;
243 if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
244 return 0;
245 ret = X509V3_add_value(name, strtmp, extlist);
246 free(strtmp);
247 return ret;
248}
249
250int
251X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
252{
253 char *btmp;
254
255 if (!(btmp = value->value))
256 goto err;
257 if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") ||
258 !strcmp(btmp, "Y") || !strcmp(btmp, "y") ||
259 !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
260 *asn1_bool = 0xff;
261 return 1;
262 } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
263 !strcmp(btmp, "N") || !strcmp(btmp, "n") ||
264 !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
265 *asn1_bool = 0;
266 return 1;
267 }
268
269err:
270 X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,
271 X509V3_R_INVALID_BOOLEAN_STRING);
272 X509V3_conf_err(value);
273 return 0;
274}
275
276int
277X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
278{
279 ASN1_INTEGER *itmp;
280
281 if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
282 X509V3_conf_err(value);
283 return 0;
284 }
285 *aint = itmp;
286 return 1;
287}
288
289#define HDR_NAME 1
290#define HDR_VALUE 2
291
292/*#define DEBUG*/
293
294STACK_OF(CONF_VALUE) *
295X509V3_parse_list(const char *line)
296{
297 char *p, *q, c;
298 char *ntmp, *vtmp;
299 STACK_OF(CONF_VALUE) *values = NULL;
300 char *linebuf;
301 int state;
302
303 /* We are going to modify the line so copy it first */
304 if ((linebuf = strdup(line)) == NULL) {
305 X509V3err(X509V3_F_X509V3_PARSE_LIST, ERR_R_MALLOC_FAILURE);
306 goto err;
307 }
308 state = HDR_NAME;
309 ntmp = NULL;
310
311 /* Go through all characters */
312 for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') &&
313 (c != '\n'); p++) {
314
315 switch (state) {
316 case HDR_NAME:
317 if (c == ':') {
318 state = HDR_VALUE;
319 *p = 0;
320 ntmp = strip_spaces(q);
321 if (!ntmp) {
322 X509V3err(X509V3_F_X509V3_PARSE_LIST,
323 X509V3_R_INVALID_NULL_NAME);
324 goto err;
325 }
326 q = p + 1;
327 } else if (c == ',') {
328 *p = 0;
329 ntmp = strip_spaces(q);
330 q = p + 1;
331 if (!ntmp) {
332 X509V3err(X509V3_F_X509V3_PARSE_LIST,
333 X509V3_R_INVALID_NULL_NAME);
334 goto err;
335 }
336 X509V3_add_value(ntmp, NULL, &values);
337 }
338 break;
339
340 case HDR_VALUE:
341 if (c == ',') {
342 state = HDR_NAME;
343 *p = 0;
344 vtmp = strip_spaces(q);
345 if (!vtmp) {
346 X509V3err(X509V3_F_X509V3_PARSE_LIST,
347 X509V3_R_INVALID_NULL_VALUE);
348 goto err;
349 }
350 X509V3_add_value(ntmp, vtmp, &values);
351 ntmp = NULL;
352 q = p + 1;
353 }
354
355 }
356 }
357
358 if (state == HDR_VALUE) {
359 vtmp = strip_spaces(q);
360 if (!vtmp) {
361 X509V3err(X509V3_F_X509V3_PARSE_LIST,
362 X509V3_R_INVALID_NULL_VALUE);
363 goto err;
364 }
365 X509V3_add_value(ntmp, vtmp, &values);
366 } else {
367 ntmp = strip_spaces(q);
368 if (!ntmp) {
369 X509V3err(X509V3_F_X509V3_PARSE_LIST,
370 X509V3_R_INVALID_NULL_NAME);
371 goto err;
372 }
373 X509V3_add_value(ntmp, NULL, &values);
374 }
375 free(linebuf);
376 return values;
377
378err:
379 free(linebuf);
380 sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
381 return NULL;
382
383}
384
385/* Delete leading and trailing spaces from a string */
386static char *
387strip_spaces(char *name)
388{
389 char *p, *q;
390
391 /* Skip over leading spaces */
392 p = name;
393 while (*p && isspace((unsigned char)*p))
394 p++;
395 if (!*p)
396 return NULL;
397 q = p + strlen(p) - 1;
398 while ((q != p) && isspace((unsigned char)*q))
399 q--;
400 if (p != q)
401 q[1] = 0;
402 if (!*p)
403 return NULL;
404 return p;
405}
406
407/* hex string utilities */
408
409/* Given a buffer of length 'len' return a malloc'ed string with its
410 * hex representation
411 */
412char *
413hex_to_string(const unsigned char *buffer, long len)
414{
415 char *tmp, *q;
416 const unsigned char *p;
417 int i;
418 static const char hexdig[] = "0123456789ABCDEF";
419
420 if (!buffer || !len)
421 return NULL;
422 if (!(tmp = malloc(len * 3 + 1))) {
423 X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE);
424 return NULL;
425 }
426 q = tmp;
427 for (i = 0, p = buffer; i < len; i++, p++) {
428 *q++ = hexdig[(*p >> 4) & 0xf];
429 *q++ = hexdig[*p & 0xf];
430 *q++ = ':';
431 }
432 q[-1] = 0;
433 return tmp;
434}
435
436/* Give a string of hex digits convert to
437 * a buffer
438 */
439
440unsigned char *
441string_to_hex(const char *str, long *len)
442{
443 unsigned char *hexbuf, *q;
444 unsigned char ch, cl, *p;
445 if (!str) {
446 X509V3err(X509V3_F_STRING_TO_HEX,
447 X509V3_R_INVALID_NULL_ARGUMENT);
448 return NULL;
449 }
450 if (!(hexbuf = malloc(strlen(str) >> 1)))
451 goto err;
452 for (p = (unsigned char *)str, q = hexbuf; *p; ) {
453 ch = *p++;
454 if (ch == ':')
455 continue;
456 cl = *p++;
457 if (!cl) {
458 X509V3err(X509V3_F_STRING_TO_HEX,
459 X509V3_R_ODD_NUMBER_OF_DIGITS);
460 free(hexbuf);
461 return NULL;
462 }
463 ch = tolower(ch);
464 cl = tolower(cl);
465
466 if ((ch >= '0') && (ch <= '9'))
467 ch -= '0';
468 else if ((ch >= 'a') && (ch <= 'f'))
469 ch -= 'a' - 10;
470 else
471 goto badhex;
472
473 if ((cl >= '0') && (cl <= '9'))
474 cl -= '0';
475 else if ((cl >= 'a') && (cl <= 'f'))
476 cl -= 'a' - 10;
477 else
478 goto badhex;
479
480 *q++ = (ch << 4) | cl;
481 }
482
483 if (len)
484 *len = q - hexbuf;
485
486 return hexbuf;
487
488err:
489 free(hexbuf);
490 X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE);
491 return NULL;
492
493badhex:
494 free(hexbuf);
495 X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT);
496 return NULL;
497}
498
499/* V2I name comparison function: returns zero if 'name' matches
500 * cmp or cmp.*
501 */
502
503int
504name_cmp(const char *name, const char *cmp)
505{
506 int len, ret;
507 char c;
508
509 len = strlen(cmp);
510 if ((ret = strncmp(name, cmp, len)))
511 return ret;
512 c = name[len];
513 if (!c || (c=='.'))
514 return 0;
515 return 1;
516}
517
518static int
519sk_strcmp(const char * const *a, const char * const *b)
520{
521 return strcmp(*a, *b);
522}
523
524STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
525{
526 GENERAL_NAMES *gens;
527 STACK_OF(OPENSSL_STRING) *ret;
528
529 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
530 ret = get_email(X509_get_subject_name(x), gens);
531 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
532 return ret;
533}
534
535STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
536{
537 AUTHORITY_INFO_ACCESS *info;
538 STACK_OF(OPENSSL_STRING) *ret = NULL;
539 int i;
540
541 info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
542 if (!info)
543 return NULL;
544 for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
545 ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
546 if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
547 if (ad->location->type == GEN_URI) {
548 if (!append_ia5(&ret,
549 ad->location->d.uniformResourceIdentifier))
550 break;
551 }
552 }
553 }
554 AUTHORITY_INFO_ACCESS_free(info);
555 return ret;
556}
557
558STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
559{
560 GENERAL_NAMES *gens;
561 STACK_OF(X509_EXTENSION) *exts;
562 STACK_OF(OPENSSL_STRING) *ret;
563
564 exts = X509_REQ_get_extensions(x);
565 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
566 ret = get_email(X509_REQ_get_subject_name(x), gens);
567 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
568 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
569 return ret;
570}
571
572
573static
574STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens)
575{
576 STACK_OF(OPENSSL_STRING) *ret = NULL;
577 X509_NAME_ENTRY *ne;
578 ASN1_IA5STRING *email;
579 GENERAL_NAME *gen;
580 int i;
581
582 /* Now add any email address(es) to STACK */
583 i = -1;
584
585 /* First supplied X509_NAME */
586 while ((i = X509_NAME_get_index_by_NID(name,
587 NID_pkcs9_emailAddress, i)) >= 0) {
588 ne = X509_NAME_get_entry(name, i);
589 email = X509_NAME_ENTRY_get_data(ne);
590 if (!append_ia5(&ret, email))
591 return NULL;
592 }
593 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
594 gen = sk_GENERAL_NAME_value(gens, i);
595 if (gen->type != GEN_EMAIL)
596 continue;
597 if (!append_ia5(&ret, gen->d.ia5))
598 return NULL;
599 }
600 return ret;
601}
602
603static void
604str_free(OPENSSL_STRING str)
605{
606 free(str);
607}
608
609static int
610append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
611{
612 char *emtmp;
613
614 /* First some sanity checks */
615 if (email->type != V_ASN1_IA5STRING)
616 return 1;
617 if (!email->data || !email->length)
618 return 1;
619 if (!*sk)
620 *sk = sk_OPENSSL_STRING_new(sk_strcmp);
621 if (!*sk)
622 return 0;
623 /* Don't add duplicates */
624 if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
625 return 1;
626 emtmp = strdup((char *)email->data);
627 if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
628 X509_email_free(*sk);
629 *sk = NULL;
630 return 0;
631 }
632 return 1;
633}
634
635void
636X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
637{
638 sk_OPENSSL_STRING_pop_free(sk, str_free);
639}
640
641/* Convert IP addresses both IPv4 and IPv6 into an
642 * OCTET STRING compatible with RFC3280.
643 */
644
645ASN1_OCTET_STRING *
646a2i_IPADDRESS(const char *ipasc)
647{
648 unsigned char ipout[16];
649 ASN1_OCTET_STRING *ret;
650 int iplen;
651
652 /* If string contains a ':' assume IPv6 */
653
654 iplen = a2i_ipadd(ipout, ipasc);
655
656 if (!iplen)
657 return NULL;
658
659 ret = ASN1_OCTET_STRING_new();
660 if (!ret)
661 return NULL;
662 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
663 ASN1_OCTET_STRING_free(ret);
664 return NULL;
665 }
666 return ret;
667}
668
669ASN1_OCTET_STRING *
670a2i_IPADDRESS_NC(const char *ipasc)
671{
672 ASN1_OCTET_STRING *ret = NULL;
673 unsigned char ipout[32];
674 char *iptmp = NULL, *p;
675 int iplen1, iplen2;
676
677 p = strchr(ipasc, '/');
678 if (!p)
679 return NULL;
680 iptmp = strdup(ipasc);
681 if (!iptmp)
682 return NULL;
683 p = iptmp + (p - ipasc);
684 *p++ = 0;
685
686 iplen1 = a2i_ipadd(ipout, iptmp);
687
688 if (!iplen1)
689 goto err;
690
691 iplen2 = a2i_ipadd(ipout + iplen1, p);
692
693 free(iptmp);
694 iptmp = NULL;
695
696 if (!iplen2 || (iplen1 != iplen2))
697 goto err;
698
699 ret = ASN1_OCTET_STRING_new();
700 if (!ret)
701 goto err;
702 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
703 goto err;
704
705 return ret;
706
707err:
708 free(iptmp);
709 if (ret)
710 ASN1_OCTET_STRING_free(ret);
711 return NULL;
712}
713
714
715int
716a2i_ipadd(unsigned char *ipout, const char *ipasc)
717{
718 /* If string contains a ':' assume IPv6 */
719
720 if (strchr(ipasc, ':')) {
721 if (!ipv6_from_asc(ipout, ipasc))
722 return 0;
723 return 16;
724 } else {
725 if (!ipv4_from_asc(ipout, ipasc))
726 return 0;
727 return 4;
728 }
729}
730
731static int
732ipv4_from_asc(unsigned char *v4, const char *in)
733{
734 int a0, a1, a2, a3;
735 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
736 return 0;
737 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) ||
738 (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
739 return 0;
740 v4[0] = a0;
741 v4[1] = a1;
742 v4[2] = a2;
743 v4[3] = a3;
744 return 1;
745}
746
747typedef struct {
748 /* Temporary store for IPV6 output */
749 unsigned char tmp[16];
750 /* Total number of bytes in tmp */
751 int total;
752 /* The position of a zero (corresponding to '::') */
753 int zero_pos;
754 /* Number of zeroes */
755 int zero_cnt;
756} IPV6_STAT;
757
758
759static int
760ipv6_from_asc(unsigned char *v6, const char *in)
761{
762 IPV6_STAT v6stat;
763
764 v6stat.total = 0;
765 v6stat.zero_pos = -1;
766 v6stat.zero_cnt = 0;
767
768 /* Treat the IPv6 representation as a list of values
769 * separated by ':'. The presence of a '::' will parse
770 * as one, two or three zero length elements.
771 */
772 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
773 return 0;
774
775 /* Now for some sanity checks */
776
777 if (v6stat.zero_pos == -1) {
778 /* If no '::' must have exactly 16 bytes */
779 if (v6stat.total != 16)
780 return 0;
781 } else {
782 /* If '::' must have less than 16 bytes */
783 if (v6stat.total == 16)
784 return 0;
785 /* More than three zeroes is an error */
786 if (v6stat.zero_cnt > 3)
787 return 0;
788 /* Can only have three zeroes if nothing else present */
789 else if (v6stat.zero_cnt == 3) {
790 if (v6stat.total > 0)
791 return 0;
792 }
793 /* Can only have two zeroes if at start or end */
794 else if (v6stat.zero_cnt == 2) {
795 if ((v6stat.zero_pos != 0) &&
796 (v6stat.zero_pos != v6stat.total))
797 return 0;
798 } else
799 /* Can only have one zero if *not* start or end */
800 {
801 if ((v6stat.zero_pos == 0) ||
802 (v6stat.zero_pos == v6stat.total))
803 return 0;
804 }
805 }
806
807 /* Format result */
808
809 if (v6stat.zero_pos >= 0) {
810 /* Copy initial part */
811 memcpy(v6, v6stat.tmp, v6stat.zero_pos);
812 /* Zero middle */
813 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
814 /* Copy final part */
815 if (v6stat.total != v6stat.zero_pos)
816 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
817 v6stat.tmp + v6stat.zero_pos,
818 v6stat.total - v6stat.zero_pos);
819 } else
820 memcpy(v6, v6stat.tmp, 16);
821
822 return 1;
823}
824
825static int
826ipv6_cb(const char *elem, int len, void *usr)
827{
828 IPV6_STAT *s = usr;
829
830 /* Error if 16 bytes written */
831 if (s->total == 16)
832 return 0;
833 if (len == 0) {
834 /* Zero length element, corresponds to '::' */
835 if (s->zero_pos == -1)
836 s->zero_pos = s->total;
837 /* If we've already got a :: its an error */
838 else if (s->zero_pos != s->total)
839 return 0;
840 s->zero_cnt++;
841 } else {
842 /* If more than 4 characters could be final a.b.c.d form */
843 if (len > 4) {
844 /* Need at least 4 bytes left */
845 if (s->total > 12)
846 return 0;
847 /* Must be end of string */
848 if (elem[len])
849 return 0;
850 if (!ipv4_from_asc(s->tmp + s->total, elem))
851 return 0;
852 s->total += 4;
853 } else {
854 if (!ipv6_hex(s->tmp + s->total, elem, len))
855 return 0;
856 s->total += 2;
857 }
858 }
859 return 1;
860}
861
862/* Convert a string of up to 4 hex digits into the corresponding
863 * IPv6 form.
864 */
865
866static int
867ipv6_hex(unsigned char *out, const char *in, int inlen)
868{
869 unsigned char c;
870 unsigned int num = 0;
871
872 if (inlen > 4)
873 return 0;
874 while (inlen--) {
875 c = *in++;
876 num <<= 4;
877 if ((c >= '0') && (c <= '9'))
878 num |= c - '0';
879 else if ((c >= 'A') && (c <= 'F'))
880 num |= c - 'A' + 10;
881 else if ((c >= 'a') && (c <= 'f'))
882 num |= c - 'a' + 10;
883 else
884 return 0;
885 }
886 out[0] = num >> 8;
887 out[1] = num & 0xff;
888 return 1;
889}
890
891int
892X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
893 unsigned long chtype)
894{
895 CONF_VALUE *v;
896 int i, mval;
897 char *p, *type;
898
899 if (!nm)
900 return 0;
901
902 for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
903 v = sk_CONF_VALUE_value(dn_sk, i);
904 type = v->name;
905 /* Skip past any leading X. X: X, etc to allow for
906 * multiple instances
907 */
908 for (p = type; *p; p++)
909 if ((*p == ':') || (*p == ',') || (*p == '.')) {
910 p++;
911 if (*p)
912 type = p;
913 break;
914 }
915 if (*type == '+') {
916 mval = -1;
917 type++;
918 } else
919 mval = 0;
920 if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
921 (unsigned char *) v->value, -1, -1, mval))
922 return 0;
923 }
924 return 1;
925}