Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/x509/x509_utl.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: x509_utl.c,v 1.3 2022/05/20 07:58:54 tb Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 1999-2003 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
/* X509 v3 extension utilities */
59
60
#include <ctype.h>
61
#include <stdio.h>
62
#include <string.h>
63
64
#include <openssl/bn.h>
65
#include <openssl/conf.h>
66
#include <openssl/err.h>
67
#include <openssl/x509v3.h>
68
69
char *bn_to_string(const BIGNUM *bn);
70
static char *strip_spaces(char *name);
71
static int sk_strcmp(const char * const *a, const char * const *b);
72
static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
73
    GENERAL_NAMES *gens);
74
static void str_free(OPENSSL_STRING str);
75
static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
76
77
static int ipv4_from_asc(unsigned char *v4, const char *in);
78
static int ipv6_from_asc(unsigned char *v6, const char *in);
79
static int ipv6_cb(const char *elem, int len, void *usr);
80
static int ipv6_hex(unsigned char *out, const char *in, int inlen);
81
82
/* Add a CONF_VALUE name-value pair to stack. */
83
int
84
X509V3_add_value(const char *name, const char *value,
85
    STACK_OF(CONF_VALUE) **extlist)
86
0
{
87
0
  CONF_VALUE *vtmp = NULL;
88
0
  STACK_OF(CONF_VALUE) *free_exts = NULL;
89
90
0
  if ((vtmp = calloc(1, sizeof(CONF_VALUE))) == NULL)
91
0
    goto err;
92
0
  if (name != NULL) {
93
0
    if ((vtmp->name = strdup(name)) == NULL)
94
0
      goto err;
95
0
  }
96
0
  if (value != NULL) {
97
0
    if ((vtmp->value = strdup(value)) == NULL)
98
0
      goto err;
99
0
  }
100
101
0
  if (*extlist == NULL) {
102
0
    if ((free_exts = *extlist = sk_CONF_VALUE_new_null()) == NULL)
103
0
      goto err;
104
0
  }
105
106
0
  if (!sk_CONF_VALUE_push(*extlist, vtmp))
107
0
    goto err;
108
109
0
  return 1;
110
111
0
 err:
112
0
  X509V3error(ERR_R_MALLOC_FAILURE);
113
0
  X509V3_conf_free(vtmp);
114
0
  if (free_exts != NULL) {
115
0
    sk_CONF_VALUE_free(*extlist);
116
0
    *extlist = NULL;
117
0
  }
118
0
  return 0;
119
0
}
120
121
int
122
X509V3_add_value_uchar(const char *name, const unsigned char *value,
123
    STACK_OF(CONF_VALUE) **extlist)
124
0
{
125
0
  return X509V3_add_value(name, (const char *)value, extlist);
126
0
}
127
128
/* Free function for STACK_OF(CONF_VALUE) */
129
130
void
131
X509V3_conf_free(CONF_VALUE *conf)
132
0
{
133
0
  if (!conf)
134
0
    return;
135
0
  free(conf->name);
136
0
  free(conf->value);
137
0
  free(conf->section);
138
0
  free(conf);
139
0
}
140
141
int
142
X509V3_add_value_bool(const char *name, int asn1_bool,
143
    STACK_OF(CONF_VALUE) **extlist)
144
0
{
145
0
  if (asn1_bool)
146
0
    return X509V3_add_value(name, "TRUE", extlist);
147
0
  return X509V3_add_value(name, "FALSE", extlist);
148
0
}
149
150
int
151
X509V3_add_value_bool_nf(const char *name, int asn1_bool,
152
    STACK_OF(CONF_VALUE) **extlist)
153
0
{
154
0
  if (asn1_bool)
155
0
    return X509V3_add_value(name, "TRUE", extlist);
156
0
  return 1;
157
0
}
158
159
char *
160
bn_to_string(const BIGNUM *bn)
161
0
{
162
0
  const char *sign = "";
163
0
  char *bnstr, *hex;
164
0
  char *ret = NULL;
165
166
  /* Only display small numbers in decimal, as conversion is quadratic. */
167
0
  if (BN_num_bits(bn) < 128)
168
0
    return BN_bn2dec(bn);
169
170
0
  if ((hex = bnstr = BN_bn2hex(bn)) == NULL)
171
0
    goto err;
172
173
0
  if (BN_is_negative(bn)) {
174
0
    sign = "-";
175
0
    hex++;
176
0
  }
177
178
0
  if (asprintf(&ret, "%s0x%s", sign, hex) == -1)
179
0
    ret = NULL;
180
181
0
 err:
182
0
  free(bnstr);
183
0
  return ret;
184
0
}
185
186
char *
187
i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, const ASN1_ENUMERATED *a)
188
0
{
189
0
  BIGNUM *bntmp;
190
0
  char *strtmp = NULL;
191
192
0
  if (a == NULL)
193
0
    return NULL;
194
0
  if ((bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) == NULL ||
195
0
      (strtmp = bn_to_string(bntmp)) == NULL)
196
0
    X509V3error(ERR_R_MALLOC_FAILURE);
197
0
  BN_free(bntmp);
198
0
  return strtmp;
199
0
}
200
201
char *
202
i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, const ASN1_INTEGER *a)
203
0
{
204
0
  BIGNUM *bntmp;
205
0
  char *strtmp = NULL;
206
207
0
  if (a == NULL)
208
0
    return NULL;
209
0
  if ((bntmp = ASN1_INTEGER_to_BN(a, NULL)) == NULL ||
210
0
      (strtmp = bn_to_string(bntmp)) == NULL)
211
0
    X509V3error(ERR_R_MALLOC_FAILURE);
212
0
  BN_free(bntmp);
213
0
  return strtmp;
214
0
}
215
216
ASN1_INTEGER *
217
s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, const char *value)
218
0
{
219
0
  BIGNUM *bn = NULL;
220
0
  ASN1_INTEGER *aint;
221
0
  int isneg, ishex;
222
0
  int ret;
223
224
0
  if (!value) {
225
0
    X509V3error(X509V3_R_INVALID_NULL_VALUE);
226
0
    return 0;
227
0
  }
228
0
  bn = BN_new();
229
0
  if (value[0] == '-') {
230
0
    value++;
231
0
    isneg = 1;
232
0
  } else
233
0
    isneg = 0;
234
235
0
  if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
236
0
    value += 2;
237
0
    ishex = 1;
238
0
  } else
