corrected typo
[gnutls.git] / lib / gnutls_str.c
blob0d6d087f8d023de28f307c63fcf4d09010cdacaa
1 /*
2 * Copyright (C) 2002-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_num.h>
26 #include <gnutls_str.h>
27 #include <stdarg.h>
28 #include <c-ctype.h>
30 /* These function are like strcat, strcpy. They only
31 * do bound checking (they shouldn't cause buffer overruns),
32 * and they always produce null terminated strings.
34 * They should be used only with null terminated strings.
36 void
37 _gnutls_str_cat (char *dest, size_t dest_tot_size, const char *src)
39 size_t str_size = strlen (src);
40 size_t dest_size = strlen (dest);
42 if (dest_tot_size - dest_size > str_size)
44 strcat (dest, src);
46 else
48 if (dest_tot_size - dest_size > 0)
50 strncat (dest, src, (dest_tot_size - dest_size) - 1);
51 dest[dest_tot_size - 1] = 0;
56 void
57 _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
59 size_t str_size = strlen (src);
61 if (dest_tot_size > str_size)
63 strcpy (dest, src);
65 else
67 if (dest_tot_size > 0)
69 strncpy (dest, src, (dest_tot_size) - 1);
70 dest[dest_tot_size - 1] = 0;
75 void
76 _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
77 size_t src_size)
80 if (dest_tot_size >= src_size)
82 memcpy (dest, src, src_size);
84 else
86 if (dest_tot_size > 0)
88 memcpy (dest, src, dest_tot_size);
93 void
94 _gnutls_buffer_init (gnutls_buffer_st * str)
96 str->data = str->allocd = NULL;
97 str->max_length = 0;
98 str->length = 0;
101 void _gnutls_buffer_replace_data( gnutls_buffer_st * buf, gnutls_datum_t * data)
103 gnutls_free(buf->allocd);
104 buf->allocd = buf->data = data->data;
105 buf->max_length = buf->length = data->size;
108 void
109 _gnutls_buffer_clear (gnutls_buffer_st * str)
111 if (str == NULL || str->allocd == NULL)
112 return;
113 gnutls_free (str->allocd);
115 str->data = str->allocd = NULL;
116 str->max_length = 0;
117 str->length = 0;
120 #define MIN_CHUNK 1024
123 _gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data,
124 size_t data_size)
126 size_t tot_len = data_size + dest->length;
128 if (data_size == 0) return 0;
130 if (dest->max_length >= tot_len)
132 size_t unused = MEMSUB (dest->data, dest->allocd);
134 if (dest->max_length - unused <= tot_len)
136 if (dest->length && dest->data)
137 memmove (dest->allocd, dest->data, dest->length);
139 dest->data = dest->allocd;
141 memmove (&dest->data[dest->length], data, data_size);
142 dest->length = tot_len;
144 return tot_len;
146 else
148 size_t unused = MEMSUB (dest->data, dest->allocd);
149 size_t new_len =
150 MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
152 dest->allocd = gnutls_realloc (dest->allocd, new_len);
153 if (dest->allocd == NULL)
155 gnutls_assert ();
156 return GNUTLS_E_MEMORY_ERROR;
158 dest->max_length = new_len;
159 dest->data = dest->allocd + unused;
161 if (dest->length && dest->data)
162 memmove (dest->allocd, dest->data, dest->length);
163 dest->data = dest->allocd;
165 memcpy (&dest->data[dest->length], data, data_size);
166 dest->length = tot_len;
168 return tot_len;
173 _gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size)
175 if (dest->max_length >= new_size)
177 size_t unused = MEMSUB (dest->data, dest->allocd);
178 if (dest->max_length - unused <= new_size)
180 if (dest->length && dest->data)
181 memmove (dest->allocd, dest->data, dest->length);
182 dest->data = dest->allocd;
185 return 0;
187 else
189 size_t unused = MEMSUB (dest->data, dest->allocd);
190 size_t alloc_len =
191 MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
193 dest->allocd = gnutls_realloc (dest->allocd, alloc_len);
194 if (dest->allocd == NULL)
196 gnutls_assert ();
197 return GNUTLS_E_MEMORY_ERROR;
199 dest->max_length = alloc_len;
200 dest->data = dest->allocd + unused;
202 if (dest->length && dest->data)
203 memmove (dest->allocd, dest->data, dest->length);
204 dest->data = dest->allocd;
206 return 0;
211 _gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src)
213 return _gnutls_buffer_append_data (dest, src, strlen (src));
216 /* returns data from a string in a constant buffer.
217 * The data will NOT be valid if buffer is released or
218 * data are appended in the buffer.
220 void
221 _gnutls_buffer_pop_datum (gnutls_buffer_st * str, gnutls_datum_t * data,
222 size_t req_size)
225 if (str->length == 0)
227 data->data = NULL;
228 data->size = 0;
229 return;
232 if (req_size > str->length)
233 req_size = str->length;
235 data->data = str->data;
236 data->size = req_size;
238 str->data += req_size;
239 str->length -= req_size;
241 /* if string becomes empty start from begining */
242 if (str->length == 0)
244 str->data = str->allocd;
247 return;
250 /* converts the buffer to a datum if possible. After this call the buffer
251 * is at an usable state and might not be used or deinitialized */
253 _gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data)
256 if (str->length == 0)
258 data->data = NULL;
259 data->size = 0;
260 return 0;
263 if (str->allocd != str->data)
265 data->data = gnutls_malloc (str->length);
266 if (data->data == NULL)
268 gnutls_assert ();
269 return GNUTLS_E_MEMORY_ERROR;
271 memcpy (data->data, str->data, str->length);
272 data->size = str->length;
273 _gnutls_buffer_clear (str);
275 else
277 data->data = str->data;
278 data->size = str->length;
281 return 0;
284 /* returns data from a string in a constant buffer.
286 void
287 _gnutls_buffer_pop_data (gnutls_buffer_st * str, void *data,
288 size_t * req_size)
290 gnutls_datum_t tdata;
292 _gnutls_buffer_pop_datum (str, &tdata, *req_size);
294 *req_size = tdata.size;
295 memcpy (data, tdata.data, tdata.size);
297 return;
301 _gnutls_buffer_append_printf (gnutls_buffer_st * dest, const char *fmt, ...)
303 va_list args;
304 int len;
305 char *str;
307 va_start (args, fmt);
308 len = vasprintf (&str, fmt, args);
309 va_end (args);
311 if (len < 0 || !str)
312 return -1;
314 len = _gnutls_buffer_append_str (dest, str);
316 free (str);
318 return len;
321 static int
322 _gnutls_buffer_insert_data (gnutls_buffer_st * dest, int pos, const void *str,
323 size_t str_size)
325 size_t orig_length = dest->length;
326 int ret;
328 ret = _gnutls_buffer_resize (dest, dest->length + str_size); /* resize to make space */
329 if (ret < 0)
330 return ret;
332 memmove (&dest->data[pos + str_size], &dest->data[pos], orig_length - pos);
334 memcpy (&dest->data[pos], str, str_size);
335 dest->length += str_size;
337 return 0;
340 static void
341 _gnutls_buffer_delete_data (gnutls_buffer_st * dest, int pos, size_t str_size)
343 memmove (&dest->data[pos], &dest->data[pos + str_size],
344 dest->length - pos - str_size);
346 dest->length -= str_size;
348 return;
353 _gnutls_buffer_escape (gnutls_buffer_st * dest, int all,
354 const char *const invalid_chars)
356 int rv = -1;
357 char t[5];
358 unsigned int pos = 0;
360 while (pos < dest->length)
363 if (all != 0 || (dest->data[pos] == '\\' || strchr (invalid_chars, dest->data[pos])
364 || !c_isgraph (dest->data[pos])))
367 snprintf (t, sizeof (t), "%%%.2X", (unsigned int) dest->data[pos]);
369 _gnutls_buffer_delete_data (dest, pos, 1);
371 if (_gnutls_buffer_insert_data (dest, pos, t, 3) < 0)
373 rv = -1;
374 goto cleanup;
376 pos+=3;
378 else
379 pos++;
382 rv = 0;
384 cleanup:
386 return rv;
390 _gnutls_buffer_unescape (gnutls_buffer_st * dest)
392 int rv = -1;
393 unsigned int pos = 0;
395 while (pos < dest->length)
397 if (dest->data[pos] == '%')
399 char b[3];
400 unsigned int u;
401 unsigned char x;
403 b[0] = dest->data[pos + 1];
404 b[1] = dest->data[pos + 2];
405 b[2] = 0;
407 sscanf (b, "%02x", &u);
409 x = u;
411 _gnutls_buffer_delete_data (dest, pos, 3);
412 _gnutls_buffer_insert_data (dest, pos, &x, 1);
414 pos++;
417 rv = 0;
419 return rv;
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).
428 char *
429 _gnutls_bin2hex (const void *_old, size_t oldlen,
430 char *buffer, size_t buffer_size, const char *separator)
432 unsigned int i, j;
433 const uint8_t *old = _old;
434 int step = 2;
435 const char empty[] = "";
437 if (separator != NULL && separator[0] != 0)
438 step = 3;
439 else
440 separator = empty;
442 if (buffer_size < 3)
444 gnutls_assert();
445 return NULL;
448 i = j = 0;
449 sprintf (&buffer[j], "%.2x", old[i]);
450 j += 2;
451 i++;
453 for (; i < oldlen && j + step < buffer_size; j += step)
455 sprintf (&buffer[j], "%s%.2x", separator, old[i]);
456 i++;
458 buffer[j] = '\0';
460 return buffer;
464 * gnutls_hex2bin:
465 * @hex_data: string with data in hex format
466 * @hex_size: size of hex data
467 * @bin_data: output array with binary data
468 * @bin_size: when calling should hold maximum size of @bin_data,
469 * on return will hold actual length of @bin_data.
471 * Convert a buffer with hex data to binary data.
473 * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
475 * Since: 2.4.0
478 gnutls_hex2bin (const char *hex_data,
479 size_t hex_size, void *bin_data, size_t * bin_size)
481 return _gnutls_hex2bin (hex_data, hex_size, (void*)bin_data, bin_size);
485 _gnutls_hex2bin (const char * hex_data, size_t hex_size, uint8_t * bin_data,
486 size_t * bin_size)
488 unsigned int i, j;
489 uint8_t hex2_data[3];
490 unsigned long val;
492 hex2_data[2] = 0;
494 for (i = j = 0; i < hex_size;)
496 if (!isxdigit (hex_data[i])) /* skip non-hex such as the ':' in 00:FF */
498 i++;
499 continue;
502 if (j > *bin_size)
504 gnutls_assert ();
505 return GNUTLS_E_SHORT_MEMORY_BUFFER;
508 hex2_data[0] = hex_data[i];
509 hex2_data[1] = hex_data[i + 1];
510 i += 2;
512 val = strtoul ((char *) hex2_data, NULL, 16);
513 if (val == ULONG_MAX)
515 gnutls_assert ();
516 return GNUTLS_E_PARSING_ERROR;
518 bin_data[j] = val;
519 j++;
521 *bin_size = j;
523 return 0;
527 /* compare hostname against certificate, taking account of wildcards
528 * return 1 on success or 0 on error
530 * note: certnamesize is required as X509 certs can contain embedded NULs in
531 * the strings such as CN or subjectAltName.
533 * @level: is used for recursion. Use 0 when you call this function.
536 _gnutls_hostname_compare (const char *certname,
537 size_t certnamesize, const char *hostname, int level)
540 if (level > 5)
541 return 0;
543 /* find the first different character */
544 for (; *certname && *hostname && c_toupper (*certname) == c_toupper (*hostname);
545 certname++, hostname++, certnamesize--)
548 /* the strings are the same */
549 if (certnamesize == 0 && *hostname == '\0')
550 return 1;
552 if (*certname == '*')
554 /* a wildcard certificate */
556 certname++;
557 certnamesize--;
559 while (1)
561 /* Use a recursive call to allow multiple wildcards */
562 if (_gnutls_hostname_compare (certname, certnamesize, hostname, level+1))
563 return 1;
565 /* wildcards are only allowed to match a single domain
566 component or component fragment */
567 if (*hostname == '\0' || *hostname == '.')
568 break;
569 hostname++;
572 return 0;
575 return 0;
579 _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, int pfx_size, size_t data_size)
581 uint8_t ss[4];
583 if (pfx_size == 32)
585 _gnutls_write_uint32 (data_size, ss);
586 pfx_size = 4;
588 else if (pfx_size == 24)
590 _gnutls_write_uint24 (data_size, ss);
591 pfx_size = 3;
593 else if (pfx_size == 16)
595 _gnutls_write_uint16 (data_size, ss);
596 pfx_size = 2;
598 else if (pfx_size == 8)
600 ss[0] = data_size;
601 pfx_size = 1;
603 else
604 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
606 return _gnutls_buffer_append_data (buf, ss, pfx_size);
609 /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
610 * the number read, is less than the data in the buffer
613 _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t * data_size,
614 int check)
616 size_t size;
618 if (buf->length < 4)
620 gnutls_assert ();
621 return GNUTLS_E_PARSING_ERROR;
624 size = _gnutls_read_uint32 (buf->data);
625 if (check && size > buf->length - 4)
627 gnutls_assert ();
628 return GNUTLS_E_PARSING_ERROR;
631 buf->data += 4;
632 buf->length -= 4;
634 *data_size = size;
636 return 0;
640 _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf,
641 gnutls_datum_t * data)
643 size_t size;
644 int ret;
646 ret = _gnutls_buffer_pop_prefix (buf, &size, 1);
647 if (ret < 0)
649 gnutls_assert ();
650 return ret;
653 if (size > 0)
655 size_t osize = size;
656 _gnutls_buffer_pop_datum (buf, data, size);
657 if (osize != data->size)
659 gnutls_assert ();
660 return GNUTLS_E_PARSING_ERROR;
663 else
665 data->size = 0;
666 data->data = NULL;
669 return 0;
673 _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf,
674 int pfx_size, const void *data, size_t data_size)
676 int ret = 0, ret1;
678 ret1 = _gnutls_buffer_append_prefix (buf, pfx_size, data_size);
679 if (ret1 < 0)
680 return gnutls_assert_val(ret1);
682 if (data_size > 0)
684 ret = _gnutls_buffer_append_data (buf, data, data_size);
686 if (ret < 0)
687 return gnutls_assert_val(ret);
690 return ret + ret1;
693 int _gnutls_buffer_append_mpi (gnutls_buffer_st * buf, int pfx_size, bigint_t mpi, int lz)
695 gnutls_datum_t dd;
696 int ret;
698 if (lz)
699 ret = _gnutls_mpi_dprint_lz (mpi, &dd);
700 else
701 ret = _gnutls_mpi_dprint (mpi, &dd);
703 if (ret < 0)
704 return gnutls_assert_val(ret);
706 ret = _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data, dd.size);
708 _gnutls_free_datum(&dd);
710 return ret;
714 _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void *data,
715 size_t * data_size)
717 size_t size;
718 int ret;
720 ret = _gnutls_buffer_pop_prefix (buf, &size, 1);
721 if (ret < 0)
723 gnutls_assert ();
724 return ret;
727 if (size > 0)
728 _gnutls_buffer_pop_data (buf, data, data_size);
730 return 0;
733 void
734 _gnutls_buffer_hexprint (gnutls_buffer_st * str,
735 const void *_data, size_t len)
737 size_t j;
738 const unsigned char* data = _data;
740 if (len == 0)
741 _gnutls_buffer_append_str (str, "00");
742 else
744 for (j = 0; j < len; j++)
745 _gnutls_buffer_append_printf (str, "%.2x", (unsigned) data[j]);
749 void
750 _gnutls_buffer_hexdump (gnutls_buffer_st * str, const void *_data, size_t len,
751 const char *spc)
753 size_t j;
754 const unsigned char* data = _data;
756 if (spc)
757 _gnutls_buffer_append_str (str, spc);
758 for (j = 0; j < len; j++)
760 if (((j + 1) % 16) == 0)
762 _gnutls_buffer_append_printf (str, "%.2x\n", (unsigned)data[j]);
763 if (spc && j != (len - 1))
764 _gnutls_buffer_append_str (str, spc);
766 else if (j == (len - 1))
767 _gnutls_buffer_append_printf (str, "%.2x", (unsigned)data[j]);
768 else
769 _gnutls_buffer_append_printf (str, "%.2x:", (unsigned)data[j]);
771 if ((j % 16) != 0)
772 _gnutls_buffer_append_str (str, "\n");
775 void
776 _gnutls_buffer_asciiprint (gnutls_buffer_st * str,
777 const char *data, size_t len)
779 size_t j;
781 for (j = 0; j < len; j++)
782 if (c_isprint (data[j]))
783 _gnutls_buffer_append_printf (str, "%c", (unsigned char) data[j]);
784 else
785 _gnutls_buffer_append_printf (str, ".");