Line data Source code
1 : /*
2 : * Copyright (C) 2002-2012 Free Software Foundation, Inc.
3 : * Copyright (C) 2016-2017 Red Hat, Inc.
4 : *
5 : * Author: Nikos Mavrogiannopoulos
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 : #include "gnutls_int.h"
25 : #include "errors.h"
26 : #include <num.h>
27 : #include "str.h"
28 : #include <stdarg.h>
29 : #include <c-ctype.h>
30 : #include <intprops.h>
31 : #include <nettle/base64.h>
32 : #include "extras/hex.h"
33 :
34 : /* These functions are like strcat, strcpy. They only
35 : * do bound checking (they shouldn't cause buffer overruns),
36 : * and they always produce null terminated strings.
37 : *
38 : * They should be used only with null terminated strings.
39 : */
40 1026710 : void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src)
41 : {
42 1026710 : size_t str_size = strlen(src);
43 1026710 : size_t dest_size = strlen(dest);
44 :
45 1026710 : if (dest_tot_size - dest_size > str_size) {
46 1026710 : strcat(dest, src);
47 : } else {
48 0 : if (dest_tot_size - dest_size > 0) {
49 0 : strncat(dest, src,
50 : (dest_tot_size - dest_size) - 1);
51 0 : dest[dest_tot_size - 1] = 0;
52 : }
53 : }
54 1026710 : }
55 :
56 983166 : void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src)
57 : {
58 983166 : size_t str_size = strlen(src);
59 :
60 983166 : if (dest_tot_size > str_size) {
61 983166 : strcpy(dest, src);
62 : } else {
63 0 : if (dest_tot_size > 0) {
64 0 : memcpy(dest, src, (dest_tot_size) - 1);
65 0 : dest[dest_tot_size - 1] = 0;
66 : }
67 : }
68 983166 : }
69 :
70 654374 : void _gnutls_buffer_init(gnutls_buffer_st * str)
71 : {
72 654374 : str->data = str->allocd = NULL;
73 654374 : str->max_length = 0;
74 654374 : str->length = 0;
75 654374 : }
76 :
77 538237 : void _gnutls_buffer_clear(gnutls_buffer_st * str)
78 : {
79 538237 : if (str == NULL || str->allocd == NULL)
80 : return;
81 222951 : gnutls_free(str->allocd);
82 :
83 222951 : str->data = NULL;
84 222951 : str->max_length = 0;
85 222951 : str->length = 0;
86 : }
87 :
88 : #define MIN_CHUNK 1024
89 :
90 333344 : static void align_allocd_with_data(gnutls_buffer_st * dest)
91 : {
92 333344 : assert(dest->allocd != NULL);
93 333344 : assert(dest->data != NULL);
94 333344 : if (dest->length)
95 19808 : memmove(dest->allocd, dest->data, dest->length);
96 333344 : dest->data = dest->allocd;
97 333344 : }
98 :
99 : /**
100 : * gnutls_buffer_append_data:
101 : * @dest: the buffer to append to
102 : * @data: the data
103 : * @data_size: the size of @data
104 : *
105 : * Appends the provided @data to the destination buffer.
106 : *
107 : * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
108 : *
109 : * Since: 3.4.0
110 : **/
111 : int
112 4823650 : gnutls_buffer_append_data(gnutls_buffer_t dest, const void *data,
113 : size_t data_size)
114 : {
115 4823650 : size_t const tot_len = data_size + dest->length;
116 4823650 : size_t const unused = MEMSUB(dest->data, dest->allocd);
117 :
118 4823650 : if (unlikely(dest->data != NULL && dest->allocd == NULL))
119 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
120 :
121 4823650 : if (data_size == 0)
122 : return 0;
123 :
124 4798160 : if (unlikely(sizeof(size_t) == 4 &&
125 : INT_ADD_OVERFLOW (((ssize_t)MAX(data_size, MIN_CHUNK)), ((ssize_t)dest->length)))) {
126 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
127 : }
128 :
129 4798160 : if (dest->max_length >= tot_len) {
130 :
131 4530770 : if (dest->max_length - unused <= tot_len) {
132 3934 : align_allocd_with_data(dest);
133 : }
134 : } else {
135 267390 : size_t const new_len =
136 267390 : MAX(data_size, MIN_CHUNK) + MAX(dest->max_length,
137 : MIN_CHUNK);
138 :
139 267390 : dest->allocd = gnutls_realloc_fast(dest->allocd, new_len);
140 267390 : if (dest->allocd == NULL) {
141 0 : gnutls_assert();
142 0 : return GNUTLS_E_MEMORY_ERROR;
143 : }
144 267390 : dest->max_length = new_len;
145 267390 : dest->data = dest->allocd + unused;
146 :
147 267390 : align_allocd_with_data(dest);
148 : }
149 4798160 : assert(dest->data != NULL);
150 :
151 4798160 : memcpy(&dest->data[dest->length], data, data_size);
152 4798160 : dest->length = tot_len;
153 :
154 4798160 : return 0;
155 : }
156 :
157 64146 : int _gnutls_buffer_resize(gnutls_buffer_st * dest, size_t new_size)
158 : {
159 64146 : if (unlikely(dest->data != NULL && dest->allocd == NULL))
160 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
161 :
162 64146 : if (dest->max_length >= new_size) {
163 2126 : size_t unused = MEMSUB(dest->data, dest->allocd);
164 2126 : if (dest->max_length - unused <= new_size) {
165 0 : align_allocd_with_data(dest);
166 : }
167 :
168 2126 : return 0;
169 : } else {
170 62020 : size_t unused = MEMSUB(dest->data, dest->allocd);
171 62020 : size_t alloc_len =
172 62020 : MAX(new_size, MIN_CHUNK) + MAX(dest->max_length,
173 : MIN_CHUNK);
174 :
175 124040 : dest->allocd =
176 62020 : gnutls_realloc_fast(dest->allocd, alloc_len);
177 62020 : if (dest->allocd == NULL) {
178 0 : gnutls_assert();
179 0 : return GNUTLS_E_MEMORY_ERROR;
180 : }
181 62020 : dest->max_length = alloc_len;
182 62020 : dest->data = dest->allocd + unused;
183 :
184 62020 : align_allocd_with_data(dest);
185 :
186 62020 : return 0;
187 : }
188 : }
189 :
190 : /* Appends the provided string. The null termination byte is appended
191 : * but not included in length.
192 : */
193 1064360 : int _gnutls_buffer_append_str(gnutls_buffer_st * dest, const char *src)
194 : {
195 1064360 : int ret;
196 1064360 : ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
197 1064360 : if (ret >= 0)
198 1064360 : dest->length--;
199 :
200 1064360 : return ret;
201 : }
202 :
203 : /* returns data from a string in a constant buffer.
204 : * The data will NOT be valid if buffer is released or
205 : * data are appended in the buffer.
206 : */
207 : void
208 12983 : _gnutls_buffer_pop_datum(gnutls_buffer_st * str, gnutls_datum_t * data,
209 : size_t req_size)
210 : {
211 12983 : if (str->length == 0) {
212 0 : data->data = NULL;
213 0 : data->size = 0;
214 0 : return;
215 : }
216 :
217 12983 : if (req_size > str->length)
218 0 : req_size = str->length;
219 :
220 12983 : data->data = str->data;
221 12983 : data->size = req_size;
222 :
223 12983 : str->data += req_size;
224 12983 : str->length -= req_size;
225 :
226 : /* if string becomes empty start from beginning */
227 12983 : if (str->length == 0) {
228 679 : str->data = str->allocd;
229 : }
230 :
231 : return;
232 : }
233 :
234 : /* converts the buffer to a datum if possible. After this call
235 : * (failed or not) the buffer should be considered deinitialized.
236 : */
237 33283 : int _gnutls_buffer_to_datum(gnutls_buffer_st * str, gnutls_datum_t * data, unsigned is_str)
238 : {
239 33283 : int ret;
240 :
241 33283 : if (str->length == 0) {
242 20 : data->data = NULL;
243 20 : data->size = 0;
244 20 : ret = 0;
245 20 : goto fail;
246 : }
247 :
248 33263 : if (is_str) {
249 19789 : ret = _gnutls_buffer_append_data(str, "\x00", 1);
250 19789 : if (ret < 0) {
251 0 : gnutls_assert();
252 0 : goto fail;
253 : }
254 : }
255 :
256 33263 : if (str->allocd != str->data) {
257 0 : data->data = gnutls_malloc(str->length);
258 0 : if (data->data == NULL) {
259 0 : gnutls_assert();
260 0 : ret = GNUTLS_E_MEMORY_ERROR;
261 0 : goto fail;
262 : }
263 0 : memcpy(data->data, str->data, str->length);
264 0 : data->size = str->length;
265 0 : _gnutls_buffer_clear(str);
266 : } else {
267 33263 : data->data = str->data;
268 33263 : data->size = str->length;
269 33263 : _gnutls_buffer_init(str);
270 : }
271 :
272 33263 : if (is_str) {
273 19789 : data->size--;
274 : }
275 :
276 : return 0;
277 20 : fail:
278 20 : _gnutls_buffer_clear(str);
279 20 : return ret;
280 : }
281 :
282 : /* returns data from a string in a constant buffer. Will
283 : * fail with GNUTLS_E_PARSING_ERROR, if the string has not enough data.
284 : */
285 : int
286 7430 : _gnutls_buffer_pop_data(gnutls_buffer_st * str, void *data,
287 : size_t req_size)
288 : {
289 7430 : gnutls_datum_t tdata;
290 :
291 7430 : _gnutls_buffer_pop_datum(str, &tdata, req_size);
292 7430 : if (tdata.data == NULL || tdata.size != req_size) {
293 : return GNUTLS_E_PARSING_ERROR;
294 : }
295 :
296 7430 : memcpy(data, tdata.data, tdata.size);
297 :
298 7430 : return 0;
299 : }
300 :
301 : int
302 803732 : _gnutls_buffer_append_printf(gnutls_buffer_st * dest, const char *fmt, ...)
303 : {
304 803732 : va_list args;
305 803732 : int len;
306 803732 : char *str = NULL;
307 :
308 803732 : va_start(args, fmt);
309 803732 : len = vasprintf(&str, fmt, args);
310 803732 : va_end(args);
311 :
312 803732 : if (len < 0 || !str)
313 : return -1;
314 :
315 803732 : len = _gnutls_buffer_append_str(dest, str);
316 :
317 803732 : free(str);
318 :
319 803732 : return len;
320 : }
321 :
322 : static int
323 3 : _gnutls_buffer_insert_data(gnutls_buffer_st * dest, int pos,
324 : const void *str, size_t str_size)
325 : {
326 3 : size_t orig_length = dest->length;
327 3 : int ret;
328 :
329 3 : ret = _gnutls_buffer_resize(dest, dest->length + str_size); /* resize to make space */
330 3 : if (ret < 0)
331 : return ret;
332 :
333 3 : assert(dest->data != NULL);
334 :
335 3 : memmove(&dest->data[pos + str_size], &dest->data[pos],
336 : orig_length - pos);
337 :
338 3 : memcpy(&dest->data[pos], str, str_size);
339 3 : dest->length += str_size;
340 :
341 3 : return 0;
342 : }
343 :
344 : static void
345 3 : _gnutls_buffer_delete_data(gnutls_buffer_st * dest, int pos,
346 : size_t str_size)
347 : {
348 3 : memmove(&dest->data[pos], &dest->data[pos + str_size],
349 3 : dest->length - pos - str_size);
350 :
351 3 : dest->length -= str_size;
352 :
353 3 : return;
354 : }
355 :
356 :
357 : int
358 0 : _gnutls_buffer_append_escape(gnutls_buffer_st * dest, const void *data,
359 : size_t data_size, const char *invalid_chars)
360 : {
361 0 : int rv = -1;
362 0 : char t[5];
363 0 : unsigned int pos = dest->length;
364 :
365 0 : rv = _gnutls_buffer_append_data(dest, data, data_size);
366 0 : if (rv < 0)
367 0 : return gnutls_assert_val(rv);
368 :
369 0 : while (pos < dest->length) {
370 :
371 0 : if (dest->data[pos] == '\\'
372 0 : || strchr(invalid_chars, dest->data[pos])
373 0 : || !c_isgraph(dest->data[pos])) {
374 :
375 0 : snprintf(t, sizeof(t), "%%%.2X",
376 : (unsigned int) dest->data[pos]);
377 :
378 0 : _gnutls_buffer_delete_data(dest, pos, 1);
379 :
380 0 : if (_gnutls_buffer_insert_data(dest, pos, t, 3) < 0) {
381 0 : rv = -1;
382 0 : goto cleanup;
383 : }
384 0 : pos += 3;
385 : } else
386 0 : pos++;
387 : }
388 :
389 : rv = 0;
390 :
391 : cleanup:
392 : return rv;
393 : }
394 :
395 8 : int _gnutls_buffer_unescape(gnutls_buffer_st * dest)
396 : {
397 8 : int rv = -1;
398 8 : unsigned int pos = 0;
399 :
400 77 : while (pos < dest->length) {
401 69 : if (dest->data[pos] == '%') {
402 6 : if (pos + 1 < dest->length && dest->data[pos + 1] == '%') {
403 : // %% -> %
404 0 : _gnutls_buffer_delete_data(dest, pos, 1);
405 6 : } else if (pos + 2 < dest->length && c_isxdigit(dest->data[pos + 1]) && c_isxdigit(dest->data[pos + 2])) {
406 3 : unsigned char x;
407 :
408 3 : hex_decode((char *) dest->data + pos + 1, 2, &x, 1);
409 :
410 3 : _gnutls_buffer_delete_data(dest, pos, 3);
411 3 : _gnutls_buffer_insert_data(dest, pos, &x, 1);
412 : }
413 : }
414 69 : pos++;
415 : }
416 :
417 8 : rv = 0;
418 :
419 8 : return rv;
420 : }
421 :
422 :
423 : /* Converts the given string (old) to hex. A buffer must be provided
424 : * to hold the new hex string. The new string will be null terminated.
425 : * If the buffer does not have enough space to hold the string, a
426 : * truncated hex string is returned (always null terminated).
427 : */
428 8359 : char *_gnutls_bin2hex(const void *_old, size_t oldlen,
429 : char *buffer, size_t buffer_size,
430 : const char *separator)
431 : {
432 8359 : unsigned int i, j;
433 8359 : const uint8_t *old = _old;
434 8359 : int step = 2;
435 8359 : const char empty[] = "";
436 :
437 8359 : if (separator != NULL && separator[0] != 0)
438 : step = 3;
439 : else
440 8334 : separator = empty;
441 :
442 8359 : if (buffer_size < 3) {
443 0 : gnutls_assert();
444 0 : return NULL;
445 : }
446 :
447 8359 : i = j = 0;
448 8359 : sprintf(&buffer[j], "%.2x", old[i]);
449 8359 : j += 2;
450 8359 : i++;
451 :
452 267041 : for (; i < oldlen && j + step < buffer_size; j += step) {
453 258682 : sprintf(&buffer[j], "%s%.2x", separator, old[i]);
454 258682 : i++;
455 : }
456 8359 : buffer[j] = '\0';
457 :
458 8359 : return buffer;
459 : }
460 :
461 : /**
462 : * gnutls_hex2bin:
463 : * @hex_data: string with data in hex format
464 : * @hex_size: size of hex data
465 : * @bin_data: output array with binary data
466 : * @bin_size: when calling should hold maximum size of @bin_data,
467 : * on return will hold actual length of @bin_data.
468 : *
469 : * Convert a buffer with hex data to binary data. This function
470 : * unlike gnutls_hex_decode() can parse hex data with separators
471 : * between numbers. That is, it ignores any non-hex characters.
472 : *
473 : * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
474 : *
475 : * Since: 2.4.0
476 : **/
477 : int
478 16 : gnutls_hex2bin(const char *hex_data,
479 : size_t hex_size, void *bin_data, size_t * bin_size)
480 : {
481 16 : return _gnutls_hex2bin(hex_data, hex_size, (void *) bin_data,
482 : bin_size);
483 : }
484 :
485 : int
486 17 : _gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t * bin_data,
487 : size_t * bin_size)
488 : {
489 17 : unsigned int i, j;
490 17 : uint8_t hex2_data[3];
491 17 : unsigned long val;
492 :
493 17 : hex2_data[2] = 0;
494 :
495 780 : for (i = j = 0; i < hex_size;) {
496 764 : if (!isxdigit(hex_data[i])) { /* skip non-hex such as the ':' in 00:FF */
497 279 : i++;
498 279 : continue;
499 : }
500 485 : if (j >= *bin_size) {
501 0 : gnutls_assert();
502 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
503 : }
504 :
505 485 : if (i+1 >= hex_size)
506 1 : return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
507 :
508 484 : hex2_data[0] = hex_data[i];
509 484 : hex2_data[1] = hex_data[i + 1];
510 484 : i += 2;
511 :
512 484 : val = strtoul((char *) hex2_data, NULL, 16);
513 484 : if (val == ULONG_MAX) {
514 0 : gnutls_assert();
515 0 : return GNUTLS_E_PARSING_ERROR;
516 : }
517 484 : bin_data[j] = val;
518 484 : j++;
519 : }
520 16 : *bin_size = j;
521 :
522 16 : return 0;
523 : }
524 :
525 : /**
526 : * gnutls_hex_decode2:
527 : * @hex_data: contain the encoded data
528 : * @result: the result in an allocated string
529 : *
530 : * This function will decode the given encoded data, using the hex
531 : * encoding used by PSK password files.
532 : *
533 : * Returns: %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
534 : **/
535 : int
536 7742 : gnutls_hex_decode2(const gnutls_datum_t * hex_data, gnutls_datum_t *result)
537 : {
538 7742 : int ret;
539 7742 : int size = hex_data_size(hex_data->size);
540 :
541 7742 : result->data = gnutls_malloc(size);
542 7742 : if (result->data == NULL) {
543 0 : gnutls_assert();
544 0 : return GNUTLS_E_MEMORY_ERROR;
545 : }
546 :
547 7742 : result->size = size;
548 7742 : ret = hex_decode((char *) hex_data->data, hex_data->size,
549 : result->data, result->size);
550 7742 : if (ret == 0) {
551 134 : gnutls_assert();
552 134 : gnutls_free(result->data);
553 134 : return GNUTLS_E_PARSING_ERROR;
554 : }
555 :
556 : return 0;
557 : }
558 :
559 : /**
560 : * gnutls_hex_decode:
561 : * @hex_data: contain the encoded data
562 : * @result: the place where decoded data will be copied
563 : * @result_size: holds the size of the result
564 : *
565 : * This function will decode the given encoded data, using the hex
566 : * encoding used by PSK password files.
567 : *
568 : * Initially @result_size must hold the maximum size available in
569 : * @result, and on return it will contain the number of bytes written.
570 : *
571 : * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
572 : * long enough, %GNUTLS_E_PARSING_ERROR on invalid hex data, or 0 on success.
573 : **/
574 : int
575 349 : gnutls_hex_decode(const gnutls_datum_t * hex_data, void *result,
576 : size_t * result_size)
577 : {
578 349 : int ret;
579 349 : size_t size = hex_data_size(hex_data->size);
580 :
581 349 : if (*result_size < size) {
582 0 : gnutls_assert();
583 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
584 : }
585 :
586 349 : ret = hex_decode((char *) hex_data->data, hex_data->size,
587 : result, size);
588 349 : if (ret == 0) {
589 0 : return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
590 : }
591 349 : *result_size = size;
592 :
593 349 : return 0;
594 : }
595 :
596 : /**
597 : * gnutls_hex_encode:
598 : * @data: contain the raw data
599 : * @result: the place where hex data will be copied
600 : * @result_size: holds the size of the result
601 : *
602 : * This function will convert the given data to printable data, using
603 : * the hex encoding, as used in the PSK password files.
604 : *
605 : * Note that the size of the result includes the null terminator.
606 : *
607 : * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
608 : * long enough, or 0 on success.
609 : **/
610 : int
611 3955 : gnutls_hex_encode(const gnutls_datum_t * data, char *result,
612 : size_t * result_size)
613 : {
614 3955 : int ret;
615 3955 : size_t size = hex_str_size(data->size);
616 :
617 3955 : if (*result_size < size) {
618 0 : gnutls_assert();
619 0 : return GNUTLS_E_SHORT_MEMORY_BUFFER;
620 : }
621 :
622 3955 : ret = hex_encode(data->data, data->size, result, *result_size);
623 3955 : if (ret == 0) {
624 0 : return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
625 : }
626 :
627 3955 : *result_size = size;
628 :
629 3955 : return 0;
630 : }
631 :
632 : /**
633 : * gnutls_hex_encode2:
634 : * @data: contain the raw data
635 : * @result: the result in an allocated string
636 : *
637 : * This function will convert the given data to printable data, using
638 : * the hex encoding, as used in the PSK password files.
639 : *
640 : * Note that the size of the result does NOT include the null terminator.
641 : *
642 : * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
643 : **/
644 : int
645 1686 : gnutls_hex_encode2(const gnutls_datum_t * data, gnutls_datum_t *result)
646 : {
647 1686 : int ret;
648 1686 : int size = hex_str_size(data->size);
649 :
650 1686 : result->data = gnutls_malloc(size);
651 1686 : if (result->data == NULL) {
652 0 : gnutls_assert();
653 0 : return GNUTLS_E_MEMORY_ERROR;
654 : }
655 :
656 1686 : ret = hex_encode((char*)data->data, data->size, (char*)result->data, size);
657 1686 : if (ret == 0) {
658 0 : gnutls_free(result->data);
659 0 : return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
660 : }
661 :
662 1686 : result->size = size-1;
663 :
664 1686 : return 0;
665 : }
666 :
667 : static int
668 0 : hostname_compare_raw(const char *certname,
669 : size_t certnamesize, const char *hostname)
670 : {
671 0 : if (certnamesize == strlen(hostname) && memcmp(hostname, certname, certnamesize) == 0)
672 0 : return 1;
673 : return 0;
674 : }
675 :
676 : static int
677 446 : hostname_compare_ascii(const char *certname,
678 : size_t certnamesize, const char *hostname)
679 : {
680 446 : for (;
681 3282 : *certname && *hostname
682 8484 : && c_toupper(*certname) == c_toupper(*hostname);
683 2836 : certname++, hostname++, certnamesize--);
684 :
685 : /* the strings are the same */
686 446 : if (certnamesize == 0 && *hostname == '\0')
687 237 : return 1;
688 :
689 : return 0;
690 : }
691 :
692 : /* compare hostname against certificate, taking account of wildcards
693 : * return 1 on success or 0 on error
694 : *
695 : * note: certnamesize is required as X509 certs can contain embedded NULs in
696 : * the strings such as CN or subjectAltName.
697 : *
698 : * Wildcards are taken into account only if they are the leftmost
699 : * component, and if the string is ascii only (partial advice from rfc6125)
700 : *
701 : */
702 : int
703 353 : _gnutls_hostname_compare(const char *certname,
704 : size_t certnamesize, const char *hostname, unsigned vflags)
705 : {
706 353 : char *p;
707 353 : unsigned i;
708 :
709 4565 : for (i=0;i<certnamesize;i++) {
710 4212 : if (c_isprint(certname[i]) == 0)
711 0 : return hostname_compare_raw(certname, certnamesize, hostname);
712 : }
713 :
714 353 : if (*certname == '*' && !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
715 : /* a wildcard certificate */
716 :
717 : /* ensure that we have at least two domain components after
718 : * the wildcard. */
719 19 : p = strrchr(certname, '.');
720 19 : if (p == NULL || strchr(certname, '.') == p || p[1] == 0) {
721 : return 0;
722 : }
723 :
724 16 : certname++;
725 16 : certnamesize--;
726 :
727 208 : while (1) {
728 112 : if (hostname_compare_ascii(certname, certnamesize, hostname))
729 : return 1;
730 :
731 : /* wildcards are only allowed to match a single domain
732 : component or component fragment */
733 108 : if (*hostname == '\0' || *hostname == '.')
734 : break;
735 96 : hostname++;
736 : }
737 :
738 : return 0;
739 : } else {
740 334 : return hostname_compare_ascii(certname, certnamesize, hostname);
741 : }
742 : }
743 :
744 : int
745 2241960 : _gnutls_buffer_append_prefix(gnutls_buffer_st * buf, int pfx_size,
746 : size_t data_size)
747 : {
748 2241960 : uint8_t ss[4];
749 :
750 2241960 : if (pfx_size == 32) {
751 344214 : _gnutls_write_uint32(data_size, ss);
752 344214 : pfx_size = 4;
753 1897740 : } else if (pfx_size == 24) {
754 42457 : _gnutls_write_uint24(data_size, ss);
755 42457 : pfx_size = 3;
756 1855290 : } else if (pfx_size == 16) {
757 1514810 : _gnutls_write_uint16(data_size, ss);
758 1514810 : pfx_size = 2;
759 340481 : } else if (pfx_size == 8) {
760 340481 : ss[0] = data_size;
761 340481 : pfx_size = 1;
762 : } else
763 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
764 :
765 2241960 : return _gnutls_buffer_append_data(buf, ss, pfx_size);
766 : }
767 :
768 : /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
769 : * the number read, is less than the data in the buffer
770 : */
771 : int
772 61787 : _gnutls_buffer_pop_prefix32(gnutls_buffer_st * buf, size_t * data_size,
773 : int check)
774 : {
775 61787 : size_t size;
776 :
777 61787 : if (buf->length < 4) {
778 0 : gnutls_assert();
779 0 : return GNUTLS_E_PARSING_ERROR;
780 : }
781 :
782 61787 : size = _gnutls_read_uint32(buf->data);
783 61787 : if (check && size > buf->length - 4) {
784 0 : gnutls_assert();
785 0 : return GNUTLS_E_PARSING_ERROR;
786 : }
787 :
788 61787 : buf->data += 4;
789 61787 : buf->length -= 4;
790 :
791 61787 : *data_size = size;
792 :
793 61787 : return 0;
794 : }
795 :
796 331 : int _gnutls_buffer_pop_prefix8(gnutls_buffer_st *buf, uint8_t *data, int check)
797 : {
798 331 : if (buf->length < 1) {
799 0 : gnutls_assert();
800 0 : return GNUTLS_E_PARSING_ERROR;
801 : }
802 :
803 331 : *data = buf->data[0];
804 :
805 331 : if (check && *data > buf->length - 1) {
806 0 : gnutls_assert();
807 0 : return GNUTLS_E_PARSING_ERROR;
808 : }
809 :
810 331 : buf->data++;
811 331 : buf->length--;
812 :
813 331 : return 0;
814 : }
815 :
816 : int
817 0 : _gnutls_buffer_pop_prefix24(gnutls_buffer_st * buf, size_t * data_size,
818 : int check)
819 : {
820 0 : size_t size;
821 :
822 0 : if (buf->length < 3) {
823 0 : gnutls_assert();
824 0 : return GNUTLS_E_PARSING_ERROR;
825 : }
826 :
827 0 : size = _gnutls_read_uint24(buf->data);
828 0 : if (check && size > buf->length - 3) {
829 0 : gnutls_assert();
830 0 : return GNUTLS_E_PARSING_ERROR;
831 : }
832 :
833 0 : buf->data += 3;
834 0 : buf->length -= 3;
835 :
836 0 : *data_size = size;
837 :
838 0 : return 0;
839 : }
840 :
841 : int
842 4904 : _gnutls_buffer_pop_datum_prefix32(gnutls_buffer_st * buf,
843 : gnutls_datum_t * data)
844 : {
845 4904 : size_t size;
846 4904 : int ret;
847 :
848 4904 : ret = _gnutls_buffer_pop_prefix32(buf, &size, 1);
849 4904 : if (ret < 0) {
850 0 : gnutls_assert();
851 0 : return ret;
852 : }
853 :
854 4904 : if (size > 0) {
855 455 : size_t osize = size;
856 455 : _gnutls_buffer_pop_datum(buf, data, size);
857 455 : if (osize != data->size) {
858 0 : gnutls_assert();
859 0 : return GNUTLS_E_PARSING_ERROR;
860 : }
861 : } else {
862 4449 : data->size = 0;
863 4449 : data->data = NULL;
864 : }
865 :
866 : return 0;
867 : }
868 :
869 : int
870 971 : _gnutls_buffer_pop_datum_prefix16(gnutls_buffer_st * buf,
871 : gnutls_datum_t * data)
872 : {
873 971 : size_t size;
874 :
875 971 : if (buf->length < 2) {
876 0 : gnutls_assert();
877 0 : return GNUTLS_E_PARSING_ERROR;
878 : }
879 :
880 971 : size = _gnutls_read_uint16(buf->data);
881 :
882 971 : buf->data += 2;
883 971 : buf->length -= 2;
884 :
885 971 : if (size > 0) {
886 971 : size_t osize = size;
887 971 : _gnutls_buffer_pop_datum(buf, data, size);
888 971 : if (osize != data->size) {
889 0 : gnutls_assert();
890 0 : return GNUTLS_E_PARSING_ERROR;
891 : }
892 : } else {
893 0 : data->size = 0;
894 0 : data->data = NULL;
895 : }
896 :
897 : return 0;
898 : }
899 :
900 : int
901 4145 : _gnutls_buffer_pop_datum_prefix8(gnutls_buffer_st * buf,
902 : gnutls_datum_t * data)
903 : {
904 4145 : size_t size;
905 :
906 4145 : if (buf->length < 1) {
907 0 : gnutls_assert();
908 0 : return GNUTLS_E_PARSING_ERROR;
909 : }
910 :
911 4145 : size = buf->data[0];
912 :
913 4145 : buf->data++;
914 4145 : buf->length--;
915 :
916 4145 : if (size > 0) {
917 4121 : size_t osize = size;
918 4121 : _gnutls_buffer_pop_datum(buf, data, size);
919 4121 : if (osize != data->size) {
920 0 : gnutls_assert();
921 0 : return GNUTLS_E_PARSING_ERROR;
922 : }
923 : } else {
924 24 : data->size = 0;
925 24 : data->data = NULL;
926 : }
927 :
928 : return 0;
929 : }
930 :
931 : int
932 365480 : _gnutls_buffer_append_data_prefix(gnutls_buffer_st * buf,
933 : int pfx_size, const void *data,
934 : size_t data_size)
935 : {
936 365480 : int ret;
937 :
938 365480 : ret = _gnutls_buffer_append_prefix(buf, pfx_size, data_size);
939 365480 : if (ret < 0)
940 0 : return gnutls_assert_val(ret);
941 :
942 365480 : if (data_size > 0) {
943 280904 : ret = _gnutls_buffer_append_data(buf, data, data_size);
944 280904 : if (ret < 0)
945 0 : return gnutls_assert_val(ret);
946 : }
947 :
948 : return 0;
949 : }
950 :
951 7007 : int _gnutls_buffer_append_mpi(gnutls_buffer_st * buf, int pfx_size,
952 : bigint_t mpi, int lz)
953 : {
954 7007 : gnutls_datum_t dd;
955 7007 : int ret;
956 :
957 7007 : if (lz)
958 0 : ret = _gnutls_mpi_dprint_lz(mpi, &dd);
959 : else
960 7007 : ret = _gnutls_mpi_dprint(mpi, &dd);
961 :
962 7007 : if (ret < 0)
963 0 : return gnutls_assert_val(ret);
964 :
965 7007 : ret =
966 14014 : _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data,
967 7007 : dd.size);
968 :
969 7007 : _gnutls_free_datum(&dd);
970 :
971 7007 : return ret;
972 : }
973 :
974 : /* Appends an MPI of fixed-size in bytes left-padded with zeros if necessary */
975 1726 : int _gnutls_buffer_append_fixed_mpi(gnutls_buffer_st * buf,
976 : bigint_t mpi, unsigned size)
977 : {
978 1726 : gnutls_datum_t dd;
979 1726 : unsigned pad, i;
980 1726 : int ret;
981 :
982 1726 : ret = _gnutls_mpi_dprint(mpi, &dd);
983 1726 : if (ret < 0)
984 0 : return gnutls_assert_val(ret);
985 :
986 1726 : if (size < dd.size) {
987 0 : ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
988 0 : goto cleanup;
989 : }
990 :
991 1726 : pad = size - dd.size;
992 1732 : for (i=0;i<pad;i++) {
993 6 : ret =
994 6 : _gnutls_buffer_append_data(buf, "\x00", 1);
995 6 : if (ret < 0) {
996 0 : gnutls_assert();
997 0 : goto cleanup;
998 : }
999 : }
1000 :
1001 : /* append the rest */
1002 1726 : ret =
1003 1726 : _gnutls_buffer_append_data(buf, dd.data, dd.size);
1004 :
1005 1726 : cleanup:
1006 1726 : _gnutls_free_datum(&dd);
1007 1726 : return ret;
1008 : }
1009 :
1010 : void
1011 20463 : _gnutls_buffer_hexprint(gnutls_buffer_st * str,
1012 : const void *_data, size_t len)
1013 : {
1014 20463 : size_t j;
1015 20463 : const unsigned char *data = _data;
1016 :
1017 20463 : if (len == 0)
1018 7 : _gnutls_buffer_append_str(str, "00");
1019 : else {
1020 376475 : for (j = 0; j < len; j++)
1021 356019 : _gnutls_buffer_append_printf(str, "%.2x",
1022 356019 : (unsigned) data[j]);
1023 : }
1024 20463 : }
1025 :
1026 : int
1027 1885 : _gnutls_buffer_base64print(gnutls_buffer_st * str,
1028 : const void *_data, size_t len)
1029 : {
1030 1885 : const unsigned char *data = _data;
1031 1885 : unsigned b64len = BASE64_ENCODE_RAW_LENGTH(len);
1032 1885 : int ret;
1033 :
1034 1885 : ret = _gnutls_buffer_resize(str, str->length+b64len+1);
1035 1885 : if (ret < 0) {
1036 0 : return gnutls_assert_val(ret);
1037 : }
1038 :
1039 1885 : base64_encode_raw((void*)&str->data[str->length], len, data);
1040 1885 : str->length += b64len;
1041 1885 : str->data[str->length] = 0;
1042 :
1043 1885 : return 0;
1044 : }
1045 :
1046 : void
1047 2700 : _gnutls_buffer_hexdump(gnutls_buffer_st * str, const void *_data,
1048 : size_t len, const char *spc)
1049 : {
1050 2700 : size_t j;
1051 2700 : const unsigned char *data = _data;
1052 :
1053 2700 : if (spc)
1054 2700 : _gnutls_buffer_append_str(str, spc);
1055 368710 : for (j = 0; j < len; j++) {
1056 366010 : if (((j + 1) % 16) == 0) {
1057 22664 : _gnutls_buffer_append_printf(str, "%.2x\n",
1058 22664 : (unsigned) data[j]);
1059 22664 : if (spc && j != (len - 1))
1060 21388 : _gnutls_buffer_append_str(str, spc);
1061 343346 : } else if (j == (len - 1))
1062 1422 : _gnutls_buffer_append_printf(str, "%.2x",
1063 1422 : (unsigned) data[j]);
1064 : else
1065 341924 : _gnutls_buffer_append_printf(str, "%.2x:",
1066 341924 : (unsigned) data[j]);
1067 : }
1068 2700 : if ((j % 16) != 0)
1069 1422 : _gnutls_buffer_append_str(str, "\n");
1070 2700 : }
1071 :
1072 : void
1073 758 : _gnutls_buffer_asciiprint(gnutls_buffer_st * str,
1074 : const char *data, size_t len)
1075 : {
1076 758 : size_t j;
1077 :
1078 30037 : for (j = 0; j < len; j++)
1079 29279 : if (c_isprint(data[j]))
1080 16298 : _gnutls_buffer_append_printf(str, "%c",
1081 16298 : (unsigned char)
1082 : data[j]);
1083 : else
1084 12981 : _gnutls_buffer_append_printf(str, ".");
1085 758 : }
|