239
0
    ishex = 0;
240
241
0
  if (ishex)
242
0
    ret = BN_hex2bn(&bn, value);
243
0
  else
244
0
    ret = BN_dec2bn(&bn, value);
245
246
0
  if (!ret || value[ret]) {
247
0
    BN_free(bn);
248
0
    X509V3error(X509V3_R_BN_DEC2BN_ERROR);
249
0
    return 0;
250
0
  }
251
252
0
  if (isneg && BN_is_zero(bn))
253
0
    isneg = 0;
254
255
0
  aint = BN_to_ASN1_INTEGER(bn, NULL);
256
0
  BN_free(bn);
257
0
  if (!aint) {
258
0
    X509V3error(X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
259
0
    return 0;
260
0
  }
261
0
  if (isneg)
262
0
    aint->type |= V_ASN1_NEG;
263
0
  return aint;
264
0
}
265
266
int
267
X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
268
    STACK_OF(CONF_VALUE) **extlist)
269
0
{
270
0
  char *strtmp;
271
0
  int ret;
272
273
0
  if (!aint)
274
0
    return 1;
275
0
  if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
276
0
    return 0;
277
0
  ret = X509V3_add_value(name, strtmp, extlist);
278
0
  free(strtmp);
279
0
  return ret;
280
0
}
281
282
int
283
X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool)
284
0
{
285
0
  char *btmp;
286
287
0
  if (!(btmp = value->value))
288
0
    goto err;
289
0
  if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true") ||
290
0
      !strcmp(btmp, "Y") || !strcmp(btmp, "y") ||
291
0
      !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
292
0
    *asn1_bool = 0xff;
293
0
    return 1;
294
0
  } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false") ||
295
0
      !strcmp(btmp, "N") || !strcmp(btmp, "n") ||
296
0
      !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
297
0
    *asn1_bool = 0;
298
0
    return 1;
299
0
  }
300
301
0
 err:
302
0
  X509V3error(X509V3_R_INVALID_BOOLEAN_STRING);
303
0
  X509V3_conf_err(value);
304
0
  return 0;
305
0
}
306
307
int
308
X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint)
309
0
{
310
0
  ASN1_INTEGER *itmp;
311
312
0
  if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
313
0
    X509V3_conf_err(value);
314
0
    return 0;
315
0
  }
316
0
  *aint = itmp;
317
0
  return 1;
318
0
}
319
320
0
#define HDR_NAME  1
321
0
#define HDR_VALUE 2
322
323
/*#define DEBUG*/
324
325
STACK_OF(CONF_VALUE) *
326
X509V3_parse_list(const char *line)
327
0
{
328
0
  char *p, *q, c;
329
0
  char *ntmp, *vtmp;
330
0
  STACK_OF(CONF_VALUE) *values = NULL;
331
0
  char *linebuf;
332
0
  int state;
333
334
  /* We are going to modify the line so copy it first */
335
0
  if ((linebuf = strdup(line)) == NULL) {
336
0
    X509V3error(ERR_R_MALLOC_FAILURE);
337
0
    goto err;
338
0
  }
339
0
  state = HDR_NAME;
340
0
  ntmp = NULL;
341
342
  /* Go through all characters */
343
0
  for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') &&
344
0
      (c != '\n'); p++) {
345
346
0
    switch (state) {
347
0
    case HDR_NAME:
348
0
      if (c == ':') {
349
0
        state = HDR_VALUE;
350
0
        *p = 0;
351
0
        ntmp = strip_spaces(q);
352
0
        if (!ntmp) {
353
0
          X509V3error(X509V3_R_INVALID_NULL_NAME);
354
0
          goto err;
355
0
        }
356
0
        q = p + 1;
357
0
      } else if (c == ',') {
358
0
        *p = 0;
359
0
        ntmp = strip_spaces(q);
360
0
        q = p + 1;
361
0
        if (!ntmp) {
362
0
          X509V3error(X509V3_R_INVALID_NULL_NAME);
363
0
          goto err;
364
0
        }
365
0
        X509V3_add_value(ntmp, NULL, &values);
366
0
      }
367
0
      break;
368
369
0
    case HDR_VALUE:
370
0
      if (c == ',') {
371
0
        state = HDR_NAME;
372
0
        *p = 0;
373
0
        vtmp = strip_spaces(q);
374
0
        if (!vtmp) {
375
0
          X509V3error(X509V3_R_INVALID_NULL_VALUE);
376
0
          goto err;
377
0
        }
378
0
        X509V3_add_value(ntmp, vtmp, &values);
379
0
        ntmp = NULL;
380
0
        q = p + 1;
381
0
      }
382
383
0
    }
384
0
  }
385
386
0
  if (state == HDR_VALUE) {
387
0
    vtmp = strip_spaces(q);
388
0
    if (!vtmp) {
389
0
      X509V3error(X509V3_R_INVALID_NULL_VALUE);
390
0
      goto err;
391
0
    }
392
0
    X509V3_add_value(ntmp, vtmp, &values);
393
0
  } else {
394
0
    ntmp = strip_spaces(q);
395
0
    if (!ntmp) {
396
0
      X509V3error(X509V3_R_INVALID_NULL_NAME);
397
0
      goto err;
398
0
    }
399
0
    X509V3_add_value(ntmp, NULL, &values);
400
0
  }
401
0
  free(linebuf);
