diff options
-rw-r--r-- | meta/recipes-support/gnutls/gnutls/CVE-2024-12243.patch | 1160 | ||||
-rw-r--r-- | meta/recipes-support/gnutls/gnutls_3.7.4.bb | 1 |
2 files changed, 1161 insertions, 0 deletions
diff --git a/meta/recipes-support/gnutls/gnutls/CVE-2024-12243.patch b/meta/recipes-support/gnutls/gnutls/CVE-2024-12243.patch new file mode 100644 index 0000000000..c0ff21fd25 --- /dev/null +++ b/meta/recipes-support/gnutls/gnutls/CVE-2024-12243.patch | |||
@@ -0,0 +1,1160 @@ | |||
1 | From 4760bc63531e3f5039e70ede91a20e1194410892 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daiki Ueno <ueno@gnu.org> | ||
3 | Date: Mon, 18 Nov 2024 17:23:46 +0900 | ||
4 | Subject: [PATCH] x509: optimize name constraints processing | ||
5 | |||
6 | This switches the representation name constraints from linked lists to | ||
7 | array lists to optimize the lookup performance from O(n) to O(1), also | ||
8 | enforces a limit of name constraint checks against subject alternative | ||
9 | names. | ||
10 | |||
11 | Signed-off-by: Daiki Ueno <ueno@gnu.org> | ||
12 | |||
13 | CVE: CVE-2024-12243 | ||
14 | |||
15 | Upstream-Status: Backport [https://gitlab.com/gnutls/gnutls/-/commit/4760bc63531e3f5039e70ede91a20e1194410892] | ||
16 | |||
17 | Signed-off-by: Archana Polampalli <archana.polampalli@windriver.com> | ||
18 | --- | ||
19 | lib/datum.c | 7 +- | ||
20 | lib/x509/name_constraints.c | 594 +++++++++++++++++++++--------------- | ||
21 | lib/x509/x509_ext.c | 87 +++--- | ||
22 | lib/x509/x509_ext_int.h | 5 + | ||
23 | lib/x509/x509_int.h | 24 +- | ||
24 | 5 files changed, 405 insertions(+), 312 deletions(-) | ||
25 | |||
26 | diff --git a/lib/datum.c b/lib/datum.c | ||
27 | index bd0f216..b0e8d11 100644 | ||
28 | --- a/lib/datum.c | ||
29 | +++ b/lib/datum.c | ||
30 | @@ -29,6 +29,7 @@ | ||
31 | #include <num.h> | ||
32 | #include <datum.h> | ||
33 | #include "errors.h" | ||
34 | +#include "intprops.h" | ||
35 | |||
36 | /* On error, @dat is not changed. */ | ||
37 | int | ||
38 | @@ -61,7 +62,11 @@ _gnutls_set_strdatum(gnutls_datum_t * dat, const void *data, size_t data_size) | ||
39 | if (data == NULL) | ||
40 | return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); | ||
41 | |||
42 | - unsigned char *m = gnutls_malloc(data_size + 1); | ||
43 | + size_t capacity; | ||
44 | + if (!INT_ADD_OK(data_size, 1, &capacity)) | ||
45 | + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
46 | + | ||
47 | + unsigned char *m = gnutls_malloc(capacity); | ||
48 | if (!m) | ||
49 | return GNUTLS_E_MEMORY_ERROR; | ||
50 | |||
51 | diff --git a/lib/x509/name_constraints.c b/lib/x509/name_constraints.c | ||
52 | index 6c1546e..c9eab70 100644 | ||
53 | --- a/lib/x509/name_constraints.c | ||
54 | +++ b/lib/x509/name_constraints.c | ||
55 | @@ -33,49 +33,99 @@ | ||
56 | #include <gnutls/x509-ext.h> | ||
57 | #include <x509_b64.h> | ||
58 | #include <x509_int.h> | ||
59 | +#include "x509_ext_int.h" | ||
60 | #include <libtasn1.h> | ||
61 | |||
62 | #include "ip.h" | ||
63 | #include "ip-in-cidr.h" | ||
64 | |||
65 | +#include "intprops.h" | ||
66 | + | ||
67 | +#define MAX_NC_CHECKS (1 << 20) | ||
68 | + | ||
69 | +struct name_constraints_node_st { | ||
70 | + unsigned type; | ||
71 | + gnutls_datum_t name; | ||
72 | +}; | ||
73 | + | ||
74 | +struct name_constraints_node_list_st { | ||
75 | + struct name_constraints_node_st **data; | ||
76 | + size_t size; | ||
77 | + size_t capacity; | ||
78 | +}; | ||
79 | + | ||
80 | +struct gnutls_name_constraints_st { | ||
81 | + struct name_constraints_node_list_st nodes; /* owns elements */ | ||
82 | + struct name_constraints_node_list_st permitted; /* borrows elements */ | ||
83 | + struct name_constraints_node_list_st excluded; /* borrows elements */ | ||
84 | +}; | ||
85 | + | ||
86 | +static struct name_constraints_node_st * | ||
87 | +name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type, | ||
88 | + unsigned char *data, unsigned int size); | ||
89 | + | ||
90 | +static int name_constraints_node_list_add(struct name_constraints_node_list_st *list, | ||
91 | + struct name_constraints_node_st *node) | ||
92 | +{ | ||
93 | + if (!list->capacity || list->size == list->capacity) { | ||
94 | + size_t new_capacity = list->capacity; | ||
95 | + struct name_constraints_node_st **new_data; | ||
96 | + | ||
97 | + if (!INT_MULTIPLY_OK(new_capacity, 2, &new_capacity) || | ||
98 | + !INT_ADD_OK(new_capacity, 1, &new_capacity)) | ||
99 | + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); | ||
100 | + new_data = _gnutls_reallocarray( | ||
101 | + list->data, new_capacity, | ||
102 | + sizeof(struct name_constraints_node_st *)); | ||
103 | + if (!new_data) | ||
104 | + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
105 | + list->capacity = new_capacity; | ||
106 | + list->data = new_data; | ||
107 | + } | ||
108 | + list->data[list->size++] = node; | ||
109 | + return 0; | ||
110 | +} | ||
111 | + | ||
112 | // for documentation see the implementation | ||
113 | -static int name_constraints_intersect_nodes(name_constraints_node_st * nc1, | ||
114 | - name_constraints_node_st * nc2, | ||
115 | - name_constraints_node_st ** intersection); | ||
116 | +static int name_constraints_intersect_nodes( | ||
117 | + gnutls_x509_name_constraints_t nc, | ||
118 | + const struct name_constraints_node_st *node1, | ||
119 | + const struct name_constraints_node_st *node2, | ||
120 | + struct name_constraints_node_st **intersection); | ||
121 | |||
122 | /*- | ||
123 | - * is_nc_empty: | ||
124 | + * _gnutls_x509_name_constraints_is_empty: | ||
125 | * @nc: name constraints structure | ||
126 | - * @type: type (gnutls_x509_subject_alt_name_t) | ||
127 | + * @type: type (gnutls_x509_subject_alt_name_t or 0) | ||
128 | * | ||
129 | * Test whether given name constraints structure has any constraints (permitted | ||
130 | * or excluded) of a given type. @nc must be allocated (not NULL) before the call. | ||
131 | + * If @type is 0, type checking will be skipped. | ||
132 | * | ||
133 | - * Returns: 0 if @nc contains constraints of type @type, 1 otherwise | ||
134 | + * Returns: false if @nc contains constraints of type @type, true otherwise | ||
135 | -*/ | ||
136 | -static unsigned is_nc_empty(struct gnutls_name_constraints_st* nc, unsigned type) | ||
137 | +bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc, | ||
138 | + unsigned type) | ||
139 | { | ||
140 | - name_constraints_node_st *t; | ||
141 | + if (nc->permitted.size == 0 && nc->excluded.size == 0) | ||
142 | + return true; | ||
143 | |||
144 | - if (nc->permitted == NULL && nc->excluded == NULL) | ||
145 | - return 1; | ||
146 | + if (type == 0) | ||
147 | + return false; | ||
148 | |||
149 | - t = nc->permitted; | ||
150 | - while (t != NULL) { | ||
151 | - if (t->type == type) | ||
152 | - return 0; | ||
153 | - t = t->next; | ||
154 | + for (size_t i = 0; i < nc->permitted.size; i++) { | ||
155 | + if (nc->permitted.data[i]->type == type) | ||
156 | + return false; | ||
157 | } | ||
158 | |||
159 | - t = nc->excluded; | ||
160 | - while (t != NULL) { | ||
161 | - if (t->type == type) | ||
162 | - return 0; | ||
163 | - t = t->next; | ||
164 | + for (size_t i = 0; i < nc->excluded.size; i++) { | ||
165 | + if (nc->excluded.data[i]->type == type) | ||
166 | + return false; | ||
167 | + | ||
168 | } | ||
169 | |||
170 | /* no constraint for that type exists */ | ||
171 | - return 1; | ||
172 | + return true; | ||
173 | } | ||
174 | |||
175 | /*- | ||
176 | @@ -111,21 +161,16 @@ static int validate_name_constraints_node(gnutls_x509_subject_alt_name_t type, | ||
177 | return GNUTLS_E_SUCCESS; | ||
178 | } | ||
179 | |||
180 | -int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, | ||
181 | - name_constraints_node_st ** _nc) | ||
182 | +static int extract_name_constraints(gnutls_x509_name_constraints_t nc, | ||
183 | + asn1_node c2, const char *vstr, | ||
184 | + struct name_constraints_node_list_st *nodes) | ||
185 | { | ||
186 | int ret; | ||
187 | char tmpstr[128]; | ||
188 | unsigned indx; | ||
189 | gnutls_datum_t tmp = { NULL, 0 }; | ||
190 | unsigned int type; | ||
191 | - struct name_constraints_node_st *nc, *prev; | ||
192 | - | ||
193 | - prev = *_nc; | ||
194 | - if (prev != NULL) { | ||
195 | - while(prev->next != NULL) | ||
196 | - prev = prev->next; | ||
197 | - } | ||
198 | + struct name_constraints_node_st *node; | ||
199 | |||
200 | for (indx=1;;indx++) { | ||
201 | snprintf(tmpstr, sizeof(tmpstr), "%s.?%u.base", vstr, indx); | ||
202 | @@ -144,25 +189,19 @@ int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, | ||
203 | goto cleanup; | ||
204 | } | ||
205 | |||
206 | - nc = gnutls_malloc(sizeof(struct name_constraints_node_st)); | ||
207 | - if (nc == NULL) { | ||
208 | + node = name_constraints_node_new(nc, type, tmp.data, tmp.size); | ||
209 | + _gnutls_free_datum(&tmp); | ||
210 | + if (node == NULL) { | ||
211 | gnutls_assert(); | ||
212 | ret = GNUTLS_E_MEMORY_ERROR; | ||
213 | goto cleanup; | ||
214 | } | ||
215 | |||
216 | - memcpy(&nc->name, &tmp, sizeof(gnutls_datum_t)); | ||
217 | - nc->type = type; | ||
218 | - nc->next = NULL; | ||
219 | - | ||
220 | - if (prev == NULL) { | ||
221 | - *_nc = prev = nc; | ||
222 | - } else { | ||
223 | - prev->next = nc; | ||
224 | - prev = nc; | ||
225 | + ret = name_constraints_node_list_add(nodes, node); | ||
226 | + if (ret < 0) { | ||
227 | + gnutls_assert(); | ||
228 | + goto cleanup; | ||
229 | } | ||
230 | - | ||
231 | - tmp.data = NULL; | ||
232 | } | ||
233 | |||
234 | assert(ret < 0); | ||
235 | @@ -177,84 +216,102 @@ int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | +int _gnutls_x509_name_constraints_extract(asn1_node c2, | ||
240 | + const char *permitted_name, | ||
241 | + const char *excluded_name, | ||
242 | + gnutls_x509_name_constraints_t nc) | ||
243 | +{ | ||
244 | + int ret; | ||
245 | + | ||
246 | + ret = extract_name_constraints(nc, c2, permitted_name, &nc->permitted); | ||
247 | + if (ret < 0) | ||
248 | + return gnutls_assert_val(ret); | ||
249 | + ret = extract_name_constraints(nc, c2, excluded_name, &nc->excluded); | ||
250 | + if (ret < 0) | ||
251 | + return gnutls_assert_val(ret); | ||
252 | + | ||
253 | + return ret; | ||
254 | +} | ||
255 | + | ||
256 | /*- | ||
257 | - * _gnutls_name_constraints_node_free: | ||
258 | + * name_constraints_node_free: | ||
259 | * @node: name constraints node | ||
260 | * | ||
261 | - * Deallocate a list of name constraints nodes starting at the given node. | ||
262 | + * Deallocate a name constraints node. | ||
263 | -*/ | ||
264 | -void _gnutls_name_constraints_node_free(name_constraints_node_st *node) | ||
265 | +static void name_constraints_node_free(struct name_constraints_node_st *node) | ||
266 | { | ||
267 | - name_constraints_node_st *next, *t; | ||
268 | - | ||
269 | - t = node; | ||
270 | - while (t != NULL) { | ||
271 | - next = t->next; | ||
272 | - gnutls_free(t->name.data); | ||
273 | - gnutls_free(t); | ||
274 | - t = next; | ||
275 | + if (node) { | ||
276 | + gnutls_free(node->name.data); | ||
277 | + gnutls_free(node); | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /*- | ||
282 | * name_constraints_node_new: | ||
283 | * @type: name constraints type to set (gnutls_x509_subject_alt_name_t) | ||
284 | + * @nc: a %gnutls_x509_name_constraints_t | ||
285 | * @data: name.data to set or NULL | ||
286 | * @size: name.size to set | ||
287 | * | ||
288 | * Allocate a new name constraints node and set its type, name size and name data. | ||
289 | - * If @data is set to NULL, name data will be an array of \x00 (the length of @size). | ||
290 | - * The .next pointer is set to NULL. | ||
291 | * | ||
292 | * Returns: Pointer to newly allocated node or NULL in case of memory error. | ||
293 | -*/ | ||
294 | -static name_constraints_node_st* name_constraints_node_new(unsigned type, | ||
295 | - unsigned char *data, | ||
296 | - unsigned int size) | ||
297 | +static struct name_constraints_node_st * | ||
298 | +name_constraints_node_new(gnutls_x509_name_constraints_t nc, unsigned type, | ||
299 | + unsigned char *data, unsigned int size) | ||
300 | { | ||
301 | - name_constraints_node_st *tmp = gnutls_malloc(sizeof(struct name_constraints_node_st)); | ||
302 | + struct name_constraints_node_st *tmp; | ||
303 | + int ret; | ||
304 | + | ||
305 | + tmp = gnutls_calloc(1, sizeof(struct name_constraints_node_st)); | ||
306 | if (tmp == NULL) | ||
307 | return NULL; | ||
308 | tmp->type = type; | ||
309 | - tmp->next = NULL; | ||
310 | - tmp->name.size = size; | ||
311 | - tmp->name.data = NULL; | ||
312 | - if (tmp->name.size > 0) { | ||
313 | - | ||
314 | - tmp->name.data = gnutls_malloc(tmp->name.size); | ||
315 | - if (tmp->name.data == NULL) { | ||
316 | + if (data) { | ||
317 | + ret = _gnutls_set_strdatum(&tmp->name, data, size); | ||
318 | + if (ret < 0) { | ||
319 | + gnutls_assert(); | ||
320 | gnutls_free(tmp); | ||
321 | return NULL; | ||
322 | } | ||
323 | - if (data != NULL) { | ||
324 | - memcpy(tmp->name.data, data, size); | ||
325 | - } else { | ||
326 | - memset(tmp->name.data, 0, size); | ||
327 | - } | ||
328 | } | ||
329 | + ret = name_constraints_node_list_add(&nc->nodes, tmp); | ||
330 | + if (ret < 0) { | ||
331 | + gnutls_assert(); | ||
332 | + name_constraints_node_free(tmp); | ||
333 | + return NULL; | ||
334 | + } | ||
335 | + | ||
336 | return tmp; | ||
337 | } | ||
338 | |||
339 | /*- | ||
340 | - * @brief _gnutls_name_constraints_intersect: | ||
341 | - * @_nc: first name constraints list (permitted) | ||
342 | - * @_nc2: name constraints list to merge with (permitted) | ||
343 | - * @_nc_excluded: Corresponding excluded name constraints list | ||
344 | + * @brief name_constraints_node_list_intersect: | ||
345 | + * @nc: %gnutls_x509_name_constraints_t | ||
346 | + * @permitted: first name constraints list (permitted) | ||
347 | + * @permitted2: name constraints list to merge with (permitted) | ||
348 | + * @excluded: Corresponding excluded name constraints list | ||
349 | * | ||
350 | - * This function finds the intersection of @_nc and @_nc2. The result is placed in @_nc, | ||
351 | - * the original @_nc is deallocated. @_nc2 is not changed. If necessary, a universal | ||
352 | + * This function finds the intersection of @permitted and @permitted2. The result is placed in @permitted, | ||
353 | + * the original @permitted is modified. @permitted2 is not changed. If necessary, a universal | ||
354 | * excluded name constraint node of the right type is added to the list provided | ||
355 | - * in @_nc_excluded. | ||
356 | + * in @excluded. | ||
357 | * | ||
358 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value. | ||
359 | -*/ | ||
360 | -static | ||
361 | -int _gnutls_name_constraints_intersect(name_constraints_node_st ** _nc, | ||
362 | - name_constraints_node_st * _nc2, | ||
363 | - name_constraints_node_st ** _nc_excluded) | ||
364 | +static int name_constraints_node_list_intersect( | ||
365 | + gnutls_x509_name_constraints_t nc, | ||
366 | + struct name_constraints_node_list_st *permitted, | ||
367 | + const struct name_constraints_node_list_st *permitted2, | ||
368 | + struct name_constraints_node_list_st *excluded) | ||
369 | { | ||
370 | - name_constraints_node_st *nc, *nc2, *t, *tmp, *dest = NULL, *prev = NULL; | ||
371 | + struct name_constraints_node_st *tmp; | ||
372 | int ret, type, used; | ||
373 | + struct name_constraints_node_list_st removed = { .data = NULL, | ||
374 | + .size = 0, | ||
375 | + .capacity = 0 }; | ||
376 | |||
377 | /* temporary array to see, if we need to add universal excluded constraints | ||
378 | * (see phase 3 for details) | ||
379 | @@ -262,61 +319,73 @@ int _gnutls_name_constraints_intersect(name_constraints_node_st ** _nc, | ||
380 | unsigned char types_with_empty_intersection[GNUTLS_SAN_MAX]; | ||
381 | memset(types_with_empty_intersection, 0, sizeof(types_with_empty_intersection)); | ||
382 | |||
383 | - if (*_nc == NULL || _nc2 == NULL) | ||
384 | + if (permitted->size == 0 || permitted2->size == 0) | ||
385 | return 0; | ||
386 | |||
387 | /* Phase 1 | ||
388 | - * For each name in _NC, if a _NC2 does not contain a name | ||
389 | - * with the same type, preserve the original name. | ||
390 | - * Do this also for node of unknown type (not DNS, email, IP */ | ||
391 | - t = nc = *_nc; | ||
392 | - while (t != NULL) { | ||
393 | - name_constraints_node_st *next = t->next; | ||
394 | - nc2 = _nc2; | ||
395 | - while (nc2 != NULL) { | ||
396 | - if (t->type == nc2->type) { | ||
397 | + * For each name in PERMITTED, if a PERMITTED2 does not contain a name | ||
398 | + * with the same type, move the original name to REMOVED. | ||
399 | + * Do this also for node of unknown type (not DNS, email, IP) */ | ||
400 | + for (size_t i = 0; i < permitted->size;) { | ||
401 | + struct name_constraints_node_st *t = permitted->data[i]; | ||
402 | + const struct name_constraints_node_st *found = NULL; | ||
403 | + | ||
404 | + for (size_t j = 0; j < permitted2->size; j++) { | ||
405 | + const struct name_constraints_node_st *t2 = | ||
406 | + permitted2->data[j]; | ||
407 | + if (t->type == t2->type) { | ||
408 | // check bounds (we will use 't->type' as index) | ||
409 | - if (t->type > GNUTLS_SAN_MAX || t->type == 0) | ||
410 | - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); | ||
411 | + if (t->type > GNUTLS_SAN_MAX || t->type == 0) { | ||
412 | + gnutls_assert(); | ||
413 | + ret = GNUTLS_E_INTERNAL_ERROR; | ||
414 | + goto cleanup; | ||
415 | + } | ||
416 | // note the possibility of empty intersection for this type | ||
417 | // if we add something to the intersection in phase 2, | ||
418 | // we will reset this flag back to 0 then | ||
419 | types_with_empty_intersection[t->type - 1] = 1; | ||
420 | + found = t2; | ||
421 | break; | ||
422 | } | ||
423 | - nc2 = nc2->next; | ||
424 | } | ||
425 | - if (nc2 == NULL || | ||
426 | - (t->type != GNUTLS_SAN_DNSNAME && | ||
427 | - t->type != GNUTLS_SAN_RFC822NAME && | ||
428 | - t->type != GNUTLS_SAN_IPADDRESS) | ||
429 | - ) { | ||
430 | - /* move node from NC to DEST */ | ||
431 | - if (prev != NULL) | ||
432 | - prev->next = next; | ||
433 | - else | ||
434 | - prev = nc = next; | ||
435 | - t->next = dest; | ||
436 | - dest = t; | ||
437 | - } else { | ||
438 | - prev = t; | ||
439 | + if (found != NULL && (t->type == GNUTLS_SAN_DNSNAME || | ||
440 | + t->type == GNUTLS_SAN_RFC822NAME || | ||
441 | + t->type == GNUTLS_SAN_IPADDRESS)) { | ||
442 | + /* move node from PERMITTED to REMOVED */ | ||
443 | + ret = name_constraints_node_list_add(&removed, t); | ||
444 | + if (ret < 0) { | ||
445 | + gnutls_assert(); | ||
446 | + goto cleanup; | ||
447 | + } | ||
448 | + /* remove node by swapping */ | ||
449 | + if (i < permitted->size - 1) | ||
450 | + permitted->data[i] = | ||
451 | + permitted->data[permitted->size - 1]; | ||
452 | + permitted->size--; | ||
453 | + continue; | ||
454 | + | ||
455 | } | ||
456 | - t = next; | ||
457 | + i++; | ||
458 | } | ||
459 | |||
460 | /* Phase 2 | ||
461 | - * iterate through all combinations from nc2 and nc1 | ||
462 | + * iterate through all combinations from PERMITTED2 and PERMITTED | ||
463 | * and create intersections of nodes with same type */ | ||
464 | - nc2 = _nc2; | ||
465 | - while (nc2 != NULL) { | ||
466 | - // current nc2 node has not yet been used for any intersection | ||
467 | - // (and is not in DEST either) | ||
468 | + for (size_t i = 0; i < permitted2->size; i++) { | ||
469 | + const struct name_constraints_node_st *t2 = permitted2->data[i]; | ||
470 | + | ||
471 | + // current PERMITTED2 node has not yet been used for any intersection | ||
472 | + // (and is not in REMOVED either) | ||
473 | used = 0; | ||
474 | - t = nc; | ||
475 | - while (t != NULL) { | ||
476 | + for (size_t j = 0; j < removed.size; j++) { | ||
477 | + const struct name_constraints_node_st *t = | ||
478 | + removed.data[j]; | ||
479 | // save intersection of name constraints into tmp | ||
480 | - ret = name_constraints_intersect_nodes(t, nc2, &tmp); | ||
481 | - if (ret < 0) return gnutls_assert_val(ret); | ||
482 | + ret = name_constraints_intersect_nodes(nc, t, t2, &tmp); | ||
483 | + if (ret < 0) { | ||
484 | + gnutls_assert(); | ||
485 | + goto cleanup; | ||
486 | + } | ||
487 | used = 1; | ||
488 | // if intersection is not empty | ||
489 | if (tmp != NULL) { // intersection for this type is not empty | ||
490 | @@ -327,31 +396,35 @@ int _gnutls_name_constraints_intersect(name_constraints_node_st ** _nc, | ||
491 | } | ||
492 | // we will not add universal excluded constraint for this type | ||
493 | types_with_empty_intersection[tmp->type - 1] = 0; | ||
494 | - // add intersection node to DEST | ||
495 | - tmp->next = dest; | ||
496 | - dest = tmp; | ||
497 | + // add intersection node to PERMITTED | ||
498 | + ret = name_constraints_node_list_add(permitted, | ||
499 | + tmp); | ||
500 | + if (ret < 0) { | ||
501 | + gnutls_assert(); | ||
502 | + goto cleanup; | ||
503 | + } | ||
504 | + | ||
505 | } | ||
506 | - t = t->next; | ||
507 | } | ||
508 | - // if the node from nc2 was not used for intersection, copy it to DEST | ||
509 | + // if the node from PERMITTED2 was not used for intersection, copy it to DEST | ||
510 | // Beware: also copies nodes other than DNS, email, IP, | ||
511 | // since their counterpart may have been moved in phase 1. | ||
512 | if (!used) { | ||
513 | - tmp = name_constraints_node_new(nc2->type, nc2->name.data, nc2->name.size); | ||
514 | + tmp = name_constraints_node_new(nc, t2->type, t2->name.data, t2->name.size); | ||
515 | if (tmp == NULL) { | ||
516 | - _gnutls_name_constraints_node_free(dest); | ||
517 | - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
518 | + gnutls_assert(); | ||
519 | + ret = GNUTLS_E_MEMORY_ERROR; | ||
520 | + goto cleanup; | ||
521 | + } | ||
522 | + ret = name_constraints_node_list_add(permitted, tmp); | ||
523 | + if (ret < 0) { | ||
524 | + gnutls_assert(); | ||
525 | + goto cleanup; | ||
526 | + | ||
527 | } | ||
528 | - tmp->next = dest; | ||
529 | - dest = tmp; | ||
530 | } | ||
531 | - nc2 = nc2->next; | ||
532 | } | ||
533 | |||
534 | - /* replace the original with the new */ | ||
535 | - _gnutls_name_constraints_node_free(nc); | ||
536 | - *_nc = dest; | ||
537 | - | ||
538 | /* Phase 3 | ||
539 | * For each type: If we have empty permitted name constraints now | ||
540 | * and we didn't have at the beginning, we have to add a new | ||
541 | @@ -364,60 +437,79 @@ int _gnutls_name_constraints_intersect(name_constraints_node_st ** _nc, | ||
542 | switch (type) { | ||
543 | case GNUTLS_SAN_IPADDRESS: | ||
544 | // add universal restricted range for IPv4 | ||
545 | - tmp = name_constraints_node_new(GNUTLS_SAN_IPADDRESS, NULL, 8); | ||
546 | + tmp = name_constraints_node_new( | ||
547 | + nc, GNUTLS_SAN_IPADDRESS, NULL, 8); | ||
548 | if (tmp == NULL) { | ||
549 | - _gnutls_name_constraints_node_free(dest); | ||
550 | - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
551 | + gnutls_assert(); | ||
552 | + ret = GNUTLS_E_MEMORY_ERROR; | ||
553 | + goto cleanup; | ||
554 | + } | ||
555 | + ret = name_constraints_node_list_add(excluded, tmp); | ||
556 | + if (ret < 0) { | ||
557 | + gnutls_assert(); | ||
558 | + goto cleanup; | ||
559 | + | ||
560 | } | ||
561 | - tmp->next = *_nc_excluded; | ||
562 | - *_nc_excluded = tmp; | ||
563 | // add universal restricted range for IPv6 | ||
564 | - tmp = name_constraints_node_new(GNUTLS_SAN_IPADDRESS, NULL, 32); | ||
565 | + tmp = name_constraints_node_new( | ||
566 | + nc, GNUTLS_SAN_IPADDRESS, NULL, 32); | ||
567 | if (tmp == NULL) { | ||
568 | - _gnutls_name_constraints_node_free(dest); | ||
569 | - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
570 | + gnutls_assert(); | ||
571 | + ret = GNUTLS_E_MEMORY_ERROR; | ||
572 | + goto cleanup; | ||
573 | + } | ||
574 | + ret = name_constraints_node_list_add(excluded, tmp); | ||
575 | + if (ret < 0) { | ||
576 | + gnutls_assert(); | ||
577 | + goto cleanup; | ||
578 | } | ||
579 | - tmp->next = *_nc_excluded; | ||
580 | - *_nc_excluded = tmp; | ||
581 | break; | ||
582 | case GNUTLS_SAN_DNSNAME: | ||
583 | case GNUTLS_SAN_RFC822NAME: | ||
584 | - tmp = name_constraints_node_new(type, NULL, 0); | ||
585 | + tmp = name_constraints_node_new(nc, type, NULL, 0); | ||
586 | if (tmp == NULL) { | ||
587 | - _gnutls_name_constraints_node_free(dest); | ||
588 | - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
589 | + gnutls_assert(); | ||
590 | + ret = GNUTLS_E_MEMORY_ERROR; | ||
591 | + goto cleanup; | ||
592 | + } | ||
593 | + ret = name_constraints_node_list_add(excluded, tmp); | ||
594 | + if (ret < 0) { | ||
595 | + gnutls_assert(); | ||
596 | + goto cleanup; | ||
597 | } | ||
598 | - tmp->next = *_nc_excluded; | ||
599 | - *_nc_excluded = tmp; | ||
600 | break; | ||
601 | default: // do nothing, at least one node was already moved in phase 1 | ||
602 | break; | ||
603 | } | ||
604 | } | ||
605 | - return GNUTLS_E_SUCCESS; | ||
606 | -} | ||
607 | - | ||
608 | -static int _gnutls_name_constraints_append(name_constraints_node_st **_nc, | ||
609 | - name_constraints_node_st *_nc2) | ||
610 | -{ | ||
611 | - name_constraints_node_st *nc, *nc2; | ||
612 | - struct name_constraints_node_st *tmp; | ||
613 | + ret = GNUTLS_E_SUCCESS; | ||
614 | |||
615 | - if (_nc2 == NULL) | ||
616 | - return 0; | ||
617 | +cleanup: | ||
618 | + gnutls_free(removed.data); | ||
619 | + return ret; | ||
620 | |||
621 | - nc2 = _nc2; | ||
622 | - while (nc2) { | ||
623 | - nc = *_nc; | ||
624 | +} | ||
625 | |||
626 | - tmp = name_constraints_node_new(nc2->type, nc2->name.data, nc2->name.size); | ||
627 | - if (tmp == NULL) | ||
628 | +static int name_constraints_node_list_concat( | ||
629 | + gnutls_x509_name_constraints_t nc, | ||
630 | + struct name_constraints_node_list_st *nodes, | ||
631 | + const struct name_constraints_node_list_st *nodes2) | ||
632 | +{ | ||
633 | + for (size_t i = 0; i < nodes2->size; i++) { | ||
634 | + const struct name_constraints_node_st *node = nodes2->data[i]; | ||
635 | + struct name_constraints_node_st *tmp; | ||
636 | + int ret; | ||
637 | + | ||
638 | + tmp = name_constraints_node_new(nc, node->type, node->name.data, | ||
639 | + node->name.size); | ||
640 | + if (tmp == NULL) { | ||
641 | return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
642 | - | ||
643 | - tmp->next = nc; | ||
644 | - *_nc = tmp; | ||
645 | - | ||
646 | - nc2 = nc2->next; | ||
647 | + } | ||
648 | + ret = name_constraints_node_list_add(nodes, tmp); | ||
649 | + if (ret < 0) { | ||
650 | + name_constraints_node_free(tmp); | ||
651 | + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
652 | + } | ||
653 | } | ||
654 | |||
655 | return 0; | ||
656 | @@ -487,6 +579,25 @@ int gnutls_x509_crt_get_name_constraints(gnutls_x509_crt_t crt, | ||
657 | |||
658 | } | ||
659 | |||
660 | +void _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc) | ||
661 | +{ | ||
662 | + for (size_t i = 0; i < nc->nodes.size; i++) { | ||
663 | + struct name_constraints_node_st *node = nc->nodes.data[i]; | ||
664 | + name_constraints_node_free(node); | ||
665 | + } | ||
666 | + gnutls_free(nc->nodes.data); | ||
667 | + nc->nodes.capacity = 0; | ||
668 | + nc->nodes.size = 0; | ||
669 | + | ||
670 | + gnutls_free(nc->permitted.data); | ||
671 | + nc->permitted.capacity = 0; | ||
672 | + nc->permitted.size = 0; | ||
673 | + | ||
674 | + gnutls_free(nc->excluded.data); | ||
675 | + nc->excluded.capacity = 0; | ||
676 | + nc->excluded.size = 0; | ||
677 | +} | ||
678 | + | ||
679 | /** | ||
680 | * gnutls_x509_name_constraints_deinit: | ||
681 | * @nc: The nameconstraints | ||
682 | @@ -497,10 +608,9 @@ int gnutls_x509_crt_get_name_constraints(gnutls_x509_crt_t crt, | ||
683 | **/ | ||
684 | void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc) | ||
685 | { | ||
686 | - _gnutls_name_constraints_node_free(nc->permitted); | ||
687 | - _gnutls_name_constraints_node_free(nc->excluded); | ||
688 | - | ||
689 | + _gnutls_x509_name_constraints_clear(nc); | ||
690 | gnutls_free(nc); | ||
691 | + | ||
692 | } | ||
693 | |||
694 | /** | ||
695 | @@ -515,12 +625,15 @@ void gnutls_x509_name_constraints_deinit(gnutls_x509_name_constraints_t nc) | ||
696 | **/ | ||
697 | int gnutls_x509_name_constraints_init(gnutls_x509_name_constraints_t *nc) | ||
698 | { | ||
699 | - *nc = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st)); | ||
700 | - if (*nc == NULL) { | ||
701 | + struct gnutls_name_constraints_st *tmp; | ||
702 | + | ||
703 | + tmp = gnutls_calloc(1, sizeof(struct gnutls_name_constraints_st)); | ||
704 | + if (tmp == NULL) { | ||
705 | gnutls_assert(); | ||
706 | return GNUTLS_E_MEMORY_ERROR; | ||
707 | } | ||
708 | |||
709 | + *nc = tmp; | ||
710 | return 0; | ||
711 | } | ||
712 | |||
713 | @@ -530,37 +643,23 @@ int name_constraints_add(gnutls_x509_name_constraints_t nc, | ||
714 | const gnutls_datum_t * name, | ||
715 | unsigned permitted) | ||
716 | { | ||
717 | - struct name_constraints_node_st * tmp, *prev = NULL; | ||
718 | + struct name_constraints_node_st *tmp; | ||
719 | + struct name_constraints_node_list_st *nodes; | ||
720 | int ret; | ||
721 | |||
722 | ret = validate_name_constraints_node(type, name); | ||
723 | if (ret < 0) | ||
724 | return gnutls_assert_val(ret); | ||
725 | |||
726 | - if (permitted != 0) | ||
727 | - prev = tmp = nc->permitted; | ||
728 | - else | ||
729 | - prev = tmp = nc->excluded; | ||
730 | + nodes = permitted ? &nc->permitted : &nc->excluded; | ||
731 | |||
732 | - while(tmp != NULL) { | ||
733 | - tmp = tmp->next; | ||
734 | - if (tmp != NULL) | ||
735 | - prev = tmp; | ||
736 | + tmp = name_constraints_node_new(nc, type, name->data, name->size); | ||
737 | + ret = name_constraints_node_list_add(nodes, tmp); | ||
738 | + if (ret < 0) { | ||
739 | + name_constraints_node_free(tmp); | ||
740 | + return gnutls_assert_val(ret); | ||
741 | } | ||
742 | |||
743 | - tmp = name_constraints_node_new(type, name->data, name->size); | ||
744 | - if (tmp == NULL) | ||
745 | - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
746 | - tmp->next = NULL; | ||
747 | - | ||
748 | - if (prev == NULL) { | ||
749 | - if (permitted != 0) | ||
750 | - nc->permitted = tmp; | ||
751 | - else | ||
752 | - nc->excluded = tmp; | ||
753 | - } else | ||
754 | - prev->next = tmp; | ||
755 | - | ||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | @@ -585,17 +684,15 @@ int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc, | ||
760 | { | ||
761 | int ret; | ||
762 | |||
763 | - ret = | ||
764 | - _gnutls_name_constraints_intersect(&nc->permitted, | ||
765 | - nc2->permitted, &nc->excluded); | ||
766 | + ret = name_constraints_node_list_intersect( | ||
767 | + nc, &nc->permitted, &nc2->permitted, &nc->excluded); | ||
768 | if (ret < 0) { | ||
769 | gnutls_assert(); | ||
770 | return ret; | ||
771 | } | ||
772 | |||
773 | - ret = | ||
774 | - _gnutls_name_constraints_append(&nc->excluded, | ||
775 | - nc2->excluded); | ||
776 | + ret = name_constraints_node_list_concat(nc, &nc->excluded, | ||
777 | + &nc2->excluded); | ||
778 | if (ret < 0) { | ||
779 | gnutls_assert(); | ||
780 | return ret; | ||
781 | @@ -767,47 +864,50 @@ static unsigned email_matches(const gnutls_datum_t *name, const gnutls_datum_t * | ||
782 | * | ||
783 | * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a negative error value. | ||
784 | -*/ | ||
785 | -static int | ||
786 | -name_constraints_intersect_nodes(name_constraints_node_st * nc1, | ||
787 | - name_constraints_node_st * nc2, | ||
788 | - name_constraints_node_st ** _intersection) | ||
789 | +static int name_constraints_intersect_nodes( | ||
790 | + gnutls_x509_name_constraints_t nc, | ||
791 | + const struct name_constraints_node_st *node1, | ||
792 | + const struct name_constraints_node_st *node2, | ||
793 | + struct name_constraints_node_st **_intersection) | ||
794 | { | ||
795 | // presume empty intersection | ||
796 | - name_constraints_node_st *intersection = NULL; | ||
797 | - name_constraints_node_st *to_copy = NULL; | ||
798 | + struct name_constraints_node_st *intersection = NULL; | ||
799 | + const struct name_constraints_node_st *to_copy = NULL; | ||
800 | unsigned iplength = 0; | ||
801 | unsigned byte; | ||
802 | |||
803 | *_intersection = NULL; | ||
804 | |||
805 | - if (nc1->type != nc2->type) { | ||
806 | + if (node1->type != node2->type) { | ||
807 | return GNUTLS_E_SUCCESS; | ||
808 | } | ||
809 | - switch (nc1->type) { | ||
810 | + switch (node1->type) { | ||
811 | case GNUTLS_SAN_DNSNAME: | ||
812 | - if (!dnsname_matches(&nc2->name, &nc1->name)) | ||
813 | + if (!dnsname_matches(&node2->name, &node1->name)) | ||
814 | return GNUTLS_E_SUCCESS; | ||
815 | - to_copy = nc2; | ||
816 | break; | ||
817 | case GNUTLS_SAN_RFC822NAME: | ||
818 | - if (!email_matches(&nc2->name, &nc1->name)) | ||
819 | + if (!email_matches(&node2->name, &node1->name)) | ||
820 | return GNUTLS_E_SUCCESS; | ||
821 | - to_copy = nc2; | ||
822 | + to_copy = node2; | ||
823 | break; | ||
824 | case GNUTLS_SAN_IPADDRESS: | ||
825 | - if (nc1->name.size != nc2->name.size) | ||
826 | + if (node1->name.size != node2->name.size) | ||
827 | return GNUTLS_E_SUCCESS; | ||
828 | - iplength = nc1->name.size/2; | ||
829 | + iplength = node1->name.size / 2; | ||
830 | for (byte = 0; byte < iplength; byte++) { | ||
831 | - if (((nc1->name.data[byte]^nc2->name.data[byte]) // XOR of addresses | ||
832 | - & nc1->name.data[byte+iplength] // AND mask from nc1 | ||
833 | - & nc2->name.data[byte+iplength]) // AND mask from nc2 | ||
834 | + if (((node1->name.data[byte] ^ | ||
835 | + node2->name.data[byte]) // XOR of addresses | ||
836 | + & node1->name.data[byte + | ||
837 | + iplength] // AND mask from nc1 | ||
838 | + & node2->name.data[byte + | ||
839 | + iplength]) // AND mask from nc2 | ||
840 | != 0) { | ||
841 | // CIDRS do not intersect | ||
842 | return GNUTLS_E_SUCCESS; | ||
843 | } | ||
844 | } | ||
845 | - to_copy = nc2; | ||
846 | + to_copy = node2; | ||
847 | break; | ||
848 | default: | ||
849 | // for other types, we don't know how to do the intersection, assume empty | ||
850 | @@ -816,7 +916,9 @@ name_constraints_intersect_nodes(name_constraints_node_st * nc1, | ||
851 | |||
852 | // copy existing node if applicable | ||
853 | if (to_copy != NULL) { | ||
854 | - *_intersection = name_constraints_node_new(to_copy->type, to_copy->name.data, to_copy->name.size); | ||
855 | + *_intersection = name_constraints_node_new(nc, to_copy->type, | ||
856 | + to_copy->name.data, | ||
857 | + to_copy->name.size); | ||
858 | if (*_intersection == NULL) | ||
859 | return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); | ||
860 | intersection = *_intersection; | ||
861 | @@ -826,10 +928,11 @@ name_constraints_intersect_nodes(name_constraints_node_st * nc1, | ||
862 | if (intersection->type == GNUTLS_SAN_IPADDRESS) { | ||
863 | // make sure both IP addresses are correctly masked | ||
864 | _gnutls_mask_ip(intersection->name.data, intersection->name.data+iplength, iplength); | ||
865 | - _gnutls_mask_ip(nc1->name.data, nc1->name.data+iplength, iplength); | ||
866 | + _gnutls_mask_ip(node1->name.data, | ||
867 | + node1->name.data + iplength, iplength); | ||
868 | // update intersection, if necessary (we already know one is subset of other) | ||
869 | for (byte = 0; byte < 2 * iplength; byte++) { | ||
870 | - intersection->name.data[byte] |= nc1->name.data[byte]; | ||
871 | + intersection->name.data[byte] |= node1->name.data[byte]; | ||
872 | } | ||
873 | } | ||
874 | } | ||
875 | @@ -1123,10 +1226,16 @@ int ret; | ||
876 | unsigned idx, t, san_type; | ||
877 | gnutls_datum_t n; | ||
878 | unsigned found_one; | ||
879 | +size_t checks; | ||
880 | |||
881 | - if (is_nc_empty(nc, type) != 0) | ||
882 | + if (_gnutls_x509_name_constraints_is_empty(nc, type) != 0) | ||
883 | return 1; /* shortcut; no constraints to check */ | ||
884 | |||
885 | + if (!INT_ADD_OK(nc->permitted.size, nc->excluded.size, &checks) || | ||
886 | + !INT_MULTIPLY_OK(checks, cert->san->size, &checks) || | ||
887 | + checks > MAX_NC_CHECKS) { | ||
888 | + return gnutls_assert_val(0); | ||
889 | + } | ||
890 | if (type == GNUTLS_SAN_RFC822NAME) { | ||
891 | found_one = 0; | ||
892 | for (idx=0;;idx++) { | ||
893 | @@ -1315,21 +1424,13 @@ int gnutls_x509_name_constraints_get_permitted(gnutls_x509_name_constraints_t nc | ||
894 | unsigned idx, | ||
895 | unsigned *type, gnutls_datum_t * name) | ||
896 | { | ||
897 | - unsigned int i; | ||
898 | - struct name_constraints_node_st * tmp = nc->permitted; | ||
899 | + const struct name_constraints_node_st *tmp; | ||
900 | |||
901 | - for (i = 0; i < idx; i++) { | ||
902 | - if (tmp == NULL) | ||
903 | - return | ||
904 | - gnutls_assert_val | ||
905 | - (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); | ||
906 | - | ||
907 | - tmp = tmp->next; | ||
908 | - } | ||
909 | - | ||
910 | - if (tmp == NULL) | ||
911 | + if (idx >= nc->permitted.size) | ||
912 | return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); | ||
913 | |||
914 | + tmp = nc->permitted.data[idx]; | ||
915 | + | ||
916 | *type = tmp->type; | ||
917 | *name = tmp->name; | ||
918 | |||
919 | @@ -1359,21 +1460,12 @@ int gnutls_x509_name_constraints_get_excluded(gnutls_x509_name_constraints_t nc, | ||
920 | unsigned idx, | ||
921 | unsigned *type, gnutls_datum_t * name) | ||
922 | { | ||
923 | - unsigned int i; | ||
924 | - struct name_constraints_node_st * tmp = nc->excluded; | ||
925 | - | ||
926 | - for (i = 0; i < idx; i++) { | ||
927 | - if (tmp == NULL) | ||
928 | - return | ||
929 | - gnutls_assert_val | ||
930 | - (GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); | ||
931 | - | ||
932 | - tmp = tmp->next; | ||
933 | - } | ||
934 | - | ||
935 | - if (tmp == NULL) | ||
936 | + const struct name_constraints_node_st *tmp; | ||
937 | + if (idx >= nc->excluded.size) | ||
938 | return gnutls_assert_val(GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); | ||
939 | |||
940 | + tmp = nc->excluded.data[idx]; | ||
941 | + | ||
942 | *type = tmp->type; | ||
943 | *name = tmp->name; | ||
944 | |||
945 | diff --git a/lib/x509/x509_ext.c b/lib/x509/x509_ext.c | ||
946 | index 8bcf183..54741c8 100644 | ||
947 | --- a/lib/x509/x509_ext.c | ||
948 | +++ b/lib/x509/x509_ext.c | ||
949 | @@ -34,10 +34,6 @@ | ||
950 | #include "intprops.h" | ||
951 | |||
952 | #define MAX_ENTRIES 64 | ||
953 | -struct gnutls_subject_alt_names_st { | ||
954 | - struct name_st *names; | ||
955 | - unsigned int size; | ||
956 | -}; | ||
957 | |||
958 | /** | ||
959 | * gnutls_subject_alt_names_init: | ||
960 | @@ -389,24 +385,15 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext, | ||
961 | } | ||
962 | |||
963 | if (flags & GNUTLS_NAME_CONSTRAINTS_FLAG_APPEND && | ||
964 | - (nc->permitted != NULL || nc->excluded != NULL)) { | ||
965 | + !_gnutls_x509_name_constraints_is_empty(nc, 0)) { | ||
966 | ret = gnutls_x509_name_constraints_init (&nc2); | ||
967 | if (ret < 0) { | ||
968 | gnutls_assert(); | ||
969 | goto cleanup; | ||
970 | } | ||
971 | |||
972 | - ret = | ||
973 | - _gnutls_extract_name_constraints(c2, "permittedSubtrees", | ||
974 | - &nc2->permitted); | ||
975 | - if (ret < 0) { | ||
976 | - gnutls_assert(); | ||
977 | - goto cleanup; | ||
978 | - } | ||
979 | - | ||
980 | - ret = | ||
981 | - _gnutls_extract_name_constraints(c2, "excludedSubtrees", | ||
982 | - &nc2->excluded); | ||
983 | + ret = _gnutls_x509_name_constraints_extract( | ||
984 | + c2, "permittedSubtrees", "excludedSubtrees", nc2); | ||
985 | if (ret < 0) { | ||
986 | gnutls_assert(); | ||
987 | goto cleanup; | ||
988 | @@ -418,20 +405,11 @@ int gnutls_x509_ext_import_name_constraints(const gnutls_datum_t * ext, | ||
989 | goto cleanup; | ||
990 | } | ||
991 | } else { | ||
992 | - _gnutls_name_constraints_node_free(nc->permitted); | ||
993 | - _gnutls_name_constraints_node_free(nc->excluded); | ||
994 | |||
995 | - ret = | ||
996 | - _gnutls_extract_name_constraints(c2, "permittedSubtrees", | ||
997 | - &nc->permitted); | ||
998 | - if (ret < 0) { | ||
999 | - gnutls_assert(); | ||
1000 | - goto cleanup; | ||
1001 | - } | ||
1002 | + _gnutls_x509_name_constraints_clear(nc); | ||
1003 | |||
1004 | - ret = | ||
1005 | - _gnutls_extract_name_constraints(c2, "excludedSubtrees", | ||
1006 | - &nc->excluded); | ||
1007 | + ret = _gnutls_x509_name_constraints_extract( | ||
1008 | + c2, "permittedSubtrees", "excludedSubtrees", nc); | ||
1009 | if (ret < 0) { | ||
1010 | gnutls_assert(); | ||
1011 | goto cleanup; | ||
1012 | @@ -467,9 +445,10 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, | ||
1013 | int ret, result; | ||
1014 | uint8_t null = 0; | ||
1015 | asn1_node c2 = NULL; | ||
1016 | - struct name_constraints_node_st *tmp; | ||
1017 | + unsigned rtype; | ||
1018 | + gnutls_datum_t rname; | ||
1019 | |||
1020 | - if (nc->permitted == NULL && nc->excluded == NULL) | ||
1021 | + if (_gnutls_x509_name_constraints_is_empty(nc, 0)) | ||
1022 | return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); | ||
1023 | |||
1024 | result = asn1_create_element | ||
1025 | @@ -479,11 +458,20 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, | ||
1026 | return _gnutls_asn2err(result); | ||
1027 | } | ||
1028 | |||
1029 | - if (nc->permitted == NULL) { | ||
1030 | + ret = gnutls_x509_name_constraints_get_permitted(nc, 0, &rtype, &rname); | ||
1031 | + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { | ||
1032 | (void)asn1_write_value(c2, "permittedSubtrees", NULL, 0); | ||
1033 | } else { | ||
1034 | - tmp = nc->permitted; | ||
1035 | - do { | ||
1036 | + for (unsigned i = 0;; i++) { | ||
1037 | + ret = gnutls_x509_name_constraints_get_permitted( | ||
1038 | + nc, i, &rtype, &rname); | ||
1039 | + if (ret < 0) { | ||
1040 | + if (ret == | ||
1041 | + GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
1042 | + break; | ||
1043 | + gnutls_assert(); | ||
1044 | + goto cleanup; | ||
1045 | + } | ||
1046 | result = | ||
1047 | asn1_write_value(c2, "permittedSubtrees", "NEW", 1); | ||
1048 | if (result != ASN1_SUCCESS) { | ||
1049 | @@ -515,22 +503,30 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, | ||
1050 | ret = | ||
1051 | _gnutls_write_general_name(c2, | ||
1052 | "permittedSubtrees.?LAST.base", | ||
1053 | - tmp->type, | ||
1054 | - tmp->name.data, | ||
1055 | - tmp->name.size); | ||
1056 | + rtype, | ||
1057 | + rname.data, | ||
1058 | + rname.size); | ||
1059 | if (ret < 0) { | ||
1060 | gnutls_assert(); | ||
1061 | goto cleanup; | ||
1062 | } | ||
1063 | - tmp = tmp->next; | ||
1064 | - } while (tmp != NULL); | ||
1065 | + } | ||
1066 | } | ||
1067 | |||
1068 | - if (nc->excluded == NULL) { | ||
1069 | + ret = gnutls_x509_name_constraints_get_excluded(nc, 0, &rtype, &rname); | ||
1070 | + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) { | ||
1071 | (void)asn1_write_value(c2, "excludedSubtrees", NULL, 0); | ||
1072 | } else { | ||
1073 | - tmp = nc->excluded; | ||
1074 | - do { | ||
1075 | + for (unsigned i = 0;; i++) { | ||
1076 | + ret = gnutls_x509_name_constraints_get_excluded( | ||
1077 | + nc, i, &rtype, &rname); | ||
1078 | + if (ret < 0) { | ||
1079 | + if (ret == | ||
1080 | + GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) | ||
1081 | + break; | ||
1082 | + gnutls_assert(); | ||
1083 | + goto cleanup; | ||
1084 | + } | ||
1085 | result = | ||
1086 | asn1_write_value(c2, "excludedSubtrees", "NEW", 1); | ||
1087 | if (result != ASN1_SUCCESS) { | ||
1088 | @@ -562,15 +558,14 @@ int gnutls_x509_ext_export_name_constraints(gnutls_x509_name_constraints_t nc, | ||
1089 | ret = | ||
1090 | _gnutls_write_general_name(c2, | ||
1091 | "excludedSubtrees.?LAST.base", | ||
1092 | - tmp->type, | ||
1093 | - tmp->name.data, | ||
1094 | - tmp->name.size); | ||
1095 | + rtype, | ||
1096 | + rname.data, | ||
1097 | + rname.size); | ||
1098 | if (ret < 0) { | ||
1099 | gnutls_assert(); | ||
1100 | goto cleanup; | ||
1101 | } | ||
1102 | - tmp = tmp->next; | ||
1103 | - } while (tmp != NULL); | ||
1104 | + } | ||
1105 | |||
1106 | } | ||
1107 | |||
1108 | diff --git a/lib/x509/x509_ext_int.h b/lib/x509/x509_ext_int.h | ||
1109 | index 2e3f162..97f0abd 100644 | ||
1110 | --- a/lib/x509/x509_ext_int.h | ||
1111 | +++ b/lib/x509/x509_ext_int.h | ||
1112 | @@ -29,6 +29,11 @@ struct name_st { | ||
1113 | gnutls_datum_t othername_oid; | ||
1114 | }; | ||
1115 | |||
1116 | +struct gnutls_subject_alt_names_st { | ||
1117 | + struct name_st *names; | ||
1118 | + unsigned int size; | ||
1119 | +}; | ||
1120 | + | ||
1121 | int _gnutls_alt_name_process(gnutls_datum_t *out, unsigned type, const gnutls_datum_t *san, unsigned raw); | ||
1122 | |||
1123 | #endif /* GNUTLS_LIB_X509_X509_EXT_INT_H */ | ||
1124 | diff --git a/lib/x509/x509_int.h b/lib/x509/x509_int.h | ||
1125 | index acbc185..bf4363e 100644 | ||
1126 | --- a/lib/x509/x509_int.h | ||
1127 | +++ b/lib/x509/x509_int.h | ||
1128 | @@ -529,20 +529,16 @@ _gnutls_x509_crt_check_revocation(gnutls_x509_crt_t cert, | ||
1129 | int crl_list_length, | ||
1130 | gnutls_verify_output_function func); | ||
1131 | |||
1132 | -typedef struct gnutls_name_constraints_st { | ||
1133 | - struct name_constraints_node_st * permitted; | ||
1134 | - struct name_constraints_node_st * excluded; | ||
1135 | -} gnutls_name_constraints_st; | ||
1136 | - | ||
1137 | -typedef struct name_constraints_node_st { | ||
1138 | - unsigned type; | ||
1139 | - gnutls_datum_t name; | ||
1140 | - struct name_constraints_node_st *next; | ||
1141 | -} name_constraints_node_st; | ||
1142 | - | ||
1143 | -int _gnutls_extract_name_constraints(asn1_node c2, const char *vstr, | ||
1144 | - name_constraints_node_st ** _nc); | ||
1145 | -void _gnutls_name_constraints_node_free (name_constraints_node_st *node); | ||
1146 | + | ||
1147 | + | ||
1148 | +bool _gnutls_x509_name_constraints_is_empty(gnutls_x509_name_constraints_t nc, | ||
1149 | + unsigned type); | ||
1150 | +int _gnutls_x509_name_constraints_extract(asn1_node c2, | ||
1151 | + const char *permitted_name, | ||
1152 | + const char *excluded_name, | ||
1153 | + gnutls_x509_name_constraints_t nc); | ||
1154 | +void _gnutls_x509_name_constraints_clear(gnutls_x509_name_constraints_t nc); | ||
1155 | + | ||
1156 | int _gnutls_x509_name_constraints_merge(gnutls_x509_name_constraints_t nc, | ||
1157 | gnutls_x509_name_constraints_t nc2); | ||
1158 | |||
1159 | -- | ||
1160 | 2.40.0 | ||
diff --git a/meta/recipes-support/gnutls/gnutls_3.7.4.bb b/meta/recipes-support/gnutls/gnutls_3.7.4.bb index 9f502e3f7c..5cd85c5996 100644 --- a/meta/recipes-support/gnutls/gnutls_3.7.4.bb +++ b/meta/recipes-support/gnutls/gnutls_3.7.4.bb | |||
@@ -28,6 +28,7 @@ SRC_URI = "https://www.gnupg.org/ftp/gcrypt/gnutls/v${SHRT_VER}/gnutls-${PV}.tar | |||
28 | file://CVE-2024-0567.patch \ | 28 | file://CVE-2024-0567.patch \ |
29 | file://CVE-2024-28834.patch \ | 29 | file://CVE-2024-28834.patch \ |
30 | file://CVE-2024-28835.patch \ | 30 | file://CVE-2024-28835.patch \ |
31 | file://CVE-2024-12243.patch \ | ||
31 | " | 32 | " |
32 | 33 | ||
33 | SRC_URI[sha256sum] = "e6adbebcfbc95867de01060d93c789938cf89cc1d1f6ef9ef661890f6217451f" | 34 | SRC_URI[sha256sum] = "e6adbebcfbc95867de01060d93c789938cf89cc1d1f6ef9ef661890f6217451f" |