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