402
0
  return values;
403
404
0
 err:
405
0
  free(linebuf);
406
0
  sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
407
0
  return NULL;
408
409
0
}
410
411
/* Delete leading and trailing spaces from a string */
412
static char *
413
strip_spaces(char *name)
414
0
{
415
0
  char *p, *q;
416
417
  /* Skip over leading spaces */
418
0
  p = name;
419
0
  while (*p && isspace((unsigned char)*p))
420
0
    p++;
421
0
  if (!*p)
422
0
    return NULL;
423
0
  q = p + strlen(p) - 1;
424
0
  while ((q != p) && isspace((unsigned char)*q))
425
0
    q--;
426
0
  if (p != q)
427
0
    q[1] = 0;
428
0
  if (!*p)
429
0
    return NULL;
430
0
  return p;
431
0
}
432
433
/* hex string utilities */
434
435
/* Given a buffer of length 'len' return a malloc'ed string with its
436
 * hex representation
437
 */
438
char *
439
hex_to_string(const unsigned char *buffer, long len)
440
0
{
441
0
  char *tmp, *q;
442
0
  const unsigned char *p;
443
0
  int i;
444
0
  static const char hexdig[] = "0123456789ABCDEF";
445
446
0
  if (!buffer || !len)
447
0
    return NULL;
448
0
  if (!(tmp = malloc(len * 3 + 1))) {
449
0
    X509V3error(ERR_R_MALLOC_FAILURE);
450
0
    return NULL;
451
0
  }
452
0
  q = tmp;
453
0
  for (i = 0, p = buffer; i < len; i++, p++) {
454
0
    *q++ = hexdig[(*p >> 4) & 0xf];
455
0
    *q++ = hexdig[*p & 0xf];
456
0
    *q++ = ':';
457
0
  }
458
0
  q[-1] = 0;
459
0
  return tmp;
460
0
}
461
462
/* Give a string of hex digits convert to
463
 * a buffer
464
 */
465
466
unsigned char *
467
string_to_hex(const char *str, long *len)
468
0
{
469
0
  unsigned char *hexbuf, *q;
470
0
  unsigned char ch, cl, *p;
471
0
  if (!str) {
472
0
    X509V3error(X509V3_R_INVALID_NULL_ARGUMENT);
473
0
    return NULL;
474
0
  }
475
0
  if (!(hexbuf = malloc(strlen(str) >> 1)))
476
0
    goto err;
477
0
  for (p = (unsigned char *)str, q = hexbuf; *p; ) {
478
0
    ch = *p++;
479
0
    if (ch == ':')
480
0
      continue;
481
0
    cl = *p++;
482
0
    if (!cl) {
483
0
      X509V3error(X509V3_R_ODD_NUMBER_OF_DIGITS);
484
0
      free(hexbuf);
485
0
      return NULL;
486
0
    }
487
0
    ch = tolower(ch);
488
0
    cl = tolower(cl);
489
490
0
    if ((ch >= '0') && (ch <= '9'))
491
0
      ch -= '0';
492
0
    else if ((ch >= 'a') && (ch <= 'f'))
493
0
      ch -= 'a' - 10;
494
0
    else
495
0
      goto badhex;
496
497
0
    if ((cl >= '0') && (cl <= '9'))
498
0
      cl -= '0';
499
0
    else if ((cl >= 'a') && (cl <= 'f'))
500
0
      cl -= 'a' - 10;
501
0
    else
502
0
      goto badhex;
503
504
0
    *q++ = (ch << 4) | cl;
505
0
  }
506
507
0
  if (len)
508
0
    *len = q - hexbuf;
509
510
0
  return hexbuf;
511
512
0
 err:
513
0
  free(hexbuf);
514
0
  X509V3error(ERR_R_MALLOC_FAILURE);
515
0
  return NULL;
516
517
0
 badhex:
518
0
  free(hexbuf);
519
0
  X509V3error(X509V3_R_ILLEGAL_HEX_DIGIT);
520
0
  return NULL;
521
0
}
522
523
/* V2I name comparison function: returns zero if 'name' matches
524
 * cmp or cmp.*
525
 */
526
527
int
528
name_cmp(const char *name, const char *cmp)
529
0
{
530
0
  int len, ret;
531
0
  char c;
532
533
0
  len = strlen(cmp);
534
0
  if ((ret = strncmp(name, cmp, len)))
535
0
    return ret;
536
0
  c = name[len];
537
0
  if (!c || (c=='.'))
538
0
    return 0;
539
0
  return 1;
540
0
}
541
542
static int
543
sk_strcmp(const char * const *a, const char * const *b)
544
0
{
545
0
  return strcmp(*a, *b);
546
0
}
547
548
STACK_OF(OPENSSL_STRING) *
549
X509_get1_email(X509 *x)
550
0
{
551
0
  GENERAL_NAMES *gens;
552
0
  STACK_OF(OPENSSL_STRING) *ret;
553
554
0
  gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
555
0
  ret = get_email(X509_get_subject_name(x), gens);
556
0
  sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
557
0
  return ret;
558
0
}
559
560
STACK_OF(OPENSSL_STRING) *
561
X509_get1_ocsp(X509 *x)
562
0
{
563
0
  AUTHORITY_INFO_ACCESS *info;
564
0
  STACK_OF(OPENSSL_STRING) *ret = NULL;
565
0
  int i;
566
567
0
  info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
568
0
  if (!info)
569
0
    return NULL;
570
0
  for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
571
0
    ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
572
0
    if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
573
0
      if (ad->location->type == GEN_URI) {
574
0
        if (!append_ia5(&ret,
575
0
            ad->location->d.uniformResourceIdentifier))
576
0
          break;
577
0
      }
578
0
    }
579
0
  }
580
0
  AUTHORITY_INFO_ACCESS_free(info);
581
0
  return ret;
