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