os/ossrv/ssl/libcrypto/src/crypto/x509v3/v3_utl.c
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/x509v3/v3_utl.c	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,858 @@
     1.4 +/* v3_utl.c */
     1.5 +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
     1.6 + * project.
     1.7 + */
     1.8 +/* ====================================================================
     1.9 + * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
    1.10 + *
    1.11 + * Redistribution and use in source and binary forms, with or without
    1.12 + * modification, are permitted provided that the following conditions
    1.13 + * are met:
    1.14 + *
    1.15 + * 1. Redistributions of source code must retain the above copyright
    1.16 + *    notice, this list of conditions and the following disclaimer. 
    1.17 + *
    1.18 + * 2. Redistributions in binary form must reproduce the above copyright
    1.19 + *    notice, this list of conditions and the following disclaimer in
    1.20 + *    the documentation and/or other materials provided with the
    1.21 + *    distribution.
    1.22 + *
    1.23 + * 3. All advertising materials mentioning features or use of this
    1.24 + *    software must display the following acknowledgment:
    1.25 + *    "This product includes software developed by the OpenSSL Project
    1.26 + *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
    1.27 + *
    1.28 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
    1.29 + *    endorse or promote products derived from this software without
    1.30 + *    prior written permission. For written permission, please contact
    1.31 + *    licensing@OpenSSL.org.
    1.32 + *
    1.33 + * 5. Products derived from this software may not be called "OpenSSL"
    1.34 + *    nor may "OpenSSL" appear in their names without prior written
    1.35 + *    permission of the OpenSSL Project.
    1.36 + *
    1.37 + * 6. Redistributions of any form whatsoever must retain the following
    1.38 + *    acknowledgment:
    1.39 + *    "This product includes software developed by the OpenSSL Project
    1.40 + *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
    1.41 + *
    1.42 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
    1.43 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.44 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    1.45 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
    1.46 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    1.47 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    1.48 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
    1.49 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    1.50 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
    1.51 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.52 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
    1.53 + * OF THE POSSIBILITY OF SUCH DAMAGE.
    1.54 + * ====================================================================
    1.55 + *
    1.56 + * This product includes cryptographic software written by Eric Young
    1.57 + * (eay@cryptsoft.com).  This product includes software written by Tim
    1.58 + * Hudson (tjh@cryptsoft.com).
    1.59 + *
    1.60 + */
    1.61 + /*
    1.62 + © Portions copyright (c) 2006 Nokia Corporation.  All rights reserved.
    1.63 + */
    1.64 +
    1.65 +
    1.66 +/* X509 v3 extension utilities */
    1.67 +
    1.68 +
    1.69 +#include <stdio.h>
    1.70 +#include <ctype.h>
    1.71 +#include "cryptlib.h"
    1.72 +#include <openssl/conf.h>
    1.73 +#include <openssl/x509v3.h>
    1.74 +#include <openssl/bn.h>
    1.75 +#if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__)))
    1.76 +#include "libcrypto_wsd_macros.h"
    1.77 +#include "libcrypto_wsd.h"
    1.78 +#endif
    1.79 +
    1.80 +static char *strip_spaces(char *name);
    1.81 +static int sk_strcmp(const char * const *a, const char * const *b);
    1.82 +static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens);
    1.83 +static void str_free(void *str);
    1.84 +static int append_ia5(STACK **sk, ASN1_IA5STRING *email);
    1.85 +
    1.86 +static int ipv4_from_asc(unsigned char *v4, const char *in);
    1.87 +static int ipv6_from_asc(unsigned char *v6, const char *in);
    1.88 +static int ipv6_cb(const char *elem, int len, void *usr);
    1.89 +static int ipv6_hex(unsigned char *out, const char *in, int inlen);
    1.90 +
    1.91 +/* Add a CONF_VALUE name value pair to stack */
    1.92 +
    1.93 +EXPORT_C int X509V3_add_value(const char *name, const char *value,
    1.94 +						STACK_OF(CONF_VALUE) **extlist)
    1.95 +{
    1.96 +	CONF_VALUE *vtmp = NULL;
    1.97 +	char *tname = NULL, *tvalue = NULL;
    1.98 +	if(name && !(tname = BUF_strdup(name))) goto err;
    1.99 +	if(value && !(tvalue = BUF_strdup(value))) goto err;;
   1.100 +	if(!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) goto err;
   1.101 +	if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
   1.102 +	vtmp->section = NULL;
   1.103 +	vtmp->name = tname;
   1.104 +	vtmp->value = tvalue;
   1.105 +	if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
   1.106 +	return 1;
   1.107 +	err:
   1.108 +	X509V3err(X509V3_F_X509V3_ADD_VALUE,ERR_R_MALLOC_FAILURE);
   1.109 +	if(vtmp) OPENSSL_free(vtmp);
   1.110 +	if(tname) OPENSSL_free(tname);
   1.111 +	if(tvalue) OPENSSL_free(tvalue);
   1.112 +	return 0;
   1.113 +}
   1.114 +
   1.115 +EXPORT_C int X509V3_add_value_uchar(const char *name, const unsigned char *value,
   1.116 +			   STACK_OF(CONF_VALUE) **extlist)
   1.117 +    {
   1.118 +    return X509V3_add_value(name,(const char *)value,extlist);
   1.119 +    }
   1.120 +
   1.121 +/* Free function for STACK_OF(CONF_VALUE) */
   1.122 +
   1.123 +EXPORT_C void X509V3_conf_free(CONF_VALUE *conf)
   1.124 +{
   1.125 +	if(!conf) return;
   1.126 +	if(conf->name) OPENSSL_free(conf->name);
   1.127 +	if(conf->value) OPENSSL_free(conf->value);
   1.128 +	if(conf->section) OPENSSL_free(conf->section);
   1.129 +	OPENSSL_free(conf);
   1.130 +}
   1.131 +
   1.132 +EXPORT_C int X509V3_add_value_bool(const char *name, int asn1_bool,
   1.133 +						STACK_OF(CONF_VALUE) **extlist)
   1.134 +{
   1.135 +	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
   1.136 +	return X509V3_add_value(name, "FALSE", extlist);
   1.137 +}
   1.138 +
   1.139 +EXPORT_C int X509V3_add_value_bool_nf(char *name, int asn1_bool,
   1.140 +						STACK_OF(CONF_VALUE) **extlist)
   1.141 +{
   1.142 +	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
   1.143 +	return 1;
   1.144 +}
   1.145 +
   1.146 +
   1.147 +EXPORT_C char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
   1.148 +{
   1.149 +	BIGNUM *bntmp = NULL;
   1.150 +	char *strtmp = NULL;
   1.151 +	if(!a) return NULL;
   1.152 +	if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
   1.153 +	    !(strtmp = BN_bn2dec(bntmp)) )
   1.154 +		X509V3err(X509V3_F_I2S_ASN1_ENUMERATED,ERR_R_MALLOC_FAILURE);
   1.155 +	BN_free(bntmp);
   1.156 +	return strtmp;
   1.157 +}
   1.158 +
   1.159 +EXPORT_C char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
   1.160 +{
   1.161 +	BIGNUM *bntmp = NULL;
   1.162 +	char *strtmp = NULL;
   1.163 +	if(!a) return NULL;
   1.164 +	if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
   1.165 +	    !(strtmp = BN_bn2dec(bntmp)) )
   1.166 +		X509V3err(X509V3_F_I2S_ASN1_INTEGER,ERR_R_MALLOC_FAILURE);
   1.167 +	BN_free(bntmp);
   1.168 +	return strtmp;
   1.169 +}
   1.170 +
   1.171 +EXPORT_C ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
   1.172 +{
   1.173 +	BIGNUM *bn = NULL;
   1.174 +	ASN1_INTEGER *aint;
   1.175 +	int isneg, ishex;
   1.176 +	int ret;
   1.177 +	if (!value) {
   1.178 +		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE);
   1.179 +		return 0;
   1.180 +	}
   1.181 +	bn = BN_new();
   1.182 +	if (value[0] == '-') {
   1.183 +		value++;
   1.184 +		isneg = 1;
   1.185 +	} else isneg = 0;
   1.186 +
   1.187 +	if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
   1.188 +		value += 2;
   1.189 +		ishex = 1;
   1.190 +	} else ishex = 0;
   1.191 +
   1.192 +	if (ishex) ret = BN_hex2bn(&bn, value);
   1.193 +	else ret = BN_dec2bn(&bn, value);
   1.194 +
   1.195 +	if (!ret || value[ret]) {
   1.196 +		BN_free(bn);
   1.197 +		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR);
   1.198 +		return 0;
   1.199 +	}
   1.200 +
   1.201 +	if (isneg && BN_is_zero(bn)) isneg = 0;
   1.202 +
   1.203 +	aint = BN_to_ASN1_INTEGER(bn, NULL);
   1.204 +	BN_free(bn);
   1.205 +	if (!aint) {
   1.206 +		X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
   1.207 +		return 0;
   1.208 +	}
   1.209 +	if (isneg) aint->type |= V_ASN1_NEG;
   1.210 +	return aint;
   1.211 +}
   1.212 +
   1.213 +EXPORT_C int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
   1.214 +	     STACK_OF(CONF_VALUE) **extlist)
   1.215 +{
   1.216 +	char *strtmp;
   1.217 +	int ret;
   1.218 +	if(!aint) return 1;
   1.219 +	if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
   1.220 +	ret = X509V3_add_value(name, strtmp, extlist);
   1.221 +	OPENSSL_free(strtmp);
   1.222 +	return ret;
   1.223 +}
   1.224 +
   1.225 +EXPORT_C int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
   1.226 +{
   1.227 +	char *btmp;
   1.228 +	if(!(btmp = value->value)) goto err;
   1.229 +	if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
   1.230 +		 || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
   1.231 +		|| !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
   1.232 +		*asn1_bool = 0xff;
   1.233 +		return 1;
   1.234 +	} else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
   1.235 +		 || !strcmp(btmp, "N") || !strcmp(btmp, "n")
   1.236 +		|| !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
   1.237 +		*asn1_bool = 0;
   1.238 +		return 1;
   1.239 +	}
   1.240 +	err:
   1.241 +	X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL,X509V3_R_INVALID_BOOLEAN_STRING);
   1.242 +	X509V3_conf_err(value);
   1.243 +	return 0;
   1.244 +}
   1.245 +
   1.246 +EXPORT_C int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
   1.247 +{
   1.248 +	ASN1_INTEGER *itmp;
   1.249 +	if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
   1.250 +		X509V3_conf_err(value);
   1.251 +		return 0;
   1.252 +	}
   1.253 +	*aint = itmp;
   1.254 +	return 1;
   1.255 +}
   1.256 +
   1.257 +#define HDR_NAME	1
   1.258 +#define HDR_VALUE	2
   1.259 +
   1.260 +/*#define DEBUG*/
   1.261 +
   1.262 +EXPORT_C STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
   1.263 +{
   1.264 +	char *p, *q, c;
   1.265 +	char *ntmp, *vtmp;
   1.266 +	STACK_OF(CONF_VALUE) *values = NULL;
   1.267 +	char *linebuf;
   1.268 +	int state;
   1.269 +	/* We are going to modify the line so copy it first */
   1.270 +	linebuf = BUF_strdup(line);
   1.271 +	state = HDR_NAME;
   1.272 +	ntmp = NULL;
   1.273 +	/* Go through all characters */
   1.274 +	for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
   1.275 +
   1.276 +		switch(state) {
   1.277 +			case HDR_NAME:
   1.278 +			if(c == ':') {
   1.279 +				state = HDR_VALUE;
   1.280 +				*p = 0;
   1.281 +				ntmp = strip_spaces(q);
   1.282 +				if(!ntmp) {
   1.283 +					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
   1.284 +					goto err;
   1.285 +				}
   1.286 +				q = p + 1;
   1.287 +			} else if(c == ',') {
   1.288 +				*p = 0;
   1.289 +				ntmp = strip_spaces(q);
   1.290 +				q = p + 1;
   1.291 +#if 0
   1.292 +				printf("%s\n", ntmp);
   1.293 +#endif
   1.294 +				if(!ntmp) {
   1.295 +					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
   1.296 +					goto err;
   1.297 +				}
   1.298 +				X509V3_add_value(ntmp, NULL, &values);
   1.299 +			}
   1.300 +			break ;
   1.301 +
   1.302 +			case HDR_VALUE:
   1.303 +			if(c == ',') {
   1.304 +				state = HDR_NAME;
   1.305 +				*p = 0;
   1.306 +				vtmp = strip_spaces(q);
   1.307 +#if 0
   1.308 +				printf("%s\n", ntmp);
   1.309 +#endif
   1.310 +				if(!vtmp) {
   1.311 +					X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
   1.312 +					goto err;
   1.313 +				}
   1.314 +				X509V3_add_value(ntmp, vtmp, &values);
   1.315 +				ntmp = NULL;
   1.316 +				q = p + 1;
   1.317 +			}
   1.318 +
   1.319 +		}
   1.320 +	}
   1.321 +
   1.322 +	if(state == HDR_VALUE) {
   1.323 +		vtmp = strip_spaces(q);
   1.324 +#if 0
   1.325 +		printf("%s=%s\n", ntmp, vtmp);
   1.326 +#endif
   1.327 +		if(!vtmp) {
   1.328 +			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_VALUE);
   1.329 +			goto err;
   1.330 +		}
   1.331 +		X509V3_add_value(ntmp, vtmp, &values);
   1.332 +	} else {
   1.333 +		ntmp = strip_spaces(q);
   1.334 +#if 0
   1.335 +		printf("%s\n", ntmp);
   1.336 +#endif
   1.337 +		if(!ntmp) {
   1.338 +			X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME);
   1.339 +			goto err;
   1.340 +		}
   1.341 +		X509V3_add_value(ntmp, NULL, &values);
   1.342 +	}
   1.343 +OPENSSL_free(linebuf);
   1.344 +return values;
   1.345 +
   1.346 +err:
   1.347 +OPENSSL_free(linebuf);
   1.348 +sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
   1.349 +return NULL;
   1.350 +
   1.351 +}
   1.352 +
   1.353 +/* Delete leading and trailing spaces from a string */
   1.354 +static char *strip_spaces(char *name)
   1.355 +{
   1.356 +	char *p, *q;
   1.357 +	/* Skip over leading spaces */
   1.358 +	p = name;
   1.359 +	while(*p && isspace((unsigned char)*p)) p++;
   1.360 +	if(!*p) return NULL;
   1.361 +	q = p + strlen(p) - 1;
   1.362 +	while((q != p) && isspace((unsigned char)*q)) q--;
   1.363 +	if(p != q) q[1] = 0;
   1.364 +	if(!*p) return NULL;
   1.365 +	return p;
   1.366 +}
   1.367 +
   1.368 +/* hex string utilities */
   1.369 +
   1.370 +/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
   1.371 + * hex representation
   1.372 + * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
   1.373 + */
   1.374 + 
   1.375 +
   1.376 +EXPORT_C char *hex_to_string(unsigned char *buffer, long len)
   1.377 +{
   1.378 +	char *tmp, *q;
   1.379 +	unsigned char *p;
   1.380 +	int i;
   1.381 +#ifndef EMULATOR	
   1.382 +	static char hexdig[] = "0123456789ABCDEF";
   1.383 +#else
   1.384 +    static const char hexdig[] = "0123456789ABCDEF";
   1.385 +#endif	
   1.386 +	if(!buffer || !len) return NULL;
   1.387 +	if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
   1.388 +		X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE);
   1.389 +		return NULL;
   1.390 +	}
   1.391 +	q = tmp;
   1.392 +	for(i = 0, p = buffer; i < len; i++,p++) {
   1.393 +		*q++ = hexdig[(*p >> 4) & 0xf];
   1.394 +		*q++ = hexdig[*p & 0xf];
   1.395 +		*q++ = ':';
   1.396 +	}
   1.397 +	q[-1] = 0;
   1.398 +#ifdef CHARSET_EBCDIC
   1.399 +	ebcdic2ascii(tmp, tmp, q - tmp - 1);
   1.400 +#endif
   1.401 +
   1.402 +	return tmp;
   1.403 +}
   1.404 +
   1.405 +/* Give a string of hex digits convert to
   1.406 + * a buffer
   1.407 + */
   1.408 +
   1.409 +EXPORT_C unsigned char *string_to_hex(char *str, long *len)
   1.410 +{
   1.411 +	unsigned char *hexbuf, *q;
   1.412 +	unsigned char ch, cl, *p;
   1.413 +	if(!str) {
   1.414 +		X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_INVALID_NULL_ARGUMENT);
   1.415 +		return NULL;
   1.416 +	}
   1.417 +	if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
   1.418 +	for(p = (unsigned char *)str, q = hexbuf; *p;) {
   1.419 +		ch = *p++;
   1.420 +#ifdef CHARSET_EBCDIC
   1.421 +		ch = os_toebcdic[ch];
   1.422 +#endif
   1.423 +		if(ch == ':') continue;
   1.424 +		cl = *p++;
   1.425 +#ifdef CHARSET_EBCDIC
   1.426 +		cl = os_toebcdic[cl];
   1.427 +#endif
   1.428 +		if(!cl) {
   1.429 +			X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ODD_NUMBER_OF_DIGITS);
   1.430 +			OPENSSL_free(hexbuf);
   1.431 +			return NULL;
   1.432 +		}
   1.433 +		if(isupper(ch)) ch = tolower(ch);
   1.434 +		if(isupper(cl)) cl = tolower(cl);
   1.435 +
   1.436 +		if((ch >= '0') && (ch <= '9')) ch -= '0';
   1.437 +		else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
   1.438 +		else goto badhex;
   1.439 +
   1.440 +		if((cl >= '0') && (cl <= '9')) cl -= '0';
   1.441 +		else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
   1.442 +		else goto badhex;
   1.443 +
   1.444 +		*q++ = (ch << 4) | cl;
   1.445 +	}
   1.446 +
   1.447 +	if(len) *len = q - hexbuf;
   1.448 +
   1.449 +	return hexbuf;
   1.450 +
   1.451 +	err:
   1.452 +	if(hexbuf) OPENSSL_free(hexbuf);
   1.453 +	X509V3err(X509V3_F_STRING_TO_HEX,ERR_R_MALLOC_FAILURE);
   1.454 +	return NULL;
   1.455 +
   1.456 +	badhex:
   1.457 +	OPENSSL_free(hexbuf);
   1.458 +	X509V3err(X509V3_F_STRING_TO_HEX,X509V3_R_ILLEGAL_HEX_DIGIT);
   1.459 +	return NULL;
   1.460 +
   1.461 +}
   1.462 +
   1.463 +/* V2I name comparison function: returns zero if 'name' matches
   1.464 + * cmp or cmp.*
   1.465 + */
   1.466 +
   1.467 +EXPORT_C int name_cmp(const char *name, const char *cmp)
   1.468 +{
   1.469 +	int len, ret;
   1.470 +	char c;
   1.471 +	len = strlen(cmp);
   1.472 +	if((ret = strncmp(name, cmp, len))) return ret;
   1.473 +	c = name[len];
   1.474 +	if(!c || (c=='.')) return 0;
   1.475 +	return 1;
   1.476 +}
   1.477 +
   1.478 +static int sk_strcmp(const char * const *a, const char * const *b)
   1.479 +{
   1.480 +	return strcmp(*a, *b);
   1.481 +}
   1.482 +
   1.483 +EXPORT_C STACK *X509_get1_email(X509 *x)
   1.484 +{
   1.485 +	GENERAL_NAMES *gens;
   1.486 +	STACK *ret;
   1.487 +	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
   1.488 +	ret = get_email(X509_get_subject_name(x), gens);
   1.489 +	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
   1.490 +	return ret;
   1.491 +}
   1.492 +
   1.493 +EXPORT_C STACK *X509_REQ_get1_email(X509_REQ *x)
   1.494 +{
   1.495 +	GENERAL_NAMES *gens;
   1.496 +	STACK_OF(X509_EXTENSION) *exts;
   1.497 +	STACK *ret;
   1.498 +	exts = X509_REQ_get_extensions(x);
   1.499 +	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
   1.500 +	ret = get_email(X509_REQ_get_subject_name(x), gens);
   1.501 +	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
   1.502 +	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
   1.503 +	return ret;
   1.504 +}
   1.505 +
   1.506 +
   1.507 +static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens)
   1.508 +{
   1.509 +	STACK *ret = NULL;
   1.510 +	X509_NAME_ENTRY *ne;
   1.511 +	ASN1_IA5STRING *email;
   1.512 +	GENERAL_NAME *gen;
   1.513 +	int i;
   1.514 +	/* Now add any email address(es) to STACK */
   1.515 +	i = -1;
   1.516 +	/* First supplied X509_NAME */
   1.517 +	while((i = X509_NAME_get_index_by_NID(name,
   1.518 +					 NID_pkcs9_emailAddress, i)) >= 0) {
   1.519 +		ne = X509_NAME_get_entry(name, i);
   1.520 +		email = X509_NAME_ENTRY_get_data(ne);
   1.521 +		if(!append_ia5(&ret, email)) return NULL;
   1.522 +	}
   1.523 +	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
   1.524 +	{
   1.525 +		gen = sk_GENERAL_NAME_value(gens, i);
   1.526 +		if(gen->type != GEN_EMAIL) continue;
   1.527 +		if(!append_ia5(&ret, gen->d.ia5)) return NULL;
   1.528 +	}
   1.529 +	return ret;
   1.530 +}
   1.531 +
   1.532 +static void str_free(void *str)
   1.533 +{
   1.534 +	OPENSSL_free(str);
   1.535 +}
   1.536 +
   1.537 +static int append_ia5(STACK **sk, ASN1_IA5STRING *email)
   1.538 +{
   1.539 +	char *emtmp;
   1.540 +	/* First some sanity checks */
   1.541 +	if(email->type != V_ASN1_IA5STRING) return 1;
   1.542 +	if(!email->data || !email->length) return 1;
   1.543 +	if(!*sk) *sk = sk_new(sk_strcmp);
   1.544 +	if(!*sk) return 0;
   1.545 +	/* Don't add duplicates */
   1.546 +	if(sk_find(*sk, (char *)email->data) != -1) return 1;
   1.547 +	emtmp = BUF_strdup((char *)email->data);
   1.548 +	if(!emtmp || !sk_push(*sk, emtmp)) {
   1.549 +		X509_email_free(*sk);
   1.550 +		*sk = NULL;
   1.551 +		return 0;
   1.552 +	}
   1.553 +	return 1;
   1.554 +}
   1.555 +
   1.556 +EXPORT_C void X509_email_free(STACK *sk)
   1.557 +{
   1.558 +	sk_pop_free(sk, str_free);
   1.559 +}
   1.560 +
   1.561 +/* Convert IP addresses both IPv4 and IPv6 into an 
   1.562 + * OCTET STRING compatible with RFC3280.
   1.563 + */
   1.564 +
   1.565 +EXPORT_C ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
   1.566 +	{
   1.567 +	unsigned char ipout[16];
   1.568 +	ASN1_OCTET_STRING *ret;
   1.569 +	int iplen;
   1.570 +
   1.571 +	/* If string contains a ':' assume IPv6 */
   1.572 +
   1.573 +	iplen = a2i_ipadd(ipout, ipasc);
   1.574 +
   1.575 +	if (!iplen)
   1.576 +		return NULL;
   1.577 +
   1.578 +	ret = ASN1_OCTET_STRING_new();
   1.579 +	if (!ret)
   1.580 +		return NULL;
   1.581 +	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
   1.582 +		{
   1.583 +		ASN1_OCTET_STRING_free(ret);
   1.584 +		return NULL;
   1.585 +		}
   1.586 +	return ret;
   1.587 +	}
   1.588 +
   1.589 +EXPORT_C ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
   1.590 +	{
   1.591 +	ASN1_OCTET_STRING *ret = NULL;
   1.592 +	unsigned char ipout[32];
   1.593 +	char *iptmp = NULL, *p;
   1.594 +	int iplen1, iplen2;
   1.595 +	p = strchr(ipasc,'/');
   1.596 +	if (!p)
   1.597 +		return NULL;
   1.598 +	iptmp = BUF_strdup(ipasc);
   1.599 +	if (!iptmp)
   1.600 +		return NULL;
   1.601 +	p = iptmp + (p - ipasc);
   1.602 +	*p++ = 0;
   1.603 +
   1.604 +	iplen1 = a2i_ipadd(ipout, iptmp);
   1.605 +
   1.606 +	if (!iplen1)
   1.607 +		goto err;
   1.608 +
   1.609 +	iplen2 = a2i_ipadd(ipout + iplen1, p);
   1.610 +
   1.611 +	OPENSSL_free(iptmp);
   1.612 +	iptmp = NULL;
   1.613 +
   1.614 +	if (!iplen2 || (iplen1 != iplen2))
   1.615 +		goto err;
   1.616 +
   1.617 +	ret = ASN1_OCTET_STRING_new();
   1.618 +	if (!ret)
   1.619 +		goto err;
   1.620 +	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
   1.621 +		goto err;
   1.622 +
   1.623 +	return ret;
   1.624 +
   1.625 +	err:
   1.626 +	if (iptmp)
   1.627 +		OPENSSL_free(iptmp);
   1.628 +	if (ret)
   1.629 +		ASN1_OCTET_STRING_free(ret);
   1.630 +	return NULL;
   1.631 +	}
   1.632 +	
   1.633 +
   1.634 +EXPORT_C int a2i_ipadd(unsigned char *ipout, const char *ipasc)
   1.635 +	{
   1.636 +	/* If string contains a ':' assume IPv6 */
   1.637 +
   1.638 +	if (strchr(ipasc, ':'))
   1.639 +		{
   1.640 +		if (!ipv6_from_asc(ipout, ipasc))
   1.641 +			return 0;
   1.642 +		return 16;
   1.643 +		}
   1.644 +	else
   1.645 +		{
   1.646 +		if (!ipv4_from_asc(ipout, ipasc))
   1.647 +			return 0;
   1.648 +		return 4;
   1.649 +		}
   1.650 +	}
   1.651 +
   1.652 +static int ipv4_from_asc(unsigned char *v4, const char *in)
   1.653 +	{
   1.654 +	int a0, a1, a2, a3;
   1.655 +	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
   1.656 +		return 0;
   1.657 +	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
   1.658 +		|| (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
   1.659 +		return 0;
   1.660 +	v4[0] = a0;
   1.661 +	v4[1] = a1;
   1.662 +	v4[2] = a2;
   1.663 +	v4[3] = a3;
   1.664 +	return 1;
   1.665 +	}
   1.666 +
   1.667 +typedef struct {
   1.668 +		/* Temporary store for IPV6 output */
   1.669 +		unsigned char tmp[16];
   1.670 +		/* Total number of bytes in tmp */
   1.671 +		int total;
   1.672 +		/* The position of a zero (corresponding to '::') */
   1.673 +		int zero_pos;
   1.674 +		/* Number of zeroes */
   1.675 +		int zero_cnt;
   1.676 +	} IPV6_STAT;
   1.677 +
   1.678 +
   1.679 +static int ipv6_from_asc(unsigned char *v6, const char *in)
   1.680 +	{
   1.681 +	IPV6_STAT v6stat;
   1.682 +	v6stat.total = 0;
   1.683 +	v6stat.zero_pos = -1;
   1.684 +	v6stat.zero_cnt = 0;
   1.685 +	/* Treat the IPv6 representation as a list of values
   1.686 +	 * separated by ':'. The presence of a '::' will parse
   1.687 + 	 * as one, two or three zero length elements.
   1.688 +	 */
   1.689 +	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
   1.690 +		return 0;
   1.691 +
   1.692 +	/* Now for some sanity checks */
   1.693 +
   1.694 +	if (v6stat.zero_pos == -1)
   1.695 +		{
   1.696 +		/* If no '::' must have exactly 16 bytes */
   1.697 +		if (v6stat.total != 16)
   1.698 +			return 0;
   1.699 +		}
   1.700 +	else 
   1.701 +		{
   1.702 +		/* If '::' must have less than 16 bytes */
   1.703 +		if (v6stat.total == 16)
   1.704 +			return 0;
   1.705 +		/* More than three zeroes is an error */
   1.706 +		if (v6stat.zero_cnt > 3)
   1.707 +			return 0;
   1.708 +		/* Can only have three zeroes if nothing else present */
   1.709 +		else if (v6stat.zero_cnt == 3)
   1.710 +			{
   1.711 +			if (v6stat.total > 0)
   1.712 +				return 0;
   1.713 +			}
   1.714 +		/* Can only have two zeroes if at start or end */
   1.715 +		else if (v6stat.zero_cnt == 2)
   1.716 +			{
   1.717 +			if ((v6stat.zero_pos != 0)
   1.718 +				&& (v6stat.zero_pos != v6stat.total))
   1.719 +				return 0;
   1.720 +			}
   1.721 +		else 
   1.722 +		/* Can only have one zero if *not* start or end */
   1.723 +			{
   1.724 +			if ((v6stat.zero_pos == 0)
   1.725 +				|| (v6stat.zero_pos == v6stat.total))
   1.726 +				return 0;
   1.727 +			}
   1.728 +		}
   1.729 +
   1.730 +	/* Format result */
   1.731 +
   1.732 +	/* Copy initial part */
   1.733 +	if (v6stat.zero_pos > 0)
   1.734 +		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
   1.735 +	/* Zero middle */
   1.736 +	if (v6stat.total != 16)
   1.737 +		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
   1.738 +	/* Copy final part */
   1.739 +	if (v6stat.total != v6stat.zero_pos)
   1.740 +		memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
   1.741 +			v6stat.tmp + v6stat.zero_pos,
   1.742 +			v6stat.total - v6stat.zero_pos);
   1.743 +
   1.744 +	return 1;
   1.745 +	}
   1.746 +
   1.747 +static int ipv6_cb(const char *elem, int len, void *usr)
   1.748 +	{
   1.749 +	IPV6_STAT *s = usr;
   1.750 +	/* Error if 16 bytes written */
   1.751 +	if (s->total == 16)
   1.752 +		return 0;
   1.753 +	if (len == 0)
   1.754 +		{
   1.755 +		/* Zero length element, corresponds to '::' */
   1.756 +		if (s->zero_pos == -1)
   1.757 +			s->zero_pos = s->total;
   1.758 +		/* If we've already got a :: its an error */
   1.759 +		else if (s->zero_pos != s->total)
   1.760 +			return 0;
   1.761 +		s->zero_cnt++;
   1.762 +		}
   1.763 +	else 
   1.764 +		{
   1.765 +		/* If more than 4 characters could be final a.b.c.d form */
   1.766 +		if (len > 4)
   1.767 +			{
   1.768 +			/* Need at least 4 bytes left */
   1.769 +			if (s->total > 12)
   1.770 +				return 0;
   1.771 +			/* Must be end of string */
   1.772 +			if (elem[len])
   1.773 +				return 0;
   1.774 +			if (!ipv4_from_asc(s->tmp + s->total, elem))
   1.775 +				return 0;
   1.776 +			s->total += 4;
   1.777 +			}
   1.778 +		else
   1.779 +			{
   1.780 +			if (!ipv6_hex(s->tmp + s->total, elem, len))
   1.781 +				return 0;
   1.782 +			s->total += 2;
   1.783 +			}
   1.784 +		}
   1.785 +	return 1;
   1.786 +	}
   1.787 +
   1.788 +/* Convert a string of up to 4 hex digits into the corresponding
   1.789 + * IPv6 form.
   1.790 + */
   1.791 +
   1.792 +static int ipv6_hex(unsigned char *out, const char *in, int inlen)
   1.793 +	{
   1.794 +	unsigned char c;
   1.795 +	unsigned int num = 0;
   1.796 +	if (inlen > 4)
   1.797 +		return 0;
   1.798 +	while(inlen--)
   1.799 +		{
   1.800 +		c = *in++;
   1.801 +		num <<= 4;
   1.802 +		if ((c >= '0') && (c <= '9'))
   1.803 +			num |= c - '0';
   1.804 +		else if ((c >= 'A') && (c <= 'F'))
   1.805 +			num |= c - 'A' + 10;
   1.806 +		else if ((c >= 'a') && (c <= 'f'))
   1.807 +			num |=  c - 'a' + 10;
   1.808 +		else
   1.809 +			return 0;
   1.810 +		}
   1.811 +	out[0] = num >> 8;
   1.812 +	out[1] = num & 0xff;
   1.813 +	return 1;
   1.814 +	}
   1.815 +
   1.816 +
   1.817 +EXPORT_C int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
   1.818 +						unsigned long chtype)
   1.819 +	{
   1.820 +	CONF_VALUE *v;
   1.821 +	int i, mval;
   1.822 +	char *p, *type;
   1.823 +	if (!nm)
   1.824 +		return 0;
   1.825 +
   1.826 +	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
   1.827 +		{
   1.828 +		v=sk_CONF_VALUE_value(dn_sk,i);
   1.829 +		type=v->name;
   1.830 +		/* Skip past any leading X. X: X, etc to allow for
   1.831 +		 * multiple instances 
   1.832 +		 */
   1.833 +		for(p = type; *p ; p++) 
   1.834 +#ifndef CHARSET_EBCDIC
   1.835 +			if ((*p == ':') || (*p == ',') || (*p == '.'))
   1.836 +#else
   1.837 +			if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.']))
   1.838 +#endif
   1.839 +				{
   1.840 +				p++;
   1.841 +				if(*p) type = p;
   1.842 +				break;
   1.843 +				}
   1.844 +#ifndef CHARSET_EBCDIC
   1.845 +		if (*type == '+')
   1.846 +#else
   1.847 +		if (*type == os_toascii['+'])
   1.848 +#endif
   1.849 +			{
   1.850 +			mval = -1;
   1.851 +			type++;
   1.852 +			}
   1.853 +		else
   1.854 +			mval = 0;
   1.855 +		if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
   1.856 +				(unsigned char *) v->value,-1,-1,mval))
   1.857 +					return 0;
   1.858 +
   1.859 +		}
   1.860 +	return 1;
   1.861 +	}