Coverage Report

Created: 2023-03-26 08:33

/src/gnutls/lib/x509/name_constraints.c
Line
Count
Source (jump to first uncovered line)
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 <libtasn1.h>
37
38
#include "ip.h"
39
#include "ip-in-cidr.h"
40
41
// for documentation see the implementation
42
static int name_constraints_intersect_nodes(name_constraints_node_st * nc1,
43
              name_constraints_node_st * nc2,
44
              name_constraints_node_st **
45
              intersection);
46
47
/*-
48
 * is_nc_empty:
49
 * @nc: name constraints structure
50
 * @type: type (gnutls_x509_subject_alt_name_t)
51
 *
52
 * Test whether given name constraints structure has any constraints (permitted
53
 * or excluded) of a given type. @nc must be allocated (not NULL) before the call.
54
 *
55
 * Returns: 0 if @nc contains constraints of type @type, 1 otherwise
56
 -*/
57
static unsigned is_nc_empty(struct gnutls_name_constraints_st *nc,
58
          unsigned type)
59
0
{
60
0
  name_constraints_node_st *t;
61
62
0
  if (nc->permitted == NULL && nc->excluded == NULL)
63
0
    return 1;
64
65
0
  t = nc->permitted;
66
0
  while (t != NULL) {
67
0
    if (t->type == type)
68
0
      return 0;
69
0
    t = t->next;
70
0
  }
71
72
0
  t = nc->excluded;
73
0
  while (t != NULL) {
74
0
    if (t->type == type)
75
0
      return 0;
76
0
    t = t->next;
77
0
  }
78
79
  /* no constraint for that type exists */
80
0
  return 1;
81
0
}
82
83
/*-
84
 * validate_name_constraints_node:
85
 * @type: type of name constraints
86
 * @name: datum of name constraint
87
 *
88
 * Check the validity of given name constraints node (@type and @name).
89
 * The supported types are GNUTLS_SAN_DNSNAME, GNUTLS_SAN_RFC822NAME,
90
 * GNUTLS_SAN_DN, GNUTLS_SAN_URI and GNUTLS_SAN_IPADDRESS.
91
 *
92
 * CIDR ranges are checked for correct length (IPv4/IPv6) and correct mask format.
93
 *
94
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
95
 -*/
96
static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type,
97
            const gnutls_datum_t * name)
98
0
{
99
0
  if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME &&
100
0
      type != GNUTLS_SAN_DN && type != GNUTLS_SAN_URI &&
101
0
      type != GNUTLS_SAN_IPADDRESS &&
102
0
      type != GNUTLS_SAN_OTHERNAME_MSUSERPRINCIPAL) {
103
0
    return gnutls_assert_val(GNUTLS_E_X509_UNKNOWN_SAN);
104
0
  }
105
106
0
  if (type == GNUTLS_SAN_IPADDRESS) {
107
0
    if (name->size != 8 && name->size != 32)
108
0
      return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
109
0
    int prefix = _gnutls_mask_to_prefix(name->data + name->size / 2,
110
0
                name->size / 2);
111
0
    if (prefix < 0)
112
0
      return gnutls_assert_val(GNUTLS_E_MALFORMED_CIDR);
113
0
  }
114
115
0
  return GNUTLS_E_SUCCESS;
116
0
}
117
118
int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr,
119
             name_constraints_node_st ** _nc)
120
0
{
121
0
  int ret;
122
0
  char tmpstr[128];
123
0
  unsigned indx;
124
0
  gnutls_datum_t tmp = { NULL, 0 };
125
0
  unsigned int type;
126
0
  struct name_constraints_node_st *nc, *prev;
127
128
0
  prev = *_nc;
129
0
  if (prev != NULL) {
130
0
    while (prev->next != NULL)
131
0
      prev = prev->next;
132
0
  }
133
134
0
  for (indx = 1;; indx++) {
135
0
    snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx);
136
137
0
    ret =
138
0
        _gnutls_parse_general_name2(c2, tmpstr, -1, &tmp, &type, 0);
139
140
0
    if (ret < 0) {
141
0
      gnutls_assert();
142
0
      break;
143
0
    }
144
145
0
    if (type == GNUTLS_SAN_OTHERNAME) {
146
0
      gnutls_datum_t oid = { NULL, 0 };
147
0
      gnutls_datum_t parsed_othername = { NULL, 0 };
148
0
      ret =
149
0
          _gnutls_parse_general_name2(c2, tmpstr, -1, &oid,
150
0
              &type, 1);
151
0
      if (ret < 0) {
152
0
        gnutls_assert();
153
0
        goto cleanup;
154
0
      }
155
156
0
      ret =
157
0
          gnutls_x509_othername_to_virtual((char *)oid.data,
158
0
                   &tmp, &type,
159
0
                   &parsed_othername);
160
0
      if (ret < 0) {
161
0
        gnutls_assert();
162
0
        goto cleanup;
163
0
      }
164
165
0
      gnutls_free(oid.data);
166
0
      gnutls_free(tmp.data);
167
168
0
      memcpy(&tmp, &parsed_othername, sizeof(gnutls_datum_t));
169
0
    }
170
171
0
    ret = validate_name_constraints_node(type, &tmp);
172
0
    if (ret < 0) {
173
0
      gnutls_assert();
174
0
      goto cleanup;
175
0
    }
176
177
0
    nc = gnutls_malloc(sizeof(struct name_constraints_node_st));
178
0
    if (nc == NULL) {
179
0
      gnutls_assert();
180
0
      ret = GNUTLS_E_MEMORY_ERROR;
181
0
      goto cleanup;
182
0
    }
183
184
0
    memcpy(&nc->name, &tmp, sizeof(gnutls_datum_t));
185
0
    nc->type = type;
186
0
    nc->next = NULL;
187
188
0
    if (prev == NULL) {
189
0
      *_nc = prev = nc;
190
0
    } else {
191
0
      prev->next = nc;
192
0
      prev = nc;
193
0
    }
194
195
0
    tmp.data = NULL;
196
0
  }
197
198
0
  assert(ret < 0);
199
0
  if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) {
200
0
    gnutls_assert();
201
0
    goto cleanup;
202
0
  }
203
204
0
  ret = 0;
205
0
 cleanup:
206
0
  gnutls_free(tmp.data);
207
0
  return ret;
208
0
}
209
210
/*-
211
 * _gnutls_name_constraints_node_free:
212
 * @node: name constraints node
213
 *
214
 * Deallocate a list of name constraints nodes starting at the given node.
215
 -*/
