155714Skris/* v3_utl.c */ 2296465Sdelphij/* 3296465Sdelphij * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 4160814Ssimon * project. 555714Skris */ 655714Skris/* ==================================================================== 7160814Ssimon * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 855714Skris * 955714Skris * Redistribution and use in source and binary forms, with or without 1055714Skris * modification, are permitted provided that the following conditions 1155714Skris * are met: 1255714Skris * 1355714Skris * 1. Redistributions of source code must retain the above copyright 14296465Sdelphij * notice, this list of conditions and the following disclaimer. 1555714Skris * 1655714Skris * 2. Redistributions in binary form must reproduce the above copyright 1755714Skris * notice, this list of conditions and the following disclaimer in 1855714Skris * the documentation and/or other materials provided with the 1955714Skris * distribution. 2055714Skris * 2155714Skris * 3. All advertising materials mentioning features or use of this 2255714Skris * software must display the following acknowledgment: 2355714Skris * "This product includes software developed by the OpenSSL Project 2455714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2555714Skris * 2655714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2755714Skris * endorse or promote products derived from this software without 2855714Skris * prior written permission. For written permission, please contact 2955714Skris * licensing@OpenSSL.org. 3055714Skris * 3155714Skris * 5. Products derived from this software may not be called "OpenSSL" 3255714Skris * nor may "OpenSSL" appear in their names without prior written 3355714Skris * permission of the OpenSSL Project. 3455714Skris * 3555714Skris * 6. Redistributions of any form whatsoever must retain the following 3655714Skris * acknowledgment: 3755714Skris * "This product includes software developed by the OpenSSL Project 3855714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3955714Skris * 4055714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4155714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4255714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4355714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4455714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4555714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4655714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4755714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4855714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4955714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5055714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5155714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5255714Skris * ==================================================================== 5355714Skris * 5455714Skris * This product includes cryptographic software written by Eric Young 5555714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5655714Skris * Hudson (tjh@cryptsoft.com). 5755714Skris * 5855714Skris */ 5955714Skris/* X509 v3 extension utilities */ 6055714Skris 6155714Skris#include <stdio.h> 6255714Skris#include <ctype.h> 6355714Skris#include "cryptlib.h" 6455714Skris#include <openssl/conf.h> 6555714Skris#include <openssl/x509v3.h> 66160814Ssimon#include <openssl/bn.h> 6755714Skris 6855714Skrisstatic char *strip_spaces(char *name); 69296465Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b); 70109998Smarkmstatic STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); 7168651Skrisstatic void str_free(void *str); 72296465Sdelphijstatic int append_ia5(STACK ** sk, ASN1_IA5STRING *email); 7355714Skris 74160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in); 75160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in); 76160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr); 77160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen); 78160814Ssimon 7955714Skris/* Add a CONF_VALUE name value pair to stack */ 8055714Skris 8155714Skrisint X509V3_add_value(const char *name, const char *value, 82296465Sdelphij STACK_OF(CONF_VALUE) **extlist) 8355714Skris{ 84296465Sdelphij CONF_VALUE *vtmp = NULL; 85296465Sdelphij char *tname = NULL, *tvalue = NULL; 86296465Sdelphij if (name && !(tname = BUF_strdup(name))) 87296465Sdelphij goto err; 88296465Sdelphij if (value && !(tvalue = BUF_strdup(value))) 89296465Sdelphij goto err; 90296465Sdelphij if (!(vtmp = (CONF_VALUE *)OPENSSL_malloc(sizeof(CONF_VALUE)))) 91296465Sdelphij goto err; 92296465Sdelphij if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) 93296465Sdelphij goto err; 94296465Sdelphij vtmp->section = NULL; 95296465Sdelphij vtmp->name = tname; 96296465Sdelphij vtmp->value = tvalue; 97296465Sdelphij if (!sk_CONF_VALUE_push(*extlist, vtmp)) 98296465Sdelphij goto err; 99296465Sdelphij return 1; 100296465Sdelphij err: 101296465Sdelphij X509V3err(X509V3_F_X509V3_ADD_VALUE, ERR_R_MALLOC_FAILURE); 102296465Sdelphij if (vtmp) 103296465Sdelphij OPENSSL_free(vtmp); 104296465Sdelphij if (tname) 105296465Sdelphij OPENSSL_free(tname); 106296465Sdelphij if (tvalue) 107296465Sdelphij OPENSSL_free(tvalue); 108296465Sdelphij return 0; 10955714Skris} 11055714Skris 11155714Skrisint X509V3_add_value_uchar(const char *name, const unsigned char *value, 112296465Sdelphij STACK_OF(CONF_VALUE) **extlist) 113296465Sdelphij{ 114296465Sdelphij return X509V3_add_value(name, (const char *)value, extlist); 115296465Sdelphij} 11655714Skris 11755714Skris/* Free function for STACK_OF(CONF_VALUE) */ 11855714Skris 11955714Skrisvoid X509V3_conf_free(CONF_VALUE *conf) 12055714Skris{ 121296465Sdelphij if (!conf) 122296465Sdelphij return; 123296465Sdelphij if (conf->name) 124296465Sdelphij OPENSSL_free(conf->name); 125296465Sdelphij if (conf->value) 126296465Sdelphij OPENSSL_free(conf->value); 127296465Sdelphij if (conf->section) 128296465Sdelphij OPENSSL_free(conf->section); 129296465Sdelphij OPENSSL_free(conf); 13055714Skris} 13155714Skris 13255714Skrisint X509V3_add_value_bool(const char *name, int asn1_bool, 133296465Sdelphij STACK_OF(CONF_VALUE) **extlist) 13455714Skris{ 135296465Sdelphij if (asn1_bool) 136296465Sdelphij return X509V3_add_value(name, "TRUE", extlist); 137296465Sdelphij return X509V3_add_value(name, "FALSE", extlist); 13855714Skris} 13955714Skris 14055714Skrisint X509V3_add_value_bool_nf(char *name, int asn1_bool, 141296465Sdelphij STACK_OF(CONF_VALUE) **extlist) 14255714Skris{ 143296465Sdelphij if (asn1_bool) 144296465Sdelphij return X509V3_add_value(name, "TRUE", extlist); 145296465Sdelphij return 1; 14655714Skris} 14755714Skris 14855714Skrischar *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a) 14955714Skris{ 150296465Sdelphij BIGNUM *bntmp = NULL; 151296465Sdelphij char *strtmp = NULL; 152296465Sdelphij if (!a) 153296465Sdelphij return NULL; 154296465Sdelphij if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) || 155296465Sdelphij !(strtmp = BN_bn2dec(bntmp))) 156296465Sdelphij X509V3err(X509V3_F_I2S_ASN1_ENUMERATED, ERR_R_MALLOC_FAILURE); 157296465Sdelphij BN_free(bntmp); 158296465Sdelphij return strtmp; 15955714Skris} 16055714Skris 16155714Skrischar *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a) 16255714Skris{ 163296465Sdelphij BIGNUM *bntmp = NULL; 164296465Sdelphij char *strtmp = NULL; 165296465Sdelphij if (!a) 166296465Sdelphij return NULL; 167296465Sdelphij if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) || 168296465Sdelphij !(strtmp = BN_bn2dec(bntmp))) 169296465Sdelphij X509V3err(X509V3_F_I2S_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); 170296465Sdelphij BN_free(bntmp); 171296465Sdelphij return strtmp; 17255714Skris} 17355714Skris 17455714SkrisASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) 17555714Skris{ 176296465Sdelphij BIGNUM *bn = NULL; 177296465Sdelphij ASN1_INTEGER *aint; 178296465Sdelphij int isneg, ishex; 179296465Sdelphij int ret; 180296465Sdelphij if (!value) { 181296465Sdelphij X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_INVALID_NULL_VALUE); 182296465Sdelphij return 0; 183296465Sdelphij } 184296465Sdelphij bn = BN_new(); 185296465Sdelphij if (value[0] == '-') { 186296465Sdelphij value++; 187296465Sdelphij isneg = 1; 188296465Sdelphij } else 189296465Sdelphij isneg = 0; 190109998Smarkm 191296465Sdelphij if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) { 192296465Sdelphij value += 2; 193296465Sdelphij ishex = 1; 194296465Sdelphij } else 195296465Sdelphij ishex = 0; 196109998Smarkm 197296465Sdelphij if (ishex) 198296465Sdelphij ret = BN_hex2bn(&bn, value); 199296465Sdelphij else 200296465Sdelphij ret = BN_dec2bn(&bn, value); 201109998Smarkm 202296465Sdelphij if (!ret || value[ret]) { 203296465Sdelphij BN_free(bn); 204296465Sdelphij X509V3err(X509V3_F_S2I_ASN1_INTEGER, X509V3_R_BN_DEC2BN_ERROR); 205296465Sdelphij return 0; 206296465Sdelphij } 20755714Skris 208296465Sdelphij if (isneg && BN_is_zero(bn)) 209296465Sdelphij isneg = 0; 210109998Smarkm 211296465Sdelphij aint = BN_to_ASN1_INTEGER(bn, NULL); 212296465Sdelphij BN_free(bn); 213296465Sdelphij if (!aint) { 214296465Sdelphij X509V3err(X509V3_F_S2I_ASN1_INTEGER, 215296465Sdelphij X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 216296465Sdelphij return 0; 217296465Sdelphij } 218296465Sdelphij if (isneg) 219296465Sdelphij aint->type |= V_ASN1_NEG; 220296465Sdelphij return aint; 22155714Skris} 22255714Skris 22355714Skrisint X509V3_add_value_int(const char *name, ASN1_INTEGER *aint, 224296465Sdelphij STACK_OF(CONF_VALUE) **extlist) 22555714Skris{ 226296465Sdelphij char *strtmp; 227296465Sdelphij int ret; 228296465Sdelphij if (!aint) 229296465Sdelphij return 1; 230296465Sdelphij if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 231296465Sdelphij return 0; 232296465Sdelphij ret = X509V3_add_value(name, strtmp, extlist); 233296465Sdelphij OPENSSL_free(strtmp); 234296465Sdelphij return ret; 23555714Skris} 23655714Skris 23755714Skrisint X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool) 23855714Skris{ 239296465Sdelphij char *btmp; 240296465Sdelphij if (!(btmp = value->value)) 241296465Sdelphij goto err; 242296465Sdelphij if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") 243296465Sdelphij || !strcmp(btmp, "Y") || !strcmp(btmp, "y") 244296465Sdelphij || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 245296465Sdelphij *asn1_bool = 0xff; 246296465Sdelphij return 1; 247296465Sdelphij } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") 248296465Sdelphij || !strcmp(btmp, "N") || !strcmp(btmp, "n") 249296465Sdelphij || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 250296465Sdelphij *asn1_bool = 0; 251296465Sdelphij return 1; 252296465Sdelphij } 253296465Sdelphij err: 254296465Sdelphij X509V3err(X509V3_F_X509V3_GET_VALUE_BOOL, 255296465Sdelphij X509V3_R_INVALID_BOOLEAN_STRING); 256296465Sdelphij X509V3_conf_err(value); 257296465Sdelphij return 0; 25855714Skris} 25955714Skris 26055714Skrisint X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint) 26155714Skris{ 262296465Sdelphij ASN1_INTEGER *itmp; 263296465Sdelphij if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 264296465Sdelphij X509V3_conf_err(value); 265296465Sdelphij return 0; 266296465Sdelphij } 267296465Sdelphij *aint = itmp; 268296465Sdelphij return 1; 26955714Skris} 27055714Skris 271296465Sdelphij#define HDR_NAME 1 272296465Sdelphij#define HDR_VALUE 2 27355714Skris 274296465Sdelphij/* 275296465Sdelphij * #define DEBUG 276296465Sdelphij */ 27755714Skris 278109998SmarkmSTACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line) 27955714Skris{ 280296465Sdelphij char *p, *q, c; 281296465Sdelphij char *ntmp, *vtmp; 282296465Sdelphij STACK_OF(CONF_VALUE) *values = NULL; 283296465Sdelphij char *linebuf; 284296465Sdelphij int state; 285296465Sdelphij /* We are going to modify the line so copy it first */ 286296465Sdelphij linebuf = BUF_strdup(line); 287296465Sdelphij state = HDR_NAME; 288296465Sdelphij ntmp = NULL; 289296465Sdelphij /* Go through all characters */ 290296465Sdelphij for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); 291296465Sdelphij p++) { 29255714Skris 293296465Sdelphij switch (state) { 294296465Sdelphij case HDR_NAME: 295296465Sdelphij if (c == ':') { 296296465Sdelphij state = HDR_VALUE; 297296465Sdelphij *p = 0; 298296465Sdelphij ntmp = strip_spaces(q); 299296465Sdelphij if (!ntmp) { 300296465Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 301296465Sdelphij X509V3_R_INVALID_NULL_NAME); 302296465Sdelphij goto err; 303296465Sdelphij } 304296465Sdelphij q = p + 1; 305296465Sdelphij } else if (c == ',') { 306296465Sdelphij *p = 0; 307296465Sdelphij ntmp = strip_spaces(q); 308296465Sdelphij q = p + 1; 309100928Snectar#if 0 310296465Sdelphij printf("%s\n", ntmp); 31155714Skris#endif 312296465Sdelphij if (!ntmp) { 313296465Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 314296465Sdelphij X509V3_R_INVALID_NULL_NAME); 315296465Sdelphij goto err; 316296465Sdelphij } 317296465Sdelphij X509V3_add_value(ntmp, NULL, &values); 318296465Sdelphij } 319296465Sdelphij break; 32055714Skris 321296465Sdelphij case HDR_VALUE: 322296465Sdelphij if (c == ',') { 323296465Sdelphij state = HDR_NAME; 324296465Sdelphij *p = 0; 325296465Sdelphij vtmp = strip_spaces(q); 326100928Snectar#if 0 327296465Sdelphij printf("%s\n", ntmp); 32855714Skris#endif 329296465Sdelphij if (!vtmp) { 330296465Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 331296465Sdelphij X509V3_R_INVALID_NULL_VALUE); 332296465Sdelphij goto err; 333296465Sdelphij } 334296465Sdelphij X509V3_add_value(ntmp, vtmp, &values); 335296465Sdelphij ntmp = NULL; 336296465Sdelphij q = p + 1; 337296465Sdelphij } 33855714Skris 339296465Sdelphij } 340296465Sdelphij } 34155714Skris 342296465Sdelphij if (state == HDR_VALUE) { 343296465Sdelphij vtmp = strip_spaces(q); 344100928Snectar#if 0 345296465Sdelphij printf("%s=%s\n", ntmp, vtmp); 34655714Skris#endif 347296465Sdelphij if (!vtmp) { 348296465Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, 349296465Sdelphij X509V3_R_INVALID_NULL_VALUE); 350296465Sdelphij goto err; 351296465Sdelphij } 352296465Sdelphij X509V3_add_value(ntmp, vtmp, &values); 353296465Sdelphij } else { 354296465Sdelphij ntmp = strip_spaces(q); 355100928Snectar#if 0 356296465Sdelphij printf("%s\n", ntmp); 35755714Skris#endif 358296465Sdelphij if (!ntmp) { 359296465Sdelphij X509V3err(X509V3_F_X509V3_PARSE_LIST, X509V3_R_INVALID_NULL_NAME); 360296465Sdelphij goto err; 361296465Sdelphij } 362296465Sdelphij X509V3_add_value(ntmp, NULL, &values); 363296465Sdelphij } 364296465Sdelphij OPENSSL_free(linebuf); 365296465Sdelphij return values; 36655714Skris 367296465Sdelphij err: 368296465Sdelphij OPENSSL_free(linebuf); 369296465Sdelphij sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 370296465Sdelphij return NULL; 37155714Skris 37255714Skris} 37355714Skris 37455714Skris/* Delete leading and trailing spaces from a string */ 37555714Skrisstatic char *strip_spaces(char *name) 37655714Skris{ 377296465Sdelphij char *p, *q; 378296465Sdelphij /* Skip over leading spaces */ 379296465Sdelphij p = name; 380296465Sdelphij while (*p && isspace((unsigned char)*p)) 381296465Sdelphij p++; 382296465Sdelphij if (!*p) 383296465Sdelphij return NULL; 384296465Sdelphij q = p + strlen(p) - 1; 385296465Sdelphij while ((q != p) && isspace((unsigned char)*q)) 386296465Sdelphij q--; 387296465Sdelphij if (p != q) 388296465Sdelphij q[1] = 0; 389296465Sdelphij if (!*p) 390296465Sdelphij return NULL; 391296465Sdelphij return p; 39255714Skris} 39355714Skris 39455714Skris/* hex string utilities */ 39555714Skris 396296465Sdelphij/* 397296465Sdelphij * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its 398296465Sdelphij * hex representation @@@ (Contents of buffer are always kept in ASCII, also 399296465Sdelphij * on EBCDIC machines) 40055714Skris */ 40155714Skris 40255714Skrischar *hex_to_string(unsigned char *buffer, long len) 40355714Skris{ 404296465Sdelphij char *tmp, *q; 405296465Sdelphij unsigned char *p; 406296465Sdelphij int i; 407296465Sdelphij const static char hexdig[] = "0123456789ABCDEF"; 408296465Sdelphij if (!buffer || !len) 409296465Sdelphij return NULL; 410296465Sdelphij if (!(tmp = OPENSSL_malloc(len * 3 + 1))) { 411296465Sdelphij X509V3err(X509V3_F_HEX_TO_STRING, ERR_R_MALLOC_FAILURE); 412296465Sdelphij return NULL; 413296465Sdelphij } 414296465Sdelphij q = tmp; 415296465Sdelphij for (i = 0, p = buffer; i < len; i++, p++) { 416296465Sdelphij *q++ = hexdig[(*p >> 4) & 0xf]; 417296465Sdelphij *q++ = hexdig[*p & 0xf]; 418296465Sdelphij *q++ = ':'; 419296465Sdelphij } 420296465Sdelphij q[-1] = 0; 42168651Skris#ifdef CHARSET_EBCDIC 422296465Sdelphij ebcdic2ascii(tmp, tmp, q - tmp - 1); 42368651Skris#endif 42468651Skris 425296465Sdelphij return tmp; 42655714Skris} 42755714Skris 428296465Sdelphij/* 429296465Sdelphij * Give a string of hex digits convert to a buffer 43055714Skris */ 43155714Skris 43255714Skrisunsigned char *string_to_hex(char *str, long *len) 43355714Skris{ 434296465Sdelphij unsigned char *hexbuf, *q; 435296465Sdelphij unsigned char ch, cl, *p; 436296465Sdelphij if (!str) { 437296465Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_INVALID_NULL_ARGUMENT); 438296465Sdelphij return NULL; 439296465Sdelphij } 440296465Sdelphij if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) 441296465Sdelphij goto err; 442296465Sdelphij for (p = (unsigned char *)str, q = hexbuf; *p;) { 443296465Sdelphij ch = *p++; 44468651Skris#ifdef CHARSET_EBCDIC 445296465Sdelphij ch = os_toebcdic[ch]; 44668651Skris#endif 447296465Sdelphij if (ch == ':') 448296465Sdelphij continue; 449296465Sdelphij cl = *p++; 45068651Skris#ifdef CHARSET_EBCDIC 451296465Sdelphij cl = os_toebcdic[cl]; 45268651Skris#endif 453296465Sdelphij if (!cl) { 454296465Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ODD_NUMBER_OF_DIGITS); 455296465Sdelphij OPENSSL_free(hexbuf); 456296465Sdelphij return NULL; 457296465Sdelphij } 458296465Sdelphij if (isupper(ch)) 459296465Sdelphij ch = tolower(ch); 460296465Sdelphij if (isupper(cl)) 461296465Sdelphij cl = tolower(cl); 46255714Skris 463296465Sdelphij if ((ch >= '0') && (ch <= '9')) 464296465Sdelphij ch -= '0'; 465296465Sdelphij else if ((ch >= 'a') && (ch <= 'f')) 466296465Sdelphij ch -= 'a' - 10; 467296465Sdelphij else 468296465Sdelphij goto badhex; 46955714Skris 470296465Sdelphij if ((cl >= '0') && (cl <= '9')) 471296465Sdelphij cl -= '0'; 472296465Sdelphij else if ((cl >= 'a') && (cl <= 'f')) 473296465Sdelphij cl -= 'a' - 10; 474296465Sdelphij else 475296465Sdelphij goto badhex; 47655714Skris 477296465Sdelphij *q++ = (ch << 4) | cl; 478296465Sdelphij } 47955714Skris 480296465Sdelphij if (len) 481296465Sdelphij *len = q - hexbuf; 48255714Skris 483296465Sdelphij return hexbuf; 48455714Skris 485296465Sdelphij err: 486296465Sdelphij if (hexbuf) 487296465Sdelphij OPENSSL_free(hexbuf); 488296465Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, ERR_R_MALLOC_FAILURE); 489296465Sdelphij return NULL; 49055714Skris 491296465Sdelphij badhex: 492296465Sdelphij OPENSSL_free(hexbuf); 493296465Sdelphij X509V3err(X509V3_F_STRING_TO_HEX, X509V3_R_ILLEGAL_HEX_DIGIT); 494296465Sdelphij return NULL; 49555714Skris 49655714Skris} 49755714Skris 498296465Sdelphij/* 499296465Sdelphij * V2I name comparison function: returns zero if 'name' matches cmp or cmp.* 50055714Skris */ 50155714Skris 50255714Skrisint name_cmp(const char *name, const char *cmp) 50355714Skris{ 504296465Sdelphij int len, ret; 505296465Sdelphij char c; 506296465Sdelphij len = strlen(cmp); 507296465Sdelphij if ((ret = strncmp(name, cmp, len))) 508296465Sdelphij return ret; 509296465Sdelphij c = name[len]; 510296465Sdelphij if (!c || (c == '.')) 511296465Sdelphij return 0; 512296465Sdelphij return 1; 51355714Skris} 51468651Skris 515296465Sdelphijstatic int sk_strcmp(const char *const *a, const char *const *b) 51668651Skris{ 517296465Sdelphij return strcmp(*a, *b); 51868651Skris} 51968651Skris 52068651SkrisSTACK *X509_get1_email(X509 *x) 52168651Skris{ 522296465Sdelphij GENERAL_NAMES *gens; 523296465Sdelphij STACK *ret; 524296465Sdelphij gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 525296465Sdelphij ret = get_email(X509_get_subject_name(x), gens); 526296465Sdelphij sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 527296465Sdelphij return ret; 52868651Skris} 52968651Skris 530194206SsimonSTACK *X509_get1_ocsp(X509 *x) 531194206Ssimon{ 532296465Sdelphij AUTHORITY_INFO_ACCESS *info; 533296465Sdelphij STACK *ret = NULL; 534296465Sdelphij int i; 535296465Sdelphij info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 536296465Sdelphij if (!info) 537296465Sdelphij return NULL; 538296465Sdelphij for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 539296465Sdelphij ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 540296465Sdelphij if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 541296465Sdelphij if (ad->location->type == GEN_URI) { 542296465Sdelphij if (!append_ia5 543296465Sdelphij (&ret, ad->location->d.uniformResourceIdentifier)) 544296465Sdelphij break; 545296465Sdelphij } 546296465Sdelphij } 547296465Sdelphij } 548296465Sdelphij AUTHORITY_INFO_ACCESS_free(info); 549296465Sdelphij return ret; 550194206Ssimon} 551194206Ssimon 55268651SkrisSTACK *X509_REQ_get1_email(X509_REQ *x) 55368651Skris{ 554296465Sdelphij GENERAL_NAMES *gens; 555296465Sdelphij STACK_OF(X509_EXTENSION) *exts; 556296465Sdelphij STACK *ret; 557296465Sdelphij exts = X509_REQ_get_extensions(x); 558296465Sdelphij gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 559296465Sdelphij ret = get_email(X509_REQ_get_subject_name(x), gens); 560296465Sdelphij sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 561296465Sdelphij sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 562296465Sdelphij return ret; 56368651Skris} 56468651Skris 565109998Smarkmstatic STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens) 56668651Skris{ 567296465Sdelphij STACK *ret = NULL; 568296465Sdelphij X509_NAME_ENTRY *ne; 569296465Sdelphij ASN1_IA5STRING *email; 570296465Sdelphij GENERAL_NAME *gen; 571296465Sdelphij int i; 572296465Sdelphij /* Now add any email address(es) to STACK */ 573296465Sdelphij i = -1; 574296465Sdelphij /* First supplied X509_NAME */ 575296465Sdelphij while ((i = X509_NAME_get_index_by_NID(name, 576296465Sdelphij NID_pkcs9_emailAddress, i)) >= 0) { 577296465Sdelphij ne = X509_NAME_get_entry(name, i); 578296465Sdelphij email = X509_NAME_ENTRY_get_data(ne); 579296465Sdelphij if (!append_ia5(&ret, email)) 580296465Sdelphij return NULL; 581296465Sdelphij } 582296465Sdelphij for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 583296465Sdelphij gen = sk_GENERAL_NAME_value(gens, i); 584296465Sdelphij if (gen->type != GEN_EMAIL) 585296465Sdelphij continue; 586296465Sdelphij if (!append_ia5(&ret, gen->d.ia5)) 587296465Sdelphij return NULL; 588296465Sdelphij } 589296465Sdelphij return ret; 59068651Skris} 59168651Skris 59268651Skrisstatic void str_free(void *str) 59368651Skris{ 594296465Sdelphij OPENSSL_free(str); 59568651Skris} 59668651Skris 597296465Sdelphijstatic int append_ia5(STACK ** sk, ASN1_IA5STRING *email) 59868651Skris{ 599296465Sdelphij char *emtmp; 600296465Sdelphij /* First some sanity checks */ 601296465Sdelphij if (email->type != V_ASN1_IA5STRING) 602296465Sdelphij return 1; 603296465Sdelphij if (!email->data || !email->length) 604296465Sdelphij return 1; 605296465Sdelphij if (!*sk) 606296465Sdelphij *sk = sk_new(sk_strcmp); 607296465Sdelphij if (!*sk) 608296465Sdelphij return 0; 609296465Sdelphij /* Don't add duplicates */ 610296465Sdelphij if (sk_find(*sk, (char *)email->data) != -1) 611296465Sdelphij return 1; 612296465Sdelphij emtmp = BUF_strdup((char *)email->data); 613296465Sdelphij if (!emtmp || !sk_push(*sk, emtmp)) { 614296465Sdelphij X509_email_free(*sk); 615296465Sdelphij *sk = NULL; 616296465Sdelphij return 0; 617296465Sdelphij } 618296465Sdelphij return 1; 61968651Skris} 62068651Skris 621296465Sdelphijvoid X509_email_free(STACK * sk) 62268651Skris{ 623296465Sdelphij sk_pop_free(sk, str_free); 62468651Skris} 625160814Ssimon 626296465Sdelphij/* 627296465Sdelphij * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible 628296465Sdelphij * with RFC3280. 629160814Ssimon */ 630160814Ssimon 631160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) 632296465Sdelphij{ 633296465Sdelphij unsigned char ipout[16]; 634296465Sdelphij ASN1_OCTET_STRING *ret; 635296465Sdelphij int iplen; 636160814Ssimon 637296465Sdelphij /* If string contains a ':' assume IPv6 */ 638160814Ssimon 639296465Sdelphij iplen = a2i_ipadd(ipout, ipasc); 640160814Ssimon 641296465Sdelphij if (!iplen) 642296465Sdelphij return NULL; 643160814Ssimon 644296465Sdelphij ret = ASN1_OCTET_STRING_new(); 645296465Sdelphij if (!ret) 646296465Sdelphij return NULL; 647296465Sdelphij if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 648296465Sdelphij ASN1_OCTET_STRING_free(ret); 649296465Sdelphij return NULL; 650296465Sdelphij } 651296465Sdelphij return ret; 652296465Sdelphij} 653160814Ssimon 654160814SsimonASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) 655296465Sdelphij{ 656296465Sdelphij ASN1_OCTET_STRING *ret = NULL; 657296465Sdelphij unsigned char ipout[32]; 658296465Sdelphij char *iptmp = NULL, *p; 659296465Sdelphij int iplen1, iplen2; 660296465Sdelphij p = strchr(ipasc, '/'); 661296465Sdelphij if (!p) 662296465Sdelphij return NULL; 663296465Sdelphij iptmp = BUF_strdup(ipasc); 664296465Sdelphij if (!iptmp) 665296465Sdelphij return NULL; 666296465Sdelphij p = iptmp + (p - ipasc); 667296465Sdelphij *p++ = 0; 668160814Ssimon 669296465Sdelphij iplen1 = a2i_ipadd(ipout, iptmp); 670160814Ssimon 671296465Sdelphij if (!iplen1) 672296465Sdelphij goto err; 673160814Ssimon 674296465Sdelphij iplen2 = a2i_ipadd(ipout + iplen1, p); 675160814Ssimon 676296465Sdelphij OPENSSL_free(iptmp); 677296465Sdelphij iptmp = NULL; 678160814Ssimon 679296465Sdelphij if (!iplen2 || (iplen1 != iplen2)) 680296465Sdelphij goto err; 681160814Ssimon 682296465Sdelphij ret = ASN1_OCTET_STRING_new(); 683296465Sdelphij if (!ret) 684296465Sdelphij goto err; 685296465Sdelphij if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 686296465Sdelphij goto err; 687160814Ssimon 688296465Sdelphij return ret; 689160814Ssimon 690296465Sdelphij err: 691296465Sdelphij if (iptmp) 692296465Sdelphij OPENSSL_free(iptmp); 693296465Sdelphij if (ret) 694296465Sdelphij ASN1_OCTET_STRING_free(ret); 695296465Sdelphij return NULL; 696296465Sdelphij} 697160814Ssimon 698167612Ssimonint a2i_ipadd(unsigned char *ipout, const char *ipasc) 699296465Sdelphij{ 700296465Sdelphij /* If string contains a ':' assume IPv6 */ 701160814Ssimon 702296465Sdelphij if (strchr(ipasc, ':')) { 703296465Sdelphij if (!ipv6_from_asc(ipout, ipasc)) 704296465Sdelphij return 0; 705296465Sdelphij return 16; 706296465Sdelphij } else { 707296465Sdelphij if (!ipv4_from_asc(ipout, ipasc)) 708296465Sdelphij return 0; 709296465Sdelphij return 4; 710296465Sdelphij } 711296465Sdelphij} 712160814Ssimon 713160814Ssimonstatic int ipv4_from_asc(unsigned char *v4, const char *in) 714296465Sdelphij{ 715296465Sdelphij int a0, a1, a2, a3; 716296465Sdelphij if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 717296465Sdelphij return 0; 718296465Sdelphij if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) 719296465Sdelphij || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 720296465Sdelphij return 0; 721296465Sdelphij v4[0] = a0; 722296465Sdelphij v4[1] = a1; 723296465Sdelphij v4[2] = a2; 724296465Sdelphij v4[3] = a3; 725296465Sdelphij return 1; 726296465Sdelphij} 727160814Ssimon 728160814Ssimontypedef struct { 729296465Sdelphij /* Temporary store for IPV6 output */ 730296465Sdelphij unsigned char tmp[16]; 731296465Sdelphij /* Total number of bytes in tmp */ 732296465Sdelphij int total; 733296465Sdelphij /* The position of a zero (corresponding to '::') */ 734296465Sdelphij int zero_pos; 735296465Sdelphij /* Number of zeroes */ 736296465Sdelphij int zero_cnt; 737296465Sdelphij} IPV6_STAT; 738160814Ssimon 739160814Ssimonstatic int ipv6_from_asc(unsigned char *v6, const char *in) 740296465Sdelphij{ 741296465Sdelphij IPV6_STAT v6stat; 742296465Sdelphij v6stat.total = 0; 743296465Sdelphij v6stat.zero_pos = -1; 744296465Sdelphij v6stat.zero_cnt = 0; 745296465Sdelphij /* 746296465Sdelphij * Treat the IPv6 representation as a list of values separated by ':'. 747296465Sdelphij * The presence of a '::' will parse as one, two or three zero length 748296465Sdelphij * elements. 749296465Sdelphij */ 750296465Sdelphij if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 751296465Sdelphij return 0; 752160814Ssimon 753296465Sdelphij /* Now for some sanity checks */ 754160814Ssimon 755296465Sdelphij if (v6stat.zero_pos == -1) { 756296465Sdelphij /* If no '::' must have exactly 16 bytes */ 757296465Sdelphij if (v6stat.total != 16) 758296465Sdelphij return 0; 759296465Sdelphij } else { 760296465Sdelphij /* If '::' must have less than 16 bytes */ 761296465Sdelphij if (v6stat.total == 16) 762296465Sdelphij return 0; 763296465Sdelphij /* More than three zeroes is an error */ 764296465Sdelphij if (v6stat.zero_cnt > 3) 765296465Sdelphij return 0; 766296465Sdelphij /* Can only have three zeroes if nothing else present */ 767296465Sdelphij else if (v6stat.zero_cnt == 3) { 768296465Sdelphij if (v6stat.total > 0) 769296465Sdelphij return 0; 770296465Sdelphij } 771296465Sdelphij /* Can only have two zeroes if at start or end */ 772296465Sdelphij else if (v6stat.zero_cnt == 2) { 773296465Sdelphij if ((v6stat.zero_pos != 0) 774296465Sdelphij && (v6stat.zero_pos != v6stat.total)) 775296465Sdelphij return 0; 776296465Sdelphij } else 777296465Sdelphij /* Can only have one zero if *not* start or end */ 778296465Sdelphij { 779296465Sdelphij if ((v6stat.zero_pos == 0) 780296465Sdelphij || (v6stat.zero_pos == v6stat.total)) 781296465Sdelphij return 0; 782296465Sdelphij } 783296465Sdelphij } 784160814Ssimon 785296465Sdelphij /* Format result */ 786160814Ssimon 787296465Sdelphij if (v6stat.zero_pos >= 0) { 788296465Sdelphij /* Copy initial part */ 789296465Sdelphij memcpy(v6, v6stat.tmp, v6stat.zero_pos); 790296465Sdelphij /* Zero middle */ 791296465Sdelphij memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 792296465Sdelphij /* Copy final part */ 793296465Sdelphij if (v6stat.total != v6stat.zero_pos) 794296465Sdelphij memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 795296465Sdelphij v6stat.tmp + v6stat.zero_pos, 796296465Sdelphij v6stat.total - v6stat.zero_pos); 797296465Sdelphij } else 798296465Sdelphij memcpy(v6, v6stat.tmp, 16); 799160814Ssimon 800296465Sdelphij return 1; 801296465Sdelphij} 802160814Ssimon 803160814Ssimonstatic int ipv6_cb(const char *elem, int len, void *usr) 804296465Sdelphij{ 805296465Sdelphij IPV6_STAT *s = usr; 806296465Sdelphij /* Error if 16 bytes written */ 807296465Sdelphij if (s->total == 16) 808296465Sdelphij return 0; 809296465Sdelphij if (len == 0) { 810296465Sdelphij /* Zero length element, corresponds to '::' */ 811296465Sdelphij if (s->zero_pos == -1) 812296465Sdelphij s->zero_pos = s->total; 813296465Sdelphij /* If we've already got a :: its an error */ 814296465Sdelphij else if (s->zero_pos != s->total) 815296465Sdelphij return 0; 816296465Sdelphij s->zero_cnt++; 817296465Sdelphij } else { 818296465Sdelphij /* If more than 4 characters could be final a.b.c.d form */ 819296465Sdelphij if (len > 4) { 820296465Sdelphij /* Need at least 4 bytes left */ 821296465Sdelphij if (s->total > 12) 822296465Sdelphij return 0; 823296465Sdelphij /* Must be end of string */ 824296465Sdelphij if (elem[len]) 825296465Sdelphij return 0; 826296465Sdelphij if (!ipv4_from_asc(s->tmp + s->total, elem)) 827296465Sdelphij return 0; 828296465Sdelphij s->total += 4; 829296465Sdelphij } else { 830296465Sdelphij if (!ipv6_hex(s->tmp + s->total, elem, len)) 831296465Sdelphij return 0; 832296465Sdelphij s->total += 2; 833296465Sdelphij } 834296465Sdelphij } 835296465Sdelphij return 1; 836296465Sdelphij} 837160814Ssimon 838296465Sdelphij/* 839296465Sdelphij * Convert a string of up to 4 hex digits into the corresponding IPv6 form. 840160814Ssimon */ 841160814Ssimon 842160814Ssimonstatic int ipv6_hex(unsigned char *out, const char *in, int inlen) 843296465Sdelphij{ 844296465Sdelphij unsigned char c; 845296465Sdelphij unsigned int num = 0; 846296465Sdelphij if (inlen > 4) 847296465Sdelphij return 0; 848296465Sdelphij while (inlen--) { 849296465Sdelphij c = *in++; 850296465Sdelphij num <<= 4; 851296465Sdelphij if ((c >= '0') && (c <= '9')) 852296465Sdelphij num |= c - '0'; 853296465Sdelphij else if ((c >= 'A') && (c <= 'F')) 854296465Sdelphij num |= c - 'A' + 10; 855296465Sdelphij else if ((c >= 'a') && (c <= 'f')) 856296465Sdelphij num |= c - 'a' + 10; 857296465Sdelphij else 858296465Sdelphij return 0; 859296465Sdelphij } 860296465Sdelphij out[0] = num >> 8; 861296465Sdelphij out[1] = num & 0xff; 862296465Sdelphij return 1; 863296465Sdelphij} 864160814Ssimon 865296465Sdelphijint X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk, 866296465Sdelphij unsigned long chtype) 867296465Sdelphij{ 868296465Sdelphij CONF_VALUE *v; 869296465Sdelphij int i, mval; 870296465Sdelphij char *p, *type; 871296465Sdelphij if (!nm) 872296465Sdelphij return 0; 873160814Ssimon 874296465Sdelphij for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 875296465Sdelphij v = sk_CONF_VALUE_value(dn_sk, i); 876296465Sdelphij type = v->name; 877296465Sdelphij /* 878296465Sdelphij * Skip past any leading X. X: X, etc to allow for multiple instances 879296465Sdelphij */ 880296465Sdelphij for (p = type; *p; p++) 881160814Ssimon#ifndef CHARSET_EBCDIC 882296465Sdelphij if ((*p == ':') || (*p == ',') || (*p == '.')) 883160814Ssimon#else 884296465Sdelphij if ((*p == os_toascii[':']) || (*p == os_toascii[',']) 885296465Sdelphij || (*p == os_toascii['.'])) 886160814Ssimon#endif 887296465Sdelphij { 888296465Sdelphij p++; 889296465Sdelphij if (*p) 890296465Sdelphij type = p; 891296465Sdelphij break; 892296465Sdelphij } 893160814Ssimon#ifndef CHARSET_EBCDIC 894296465Sdelphij if (*type == '+') 895160814Ssimon#else 896296465Sdelphij if (*type == os_toascii['+']) 897160814Ssimon#endif 898296465Sdelphij { 899296465Sdelphij mval = -1; 900296465Sdelphij type++; 901296465Sdelphij } else 902296465Sdelphij mval = 0; 903296465Sdelphij if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 904296465Sdelphij (unsigned char *)v->value, -1, -1, 905296465Sdelphij mval)) 906296465Sdelphij return 0; 907160814Ssimon 908296465Sdelphij } 909296465Sdelphij return 1; 910296465Sdelphij} 911