582
0
}
583
584
STACK_OF(OPENSSL_STRING) *
585
X509_REQ_get1_email(X509_REQ *x)
586
0
{
587
0
  GENERAL_NAMES *gens;
588
0
  STACK_OF(X509_EXTENSION) *exts;
589
0
  STACK_OF(OPENSSL_STRING) *ret;
590
591
0
  exts = X509_REQ_get_extensions(x);
592
0
  gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
593
0
  ret = get_email(X509_REQ_get_subject_name(x), gens);
594
0
  sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
595
0
  sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
596
0
  return ret;
597
0
}
598
599
600
static STACK_OF(OPENSSL_STRING) *
601
get_email(X509_NAME *name, GENERAL_NAMES *gens)
602
0
{
603
0
  STACK_OF(OPENSSL_STRING) *ret = NULL;
604
0
  X509_NAME_ENTRY *ne;
605
0
  ASN1_IA5STRING *email;
606
0
  GENERAL_NAME *gen;
607
0
  int i;
608
609
  /* Now add any email address(es) to STACK */
610
0
  i = -1;
611
612
  /* First supplied X509_NAME */
613
0
  while ((i = X509_NAME_get_index_by_NID(name,
614
0
      NID_pkcs9_emailAddress, i)) >= 0) {
615
0
    ne = X509_NAME_get_entry(name, i);
616
0
    email = X509_NAME_ENTRY_get_data(ne);
617
0
    if (!append_ia5(&ret, email))
618
0
      return NULL;
619
0
  }
620
0
  for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
621
0
    gen = sk_GENERAL_NAME_value(gens, i);
622
0
    if (gen->type != GEN_EMAIL)
623
0
      continue;
624
0
    if (!append_ia5(&ret, gen->d.ia5))
625
0
      return NULL;
626
0
  }
627
0
  return ret;
628
0
}
629
630
static void
631
str_free(OPENSSL_STRING str)
632
0
{
633
0
  free(str);
634
0
}
635
636
static int
637
append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
638
0
{
639
0
  char *emtmp;
640
641
  /* First some sanity checks */
642
0
  if (email->type != V_ASN1_IA5STRING)
643
0
    return 1;
644
0
  if (!email->data || !email->length)
645
0
    return 1;
646
0
  if (!*sk)
647
0
    *sk = sk_OPENSSL_STRING_new(sk_strcmp);
648
0
  if (!*sk)
649
0
    return 0;
650
  /* Don't add duplicates */
651
0
  if (sk_OPENSSL_STRING_find(*sk, (char *)email->data) != -1)
652
0
    return 1;
653
0
  emtmp = strdup((char *)email->data);
654
0
  if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
655
0
    X509_email_free(*sk);
656
0
    *sk = NULL;
657
0
    return 0;
658
0
  }
659
0
  return 1;
660
0
}
661
662
void
663
X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
664
0
{
665
0
  sk_OPENSSL_STRING_pop_free(sk, str_free);
666
0
}
667
668
typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len,
669
    const unsigned char *subject, size_t subject_len, unsigned int flags);
670
671
/* Skip pattern prefix to match "wildcard" subject */
672
static void
673
skip_prefix(const unsigned char **p, size_t *plen, const unsigned char *subject,
674
    size_t subject_len, unsigned int flags)
675
0
{
676
0
  const unsigned char *pattern = *p;
677
0
  size_t pattern_len = *plen;
678
679
  /*
680
   * If subject starts with a leading '.' followed by more octets, and
681
   * pattern is longer, compare just an equal-length suffix with the
682
   * full subject (starting at the '.'), provided the prefix contains
683
   * no NULs.
684
   */
685
0
  if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
686
0
    return;
687
688
0
  while (pattern_len > subject_len && *pattern) {
689
0
    if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
690
0
        *pattern == '.')
691
0
      break;
692
0
    ++pattern;
693
0
    --pattern_len;
694
0
  }
695
696
  /* Skip if entire prefix acceptable */
697
0
  if (pattern_len == subject_len) {
698
0
    *p = pattern;
699
0
    *plen = pattern_len;
700
0
  }
701
0
}
702
703
/*
704
 * Open/BoringSSL uses memcmp for "equal_case" while their
705
 * "equal_nocase" function is a hand-rolled strncasecmp that does not
706
 * allow \0 in the pattern. Since an embedded \0 is likely a sign of
707
 * problems, we simply don't allow it in either case, and then we use
708
 * standard libc funcitons.
709
 */
710
711
/* Compare using strncasecmp */
712
static int
713
equal_nocase(const unsigned char *pattern, size_t pattern_len,
714
    const unsigned char *subject, size_t subject_len, unsigned int flags)
715
0
{
716
0
  if (memchr(pattern, '\0', pattern_len) != NULL)
717
0
    return 0;
718
0
  if (memchr(subject, '\0', subject_len) != NULL)
719
0
    return 0;
720
0
  skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
721
0
  if (pattern_len != subject_len)
722
0
    return 0;
723
0
  return (strncasecmp(pattern, subject, pattern_len) == 0);
724
0
}
725
726
/* Compare using strncmp. */
727
static int
728
equal_case(const unsigned char *pattern, size_t pattern_len,
729
    const unsigned char *subject, size_t subject_len, unsigned int flags)
730
0
{
731
0
  if (memchr(pattern, 0, pattern_len) != NULL)
732
0
    return 0;
733
0
  if (memchr(subject, 0, subject_len) != NULL)
734
0
    return 0;
735
0
  skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
736
0
  if (pattern_len != subject_len)
737
0
    return 0;
738
0
  return (strncmp(pattern, subject, pattern_len) == 0);
739
0
}
740
741
/*
742
 * RFC 5280, section 7.5, requires that only the domain is compared in a
743
 * case-insensitive manner.
744
 */
745
static int
746
equal_email(const unsigned char *a, size_t a_len, const unsigned char *b,
747
    size_t b_len, unsigned int unused_flags)