216
void _gnutls_name_constraints_node_free(name_constraints_node_st * node)
217
0
{
218
0
  name_constraints_node_st *next, *t;
219
220
0
  t = node;
221
0
  while (t != NULL) {
222
0
    next = t->next;
223
0
    gnutls_free(t->name.data);
224
0
    gnutls_free(t);
225
0
    t = next;
226
0
  }
227
0
}
228
229
/*-
230
 * name_constraints_node_new:
231
 * @type: name constraints type to set (gnutls_x509_subject_alt_name_t)
232
 * @data: name.data to set or NULL
233
 * @size: name.size to set
234
 *
235
 * Allocate a new name constraints node and set its type, name size and name data.
236
 * If @data is set to NULL, name data will be an array of \x00 (the length of @size).
237
 * The .next pointer is set to NULL.
238
 *
239
 * Returns: Pointer to newly allocated node or NULL in case of memory error.
240
 -*/
241
static name_constraints_node_st *name_constraints_node_new(unsigned type,
242
                 unsigned char *data,
243
                 unsigned int size)
244
0
{
245
0
  name_constraints_node_st *tmp =
246
0
      gnutls_malloc(sizeof(struct name_constraints_node_st));
247
0
  if (tmp == NULL)
248
0
    return NULL;
249
0
  tmp->type = type;
250
0
  tmp->next = NULL;
251
0
  tmp->name.size = size;
252
0
  tmp->name.data = NULL;
253
0
  if (tmp->name.size > 0) {
254
255
0
    tmp->name.data = gnutls_malloc(tmp->name.size);
256
0
    if (tmp->name.data == NULL) {
257
0
      gnutls_free(tmp);
258
0
      return NULL;
259
0
    }
260
0
    if (data != NULL) {
261
0
      memcpy(tmp->name.data, data, size);
262
0
    } else {
263
0
      memset(tmp->name.data, 0, size);
264
0
    }
265
0
  }
266
0
  return tmp;
267
0
}
268
269
/*-
270
 * @brief _gnutls_name_constraints_intersect:
271
 * @_nc: first name constraints list (permitted)
272
 * @_nc2: name constraints list to merge with (permitted)
273
 * @_nc_excluded: Corresponding excluded name constraints list
274
 *
275
 * This function finds the intersection of @_nc and @_nc2. The result is placed in @_nc,
276
 * the original @_nc is deallocated. @_nc2 is not changed. If necessary, a universal
277
 * excluded name constraint node of the right type is added to the list provided
278
 * in @_nc_excluded.
279
 *
280
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
281
 -*/
282
static
283
int _gnutls_name_constraints_intersect(name_constraints_node_st ** _nc,
284
               name_constraints_node_st * _nc2,
285
               name_constraints_node_st ** _nc_excluded)
286
0
{
287
0
  name_constraints_node_st *nc, *nc2, *t, *tmp, *dest = NULL, *prev =
288
0
      NULL;
289
0
  int ret, type, used;
290
291
  /* temporary array to see, if we need to add universal excluded constraints
292
   * (see phase 3 for details)
293
   * indexed directly by (gnutls_x509_subject_alt_name_t enum - 1) */
294
0
  unsigned char types_with_empty_intersection[GNUTLS_SAN_MAX];
295
0
  memset(types_with_empty_intersection, 0,
296
0
         sizeof(types_with_empty_intersection));
297
298
0
  if (*_nc == NULL || _nc2 == NULL)
299
0
    return 0;
300
301
  /* Phase 1
302
   * For each name in _NC, if a _NC2 does not contain a name
303
   * with the same type, preserve the original name.
304
   * Do this also for node of unknown type (not DNS, email, IP */
305
0
  t = nc = *_nc;
306
0
  while (t != NULL) {
307
0
    name_constraints_node_st *next = t->next;
308
0
    nc2 = _nc2;
309
0
    while (nc2 != NULL) {
310
0
      if (t->type == nc2->type) {
311
        // check bounds (we will use 't->type' as index)
312
0
        if (t->type > GNUTLS_SAN_MAX || t->type == 0)
313
0
          return
314
0
              gnutls_assert_val
315
0
              (GNUTLS_E_INTERNAL_ERROR);
316
        // note the possibility of empty intersection for this type
317
        // if we add something to the intersection in phase 2,
318
        // we will reset this flag back to 0 then
319
0
        types_with_empty_intersection[t->type - 1] = 1;
320
0
        break;
321
0
      }
322
0
      nc2 = nc2->next;
323
0
    }
324
0
    if (nc2 == NULL ||
325
0
        (t->type != GNUTLS_SAN_DNSNAME &&
326
0
         t->type != GNUTLS_SAN_RFC822NAME &&
327
0
         t->type != GNUTLS_SAN_IPADDRESS)
328
0
        ) {
329
      /* move node from NC to DEST */
330
0
      if (prev != NULL)
331
0
        prev->next = next;
332
0
      else
333
0
        prev = nc = next;
334
0
      t->next = dest;
335
0
      dest = t;
336
0
    } else {
337
0
      prev = t;
338
0
    }
339
0
    t = next;
340
0
  }
341
342
  /* Phase 2
343
   * iterate through all combinations from nc2 and nc1
344
   * and create intersections of nodes with same type */
345
0
  nc2 = _nc2;
346
0
  while (nc2 != NULL) {
347
    // current nc2 node has not yet been used for any intersection
348
    // (and is not in DEST either)
349
0
    used = 0;
350
0
    t = nc;
351
0
    while (t != NULL) {
352
      // save intersection of name constraints into tmp
353
0
      ret = name_constraints_intersect_nodes(t, nc2, &tmp);
354
0
      if (ret < 0)
355
0
        return gnutls_assert_val(ret);
356
0
      used = 1;
357
      // if intersection is not empty
358
0
      if (tmp != NULL) { // intersection for this type is not empty
359
        // check bounds
360
0
        if (tmp->type > GNUTLS_SAN_MAX
361
0
            || tmp->type == 0) {
362
0
          gnutls_free(tmp);
363
0
          return
364
0
              gnutls_assert_val
365
0
              (GNUTLS_E_INTERNAL_ERROR);
366
0
        }
367
        // we will not add universal excluded constraint for this type
368
0
        types_with_empty_intersection[tmp->type - 1] =
369
0
            0;
370
        // add intersection node to DEST
371
0
        tmp->next = dest;
372
0
        dest = tmp;
373
0
      }
374
0
      t = t->next;
375
0
    }
376
    // if the node from nc2 was not used for intersection, copy it to DEST
377
    // Beware: also copies nodes other than DNS, email, IP,
378
    //       since their counterpart may have been moved in phase 1.
379
0
    if (!used) {
380
0
      tmp =
381
0
          name_constraints_node_new(nc2->type, nc2->name.data,
382
0
                  nc2->name.size);
383
0
      if (tmp == NULL) {
384
0
        _gnutls_name_constraints_node_free(dest);
385
0
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
386
0
      }
387
0
      tmp->next = dest;
388
0
      dest = tmp;
389
0
    }
390
0
    nc2 = nc2->next;
391
0
  }
392
393
  /* replace the original with the new */
394
0
  _gnutls_name_constraints_node_free(nc);
395
0
  *_nc = dest;
396
397
  /* Phase 3
398
   * For each type: If we have empty permitted name constraints now
399
   * and we didn't have at the beginning, we have to add a new
400
   * excluded constraint with universal wildcard
401
   * (since the intersection of permitted is now empty). */
402
0
  for (type = 1; type <= GNUTLS_SAN_MAX; type++) {
403
0
    if (types_with_empty_intersection[type - 1] == 0)
404
0
      continue;
405
0
    _gnutls_hard_log
406
0
        ("Adding universal excluded name constraint for type %d.\n",
407
0
         type);
408
0
    switch (type) {
409
0
    case GNUTLS_SAN_IPADDRESS:
410
      // add universal restricted range for IPv4
411
0
      tmp =
412
0
          name_constraints_node_new(GNUTLS_SAN_IPADDRESS,
413
0
                  NULL, 8);
414
0
      if (tmp == NULL) {
415
0
        _gnutls_name_constraints_node_free(dest);
416
0
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
417
0
      }
418
0
      tmp->next = *_nc_excluded;
419
0
      *_nc_excluded = tmp;
420
      // add universal restricted range for IPv6
421
0
      tmp =
422
0
          name_constraints_node_new(GNUTLS_SAN_IPADDRESS,
423
0
                  NULL, 32);
424
0
      if (tmp == NULL) {
425
0
        _gnutls_name_constraints_node_free(dest);
426
0
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
427
0
      }
428
0
      tmp->next = *_nc_excluded;
429
0
      *_nc_excluded = tmp;
430
0
      break;
431
0
    case GNUTLS_SAN_DNSNAME:
432
0
    case GNUTLS_SAN_RFC822NAME:
433
0
      tmp = name_constraints_node_new(type, NULL, 0);
434
0
      if (tmp == NULL) {
435
0
        _gnutls_name_constraints_node_free(dest);
436
0
        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
437
0
      }
438
0
      tmp->next = *_nc_excluded;
439
0
      *_nc_excluded = tmp;
440
0
      break;
441
0
    default:  // do nothing, at least one node was already moved in phase 1
442
0
      break;
443
0
    }
444
0
  }
445
0
  return GNUTLS_E_SUCCESS;
446
0
}
447
448
static int _gnutls_name_constraints_append(name_constraints_node_st ** _nc,
449
             name_constraints_node_st * _nc2)
