1*71585515Stb /* $OpenBSD: x509_utl.c,v 1.26 2025/01/26 13:51:41 tb Exp $ */ 2e500e238Sjsing /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 3e500e238Sjsing * project. 4e500e238Sjsing */ 5e500e238Sjsing /* ==================================================================== 6e500e238Sjsing * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 7e500e238Sjsing * 8e500e238Sjsing * Redistribution and use in source and binary forms, with or without 9e500e238Sjsing * modification, are permitted provided that the following conditions 10e500e238Sjsing * are met: 11e500e238Sjsing * 12e500e238Sjsing * 1. Redistributions of source code must retain the above copyright 13e500e238Sjsing * notice, this list of conditions and the following disclaimer. 14e500e238Sjsing * 15e500e238Sjsing * 2. Redistributions in binary form must reproduce the above copyright 16e500e238Sjsing * notice, this list of conditions and the following disclaimer in 17e500e238Sjsing * the documentation and/or other materials provided with the 18e500e238Sjsing * distribution. 19e500e238Sjsing * 20e500e238Sjsing * 3. All advertising materials mentioning features or use of this 21e500e238Sjsing * software must display the following acknowledgment: 22e500e238Sjsing * "This product includes software developed by the OpenSSL Project 23e500e238Sjsing * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24e500e238Sjsing * 25e500e238Sjsing * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26e500e238Sjsing * endorse or promote products derived from this software without 27e500e238Sjsing * prior written permission. For written permission, please contact 28e500e238Sjsing * licensing@OpenSSL.org. 29e500e238Sjsing * 30e500e238Sjsing * 5. Products derived from this software may not be called "OpenSSL" 31e500e238Sjsing * nor may "OpenSSL" appear in their names without prior written 32e500e238Sjsing * permission of the OpenSSL Project. 33e500e238Sjsing * 34e500e238Sjsing * 6. Redistributions of any form whatsoever must retain the following 35e500e238Sjsing * acknowledgment: 36e500e238Sjsing * "This product includes software developed by the OpenSSL Project 37e500e238Sjsing * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38e500e238Sjsing * 39e500e238Sjsing * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40e500e238Sjsing * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41e500e238Sjsing * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42e500e238Sjsing * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43e500e238Sjsing * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44e500e238Sjsing * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45e500e238Sjsing * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46e500e238Sjsing * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47e500e238Sjsing * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48e500e238Sjsing * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49e500e238Sjsing * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50e500e238Sjsing * OF THE POSSIBILITY OF SUCH DAMAGE. 51e500e238Sjsing * ==================================================================== 52e500e238Sjsing * 53e500e238Sjsing * This product includes cryptographic software written by Eric Young 54e500e238Sjsing * (eay@cryptsoft.com). This product includes software written by Tim 55e500e238Sjsing * Hudson (tjh@cryptsoft.com). 56e500e238Sjsing * 57e500e238Sjsing */ 58e500e238Sjsing 59e500e238Sjsing #include <ctype.h> 6065383164Stb #include <limits.h> 61e500e238Sjsing #include <stdio.h> 62e500e238Sjsing #include <string.h> 63e500e238Sjsing 644b51fbb1Stb #include <openssl/asn1.h> 65e500e238Sjsing #include <openssl/bn.h> 66e500e238Sjsing #include <openssl/conf.h> 67e500e238Sjsing #include <openssl/err.h> 68e500e238Sjsing #include <openssl/x509v3.h> 69e500e238Sjsing 7065383164Stb #include "bytestring.h" 71*71585515Stb #include "conf_local.h" 7265383164Stb 73b0365755Stb /* 749f0e52e1Stb * Match reference identifiers starting with "." to any sub-domain. This 759f0e52e1Stb * flag is set implicitly when the subject reference identity is a DNS name. 76b0365755Stb */ 77b0365755Stb #define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000 78b0365755Stb 79c5b33e2fStb static char *bn_to_string(const BIGNUM *bn); 80e500e238Sjsing static char *strip_spaces(char *name); 81e500e238Sjsing static int sk_strcmp(const char * const *a, const char * const *b); 82e500e238Sjsing static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, 83e500e238Sjsing GENERAL_NAMES *gens); 84e500e238Sjsing static void str_free(OPENSSL_STRING str); 85e500e238Sjsing static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email); 86e500e238Sjsing 87e500e238Sjsing static int ipv4_from_asc(unsigned char *v4, const char *in); 88e500e238Sjsing static int ipv6_from_asc(unsigned char *v6, const char *in); 89e500e238Sjsing static int ipv6_cb(const char *elem, int len, void *usr); 90e500e238Sjsing static int ipv6_hex(unsigned char *out, const char *in, int inlen); 91e500e238Sjsing 92e500e238Sjsing /* Add a CONF_VALUE name-value pair to stack. */ 93e500e238Sjsing int 94e500e238Sjsing X509V3_add_value(const char *name, const char *value, 9535434a01Stb STACK_OF(CONF_VALUE) **out_extlist) 96e500e238Sjsing { 9735434a01Stb STACK_OF(CONF_VALUE) *extlist = NULL; 9835434a01Stb CONF_VALUE *conf_value = NULL; 9935434a01Stb int ret = 0; 100e500e238Sjsing 10135434a01Stb if ((conf_value = calloc(1, sizeof(*conf_value))) == NULL) { 10235434a01Stb X509V3error(ERR_R_MALLOC_FAILURE); 103e500e238Sjsing goto err; 10435434a01Stb } 105e500e238Sjsing if (name != NULL) { 10635434a01Stb if ((conf_value->name = strdup(name)) == NULL) { 10735434a01Stb X509V3error(ERR_R_MALLOC_FAILURE); 108e500e238Sjsing goto err; 109e500e238Sjsing } 11035434a01Stb } 111e500e238Sjsing if (value != NULL) { 11235434a01Stb if ((conf_value->value = strdup(value)) == NULL) { 11335434a01Stb X509V3error(ERR_R_MALLOC_FAILURE); 11435434a01Stb goto err; 11535434a01Stb } 11635434a01Stb } 11735434a01Stb 11835434a01Stb if ((extlist = *out_extlist) == NULL) 11935434a01Stb extlist = sk_CONF_VALUE_new_null(); 12035434a01Stb if (extlist == NULL) { 12135434a01Stb X509V3error(ERR_R_MALLOC_FAILURE); 122e500e238Sjsing goto err; 123e500e238Sjsing } 124e500e238Sjsing 12535434a01Stb if (!sk_CONF_VALUE_push(extlist, conf_value)) { 12635434a01Stb X509V3error(ERR_R_MALLOC_FAILURE); 127e500e238Sjsing goto err; 128e500e238Sjsing } 12935434a01Stb conf_value = NULL; 130e500e238Sjsing 13135434a01Stb *out_extlist = extlist; 13235434a01Stb extlist = NULL; 133e500e238Sjsing 13435434a01Stb ret = 1; 135e500e238Sjsing 136e500e238Sjsing err: 13735434a01Stb if (extlist != *out_extlist) 13835434a01Stb sk_CONF_VALUE_pop_free(extlist, X509V3_conf_free); 13935434a01Stb X509V3_conf_free(conf_value); 14035434a01Stb 14135434a01Stb return ret; 142e500e238Sjsing } 143e500e238Sjsing 144e500e238Sjsing int 145e500e238Sjsing X509V3_add_value_uchar(const char *name, const unsigned char *value, 146e500e238Sjsing STACK_OF(CONF_VALUE) **extlist) 147e500e238Sjsing { 148e500e238Sjsing return X509V3_add_value(name, (const char *)value, extlist); 149e500e238Sjsing } 150e500e238Sjsing 151e500e238Sjsing /* Free function for STACK_OF(CONF_VALUE) */ 152e500e238Sjsing 153e500e238Sjsing void 154e500e238Sjsing X509V3_conf_free(CONF_VALUE *conf) 155e500e238Sjsing { 156e500e238Sjsing if (!conf) 157e500e238Sjsing return; 158e500e238Sjsing free(conf->name); 159e500e238Sjsing free(conf->value); 160e500e238Sjsing free(conf->section); 161e500e238Sjsing free(conf); 162e500e238Sjsing } 163cedac418Stb LCRYPTO_ALIAS(X509V3_conf_free); 164e500e238Sjsing 165e500e238Sjsing int 166e500e238Sjsing X509V3_add_value_bool(const char *name, int asn1_bool, 167e500e238Sjsing STACK_OF(CONF_VALUE) **extlist) 168e500e238Sjsing { 169e500e238Sjsing if (asn1_bool) 170e500e238Sjsing return X509V3_add_value(name, "TRUE", extlist); 171e500e238Sjsing return X509V3_add_value(name, "FALSE", extlist); 172e500e238Sjsing } 173e500e238Sjsing 174c5b33e2fStb static char * 175e500e238Sjsing bn_to_string(const BIGNUM *bn) 176e500e238Sjsing { 177e500e238Sjsing const char *sign = ""; 178e500e238Sjsing char *bnstr, *hex; 179e500e238Sjsing char *ret = NULL; 180e500e238Sjsing 181e500e238Sjsing /* Only display small numbers in decimal, as conversion is quadratic. */ 182e500e238Sjsing if (BN_num_bits(bn) < 128) 183e500e238Sjsing return BN_bn2dec(bn); 184e500e238Sjsing 185e500e238Sjsing if ((hex = bnstr = BN_bn2hex(bn)) == NULL) 186e500e238Sjsing goto err; 187e500e238Sjsing 188e500e238Sjsing if (BN_is_negative(bn)) { 189e500e238Sjsing sign = "-"; 190e500e238Sjsing hex++; 191e500e238Sjsing } 192e500e238Sjsing 193e500e238Sjsing if (asprintf(&ret, "%s0x%s", sign, hex) == -1) 194e500e238Sjsing ret = NULL; 195e500e238Sjsing 196e500e238Sjsing err: 197e500e238Sjsing free(bnstr); 198e500e238Sjsing return ret; 199e500e238Sjsing } 200e500e238Sjsing 201e500e238Sjsing char * 202e500e238Sjsing i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a) 203e500e238Sjsing { 204e500e238Sjsing BIGNUM *bntmp; 205e500e238Sjsing char *strtmp = NULL; 206e500e238Sjsing 207e500e238Sjsing if (a == NULL) 208e500e238Sjsing return NULL; 209e500e238Sjsing if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL || 210e500e238Sjsing (strtmp = bn_to_string(bntmp)) == NULL) 211e500e238Sjsing X509V3error(ERR_R_MALLOC_FAILURE); 212e500e238Sjsing BN_free(bntmp); 213e500e238Sjsing return strtmp; 214e500e238Sjsing } 215cedac418Stb LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED); 216e500e238Sjsing 217e500e238Sjsing char * 2184b51fbb1Stb i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *e) 2194b51fbb1Stb { 2202aedf8d3Stb const BIT_STRING_BITNAME *enam; 2214b51fbb1Stb long strval; 2224b51fbb1Stb 2234b51fbb1Stb strval = ASN1_ENUMERATED_get(e); 2244b51fbb1Stb for (enam = method->usr_data; enam->lname; enam++) { 2254b51fbb1Stb if (strval == enam->bitnum) 2264b51fbb1Stb return strdup(enam->lname); 2274b51fbb1Stb } 2284b51fbb1Stb return i2s_ASN1_ENUMERATED(method, e); 2294b51fbb1Stb } 2304b51fbb1Stb LCRYPTO_ALIAS(i2s_ASN1_ENUMERATED_TABLE); 2314b51fbb1Stb 2324b51fbb1Stb char * 233e500e238Sjsing i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a) 234e500e238Sjsing { 235e500e238Sjsing BIGNUM *bntmp; 236e500e238Sjsing char *strtmp = NULL; 237e500e238Sjsing 238e500e238Sjsing if (a == NULL) 239e500e238Sjsing return NULL; 240e500e238Sjsing if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL || 241e500e238Sjsing (strtmp = bn_to_string(bntmp)) == NULL) 242e500e238Sjsing X509V3error(ERR_R_MALLOC_FAILURE); 243e500e238Sjsing BN_free(bntmp); 244e500e238Sjsing return strtmp; 245e500e238Sjsing } 246cedac418Stb LCRYPTO_ALIAS(i2s_ASN1_INTEGER); 247e500e238Sjsing 248e500e238Sjsing ASN1_INTEGER * 249e500e238Sjsing s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value) 250e500e238Sjsing { 251e500e238Sjsing BIGNUM *bn = NULL; 252e500e238Sjsing ASN1_INTEGER *aint; 2539015b48bStb int isneg = 0, ishex = 0; 254e500e238Sjsing int ret; 255e500e238Sjsing 256e500e238Sjsing if (!value) { 257e500e238Sjsing X509V3error(X509V3_R_INVALID_NULL_VALUE); 258321b36b5Stb return NULL; 259e500e238Sjsing } 260680d013eStb if ((bn = BN_new()) == NULL) { 261680d013eStb X509V3error(ERR_R_MALLOC_FAILURE); 262680d013eStb return NULL; 263680d013eStb } 264e500e238Sjsing if (value[0] == '-') { 265e500e238Sjsing value++; 266e500e238Sjsing isneg = 1; 2679015b48bStb } 268e500e238Sjsing 2690cb17b89Stb if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) { 270e500e238Sjsing value += 2; 271e500e238Sjsing ishex = 1; 2729015b48bStb } 273e500e238Sjsing 274e500e238Sjsing if (ishex) 275e500e238Sjsing ret = BN_hex2bn(&bn, value); 276e500e238Sjsing else 277e500e238Sjsing ret = BN_dec2bn(&bn, value); 278e500e238Sjsing 279e500e238Sjsing if (!ret || value[ret]) { 280e500e238Sjsing BN_free(bn); 281e500e238Sjsing X509V3error(X509V3_R_BN_DEC2BN_ERROR); 282321b36b5Stb return NULL; 283e500e238Sjsing } 284e500e238Sjsing 2856c1a678eStb if (BN_is_zero(bn)) 286e500e238Sjsing isneg = 0; 287e500e238Sjsing 288e500e238Sjsing aint = BN_to_ASN1_INTEGER(bn, NULL); 289e500e238Sjsing BN_free(bn); 290e500e238Sjsing if (!aint) { 291e500e238Sjsing X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR); 292321b36b5Stb return NULL; 293e500e238Sjsing } 294e500e238Sjsing if (isneg) 295e500e238Sjsing aint->type |= V_ASN1_NEG; 296e500e238Sjsing return aint; 297e500e238Sjsing } 298cedac418Stb LCRYPTO_ALIAS(s2i_ASN1_INTEGER); 299e500e238Sjsing 300e500e238Sjsing int 301e500e238Sjsing X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint, 302e500e238Sjsing STACK_OF(CONF_VALUE) **extlist) 303e500e238Sjsing { 304e500e238Sjsing char *strtmp; 305e500e238Sjsing int ret; 306e500e238Sjsing 307e500e238Sjsing if (!aint) 308e500e238Sjsing return 1; 309e500e238Sjsing if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) 310e500e238Sjsing return 0; 311e500e238Sjsing ret = X509V3_add_value(name, strtmp, extlist); 312e500e238Sjsing free(strtmp); 313e500e238Sjsing return ret; 314e500e238Sjsing } 315e500e238Sjsing 316e500e238Sjsing int 317e500e238Sjsing X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool) 318e500e238Sjsing { 319e500e238Sjsing char *btmp; 320e500e238Sjsing 321e500e238Sjsing if (!(btmp = value->value)) 322e500e238Sjsing goto err; 323e500e238Sjsing if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") || 324e500e238Sjsing !strcmp(btmp, "Y") || !strcmp(btmp, "y") || 325e500e238Sjsing !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) { 326e500e238Sjsing *asn1_bool = 0xff; 327e500e238Sjsing return 1; 328e500e238Sjsing } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") || 329e500e238Sjsing !strcmp(btmp, "N") || !strcmp(btmp, "n") || 330e500e238Sjsing !strcmp(btmp, "NO") || !strcmp(btmp, "no")) { 331e500e238Sjsing *asn1_bool = 0; 332e500e238Sjsing return 1; 333e500e238Sjsing } 334e500e238Sjsing 335e500e238Sjsing err: 336e500e238Sjsing X509V3error(X509V3_R_INVALID_BOOLEAN_STRING); 337e500e238Sjsing X509V3_conf_err(value); 338e500e238Sjsing return 0; 339e500e238Sjsing } 340e500e238Sjsing 341e500e238Sjsing int 342e500e238Sjsing X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint) 343e500e238Sjsing { 344e500e238Sjsing ASN1_INTEGER *itmp; 345e500e238Sjsing 346e500e238Sjsing if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) { 347e500e238Sjsing X509V3_conf_err(value); 348e500e238Sjsing return 0; 349e500e238Sjsing } 350e500e238Sjsing *aint = itmp; 351e500e238Sjsing return 1; 352e500e238Sjsing } 353e500e238Sjsing 354e500e238Sjsing #define HDR_NAME 1 355e500e238Sjsing #define HDR_VALUE 2 356e500e238Sjsing 357e500e238Sjsing /*#define DEBUG*/ 358e500e238Sjsing 359e500e238Sjsing STACK_OF(CONF_VALUE) * 360e500e238Sjsing X509V3_parse_list(const char *line) 361e500e238Sjsing { 362e500e238Sjsing char *p, *q, c; 363e500e238Sjsing char *ntmp, *vtmp; 364e500e238Sjsing STACK_OF(CONF_VALUE) *values = NULL; 365e500e238Sjsing char *linebuf; 366e500e238Sjsing int state; 367e500e238Sjsing 368e500e238Sjsing /* We are going to modify the line so copy it first */ 369e500e238Sjsing if ((linebuf = strdup(line)) == NULL) { 370e500e238Sjsing X509V3error(ERR_R_MALLOC_FAILURE); 371e500e238Sjsing goto err; 372e500e238Sjsing } 373e500e238Sjsing state = HDR_NAME; 374e500e238Sjsing ntmp = NULL; 375e500e238Sjsing 376e500e238Sjsing /* Go through all characters */ 377e500e238Sjsing for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && 378e500e238Sjsing (c != '\n'); p++) { 379e500e238Sjsing 380e500e238Sjsing switch (state) { 381e500e238Sjsing case HDR_NAME: 382e500e238Sjsing if (c == ':') { 383e500e238Sjsing state = HDR_VALUE; 384e500e238Sjsing *p = 0; 385e500e238Sjsing ntmp = strip_spaces(q); 386e500e238Sjsing if (!ntmp) { 387e500e238Sjsing X509V3error(X509V3_R_INVALID_NULL_NAME); 388e500e238Sjsing goto err; 389e500e238Sjsing } 390e500e238Sjsing q = p + 1; 391e500e238Sjsing } else if (c == ',') { 392e500e238Sjsing *p = 0; 393e500e238Sjsing ntmp = strip_spaces(q); 394e500e238Sjsing q = p + 1; 395e500e238Sjsing if (!ntmp) { 396e500e238Sjsing X509V3error(X509V3_R_INVALID_NULL_NAME); 397e500e238Sjsing goto err; 398e500e238Sjsing } 39958f6608bSschwarze if (!X509V3_add_value(ntmp, NULL, &values)) 40058f6608bSschwarze goto err; 401e500e238Sjsing } 402e500e238Sjsing break; 403e500e238Sjsing 404e500e238Sjsing case HDR_VALUE: 405e500e238Sjsing if (c == ',') { 406e500e238Sjsing state = HDR_NAME; 407e500e238Sjsing *p = 0; 408e500e238Sjsing vtmp = strip_spaces(q); 409e500e238Sjsing if (!vtmp) { 410e500e238Sjsing X509V3error(X509V3_R_INVALID_NULL_VALUE); 411e500e238Sjsing goto err; 412e500e238Sjsing } 41358f6608bSschwarze if (!X509V3_add_value(ntmp, vtmp, &values)) 41458f6608bSschwarze goto err; 415e500e238Sjsing ntmp = NULL; 416e500e238Sjsing q = p + 1; 417e500e238Sjsing } 418e500e238Sjsing 419e500e238Sjsing } 420e500e238Sjsing } 421e500e238Sjsing 422e500e238Sjsing if (state == HDR_VALUE) { 423e500e238Sjsing vtmp = strip_spaces(q); 424e500e238Sjsing if (!vtmp) { 425e500e238Sjsing X509V3error(X509V3_R_INVALID_NULL_VALUE); 426e500e238Sjsing goto err; 427e500e238Sjsing } 42858f6608bSschwarze if (!X509V3_add_value(ntmp, vtmp, &values)) 42958f6608bSschwarze goto err; 430e500e238Sjsing } else { 431e500e238Sjsing ntmp = strip_spaces(q); 432e500e238Sjsing if (!ntmp) { 433e500e238Sjsing X509V3error(X509V3_R_INVALID_NULL_NAME); 434e500e238Sjsing goto err; 435e500e238Sjsing } 43658f6608bSschwarze if (!X509V3_add_value(ntmp, NULL, &values)) 43758f6608bSschwarze goto err; 438e500e238Sjsing } 439e500e238Sjsing free(linebuf); 440e500e238Sjsing return values; 441e500e238Sjsing 442e500e238Sjsing err: 443e500e238Sjsing free(linebuf); 444e500e238Sjsing sk_CONF_VALUE_pop_free(values, X509V3_conf_free); 445e500e238Sjsing return NULL; 446e500e238Sjsing } 447cedac418Stb LCRYPTO_ALIAS(X509V3_parse_list); 448e500e238Sjsing 449e500e238Sjsing /* Delete leading and trailing spaces from a string */ 450e500e238Sjsing static char * 451e500e238Sjsing strip_spaces(char *name) 452e500e238Sjsing { 453e500e238Sjsing char *p, *q; 454e500e238Sjsing 455e500e238Sjsing /* Skip over leading spaces */ 456e500e238Sjsing p = name; 457e500e238Sjsing while (*p && isspace((unsigned char)*p)) 458e500e238Sjsing p++; 459e500e238Sjsing if (!*p) 460e500e238Sjsing return NULL; 461e500e238Sjsing q = p + strlen(p) - 1; 462e500e238Sjsing while ((q != p) && isspace((unsigned char)*q)) 463e500e238Sjsing q--; 464e500e238Sjsing if (p != q) 465e500e238Sjsing q[1] = 0; 466e500e238Sjsing if (!*p) 467e500e238Sjsing return NULL; 468e500e238Sjsing return p; 469e500e238Sjsing } 470e500e238Sjsing 47165383164Stb static const char hex_digits[] = "0123456789ABCDEF"; 472e500e238Sjsing 473e500e238Sjsing char * 474e500e238Sjsing hex_to_string(const unsigned char *buffer, long len) 475e500e238Sjsing { 47665383164Stb CBB cbb; 47765383164Stb CBS cbs; 47865383164Stb uint8_t *out = NULL; 47965383164Stb uint8_t c; 48065383164Stb size_t out_len; 48165383164Stb 48265383164Stb if (!CBB_init(&cbb, 0)) 48365383164Stb goto err; 484e500e238Sjsing 4855517f1c8Stb if (len < 0) 48665383164Stb goto err; 48765383164Stb 48865383164Stb CBS_init(&cbs, buffer, len); 48965383164Stb while (CBS_len(&cbs) > 0) { 49065383164Stb if (!CBS_get_u8(&cbs, &c)) 49165383164Stb goto err; 49265383164Stb if (!CBB_add_u8(&cbb, hex_digits[c >> 4])) 49365383164Stb goto err; 49465383164Stb if (!CBB_add_u8(&cbb, hex_digits[c & 0xf])) 49565383164Stb goto err; 49665383164Stb if (CBS_len(&cbs) > 0) { 49765383164Stb if (!CBB_add_u8(&cbb, ':')) 49865383164Stb goto err; 499e500e238Sjsing } 500e500e238Sjsing } 50165383164Stb 50265383164Stb if (!CBB_add_u8(&cbb, '\0')) 50365383164Stb goto err; 50465383164Stb 50565383164Stb if (!CBB_finish(&cbb, &out, &out_len)) 50665383164Stb goto err; 50765383164Stb 50865383164Stb err: 50965383164Stb CBB_cleanup(&cbb); 51065383164Stb 51165383164Stb return out; 512e500e238Sjsing } 513cedac418Stb LCRYPTO_ALIAS(hex_to_string); 514e500e238Sjsing 51565383164Stb static int 51665383164Stb x509_skip_colons_cbs(CBS *cbs) 51765383164Stb { 51865383164Stb uint8_t c; 51965383164Stb 52065383164Stb while (CBS_len(cbs) > 0) { 52165383164Stb if (!CBS_peek_u8(cbs, &c)) 52265383164Stb return 0; 52365383164Stb if (c != ':') 52465383164Stb return 1; 52565383164Stb if (!CBS_get_u8(cbs, &c)) 52665383164Stb return 0; 52765383164Stb } 52865383164Stb 52965383164Stb return 1; 53065383164Stb } 53165383164Stb 53265383164Stb static int 53390bc65e1Stb x509_get_xdigit_nibble_cbs(CBS *cbs, uint8_t *out_nibble) 53490bc65e1Stb { 53565383164Stb uint8_t c; 53665383164Stb 53765383164Stb if (!CBS_get_u8(cbs, &c)) 53865383164Stb return 0; 53965383164Stb 54065383164Stb if (c >= '0' && c <= '9') { 54165383164Stb *out_nibble = c - '0'; 54265383164Stb return 1; 54365383164Stb } 54465383164Stb if (c >= 'a' && c <= 'f') { 54565383164Stb *out_nibble = c - 'a' + 10; 54665383164Stb return 1; 54765383164Stb } 54865383164Stb if (c >= 'A' && c <= 'F') { 54965383164Stb *out_nibble = c - 'A' + 10; 55065383164Stb return 1; 55165383164Stb } 55265383164Stb 55365383164Stb X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT); 55465383164Stb return 0; 55565383164Stb } 556e500e238Sjsing 557e500e238Sjsing unsigned char * 558e500e238Sjsing string_to_hex(const char *str, long *len) 559e500e238Sjsing { 56065383164Stb CBB cbb; 56165383164Stb CBS cbs; 56265383164Stb uint8_t *out = NULL; 56365383164Stb size_t out_len; 56465383164Stb uint8_t hi, lo; 56565383164Stb 56665383164Stb *len = 0; 56765383164Stb 56865383164Stb if (!CBB_init(&cbb, 0)) 569e500e238Sjsing goto err; 570e500e238Sjsing 57165383164Stb if (str == NULL) { 57265383164Stb X509V3error(X509V3_R_INVALID_NULL_ARGUMENT); 57365383164Stb goto err; 574e500e238Sjsing } 575e500e238Sjsing 57665383164Stb CBS_init(&cbs, str, strlen(str)); 57765383164Stb while (CBS_len(&cbs) > 0) { 57865383164Stb /* 57965383164Stb * Skipping only a single colon between two pairs of digits 58065383164Stb * would make more sense - history... 58165383164Stb */ 58265383164Stb if (!x509_skip_colons_cbs(&cbs)) 58365383164Stb goto err; 58465383164Stb /* Another historic idiocy. */ 58565383164Stb if (CBS_len(&cbs) == 0) 58665383164Stb break; 58765383164Stb if (!x509_get_xdigit_nibble_cbs(&cbs, &hi)) 58865383164Stb goto err; 58965383164Stb if (CBS_len(&cbs) == 0) { 590025fffe4Stb X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS); 59165383164Stb goto err; 59265383164Stb } 59365383164Stb if (!x509_get_xdigit_nibble_cbs(&cbs, &lo)) 59465383164Stb goto err; 59565383164Stb if (!CBB_add_u8(&cbb, hi << 4 | lo)) 59665383164Stb goto err; 59765383164Stb } 598e500e238Sjsing 59965383164Stb if (!CBB_finish(&cbb, &out, &out_len)) 60065383164Stb goto err; 60165383164Stb if (out_len > LONG_MAX) { 60265383164Stb freezero(out, out_len); 60365383164Stb out = NULL; 60465383164Stb goto err; 60565383164Stb } 60665383164Stb 60765383164Stb *len = out_len; 608e500e238Sjsing 609e500e238Sjsing err: 61065383164Stb CBB_cleanup(&cbb); 611e500e238Sjsing 61265383164Stb return out; 613e500e238Sjsing } 614cedac418Stb LCRYPTO_ALIAS(string_to_hex); 615e500e238Sjsing 616e500e238Sjsing /* V2I name comparison function: returns zero if 'name' matches 617e500e238Sjsing * cmp or cmp.* 618e500e238Sjsing */ 619e500e238Sjsing 620e500e238Sjsing int 621e500e238Sjsing name_cmp(const char *name, const char *cmp) 622e500e238Sjsing { 623e500e238Sjsing int len, ret; 624e500e238Sjsing char c; 625e500e238Sjsing 626e500e238Sjsing len = strlen(cmp); 627e500e238Sjsing if ((ret = strncmp(name, cmp, len))) 628e500e238Sjsing return ret; 629e500e238Sjsing c = name[len]; 630e500e238Sjsing if (!c || (c=='.')) 631e500e238Sjsing return 0; 632e500e238Sjsing return 1; 633e500e238Sjsing } 634e500e238Sjsing 635e500e238Sjsing static int 636e500e238Sjsing sk_strcmp(const char * const *a, const char * const *b) 637e500e238Sjsing { 638e500e238Sjsing return strcmp(*a, *b); 639e500e238Sjsing } 640e500e238Sjsing 641e500e238Sjsing STACK_OF(OPENSSL_STRING) * 642e500e238Sjsing X509_get1_email(X509 *x) 643e500e238Sjsing { 644e500e238Sjsing GENERAL_NAMES *gens; 645e500e238Sjsing STACK_OF(OPENSSL_STRING) *ret; 646e500e238Sjsing 647e500e238Sjsing gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 648e500e238Sjsing ret = get_email(X509_get_subject_name(x), gens); 649e500e238Sjsing sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 650e500e238Sjsing return ret; 651e500e238Sjsing } 652cedac418Stb LCRYPTO_ALIAS(X509_get1_email); 653e500e238Sjsing 654e500e238Sjsing STACK_OF(OPENSSL_STRING) * 655e500e238Sjsing X509_get1_ocsp(X509 *x) 656e500e238Sjsing { 657e500e238Sjsing AUTHORITY_INFO_ACCESS *info; 658e500e238Sjsing STACK_OF(OPENSSL_STRING) *ret = NULL; 659e500e238Sjsing int i; 660e500e238Sjsing 661e500e238Sjsing info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); 662e500e238Sjsing if (!info) 663e500e238Sjsing return NULL; 664e500e238Sjsing for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) { 665e500e238Sjsing ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); 666e500e238Sjsing if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) { 667e500e238Sjsing if (ad->location->type == GEN_URI) { 668e500e238Sjsing if (!append_ia5(&ret, 669e500e238Sjsing ad->location->d.uniformResourceIdentifier)) 670e500e238Sjsing break; 671e500e238Sjsing } 672e500e238Sjsing } 673e500e238Sjsing } 674e500e238Sjsing AUTHORITY_INFO_ACCESS_free(info); 675e500e238Sjsing return ret; 676e500e238Sjsing } 677cedac418Stb LCRYPTO_ALIAS(X509_get1_ocsp); 678e500e238Sjsing 679e500e238Sjsing STACK_OF(OPENSSL_STRING) * 680e500e238Sjsing X509_REQ_get1_email(X509_REQ *x) 681e500e238Sjsing { 682e500e238Sjsing GENERAL_NAMES *gens; 683e500e238Sjsing STACK_OF(X509_EXTENSION) *exts; 684e500e238Sjsing STACK_OF(OPENSSL_STRING) *ret; 685e500e238Sjsing 686e500e238Sjsing exts = X509_REQ_get_extensions(x); 687e500e238Sjsing gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL); 688e500e238Sjsing ret = get_email(X509_REQ_get_subject_name(x), gens); 689e500e238Sjsing sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 690e500e238Sjsing sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); 691e500e238Sjsing return ret; 692e500e238Sjsing } 693cedac418Stb LCRYPTO_ALIAS(X509_REQ_get1_email); 694e500e238Sjsing 695e500e238Sjsing 696e500e238Sjsing static STACK_OF(OPENSSL_STRING) * 697e500e238Sjsing get_email(X509_NAME *name, GENERAL_NAMES *gens) 698e500e238Sjsing { 699e500e238Sjsing STACK_OF(OPENSSL_STRING) *ret = NULL; 700e500e238Sjsing X509_NAME_ENTRY *ne; 701e500e238Sjsing ASN1_IA5STRING *email; 702e500e238Sjsing GENERAL_NAME *gen; 703e500e238Sjsing int i; 704e500e238Sjsing 705e500e238Sjsing /* Now add any email address(es) to STACK */ 706e500e238Sjsing i = -1; 707e500e238Sjsing 708e500e238Sjsing /* First supplied X509_NAME */ 709e500e238Sjsing while ((i = X509_NAME_get_index_by_NID(name, 710e500e238Sjsing NID_pkcs9_emailAddress, i)) >= 0) { 711e500e238Sjsing ne = X509_NAME_get_entry(name, i); 712e500e238Sjsing email = X509_NAME_ENTRY_get_data(ne); 713e500e238Sjsing if (!append_ia5(&ret, email)) 714e500e238Sjsing return NULL; 715e500e238Sjsing } 716e500e238Sjsing for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 717e500e238Sjsing gen = sk_GENERAL_NAME_value(gens, i); 718e500e238Sjsing if (gen->type != GEN_EMAIL) 719e500e238Sjsing continue; 720e500e238Sjsing if (!append_ia5(&ret, gen->d.ia5)) 721e500e238Sjsing return NULL; 722e500e238Sjsing } 723e500e238Sjsing return ret; 724e500e238Sjsing } 725e500e238Sjsing 726e500e238Sjsing static void 727e500e238Sjsing str_free(OPENSSL_STRING str) 728e500e238Sjsing { 729e500e238Sjsing free(str); 730e500e238Sjsing } 731e500e238Sjsing 732e500e238Sjsing static int 733e500e238Sjsing append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email) 734e500e238Sjsing { 735e500e238Sjsing char *emtmp; 736e500e238Sjsing 737e500e238Sjsing /* First some sanity checks */ 738e500e238Sjsing if (email->type != V_ASN1_IA5STRING) 739e500e238Sjsing return 1; 740e500e238Sjsing if (!email->data || !email->length) 741e500e238Sjsing return 1; 742e500e238Sjsing if (!*sk) 743e500e238Sjsing *sk = sk_OPENSSL_STRING_new(sk_strcmp); 744e500e238Sjsing if (!*sk) 745e500e238Sjsing return 0; 746e500e238Sjsing /* Don't add duplicates */ 747e500e238Sjsing if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1) 748e500e238Sjsing return 1; 749e500e238Sjsing emtmp = strdup((char *)email->data); 750e500e238Sjsing if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) { 751e500e238Sjsing X509_email_free(*sk); 752e500e238Sjsing *sk = NULL; 753e500e238Sjsing return 0; 754e500e238Sjsing } 755e500e238Sjsing return 1; 756e500e238Sjsing } 757e500e238Sjsing 758e500e238Sjsing void 759e500e238Sjsing X509_email_free(STACK_OF(OPENSSL_STRING) *sk) 760e500e238Sjsing { 761e500e238Sjsing sk_OPENSSL_STRING_pop_free(sk, str_free); 762e500e238Sjsing } 763cedac418Stb LCRYPTO_ALIAS(X509_email_free); 764e500e238Sjsing 765e500e238Sjsing typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len, 766e500e238Sjsing const unsigned char *subject, size_t subject_len, unsigned int flags); 767e500e238Sjsing 768e500e238Sjsing /* Skip pattern prefix to match "wildcard" subject */ 769e500e238Sjsing static void 770e500e238Sjsing skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject, 771e500e238Sjsing size_t subject_len, unsigned int flags) 772e500e238Sjsing { 773e500e238Sjsing const unsigned char *pattern = *p; 774e500e238Sjsing size_t pattern_len = *plen; 775e500e238Sjsing 776e500e238Sjsing /* 777e500e238Sjsing * If subject starts with a leading '.' followed by more octets, and 778e500e238Sjsing * pattern is longer, compare just an equal-length suffix with the 779e500e238Sjsing * full subject (starting at the '.'), provided the prefix contains 780e500e238Sjsing * no NULs. 781e500e238Sjsing */ 782e500e238Sjsing if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0) 783e500e238Sjsing return; 784e500e238Sjsing 785e500e238Sjsing while (pattern_len > subject_len && *pattern) { 786e500e238Sjsing if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) && 787e500e238Sjsing *pattern == '.') 788e500e238Sjsing break; 789e500e238Sjsing ++pattern; 790e500e238Sjsing --pattern_len; 791e500e238Sjsing } 792e500e238Sjsing 793e500e238Sjsing /* Skip if entire prefix acceptable */ 794e500e238Sjsing if (pattern_len == subject_len) { 795e500e238Sjsing *p = pattern; 796e500e238Sjsing *plen = pattern_len; 797e500e238Sjsing } 798e500e238Sjsing } 799e500e238Sjsing 800e500e238Sjsing /* 801e500e238Sjsing * Open/BoringSSL uses memcmp for "equal_case" while their 802e500e238Sjsing * "equal_nocase" function is a hand-rolled strncasecmp that does not 803e500e238Sjsing * allow \0 in the pattern. Since an embedded \0 is likely a sign of 804e500e238Sjsing * problems, we simply don't allow it in either case, and then we use 80571743258Sjmc * standard libc functions. 806e500e238Sjsing */ 807e500e238Sjsing 808e500e238Sjsing /* Compare using strncasecmp */ 809e500e238Sjsing static int 810e500e238Sjsing equal_nocase(const unsigned char *pattern, size_t pattern_len, 811e500e238Sjsing const unsigned char *subject, size_t subject_len, unsigned int flags) 812e500e238Sjsing { 813e500e238Sjsing if (memchr(pattern, '\0', pattern_len) != NULL) 814e500e238Sjsing return 0; 815e500e238Sjsing if (memchr(subject, '\0', subject_len) != NULL) 816e500e238Sjsing return 0; 817e500e238Sjsing skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); 818e500e238Sjsing if (pattern_len != subject_len) 819e500e238Sjsing return 0; 820e500e238Sjsing return (strncasecmp(pattern, subject, pattern_len) == 0); 821e500e238Sjsing } 822e500e238Sjsing 823e500e238Sjsing /* Compare using strncmp. */ 824e500e238Sjsing static int 825e500e238Sjsing equal_case(const unsigned char *pattern, size_t pattern_len, 826e500e238Sjsing const unsigned char *subject, size_t subject_len, unsigned int flags) 827e500e238Sjsing { 828e500e238Sjsing if (memchr(pattern, 0, pattern_len) != NULL) 829e500e238Sjsing return 0; 830e500e238Sjsing if (memchr(subject, 0, subject_len) != NULL) 831e500e238Sjsing return 0; 832e500e238Sjsing skip_prefix(&pattern, &pattern_len, subject, subject_len, flags); 833e500e238Sjsing if (pattern_len != subject_len) 834e500e238Sjsing return 0; 835e500e238Sjsing return (strncmp(pattern, subject, pattern_len) == 0); 836e500e238Sjsing } 837e500e238Sjsing 838e500e238Sjsing /* 839e500e238Sjsing * RFC 5280, section 7.5, requires that only the domain is compared in a 840e500e238Sjsing * case-insensitive manner. 841e500e238Sjsing */ 842e500e238Sjsing static int 843e500e238Sjsing equal_email(const unsigned char *a, size_t a_len, const unsigned char *b, 844e500e238Sjsing size_t b_len, unsigned int unused_flags) 845e500e238Sjsing { 846e500e238Sjsing size_t pos = a_len; 847e500e238Sjsing if (a_len != b_len) 848e500e238Sjsing return 0; 849e500e238Sjsing /* 850e500e238Sjsing * We search backwards for the '@' character, so that we do not have to 851e500e238Sjsing * deal with quoted local-parts. The domain part is compared in a 852e500e238Sjsing * case-insensitive manner. 853e500e238Sjsing */ 854e500e238Sjsing while (pos > 0) { 855e500e238Sjsing pos--; 856e500e238Sjsing if (a[pos] == '@' || b[pos] == '@') { 857e500e238Sjsing if (!equal_nocase(a + pos, a_len - pos, b + pos, 858e500e238Sjsing a_len - pos, 0)) 859e500e238Sjsing return 0; 860e500e238Sjsing break; 861e500e238Sjsing } 862e500e238Sjsing } 863e500e238Sjsing if (pos == 0) 864e500e238Sjsing pos = a_len; 865e500e238Sjsing return equal_case(a, pos, b, pos, 0); 866e500e238Sjsing } 867e500e238Sjsing 868e500e238Sjsing /* 869e500e238Sjsing * Compare the prefix and suffix with the subject, and check that the 870e500e238Sjsing * characters in-between are valid. 871e500e238Sjsing */ 872e500e238Sjsing static int 873e500e238Sjsing wildcard_match(const unsigned char *prefix, size_t prefix_len, 874e500e238Sjsing const unsigned char *suffix, size_t suffix_len, 875e500e238Sjsing const unsigned char *subject, size_t subject_len, unsigned int flags) 876e500e238Sjsing { 877e500e238Sjsing const unsigned char *wildcard_start; 878e500e238Sjsing const unsigned char *wildcard_end; 879e500e238Sjsing const unsigned char *p; 880e500e238Sjsing int allow_multi = 0; 881e500e238Sjsing int allow_idna = 0; 882e500e238Sjsing 883e500e238Sjsing if (subject_len < prefix_len + suffix_len) 884e500e238Sjsing return 0; 885e500e238Sjsing if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags)) 886e500e238Sjsing return 0; 887e500e238Sjsing wildcard_start = subject + prefix_len; 888e500e238Sjsing wildcard_end = subject + (subject_len - suffix_len); 889e500e238Sjsing if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags)) 890e500e238Sjsing return 0; 891e500e238Sjsing /* 892e500e238Sjsing * If the wildcard makes up the entire first label, it must match at 893e500e238Sjsing * least one character. 894e500e238Sjsing */ 895e500e238Sjsing if (prefix_len == 0 && *suffix == '.') { 896e500e238Sjsing if (wildcard_start == wildcard_end) 897e500e238Sjsing return 0; 898e500e238Sjsing allow_idna = 1; 899e500e238Sjsing if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS) 900e500e238Sjsing allow_multi = 1; 901e500e238Sjsing } 902e500e238Sjsing /* IDNA labels cannot match partial wildcards */ 903e500e238Sjsing if (!allow_idna && 904e500e238Sjsing subject_len >= 4 905e500e238Sjsing && strncasecmp((char *)subject, "xn--", 4) == 0) 906e500e238Sjsing return 0; 907e500e238Sjsing /* The wildcard may match a literal '*' */ 908e500e238Sjsing if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*') 909e500e238Sjsing return 1; 910e500e238Sjsing /* 911e500e238Sjsing * Check that the part matched by the wildcard contains only 912e500e238Sjsing * permitted characters and only matches a single label unless 913e500e238Sjsing * allow_multi is set. 914e500e238Sjsing */ 915e500e238Sjsing for (p = wildcard_start; p != wildcard_end; ++p) 916e500e238Sjsing if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') || 917e500e238Sjsing ('a' <= *p && *p <= 'z') || *p == '-' || 918e500e238Sjsing (allow_multi && *p == '.'))) 919e500e238Sjsing return 0; 920e500e238Sjsing return 1; 921e500e238Sjsing } 922e500e238Sjsing 923e500e238Sjsing #define LABEL_START (1 << 0) 924e500e238Sjsing #define LABEL_END (1 << 1) 925e500e238Sjsing #define LABEL_HYPHEN (1 << 2) 926e500e238Sjsing #define LABEL_IDNA (1 << 3) 927e500e238Sjsing 928e500e238Sjsing static const unsigned char * 929e500e238Sjsing valid_star(const unsigned char *p, size_t len, unsigned int flags) 930e500e238Sjsing { 931e500e238Sjsing const unsigned char *star = 0; 932e500e238Sjsing size_t i; 933e500e238Sjsing int state = LABEL_START; 934e500e238Sjsing int dots = 0; 935e500e238Sjsing for (i = 0; i < len; ++i) { 936e500e238Sjsing /* 937e500e238Sjsing * Locate first and only legal wildcard, either at the start 938e500e238Sjsing * or end of a non-IDNA first and not final label. 939e500e238Sjsing */ 940e500e238Sjsing if (p[i] == '*') { 941e500e238Sjsing int atstart = (state & LABEL_START); 942e500e238Sjsing int atend = (i == len - 1 || p[i + 1] == '.'); 943e500e238Sjsing /* 944e500e238Sjsing * At most one wildcard per pattern. 945e500e238Sjsing * No wildcards in IDNA labels. 946e500e238Sjsing * No wildcards after the first label. 947e500e238Sjsing */ 948e500e238Sjsing if (star != NULL || (state & LABEL_IDNA) != 0 || dots) 949e500e238Sjsing return NULL; 950e500e238Sjsing /* Only full-label '*.example.com' wildcards? */ 951e500e238Sjsing if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) 952e500e238Sjsing && (!atstart || !atend)) 953e500e238Sjsing return NULL; 954e500e238Sjsing /* No 'foo*bar' wildcards */ 955e500e238Sjsing if (!atstart && !atend) 956e500e238Sjsing return NULL; 957e500e238Sjsing star = &p[i]; 958e500e238Sjsing state &= ~LABEL_START; 959e500e238Sjsing } else if ((state & LABEL_START) != 0) { 960e500e238Sjsing /* 961e500e238Sjsing * At the start of a label, skip any "xn--" and 962e500e238Sjsing * remain in the LABEL_START state, but set the 963e500e238Sjsing * IDNA label state 964e500e238Sjsing */ 965e500e238Sjsing if ((state & LABEL_IDNA) == 0 && len - i >= 4 966e500e238Sjsing && strncasecmp((char *)&p[i], "xn--", 4) == 0) { 967e500e238Sjsing i += 3; 968e500e238Sjsing state |= LABEL_IDNA; 969e500e238Sjsing continue; 970e500e238Sjsing } 971e500e238Sjsing /* Labels must start with a letter or digit */ 972e500e238Sjsing state &= ~LABEL_START; 973e500e238Sjsing if (('a' <= p[i] && p[i] <= 'z') 974e500e238Sjsing || ('A' <= p[i] && p[i] <= 'Z') 975e500e238Sjsing || ('0' <= p[i] && p[i] <= '9')) 976e500e238Sjsing continue; 977e500e238Sjsing return NULL; 978e500e238Sjsing } else if (('a' <= p[i] && p[i] <= 'z') 979e500e238Sjsing || ('A' <= p[i] && p[i] <= 'Z') 980e500e238Sjsing || ('0' <= p[i] && p[i] <= '9')) { 981e500e238Sjsing state &= LABEL_IDNA; 982e500e238Sjsing continue; 983e500e238Sjsing } else if (p[i] == '.') { 984e500e238Sjsing if (state & (LABEL_HYPHEN | LABEL_START)) 985e500e238Sjsing return NULL; 986e500e238Sjsing state = LABEL_START; 987e500e238Sjsing ++dots; 988e500e238Sjsing } else if (p[i] == '-') { 989e500e238Sjsing /* no domain/subdomain starts with '-' */ 990e500e238Sjsing if ((state & LABEL_START) != 0) 991e500e238Sjsing return NULL; 992e500e238Sjsing state |= LABEL_HYPHEN; 993e500e238Sjsing } else 994e500e238Sjsing return NULL; 995e500e238Sjsing } 996e500e238Sjsing 997e500e238Sjsing /* 998e500e238Sjsing * The final label must not end in a hyphen or ".", and 999e500e238Sjsing * there must be at least two dots after the star. 1000e500e238Sjsing */ 1001e500e238Sjsing if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2) 1002e500e238Sjsing return NULL; 1003e500e238Sjsing return star; 1004e500e238Sjsing } 1005e500e238Sjsing 1006e500e238Sjsing /* Compare using wildcards. */ 1007e500e238Sjsing static int 1008e500e238Sjsing equal_wildcard(const unsigned char *pattern, size_t pattern_len, 1009e500e238Sjsing const unsigned char *subject, size_t subject_len, unsigned int flags) 1010e500e238Sjsing { 1011e500e238Sjsing const unsigned char *star = NULL; 1012e500e238Sjsing 1013e500e238Sjsing /* 1014e500e238Sjsing * Subject names starting with '.' can only match a wildcard pattern 1015e500e238Sjsing * via a subject sub-domain pattern suffix match. 1016e500e238Sjsing */ 1017e500e238Sjsing if (!(subject_len > 1 && subject[0] == '.')) 1018e500e238Sjsing star = valid_star(pattern, pattern_len, flags); 1019e500e238Sjsing if (star == NULL) 1020e500e238Sjsing return equal_nocase(pattern, pattern_len, 1021e500e238Sjsing subject, subject_len, flags); 1022e500e238Sjsing return wildcard_match(pattern, star - pattern, 1023e500e238Sjsing star + 1, (pattern + pattern_len) - star - 1, 1024e500e238Sjsing subject, subject_len, flags); 1025e500e238Sjsing } 1026e500e238Sjsing 1027e500e238Sjsing /* 1028e500e238Sjsing * Compare an ASN1_STRING to a supplied string. If they match return 1. If 1029e500e238Sjsing * cmp_type > 0 only compare if string matches the type, otherwise convert it 1030e500e238Sjsing * to UTF8. 1031e500e238Sjsing */ 1032e500e238Sjsing 1033e500e238Sjsing static int 1034e500e238Sjsing do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal, 1035e500e238Sjsing unsigned int flags, const char *b, size_t blen, char **peername) 1036e500e238Sjsing { 1037e500e238Sjsing int rv = 0; 1038e500e238Sjsing 1039e500e238Sjsing if (!a->data || !a->length) 1040e500e238Sjsing return 0; 1041e500e238Sjsing if (cmp_type > 0) { 1042e500e238Sjsing if (cmp_type != a->type) 1043e500e238Sjsing return 0; 1044e500e238Sjsing if (cmp_type == V_ASN1_IA5STRING) 1045e500e238Sjsing rv = equal(a->data, a->length, (unsigned char *)b, 1046e500e238Sjsing blen, flags); 1047e500e238Sjsing else if (a->length == (int)blen && !memcmp(a->data, b, blen)) 1048e500e238Sjsing rv = 1; 1049e500e238Sjsing if (rv > 0 && peername && 1050e500e238Sjsing (*peername = strndup((char *)a->data, a->length)) == NULL) 1051e500e238Sjsing rv = -1; 1052e500e238Sjsing } else { 1053e500e238Sjsing int astrlen; 10549685dac0Stb unsigned char *astr = NULL; 1055e500e238Sjsing astrlen = ASN1_STRING_to_UTF8(&astr, a); 1056e500e238Sjsing if (astrlen < 0) 1057e500e238Sjsing return -1; 1058e500e238Sjsing rv = equal(astr, astrlen, (unsigned char *)b, blen, flags); 1059e500e238Sjsing if (rv > 0 && peername && 1060e500e238Sjsing (*peername = strndup((char *)astr, astrlen)) == NULL) 1061e500e238Sjsing rv = -1; 1062e500e238Sjsing free(astr); 1063e500e238Sjsing } 1064e500e238Sjsing return rv; 1065e500e238Sjsing } 1066e500e238Sjsing 1067e500e238Sjsing static int 1068e500e238Sjsing do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags, 1069e500e238Sjsing int check_type, char **peername) 1070e500e238Sjsing { 1071e500e238Sjsing GENERAL_NAMES *gens = NULL; 1072e500e238Sjsing X509_NAME *name = NULL; 1073e500e238Sjsing size_t i; 1074e500e238Sjsing int j; 1075e500e238Sjsing int cnid = NID_undef; 1076e500e238Sjsing int alt_type; 1077e500e238Sjsing int san_present = 0; 1078e500e238Sjsing int rv = 0; 1079e500e238Sjsing equal_fn equal; 1080e500e238Sjsing 1081e500e238Sjsing /* See below, this flag is internal-only */ 1082e500e238Sjsing flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS; 1083e500e238Sjsing if (check_type == GEN_EMAIL) { 1084e500e238Sjsing cnid = NID_pkcs9_emailAddress; 1085e500e238Sjsing alt_type = V_ASN1_IA5STRING; 1086e500e238Sjsing equal = equal_email; 1087e500e238Sjsing } else if (check_type == GEN_DNS) { 108823258cfeSbeck if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT)) 1089e500e238Sjsing cnid = NID_commonName; 1090e500e238Sjsing /* Implicit client-side DNS sub-domain pattern */ 1091e500e238Sjsing if (chklen > 1 && chk[0] == '.') 1092e500e238Sjsing flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS; 1093e500e238Sjsing alt_type = V_ASN1_IA5STRING; 1094e500e238Sjsing if (flags & X509_CHECK_FLAG_NO_WILDCARDS) 1095e500e238Sjsing equal = equal_nocase; 1096e500e238Sjsing else 1097e500e238Sjsing equal = equal_wildcard; 1098e500e238Sjsing } else { 1099e500e238Sjsing alt_type = V_ASN1_OCTET_STRING; 1100e500e238Sjsing equal = equal_case; 1101e500e238Sjsing } 1102e500e238Sjsing 1103e500e238Sjsing gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); 1104e500e238Sjsing if (gens != NULL) { 1105e500e238Sjsing for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 1106e500e238Sjsing GENERAL_NAME *gen; 1107e500e238Sjsing ASN1_STRING *cstr; 1108e500e238Sjsing gen = sk_GENERAL_NAME_value(gens, i); 1109e500e238Sjsing if (gen->type != check_type) 1110e500e238Sjsing continue; 1111e500e238Sjsing san_present = 1; 1112e500e238Sjsing if (check_type == GEN_EMAIL) 1113e500e238Sjsing cstr = gen->d.rfc822Name; 1114e500e238Sjsing else if (check_type == GEN_DNS) 1115e500e238Sjsing cstr = gen->d.dNSName; 1116e500e238Sjsing else 1117e500e238Sjsing cstr = gen->d.iPAddress; 1118e500e238Sjsing /* Positive on success, negative on error! */ 1119e500e238Sjsing if ((rv = do_check_string(cstr, alt_type, equal, flags, 1120e500e238Sjsing chk, chklen, peername)) != 0) 1121e500e238Sjsing break; 1122e500e238Sjsing } 1123e500e238Sjsing GENERAL_NAMES_free(gens); 1124e500e238Sjsing if (rv != 0) 1125e500e238Sjsing return rv; 1126e500e238Sjsing if (cnid == NID_undef || 1127e500e238Sjsing (san_present && 1128e500e238Sjsing !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT))) 1129e500e238Sjsing return 0; 1130e500e238Sjsing } 1131e500e238Sjsing 1132e500e238Sjsing /* We're done if CN-ID is not pertinent */ 1133e500e238Sjsing if (cnid == NID_undef) 1134e500e238Sjsing return 0; 1135e500e238Sjsing 1136e500e238Sjsing j = -1; 1137e500e238Sjsing name = X509_get_subject_name(x); 1138e500e238Sjsing while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) { 1139e500e238Sjsing X509_NAME_ENTRY *ne; 1140e500e238Sjsing ASN1_STRING *str; 1141e500e238Sjsing if ((ne = X509_NAME_get_entry(name, j)) == NULL) 1142e500e238Sjsing return -1; 1143e500e238Sjsing if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL) 1144e500e238Sjsing return -1; 1145e500e238Sjsing /* Positive on success, negative on error! */ 1146e500e238Sjsing if ((rv = do_check_string(str, -1, equal, flags, 1147e500e238Sjsing chk, chklen, peername)) != 0) 1148e500e238Sjsing return rv; 1149e500e238Sjsing } 1150e500e238Sjsing return 0; 1151e500e238Sjsing } 1152e500e238Sjsing 1153e500e238Sjsing int 1154e500e238Sjsing X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags, 1155e500e238Sjsing char **peername) 1156e500e238Sjsing { 1157e500e238Sjsing if (chk == NULL) 1158e500e238Sjsing return -2; 1159e500e238Sjsing if (chklen == 0) 1160e500e238Sjsing chklen = strlen(chk); 1161e500e238Sjsing else if (memchr(chk, '\0', chklen)) 1162e500e238Sjsing return -2; 1163e500e238Sjsing return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername); 1164e500e238Sjsing } 1165cedac418Stb LCRYPTO_ALIAS(X509_check_host); 1166e500e238Sjsing 1167e500e238Sjsing int 1168e500e238Sjsing X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags) 1169e500e238Sjsing { 1170e500e238Sjsing if (chk == NULL) 1171e500e238Sjsing return -2; 1172e500e238Sjsing if (chklen == 0) 1173e500e238Sjsing chklen = strlen(chk); 1174e500e238Sjsing else if (memchr(chk, '\0', chklen)) 1175e500e238Sjsing return -2; 1176e500e238Sjsing return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL); 1177e500e238Sjsing } 1178cedac418Stb LCRYPTO_ALIAS(X509_check_email); 1179e500e238Sjsing 1180e500e238Sjsing int 1181e500e238Sjsing X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen, 1182e500e238Sjsing unsigned int flags) 1183e500e238Sjsing { 1184e500e238Sjsing if (chk == NULL) 1185e500e238Sjsing return -2; 1186e500e238Sjsing return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL); 1187e500e238Sjsing } 1188cedac418Stb LCRYPTO_ALIAS(X509_check_ip); 1189e500e238Sjsing 1190e500e238Sjsing int 1191e500e238Sjsing X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags) 1192e500e238Sjsing { 1193e500e238Sjsing unsigned char ipout[16]; 1194e500e238Sjsing size_t iplen; 1195e500e238Sjsing 1196e500e238Sjsing if (ipasc == NULL) 1197e500e238Sjsing return -2; 1198e500e238Sjsing iplen = (size_t)a2i_ipadd(ipout, ipasc); 1199e500e238Sjsing if (iplen == 0) 1200e500e238Sjsing return -2; 1201e500e238Sjsing return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL); 1202e500e238Sjsing } 1203cedac418Stb LCRYPTO_ALIAS(X509_check_ip_asc); 1204e500e238Sjsing 1205e500e238Sjsing /* Convert IP addresses both IPv4 and IPv6 into an 1206e500e238Sjsing * OCTET STRING compatible with RFC3280. 1207e500e238Sjsing */ 1208e500e238Sjsing 1209e500e238Sjsing ASN1_OCTET_STRING * 1210e500e238Sjsing a2i_IPADDRESS(const char *ipasc) 1211e500e238Sjsing { 1212e500e238Sjsing unsigned char ipout[16]; 1213e500e238Sjsing ASN1_OCTET_STRING *ret; 1214e500e238Sjsing int iplen; 1215e500e238Sjsing 1216e500e238Sjsing /* If string contains a ':' assume IPv6 */ 1217e500e238Sjsing 1218e500e238Sjsing iplen = a2i_ipadd(ipout, ipasc); 1219e500e238Sjsing 1220e500e238Sjsing if (!iplen) 1221e500e238Sjsing return NULL; 1222e500e238Sjsing 1223e500e238Sjsing ret = ASN1_OCTET_STRING_new(); 1224e500e238Sjsing if (!ret) 1225e500e238Sjsing return NULL; 1226e500e238Sjsing if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) { 1227e500e238Sjsing ASN1_OCTET_STRING_free(ret); 1228e500e238Sjsing return NULL; 1229e500e238Sjsing } 1230e500e238Sjsing return ret; 1231e500e238Sjsing } 1232cedac418Stb LCRYPTO_ALIAS(a2i_IPADDRESS); 1233e500e238Sjsing 1234e500e238Sjsing ASN1_OCTET_STRING * 1235e500e238Sjsing a2i_IPADDRESS_NC(const char *ipasc) 1236e500e238Sjsing { 1237e500e238Sjsing ASN1_OCTET_STRING *ret = NULL; 1238e500e238Sjsing unsigned char ipout[32]; 1239e500e238Sjsing char *iptmp = NULL, *p; 1240e500e238Sjsing int iplen1, iplen2; 1241e500e238Sjsing 1242e500e238Sjsing p = strchr(ipasc, '/'); 1243e500e238Sjsing if (!p) 1244e500e238Sjsing return NULL; 1245e500e238Sjsing iptmp = strdup(ipasc); 1246e500e238Sjsing if (!iptmp) 1247e500e238Sjsing return NULL; 1248e500e238Sjsing p = iptmp + (p - ipasc); 1249e500e238Sjsing *p++ = 0; 1250e500e238Sjsing 1251e500e238Sjsing iplen1 = a2i_ipadd(ipout, iptmp); 1252e500e238Sjsing 1253e500e238Sjsing if (!iplen1) 1254e500e238Sjsing goto err; 1255e500e238Sjsing 1256e500e238Sjsing iplen2 = a2i_ipadd(ipout + iplen1, p); 1257e500e238Sjsing 1258e500e238Sjsing free(iptmp); 1259e500e238Sjsing iptmp = NULL; 1260e500e238Sjsing 1261e500e238Sjsing if (!iplen2 || (iplen1 != iplen2)) 1262e500e238Sjsing goto err; 1263e500e238Sjsing 1264e500e238Sjsing ret = ASN1_OCTET_STRING_new(); 1265e500e238Sjsing if (!ret) 1266e500e238Sjsing goto err; 1267e500e238Sjsing if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) 1268e500e238Sjsing goto err; 1269e500e238Sjsing 1270e500e238Sjsing return ret; 1271e500e238Sjsing 1272e500e238Sjsing err: 1273e500e238Sjsing free(iptmp); 1274e500e238Sjsing if (ret) 1275e500e238Sjsing ASN1_OCTET_STRING_free(ret); 1276e500e238Sjsing return NULL; 1277e500e238Sjsing } 1278cedac418Stb LCRYPTO_ALIAS(a2i_IPADDRESS_NC); 1279e500e238Sjsing 1280e500e238Sjsing 1281e500e238Sjsing int 1282e500e238Sjsing a2i_ipadd(unsigned char *ipout, const char *ipasc) 1283e500e238Sjsing { 1284e500e238Sjsing /* If string contains a ':' assume IPv6 */ 1285e500e238Sjsing 1286e500e238Sjsing if (strchr(ipasc, ':')) { 1287e500e238Sjsing if (!ipv6_from_asc(ipout, ipasc)) 1288e500e238Sjsing return 0; 1289e500e238Sjsing return 16; 1290e500e238Sjsing } else { 1291e500e238Sjsing if (!ipv4_from_asc(ipout, ipasc)) 1292e500e238Sjsing return 0; 1293e500e238Sjsing return 4; 1294e500e238Sjsing } 1295e500e238Sjsing } 1296cedac418Stb LCRYPTO_ALIAS(a2i_ipadd); 1297e500e238Sjsing 1298e500e238Sjsing static int 1299e500e238Sjsing ipv4_from_asc(unsigned char *v4, const char *in) 1300e500e238Sjsing { 1301e500e238Sjsing int a0, a1, a2, a3; 1302e500e238Sjsing if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) 1303e500e238Sjsing return 0; 1304e500e238Sjsing if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) || 1305e500e238Sjsing (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) 1306e500e238Sjsing return 0; 1307e500e238Sjsing v4[0] = a0; 1308e500e238Sjsing v4[1] = a1; 1309e500e238Sjsing v4[2] = a2; 1310e500e238Sjsing v4[3] = a3; 1311e500e238Sjsing return 1; 1312e500e238Sjsing } 1313e500e238Sjsing 1314e500e238Sjsing typedef struct { 1315e500e238Sjsing /* Temporary store for IPV6 output */ 1316e500e238Sjsing unsigned char tmp[16]; 1317e500e238Sjsing /* Total number of bytes in tmp */ 1318e500e238Sjsing int total; 1319e500e238Sjsing /* The position of a zero (corresponding to '::') */ 1320e500e238Sjsing int zero_pos; 1321e500e238Sjsing /* Number of zeroes */ 1322e500e238Sjsing int zero_cnt; 1323e500e238Sjsing } IPV6_STAT; 1324e500e238Sjsing 1325e500e238Sjsing 1326e500e238Sjsing static int 1327e500e238Sjsing ipv6_from_asc(unsigned char *v6, const char *in) 1328e500e238Sjsing { 1329e500e238Sjsing IPV6_STAT v6stat; 1330e500e238Sjsing 1331e500e238Sjsing v6stat.total = 0; 1332e500e238Sjsing v6stat.zero_pos = -1; 1333e500e238Sjsing v6stat.zero_cnt = 0; 1334e500e238Sjsing 1335d1aeef77Sjca /* 1336d1aeef77Sjca * Treat the IPv6 representation as a list of values separated by ':'. 1337d1aeef77Sjca * The presence of a '::' will parse as one (e.g., "2001:db8::1"), 1338d1aeef77Sjca * two (e.g., "2001:db8::") or three (e.g., "::") zero length elements. 1339e500e238Sjsing */ 1340e500e238Sjsing if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) 1341e500e238Sjsing return 0; 1342e500e238Sjsing 1343e500e238Sjsing /* Now for some sanity checks */ 1344e500e238Sjsing 1345e500e238Sjsing if (v6stat.zero_pos == -1) { 1346e500e238Sjsing /* If no '::' must have exactly 16 bytes */ 1347e500e238Sjsing if (v6stat.total != 16) 1348e500e238Sjsing return 0; 1349e500e238Sjsing } else { 1350e500e238Sjsing /* If '::' must have less than 16 bytes */ 1351e500e238Sjsing if (v6stat.total == 16) 1352e500e238Sjsing return 0; 1353e500e238Sjsing /* More than three zeroes is an error */ 1354e500e238Sjsing if (v6stat.zero_cnt > 3) 1355e500e238Sjsing return 0; 1356e500e238Sjsing /* Can only have three zeroes if nothing else present */ 1357e500e238Sjsing else if (v6stat.zero_cnt == 3) { 1358e500e238Sjsing if (v6stat.total > 0) 1359e500e238Sjsing return 0; 1360e500e238Sjsing } 1361e500e238Sjsing /* Can only have two zeroes if at start or end */ 1362e500e238Sjsing else if (v6stat.zero_cnt == 2) { 1363e500e238Sjsing if ((v6stat.zero_pos != 0) && 1364e500e238Sjsing (v6stat.zero_pos != v6stat.total)) 1365e500e238Sjsing return 0; 1366e500e238Sjsing } else 1367e500e238Sjsing /* Can only have one zero if *not* start or end */ 1368e500e238Sjsing { 1369e500e238Sjsing if ((v6stat.zero_pos == 0) || 1370e500e238Sjsing (v6stat.zero_pos == v6stat.total)) 1371e500e238Sjsing return 0; 1372e500e238Sjsing } 1373e500e238Sjsing } 1374e500e238Sjsing 1375e500e238Sjsing /* Format result */ 1376e500e238Sjsing 1377e500e238Sjsing if (v6stat.zero_pos >= 0) { 1378e500e238Sjsing /* Copy initial part */ 1379e500e238Sjsing memcpy(v6, v6stat.tmp, v6stat.zero_pos); 1380e500e238Sjsing /* Zero middle */ 1381e500e238Sjsing memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); 1382e500e238Sjsing /* Copy final part */ 1383e500e238Sjsing if (v6stat.total != v6stat.zero_pos) 1384e500e238Sjsing memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, 1385e500e238Sjsing v6stat.tmp + v6stat.zero_pos, 1386e500e238Sjsing v6stat.total - v6stat.zero_pos); 1387e500e238Sjsing } else 1388e500e238Sjsing memcpy(v6, v6stat.tmp, 16); 1389e500e238Sjsing 1390e500e238Sjsing return 1; 1391e500e238Sjsing } 1392e500e238Sjsing 1393e500e238Sjsing static int 1394e500e238Sjsing ipv6_cb(const char *elem, int len, void *usr) 1395e500e238Sjsing { 1396e500e238Sjsing IPV6_STAT *s = usr; 1397e500e238Sjsing 1398e500e238Sjsing /* Error if 16 bytes written */ 1399e500e238Sjsing if (s->total == 16) 1400e500e238Sjsing return 0; 1401e500e238Sjsing if (len == 0) { 1402e500e238Sjsing /* Zero length element, corresponds to '::' */ 1403e500e238Sjsing if (s->zero_pos == -1) 1404e500e238Sjsing s->zero_pos = s->total; 1405e500e238Sjsing /* If we've already got a :: its an error */ 1406e500e238Sjsing else if (s->zero_pos != s->total) 1407e500e238Sjsing return 0; 1408e500e238Sjsing s->zero_cnt++; 1409e500e238Sjsing } else { 1410e500e238Sjsing /* If more than 4 characters could be final a.b.c.d form */ 1411e500e238Sjsing if (len > 4) { 1412e500e238Sjsing /* Need at least 4 bytes left */ 1413e500e238Sjsing if (s->total > 12) 1414e500e238Sjsing return 0; 1415e500e238Sjsing /* Must be end of string */ 1416e500e238Sjsing if (elem[len]) 1417e500e238Sjsing return 0; 1418e500e238Sjsing if (!ipv4_from_asc(s->tmp + s->total, elem)) 1419e500e238Sjsing return 0; 1420e500e238Sjsing s->total += 4; 1421e500e238Sjsing } else { 1422e500e238Sjsing if (!ipv6_hex(s->tmp + s->total, elem, len)) 1423e500e238Sjsing return 0; 1424e500e238Sjsing s->total += 2; 1425e500e238Sjsing } 1426e500e238Sjsing } 1427e500e238Sjsing return 1; 1428e500e238Sjsing } 1429e500e238Sjsing 1430e500e238Sjsing /* Convert a string of up to 4 hex digits into the corresponding 1431e500e238Sjsing * IPv6 form. 1432e500e238Sjsing */ 1433e500e238Sjsing 1434e500e238Sjsing static int 1435e500e238Sjsing ipv6_hex(unsigned char *out, const char *in, int inlen) 1436e500e238Sjsing { 1437e500e238Sjsing unsigned char c; 1438e500e238Sjsing unsigned int num = 0; 1439e500e238Sjsing 1440e500e238Sjsing if (inlen > 4) 1441e500e238Sjsing return 0; 1442e500e238Sjsing while (inlen--) { 1443e500e238Sjsing c = *in++; 1444e500e238Sjsing num <<= 4; 1445e500e238Sjsing if ((c >= '0') && (c <= '9')) 1446e500e238Sjsing num |= c - '0'; 1447e500e238Sjsing else if ((c >= 'A') && (c <= 'F')) 1448e500e238Sjsing num |= c - 'A' + 10; 1449e500e238Sjsing else if ((c >= 'a') && (c <= 'f')) 1450e500e238Sjsing num |= c - 'a' + 10; 1451e500e238Sjsing else 1452e500e238Sjsing return 0; 1453e500e238Sjsing } 1454e500e238Sjsing out[0] = num >> 8; 1455e500e238Sjsing out[1] = num & 0xff; 1456e500e238Sjsing return 1; 1457e500e238Sjsing } 1458e500e238Sjsing 1459e500e238Sjsing int 1460e500e238Sjsing X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, 1461e500e238Sjsing unsigned long chtype) 1462e500e238Sjsing { 1463e500e238Sjsing CONF_VALUE *v; 1464e500e238Sjsing int i, mval; 1465e500e238Sjsing char *p, *type; 1466e500e238Sjsing 1467e500e238Sjsing if (!nm) 1468e500e238Sjsing return 0; 1469e500e238Sjsing 1470e500e238Sjsing for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { 1471e500e238Sjsing v = sk_CONF_VALUE_value(dn_sk, i); 1472e500e238Sjsing type = v->name; 1473e500e238Sjsing /* Skip past any leading X. X: X, etc to allow for 1474e500e238Sjsing * multiple instances 1475e500e238Sjsing */ 1476e500e238Sjsing for (p = type; *p; p++) 1477e500e238Sjsing if ((*p == ':') || (*p == ',') || (*p == '.')) { 1478e500e238Sjsing p++; 1479e500e238Sjsing if (*p) 1480e500e238Sjsing type = p; 1481e500e238Sjsing break; 1482e500e238Sjsing } 1483e500e238Sjsing if (*type == '+') { 1484e500e238Sjsing mval = -1; 1485e500e238Sjsing type++; 1486e500e238Sjsing } else 1487e500e238Sjsing mval = 0; 1488e500e238Sjsing if (!X509_NAME_add_entry_by_txt(nm, type, chtype, 1489e500e238Sjsing (unsigned char *) v->value, -1, -1, mval)) 1490e500e238Sjsing return 0; 1491e500e238Sjsing } 1492e500e238Sjsing return 1; 1493e500e238Sjsing } 1494cedac418Stb LCRYPTO_ALIAS(X509V3_NAME_from_section); 1495