2 * Copyright (C) 2002, 2004, 2005, 2007, 2008, 2009, 2010 Free Software
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
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.
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.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_num.h>
29 #include <gnutls_str.h>
33 /* These function are like strcat, strcpy. They only
34 * do bound checking (they shouldn't cause buffer overruns),
35 * and they always produce null terminated strings.
37 * They should be used only with null terminated strings.
40 _gnutls_str_cat (char *dest, size_t dest_tot_size, const char *src)
42 size_t str_size = strlen (src);
43 size_t dest_size = strlen (dest);
45 if (dest_tot_size - dest_size > str_size)
51 if (dest_tot_size - dest_size > 0)
53 strncat (dest, src, (dest_tot_size - dest_size) - 1);
54 dest[dest_tot_size - 1] = 0;
60 _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
62 size_t str_size = strlen (src);
64 if (dest_tot_size > str_size)
70 if (dest_tot_size > 0)
72 strncpy (dest, src, (dest_tot_size) - 1);
73 dest[dest_tot_size - 1] = 0;
79 _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
83 if (dest_tot_size >= src_size)
85 memcpy (dest, src, src_size);
89 if (dest_tot_size > 0)
91 memcpy (dest, src, dest_tot_size);
97 _gnutls_buffer_init (gnutls_buffer_st * str)
99 str->data = str->allocd = NULL;
105 _gnutls_buffer_clear (gnutls_buffer_st * str)
107 if (str == NULL || str->allocd == NULL)
109 gnutls_free (str->allocd);
111 str->data = str->allocd = NULL;
116 #define MIN_CHUNK 1024
119 _gnutls_buffer_append_data (gnutls_buffer_st * dest, const void *data,
122 size_t tot_len = data_size + dest->length;
124 if (dest->max_length >= tot_len)
126 size_t unused = MEMSUB (dest->data, dest->allocd);
128 if (dest->max_length - unused <= tot_len)
130 if (dest->length && dest->data)
131 memmove (dest->allocd, dest->data, dest->length);
133 dest->data = dest->allocd;
135 memmove (&dest->data[dest->length], data, data_size);
136 dest->length = tot_len;
142 size_t unused = MEMSUB (dest->data, dest->allocd);
144 MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
146 dest->allocd = gnutls_realloc (dest->allocd, new_len);
147 if (dest->allocd == NULL)
150 return GNUTLS_E_MEMORY_ERROR;
152 dest->max_length = new_len;
153 dest->data = dest->allocd + unused;
155 if (dest->length && dest->data)
156 memmove (dest->allocd, dest->data, dest->length);
157 dest->data = dest->allocd;
159 memcpy (&dest->data[dest->length], data, data_size);
160 dest->length = tot_len;
167 _gnutls_buffer_resize (gnutls_buffer_st * dest, size_t new_size)
169 if (dest->max_length >= new_size)
171 size_t unused = MEMSUB (dest->data, dest->allocd);
172 if (dest->max_length - unused <= new_size)
174 if (dest->length && dest->data)
175 memmove (dest->allocd, dest->data, dest->length);
176 dest->data = dest->allocd;
183 size_t unused = MEMSUB (dest->data, dest->allocd);
185 MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
187 dest->allocd = gnutls_realloc (dest->allocd, alloc_len);
188 if (dest->allocd == NULL)
191 return GNUTLS_E_MEMORY_ERROR;
193 dest->max_length = alloc_len;
194 dest->data = dest->allocd + unused;
196 if (dest->length && dest->data)
197 memmove (dest->allocd, dest->data, dest->length);
198 dest->data = dest->allocd;
205 _gnutls_buffer_append_str (gnutls_buffer_st * dest, const char *src)
207 return _gnutls_buffer_append_data (dest, src, strlen (src));
210 /* returns data from a string in a constant buffer.
211 * The data will NOT be valid if buffer is released or
212 * data are appended in the buffer.
215 _gnutls_buffer_pop_datum (gnutls_buffer_st * str, gnutls_datum_t * data,
219 if (str->length == 0)
226 if (req_size > str->length)
227 req_size = str->length;
229 data->data = str->data;
230 data->size = req_size;
232 str->data += req_size;
233 str->length -= req_size;
235 /* if string becomes empty start from begining */
236 if (str->length == 0)
238 str->data = str->allocd;
244 /* converts the buffer to a datum if possible. After this call the buffer
245 * is at an usable state and might not be used or deinitialized */
247 _gnutls_buffer_to_datum (gnutls_buffer_st * str, gnutls_datum_t * data)
250 if (str->length == 0)
257 if (str->allocd != str->data)
259 data->data = gnutls_malloc (str->length);
260 if (data->data == NULL)
263 return GNUTLS_E_MEMORY_ERROR;
265 memcpy (data->data, str->data, str->length);
266 data->size = str->length;
267 _gnutls_buffer_clear (str);
271 data->data = str->data;
272 data->size = str->length;
278 /* returns data from a string in a constant buffer.
281 _gnutls_buffer_pop_data (gnutls_buffer_st * str, void *data,
284 gnutls_datum_t tdata;
286 _gnutls_buffer_pop_datum (str, &tdata, *req_size);
288 *req_size = tdata.size;
289 memcpy (data, tdata.data, tdata.size);
295 _gnutls_buffer_append_printf (gnutls_buffer_st * dest, const char *fmt, ...)
301 va_start (args, fmt);
302 len = vasprintf (&str, fmt, args);
308 len = _gnutls_buffer_append_str (dest, str);
316 _gnutls_buffer_insert_data (gnutls_buffer_st * dest, int pos, const void *str,
319 size_t orig_length = dest->length;
322 ret = _gnutls_buffer_resize (dest, dest->length + str_size); /* resize to make space */
326 memmove (&dest->data[pos + str_size], &dest->data[pos], orig_length - pos);
328 memcpy (&dest->data[pos], str, str_size);
329 dest->length += str_size;
335 _gnutls_buffer_delete_data (gnutls_buffer_st * dest, int pos, size_t str_size)
337 memmove (&dest->data[pos], &dest->data[pos + str_size],
338 dest->length - pos - str_size);
340 dest->length -= str_size;
347 _gnutls_buffer_escape (gnutls_buffer_st * dest, int all,
348 const char *const invalid_chars)
354 while (pos < dest->length)
357 if (all != 0 || (dest->data[pos] == '\\' || strchr (invalid_chars, dest->data[pos])
358 || !c_isgraph (dest->data[pos])))
361 snprintf (t, sizeof (t), "%%%.2X", (unsigned int) dest->data[pos]);
363 _gnutls_buffer_delete_data (dest, pos, 1);
365 if (_gnutls_buffer_insert_data (dest, pos, t, 3) < 0)
384 _gnutls_buffer_unescape (gnutls_buffer_st * dest)
389 while (pos < dest->length)
391 if (dest->data[pos] == '%')
397 b[0] = dest->data[pos + 1];
398 b[1] = dest->data[pos + 2];
401 sscanf (b, "%02x", &u);
405 _gnutls_buffer_delete_data (dest, pos, 3);
406 _gnutls_buffer_insert_data (dest, pos, &x, 1);
417 /* Converts the given string (old) to hex. A buffer must be provided
418 * to hold the new hex string. The new string will be null terminated.
419 * If the buffer does not have enough space to hold the string, a
420 * truncated hex string is returned (always null terminated).
423 _gnutls_bin2hex (const void *_old, size_t oldlen,
424 char *buffer, size_t buffer_size, const char *separator)
427 const opaque *old = _old;
429 const char empty[] = "";
431 if (separator != NULL && separator[0] != 0)
443 sprintf (&buffer[j], "%.2x", old[i]);
447 for (; i < oldlen && j + step < buffer_size; j += step)
449 sprintf (&buffer[j], "%s%.2x", separator, old[i]);
459 * @hex_data: string with data in hex format
460 * @hex_size: size of hex data
461 * @bin_data: output array with binary data
462 * @bin_size: when calling *@bin_size should hold size of @bin_data,
463 * on return will hold actual size of @bin_data.
465 * Convert a buffer with hex data to binary data.
467 * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
472 gnutls_hex2bin (const char *hex_data,
473 size_t hex_size, char *bin_data, size_t * bin_size)
475 return _gnutls_hex2bin (hex_data, (int) hex_size, bin_data, bin_size);
479 _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
488 for (i = j = 0; i < hex_size;)
490 if (!isxdigit (hex_data[i])) /* skip non-hex such as the ':' in 00:FF */
499 return GNUTLS_E_SHORT_MEMORY_BUFFER;
502 hex2_data[0] = hex_data[i];
503 hex2_data[1] = hex_data[i + 1];
506 val = strtoul ((char *) hex2_data, NULL, 16);
507 if (val == ULONG_MAX)
510 return GNUTLS_E_PARSING_ERROR;
521 /* compare hostname against certificate, taking account of wildcards
522 * return 1 on success or 0 on error
524 * note: certnamesize is required as X509 certs can contain embedded NULs in
525 * the strings such as CN or subjectAltName.
527 * @level: is used for recursion. Use 0 when you call this function.
530 _gnutls_hostname_compare (const char *certname,
531 size_t certnamesize, const char *hostname, int level)
537 /* find the first different character */
538 for (; *certname && *hostname && c_toupper (*certname) == c_toupper (*hostname);
539 certname++, hostname++, certnamesize--)
542 /* the strings are the same */
543 if (certnamesize == 0 && *hostname == '\0')
546 if (*certname == '*')
548 /* a wildcard certificate */
555 /* Use a recursive call to allow multiple wildcards */
556 if (_gnutls_hostname_compare (certname, certnamesize, hostname, level+1))
559 /* wildcards are only allowed to match a single domain
560 component or component fragment */
561 if (*hostname == '\0' || *hostname == '.')
573 _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, size_t data_size)
576 _gnutls_write_uint32 (data_size, ss);
577 return _gnutls_buffer_append_data (buf, ss, 4);
580 /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
581 * the number read, is less than the data in the buffer
584 _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t * data_size,
592 return GNUTLS_E_PARSING_ERROR;
595 size = _gnutls_read_uint32 (buf->data);
596 if (check && size > buf->length - 4)
599 return GNUTLS_E_PARSING_ERROR;
611 _gnutls_buffer_pop_datum_prefix (gnutls_buffer_st * buf,
612 gnutls_datum_t * data)
617 ret = _gnutls_buffer_pop_prefix (buf, &size, 1);
627 _gnutls_buffer_pop_datum (buf, data, size);
628 if (osize != data->size)
631 return GNUTLS_E_PARSING_ERROR;
644 _gnutls_buffer_append_data_prefix (gnutls_buffer_st * buf, const void *data,
647 _gnutls_buffer_append_prefix (buf, data_size);
649 return _gnutls_buffer_append_data (buf, data, data_size);
655 _gnutls_buffer_pop_data_prefix (gnutls_buffer_st * buf, void *data,
661 ret = _gnutls_buffer_pop_prefix (buf, &size, 1);
669 _gnutls_buffer_pop_data (buf, data, data_size);