450
0
{
451
0
  name_constraints_node_st *nc, *nc2;
452
0
  struct name_constraints_node_st *tmp;
453
454
0
  if (_nc2 == NULL)
455
0
    return 0;
456
457
0
  nc2 = _nc2;
458
0
  while (nc2) {
459
0
    nc = *_nc;
460
461
0
    tmp =
462
0
        name_constraints_node_new(nc2->type, nc2->name.data,
463
0
                nc2->name.size);
464
0
    if (tmp == NULL)
465
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
466
467
0
    tmp->next = nc;
468
0
    *_nc = tmp;
469
470
0
    nc2 = nc2->next;
471
0
  }
472
473
0
  return 0;
474
0
}
475
476
/**
477
 * gnutls_x509_crt_get_name_constraints:
478
 * @crt: should contain a #gnutls_x509_crt_t type
479
 * @nc: The nameconstraints intermediate type
480
 * @flags: zero or %GNUTLS_EXT_FLAG_APPEND
481
 * @critical: the extension status
482
 *
483
 * This function will return an intermediate type containing
484
 * the name constraints of the provided CA certificate. That
485
 * structure can be used in combination with gnutls_x509_name_constraints_check()
486
 * to verify whether a server's name is in accordance with the constraints.
487
 *
488
 * When the @flags is set to %GNUTLS_EXT_FLAG_APPEND,
489
 * then if the @nc structure is empty this function will behave
490
 * identically as if the flag was not set.
491
 * Otherwise if there are elements in the @nc structure then the
492
 * constraints will be merged with the existing constraints following
493
 * RFC5280 p6.1.4 (excluded constraints will be appended, permitted
494
 * will be intersected).
495
 *
496
 * Note that @nc must be initialized prior to calling this function.
497
 *
498
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
499
 * if the extension is not present, otherwise a negative error value.
500
 *
501
 * Since: 3.3.0
502
 **/
503
int gnutls_x509_crt_get_name_constraints(gnutls_x509_crt_t crt,
504
           gnutls_x509_name_constraints_t nc,
505
           unsigned int flags,
506
           unsigned int *critical)
507
0
{
508
0
  int ret;
509
0
  gnutls_datum_t der = { NULL, 0 };
510
511
0
  if (crt == NULL) {
512
0
    gnutls_assert();
513
0
    return GNUTLS_E_INVALID_REQUEST;
514
0
  }
515
516
0
  ret =
517
0
      _gnutls_x509_crt_get_extension(crt, "2.5.29.30", 0, &der, critical);
518
0
  if (ret < 0)
519
0
    return gnutls_assert_val(ret);
520
521
0
  if (der.size == 0 || der.data == NULL)
522
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
523
524
0
  ret = gnutls_x509_ext_import_name_constraints(&der, nc, flags);
525
0
  if (ret < 0) {
526
0
    gnutls_assert();
527
0
    goto cleanup;
528
0
  }
529
530
0
  ret = 0;
531
532
0
 cleanup:
533
0
  _gnutls_free_datum(&der);
534
535
0
  return ret;
536
537
0
}
538
539
/**
540
 * gnutls_x509_name_constraints_deinit:
541
 * @nc: The nameconstraints
542
 *
543
 * This function will deinitialize a name constraints type.
544
 *
545
 * Since: 3.3.0
546
 **/
547
void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc)
548
0
{
549
0
  _gnutls_name_constraints_node_free(nc->permitted);
550
0
  _gnutls_name_constraints_node_free(nc->excluded);
551
552
0
  gnutls_free(nc);
553
0
}
554
555
/**
556
 * gnutls_x509_name_constraints_init:
557
 * @nc: The nameconstraints
558
 *
559
 * This function will initialize a name constraints type.
560
 *
561
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
562
 *
563
 * Since: 3.3.0
564
 **/
565
int gnutls_x509_name_constraints_init(gnutls_x509_name_constraints_t * nc)
566
0
{
567
0
  *nc = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st));
568
0
  if (*nc == NULL) {
569
0
    gnutls_assert();
570
0
    return GNUTLS_E_MEMORY_ERROR;
571
0
  }
572
573
0
  return 0;
574
0
}
575
576
static
577
int name_constraints_add(gnutls_x509_name_constraints_t nc,
578
       gnutls_x509_subject_alt_name_t type,
579
       const gnutls_datum_t * name, unsigned permitted)
