Coverage Report

Created: 2026-03-31 07:20

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