ssl/libcrypto/src/crypto/x509v3/v3_utl.c
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 	}