580
0
{
581
0
  struct name_constraints_node_st *tmp, *prev = NULL;
582
0
  int ret;
583
584
0
  ret = validate_name_constraints_node(type, name);
585
0
  if (ret < 0)
586
0
    return gnutls_assert_val(ret);
587
588
0
  if (permitted != 0)
589
0
    prev = tmp = nc->permitted;
590
0
  else
591
0
    prev = tmp = nc->excluded;
592
593
0
  while (tmp != NULL) {
594
0
    tmp = tmp->next;
595
0
    if (tmp != NULL)
596
0
      prev = tmp;
597
0
  }
598
599
0
  tmp = name_constraints_node_new(type, name->data, name->size);
600
0
  if (tmp == NULL)
601
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
602
0
  tmp->next = NULL;
603
604
0
  if (prev == NULL) {
605
0
    if (permitted != 0)
606
0
      nc->permitted = tmp;
607
0
    else
608
0
      nc->excluded = tmp;
609
0
  } else
610
0
    prev->next = tmp;
611
612
0
  return 0;
613
0
}
614
615
/*-
616
 * _gnutls_x509_name_constraints_merge:
617
 * @nc: The nameconstraints
618
 * @nc2: The name constraints to be merged with
619
 *
620
 * This function will merge the provided name constraints structures
621
 * as per RFC5280 p6.1.4. That is, the excluded constraints will be appended,
622
 * and permitted will be intersected. The intersection assumes that @nc
623
 * is the root CA constraints.
624
 *
625
 * The merged constraints will be placed in @nc.
626
 *
627
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
628
 *
629
 * Since: 3.5.0
630
 -*/
631
int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc,
632
          gnutls_x509_name_constraints_t nc2)
633
0
{
634
0
  int ret;
635
636
0
  ret =
637
0
      _gnutls_name_constraints_intersect(&nc->permitted,
638
0
                 nc2->permitted, &nc->excluded);
639
0
  if (ret < 0) {
640
0
    gnutls_assert();
641
0
    return ret;
642
0
  }
643
644
0
  ret = _gnutls_name_constraints_append(&nc->excluded, nc2->excluded);
645
0
  if (ret < 0) {
646
0
    gnutls_assert();
647
0
    return ret;
648
0
  }
649
650
0
  return 0;
651
0
}
652
653
/**
654
 * gnutls_x509_name_constraints_add_permitted:
655
 * @nc: The nameconstraints
656
 * @type: The type of the constraints
657
 * @name: The data of the constraints
658
 *
659
 * This function will add a name constraint to the list of permitted
660
 * constraints. The constraints @type can be any of the following types:
661
 * %GNUTLS_SAN_DNSNAME, %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DN,
662
 * %GNUTLS_SAN_URI, %GNUTLS_SAN_IPADDRESS. For the latter, an IP address
663
 * in network byte order is expected, followed by its network mask.
664
 *
665
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
666
 *
667
 * Since: 3.3.0
668
 **/
669
int gnutls_x509_name_constraints_add_permitted(gnutls_x509_name_constraints_t
670
                 nc,
671
                 gnutls_x509_subject_alt_name_t
672
                 type,
673
                 const gnutls_datum_t * name)
674
0
{
675
0
  return name_constraints_add(nc, type, name, 1);
676
0
}
677
678
/**
679
 * gnutls_x509_name_constraints_add_excluded:
680
 * @nc: The nameconstraints
681
 * @type: The type of the constraints
682
 * @name: The data of the constraints
683
 *
684
 * This function will add a name constraint to the list of excluded
685
 * constraints. The constraints @type can be any of the following types:
686
 * %GNUTLS_SAN_DNSNAME, %GNUTLS_SAN_RFC822NAME, %GNUTLS_SAN_DN,
687
 * %GNUTLS_SAN_URI, %GNUTLS_SAN_IPADDRESS. For the latter, an IP address
688
 * in network byte order is expected, followed by its network mask (which is
689
 * 4 bytes in IPv4 or 16-bytes in IPv6).
690
 *
691
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
692
 *
693
 * Since: 3.3.0
694
 **/
695
int gnutls_x509_name_constraints_add_excluded(gnutls_x509_name_constraints_t nc,
696
                gnutls_x509_subject_alt_name_t
697
                type, const gnutls_datum_t * name)
698
0
{
699
0
  return name_constraints_add(nc, type, name, 0);
700
0
}
701
702
/**
703
 * gnutls_x509_crt_set_name_constraints:
704
 * @crt: The certificate
705
 * @nc: The nameconstraints structure
706
 * @critical: whether this extension will be critical
707
 *
708
 * This function will set the provided name constraints to
709
 * the certificate extension list. This extension is always
710
 * marked as critical.
711
 *
712
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
713
 *
714
 * Since: 3.3.0
715
 **/
716
int gnutls_x509_crt_set_name_constraints(gnutls_x509_crt_t crt,
717
           gnutls_x509_name_constraints_t nc,
718
           unsigned int critical)
719
0
{
720
0
  int ret;
721
0
  gnutls_datum_t der;
722
723
0
  ret = gnutls_x509_ext_export_name_constraints(nc, &der);
724
0
  if (ret < 0)
725
0
    return gnutls_assert_val(ret);
726
727
0
  ret = _gnutls_x509_crt_set_extension(crt, "2.5.29.30", &der, critical);
728
0
  if (ret < 0) {
729
0
    gnutls_assert();
730
0
    goto cleanup;
731
0
  }
732
733
0
  ret = 0;
734
0
  crt->use_extensions = 1;
735
736
0
 cleanup:
737
0
  _gnutls_free_datum(&der);
738
0
  return ret;
739
0
}
740
741
static
742
unsigned ends_with(const gnutls_datum_t * str, const gnutls_datum_t * suffix)
743
0
{
744
0
  unsigned char *tree;
745
0
  unsigned int treelen;
746
747
0
  if (suffix->size >= str->size)
748
0
    return 0;
749
750
0
  tree = suffix->data;
751
0
  treelen = suffix->size;
752
0
  if ((treelen > 0) && (tree[0] == '.')) {
753
0
    tree++;
754
0
    treelen--;
755
0
  }
756
757
0
  if (memcmp(str->data + str->size - treelen, tree, treelen) == 0 &&
758
0
      str->data[str->size - treelen - 1] == '.')
759
0
    return 1; /* match */
760
761
0
  return 0;
762
0
}
763
764
static
765
unsigned email_ends_with(const gnutls_datum_t * str,
766
       const gnutls_datum_t * suffix)
767
0
{
768
0
  if (suffix->size >= str->size)
769
0
    return 0;
770
771
0
  if (suffix->size > 1 && suffix->data[0] == '.') {
772
    /* .domain.com */
773
0
    if (memcmp
774
0
        (str->data + str->size - suffix->size, suffix->data,
775
0
         suffix->size) == 0)
776
0
      return 1; /* match */
777
0
  } else {
778
0
    if (memcmp
779
0
        (str->data + str->size - suffix->size, suffix->data,
780
0
         suffix->size) == 0
781
0
        && str->data[str->size - suffix->size - 1] == '@')
782
0
      return 1; /* match */
783
0
  }
784
785
0
  return 0;
786
0
}
787
788
static unsigned dnsname_matches(const gnutls_datum_t * name,
789
        const gnutls_datum_t * suffix)
