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 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,
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_num.h>
29 #include <gnutls_str.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.
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
)
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;
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
)
69 if (dest_tot_size
> 0)
71 strncpy (dest
, src
, (dest_tot_size
) - 1);
72 dest
[dest_tot_size
- 1] = 0;
78 _gnutls_mem_cpy (char *dest
, size_t dest_tot_size
, const char *src
,
82 if (dest_tot_size
>= src_size
)
84 memcpy (dest
, src
, src_size
);
88 if (dest_tot_size
> 0)
90 memcpy (dest
, src
, dest_tot_size
);
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
;
105 str
->alloc_func
= alloc_func
;
106 str
->free_func
= free_func
;
107 str
->realloc_func
= realloc_func
;
111 _gnutls_string_clear (gnutls_string
* str
)
113 if (str
== NULL
|| str
->allocd
== NULL
)
115 str
->free_func (str
->allocd
);
117 str
->data
= str
->allocd
= NULL
;
122 #define MIN_CHUNK 256
125 _gnutls_string_append_data (gnutls_string
* dest
, const void *data
,
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
;
148 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
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
)
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
;
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
;
189 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
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
)
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
;
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.
221 _gnutls_string_get_datum (gnutls_string
* str
, gnutls_datum_t
* data
,
225 if (str
->length
== 0)
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
;
250 /* returns data from a string in a constant buffer.
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
);
266 _gnutls_string_append_printf (gnutls_string
* dest
, const char *fmt
, ...)
272 va_start (args
, fmt
);
273 len
= vasprintf (&str
, fmt
, args
);
279 len
= _gnutls_string_append_str (dest
, str
);
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).
292 _gnutls_bin2hex (const void *_old
, size_t oldlen
,
293 char *buffer
, size_t buffer_size
)
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
]);
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.
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
,
337 /* FIXME: we don't handle whitespace.
341 if (*bin_size
< (size_t) hex_size
)
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];
352 val
= strtoul ((char *) hex2_data
, NULL
, 16);
353 if (val
== ULONG_MAX
)
356 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
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')
384 if (*certname
== '*')
386 /* a wildcard certificate */
393 /* Use a recursive call to allow multiple wildcards */
394 if (_gnutls_hostname_compare (certname
, certnamesize
, hostname
))
397 /* wildcards are only allowed to match a single domain
398 component or component fragment */
399 if (*hostname
== '\0' || *hostname
== '.')