Coverage Report

Created: 2026-02-14 07:17

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