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