Coverage Report

Created: 2026-05-16 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gnutls/lib/x509/name_constraints.c
Line
Count
Source
1
/*
2
 * Copyright (C) 2014-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2016 Red Hat, Inc.
4
 *
5
 * Authors: Nikos Mavrogiannopoulos, Daiki Ueno, Martin Ukrop
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
/* Functions on X.509 Certificate parsing
25
 */
26
27
#include "gnutls_int.h"
28
#include "datum.h"
29
#include "global.h"
30
#include "errors.h"
31
#include "common.h"
32
#include "x509.h"
33
#include <gnutls/x509-ext.h>
34
#include "x509_b64.h"
35
#include "x509_int.h"
36
#include "x509_ext_int.h"
37
#include <libtasn1.h>
38
#include "c-strcase.h"
39
40
#include "ip.h"
41
#include "ip-in-cidr.h"
42
#include "intprops.h"
43
#include "minmax.h"
44
#include "gl_array_list.h"
45
#include "gl_rbtree_list.h"
46
47
#include <assert.h>
48
#include <string.h>
49
#include <limits.h>
50
51
0
#define MAX_NC_CHECKS (1 << 20)
52
53
0
#define SAN_MIN GNUTLS_SAN_DNSNAME
54
55
/* For historical reasons, these are not in the range
56
 * SAN_MIN..GNUTLS_SAN_MAX. They should probably deserve a separate
57
 * enum type.
58
 */
59
0
#define SAN_OTHERNAME_MIN GNUTLS_SAN_OTHERNAME_XMPP
60
#define SAN_OTHERNAME_MAX GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL
61
62
typedef unsigned long san_flags_t;
63
64
#define SAN_BIT(san)                                 \
65
0
  ((san) <= GNUTLS_SAN_MAX ? (san) - SAN_MIN : \
66
0
           GNUTLS_SAN_MAX + (san) - SAN_OTHERNAME_MIN)
67
68
static_assert(SAN_BIT(SAN_OTHERNAME_MIN) > SAN_BIT(GNUTLS_SAN_MAX));
69
static_assert(SAN_BIT(SAN_OTHERNAME_MAX) < CHAR_BIT * sizeof(san_flags_t));
70
71
0
#define SAN_FLAG(san) (1UL << SAN_BIT(san))
72
73
struct name_constraints_node_st {
74
  gnutls_x509_subject_alt_name_t type;
75
  gnutls_datum_t name;
76
};
77
78
struct name_constraints_node_list_st {
79
  gl_list_t items;
80
  gl_list_t sorted_items;
81
};
82
83
struct gnutls_name_constraints_st {
84
  gl_list_t nodes; /* owns elements */
85
  struct name_constraints_node_list_st permitted; /* borrows elements */
86
  struct name_constraints_node_list_st excluded; /* borrows elements */
87
};
88
89
static struct name_constraints_node_st *
90
name_constraints_node_new(gnutls_x509_name_constraints_t nc,
91
        gnutls_x509_subject_alt_name_t type,
92
        const unsigned char *data, unsigned int size);
93
94
/* An enum for "rich" comparisons that not only let us sort name constraints,
95
 * children-before-parent, but also subsume them during intersection. */
96
enum name_constraint_relation {
97
  NC_SORTS_BEFORE = -2, /* unrelated constraints */
98
  NC_INCLUDED_BY = -1, /* nc1 is included by nc2 / children sort first */
99
  NC_EQUAL = 0, /* exact match */
100
  NC_INCLUDES = 1, /* nc1 includes nc2 / parents sort last */
101
  NC_SORTS_AFTER = 2 /* unrelated constraints */
102
};
103
104
/* Helpers to compare just a pair of strings with this rich comparison */
105
static enum name_constraint_relation
106
compare_strings(const void *n1, size_t n1_len, const void *n2, size_t n2_len)
107
0
{
108
0
  int r = memcmp(n1, n2, MIN(n1_len, n2_len));
109
0
  if (r < 0)
110
0
    return NC_SORTS_BEFORE;
111
0
  if (r > 0)
112
0
    return NC_SORTS_AFTER;
113
0
  if (n1_len < n2_len)
114
0
    return NC_SORTS_BEFORE;
115
0
  if (n1_len > n2_len)
116
0
    return NC_SORTS_AFTER;
117
0
  return NC_EQUAL;
118
0
}
119
120
static enum name_constraint_relation
121
compare_strings_case_insensitive(const void *n1, size_t n1_len, const void *n2,
122
         size_t n2_len)
123
0
{
124
0
  int r = c_strncasecmp(n1, n2, MIN(n1_len, n2_len));
125
0
  if (r < 0)
126
0
    return NC_SORTS_BEFORE;
127
0
  if (r > 0)
128
0
    return NC_SORTS_AFTER;
129
0
  if (n1_len < n2_len)
130
0
    return NC_SORTS_BEFORE;
131
0
  if (n1_len > n2_len)
132
0
    return NC_SORTS_AFTER;
133
0
  return NC_EQUAL;
134
0
}
135
136
/* Rich-compare DNS names. Example order/relationships:
137
 * z.x.a INCLUDED_BY x.a BEFORE y.a INCLUDED_BY a BEFORE x.b BEFORE y.b */
138
static enum name_constraint_relation compare_dns_names(const gnutls_datum_t *n1,
139
                   const gnutls_datum_t *n2)
140
0
{
141
0
  enum name_constraint_relation rel;
142
0
  unsigned int i, j, i_end, j_end;
143
144
  /* start from the end of each name */
145
0
  i = i_end = n1->size;
146
0
  j = j_end = n2->size;
147
148
  /* skip the trailing dots for the comparison */
149
0
  while (i && n1->data[i - 1] == '.')
150
0
    i_end = i = i - 1;
151
0
  while (j && n2->data[j - 1] == '.')
152
0
    j_end = j = j - 1;
153
154
0
  while (1) {
155
    // rewind back to beginning or an after-dot position
156
0
    while (i && n1->data[i - 1] != '.')
157
0
      i--;
158
0
    while (j && n2->data[j - 1] != '.')
159
0
      j--;
160
161
0
    rel = compare_strings_case_insensitive(&n1->data[i], i_end - i,
162
0
                   &n2->data[j], j_end - j);
163
0
    if (rel == NC_SORTS_BEFORE) /* x.a BEFORE y.a */
164
0
      return NC_SORTS_BEFORE;
165
0
    if (rel == NC_SORTS_AFTER) /* y.a AFTER x.a */
166
0
      return NC_SORTS_AFTER;
167
0
    if (!i && j) /* x.a INCLUDES z.x.a */
168
0
      return NC_INCLUDES;
169
0
    if (i && !j) /* z.x.a INCLUDED_BY x.a */
170
0
      return NC_INCLUDED_BY;
171
172
0
    if (!i && !j) /* r == 0, we ran out of components to compare */
173
0
      return NC_EQUAL;
174
    /* r == 0, i && j: step back past a dot and keep comparing */
175
0
    i_end = i = i - 1;
176
0
    j_end = j = j - 1;
177
178
    /* support for non-standard ".gr INCLUDES example.gr" [1] */
179
0
    if (!i && j) /* .a INCLUDES x.a */
180
0
      return NC_INCLUDES;
181
0
    if (i && !j) /* x.a INCLUDED_BY .a */
182
0
      return NC_INCLUDED_BY;
183
0
  }
184
0
}
185
/* [1] https://mailarchive.ietf.org/arch/msg/saag/Bw6PtreW0G7aEG7SikfzKHES4VA */
186
187
/* Rich-compare email name constraints. Example order/relationships:
188
 * z@x.a INCLUDED_BY x.a BEFORE y.a INCLUDED_BY a BEFORE x@b BEFORE y@b */
189
static enum name_constraint_relation compare_emails(const gnutls_datum_t *n1,
190
                const gnutls_datum_t *n2)
191
0
{
192
0
  enum name_constraint_relation domains_rel;
193
0
  unsigned int i, j, i_end, j_end;
194
0
  gnutls_datum_t d1, d2; /* borrow from n1 and n2 */
195
196
  /* start from the end of each name */
197
0
  i = i_end = n1->size;
198
0
  j = j_end = n2->size;
199
200
  /* rewind to @s to look for domains */
201
0
  while (i && n1->data[i - 1] != '@')
202
0
    i--;
203
0
  d1.size = i_end - i;
204
0
  d1.data = &n1->data[i];
205
0
  while (j && n2->data[j - 1] != '@')
206
0
    j--;
207
0
  d2.size = j_end - j;
208
0
  d2.data = &n2->data[j];
209
210
0
  domains_rel = compare_dns_names(&d1, &d2);
211
212
  /* email constraint semantics differ from DNS
213
   * DNS: x.a INCLUDED_BY a
214
   * Email: x.a INCLUDED_BY .a BEFORE a */
215
0
  if (domains_rel == NC_INCLUDED_BY || domains_rel == NC_INCLUDES) {
216
0
    bool d1_has_dot = (d1.size > 0 && d1.data[0] == '.');
217
0
    bool d2_has_dot = (d2.size > 0 && d2.data[0] == '.');
218
    /* a constraint without a dot is exact, excluding subdomains */
219
0
    if (!d2_has_dot && domains_rel == NC_INCLUDED_BY)
220
0
      domains_rel = NC_SORTS_BEFORE; /* x.a BEFORE a */
221
0
    if (!d1_has_dot && domains_rel == NC_INCLUDES)
222
0
      domains_rel = NC_SORTS_AFTER; /* a AFTER x.a */
223
0
  }
224
225
0
  if (!i && !j) { /* both are domains-only */
226
0
    return domains_rel;
227
0
  } else if (i && !j) { /* n1 is email, n2 is domain */
228
0
    switch (domains_rel) {
229
0
    case NC_SORTS_AFTER:
230
0
      return NC_SORTS_AFTER;
231
0
    case NC_SORTS_BEFORE:
232
0
      return NC_SORTS_BEFORE;
233
0
    case NC_INCLUDES: /* n2 is more specific, a@x.a AFTER z.x.a */
234
0
      return NC_SORTS_AFTER;
235
0
    case NC_EQUAL: /* subdomains match, z@x.a INCLUDED_BY x.a */
236
0
    case NC_INCLUDED_BY: /* n1 is more specific */
237
0
      return NC_INCLUDED_BY;
238
0
    }
239
0
  } else if (!i && j) { /* n1 is domain, n2 is email */
240
0
    switch (domains_rel) {
241
0
    case NC_SORTS_AFTER:
242
0
      return NC_SORTS_AFTER;
243
0
    case NC_SORTS_BEFORE:
244
0
      return NC_SORTS_BEFORE;
245
0
    case NC_INCLUDES: /* n2 is more specific, a AFTER z@x.a */
246
0
      return NC_SORTS_AFTER;
247
0
    case NC_EQUAL: /* subdomains match, x.a INCLUDES z@x.a */
248
0
      return NC_INCLUDES;
249
0
    case NC_INCLUDED_BY: /* n1 is more specific, x.a BEFORE z@a */
250
0
      return NC_SORTS_BEFORE;
251
0
    }
252
0
  } else if (i && j) { /* both are emails */
253
0
    switch (domains_rel) {
254
0
    case NC_SORTS_AFTER:
255
0
      return NC_SORTS_AFTER;
256
0
    case NC_SORTS_BEFORE:
257
0
      return NC_SORTS_BEFORE;
258
0
    case NC_INCLUDES: // n2 is more specific
259
0
      return NC_SORTS_AFTER;
260
0
    case NC_INCLUDED_BY: // n1 is more specific
261
0
      return NC_SORTS_BEFORE;
262
0
    case NC_EQUAL: // only case when we need to look before the @
263
0
      break; // see below for readability
264
0
    }
265
0
  }
266
267
  /* i && j, both are emails, domain names match, compare up to @ */
268
0
  return compare_strings(n1->data, i - 1, n2->data, j - 1);
269
0
}
270
271
/* Rich-compare IP address constraints. Example order/relationships:
272
 * 10.0.0.0/24 INCLUDED_BY 10.0.0.0/16 BEFORE 1::1/128 INCLUDED_BY 1::1/127 */
