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 + }