748
0
{
749
0
  size_t pos = a_len;
750
0
  if (a_len != b_len)
751
0
    return 0;
752
  /*
753
   * We search backwards for the '@' character, so that we do not have to
754
   * deal with quoted local-parts.  The domain part is compared in a
755
   * case-insensitive manner.
756
   */
757
0
  while (pos > 0) {
758
0
    pos--;
759
0
    if (a[pos] == '@' || b[pos] == '@') {
760
0
      if (!equal_nocase(a + pos, a_len - pos, b + pos,
761
0
          a_len - pos, 0))
762
0
        return 0;
763
0
      break;
764
0
    }
765
0
  }
766
0
  if (pos == 0)
767
0
    pos = a_len;
768
0
  return equal_case(a, pos, b, pos, 0);
769
0
}
770
771
/*
772
 * Compare the prefix and suffix with the subject, and check that the
773
 * characters in-between are valid.
774
 */
775
static int
776
wildcard_match(const unsigned char *prefix, size_t prefix_len,
777
    const unsigned char *suffix, size_t suffix_len,
778
    const unsigned char *subject, size_t subject_len, unsigned int flags)
779
0
{
780
0
  const unsigned char *wildcard_start;
781
0
  const unsigned char *wildcard_end;
782
0
  const unsigned char *p;
783
0
  int allow_multi = 0;
784
0
  int allow_idna = 0;
785
786
0
  if (subject_len < prefix_len + suffix_len)
787
0
    return 0;
788
0
  if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
789
0
    return 0;
790
0
  wildcard_start = subject + prefix_len;
791
0
  wildcard_end = subject + (subject_len - suffix_len);
792
0
  if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
793
0
    return 0;
794
  /*
795
   * If the wildcard makes up the entire first label, it must match at
796
   * least one character.
797
   */
798
0
  if (prefix_len == 0 && *suffix == '.') {
799
0
    if (wildcard_start == wildcard_end)
800
0
      return 0;
801
0
    allow_idna = 1;
802
0
    if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
803
0
      allow_multi = 1;
804
0
  }
805
  /* IDNA labels cannot match partial wildcards */
806
0
  if (!allow_idna &&
807
0
      subject_len >= 4
808
0
      && strncasecmp((char *)subject, "xn--", 4) == 0)
809
0
    return 0;
810
  /* The wildcard may match a literal '*' */
811
0
  if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
812
0
    return 1;
813
  /*
814
   * Check that the part matched by the wildcard contains only
815
   * permitted characters and only matches a single label unless
816
   * allow_multi is set.
817
   */
818
0
  for (p = wildcard_start; p != wildcard_end; ++p)
819
0
    if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
820
0
        ('a' <= *p && *p <= 'z') || *p == '-' ||
821
0
        (allow_multi && *p == '.')))
822
0
      return 0;
823
0
  return 1;
824
0
}
825
826
0
#define LABEL_START     (1 << 0)
827
#define LABEL_END       (1 << 1)
828
0
#define LABEL_HYPHEN    (1 << 2)
829
0
#define LABEL_IDNA      (1 << 3)
830
831
static const unsigned char *
832
valid_star(const unsigned char *p, size_t len, unsigned int flags)
833
0
{
834
0
  const unsigned char *star = 0;
835
0
  size_t i;
836
0
  int state = LABEL_START;
837
0
  int dots = 0;
838
0
  for (i = 0; i < len; ++i) {
839
    /*
840
     * Locate first and only legal wildcard, either at the start
841
     * or end of a non-IDNA first and not final label.
842
     */
843
0
    if (p[i] == '*') {
844
0
      int atstart = (state & LABEL_START);
845
0
      int atend = (i == len - 1 || p[i + 1] == '.');
846
      /*
847
       * At most one wildcard per pattern.
848
       * No wildcards in IDNA labels.
849
       * No wildcards after the first label.
850
       */
851
0
      if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
852
0
        return NULL;
853
      /* Only full-label '*.example.com' wildcards? */
854
0
      if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
855
0
          && (!atstart || !atend))
856
0
        return NULL;
857
      /* No 'foo*bar' wildcards */
858
0
      if (!atstart && !atend)
859
0
        return NULL;
860
0
      star = &p[i];
861
0
      state &= ~LABEL_START;
862
0
    } else if ((state & LABEL_START) != 0) {
863
      /*
864
       * At the start of a label, skip any "xn--" and
865
       * remain in the LABEL_START state, but set the
866
       * IDNA label state
867
       */
868
0
      if ((state & LABEL_IDNA) == 0 && len - i >= 4
869
0
          && strncasecmp((char *)&p[i], "xn--", 4) == 0) {
870
0
        i += 3;
871
0
        state |= LABEL_IDNA;
872
0
        continue;
873
0
      }
874
      /* Labels must start with a letter or digit */
875
0
      state &= ~LABEL_START;
876
0
      if (('a' <= p[i] && p[i] <= 'z')
877
0
          || ('A' <= p[i] && p[i] <= 'Z')
878
0
          || ('0' <= p[i] && p[i] <= '9'))
879
0
        continue;
880
0
      return NULL;
881
0
    } else if (('a' <= p[i] && p[i] <= 'z')
882
0
        || ('A' <= p[i] && p[i] <= 'Z')
883
0
        || ('0' <= p[i] && p[i] <= '9')) {
884
0
      state &= LABEL_IDNA;
885
0
      continue;
886
0
    } else if (p[i] == '.') {
887
0
      if (state & (LABEL_HYPHEN | LABEL_START))
888
0
        return NULL;
889
0
      state = LABEL_START;
890
0
      ++dots;
891
0
    } else if (p[i] == '-') {
892
      /* no domain/subdomain starts with '-' */
893
0
      if ((state & LABEL_START) != 0)
894
0
        return NULL;
895
0
      state |= LABEL_HYPHEN;
896
0
    } else
897
0
      return NULL;
898
0
  }