273
static enum name_constraint_relation compare_ip_ncs(const gnutls_datum_t *n1,
274
                const gnutls_datum_t *n2)
275
0
{
276
0
  unsigned int len, i;
277
0
  int r;
278
0
  const unsigned char *ip1, *ip2, *mask1, *mask2;
279
0
  unsigned char masked11[16], masked22[16], masked12[16], masked21[16];
280
281
0
  if (n1->size < n2->size)
282
0
    return NC_SORTS_BEFORE;
283
0
  if (n1->size > n2->size)
284
0
    return NC_SORTS_AFTER;
285
0
  len = n1->size / 2; /* 4 for IPv4, 16 for IPv6 */
286
287
  /* data is a concatenation of prefix and mask */
288
0
  ip1 = n1->data;
289
0
  ip2 = n2->data;
290
0
  mask1 = n1->data + len;
291
0
  mask2 = n2->data + len;
292
0
  for (i = 0; i < len; i++) {
293
0
    masked11[i] = ip1[i] & mask1[i];
294
0
    masked22[i] = ip2[i] & mask2[i];
295
0
    masked12[i] = ip1[i] & mask2[i];
296
0
    masked21[i] = ip2[i] & mask1[i];
297
0
  }
298
299
0
  r = memcmp(mask1, mask2, len);
300
0
  if (r < 0 && !memcmp(masked11, masked21, len)) /* prefix1 < prefix2 */
301
0
    return NC_INCLUDES; /* ip1 & mask1 == ip2 & mask1 */
302
0
  if (r > 0 && !memcmp(masked12, masked22, len)) /* prefix1 > prefix2 */
303
0
    return NC_INCLUDED_BY; /* ip1 & mask2 == ip2 & mask2 */
304
305
0
  r = memcmp(masked11, masked22, len);
306
0
  if (r < 0)
307
0
    return NC_SORTS_BEFORE;
308
0
  else if (r > 0)
309
0
    return NC_SORTS_AFTER;
310
0
  return NC_EQUAL;
311
0
}
312
313
static inline bool is_supported_type(gnutls_x509_subject_alt_name_t type)
314
0
{
315
  /* all of these should be under GNUTLS_SAN_MAX (intersect bitmasks) */
316
0
  return type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME ||
317
0
         type == GNUTLS_SAN_IPADDRESS;
318
0
}
319
320
/* Universal comparison for name constraint nodes.
321
 * Unsupported types sort before supported types to allow early handling.
322
 * NULL represents end-of-list and sorts after everything else. */
323
static enum name_constraint_relation
324
compare_name_constraint_nodes(const struct name_constraints_node_st *n1,
325
            const struct name_constraints_node_st *n2)
326
0
{
327
0
  bool n1_supported, n2_supported;
328
329
0
  if (!n1 && !n2)
330
0
    return NC_EQUAL;
331
0
  if (!n1)
332
0
    return NC_SORTS_AFTER;
333
0
  if (!n2)
334
0
    return NC_SORTS_BEFORE;
335
336
0
  n1_supported = is_supported_type(n1->type);
337
0
  n2_supported = is_supported_type(n2->type);
338
339
  /* unsupported types bubble up (sort first). intersect relies on this */
340
0
  if (!n1_supported && n2_supported)
341
0
    return NC_SORTS_BEFORE;
342
0
  if (n1_supported && !n2_supported)
343
0
    return NC_SORTS_AFTER;
344
345
  /* next, sort by type */
346
0
  if (n1->type < n2->type)
347
0
    return NC_SORTS_BEFORE;
348
0
  if (n1->type > n2->type)
349
0
    return NC_SORTS_AFTER;
350
351
  /* now look deeper */
352
0
  switch (n1->type) {
353
0
  case GNUTLS_SAN_DNSNAME:
354
0
    return compare_dns_names(&n1->name, &n2->name);
355
0
  case GNUTLS_SAN_RFC822NAME:
356
0
    return compare_emails(&n1->name, &n2->name);
357
0
  case GNUTLS_SAN_IPADDRESS:
358
0
    return compare_ip_ncs(&n1->name, &n2->name);
359
0
  default:
360
    /* unsupported types: stable lexicographic order */
361
0
    return compare_strings(n1->name.data, n1->name.size,
362
0
               n2->name.data, n2->name.size);
363
0
  }
364
0
}
365
366
static int compare_name_constraint_nodes_wrapper(const void *a, const void *b)
367
0
{
368
0
  const struct name_constraints_node_st *n1 = a;
369
0
  const struct name_constraints_node_st *n2 = b;
370
0
  enum name_constraint_relation rel;
371
372
0
  rel = compare_name_constraint_nodes(n1, n2);
373
0
  switch (rel) {
374
0
  case NC_SORTS_BEFORE:
375
0
  case NC_INCLUDED_BY:
376
0
    return -1;
377
0
  case NC_SORTS_AFTER:
378
0
  case NC_INCLUDES:
379
0
    return 1;
380
0
  case NC_EQUAL:
381
0
  default:
382
0
    return 0;
383
0
  }
384
0
}
385
386
static int
387
name_constraints_node_list_add(struct name_constraints_node_list_st *list,
388
             const struct name_constraints_node_st *node)
389
0
{
390
0
  if (!gl_list_nx_add_last(list->items, node))
391
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
392
0
  if (!gl_sortedlist_nx_add(list->sorted_items,
393
0
          (gl_listelement_compar_fn)
394
0
            compare_name_constraint_nodes_wrapper,
395
0
          node))
396
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
397
0
  return 0;
398
0
}
399
400
static int
401
name_constraints_node_list_init(struct name_constraints_node_list_st *list)
402
0
{
403
0
  int ret;
404
0
  gl_list_t items = NULL, sorted_items = NULL;
405
406
0
  items = gl_list_nx_create_empty(GL_ARRAY_LIST, NULL, NULL, NULL, true);
407
0
  if (!items) {
408
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
409
0
    goto cleanup;
410
0
  }
411
412
0
  sorted_items =
413
0
    gl_list_nx_create_empty(GL_RBTREE_LIST, NULL, NULL, NULL, true);
414
0
  if (!sorted_items) {
415
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
416
0
    goto cleanup;
417
0
  }
418
419
0
  list->items = _gnutls_take_pointer(&items);
420
0
  list->sorted_items = _gnutls_take_pointer(&sorted_items);
421
422
0
  ret = GNUTLS_E_SUCCESS;
423
424
0
cleanup:
425
0
  if (items)
426
0
    gl_list_free(items);
427
0
  if (sorted_items)
428
0
    gl_list_free(sorted_items);
429
0
  return ret;
430
0
}
431
432
static void
433
name_constraints_node_list_deinit(struct name_constraints_node_list_st *list)
434
0
{
435
0
  if (list->items)
436
0
    gl_list_free(list->items);
437
0
  if (list->sorted_items)
438
0
    gl_list_free(list->sorted_items);
439
0
}
440
441
static struct name_constraints_node_list_st
442
name_constraints_node_list_take(struct name_constraints_node_list_st *list)
443
0
{
444
0
  struct name_constraints_node_list_st dst;
445
446
0
  dst = *list;
447
0
  dst.items = _gnutls_take_pointer(&list->items);
448
0
  dst.sorted_items = _gnutls_take_pointer(&list->sorted_items);
449
450
0
  return dst;
451
0
}
452
453
static int
454
name_constraints_node_add_new(gnutls_x509_name_constraints_t nc,
455
            struct name_constraints_node_list_st *list,
456
            gnutls_x509_subject_alt_name_t type,
457
            const unsigned char *data, unsigned int size)
458
0
{
459
0
  struct name_constraints_node_st *node;
460
0
  int ret;
461
0
  node = name_constraints_node_new(nc, type, data, size);
462
0
  if (node == NULL) {
463
0
    gnutls_assert();
464
0
    return GNUTLS_E_MEMORY_ERROR;
465
0
  }
466
0
  ret = name_constraints_node_list_add(list, node);
467
0
  if (ret < 0) {
468
0
    gnutls_assert();
469
0
    return ret;
470
0
  }
471
0
  return GNUTLS_E_SUCCESS;
472
0
}
473
474
static int
475
name_constraints_node_add_copy(gnutls_x509_name_constraints_t nc,
476
             struct name_constraints_node_list_st *dest,
477
             const struct name_constraints_node_st *src)
