Coverage Report

Created: 2026-08-14 06:46

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