899
900
  /*
901
   * The final label must not end in a hyphen or ".", and
902
   * there must be at least two dots after the star.
903
   */
904
0
  if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
905
0
    return NULL;
906
0
  return star;
907
0
}
908
909
/* Compare using wildcards. */
910
static int
911
equal_wildcard(const unsigned char *pattern, size_t pattern_len,
912
    const unsigned char *subject, size_t subject_len, unsigned int flags)
913
0
{
914
0
  const unsigned char *star = NULL;
915
916
  /*
917
   * Subject names starting with '.' can only match a wildcard pattern
918
   * via a subject sub-domain pattern suffix match.
919
   */
920
0
  if (!(subject_len > 1 && subject[0] == '.'))
921
0
    star = valid_star(pattern, pattern_len, flags);
922
0
  if (star == NULL)
923
0
    return equal_nocase(pattern, pattern_len,
924
0
        subject, subject_len, flags);
925
0
  return wildcard_match(pattern, star - pattern,
926
0
      star + 1, (pattern + pattern_len) - star - 1,
927
0
      subject, subject_len, flags);
928
0
}
929
930
/*
931
 * Compare an ASN1_STRING to a supplied string. If they match return 1. If
932
 * cmp_type > 0 only compare if string matches the type, otherwise convert it
933
 * to UTF8.
934
 */
935
936
static int
937
do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
938
    unsigned int flags, const char *b, size_t blen, char **peername)
939
0
{
940
0
  int rv = 0;
941
942
0
  if (!a->data || !a->length)
943
0
    return 0;
944
0
  if (cmp_type > 0) {
945
0
    if (cmp_type != a->type)
946
0
      return 0;
947
0
    if (cmp_type == V_ASN1_IA5STRING)
948
0
      rv = equal(a->data, a->length, (unsigned char *)b,
949
0
          blen, flags);
950
0
    else if (a->length == (int)blen && !memcmp(a->data, b, blen))
951
0
      rv = 1;
952
0
    if (rv > 0 && peername &&
953
0
        (*peername = strndup((char *)a->data, a->length)) == NULL)
954
0
      rv = -1;
955
0
  } else {
956
0
    int astrlen;
957
0
    unsigned char *astr = NULL;
958
0
    astrlen = ASN1_STRING_to_UTF8(&astr, a);
959
0
    if (astrlen < 0)
960
0
      return -1;
961
0
    rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
962
0
    if (rv > 0 && peername &&
963
0
        (*peername = strndup((char *)astr, astrlen)) == NULL)
964
0
      rv = -1;
965
0
    free(astr);
966
0
  }
967
0
  return rv;
968
0
}
969
970
static int
971
do_x509_check(X509 *x, const char *chk, size_t chklen, unsigned int flags,
972
    int check_type, char **peername)
973
0
{
974
0
  GENERAL_NAMES *gens = NULL;
975
0
  X509_NAME *name = NULL;
976
0
  size_t i;
977
0
  int j;
978
0
  int cnid = NID_undef;
979
0
  int alt_type;
980
0
  int san_present = 0;
981
0
  int rv = 0;
982
0
  equal_fn equal;
983
984
  /* See below, this flag is internal-only */
985
0
  flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
986
0
  if (check_type == GEN_EMAIL) {
987
0
    cnid = NID_pkcs9_emailAddress;
988
0
    alt_type = V_ASN1_IA5STRING;
989
0
    equal = equal_email;
990
0
  } else if (check_type == GEN_DNS) {
991
0
    if (!(flags & X509_CHECK_FLAG_NEVER_CHECK_SUBJECT))
992
0
      cnid = NID_commonName;
993
    /* Implicit client-side DNS sub-domain pattern */
994
0
    if (chklen > 1 && chk[0] == '.')
995
0
      flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
996
0
    alt_type = V_ASN1_IA5STRING;
997
0
    if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
998
0
      equal = equal_nocase;
999
0
    else
1000
0
      equal = equal_wildcard;
1001
0
  } else {
1002
0
    alt_type = V_ASN1_OCTET_STRING;
1003
0
    equal = equal_case;
1004
0
  }
1005
1006
0
  gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
1007
0
  if (gens != NULL) {
1008
0
    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
1009
0
      GENERAL_NAME *gen;
1010
0
      ASN1_STRING *cstr;
1011
0
      gen = sk_GENERAL_NAME_value(gens, i);
1012
0
      if (gen->type != check_type)
1013
0
        continue;
1014
0
      san_present = 1;
1015
0
      if (check_type == GEN_EMAIL)
1016
0
        cstr = gen->d.rfc822Name;
1017
0
      else if (check_type == GEN_DNS)
1018
0
        cstr = gen->d.dNSName;
1019
0
      else
1020
0
        cstr = gen->d.iPAddress;
1021
      /* Positive on success, negative on error! */
1022
0
      if ((rv = do_check_string(cstr, alt_type, equal, flags,
1023
0
          chk, chklen, peername)) != 0)
1024
0
        break;
1025
0
    }
1026
0
    GENERAL_NAMES_free(gens);
1027
0
    if (rv != 0)
1028
0
      return rv;
1029
0
    if (cnid == NID_undef ||
1030
0
        (san_present &&
1031
0
        !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
1032
0
      return 0;
1033
0
  }
1034
1035
  /* We're done if CN-ID is not pertinent */
1036
0
  if (cnid == NID_undef)
1037
0
    return 0;
1038
1039
0
  j = -1;
1040
0
  name = X509_get_subject_name(x);
1041
0
  while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
1042
0
    X509_NAME_ENTRY *ne;
1043
0
    ASN1_STRING *str;
1044
0
    if ((ne = X509_NAME_get_entry(name, j)) == NULL)
1045
0
      return -1;
1046
0
    if ((str = X509_NAME_ENTRY_get_data(ne)) == NULL)
1047
0
      return -1;
1048
    /* Positive on success, negative on error! */
1049
0
    if ((rv = do_check_string(str, -1, equal, flags,
1050
0
       chk, chklen, peername)) != 0)
1051
0
      return rv;
1052
0
  }
1053
0
  return 0;
1054
0
}
1055
1056
int
1057
X509_check_host(X509 *x, const char *chk, size_t chklen, unsigned int flags,
1058
    char **peername)