478
0
{
479
0
  if (!src)
480
0
    return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
481
0
  return name_constraints_node_add_new(nc, dest, src->type,
482
0
               src->name.data, src->name.size);
483
0
}
484
485
/*-
486
 * _gnutls_x509_name_constraints_is_empty:
487
 * @nc: name constraints structure
488
 *
489
 * Test whether given name constraints structure has any constraints (permitted
490
 * or excluded). @nc must be allocated (not NULL) before the call.
491
 *
492
 * Returns: true if @nc contains no constraints, false otherwise
493
 -*/
494
bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc)
495
0
{
496
0
  return gl_list_size(nc->permitted.items) == 0 &&
497
0
         gl_list_size(nc->excluded.items) == 0;
498
0
}
499
500
static bool name_constraints_contains_type(gnutls_x509_name_constraints_t nc,
501
             gnutls_x509_subject_alt_name_t type)
502
0
{
503
0
  const struct name_constraints_node_st *node;
504
0
  gl_list_iterator_t iter;
505
506
0
  iter = gl_list_iterator(nc->permitted.items);
507
0
  while (gl_list_iterator_next(&iter, (const void **)&node, NULL)) {
508
0
    if (node->type == type) {
509
0
      gl_list_iterator_free(&iter);
510
0
      return true;
511
0
    }
512
0
  }
513
0
  gl_list_iterator_free(&iter);
514
515
0
  iter = gl_list_iterator(nc->excluded.items);
516
0
  while (gl_list_iterator_next(&iter, (const void **)&node, NULL)) {
517
0
    if (node->type == type) {
518
0
      gl_list_iterator_free(&iter);
519
0
      return true;
520
0
    }
521
0
  }
522
0
  gl_list_iterator_free(&iter);
523
524
  /* no constraint for that type exists */
525
0
  return false;
526
0
}
527
528
/*-
529
 * validate_name_constraints_node:
530
 * @type: type of name constraints
531
 * @name: datum of name constraint
532
 *
533
 * Check the validity of given name constraints node (@type and @name).
534
 * The supported types are GNUTLS_SAN_DNSNAME, GNUTLS_SAN_RFC822NAME,
535
 * GNUTLS_SAN_DN, GNUTLS_SAN_URI and GNUTLS_SAN_IPADDRESS.
536
 *
537
 * CIDR ranges are checked for correct length (IPv4/IPv6) and correct mask format.
538
 *
539
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
540
 -*/
541
static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type,
542
            const gnutls_datum_t *name)
543
0
{
544
0
  if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME &&
545
0
      type != GNUTLS_SAN_DN && type != GNUTLS_SAN_URI &&
546
0
      type != GNUTLS_SAN_IPADDRESS &&
547
0
      type != GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL &&
548
0
      type != GNUTLS_SAN_OTHERNAME_SRV) {
549
0
    return gnutls_assert_val(GNUTLS_E_X509_UNKNOWN_SAN);
550
0
  }
551
552
0
  if (type == GNUTLS_SAN_IPADDRESS) {
553
0
    if (name->size != 8 && name->size != 32)
554
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
555
0
    int prefix = _gnutls_mask_to_prefix(name->data + name->size / 2,
556
0
                name->size / 2);
557
0
    if (prefix < 0)
558
0
      return gnutls_assert_val(GNUTLS_E_MALFORMED_CIDR);
559
0
  }
560
561
  /* Validate DNS names and email addresses for malformed input */
562
0
  if (type == GNUTLS_SAN_DNSNAME || type == GNUTLS_SAN_RFC822NAME) {
563
0
    unsigned int i;
564
0
    if (name->size == 0)
565
0
      return GNUTLS_E_SUCCESS;
566
567
    /* reject names with consecutive dots... */
568
0
    for (i = 0; i + 1 < name->size; i++) {
569
0
      if (name->data[i] == '.' && name->data[i + 1] == '.')
570
0
        return gnutls_assert_val(
571
0
          GNUTLS_E_ILLEGAL_PARAMETER);
572
0
    }
573
    /* ... or names consisting exclusively of dots */
574
0
    if (name->size == 1 && name->data[0] == '.')
575
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
576
0
  }
577
578
0
  return GNUTLS_E_SUCCESS;
579
0
}
580
581
static int extract_name_constraints(gnutls_x509_name_constraints_t nc,
582
            asn1_node c2, const char *vstr,
583
            struct name_constraints_node_list_st *nodes)
584
0
{
585
0
  int ret;
586
0
  char tmpstr[128];
587
0
  unsigned indx;
588
0
  gnutls_datum_t tmp = { NULL, 0 };
589
0
  gnutls_x509_subject_alt_name_t type;
590
591
0
  for (indx = 1;; indx++) {
592
0
    snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx);
593
594
0
    ret = _gnutls_parse_general_name2(c2, tmpstr, -1, &tmp, &type,
595
0
              0);
596
597
0
    if (ret < 0) {
598
0
      gnutls_assert();
599
0
      break;
600
0
    }
601
602
0
    if (type == GNUTLS_SAN_OTHERNAME) {
603
0
      gnutls_datum_t oid = { NULL, 0 };
604
0
      gnutls_datum_t parsed_othername = { NULL, 0 };
605
0
      ret = _gnutls_parse_general_name2(c2, tmpstr, -1, &oid,
606
0
                &type, 1);
607
0
      if (ret < 0) {
608
0
        gnutls_assert();
609
0
        goto cleanup;
610
0
      }
611
612
0
      ret = gnutls_x509_othername_to_virtual(
613
0
        (char *)oid.data, &tmp, &type,
614
0
        &parsed_othername);
615
0
      if (ret < 0) {
616
0
        gnutls_assert();
617
0
        goto cleanup;
618
0
      }
619
620
0
      gnutls_free(oid.data);
621
0
      gnutls_free(tmp.data);
622
623
0
      memcpy(&tmp, &parsed_othername, sizeof(gnutls_datum_t));
624
0
    }
625
626
0
    ret = validate_name_constraints_node(type, &tmp);
627
0
    if (ret < 0) {
628
0
      gnutls_assert();
629
0
      goto cleanup;
630
0
    }
631
632
0
    ret = name_constraints_node_add_new(nc, nodes, type, tmp.data,
633
0
                tmp.size);
634
0
    _gnutls_free_datum(&tmp);
635
0
    if (ret < 0) {
636
0
      gnutls_assert();
637
0
      goto cleanup;
638
0
    }
639
0
  }
640
641
0
  assert(ret < 0);
642
0
  if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
643
0
    gnutls_assert();
644
0
    goto cleanup;
645
0
  }
646
647
0
  ret = 0;
648
0
cleanup:
649
0
  gnutls_free(tmp.data);
650
0
  return ret;
651
0
}
652
653
int _gnutls_x509_name_constraints_extract(asn1_node c2,
654
            const char *permitted_name,
655
            const char *excluded_name,
656
            gnutls_x509_name_constraints_t nc)
657
0
{
658
0
  int ret;
659
660
0
  ret = extract_name_constraints(nc, c2, permitted_name, &nc->permitted);
661
0
  if (ret < 0)
662
0
    return gnutls_assert_val(ret);
663
0
  ret = extract_name_constraints(nc, c2, excluded_name, &nc->excluded);
664
0
  if (ret < 0)
665
0
    return gnutls_assert_val(ret);
666
667
0
  return ret;
668
0
}
669
670
/*-
671
 * name_constraints_node_free:
672
 * @node: name constraints node
673
 *
674
 * Deallocate a name constraints node.
675
 -*/
676
static void name_constraints_node_free(struct name_constraints_node_st *node)
677
0
{
678
0
  if (node) {
679
0
    gnutls_free(node->name.data);
680
0
    gnutls_free(node);
681
0
  }
682
0
}
683
684
/*-
685
 * name_constraints_node_new:
686
 * @type: name constraints type to set (gnutls_x509_subject_alt_name_t)
687
 * @nc: a %gnutls_x509_name_constraints_t
688
 * @data: name.data to set or NULL
689
 * @size: name.size to set
690
 *
691
 * Allocate a new name constraints node and set its type, name size and name data.
692
 *
693
 * Returns: Pointer to newly allocated node or NULL in case of memory error.
694
 -*/
695
static struct name_constraints_node_st *
696
name_constraints_node_new(gnutls_x509_name_constraints_t nc,
697
        gnutls_x509_subject_alt_name_t type,
698
        const unsigned char *data, unsigned int size)
699
0
{
700
0
  struct name_constraints_node_st *tmp;
701
0
  int ret;
702
703
0
  tmp = gnutls_calloc(1, sizeof(struct name_constraints_node_st));
704
0
  if (tmp == NULL)
705
0
    return NULL;
706
0
  tmp->type = type;
707
708
0
  if (data) {
709
0
    ret = _gnutls_set_strdatum(&tmp->name, data, size);
710
0
    if (ret < 0) {
711
0
      gnutls_assert();
712
0
      gnutls_free(tmp);
713
0
      return NULL;
714
0
    }
715
0
  }
716
717
0
  if (!gl_list_nx_add_last(nc->nodes, tmp)) {
718
0
    gnutls_assert();
719
0
    name_constraints_node_free(tmp);
720
0
    return NULL;
721
0
  }
722
723
0
  return tmp;
724
0
}
725
726
static int name_constraints_node_list_union(
727
  gnutls_x509_name_constraints_t nc,
728
  struct name_constraints_node_list_st *result,
729
  const struct name_constraints_node_list_st *nodes1,
730
  const struct name_constraints_node_list_st *nodes2);
731
732
static san_flags_t name_constraints_node_list_types(
733
  const struct name_constraints_node_list_st *nodes)
