Fix --disable-valgrind-tests.
[gnutls.git] / lib / gnutls_str.c
blob4586b4b1ceabfe0d4b445b759535dca7b887e1a5
1 /*
2 * Copyright (C) 2002, 2004, 2005, 2007, 2008, 2009 Free Software Foundation
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GNUTLS.
8 * The GNUTLS library 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 2.1 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
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
21 * USA
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
27 #include <gnutls_num.h>
28 #include <gnutls_str.h>
29 #include <stdarg.h>
31 /* These function are like strcat, strcpy. They only
32 * do bound checking (they shouldn't cause buffer overruns),
33 * and they always produce null terminated strings.
35 * They should be used only with null terminated strings.
37 void
38 _gnutls_str_cat (char *dest, size_t dest_tot_size, const char *src)
40 size_t str_size = strlen (src);
41 size_t dest_size = strlen (dest);
43 if (dest_tot_size - dest_size > str_size)
45 strcat (dest, src);
47 else
49 if (dest_tot_size - dest_size > 0)
51 strncat (dest, src, (dest_tot_size - dest_size) - 1);
52 dest[dest_tot_size - 1] = 0;
57 void
58 _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
60 size_t str_size = strlen (src);
62 if (dest_tot_size > str_size)
64 strcpy (dest, src);
66 else
68 if (dest_tot_size > 0)
70 strncpy (dest, src, (dest_tot_size) - 1);
71 dest[dest_tot_size - 1] = 0;
76 void
77 _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
78 size_t src_size)
81 if (dest_tot_size >= src_size)
83 memcpy (dest, src, src_size);
85 else
87 if (dest_tot_size > 0)
89 memcpy (dest, src, dest_tot_size);
94 void
95 _gnutls_string_init (gnutls_string * str,
96 gnutls_alloc_function alloc_func,
97 gnutls_realloc_function realloc_func,
98 gnutls_free_function free_func)
100 str->data = str->allocd = NULL;
101 str->max_length = 0;
102 str->length = 0;
104 str->alloc_func = alloc_func;
105 str->free_func = free_func;
106 str->realloc_func = realloc_func;
109 void
110 _gnutls_string_clear (gnutls_string * str)
112 if (str == NULL || str->allocd == NULL)
113 return;
114 str->free_func (str->allocd);
116 str->data = str->allocd = NULL;
117 str->max_length = 0;
118 str->length = 0;
121 #define MIN_CHUNK 256
124 _gnutls_string_append_data (gnutls_string * dest, const void *data,
125 size_t data_size)
127 size_t tot_len = data_size + dest->length;
129 if (dest->max_length >= tot_len)
131 size_t unused = MEMSUB (dest->data, dest->allocd);
133 if (dest->max_length - unused <= tot_len)
135 if (dest->length && dest->data)
136 memmove (dest->allocd, dest->data, dest->length);
138 dest->data = dest->allocd;
140 memmove (&dest->data[dest->length], data, data_size);
141 dest->length = tot_len;
143 return tot_len;
145 else
147 size_t unused = MEMSUB (dest->data, dest->allocd);
148 size_t new_len =
149 MAX (data_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
151 dest->allocd = dest->realloc_func (dest->allocd, new_len);
152 if (dest->allocd == NULL)
154 gnutls_assert ();
155 return GNUTLS_E_MEMORY_ERROR;
157 dest->max_length = new_len;
158 dest->data = dest->allocd + unused;
160 if (dest->length && dest->data)
161 memmove (dest->allocd, dest->data, dest->length);
162 dest->data = dest->allocd;
164 memcpy (&dest->data[dest->length], data, data_size);
165 dest->length = tot_len;
167 return tot_len;
172 _gnutls_string_resize (gnutls_string * dest, size_t new_size)
174 if (dest->max_length >= new_size)
176 size_t unused = MEMSUB (dest->data, dest->allocd);
177 if (dest->max_length - unused <= new_size)
179 if (dest->length && dest->data)
180 memmove (dest->allocd, dest->data, dest->length);
181 dest->data = dest->allocd;
184 return 0;
186 else
188 size_t unused = MEMSUB (dest->data, dest->allocd);
189 size_t alloc_len =
190 MAX (new_size, MIN_CHUNK) + MAX (dest->max_length, MIN_CHUNK);
192 dest->allocd = dest->realloc_func (dest->allocd, alloc_len);
193 if (dest->allocd == NULL)
195 gnutls_assert ();
196 return GNUTLS_E_MEMORY_ERROR;
198 dest->max_length = alloc_len;
199 dest->data = dest->allocd + unused;
201 if (dest->length && dest->data)
202 memmove (dest->allocd, dest->data, dest->length);
203 dest->data = dest->allocd;
205 return 0;
210 _gnutls_string_append_str (gnutls_string * dest, const char *src)
212 return _gnutls_string_append_data (dest, src, strlen (src));
215 /* returns data from a string in a constant buffer.
216 * The data will NOT be valid if buffer is released or
217 * data are appended in the buffer.
219 void
220 _gnutls_string_get_datum (gnutls_string * str, gnutls_datum_t * data,
221 size_t req_size)
224 if (str->length == 0)
226 data->data = NULL;
227 data->size = 0;
228 return;
231 if (req_size > str->length)
232 req_size = str->length;
234 data->data = str->data;
235 data->size = req_size;
237 str->data += req_size;
238 str->length -= req_size;
240 /* if string becomes empty start from begining */
241 if (str->length == 0)
243 str->data = str->allocd;
246 return;
249 /* returns data from a string in a constant buffer.
251 void
252 _gnutls_string_get_data (gnutls_string * str, void *data, size_t * req_size)
254 gnutls_datum_t tdata;
256 _gnutls_string_get_datum (str, &tdata, *req_size);
258 *req_size = tdata.size;
259 memcpy (data, tdata.data, tdata.size);
261 return;
265 _gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
267 va_list args;
268 int len;
269 char *str;
271 va_start (args, fmt);
272 len = vasprintf (&str, fmt, args);
273 va_end (args);
275 if (len < 0 || !str)
276 return -1;
278 len = _gnutls_string_append_str (dest, str);
280 free (str);
282 return len;
285 /* Converts the given string (old) to hex. A buffer must be provided
286 * to hold the new hex string. The new string will be null terminated.
287 * If the buffer does not have enough space to hold the string, a
288 * truncated hex string is returned (always null terminated).
290 char *
291 _gnutls_bin2hex (const void *_old, size_t oldlen,
292 char *buffer, size_t buffer_size)
294 unsigned int i, j;
295 const opaque *old = _old;
297 for (i = j = 0; i < oldlen && j + 2 < buffer_size; j += 2)
299 sprintf (&buffer[j], "%.2x", old[i]);
300 i++;
302 buffer[j] = '\0';
304 return buffer;
308 * gnutls_hex2bin - convert hex string into binary buffer.
309 * @hex_data: string with data in hex format
310 * @hex_size: size of hex data
311 * @bin_data: output array with binary data
312 * @bin_size: when calling *@bin_size should hold size of @bin_data,
313 * on return will hold actual size of @bin_data.
315 * Convert a buffer with hex data to binary data.
317 * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
319 * Since: 2.4.0
322 gnutls_hex2bin (const char *hex_data,
323 size_t hex_size, char *bin_data, size_t * bin_size)
325 return _gnutls_hex2bin (hex_data, (int) hex_size, bin_data, bin_size);
329 _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
330 size_t * bin_size)
332 int i, j;
333 opaque hex2_data[3];
334 unsigned long val;
336 /* FIXME: we don't handle whitespace.
338 hex_size /= 2;
340 if (*bin_size < (size_t) hex_size)
342 gnutls_assert ();
343 return GNUTLS_E_SHORT_MEMORY_BUFFER;
346 for (i = j = 0; j < hex_size; i += 2, j++)
348 hex2_data[0] = hex_data[i];
349 hex2_data[1] = hex_data[i + 1];
350 hex2_data[2] = 0;
351 val = strtoul ((char *) hex2_data, NULL, 16);
352 if (val == ULONG_MAX)
354 gnutls_assert ();
355 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
357 bin_data[j] = val;
360 return 0;
364 /* compare hostname against certificate, taking account of wildcards
365 * return 1 on success or 0 on error
367 * note: certnamesize is required as X509 certs can contain embedded NULs in
368 * the strings such as CN or subjectAltName
371 _gnutls_hostname_compare (const char *certname,
372 size_t certnamesize, const char *hostname)
374 /* find the first different character */
375 for (; *certname && *hostname && toupper (*certname) == toupper (*hostname);
376 certname++, hostname++, certnamesize--)
379 /* the strings are the same */
380 if (certnamesize == 0 && *hostname == '\0')
381 return 1;
383 if (*certname == '*')
385 /* a wildcard certificate */
387 certname++;
388 certnamesize--;
390 while (1)
392 /* Use a recursive call to allow multiple wildcards */
393 if (_gnutls_hostname_compare (certname, certnamesize, hostname))
394 return 1;
396 /* wildcards are only allowed to match a single domain
397 component or component fragment */
398 if (*hostname == '\0' || *hostname == '.')
399 break;
400 hostname++;
403 return 0;
406 return 0;