1059
0
{
1060
0
  if (chk == NULL)
1061
0
    return -2;
1062
0
  if (chklen == 0)
1063
0
    chklen = strlen(chk);
1064
0
  else if (memchr(chk, '\0', chklen))
1065
0
    return -2;
1066
0
  return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
1067
0
}
1068
1069
int
1070
X509_check_email(X509 *x, const char *chk, size_t chklen, unsigned int flags)
1071
0
{
1072
0
  if (chk == NULL)
1073
0
    return -2;
1074
0
  if (chklen == 0)
1075
0
    chklen = strlen(chk);
1076
0
  else if (memchr(chk, '\0', chklen))
1077
0
    return -2;
1078
0
  return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
1079
0
}
1080
1081
int
1082
X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
1083
    unsigned int flags)
1084
0
{
1085
0
  if (chk == NULL)
1086
0
    return -2;
1087
0
  return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
1088
0
}
1089
1090
int
1091
X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
1092
0
{
1093
0
  unsigned char ipout[16];
1094
0
  size_t iplen;
1095
1096
0
  if (ipasc == NULL)
1097
0
    return -2;
1098
0
  iplen = (size_t)a2i_ipadd(ipout, ipasc);
1099
0
  if (iplen == 0)
1100
0
    return -2;
1101
0
  return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
1102
0
}
1103
1104
/* Convert IP addresses both IPv4 and IPv6 into an
1105
 * OCTET STRING compatible with RFC3280.
1106
 */
1107
1108
ASN1_OCTET_STRING *
1109
a2i_IPADDRESS(const char *ipasc)
1110
0
{
1111
0
  unsigned char ipout[16];
1112
0
  ASN1_OCTET_STRING *ret;
1113
0
  int iplen;
1114
1115
  /* If string contains a ':' assume IPv6 */
1116
1117
0
  iplen = a2i_ipadd(ipout, ipasc);
1118
1119
0
  if (!iplen)
1120
0
    return NULL;
1121
1122
0
  ret = ASN1_OCTET_STRING_new();
1123
0
  if (!ret)
1124
0
    return NULL;
1125
0
  if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
1126
0
    ASN1_OCTET_STRING_free(ret);
1127
0
    return NULL;
1128
0
  }
1129
0
  return ret;
1130
0
}
1131
1132
ASN1_OCTET_STRING *
1133
a2i_IPADDRESS_NC(const char *ipasc)
1134
0
{
1135
0
  ASN1_OCTET_STRING *ret = NULL;
1136
0
  unsigned char ipout[32];
1137
0
  char *iptmp = NULL, *p;
1138
0
  int iplen1, iplen2;
1139
1140
0
  p = strchr(ipasc, '/');
1141
0
  if (!p)
1142
0
    return NULL;
1143
0
  iptmp = strdup(ipasc);
1144
0
  if (!iptmp)
1145
0
    return NULL;
1146
0
  p = iptmp + (p - ipasc);
1147
0
  *p++ = 0;
1148
1149
0
  iplen1 = a2i_ipadd(ipout, iptmp);
1150
1151
0
  if (!iplen1)
1152
0
    goto err;
1153
1154
0
  iplen2 = a2i_ipadd(ipout + iplen1, p);
1155
1156
0
  free(iptmp);
1157
0
  iptmp = NULL;
1158
1159
0
  if (!iplen2 || (iplen1 != iplen2))
1160
0
    goto err;
1161
1162
0
  ret = ASN1_OCTET_STRING_new();
1163
0
  if (!ret)
1164
0
    goto err;
1165
0
  if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
1166
0
    goto err;
1167
1168
0
  return ret;
1169
1170
0
 err:
1171
0
  free(iptmp);
1172
0
  if (ret)
1173
0
    ASN1_OCTET_STRING_free(ret);
1174
0
  return NULL;
1175
0
}
1176
1177
1178
int
1179
a2i_ipadd(unsigned char *ipout, const char *ipasc)
1180
0
{
1181
  /* If string contains a ':' assume IPv6 */
1182
1183
0
  if (strchr(ipasc, ':')) {
1184
0
    if (!ipv6_from_asc(ipout, ipasc))
1185
0
      return 0;
1186
0
    return 16;
1187
0
  } else {
1188
0
    if (!ipv4_from_asc(ipout, ipasc))
1189
0
      return 0;
1190
0
    return 4;
1191
0
  }
1192
0
}
1193
1194
static int
1195
ipv4_from_asc(unsigned char *v4, const char *in)
1196
0
{
1197
0
  int a0, a1, a2, a3;
1198
0
  if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
1199
0
    return 0;
1200
0
  if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) ||