734
0
{
735
0
  const struct name_constraints_node_st *node;
736
0
  gl_list_iterator_t iter;
737
0
  san_flags_t flags = 0;
738
739
0
  iter = gl_list_iterator(nodes->sorted_items);
740
0
  while (gl_list_iterator_next(&iter, (const void **)&node, NULL))
741
0
    flags |= SAN_FLAG(node->type);
742
0
  gl_list_iterator_free(&iter);
743
0
  return flags;
744
0
}
745
746
static int name_constraints_node_list_partition(
747
  struct name_constraints_node_list_st *supported,
748
  struct name_constraints_node_list_st *unsupported,
749
  const struct name_constraints_node_list_st *nodes)
750
0
{
751
0
  int ret;
752
0
  const struct name_constraints_node_st *node = NULL;
753
0
  gl_list_iterator_t iter;
754
755
0
  iter = gl_list_iterator(nodes->sorted_items);
756
0
  while (gl_list_iterator_next(&iter, (const void **)&node, NULL)) {
757
0
    ret = name_constraints_node_list_add(
758
0
      is_supported_type(node->type) ? supported : unsupported,
759
0
      node);
760
0
    if (ret < 0) {
761
0
      gnutls_assert();
762
0
      goto cleanup;
763
0
    }
764
0
  }
765
766
0
  ret = GNUTLS_E_SUCCESS;
767
768
0
cleanup:
769
0
  gl_list_iterator_free(&iter);
770
0
  return ret;
771
0
}
772
773
/*-
774
 * @brief name_constraints_node_list_intersect:
775
 * @nc: %gnutls_x509_name_constraints_t
776
 * @result: resulting name constraints list (permitted)
777
 * @permitted1: first name constraints list (permitted)
778
 * @permitted2: second name constraints list (permitted)
779
 * @excluded: corresponding excluded name constraints list
780
 *
781
 * This function finds the intersection of @permitted1 and
782
 * @permitted2. The result is placed in @result. If necessary, a
783
 * universal excluded name constraint node of the right type is added
784
 * to the list provided in @excluded.
785
 *
786
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
787
 -*/
788
static int name_constraints_node_list_intersect(
789
  gnutls_x509_name_constraints_t nc,
790
  struct name_constraints_node_list_st *result,
791
  const struct name_constraints_node_list_st *permitted1,
792
  const struct name_constraints_node_list_st *permitted2,
793
  struct name_constraints_node_list_st *excluded)
794
0
{
795
0
  struct name_constraints_node_list_st supported1 = { NULL, }, unsupported1 = { NULL, };
796
0
  struct name_constraints_node_list_st supported2 = { NULL, }, unsupported2 = { NULL, };
797
0
  int ret;
798
0
  const struct name_constraints_node_st *node1 = NULL, *node2 = NULL;
799
0
  gl_list_iterator_t iter1, iter2;
800
0
  san_flags_t universal_exclude_needed = 0;
801
0
  san_flags_t types_in_p1 = 0, types_in_p2 = 0;
802
0
  static const unsigned char universal_ip[32] = { 0 };
803
804
  /* First partition PERMITTED1 into supported and unsupported lists */
805
0
  ret = name_constraints_node_list_init(&supported1);
806
0
  if (ret < 0) {
807
0
    gnutls_assert();
808
0
    goto cleanup;
809
0
  }
810
811
0
  ret = name_constraints_node_list_init(&unsupported1);
812
0
  if (ret < 0) {
813
0
    gnutls_assert();
814
0
    goto cleanup;
815
0
  }
816
817
0
  ret = name_constraints_node_list_partition(&supported1, &unsupported1,
818
0
               permitted1);
819
0
  if (ret < 0) {
820
0
    gnutls_assert();
821
0
    goto cleanup;
822
0
  }
823
824
  /* Do the same for PERMITTED2 */
825
0
  ret = name_constraints_node_list_init(&supported2);
826
0
  if (ret < 0) {
827
0
    gnutls_assert();
828
0
    goto cleanup;
829
0
  }
830
831
0
  ret = name_constraints_node_list_init(&unsupported2);
832
0
  if (ret < 0) {
833
0
    gnutls_assert();
834
0
    goto cleanup;
835
0
  }
836
837
0
  ret = name_constraints_node_list_partition(&supported2, &unsupported2,
838
0
               permitted2);
839
0
  if (ret < 0) {
840
0
    gnutls_assert();
841
0
    goto cleanup;
842
0
  }
843
844
  /* Store unsupported1 | unsupported2 as a temporary result */
845
0
  ret = name_constraints_node_list_union(nc, result, &unsupported1,
846
0
                 &unsupported2);
847
0
  if (ret < 0) {
848
0
    gnutls_assert();
849
0
    goto cleanup;
850
0
  }
851
852
  /* Secondly figure out which types are in supported1 and supported2 */
853
0
  types_in_p1 = name_constraints_node_list_types(&supported1);
854
0
  types_in_p2 = name_constraints_node_list_types(&supported2);
855
  /* Universal excludes might be needed for types intersecting
856
   * to empty */
857
0
  universal_exclude_needed = types_in_p1 & types_in_p2;
858
859
  /* Finally go through supported type NCs and intersect in a
860
   * single pass */
861
0
  iter1 = gl_list_iterator(supported1.sorted_items);
862
0
  iter2 = gl_list_iterator(supported2.sorted_items);
863
0
  gl_list_iterator_next(&iter1, (const void **)&node1, NULL);
864
0
  gl_list_iterator_next(&iter2, (const void **)&node2, NULL);
865
0
  while (node1 || node2) {
866
0
    enum name_constraint_relation rel;
867
868
0
    rel = compare_name_constraint_nodes(node1, node2);
869
0
    switch (rel) {
870
0
    case NC_SORTS_BEFORE:
871
0
      assert(node1 != NULL); /* comparator-guaranteed */
872
      /* if nothing to intersect with, shallow-copy node1 */
873
0
      if (!(types_in_p2 & SAN_FLAG(node1->type))) {
874
0
        ret = name_constraints_node_list_add(result,
875
0
                     node1);
876
0
        if (ret < 0) {
877
0
          gnutls_assert();
878
0
          goto out;
879
0
        }
880
0
      }
881
      /* otherwise skip node1 */
882
0
      node1 = NULL;
883
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
884
0
                NULL);
885
0
      break;
886
0
    case NC_SORTS_AFTER:
887
0
      assert(node2 != NULL); /* comparator-guaranteed */
888
      /* if nothing to intersect with, deep-copy node2 */
889
0
      if (!(types_in_p1 & SAN_FLAG(node2->type))) {
890
0
        ret = name_constraints_node_add_copy(nc, result,
891
0
                     node2);
892
0
        if (ret < 0) {
893
0
          gnutls_assert();
894
0
          goto out;
895
0
        }
896
0
      }
897
      /* otherwise skip node2 */
898
0
      node2 = NULL;
899
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
900
0
                NULL);
901
0
      break;
902
0
    case NC_INCLUDED_BY: /* add node1, shallow-copy */
903
0
      assert(node1 != NULL && node2 != NULL); /* comparator */
904
0
      universal_exclude_needed &= ~SAN_FLAG(node1->type);
905
0
      ret = name_constraints_node_list_add(result, node1);
906
0
      if (ret < 0) {
907
0
        gnutls_assert();
908
0
        goto out;
909
0
      }
910
0
      node1 = NULL;
911
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
912
0
                NULL);
913
0
      break;
914
0
    case NC_INCLUDES: /* pick node2, deep-copy */
915
0
      assert(node1 != NULL && node2 != NULL); /* comparator */
916
0
      universal_exclude_needed &= ~SAN_FLAG(node2->type);
917
0
      ret = name_constraints_node_add_copy(nc, result, node2);
918
0
      if (ret < 0) {
919
0
        gnutls_assert();
920
0
        goto out;
921
0
      }
922
0
      node2 = NULL;
923
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
924
0
                NULL);
925
0
      break;
926
0
    case NC_EQUAL: /* pick whichever: nc1, shallow-copy */
927
0
      assert(node1 != NULL &&
928
0
             node2 != NULL); /* loop condition */
929
0
      universal_exclude_needed &= ~SAN_FLAG(node1->type);
930
0
      ret = name_constraints_node_list_add(result, node1);
931
0
      if (ret < 0) {
932
0
        gnutls_assert();
933
0
        goto out;
934
0
      }
935
0
      node1 = NULL;
936
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
937
0
                NULL);
938
0
      node2 = NULL;
939
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
940
0
                NULL);
941
0
      break;
942
0
    }
943
0
  }
944
0
out:
945
0
  gl_list_iterator_free(&iter1);
946
0
  gl_list_iterator_free(&iter2);
947
0
  if (ret < 0)
948
0
    goto cleanup;
949
950
  /* finishing touch: add universal excluded constraints for types where
951
   * both lists had constraints, but all intersections ended up empty */
952
0
  for (gnutls_x509_subject_alt_name_t type = SAN_MIN;
953
0
       type <= GNUTLS_SAN_MAX; type++) {
954
0
    if (!(universal_exclude_needed & SAN_FLAG(type)))
955
0
      continue;
956
0
    _gnutls_hard_log(
957
0
      "Adding universal excluded name constraint for type %d.\n",
958
0
      type);
959
0
    switch (type) {
960
0
    case GNUTLS_SAN_IPADDRESS:
961
      // add universal restricted range for IPv4
962
0
      ret = name_constraints_node_add_new(
963
0
        nc, excluded, GNUTLS_SAN_IPADDRESS,
964
0
        universal_ip, 8);
965
0
      if (ret < 0) {
966
0
        gnutls_assert();
967
0
        goto cleanup;
968
0
      }
969
      // add universal restricted range for IPv6
970
0
      ret = name_constraints_node_add_new(
971
0
        nc, excluded, GNUTLS_SAN_IPADDRESS,
972
0
        universal_ip, 32);
973
0
      if (ret < 0) {
974
0
        gnutls_assert();
975
0
        goto cleanup;
976
0
      }
977
0
      break;
978
0
    case GNUTLS_SAN_DNSNAME:
979
0
    case GNUTLS_SAN_RFC822NAME:
980
0
      ret = name_constraints_node_add_new(nc, excluded, type,
981
0
                  NULL, 0);
982
0
      if (ret < 0) {
983
0
        gnutls_assert();
984
0
        goto cleanup;
985
0
      }
986
0
      break;
987
0
    default: /* unsupported type; should be unreacheable */
988
0
      ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
989
0
      goto cleanup;
990
0
    }
991
0
  }
