]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509v3/v3_utl.c
IPv6 display and input support for extensions usingh GeneralName.
[thirdparty/openssl.git] / crypto / x509v3 / v3_utl.c
CommitLineData
9aeaf1b4
DSH
1/* v3_utl.c */
2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) 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
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
e527ba09
DSH
60
61#include <stdio.h>
9aeaf1b4 62#include <ctype.h>
e527ba09 63#include "cryptlib.h"
ec577822
BM
64#include <openssl/conf.h>
65#include <openssl/x509v3.h>
9aeaf1b4 66
9aeaf1b4 67static char *strip_spaces(char *name);
a91dedca 68static int sk_strcmp(const char * const *a, const char * const *b);
9d6b1ce6 69static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
a91dedca
DSH
70static void str_free(void *str);
71static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
9aeaf1b4 72
4e5d3a7f
DSH
73static int ipv4_from_asc(unsigned char *v4, const char *in);
74static int ipv6_from_asc(unsigned char *v6, const char *in);
75static int ipv6_cb(const char *elem, int len, void *usr);
76static int ipv6_hex(unsigned char *out, const char *in, int inlen);
77
9aeaf1b4
DSH
78/* Add a CONF_VALUE name value pair to stack */
79
ba404b5e
DSH
80int X509V3_add_value(const char *name, const char *value,
81 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4
DSH
82{
83 CONF_VALUE *vtmp = NULL;
84 char *tname = NULL, *tvalue = NULL;
9985bed3
DSH
85 if(name && !(tname = BUF_strdup(name))) goto err;
86 if(value && !(tvalue = BUF_strdup(value))) goto err;;
26a3a48d 87 if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
62324627 88 if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
9aeaf1b4
DSH
89 vtmp->section = NULL;
90 vtmp->name = tname;
91 vtmp->value = tvalue;
ba404b5e 92 if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
9aeaf1b4
DSH
93 return 1;
94 err:
95 X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE);
26a3a48d
RL
96 if(vtmp) OPENSSL_free(vtmp);
97 if(tname) OPENSSL_free(tname);
98 if(tvalue) OPENSSL_free(tvalue);
9aeaf1b4
DSH
99 return 0;
100}
101
61f5b6f3 102int X509V3_add_value_uchar(const char *name, const unsigned char *value,
ba404b5e 103 STACK_OF(CONF_VALUE) **extlist)
61f5b6f3
BL
104 {
105 return X509V3_add_value(name,(const char *)value,extlist);
106 }
107
66ab08b1 108/* Free function for STACK_OF(CONF_VALUE) */
9aeaf1b4 109
6b691a5c 110void X509V3_conf_free(CONF_VALUE *conf)
9aeaf1b4
DSH
111{
112 if(!conf) return;
26a3a48d
RL
113 if(conf->name) OPENSSL_free(conf->name);
114 if(conf->value) OPENSSL_free(conf->value);
115 if(conf->section) OPENSSL_free(conf->section);
116 OPENSSL_free(conf);
9aeaf1b4
DSH
117}
118
ba404b5e
DSH
119int X509V3_add_value_bool(const char *name, int asn1_bool,
120 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4
DSH
121{
122 if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
123 return X509V3_add_value(name, "FALSE", extlist);
124}
125
ba404b5e
DSH
126int X509V3_add_value_bool_nf(char *name, int asn1_bool,
127 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4
DSH
128{
129 if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
130 return 1;
131}
132
c74f1eb9 133
6b691a5c 134char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
c74f1eb9
DSH
135{
136 BIGNUM *bntmp = NULL;
137 char *strtmp = NULL;
138 if(!a) return NULL;
139 if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
140 !(strtmp = BN_bn2dec(bntmp)) )
141 X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE);
142 BN_free(bntmp);
143 return strtmp;
144}
145
6b691a5c 146char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
0ca5f8b1
DSH
147{
148 BIGNUM *bntmp = NULL;
149 char *strtmp = NULL;
150 if(!a) return NULL;
151 if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
152 !(strtmp = BN_bn2dec(bntmp)) )
153 X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE);
154 BN_free(bntmp);
155 return strtmp;
156}
157
6b691a5c 158ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
28a98809
DSH
159{
160 BIGNUM *bn = NULL;
161 ASN1_INTEGER *aint;
8e8972bb
DSH
162 int isneg, ishex;
163 int ret;
8e8972bb 164 if (!value) {
28a98809
DSH
165 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE);
166 return 0;
167 }
2232e262 168 bn = BN_new();
8e8972bb
DSH
169 if (value[0] == '-') {
170 value++;
171 isneg = 1;
172 } else isneg = 0;
173
174 if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
175 value += 2;
176 ishex = 1;
177 } else ishex = 0;
178
179 if (ishex) ret = BN_hex2bn(&bn, value);
180 else ret = BN_dec2bn(&bn, value);
181
2232e262
DSH
182 if (!ret || value[ret]) {
183 BN_free(bn);
28a98809
DSH
184 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR);
185 return 0;
186 }
187
8e8972bb
DSH
188 if (isneg && BN_is_zero(bn)) isneg = 0;
189
190 aint = BN_to_ASN1_INTEGER(bn, NULL);
191 BN_free(bn);
192 if (!aint) {
28a98809
DSH
193 X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
194 return 0;
195 }
8e8972bb 196 if (isneg) aint->type |= V_ASN1_NEG;
28a98809
DSH
197 return aint;
198}
199
6b691a5c 200int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
ba404b5e 201 STACK_OF(CONF_VALUE) **extlist)
9aeaf1b4 202{
9aeaf1b4
DSH
203 char *strtmp;
204 int ret;
205 if(!aint) return 1;
0ca5f8b1 206 if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
9aeaf1b4 207 ret = X509V3_add_value(name, strtmp, extlist);
26a3a48d 208 OPENSSL_free(strtmp);
9aeaf1b4
DSH
209 return ret;
210}
211
6b691a5c 212int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
9aeaf1b4
DSH
213{
214 char *btmp;
215 if(!(btmp = value->value)) goto err;
216 if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
217 || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
218 || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
219 *asn1_bool = 0xff;
220 return 1;
221 } else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
222 || !strcmp(btmp, "N") || !strcmp(btmp, "n")
223 || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
224 *asn1_bool = 0;
225 return 1;
226 }
227 err:
28a98809 228 X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING);
9aeaf1b4
DSH
229 X509V3_conf_err(value);
230 return 0;
231}
232
6b691a5c 233int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
9aeaf1b4 234{
28a98809
DSH
235 ASN1_INTEGER *itmp;
236 if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
9aeaf1b4
DSH
237 X509V3_conf_err(value);
238 return 0;
239 }
28a98809 240 *aint = itmp;
9aeaf1b4
DSH
241 return 1;
242}
243
244#define HDR_NAME 1
245#define HDR_VALUE 2
246
247/*#define DEBUG*/
248
535d79da 249STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
9aeaf1b4
DSH
250{
251 char *p, *q, c;
252 char *ntmp, *vtmp;
ba404b5e 253 STACK_OF(CONF_VALUE) *values = NULL;
9aeaf1b4
DSH
254 char *linebuf;
255 int state;
256 /* We are going to modify the line so copy it first */
9985bed3 257 linebuf = BUF_strdup(line);
9aeaf1b4
DSH
258 state = HDR_NAME;
259 ntmp = NULL;
260 /* Go through all characters */
261 for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
262
263 switch(state) {
264 case HDR_NAME:
265 if(c == ':') {
266 state = HDR_VALUE;
267 *p = 0;
268 ntmp = strip_spaces(q);
269 if(!ntmp) {
270 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
271 goto err;
272 }
273 q = p + 1;
274 } else if(c == ',') {
275 *p = 0;
276 ntmp = strip_spaces(q);
277 q = p + 1;
59dbdb51 278#if 0
9aeaf1b4
DSH
279 printf("%s\n", ntmp);
280#endif
281 if(!ntmp) {
282 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
283 goto err;
284 }
285 X509V3_add_value(ntmp, NULL, &values);
286 }
287 break ;
288
289 case HDR_VALUE:
290 if(c == ',') {
291 state = HDR_NAME;
292 *p = 0;
293 vtmp = strip_spaces(q);
59dbdb51 294#if 0
9aeaf1b4
DSH
295 printf("%s\n", ntmp);
296#endif
297 if(!vtmp) {
298 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
299 goto err;
300 }
301 X509V3_add_value(ntmp, vtmp, &values);
302 ntmp = NULL;
303 q = p + 1;
304 }
305
306 }
307 }
308
309 if(state == HDR_VALUE) {
310 vtmp = strip_spaces(q);
59dbdb51 311#if 0
9aeaf1b4
DSH
312 printf("%s=%s\n", ntmp, vtmp);
313#endif
314 if(!vtmp) {
315 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
316 goto err;
317 }
318 X509V3_add_value(ntmp, vtmp, &values);
319 } else {
320 ntmp = strip_spaces(q);
59dbdb51 321#if 0
9aeaf1b4
DSH
322 printf("%s\n", ntmp);
323#endif
324 if(!ntmp) {
325 X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
326 goto err;
327 }
328 X509V3_add_value(ntmp, NULL, &values);
329 }
26a3a48d 330OPENSSL_free(linebuf);
9aeaf1b4
DSH
331return values;
332
333err:
26a3a48d 334OPENSSL_free(linebuf);
ba404b5e 335sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
9aeaf1b4
DSH
336return NULL;
337
338}
339
340/* Delete leading and trailing spaces from a string */
6b691a5c 341static char *strip_spaces(char *name)
9aeaf1b4
DSH
342{
343 char *p, *q;
344 /* Skip over leading spaces */
345 p = name;
84a370a4 346 while(*p && isspace((unsigned char)*p)) p++;
9aeaf1b4
DSH
347 if(!*p) return NULL;
348 q = p + strlen(p) - 1;
84a370a4 349 while((q != p) && isspace((unsigned char)*q)) q--;
9aeaf1b4
DSH
350 if(p != q) q[1] = 0;
351 if(!*p) return NULL;
352 return p;
353}
175b0942
DSH
354
355/* hex string utilities */
356
26a3a48d 357/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
175b0942 358 * hex representation
97d8e82c 359 * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
175b0942
DSH
360 */
361
6b691a5c 362char *hex_to_string(unsigned char *buffer, long len)
175b0942
DSH
363{
364 char *tmp, *q;
365 unsigned char *p;
366 int i;
367 static char hexdig[] = "0123456789ABCDEF";
368 if(!buffer || !len) return NULL;
26a3a48d 369 if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
175b0942
DSH
370 X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
371 return NULL;
372 }
373 q = tmp;
374 for(i = 0, p = buffer; i < len; i++,p++) {
375 *q++ = hexdig[(*p >> 4) & 0xf];
376 *q++ = hexdig[*p & 0xf];
377 *q++ = ':';
378 }
379 q[-1] = 0;
97d8e82c
RL
380#ifdef CHARSET_EBCDIC
381 ebcdic2ascii(tmp, tmp, q - tmp - 1);
382#endif
383
175b0942
DSH
384 return tmp;
385}
386
387/* Give a string of hex digits convert to
388 * a buffer
389 */
390
6b691a5c 391unsigned char *string_to_hex(char *str, long *len)
175b0942
DSH
392{
393 unsigned char *hexbuf, *q;
394 unsigned char ch, cl, *p;
395 if(!str) {
396 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
397 return NULL;
398 }
26a3a48d 399 if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
175b0942
DSH
400 for(p = (unsigned char *)str, q = hexbuf; *p;) {
401 ch = *p++;
97d8e82c
RL
402#ifdef CHARSET_EBCDIC
403 ch = os_toebcdic[ch];
404#endif
175b0942
DSH
405 if(ch == ':') continue;
406 cl = *p++;
97d8e82c
RL
407#ifdef CHARSET_EBCDIC
408 cl = os_toebcdic[cl];
409#endif
175b0942
DSH
410 if(!cl) {
411 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
26a3a48d 412 OPENSSL_free(hexbuf);
175b0942
DSH
413 return NULL;
414 }
415 if(isupper(ch)) ch = tolower(ch);
416 if(isupper(cl)) cl = tolower(cl);
417
418 if((ch >= '0') && (ch <= '9')) ch -= '0';
419 else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
420 else goto badhex;
421
422 if((cl >= '0') && (cl <= '9')) cl -= '0';
423 else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
424 else goto badhex;
425
426 *q++ = (ch << 4) | cl;
427 }
428
429 if(len) *len = q - hexbuf;
430
431 return hexbuf;
432
433 err:
26a3a48d 434 if(hexbuf) OPENSSL_free(hexbuf);
175b0942
DSH
435 X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
436 return NULL;
437
438 badhex:
26a3a48d 439 OPENSSL_free(hexbuf);
175b0942
DSH
440 X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
441 return NULL;
442
443}
d08d8da4
DSH
444
445/* V2I name comparison function: returns zero if 'name' matches
446 * cmp or cmp.*
447 */
448
6b691a5c 449int name_cmp(const char *name, const char *cmp)
d08d8da4
DSH
450{
451 int len, ret;
452 char c;
453 len = strlen(cmp);
454 if((ret = strncmp(name, cmp, len))) return ret;
455 c = name[len];
456 if(!c || (c=='.')) return 0;
457 return 1;
458}
a91dedca
DSH
459
460static int sk_strcmp(const char * const *a, const char * const *b)
461{
462 return strcmp(*a, *b);
463}
464
465STACK *X509_get1_email(X509 *x)
466{
9d6b1ce6 467 GENERAL_NAMES *gens;
a91dedca
DSH
468 STACK *ret;
469 gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
470 ret = get_email(X509_get_subject_name(x), gens);
471 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
472 return ret;
473}
474
475STACK *X509_REQ_get1_email(X509_REQ *x)
476{
9d6b1ce6 477 GENERAL_NAMES *gens;
a91dedca
DSH
478 STACK_OF(X509_EXTENSION) *exts;
479 STACK *ret;
480 exts = X509_REQ_get_extensions(x);
481 gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
482 ret = get_email(X509_REQ_get_subject_name(x), gens);
483 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
484 sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
485 return ret;
486}
487
488
9d6b1ce6 489static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens)
a91dedca
DSH
490{
491 STACK *ret = NULL;
492 X509_NAME_ENTRY *ne;
493 ASN1_IA5STRING *email;
494 GENERAL_NAME *gen;
495 int i;
496 /* Now add any email address(es) to STACK */
497 i = -1;
498 /* First supplied X509_NAME */
499 while((i = X509_NAME_get_index_by_NID(name,
65caee44 500 NID_pkcs9_emailAddress, i)) >= 0) {
a91dedca
DSH
501 ne = X509_NAME_get_entry(name, i);
502 email = X509_NAME_ENTRY_get_data(ne);
503 if(!append_ia5(&ret, email)) return NULL;
504 }
505 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
506 {
507 gen = sk_GENERAL_NAME_value(gens, i);
508 if(gen->type != GEN_EMAIL) continue;
509 if(!append_ia5(&ret, gen->d.ia5)) return NULL;
510 }
511 return ret;
512}
513
514static void str_free(void *str)
515{
516 OPENSSL_free(str);
517}
518
519static int append_ia5(STACK **sk, ASN1_IA5STRING *email)
520{
521 char *emtmp;
522 /* First some sanity checks */
523 if(email->type != V_ASN1_IA5STRING) return 1;
524 if(!email->data || !email->length) return 1;
525 if(!*sk) *sk = sk_new(sk_strcmp);
526 if(!*sk) return 0;
527 /* Don't add duplicates */
528 if(sk_find(*sk, (char *)email->data) != -1) return 1;
529 emtmp = BUF_strdup((char *)email->data);
530 if(!emtmp || !sk_push(*sk, emtmp)) {
531 X509_email_free(*sk);
532 *sk = NULL;
533 return 0;
534 }
535 return 1;
536}
537
538void X509_email_free(STACK *sk)
539{
540 sk_pop_free(sk, str_free);
541}
4e5d3a7f
DSH
542
543/* Convert IP addresses both IPv4 and IPv6 into an
544 * OCTET STRING compatible with RFC3280.
545 */
546
547ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
548 {
549 unsigned char ipout[16];
550 ASN1_OCTET_STRING *ret;
551 int iplen;
552
553 /* If string contains a ':' assume IPv6 */
554
555 if (strchr(ipasc, ':'))
556 {
557 if (!ipv6_from_asc(ipout, ipasc))
558 return NULL;
559 iplen = 16;
560 }
561 else
562 {
563 if (!ipv4_from_asc(ipout, ipasc))
564 return NULL;
565 iplen = 4;
566 }
567
568 ret = ASN1_OCTET_STRING_new();
569 if (!ret)
570 return NULL;
571 if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
572 {
573 ASN1_OCTET_STRING_free(ret);
574 return NULL;
575 }
576 return ret;
577 }
578
579static int ipv4_from_asc(unsigned char *v4, const char *in)
580 {
581 int a0, a1, a2, a3;
582 if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
583 return 0;
584 if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
585 || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
586 return 0;
587 v4[0] = a0;
588 v4[1] = a1;
589 v4[2] = a2;
590 v4[3] = a3;
591 return 1;
592 }
593
594typedef struct {
595 /* Temporary store for IPV6 output */
596 unsigned char tmp[16];
597 /* Total number of bytes in tmp */
598 int total;
599 /* The position of a zero (corresponding to '::') */
600 int zero_pos;
601 /* Number of zeroes */
602 int zero_cnt;
603 } IPV6_STAT;
604
605
606static int ipv6_from_asc(unsigned char *v6, const char *in)
607 {
608 IPV6_STAT v6stat;
609 v6stat.total = 0;
610 v6stat.zero_pos = -1;
611 v6stat.zero_cnt = 0;
612 /* Treat the IPv6 representation as a list of values
613 * separated by ':'. The presence of a '::' will parse
614 * as one, two or three zero length elements.
615 */
616 if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
617 return 0;
618
619 /* Now for some sanity checks */
620
621 if (v6stat.zero_pos == -1)
622 {
623 /* If no '::' must have exactly 16 bytes */
624 if (v6stat.total != 16)
625 return 0;
626 }
627 else
628 {
629 /* If '::' must have less than 16 bytes */
630 if (v6stat.total == 16)
631 return 0;
632 /* More than three zeroes is an error */
633 if (v6stat.zero_cnt > 3)
634 return 0;
635 /* Can only have three zeroes if nothing else present */
636 else if (v6stat.zero_cnt == 3)
637 {
638 if (v6stat.total > 0)
639 return 0;
640 }
641 /* Can only have two zeroes if at start or end */
642 else if (v6stat.zero_cnt == 2)
643 {
644 if ((v6stat.zero_pos != 0)
645 && (v6stat.zero_pos != v6stat.total))
646 return 0;
647 }
648 else
649 /* Can only have one zero if *not* start or end */
650 {
651 if ((v6stat.zero_pos == 0)
652 || (v6stat.zero_pos == v6stat.total))
653 return 0;
654 }
655 }
656
657 /* Format result */
658
659 /* Copy initial part */
660 if (v6stat.zero_pos > 0)
661 memcpy(v6, v6stat.tmp, v6stat.zero_pos);
662 /* Zero middle */
663 if (v6stat.total != 16)
664 memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
665 /* Copy final part */
666 if (v6stat.total != v6stat.zero_pos)
667 memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
668 v6stat.tmp + v6stat.zero_pos,
669 v6stat.total - v6stat.zero_pos);
670
671 return 1;
672 }
673
674static int ipv6_cb(const char *elem, int len, void *usr)
675 {
676 IPV6_STAT *s = usr;
677 /* Error if 16 bytes written */
678 if (s->total == 16)
679 return 0;
680 if (len == 0)
681 {
682 /* Zero length element, corresponds to '::' */
683 if (s->zero_pos == -1)
684 s->zero_pos = s->total;
685 /* If we've already got a :: its an error */
686 else if (s->zero_pos != s->total)
687 return 0;
688 s->zero_cnt++;
689 }
690 else
691 {
692 /* If more than 4 characters could be final a.b.c.d form */
693 if (len > 4)
694 {
695 /* Need at least 4 bytes left */
696 if (s->total > 12)
697 return 0;
698 /* Must be end of string */
699 if (elem[len])
700 return 0;
701 if (!ipv4_from_asc(s->tmp + s->total, elem))
702 return 0;
703 s->total += 4;
704 }
705 else
706 {
707 if (!ipv6_hex(s->tmp + s->total, elem, len))
708 return 0;
709 s->total += 2;
710 }
711 }
712 return 1;
713 }
714
715/* Convert a string of up to 4 hex digits into the corresponding
716 * IPv6 form.
717 */
718
719static int ipv6_hex(unsigned char *out, const char *in, int inlen)
720 {
721 unsigned char c;
722 unsigned int num = 0;
723 if (inlen > 4)
724 return 0;
725 while(inlen--)
726 {
727 c = *in++;
728 num <<= 4;
729 if ((c >= '0') && (c <= '9'))
730 num |= c - '0';
731 else if ((c >= 'A') && (c <= 'F'))
732 num |= c - 'A' + 10;
733 else if ((c >= 'a') && (c <= 'f'))
734 num |= c - 'a' + 10;
735 else
736 return 0;
737 }
738 out[0] = num >> 8;
739 out[1] = num & 0xff;
740 return 1;
741 }
742