790
0
{
791
0
  _gnutls_hard_log("matching %.*s with DNS constraint %.*s\n", name->size,
792
0
       name->data, suffix->size, suffix->data);
793
794
0
  if (suffix->size == name->size
795
0
      && memcmp(suffix->data, name->data, suffix->size) == 0)
796
0
    return 1; /* match */
797
798
0
  return ends_with(name, suffix);
799
0
}
800
801
static unsigned email_matches(const gnutls_datum_t * name,
802
            const gnutls_datum_t * suffix)
803
0
{
804
0
  _gnutls_hard_log("matching %.*s with e-mail constraint %.*s\n",
805
0
       name->size, name->data, suffix->size, suffix->data);
806
807
0
  if (suffix->size == name->size
808
0
      && memcmp(suffix->data, name->data, suffix->size) == 0)
809
0
    return 1; /* match */
810
811
0
  return email_ends_with(name, suffix);
812
0
}
813
814
/*-
815
 * name_constraints_intersect_nodes:
816
 * @nc1: name constraints node 1
817
 * @nc2: name constraints node 2
818
 * @_intersection: newly allocated node with intersected constraints,
819
 *     NULL if the intersection is empty
820
 *
821
 * Inspect 2 name constraints nodes (of possibly different types) and allocate
822
 * a new node with intersection of given constraints.
823
 *
824
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value.
825
 -*/
826
static int
827
name_constraints_intersect_nodes(name_constraints_node_st * nc1,
828
         name_constraints_node_st * nc2,
829
         name_constraints_node_st ** _intersection)
830
0
{
831
  // presume empty intersection
832
0
  name_constraints_node_st *intersection = NULL;
833
0
  name_constraints_node_st *to_copy = NULL;
834
0
  unsigned iplength = 0;
835
0
  unsigned byte;
836
837
0
  *_intersection = NULL;
838
839
0
  if (nc1->type != nc2->type) {
840
0
    return GNUTLS_E_SUCCESS;
841
0
  }
842
0
  switch (nc1->type) {
843
0
  case GNUTLS_SAN_DNSNAME:
844
0
    if (!dnsname_matches(&nc2->name, &nc1->name))
845
0
      return GNUTLS_E_SUCCESS;
846
0
    to_copy = nc2;
847
0
    break;
848
0
  case GNUTLS_SAN_RFC822NAME:
849
0
    if (!email_matches(&nc2->name, &nc1->name))
850
0
      return GNUTLS_E_SUCCESS;
851
0
    to_copy = nc2;
852
0
    break;
853
0
  case GNUTLS_SAN_IPADDRESS:
854
0
    if (nc1->name.size != nc2->name.size)
855
0
      return GNUTLS_E_SUCCESS;
856
0
    iplength = nc1->name.size / 2;
857
0
    for (byte = 0; byte < iplength; byte++) {
858
0
      if (((nc1->name.data[byte] ^ nc2->name.data[byte])  // XOR of addresses
859
0
           & nc1->name.data[byte + iplength]  // AND mask from nc1
860
0
           & nc2->name.data[byte + iplength]) // AND mask from nc2
861
0
          != 0) {
862
        // CIDRS do not intersect
863
0
        return GNUTLS_E_SUCCESS;
864
0
      }
865
0
    }
866
0
    to_copy = nc2;
867
0
    break;
868
0
  default:
869
    // for other types, we don't know how to do the intersection, assume empty
870
0
    return GNUTLS_E_SUCCESS;
871
0
  }
872
873
  // copy existing node if applicable
874
0
  if (to_copy != NULL) {
875
0
    *_intersection =
876
0
        name_constraints_node_new(to_copy->type, to_copy->name.data,
877
0
                to_copy->name.size);
878
0
    if (*_intersection == NULL)
879
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
880
0
    intersection = *_intersection;
881
882
0
    assert(intersection->name.data != NULL);
883
884
0
    if (intersection->type == GNUTLS_SAN_IPADDRESS) {
885
      // make sure both IP addresses are correctly masked
886
0
      _gnutls_mask_ip(intersection->name.data,
887
0
          intersection->name.data + iplength,
888
0
          iplength);
889
0
      _gnutls_mask_ip(nc1->name.data,
890
0
          nc1->name.data + iplength, iplength);
891
      // update intersection, if necessary (we already know one is subset of other)
892
0
      for (byte = 0; byte < 2 * iplength; byte++) {
893
0
        intersection->name.data[byte] |=
894
0
            nc1->name.data[byte];
895
0
      }
896
0
    }
897
0
  }
898
899
0
  return GNUTLS_E_SUCCESS;
900
0
}
901
902
/*
903
 * Returns: true if the certification is acceptable, and false otherwise.
904
 */
905
static
906
unsigned check_unsupported_constraint(gnutls_x509_name_constraints_t nc,
907
              gnutls_x509_subject_alt_name_t type)
908
0
{
909
0
  unsigned i;
910
0
  int ret;
911
0
  unsigned rtype;
912
0
  gnutls_datum_t rname;
913
914
  /* check if there is a restrictions with that type, if
915
   * yes, then reject the name.
916
   */
917
0
  i = 0;
918
0
  do {
919
0
    ret =
920
0
        gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
921
0
                    &rname);
922
0
    if (ret >= 0) {
923
0
      if (rtype != type)
924
0
        continue;
925
0
      else
926
0
        return gnutls_assert_val(0);
927
0
    }
928
929
0
  } while (ret == 0);
930
931
0
  return 1;
932
0
}
933
934
static
935
unsigned check_dns_constraints(gnutls_x509_name_constraints_t nc,
936
             const gnutls_datum_t * name)
937
0
{
938
0
  unsigned i;
939
0
  int ret;
940
0
  unsigned rtype;
941
0
  unsigned allowed_found = 0;
942
0
  gnutls_datum_t rname;
943
944
  /* check restrictions */
945
0
  i = 0;
946
0
  do {
947
0
    ret =
948
0
        gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
949
0
                    &rname);
950
0
    if (ret >= 0) {
951
0
      if (rtype != GNUTLS_SAN_DNSNAME)
952
0
        continue;
953
954
      /* a name of value 0 means that the CA shouldn't have issued
955
       * a certificate with a DNSNAME. */
956
0
      if (rname.size == 0)
957
0
        return gnutls_assert_val(0);
958
959
0
      if (dnsname_matches(name, &rname) != 0)
960
0
        return gnutls_assert_val(0);  /* rejected */
961
0
    }
962
0
  } while (ret == 0);