992
993
0
  ret = GNUTLS_E_SUCCESS;
994
995
0
cleanup:
996
0
  name_constraints_node_list_deinit(&supported1);
997
0
  name_constraints_node_list_deinit(&unsupported1);
998
0
  name_constraints_node_list_deinit(&supported2);
999
0
  name_constraints_node_list_deinit(&unsupported2);
1000
0
  return ret;
1001
0
}
1002
1003
static int name_constraints_node_list_union(
1004
  gnutls_x509_name_constraints_t nc,
1005
  struct name_constraints_node_list_st *result,
1006
  const struct name_constraints_node_list_st *nodes1,
1007
  const struct name_constraints_node_list_st *nodes2)
1008
0
{
1009
0
  int ret;
1010
0
  gl_list_iterator_t iter1, iter2;
1011
0
  const struct name_constraints_node_st *node1 = NULL, *node2 = NULL;
1012
1013
  /* traverse both lists in a single pass and merge them w/o duplicates */
1014
0
  iter1 = gl_list_iterator(nodes1->sorted_items);
1015
0
  iter2 = gl_list_iterator(nodes2->sorted_items);
1016
0
  gl_list_iterator_next(&iter1, (const void **)&node1, NULL);
1017
0
  gl_list_iterator_next(&iter2, (const void **)&node2, NULL);
1018
0
  while (node1 || node2) {
1019
0
    enum name_constraint_relation rel;
1020
1021
0
    rel = compare_name_constraint_nodes(node1, node2);
1022
0
    switch (rel) {
1023
0
    case NC_SORTS_BEFORE:
1024
0
      assert(node1 != NULL); /* comparator-guaranteed */
1025
0
      ret = name_constraints_node_list_add(result, node1);
1026
0
      if (ret < 0) {
1027
0
        gnutls_assert();
1028
0
        goto cleanup;
1029
0
      }
1030
0
      node1 = NULL;
1031
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
1032
0
                NULL);
1033
0
      break;
1034
0
    case NC_SORTS_AFTER:
1035
0
      assert(node2 != NULL); /* comparator-guaranteed */
1036
0
      ret = name_constraints_node_add_copy(nc, result, node2);
1037
0
      if (ret < 0) {
1038
0
        gnutls_assert();
1039
0
        goto cleanup;
1040
0
      }
1041
0
      node2 = NULL;
1042
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
1043
0
                NULL);
1044
0
      break;
1045
0
    case NC_INCLUDES: /* node1 is broader, shallow-copy it */
1046
0
      assert(node1 != NULL && node2 != NULL); /* comparator */
1047
0
      ret = name_constraints_node_list_add(result, node1);
1048
0
      if (ret < 0) {
1049
0
        gnutls_assert();
1050
0
        goto cleanup;
1051
0
      }
1052
0
      node1 = NULL;
1053
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
1054
0
                NULL);
1055
0
      node2 = NULL;
1056
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
1057
0
                NULL);
1058
0
      break;
1059
0
    case NC_INCLUDED_BY: /* node2 is broader, deep-copy it */
1060
0
      assert(node1 != NULL && node2 != NULL); /* comparator */
1061
0
      ret = name_constraints_node_add_copy(nc, result, node2);
1062
0
      if (ret < 0) {
1063
0
        gnutls_assert();
1064
0
        goto cleanup;
1065
0
      }
1066
0
      node1 = NULL;
1067
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
1068
0
                NULL);
1069
0
      node2 = NULL;
1070
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
1071
0
                NULL);
1072
0
      break;
1073
0
    case NC_EQUAL:
1074
0
      assert(node1 != NULL &&
1075
0
             node2 != NULL); /* loop condition */
1076
0
      ret = name_constraints_node_list_add(result, node1);
1077
0
      if (ret < 0) {
1078
0
        gnutls_assert();
1079
0
        goto cleanup;
1080
0
      }
1081
0
      node1 = NULL;
1082
0
      gl_list_iterator_next(&iter1, (const void **)&node1,
1083
0
                NULL);
1084
0
      node2 = NULL;
1085
0
      gl_list_iterator_next(&iter2, (const void **)&node2,
1086
0
                NULL);
1087
0
      break;
1088
0
    }
1089
0
  }
1090
1091
0
  ret = GNUTLS_E_SUCCESS;
1092
1093
0
cleanup:
1094
0
  gl_list_iterator_free(&iter1);
1095
0
  gl_list_iterator_free(&iter2);
1096
1097
0
  return ret;
1098
0
}
1099
1100
/**
1101
 * gnutls_x509_crt_get_name_constraints:
1102
 * @crt: should contain a #gnutls_x509_crt_t type
1103
 * @nc: The nameconstraints intermediate type
1104
 * @flags: zero or %GNUTLS_EXT_FLAG_APPEND
1105
 * @critical: the extension status
1106
 *
1107
 * This function will return an intermediate type containing
1108
 * the name constraints of the provided CA certificate. That
1109
 * structure can be used in combination with gnutls_x509_name_constraints_check()
1110
 * to verify whether a server's name is in accordance with the constraints.
1111
 *
1112
 * When the @flags is set to %GNUTLS_EXT_FLAG_APPEND,
1113
 * then if the @nc structure is empty this function will behave
1114
 * identically as if the flag was not set.
1115
 * Otherwise if there are elements in the @nc structure then the
1116
 * constraints will be merged with the existing constraints following
1117
 * RFC5280 p6.1.4 (excluded constraints will be appended, permitted
1118
 * will be intersected).
1119
 *
1120
 * Note that @nc must be initialized prior to calling this function.
1121
 *
1122
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1123
 * if the extension is not present, otherwise a negative error value.
1124
 *
1125
 * Since: 3.3.0
1126
 **/
1127
int gnutls_x509_crt_get_name_constraints(gnutls_x509_crt_t crt,
1128
           gnutls_x509_name_constraints_t nc,
1129
           unsigned int flags,
1130
           unsigned int *critical)
1131
0
{
1132
0
  int ret;
1133
0
  gnutls_datum_t der = { NULL, 0 };
1134
1135
0
  if (crt == NULL) {
1136
0
    gnutls_assert();
1137
0
    return GNUTLS_E_INVALID_REQUEST;
1138
0
  }
1139
1140
0
  ret = _gnutls_x509_crt_get_extension(crt, "2.5.29.30", 0, &der,
1141
0
               critical);
1142
0
  if (ret < 0)
1143
0
    return gnutls_assert_val(ret);
1144
1145
0
  if (der.size == 0 || der.data == NULL)
1146
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1147
1148
0
  ret = gnutls_x509_ext_import_name_constraints(&der, nc, flags);
1149
0
  if (ret < 0) {
1150
0
    gnutls_assert();
1151
0
    goto cleanup;
1152
0
  }
1153
1154
0
  ret = 0;
1155
1156
0
cleanup:
1157
0
  _gnutls_free_datum(&der);
1158
1159
0
  return ret;
1160
0
}
1161
1162
static void name_constraints_deinit(struct gnutls_name_constraints_st *nc)
1163
0
{
1164
0
  if (nc->nodes)
1165
0
    gl_list_free(nc->nodes);
1166
0
  name_constraints_node_list_deinit(&nc->permitted);
1167
0
  name_constraints_node_list_deinit(&nc->excluded);
1168
0
}
1169
1170
static struct gnutls_name_constraints_st
1171
name_constraints_take(struct gnutls_name_constraints_st *nc)
1172
0
{
1173
0
  struct gnutls_name_constraints_st dst;
1174
1175
0
  dst = *nc;
1176
0
  dst.nodes = _gnutls_take_pointer(&nc->nodes);
1177
0
  dst.permitted = name_constraints_node_list_take(&nc->permitted);
1178
0
  dst.excluded = name_constraints_node_list_take(&nc->excluded);
1179
1180
0
  return dst;
1181
0
}
1182
1183
static int name_constraints_init(struct gnutls_name_constraints_st *nc)
1184
0
{
1185
0
  struct gnutls_name_constraints_st tmp = {
1186
0
    NULL,
1187
0
  };
1188
0
  int ret;
1189
1190
0
  tmp.nodes = gl_list_nx_create_empty(
1191
0
    GL_ARRAY_LIST, NULL, NULL,
1192
0
    (gl_listelement_dispose_fn)name_constraints_node_free, true);
1193
0
  if (!tmp.nodes) {
1194
0
    ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1195
0
    goto cleanup;
1196
0
  }
1197
1198
0
  ret = name_constraints_node_list_init(&tmp.permitted);
1199
0
  if (ret < 0) {
1200
0
    gnutls_assert();
1201
0
    goto cleanup;
1202
0
  }
1203
1204
0
  ret = name_constraints_node_list_init(&tmp.excluded);
1205
0
  if (ret < 0) {
1206
0
    gnutls_assert();
1207
0
    goto cleanup;
1208
0
  }
1209
1210
0
  *nc = name_constraints_take(&tmp);
1211
1212
0
  ret = 0;
1213
1214
0
cleanup:
1215
0
  name_constraints_deinit(&tmp);
1216
0
  return ret;
1217
0
}
1218
1219
int _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc)
1220
0
{
1221
0
  name_constraints_deinit(nc);
1222
0
  return name_constraints_init(nc);
1223
0
}
1224
1225
/**
1226
 * gnutls_x509_name_constraints_deinit:
1227
 * @nc: The nameconstraints
1228
 *
1229
 * This function will deinitialize a name constraints type.
1230
 *
1231
 * Since: 3.3.0
1232
 **/
1233
void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc)
1234
0
{
1235
0
  name_constraints_deinit(nc);
1236
0
  gnutls_free(nc);
1237
0
}
1238
1239
/**
1240
 * gnutls_x509_name_constraints_init:
1241
 * @nc: The nameconstraints
1242
 *
1243
 * This function will initialize a name constraints type.
1244
 *
1245
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1246
 *
1247
 * Since: 3.3.0
1248
 **/
