Coverage Report

Created: 2024-06-20 06:28

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