963
964
  /* check allowed */
965
0
  i = 0;
966
0
  do {
967
0
    ret =
968
0
        gnutls_x509_name_constraints_get_permitted(nc, i++, &rtype,
969
0
                     &rname);
970
0
    if (ret >= 0) {
971
0
      if (rtype != GNUTLS_SAN_DNSNAME)
972
0
        continue;
973
974
0
      if (rname.size == 0)
975
0
        continue;
976
977
0
      allowed_found = 1;
978
979
0
      if (dnsname_matches(name, &rname) != 0)
980
0
        return 1; /* accepted */
981
0
    }
982
0
  } while (ret == 0);
983
984
0
  if (allowed_found != 0) /* there are allowed directives but this host wasn't found */
985
0
    return gnutls_assert_val(0);
986
987
0
  return 1;
988
0
}
989
990
static
991
unsigned check_email_constraints(gnutls_x509_name_constraints_t nc,
992
         const gnutls_datum_t * name)
993
0
{
994
0
  unsigned i;
995
0
  int ret;
996
0
  unsigned rtype;
997
0
  unsigned allowed_found = 0;
998
0
  gnutls_datum_t rname;
999
1000
  /* check restrictions */
1001
0
  i = 0;
1002
0
  do {
1003
0
    ret =
1004
0
        gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
1005
0
                    &rname);
1006
0
    if (ret >= 0) {
1007
0
      if (rtype != GNUTLS_SAN_RFC822NAME)
1008
0
        continue;
1009
1010
      /* a name of value 0 means that the CA shouldn't have issued
1011
       * a certificate with an e-mail. */
1012
0
      if (rname.size == 0)
1013
0
        return gnutls_assert_val(0);
1014
1015
0
      if (email_matches(name, &rname) != 0)
1016
0
        return gnutls_assert_val(0);  /* rejected */
1017
0
    }
1018
0
  } while (ret == 0);
1019
1020
  /* check allowed */
1021
0
  i = 0;
1022
0
  do {
1023
0
    ret =
1024
0
        gnutls_x509_name_constraints_get_permitted(nc, i++, &rtype,
1025
0
                     &rname);
1026
0
    if (ret >= 0) {
1027
0
      if (rtype != GNUTLS_SAN_RFC822NAME)
1028
0
        continue;
1029
1030
0
      if (rname.size == 0)
1031
0
        continue;
1032
1033
0
      allowed_found = 1;
1034
1035
0
      if (email_matches(name, &rname) != 0)
1036
0
        return 1; /* accepted */
1037
0
    }
1038
0
  } while (ret == 0);
1039
1040
0
  if (allowed_found != 0) /* there are allowed directives but this host wasn't found */
1041
0
    return gnutls_assert_val(0);
1042
1043
0
  return 1;
1044
0
}
1045
1046
static
1047
unsigned check_ip_constraints(gnutls_x509_name_constraints_t nc,
1048
            const gnutls_datum_t * name)
1049
0
{
1050
0
  unsigned i;
1051
0
  int ret;
1052
0
  unsigned rtype;
1053
0
  unsigned allowed_found = 0;
1054
0
  gnutls_datum_t rname;
1055
1056
  /* check restrictions */
1057
0
  i = 0;
1058
0
  do {
1059
0
    ret =
1060
0
        gnutls_x509_name_constraints_get_excluded(nc, i++, &rtype,
1061
0
                    &rname);
1062
0
    if (ret >= 0) {
1063
0
      if (rtype != GNUTLS_SAN_IPADDRESS)
1064
0
        continue;
1065
1066
      /* do not check IPv4 against IPv6 constraints and vice versa */
1067
0
      if (name->size != rname.size / 2)
1068
0
        continue;
1069
1070
0
      if (ip_in_cidr(name, &rname) != 0)
1071
0
        return gnutls_assert_val(0);  /* rejected */
1072
0
    }
1073
0
  } while (ret == 0);
1074
1075
  /* check allowed */
1076
0
  i = 0;
1077
0
  do {
1078
0
    ret =
1079
0
        gnutls_x509_name_constraints_get_permitted(nc, i++, &rtype,
1080
0
                     &rname);
1081
0
    if (ret >= 0) {
1082
0
      if (rtype != GNUTLS_SAN_IPADDRESS)
1083
0
        continue;
1084
1085
      /* do not check IPv4 against IPv6 constraints and vice versa */
1086
0
      if (name->size != rname.size / 2)
1087
0
        continue;
1088
1089
0
      allowed_found = 1;
1090
1091
0
      if (ip_in_cidr(name, &rname) != 0)
1092
0
        return 1; /* accepted */
1093
0
    }
1094
0
  } while (ret == 0);
1095
1096
0
  if (allowed_found != 0) /* there are allowed directives but this host wasn't found */
1097
0
    return gnutls_assert_val(0);
1098
1099
0
  return 1;
1100
0
}
1101
1102
/**
1103
 * gnutls_x509_name_constraints_check:
1104
 * @nc: the extracted name constraints
1105
 * @type: the type of the constraint to check (of type gnutls_x509_subject_alt_name_t)
1106
 * @name: the name to be checked
1107
 *
1108
 * This function will check the provided name against the constraints in
1109
 * @nc using the RFC5280 rules. Currently this function is limited to DNS
1110
 * names, emails and IP addresses (of type %GNUTLS_SAN_DNSNAME,
1111
 * %GNUTLS_SAN_RFC822NAME and %GNUTLS_SAN_IPADDRESS).
1112
 *
1113
 * Returns: zero if the provided name is not acceptable, and non-zero otherwise.
1114
 *
1115
 * Since: 3.3.0
1116
 **/
1117
unsigned gnutls_x509_name_constraints_check(gnutls_x509_name_constraints_t nc,
1118
              gnutls_x509_subject_alt_name_t type,
1119
              const gnutls_datum_t * name)
1120
0
{
1121
0
  if (type == GNUTLS_SAN_DNSNAME)
1122
0
    return check_dns_constraints(nc, name);
1123
1124
0
  if (type == GNUTLS_SAN_RFC822NAME)
1125
0
    return check_email_constraints(nc, name);
1126
1127
0
  if (type == GNUTLS_SAN_IPADDRESS)
1128
0
    return check_ip_constraints(nc, name);
1129
1130
0
  return check_unsupported_constraint(nc, type);
1131
0
}
1132
1133
/* This function checks for unsupported constraints, that we also
1134
 * know their structure. That is it will fail only if the constraint
1135
 * is present in the CA, _and_ the name in the end certificate contains
1136
 * the constrained element.
1137
 *
1138
 * Returns: true if the certification is acceptable, and false otherwise
1139
 */
1140
static unsigned check_unsupported_constraint2(gnutls_x509_crt_t cert,
1141
                gnutls_x509_name_constraints_t nc,
1142
                gnutls_x509_subject_alt_name_t
1143
                type)