1249
int gnutls_x509_name_constraints_init(gnutls_x509_name_constraints_t *nc)
1250
0
{
1251
0
  struct gnutls_name_constraints_st *tmp;
1252
0
  int ret;
1253
1254
0
  tmp = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st));
1255
0
  if (tmp == NULL) {
1256
0
    gnutls_assert();
1257
0
    return GNUTLS_E_MEMORY_ERROR;
1258
0
  }
1259
1260
0
  ret = name_constraints_init(tmp);
1261
0
  if (ret < 0) {
1262
0
    gnutls_assert();
1263
0
    goto cleanup;
1264
0
  }
1265
1266
0
  *nc = _gnutls_take_pointer(&tmp);
1267
0
  ret = 0;
1268
1269
0
cleanup:
1270
0
  if (tmp) {
1271
0
    name_constraints_deinit(tmp);
1272
0
    gnutls_free(tmp);
1273
0
  }
1274
0
  return ret;
1275
0
}
1276
1277
static int name_constraints_add(gnutls_x509_name_constraints_t nc,
1278
        gnutls_x509_subject_alt_name_t type,
1279
        const gnutls_datum_t *name, unsigned permitted)
1280
0
{
1281
0
  struct name_constraints_node_list_st *nodes;
1282
0
  int ret;
1283
1284
0
  ret = validate_name_constraints_node(type, name);
1285
0
  if (ret < 0)
1286
0
    return gnutls_assert_val(ret);
1287
1288
0
  nodes = permitted ? &nc->permitted : &nc->excluded;
1289
1290
0
  ret = name_constraints_node_add_new(nc, nodes, type, name->data,
1291
0
              name->size);
1292
0
  if (ret < 0)
1293
0
    return gnutls_assert_val(ret);
1294
1295
0
  return 0;
1296
0
}
1297
1298
/*-
1299
 * _gnutls_x509_name_constraints_merge:
1300
 * @nc: The nameconstraints
1301
 * @nc2: The name constraints to be merged with
1302
 *
1303
 * This function will merge the provided name constraints structures
1304
 * as per RFC5280 p6.1.4. That is, the excluded constraints will be unioned,
1305
 * and permitted will be intersected. The intersection assumes that @nc
1306
 * is the root CA constraints.
1307
 *
1308
 * The merged constraints will be placed in @nc.
1309
 *
1310
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1311
 *
1312
 * Since: 3.5.0
1313
 -*/
1314
int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
1315
          gnutls_x509_name_constraints_t nc2)
1316
0
{
1317
0
  struct name_constraints_node_list_st permitted = { NULL, }, excluded = { NULL, };
1318
0
  int ret;
1319
1320
0
  ret = name_constraints_node_list_init(&permitted);
1321
0
  if (ret < 0) {
1322
0
    gnutls_assert();
1323
0
    goto cleanup;
1324
0
  }
1325
1326
0
  ret = name_constraints_node_list_intersect(
1327
0
    nc, &permitted, &nc->permitted, &nc2->permitted, &nc->excluded);
1328
0
  if (ret < 0) {
1329
0
    gnutls_assert();
1330
0
    goto cleanup;
1331
0
  }
1332
1333
0
  ret = name_constraints_node_list_init(&excluded);
1334
0
  if (ret < 0) {
1335
0
    gnutls_assert();
1336
0
    goto cleanup;
1337
0
  }
1338
1339
0
  ret = name_constraints_node_list_union(nc, &excluded, &nc->excluded,
1340
0
                 &nc2->excluded);
1341
0
  if (ret < 0) {
1342
0
    gnutls_assert();
1343
0
    goto cleanup;
1344
0
  }
1345
0
  name_constraints_node_list_deinit(&nc->permitted);
1346
0
  nc->permitted = name_constraints_node_list_take(&permitted);
1347
0
  name_constraints_node_list_deinit(&nc->excluded);
1348
0
  nc->excluded = name_constraints_node_list_take(&excluded);
1349
1350
0
  ret = GNUTLS_E_SUCCESS;
1351
1352
0
cleanup:
1353
0
  name_constraints_node_list_deinit(&permitted);
1354
0
  name_constraints_node_list_deinit(&excluded);
1355
0
  return ret;
1356
0
}
1357
1358
/**
1359
 * gnutls_x509_name_constraints_add_permitted:
1360
 * @nc: The nameconstraints
1361
 * @type: The type of the constraints
1362
 * @name: The data of the constraints
1363
 *
1364
 * This function will add a name constraint to the list of permitted
1365
 * constraints. The constraints @type can be any of the following types:
1366
 * %GNUTLS_SAN_DNSNAME, %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DN,
1367
 * %GNUTLS_SAN_URI, %GNUTLS_SAN_IPADDRESS. For the latter, an IP address
1368
 * in network byte order is expected, followed by its network mask.
1369
 *
1370
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1371
 *
1372
 * Since: 3.3.0
1373
 **/
1374
int gnutls_x509_name_constraints_add_permitted(
1375
  gnutls_x509_name_constraints_t nc, gnutls_x509_subject_alt_name_t type,
1376
  const gnutls_datum_t *name)
1377
0
{
1378
0
  return name_constraints_add(nc, type, name, 1);
1379
0
}
1380
1381
/**
1382
 * gnutls_x509_name_constraints_add_excluded:
1383
 * @nc: The nameconstraints
1384
 * @type: The type of the constraints
1385
 * @name: The data of the constraints
1386
 *
1387
 * This function will add a name constraint to the list of excluded
1388
 * constraints. The constraints @type can be any of the following types:
1389
 * %GNUTLS_SAN_DNSNAME, %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DN,
1390
 * %GNUTLS_SAN_URI, %GNUTLS_SAN_IPADDRESS. For the latter, an IP address
1391
 * in network byte order is expected, followed by its network mask (which is
1392
 * 4 bytes in IPv4 or 16-bytes in IPv6).
1393
 *
1394
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1395
 *
1396
 * Since: 3.3.0
1397
 **/
1398
int gnutls_x509_name_constraints_add_excluded(
1399
  gnutls_x509_name_constraints_t nc, gnutls_x509_subject_alt_name_t type,
1400
  const gnutls_datum_t *name)
1401
0
{
1402
0
  return name_constraints_add(nc, type, name, 0);
1403
0
}
1404
1405
/**
1406
 * gnutls_x509_crt_set_name_constraints:
1407
 * @crt: The certificate
1408
 * @nc: The nameconstraints structure
1409
 * @critical: whether this extension will be critical
1410
 *
1411
 * This function will set the provided name constraints to
1412
 * the certificate extension list. This extension is always
1413
 * marked as critical.
1414
 *
1415
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
1416
 *
1417
 * Since: 3.3.0
1418
 **/
1419
int gnutls_x509_crt_set_name_constraints(gnutls_x509_crt_t crt,
1420
           gnutls_x509_name_constraints_t nc,
1421
           unsigned int critical)
1422
0
{
1423
0
  int ret;
1424
0
  gnutls_datum_t der;
1425
1426
0
  ret = gnutls_x509_ext_export_name_constraints(nc, &der);
1427
0
  if (ret < 0)
1428
0
    return gnutls_assert_val(ret);
1429
1430
0
  ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.30", &der, critical);
1431
0
  if (ret < 0) {
1432
0
    gnutls_assert();
1433
0
    goto cleanup;
1434
0
  }
1435
1436
0
  ret = 0;
1437
0
  crt->use_extensions = 1;
1438
1439
0
cleanup:
1440
0
  _gnutls_free_datum(&der);
1441
0
  return ret;
1442
0
}
1443
1444
static bool dnsname_matches(const gnutls_datum_t *name,
1445
          const gnutls_datum_t *suffix)
1446
0
{
1447
0
  _gnutls_hard_log("matching %.*s with DNS constraint %.*s\n", name->size,
1448
0
       name->data, suffix->size, suffix->data);
1449
1450
0
  enum name_constraint_relation rel = compare_dns_names(name, suffix);
1451
0
  return rel == NC_EQUAL || rel == NC_INCLUDED_BY;
1452
0
}
1453
1454
static bool email_matches(const gnutls_datum_t *name,
1455
        const gnutls_datum_t *suffix)
1456
0
{
1457
0
  _gnutls_hard_log("matching %.*s with e-mail constraint %.*s\n",
1458
0
       name->size, name->data, suffix->size, suffix->data);
1459
1460
0
  enum name_constraint_relation rel = compare_emails(name, suffix);
1461
0
  return rel == NC_EQUAL || rel == NC_INCLUDED_BY;
1462
0
}
1463
1464
/*
1465
 * Returns: true if the certification is acceptable, and false otherwise.
1466
 */
1467
static bool check_unsupported_constraint(gnutls_x509_name_constraints_t nc,
1468
           gnutls_x509_subject_alt_name_t type)
1469
0
{
1470
0
  unsigned i;
1471
0
  int ret;
1472
0
  unsigned rtype;
1473
0
  gnutls_datum_t rname;
1474
1475
  /* check if there is a restrictions with that type, if
1476
   * yes, then reject the name.
1477
   */
1478
0
  i = 0;
1479
0
  do {
1480
0
    ret = gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
1481
0
                &rname);
1482
0
    if (ret >= 0) {
1483
0
      if (rtype != type)
1484
0
        continue;
1485
0
      else
1486
0
        return gnutls_assert_val(false);
1487
0
    }
1488
1489
0
  } while (ret == 0);
1490
1491
0
  return true;
1492
0
}
1493
1494
static bool check_dns_constraints(gnutls_x509_name_constraints_t nc,
1495
          const gnutls_datum_t *name)
