Update copyright years.
[gnutls.git] / lib / gnutls_str.c
blob02d629003c24d8ecd47f64830f2a721c0c993508
1 /*
2 * Copyright (C) 2002, 2004, 2005, 2007, 2008, 2009, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GNUTLS.
9 * The GNUTLS library 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,
22 * USA
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_num.h>
29 #include <gnutls_str.h>
30 #include <stdarg.h>
32 /* These function are like strcat, strcpy. They only
33 * do bound checking (they shouldn't cause buffer overruns),
34 * and they always produce null terminated strings.
36 * They should be used only with null terminated strings.
38 void
39 _gnutls_str_cat (char *dest, size_t dest_tot_size, const char *src)
41 size_t str_size = strlen (src);
42 size_t dest_size = strlen (dest);
44 if (dest_tot_size - dest_size > str_size)
46 strcat (dest, src);
48 else
50 if (dest_tot_size - dest_size > 0)
52 strncat (dest, src, (dest_tot_size - dest_size) - 1);
53 dest[dest_tot_size - 1] = 0;
58 void
59 _gnutls_str_cpy (char *dest, size_t dest_tot_size, const char *src)
61 size_t str_size = strlen (src);
63 if (dest_tot_size > str_size)
65 strcpy (dest, src);
67 else
69 if (dest_tot_size > 0)
71 strncpy (dest, src, (dest_tot_size) - 1);
72 dest[dest_tot_size - 1] = 0;
77 void
78 _gnutls_mem_cpy (char *dest, size_t dest_tot_size, const char *src,
79 size_t src_size)
82 if (dest_tot_size >= src_size)
84 memcpy (dest, src, src_size);
86 else
88 if (dest_tot_size > 0)
90 memcpy (dest, src, dest_tot_size);
95 void
96 _gnutls_string_init (gnutls_string * str,
97 gnutls_alloc_function alloc_func,
98 gnutls_realloc_function realloc_func,
99 gnutls_free_function free_func)
101 str->data = str->allocd = NULL;
102 str->max_length = 0;
103 str->length = 0;
105 str->alloc_func = alloc_func;
106 str->free_func = free_func;
107 str->realloc_func = realloc_func;
110 void
111 _gnutls_string_clear (gnutls_string * str)
113 if (str == NULL || str->allocd == NULL)
114 return;
115 str->free_func (str->allocd);
117 str->data = str->allocd = NULL;
118 str->max_length = 0;
119 str->length = 0;
122 #define MIN_CHUNK 256
125 _gnutls_string_append_data (gnutls_string * dest, const void *data,
126 size_t data_size)
128 size_t tot_len = data_size + dest->length;
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 = dest->realloc_func (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_string_resize (gnutls_string * 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 = dest->realloc_func (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_string_append_str (gnutls_string * dest, const char *src)
213 return _gnutls_string_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_string_get_datum (gnutls_string * 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 /* returns data from a string in a constant buffer.
252 void
253 _gnutls_string_get_data (gnutls_string * str, void *data, size_t * req_size)
255 gnutls_datum_t tdata;
257 _gnutls_string_get_datum (str, &tdata, *req_size);
259 *req_size = tdata.size;
260 memcpy (data, tdata.data, tdata.size);
262 return;
266 _gnutls_string_append_printf (gnutls_string * dest, const char *fmt, ...)
268 va_list args;
269 int len;
270 char *str;
272 va_start (args, fmt);
273 len = vasprintf (&str, fmt, args);
274 va_end (args);
276 if (len < 0 || !str)
277 return -1;
279 len = _gnutls_string_append_str (dest, str);
281 free (str);
283 return len;
286 /* Converts the given string (old) to hex. A buffer must be provided
287 * to hold the new hex string. The new string will be null terminated.
288 * If the buffer does not have enough space to hold the string, a
289 * truncated hex string is returned (always null terminated).
291 char *
292 _gnutls_bin2hex (const void *_old, size_t oldlen,
293 char *buffer, size_t buffer_size)
295 unsigned int i, j;
296 const opaque *old = _old;
298 for (i = j = 0; i < oldlen && j + 2 < buffer_size; j += 2)
300 sprintf (&buffer[j], "%.2x", old[i]);
301 i++;
303 buffer[j] = '\0';
305 return buffer;
309 * gnutls_hex2bin - convert hex string into binary buffer.
310 * @hex_data: string with data in hex format
311 * @hex_size: size of hex data
312 * @bin_data: output array with binary data
313 * @bin_size: when calling *@bin_size should hold size of @bin_data,
314 * on return will hold actual size of @bin_data.
316 * Convert a buffer with hex data to binary data.
318 * Returns: %GNUTLS_E_SUCCESS on success, otherwise an error.
320 * Since: 2.4.0
323 gnutls_hex2bin (const char *hex_data,
324 size_t hex_size, char *bin_data, size_t * bin_size)
326 return _gnutls_hex2bin (hex_data, (int) hex_size, bin_data, bin_size);
330 _gnutls_hex2bin (const opaque * hex_data, int hex_size, opaque * bin_data,
331 size_t * bin_size)
333 int i, j;
334 opaque hex2_data[3];
335 unsigned long val;
337 /* FIXME: we don't handle whitespace.
339 hex_size /= 2;
341 if (*bin_size < (size_t) hex_size)
343 gnutls_assert ();
344 return GNUTLS_E_SHORT_MEMORY_BUFFER;
347 for (i = j = 0; j < hex_size; i += 2, j++)
349 hex2_data[0] = hex_data[i];
350 hex2_data[1] = hex_data[i + 1];
351 hex2_data[2] = 0;
352 val = strtoul ((char *) hex2_data, NULL, 16);
353 if (val == ULONG_MAX)
355 gnutls_assert ();
356 return GNUTLS_E_SRP_PWD_PARSING_ERROR;
358 bin_data[j] = val;
361 return 0;
365 /* compare hostname against certificate, taking account of wildcards
366 * return 1 on success or 0 on error
368 * note: certnamesize is required as X509 certs can contain embedded NULs in
369 * the strings such as CN or subjectAltName
372 _gnutls_hostname_compare (const char *certname,
373 size_t certnamesize, const char *hostname)
375 /* find the first different character */
376 for (; *certname && *hostname && toupper (*certname) == toupper (*hostname);
377 certname++, hostname++, certnamesize--)
380 /* the strings are the same */
381 if (certnamesize == 0 && *hostname == '\0')
382 return 1;
384 if (*certname == '*')
386 /* a wildcard certificate */
388 certname++;
389 certnamesize--;
391 while (1)
393 /* Use a recursive call to allow multiple wildcards */
394 if (_gnutls_hostname_compare (certname, certnamesize, hostname))
395 return 1;
397 /* wildcards are only allowed to match a single domain
398 component or component fragment */
399 if (*hostname == '\0' || *hostname == '.')
400 break;
401 hostname++;
404 return 0;
407 return 0;