1144
0
{
1145
0
  unsigned idx, found_one;
1146
0
  char name[MAX_CN];
1147
0
  size_t name_size;
1148
0
  unsigned san_type;
1149
0
  int ret;
1150
1151
0
  found_one = 0;
1152
1153
0
  for (idx = 0;; idx++) {
1154
0
    name_size = sizeof(name);
1155
0
    ret = gnutls_x509_crt_get_subject_alt_name2(cert,
1156
0
                  idx, name,
1157
0
                  &name_size,
1158
0
                  &san_type, NULL);
1159
0
    if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1160
0
      break;
1161
0
    else if (ret < 0)
1162
0
      return gnutls_assert_val(0);
1163
1164
0
    if (san_type != GNUTLS_SAN_URI)
1165
0
      continue;
1166
1167
0
    found_one = 1;
1168
0
    break;
1169
0
  }
1170
1171
0
  if (found_one != 0)
1172
0
    return check_unsupported_constraint(nc, type);
1173
1174
  /* no name was found in the certificate, so accept */
1175
0
  return 1;
1176
0
}
1177
1178
/**
1179
 * gnutls_x509_name_constraints_check_crt:
1180
 * @nc: the extracted name constraints
1181
 * @type: the type of the constraint to check (of type gnutls_x509_subject_alt_name_t)
1182
 * @cert: the certificate to be checked
1183
 *
1184
 * This function will check the provided certificate names against the constraints in
1185
 * @nc using the RFC5280 rules. It will traverse all the certificate's names and
1186
 * alternative names.
1187
 *
1188
 * Currently this function is limited to DNS
1189
 * names and emails (of type %GNUTLS_SAN_DNSNAME and %GNUTLS_SAN_RFC822NAME).
1190
 *
1191
 * Returns: zero if the provided name is not acceptable, and non-zero otherwise.
1192
 *
1193
 * Since: 3.3.0
1194
 **/
1195
unsigned gnutls_x509_name_constraints_check_crt(gnutls_x509_name_constraints_t
1196
            nc,
1197
            gnutls_x509_subject_alt_name_t
1198
            type, gnutls_x509_crt_t cert)