1496
0
{
1497
0
  unsigned i;
1498
0
  int ret;
1499
0
  unsigned rtype;
1500
0
  bool allowed_found = false;
1501
0
  gnutls_datum_t rname;
1502
1503
  /* check restrictions */
1504
0
  i = 0;
1505
0
  do {
1506
0
    ret = gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
1507
0
                &rname);
1508
0
    if (ret >= 0) {
1509
0
      if (rtype != GNUTLS_SAN_DNSNAME)
1510
0
        continue;
1511
1512
      /* a name of value 0 means that the CA shouldn't have issued
1513
       * a certificate with a DNSNAME. */
1514
0
      if (rname.size == 0)
1515
0
        return gnutls_assert_val(false);
1516
1517
0
      if (dnsname_matches(name, &rname))
1518
0
        return gnutls_assert_val(false); /* rejected */
1519
0
    }
1520
0
  } while (ret == 0);
1521
1522
  /* check allowed */
1523
0
  i = 0;
1524
0
  do {
1525
0
    ret = gnutls_x509_name_constraints_get_permitted(
1526
0
      nc, i++, &rtype, &rname);
1527
0
    if (ret >= 0) {
1528
0
      if (rtype != GNUTLS_SAN_DNSNAME)
1529
0
        continue;
1530
1531
0
      if (rname.size == 0)
1532
0
        continue;
1533
1534
0
      allowed_found = true;
1535
1536
0
      if (dnsname_matches(name, &rname))
1537
0
        return true; /* accepted */
1538
0
    }
1539
0
  } while (ret == 0);
1540
1541
  /* there are allowed directives but this host wasn't found */
1542
0
  if (allowed_found)
1543
0
    return gnutls_assert_val(false);
1544
1545
0
  return true;
1546
0
}
1547
1548
static unsigned check_email_constraints(gnutls_x509_name_constraints_t nc,
1549
          const gnutls_datum_t *name)
1550
0
{
1551
0
  unsigned i;
1552
0
  int ret;
1553
0
  unsigned rtype;
1554
0
  bool allowed_found = false;
1555
0
  gnutls_datum_t rname;
1556
1557
  /* check restrictions */
1558
0
  i = 0;
1559
0
  do {
1560
0
    ret = gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
1561
0
                &rname);
1562
0
    if (ret >= 0) {
1563
0
      if (rtype != GNUTLS_SAN_RFC822NAME)
1564
0
        continue;
1565
1566
      /* a name of value 0 means that the CA shouldn't have issued
1567
       * a certificate with an e-mail. */
1568
0
      if (rname.size == 0)
1569
0
        return gnutls_assert_val(false);
1570
1571
0
      if (email_matches(name, &rname))
1572
0
        return gnutls_assert_val(false); /* rejected */
1573
0
    }
1574
0
  } while (ret == 0);
1575
1576
  /* check allowed */
1577
0
  i = 0;
1578
0
  do {
1579
0
    ret = gnutls_x509_name_constraints_get_permitted(
1580
0
      nc, i++, &rtype, &rname);
1581
0
    if (ret >= 0) {
1582
0
      if (rtype != GNUTLS_SAN_RFC822NAME)
1583
0
        continue;
1584
1585
0
      if (rname.size == 0)
1586
0
        continue;
1587
1588
0
      allowed_found = true;
1589
1590
0
      if (email_matches(name, &rname))
1591
0
        return true; /* accepted */
1592
0
    }
1593
0
  } while (ret == 0);
1594
1595
  /* there are allowed directives but this host wasn't found */
1596
0
  if (allowed_found)
1597
0
    return gnutls_assert_val(false);
1598
1599
0
  return true;
1600
0
}
1601
1602
static unsigned check_ip_constraints(gnutls_x509_name_constraints_t nc,
1603
             const gnutls_datum_t *name)
1604
0
{
1605
0
  unsigned i;
1606
0
  int ret;
1607
0
  unsigned rtype;
1608
0
  bool allowed_found = false;
1609
0
  gnutls_datum_t rname;
1610
1611
  /* check restrictions */
1612
0
  i = 0;
1613
0
  do {
1614
0
    ret = gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
1615
0
                &rname);
1616
0
    if (ret >= 0) {
1617
0
      if (rtype != GNUTLS_SAN_IPADDRESS)
1618
0
        continue;
1619
1620
      /* do not check IPv4 against IPv6 constraints and vice versa */
1621
0
      if (name->size != rname.size / 2)
1622
0
        continue;
1623
1624
0
      if (ip_in_cidr(name, &rname))
1625
0
        return gnutls_assert_val(false); /* rejected */
1626
0
    }
1627
0
  } while (ret == 0);
1628
1629
  /* check allowed */
1630
0
  i = 0;
1631
0
  do {
1632
0
    ret = gnutls_x509_name_constraints_get_permitted(
1633
0
      nc, i++, &rtype, &rname);
1634
0
    if (ret >= 0) {
1635
0
      if (rtype != GNUTLS_SAN_IPADDRESS)
1636
0
        continue;
1637
1638
      /* do not check IPv4 against IPv6 constraints and vice versa */
1639
0
      if (name->size != rname.size / 2)
1640
0
        continue;
1641
1642
0
      allowed_found = true;
1643
1644
0
      if (ip_in_cidr(name, &rname))
1645
0
        return true; /* accepted */
1646
0
    }
1647
0
  } while (ret == 0);
1648
1649
  /* there are allowed directives but this host wasn't found */
1650
0
  if (allowed_found)
1651
0
    return gnutls_assert_val(false);
1652
1653
0
  return true;
1654
0
}
1655
1656
/**
1657
 * gnutls_x509_name_constraints_check:
1658
 * @nc: the extracted name constraints
1659
 * @type: the type of the constraint to check (of type gnutls_x509_subject_alt_name_t)
1660
 * @name: the name to be checked
1661
 *
1662
 * This function will check the provided name against the constraints in
1663
 * @nc using the RFC5280 rules. Currently this function is limited to DNS
1664
 * names, emails and IP addresses (of type %GNUTLS_SAN_DNSNAME,
1665
 * %GNUTLS_SAN_RFC822NAME and %GNUTLS_SAN_IPADDRESS).
1666
 *
1667
 * Returns: zero if the provided name is not acceptable, and non-zero otherwise.
1668
 *
1669
 * Since: 3.3.0
1670
 **/
1671
unsigned gnutls_x509_name_constraints_check(gnutls_x509_name_constraints_t nc,
1672
              gnutls_x509_subject_alt_name_t type,
1673
              const gnutls_datum_t *name)
1674
0
{
1675
0
  if (type == GNUTLS_SAN_DNSNAME)
1676
0
    return check_dns_constraints(nc, name);
1677
1678
0
  if (type == GNUTLS_SAN_RFC822NAME)
1679
0
    return check_email_constraints(nc, name);
1680
1681
0
  if (type == GNUTLS_SAN_IPADDRESS)
1682
0
    return check_ip_constraints(nc, name);
1683
1684
0
  return check_unsupported_constraint(nc, type);
1685
0
}
1686
1687
/* This function checks for unsupported constraints, that we also
1688
 * know their structure. That is it will fail only if the constraint
1689
 * is present in the CA, _and_ the name in the end certificate contains
1690
 * the constrained element.
1691
 *
1692
 * Returns: true if the certification is acceptable, and false otherwise
1693
 */
1694
static bool check_unsupported_constraint2(gnutls_x509_crt_t cert,
1695
            gnutls_x509_name_constraints_t nc,
1696
            gnutls_x509_subject_alt_name_t type)
1697
0
{
1698
0
  unsigned idx;
1699
0
  bool found_one;
1700
0
  char name[MAX_CN];
1701
0
  size_t name_size;
1702
0
  unsigned san_type;
1703
0
  int ret;
1704
1705
0
  found_one = false;
1706
1707
0
  for (idx = 0;; idx++) {
1708
0
    name_size = sizeof(name);
1709
0
    ret = gnutls_x509_crt_get_subject_alt_name2(
1710
0
      cert, idx, name, &name_size, &san_type, NULL);
1711
0
    if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1712
0
      break;
1713
0
    else if (ret < 0)
1714
0
      return gnutls_assert_val(false);
1715
1716
0
    if (san_type != GNUTLS_SAN_URI)
1717
0
      continue;
1718
1719
0
    found_one = true;
1720
0
    break;
1721
0
  }
1722
1723
0
  if (found_one)
1724
0
    return check_unsupported_constraint(nc, type);
1725
1726
  /* no name was found in the certificate, so accept */
1727
0
  return true;
1728
0
}
1729
1730
/**
1731
 * gnutls_x509_name_constraints_check_crt:
1732
 * @nc: the extracted name constraints
1733
 * @type: the type of the constraint to check (of type gnutls_x509_subject_alt_name_t)
1734
 * @cert: the certificate to be checked
1735
 *
1736
 * This function will check the provided certificate names against the constraints in
1737
 * @nc using the RFC5280 rules. It will traverse all the certificate's names and
1738
 * alternative names.
1739
 *
1740
 * Currently this function is limited to DNS
1741
 * names and emails (of type %GNUTLS_SAN_DNSNAME and %GNUTLS_SAN_RFC822NAME).
1742
 *
1743
 * Returns: zero if the provided name is not acceptable, and non-zero otherwise.
1744
 *
1745
 * Since: 3.3.0
1746
 **/
1747
unsigned
1748
gnutls_x509_name_constraints_check_crt(gnutls_x509_name_constraints_t nc,
1749
               gnutls_x509_subject_alt_name_t type,
1750
               gnutls_x509_crt_t cert)
