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,
25 #include <gnutls_int.h>
26 #include <gnutls_errors.h>
27 #include <gnutls_num.h>
28 #include <gnutls_str.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.
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
)
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;
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
)
68 if (dest_tot_size
> 0)
70 strncpy (dest
, src
, (dest_tot_size
) - 1);
71 dest
[dest_tot_size
- 1] = 0;
77 _gnutls_mem_cpy (char *dest
, size_t dest_tot_size
, const char *src
,
81 if (dest_tot_size
>= src_size
)
83 memcpy (dest
, src
, src_size
);
87 if (dest_tot_size
> 0)
89 memcpy (dest
, src
, dest_tot_size
);
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
;
104 str
->alloc_func
= alloc_func
;
105 str
->free_func
= free_func
;
106 str
->realloc_func
= realloc_func
;
110 _gnutls_string_clear (gnutls_string
* str
)
112 if (str
== NULL
|| str
->allocd
== NULL
)
114 str
->free_func (str
->allocd
);
116 str
->data
= str
->allocd
= NULL
;
121 #define MIN_CHUNK 256
124 _gnutls_string_append_data (gnutls_string
* dest
, const void *data
,
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
;
147 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
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
)
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
;
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
;
188 size_t unused
= MEMSUB (dest
->data
, dest
->allocd
);
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
)
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
;
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.
220 _gnutls_string_get_datum (gnutls_string
* str
, gnutls_datum_t
* data
,
224 if (str
->length
== 0)
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
;
249 /* returns data from a string in a constant buffer.
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
);
265 _gnutls_string_append_printf (gnutls_string
* dest
, const char *fmt
, ...)
271 va_start (args
, fmt
);
272 len
= vasprintf (&str
, fmt
, args
);
278 len
= _gnutls_string_append_str (dest
, str
);
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).
291 _gnutls_bin2hex (const void *_old
, size_t oldlen
,
292 char *buffer
, size_t buffer_size
)
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
]);
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.
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
,
336 /* FIXME: we don't handle whitespace.
340 if (*bin_size
< (size_t) hex_size
)
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];
351 val
= strtoul ((char *) hex2_data
, NULL
, 16);
352 if (val
== ULONG_MAX
)
355 return GNUTLS_E_SRP_PWD_PARSING_ERROR
;
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')
383 if (*certname
== '*')
385 /* a wildcard certificate */
392 /* Use a recursive call to allow multiple wildcards */
393 if (_gnutls_hostname_compare (certname
, certnamesize
, hostname
))
396 /* wildcards are only allowed to match a single domain
397 component or component fragment */
398 if (*hostname
== '\0' || *hostname
== '.')