1199
0
{
1200
0
  char name[MAX_CN];
1201
0
  size_t name_size;
1202
0
  int ret;
1203
0
  unsigned idx, t, san_type;
1204
0
  gnutls_datum_t n;
1205
0
  unsigned found_one;
1206
1207
0
  if (is_nc_empty(nc, type) != 0)
1208
0
    return 1; /* shortcut; no constraints to check */
1209
1210
0
  if (type == GNUTLS_SAN_RFC822NAME) {
1211
0
    found_one = 0;
1212
0
    for (idx = 0;; idx++) {
1213
0
      name_size = sizeof(name);
1214
0
      ret = gnutls_x509_crt_get_subject_alt_name2(cert,
1215
0
                    idx, name,
1216
0
                    &name_size,
1217
0
                    &san_type,
1218
0
                    NULL);
1219
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1220
0
        break;
1221
0
      else if (ret < 0)
1222
0
        return gnutls_assert_val(0);
1223
1224
0
      if (san_type != GNUTLS_SAN_RFC822NAME)
1225
0
        continue;
1226
1227
0
      found_one = 1;
1228
0
      n.data = (void *)name;
1229
0
      n.size = name_size;
1230
0
      t = gnutls_x509_name_constraints_check(nc,
1231
0
                     GNUTLS_SAN_RFC822NAME,
1232
0
                     &n);
1233
0
      if (t == 0)
1234
0
        return gnutls_assert_val(t);
1235
0
    }
1236
1237
    /* there is at least a single e-mail. That means that the EMAIL field will
1238
     * not be used for verifying the identity of the holder. */
1239
0
    if (found_one != 0)
1240
0
      return 1;
1241
1242
0
    do {
1243
      /* ensure there is only a single EMAIL, similarly to CN handling (rfc6125) */
1244
0
      name_size = sizeof(name);
1245
0
      ret =
1246
0
          gnutls_x509_crt_get_dn_by_oid(cert,
1247
0
                GNUTLS_OID_PKCS9_EMAIL,
1248
0
                1, 0, name,
1249
0
                &name_size);
1250
0
      if (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1251
0
        return gnutls_assert_val(0);
1252
1253
0
      name_size = sizeof(name);
1254
0
      ret =
1255
0
          gnutls_x509_crt_get_dn_by_oid(cert,
1256
0
                GNUTLS_OID_PKCS9_EMAIL,
1257
0
                0, 0, name,
1258
0
                &name_size);
1259
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1260
0
        break;
1261
0
      else if (ret < 0)
1262
0
        return gnutls_assert_val(0);
1263
1264
0
      found_one = 1;
1265
0
      n.data = (void *)name;
1266
0
      n.size = name_size;
1267
0
      t = gnutls_x509_name_constraints_check(nc,
1268
0
                     GNUTLS_SAN_RFC822NAME,
1269
0
                     &n);
1270
0
      if (t == 0)
1271
0
        return gnutls_assert_val(t);
1272
0
    } while (0);
1273
1274
    /* passed */
1275
0
    if (found_one != 0)
1276
0
      return 1;
1277
0
    else {
1278
      /* no name was found. According to RFC5280: 
1279
       * If no name of the type is in the certificate, the certificate is acceptable.
1280
       */
1281
0
      return gnutls_assert_val(1);
1282
0
    }
1283
0
  } else if (type == GNUTLS_SAN_DNSNAME) {
1284
0
    found_one = 0;
1285
0
    for (idx = 0;; idx++) {
1286
0
      name_size = sizeof(name);
1287
0
      ret = gnutls_x509_crt_get_subject_alt_name2(cert,
1288
0
                    idx, name,
1289
0
                    &name_size,
1290
0
                    &san_type,
1291
0
                    NULL);
1292
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1293
0
        break;
1294
0
      else if (ret < 0)
1295
0
        return gnutls_assert_val(0);
1296
1297
0
      if (san_type != GNUTLS_SAN_DNSNAME)
1298
0
        continue;
1299
1300
0
      found_one = 1;
1301
0
      n.data = (void *)name;
1302
0
      n.size = name_size;
1303
0
      t = gnutls_x509_name_constraints_check(nc,
1304
0
                     GNUTLS_SAN_DNSNAME,
1305
0
                     &n);
1306
0
      if (t == 0)
1307
0
        return gnutls_assert_val(t);
1308
0
    }
1309
1310
    /* there is at least a single DNS name. That means that the CN will
1311
     * not be used for verifying the identity of the holder. */
1312
0
    if (found_one != 0)
1313
0
      return 1;
1314
1315
    /* verify the name constraints against the CN, if the certificate is
1316
     * not a CA. We do this check only on certificates marked as WWW server,
1317
     * because that's where the CN check is only performed. */
1318
0
    if (_gnutls_check_key_purpose(cert, GNUTLS_KP_TLS_WWW_SERVER, 0)
1319
0
        != 0)
1320
0
      do {
1321
        /* ensure there is only a single CN, according to rfc6125 */
1322
0
        name_size = sizeof(name);
1323
0
        ret =
1324
0
            gnutls_x509_crt_get_dn_by_oid(cert,
1325
0
                  GNUTLS_OID_X520_COMMON_NAME,
1326
0
                  1, 0, name,
1327
0
                  &name_size);
1328
0
        if (ret !=
1329
0
            GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1330
0
          return gnutls_assert_val(0);
1331
1332
0
        name_size = sizeof(name);
1333
0
        ret =
1334
0
            gnutls_x509_crt_get_dn_by_oid(cert,
1335
0
                  GNUTLS_OID_X520_COMMON_NAME,
1336
0
                  0, 0, name,
1337
0
                  &name_size);
1338
0
        if (ret ==
1339
0
            GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1340
0
          break;
1341
0
        else if (ret < 0)
1342
0
          return gnutls_assert_val(0);
1343
1344
0
        found_one = 1;
1345
0
        n.data = (void *)name;
1346
0
        n.size = name_size;
1347
0
        t = gnutls_x509_name_constraints_check(nc,
1348
0
                       GNUTLS_SAN_DNSNAME,
1349
0
                       &n);
1350
0
        if (t == 0)
1351
0
          return gnutls_assert_val(t);
1352
0
      } while (0);
1353
1354
    /* passed */
1355
0
    if (found_one != 0)
1356
0
      return 1;
1357
0
    else {
1358
      /* no name was found. According to RFC5280: 
1359
       * If no name of the type is in the certificate, the certificate is acceptable.
1360
       */
1361
0
      return gnutls_assert_val(1);
1362
0
    }
1363
0
  } else if (type == GNUTLS_SAN_IPADDRESS) {
1364
0
    found_one = 0;
1365
0
    for (idx = 0;; idx++) {
1366
0
      name_size = sizeof(name);
1367
0
      ret = gnutls_x509_crt_get_subject_alt_name2(cert,
1368
0
                    idx, name,
1369
0
                    &name_size,
1370
0
                    &san_type,
1371
0
                    NULL);
1372
0
      if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE)
1373
0
        break;
1374
0
      else if (ret < 0)
1375
0
        return gnutls_assert_val(0);
1376
1377
0
      if (san_type != GNUTLS_SAN_IPADDRESS)
1378
0
        continue;
1379
1380
0
      found_one = 1;
1381
0
      n.data = (void *)name;
1382
0
      n.size = name_size;
1383
0
      t = gnutls_x509_name_constraints_check(nc,
1384
0
                     GNUTLS_SAN_IPADDRESS,
1385
0
                     &n);
1386
0
      if (t == 0)
1387
0
        return gnutls_assert_val(t);
1388
0
    }
1389
1390
    /* there is at least a single IP address. */
1391
1392
0
    if (found_one != 0) {
1393
0
      return 1;
1394
0
    } else {
1395
      /* no name was found. According to RFC5280:
1396
       * If no name of the type is in the certificate, the certificate is acceptable.
1397
       */
1398
0
      return gnutls_assert_val(1);
1399
0
    }
1400
0
  } else if (type == GNUTLS_SAN_URI) {
1401
0
    return check_unsupported_constraint2(cert, nc, type);
1402
0
  } else
1403
0
    return check_unsupported_constraint(nc, type);
1404
0
}
1405
1406
/**
1407
 * gnutls_x509_name_constraints_get_permitted:
1408
 * @nc: the extracted name constraints
1409
 * @idx: the index of the constraint
1410
 * @type: the type of the constraint (of type gnutls_x509_subject_alt_name_t)
1411
 * @name: the name in the constraint (of the specific type)
1412
 *
1413
 * This function will return an intermediate type containing
1414
 * the name constraints of the provided CA certificate. That
1415
 * structure can be used in combination with gnutls_x509_name_constraints_check()
1416
 * to verify whether a server's name is in accordance with the constraints.
1417
 *
1418
 * The name should be treated as constant and valid for the lifetime of @nc.
1419
 *
1420
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1421
 * if the extension is not present, otherwise a negative error value.
1422
 *
1423
 * Since: 3.3.0
1424
 **/
1425
int gnutls_x509_name_constraints_get_permitted(gnutls_x509_name_constraints_t
1426
                 nc, unsigned idx, unsigned *type,
1427
                 gnutls_datum_t * name)
1428
0
{
1429
0
  unsigned int i;
1430
0
  struct name_constraints_node_st *tmp = nc->permitted;
1431
1432
0
  for (i = 0; i < idx; i++) {
1433
0
    if (tmp == NULL)
1434
0
      return
1435
0
          gnutls_assert_val
1436
0
          (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1437
1438
0
    tmp = tmp->next;
1439
0
  }
1440
1441
0
  if (tmp == NULL)
1442
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1443
1444
0
  *type = tmp->type;
1445
0
  *name = tmp->name;
1446
1447
0
  return 0;
1448
0
}
1449
1450
/**
1451
 * gnutls_x509_name_constraints_get_excluded:
1452
 * @nc: the extracted name constraints
1453
 * @idx: the index of the constraint
1454
 * @type: the type of the constraint (of type gnutls_x509_subject_alt_name_t)
1455
 * @name: the name in the constraint (of the specific type)
1456
 *
1457
 * This function will return an intermediate type containing
1458
 * the name constraints of the provided CA certificate. That
1459
 * structure can be used in combination with gnutls_x509_name_constraints_check()
1460
 * to verify whether a server's name is in accordance with the constraints.
1461
 *
1462
 * The name should be treated as constant and valid for the lifetime of @nc.
1463
 *
1464
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE
1465
 * if the extension is not present, otherwise a negative error value.
1466
 *
1467
 * Since: 3.3.0
1468
 **/
1469
int gnutls_x509_name_constraints_get_excluded(gnutls_x509_name_constraints_t nc,
1470
                unsigned idx,
1471
                unsigned *type,
1472
                gnutls_datum_t * name)
1473
0
{
1474
0
  unsigned int i;
1475
0
  struct name_constraints_node_st *tmp = nc->excluded;
1476
1477
0
  for (i = 0; i < idx; i++) {
1478
0
    if (tmp == NULL)
1479
0
      return
1480
0
          gnutls_assert_val
1481
0
          (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1482
1483
0
    tmp = tmp->next;
1484
0
  }
1485
1486
0
  if (tmp == NULL)
1487
0
    return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE);
1488
1489
0
  *type = tmp->type;
1490
0
  *name = tmp->name;
1491
1492
0
  return 0;
1493
0
}