1751
0
{
1752
0
  char name[MAX_CN];
1753
0
  size_t name_size;
1754
0
  int ret;
1755
0
  unsigned idx, t, san_type;
1756
0
  gnutls_datum_t n;
1757
0
  bool found_one;
1758
0
  size_t checks;
1759
1760
0
  if (!name_constraints_contains_type(nc, type))
1761
0
    return 1; /* shortcut; no constraints to check */
1762
1763
0
  if (!INT_ADD_OK(gl_list_size(nc->permitted.items),
1764
0
      gl_list_size(nc->excluded.items), &checks) ||
1765
0
      !INT_MULTIPLY_OK(checks, cert->san->size, &checks) ||
1766
0
      checks > MAX_NC_CHECKS) {
1767
0
    return gnutls_assert_val(0);
1768
0
  }
1769
1770
0
  if (type == GNUTLS_SAN_RFC822NAME) {
1771
0
    found_one = false;
1772
0
    for (idx = 0;; idx++) {
1773
0
      name_size = sizeof(name);
1774
0
      ret = gnutls_x509_crt_get_subject_alt_name2(
1775
0
        cert, idx, name, &name_size, &san_type, NULL);
1776
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1777
0
        break;
1778
0
      else if (ret < 0)
1779
0
        return gnutls_assert_val(0);
1780
1781
0
      if (san_type != GNUTLS_SAN_RFC822NAME)
1782
0
        continue;
1783
1784
0
      found_one = true;
1785
0
      n.data = (void *)name;
1786
0
      n.size = name_size;
1787
0
      t = gnutls_x509_name_constraints_check(
1788
0
        nc, GNUTLS_SAN_RFC822NAME, &n);
1789
0
      if (t == 0)
1790
0
        return gnutls_assert_val(t);
1791
0
    }
1792
1793
    /* there is at least a single e-mail. That means that the EMAIL field will
1794
     * not be used for verifying the identity of the holder. */
1795
0
    if (found_one)
1796
0
      return 1;
1797
1798
0
    do {
1799
      /* ensure there is only a single EMAIL, similarly to CN handling (rfc6125) */
1800
0
      name_size = sizeof(name);
1801
0
      ret = gnutls_x509_crt_get_dn_by_oid(
1802
0
        cert, GNUTLS_OID_PKCS9_EMAIL, 1, 0, name,
1803
0
        &name_size);
1804
0
      if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1805
0
        return gnutls_assert_val(0);
1806
1807
0
      name_size = sizeof(name);
1808
0
      ret = gnutls_x509_crt_get_dn_by_oid(
1809
0
        cert, GNUTLS_OID_PKCS9_EMAIL, 0, 0, name,
1810
0
        &name_size);
1811
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1812
0
        break;
1813
0
      else if (ret < 0)
1814
0
        return gnutls_assert_val(0);
1815
1816
0
      found_one = true;
1817
0
      n.data = (void *)name;
1818
0
      n.size = name_size;
1819
0
      t = gnutls_x509_name_constraints_check(
1820
0
        nc, GNUTLS_SAN_RFC822NAME, &n);
1821
0
      if (t == 0)
1822
0
        return gnutls_assert_val(t);
1823
0
    } while (0);
1824
1825
    /* passed */
1826
0
    if (found_one)
1827
0
      return 1;
1828
0
    else {
1829
      /* no name was found. According to RFC5280: 
1830
       * If no name of the type is in the certificate, the certificate is acceptable.
1831
       */
1832
0
      return gnutls_assert_val(1);
1833
0
    }
1834
0
  } else if (type == GNUTLS_SAN_DNSNAME) {
1835
0
    found_one = false;
1836
0
    for (idx = 0;; idx++) {
1837
0
      name_size = sizeof(name);
1838
0
      ret = gnutls_x509_crt_get_subject_alt_name2(
1839
0
        cert, idx, name, &name_size, &san_type, NULL);
1840
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1841
0
        break;
1842
0
      else if (ret < 0)
1843
0
        return gnutls_assert_val(0);
1844
1845
0
      if (san_type != GNUTLS_SAN_DNSNAME)
1846
0
        continue;
1847
1848
0
      found_one = true;
1849
0
      n.data = (void *)name;
1850
0
      n.size = name_size;
1851
0
      t = gnutls_x509_name_constraints_check(
1852
0
        nc, GNUTLS_SAN_DNSNAME, &n);
1853
0
      if (t == 0)
1854
0
        return gnutls_assert_val(t);
1855
0
    }
1856
1857
    /* there is at least a single DNS name. That means that the CN will
1858
     * not be used for verifying the identity of the holder. */
1859
0
    if (found_one)
1860
0
      return 1;
1861
1862
    /* verify the name constraints against the CN, if the certificate is
1863
     * not a CA. We do this check only on certificates marked as WWW server,
1864
     * because that's where the CN check is only performed. */
1865
0
    if (_gnutls_check_key_purpose(cert, GNUTLS_KP_TLS_WWW_SERVER,
1866
0
                0) != 0)
1867
0
      do {
1868
        /* ensure there is only a single CN, according to rfc6125 */
1869
0
        name_size = sizeof(name);
1870
0
        ret = gnutls_x509_crt_get_dn_by_oid(
1871
0
          cert, GNUTLS_OID_X520_COMMON_NAME, 1, 0,
1872
0
          name, &name_size);
1873
0
        if (ret !=
1874
0
            GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1875
0
          return gnutls_assert_val(0);
1876
1877
0
        name_size = sizeof(name);
1878
0
        ret = gnutls_x509_crt_get_dn_by_oid(
1879
0
          cert, GNUTLS_OID_X520_COMMON_NAME, 0, 0,
1880
0
          name, &name_size);
1881
0
        if (ret ==
1882
0
            GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1883
0
          break;
1884
0
        else if (ret < 0)
1885
0
          return gnutls_assert_val(0);
1886
1887
0
        found_one = true;
1888
0
        n.data = (void *)name;
1889
0
        n.size = name_size;
1890
0
        t = gnutls_x509_name_constraints_check(
1891
0
          nc, GNUTLS_SAN_DNSNAME, &n);
1892
0
        if (t == 0)
1893
0
          return gnutls_assert_val(t);
1894
0
      } while (0);
1895
1896
    /* passed */
1897
0
    if (found_one)
1898
0
      return 1;
1899
0
    else {
1900
      /* no name was found. According to RFC5280: 
1901
       * If no name of the type is in the certificate, the certificate is acceptable.
1902
       */
1903
0
      return gnutls_assert_val(1);
1904
0
    }
1905
0
  } else if (type == GNUTLS_SAN_IPADDRESS) {
1906
0
    found_one = false;
1907
0
    for (idx = 0;; idx++) {
1908
0
      name_size = sizeof(name);
1909
0
      ret = gnutls_x509_crt_get_subject_alt_name2(
1910
0
        cert, idx, name, &name_size, &san_type, NULL);
1911
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1912
0
        break;
1913
0
      else if (ret < 0)
1914
0
        return gnutls_assert_val(0);
1915
1916
0
      if (san_type != GNUTLS_SAN_IPADDRESS)
1917
0
        continue;
1918
1919
0
      found_one = true;
1920
0
      n.data = (void *)name;
1921
0
      n.size = name_size;
1922
0
      t = gnutls_x509_name_constraints_check(
1923
0
        nc, GNUTLS_SAN_IPADDRESS, &n);
1924
0
      if (t == 0)
1925
0
        return gnutls_assert_val(t);
1926
0
    }
1927
1928
    /* there is at least a single IP address. */
1929
1930
0
    if (found_one) {
1931
0
      return 1;
1932
0
    } else {
1933
      /* no name was found. According to RFC5280:
1934
       * If no name of the type is in the certificate, the certificate is acceptable.
1935
       */
1936
0
      return gnutls_assert_val(1);
1937
0
    }
1938
0
  } else if (type == GNUTLS_SAN_URI) {
1939
0
    return check_unsupported_constraint2(cert, nc, type);
1940
0
  } else
1941
0
    return check_unsupported_constraint(nc, type);
1942
0
}
1943
1944
/**
1945
 * gnutls_x509_name_constraints_get_permitted:
1946
 * @nc: the extracted name constraints
1947
 * @idx: the index of the constraint
1948
 * @type: the type of the constraint (of type gnutls_x509_subject_alt_name_t)
1949
 * @name: the name in the constraint (of the specific type)
1950
 *
1951
 * This function will return an intermediate type containing
1952
 * the name constraints of the provided CA certificate. That
1953
 * structure can be used in combination with gnutls_x509_name_constraints_check()
1954
 * to verify whether a server's name is in accordance with the constraints.
1955
 *
1956
 * The name should be treated as constant and valid for the lifetime of @nc.
1957
 *
1958
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1959
 * if the extension is not present, otherwise a negative error value.
1960
 *
1961
 * Since: 3.3.0
1962
 **/
1963
int gnutls_x509_name_constraints_get_permitted(gnutls_x509_name_constraints_t nc,
1964
                 unsigned idx, unsigned *type,
1965
                 gnutls_datum_t *name)
1966
0
{
1967
0
  const struct name_constraints_node_st *tmp;
1968
1969
0
  if (idx >= gl_list_size(nc->permitted.items))
1970
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1971
1972
0
  tmp = gl_list_get_at(nc->permitted.items, idx);
1973
1974
0
  *type = tmp->type;
1975
0
  *name = tmp->name;
1976
1977
0
  return 0;
1978
0
}
1979
1980
/**
1981
 * gnutls_x509_name_constraints_get_excluded:
1982
 * @nc: the extracted name constraints
1983
 * @idx: the index of the constraint
1984
 * @type: the type of the constraint (of type gnutls_x509_subject_alt_name_t)
1985
 * @name: the name in the constraint (of the specific type)
1986
 *
1987
 * This function will return an intermediate type containing
1988
 * the name constraints of the provided CA certificate. That
1989
 * structure can be used in combination with gnutls_x509_name_constraints_check()
1990
 * to verify whether a server's name is in accordance with the constraints.
1991
 *
1992
 * The name should be treated as constant and valid for the lifetime of @nc.
1993
 *
1994
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1995
 * if the extension is not present, otherwise a negative error value.
1996
 *
1997
 * Since: 3.3.0
1998
 **/
1999
int gnutls_x509_name_constraints_get_excluded(gnutls_x509_name_constraints_t nc,
2000
                unsigned idx, unsigned *type,
2001
                gnutls_datum_t *name)
2002
0
{
2003
0
  const struct name_constraints_node_st *tmp;
2004
2005
0
  if (idx >= gl_list_size(nc->excluded.items))
2006
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
2007
2008
0
  tmp = gl_list_get_at(nc->excluded.items, idx);
2009
2010
0
  *type = tmp->type;
2011
0
  *name = tmp->name;
2012
2013
0
  return 0;
2014
0
}