1201
0
      (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
1202
0
    return 0;
1203
0
  v4[0] = a0;
1204
0
  v4[1] = a1;
1205
0
  v4[2] = a2;
1206
0
  v4[3] = a3;
1207
0
  return 1;
1208
0
}
1209
1210
typedef struct {
1211
  /* Temporary store for IPV6 output */
1212
  unsigned char tmp[16];
1213
  /* Total number of bytes in tmp */
1214
  int total;
1215
  /* The position of a zero (corresponding to '::') */
1216
  int zero_pos;
1217
  /* Number of zeroes */
1218
  int zero_cnt;
1219
} IPV6_STAT;
1220
1221
1222
static int
1223
ipv6_from_asc(unsigned char *v6, const char *in)
1224
0
{
1225
0
  IPV6_STAT v6stat;
1226
1227
0
  v6stat.total = 0;
1228
0
  v6stat.zero_pos = -1;
1229
0
  v6stat.zero_cnt = 0;
1230
1231
  /* Treat the IPv6 representation as a list of values
1232
   * separated by ':'. The presence of a '::' will parse
1233
   * as one, two or three zero length elements.
1234
   */
1235
0
  if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
1236
0
    return 0;
1237
1238
  /* Now for some sanity checks */
1239
1240
0
  if (v6stat.zero_pos == -1) {
1241
    /* If no '::' must have exactly 16 bytes */
1242
0
    if (v6stat.total != 16)
1243
0
      return 0;
1244
0
  } else {
1245
    /* If '::' must have less than 16 bytes */
1246
0
    if (v6stat.total == 16)
1247
0
      return 0;
1248
    /* More than three zeroes is an error */
1249
0
    if (v6stat.zero_cnt > 3)
1250
0
      return 0;
1251
    /* Can only have three zeroes if nothing else present */
1252
0
    else if (v6stat.zero_cnt == 3) {
1253
0
      if (v6stat.total > 0)
1254
0
        return 0;
1255
0
    }
1256
    /* Can only have two zeroes if at start or end */
1257
0
    else if (v6stat.zero_cnt == 2) {
1258
0
      if ((v6stat.zero_pos != 0) &&
1259
0
          (v6stat.zero_pos != v6stat.total))
1260
0
        return 0;
1261
0
    } else
1262
      /* Can only have one zero if *not* start or end */
1263
0
    {
1264
0
      if ((v6stat.zero_pos == 0) ||
1265
0
          (v6stat.zero_pos == v6stat.total))
1266
0
        return 0;
1267
0
    }
1268
0
  }
1269
1270
  /* Format result */
1271
1272
0
  if (v6stat.zero_pos >= 0) {
1273
    /* Copy initial part */
1274
0
    memcpy(v6, v6stat.tmp, v6stat.zero_pos);
1275
    /* Zero middle */
1276
0
    memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
1277
    /* Copy final part */
1278
0
    if (v6stat.total != v6stat.zero_pos)
1279
0
      memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
1280
0
          v6stat.tmp + v6stat.zero_pos,
1281
0
          v6stat.total - v6stat.zero_pos);
1282
0
  } else
1283
0
    memcpy(v6, v6stat.tmp, 16);
1284
1285
0
  return 1;
1286
0
}
1287
1288
static int
1289
ipv6_cb(const char *elem, int len, void *usr)
1290
0
{
1291
0
  IPV6_STAT *s = usr;
1292
1293
  /* Error if 16 bytes written */
1294
0
  if (s->total == 16)
1295
0
    return 0;
1296
0
  if (len == 0) {
1297
    /* Zero length element, corresponds to '::' */
1298
0
    if (s->zero_pos == -1)
1299
0
      s->zero_pos = s->total;
1300
    /* If we've already got a :: its an error */
1301
0
    else if (s->zero_pos != s->total)
1302
0
      return 0;
1303
0
    s->zero_cnt++;
1304
0
  } else {
1305
    /* If more than 4 characters could be final a.b.c.d form */
1306
0
    if (len > 4) {
1307
      /* Need at least 4 bytes left */
1308
0
      if (s->total > 12)
1309
0
        return 0;
1310
      /* Must be end of string */
1311
0
      if (elem[len])
1312
0
        return 0;
1313
0
      if (!ipv4_from_asc(s->tmp + s->total, elem))
1314
0
        return 0;
1315
0
      s->total += 4;
1316
0
    } else {
1317
0
      if (!ipv6_hex(s->tmp + s->total, elem, len))
1318
0
        return 0;
1319
0
      s->total += 2;
1320
0
    }
1321
0
  }
1322
0
  return 1;
1323
0
}
1324
1325
/* Convert a string of up to 4 hex digits into the corresponding
1326
 * IPv6 form.
1327
 */
1328
1329
static int
1330
ipv6_hex(unsigned char *out, const char *in, int inlen)
1331
0
{
1332
0
  unsigned char c;
1333
0
  unsigned int num = 0;
1334
1335
0
  if (inlen > 4)
1336
0
    return 0;
1337
0
  while (inlen--) {
1338
0
    c = *in++;
1339
0
    num <<= 4;
1340
0
    if ((c >= '0') && (c <= '9'))
1341
0
      num |= c - '0';
1342
0
    else if ((c >= 'A') && (c <= 'F'))
1343
0
      num |= c - 'A' + 10;
1344
0
    else if ((c >= 'a') && (c <= 'f'))
1345
0
      num |=  c - 'a' + 10;
1346
0
    else
1347
0
      return 0;
1348
0
  }
1349
0
  out[0] = num >> 8;
1350
0
  out[1] = num & 0xff;
1351
0
  return 1;
1352
0
}
1353
1354
int
1355
X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
1356
    unsigned long chtype)
1357
0
{
1358
0
  CONF_VALUE *v;
1359
0
  int i, mval;
1360
0
  char *p, *type;
1361
1362
0
  if (!nm)
1363
0
    return 0;
1364
1365
0
  for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
1366
0
    v = sk_CONF_VALUE_value(dn_sk, i);
1367
0
    type = v->name;
1368
    /* Skip past any leading X. X: X, etc to allow for
1369
     * multiple instances
1370
     */
1371
0
    for (p = type; *p; p++)
1372
0
      if ((*p == ':') || (*p == ',') || (*p == '.')) {
1373
0
        p++;
1374
0
        if (*p)
1375
0
          type = p;
1376
0
        break;
1377
0
      }
1378
0
    if (*type == '+') {
1379
0
      mval = -1;
1380
0
      type++;
1381
0
    } else
1382
0
      mval = 0;
1383
0
    if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
1384
0
        (unsigned char *) v->value, -1, -1, mval))
1385
0
      return 0;
1386
0
  }
1387
0
  return 1;
1388
0
}