PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/gnutls_str.c

https://gitlab.com/axil/gnutls
C | 821 lines | 574 code | 143 blank | 104 comment | 137 complexity | cf171ba72a5ce241996cdf971f5ea725 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0, LGPL-2.1, LGPL-2.0
  1. /*
  2. * Copyright (C) 2002-2012 Free Software Foundation, Inc.
  3. *
  4. * Author: Nikos Mavrogiannopoulos
  5. *
  6. * This file is part of GnuTLS.
  7. *
  8. * The GnuTLS 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.
  12. *
  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.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>
  20. *
  21. */
  22. #include <gnutls_int.h>
  23. #include <gnutls_errors.h>
  24. #include <gnutls_num.h>
  25. #include <gnutls_str.h>
  26. #include <stdarg.h>
  27. #include <c-ctype.h>
  28. #include "vasprintf.h"
  29. /* These functions are like strcat, strcpy. They only
  30. * do bound checking (they shouldn't cause buffer overruns),
  31. * and they always produce null terminated strings.
  32. *
  33. * They should be used only with null terminated strings.
  34. */
  35. void _gnutls_str_cat(char *dest, size_t dest_tot_size, const char *src)
  36. {
  37. size_t str_size = strlen(src);
  38. size_t dest_size = strlen(dest);
  39. if (dest_tot_size - dest_size > str_size) {
  40. strcat(dest, src);
  41. } else {
  42. if (dest_tot_size - dest_size > 0) {
  43. strncat(dest, src,
  44. (dest_tot_size - dest_size) - 1);
  45. dest[dest_tot_size - 1] = 0;
  46. }
  47. }
  48. }
  49. void _gnutls_str_cpy(char *dest, size_t dest_tot_size, const char *src)
  50. {
  51. size_t str_size = strlen(src);
  52. if (dest_tot_size > str_size) {
  53. strcpy(dest, src);
  54. } else {
  55. if (dest_tot_size > 0) {
  56. strncpy(dest, src, (dest_tot_size) - 1);
  57. dest[dest_tot_size - 1] = 0;
  58. }
  59. }
  60. }
  61. void
  62. _gnutls_mem_cpy(char *dest, size_t dest_tot_size, const char *src,
  63. size_t src_size)
  64. {
  65. if (dest_tot_size >= src_size) {
  66. memcpy(dest, src, src_size);
  67. } else {
  68. if (dest_tot_size > 0) {
  69. memcpy(dest, src, dest_tot_size);
  70. }
  71. }
  72. }
  73. void _gnutls_buffer_init(gnutls_buffer_st * str)
  74. {
  75. str->data = str->allocd = NULL;
  76. str->max_length = 0;
  77. str->length = 0;
  78. }
  79. void _gnutls_buffer_replace_data(gnutls_buffer_st * buf,
  80. gnutls_datum_t * data)
  81. {
  82. gnutls_free(buf->allocd);
  83. buf->allocd = buf->data = data->data;
  84. buf->max_length = buf->length = data->size;
  85. }
  86. void _gnutls_buffer_clear(gnutls_buffer_st * str)
  87. {
  88. if (str == NULL || str->allocd == NULL)
  89. return;
  90. gnutls_free(str->allocd);
  91. str->data = str->allocd = NULL;
  92. str->max_length = 0;
  93. str->length = 0;
  94. }
  95. #define MIN_CHUNK 1024
  96. int
  97. _gnutls_buffer_append_data(gnutls_buffer_st * dest, const void *data,
  98. size_t data_size)
  99. {
  100. size_t tot_len = data_size + dest->length;
  101. if (data_size == 0)
  102. return 0;
  103. if (dest->max_length >= tot_len) {
  104. size_t unused = MEMSUB(dest->data, dest->allocd);
  105. if (dest->max_length - unused <= tot_len) {
  106. if (dest->length && dest->data)
  107. memmove(dest->allocd, dest->data,
  108. dest->length);
  109. dest->data = dest->allocd;
  110. }
  111. memmove(&dest->data[dest->length], data, data_size);
  112. dest->length = tot_len;
  113. return tot_len;
  114. } else {
  115. size_t unused = MEMSUB(dest->data, dest->allocd);
  116. size_t new_len =
  117. MAX(data_size, MIN_CHUNK) + MAX(dest->max_length,
  118. MIN_CHUNK);
  119. dest->allocd = gnutls_realloc_fast(dest->allocd, new_len);
  120. if (dest->allocd == NULL) {
  121. gnutls_assert();
  122. return GNUTLS_E_MEMORY_ERROR;
  123. }
  124. dest->max_length = new_len;
  125. dest->data = dest->allocd + unused;
  126. if (dest->length && dest->data)
  127. memmove(dest->allocd, dest->data, dest->length);
  128. dest->data = dest->allocd;
  129. memcpy(&dest->data[dest->length], data, data_size);
  130. dest->length = tot_len;
  131. return tot_len;
  132. }
  133. }
  134. int _gnutls_buffer_resize(gnutls_buffer_st * dest, size_t new_size)
  135. {
  136. if (dest->max_length >= new_size) {
  137. size_t unused = MEMSUB(dest->data, dest->allocd);
  138. if (dest->max_length - unused <= new_size) {
  139. if (dest->length && dest->data)
  140. memmove(dest->allocd, dest->data,
  141. dest->length);
  142. dest->data = dest->allocd;
  143. }
  144. return 0;
  145. } else {
  146. size_t unused = MEMSUB(dest->data, dest->allocd);
  147. size_t alloc_len =
  148. MAX(new_size, MIN_CHUNK) + MAX(dest->max_length,
  149. MIN_CHUNK);
  150. dest->allocd =
  151. gnutls_realloc_fast(dest->allocd, alloc_len);
  152. if (dest->allocd == NULL) {
  153. gnutls_assert();
  154. return GNUTLS_E_MEMORY_ERROR;
  155. }
  156. dest->max_length = alloc_len;
  157. dest->data = dest->allocd + unused;
  158. if (dest->length && dest->data)
  159. memmove(dest->allocd, dest->data, dest->length);
  160. dest->data = dest->allocd;
  161. return 0;
  162. }
  163. }
  164. /* Appends the provided string. The null termination byte is appended
  165. * but not included in length.
  166. */
  167. int _gnutls_buffer_append_str(gnutls_buffer_st * dest, const char *src)
  168. {
  169. int ret;
  170. ret = _gnutls_buffer_append_data(dest, src, strlen(src) + 1);
  171. if (ret >= 0)
  172. dest->length--;
  173. return ret;
  174. }
  175. /* returns data from a string in a constant buffer.
  176. * The data will NOT be valid if buffer is released or
  177. * data are appended in the buffer.
  178. */
  179. void
  180. _gnutls_buffer_pop_datum(gnutls_buffer_st * str, gnutls_datum_t * data,
  181. size_t req_size)
  182. {
  183. if (str->length == 0) {
  184. data->data = NULL;
  185. data->size = 0;
  186. return;
  187. }
  188. if (req_size > str->length)
  189. req_size = str->length;
  190. data->data = str->data;
  191. data->size = req_size;
  192. str->data += req_size;
  193. str->length -= req_size;
  194. /* if string becomes empty start from begining */
  195. if (str->length == 0) {
  196. str->data = str->allocd;
  197. }
  198. return;
  199. }
  200. /* converts the buffer to a datum if possible. After this call
  201. * (failed or not) the buffer should be considered deinitialized.
  202. */
  203. int _gnutls_buffer_to_datum(gnutls_buffer_st * str, gnutls_datum_t * data)
  204. {
  205. if (str->length == 0) {
  206. data->data = NULL;
  207. data->size = 0;
  208. _gnutls_buffer_clear(str);
  209. return 0;
  210. }
  211. if (str->allocd != str->data) {
  212. data->data = gnutls_malloc(str->length);
  213. if (data->data == NULL) {
  214. gnutls_assert();
  215. _gnutls_buffer_clear(str);
  216. return GNUTLS_E_MEMORY_ERROR;
  217. }
  218. memcpy(data->data, str->data, str->length);
  219. data->size = str->length;
  220. _gnutls_buffer_clear(str);
  221. } else {
  222. data->data = str->data;
  223. data->size = str->length;
  224. _gnutls_buffer_init(str);
  225. }
  226. return 0;
  227. }
  228. /* returns data from a string in a constant buffer.
  229. */
  230. void
  231. _gnutls_buffer_pop_data(gnutls_buffer_st * str, void *data,
  232. size_t * req_size)
  233. {
  234. gnutls_datum_t tdata;
  235. _gnutls_buffer_pop_datum(str, &tdata, *req_size);
  236. if (tdata.data == NULL) {
  237. *req_size = 0;
  238. return;
  239. }
  240. *req_size = tdata.size;
  241. memcpy(data, tdata.data, tdata.size);
  242. return;
  243. }
  244. int
  245. _gnutls_buffer_append_printf(gnutls_buffer_st * dest, const char *fmt, ...)
  246. {
  247. va_list args;
  248. int len;
  249. char *str;
  250. va_start(args, fmt);
  251. len = vasprintf(&str, fmt, args);
  252. va_end(args);
  253. if (len < 0 || !str)
  254. return -1;
  255. len = _gnutls_buffer_append_str(dest, str);
  256. free(str);
  257. return len;
  258. }
  259. static int
  260. _gnutls_buffer_insert_data(gnutls_buffer_st * dest, int pos,
  261. const void *str, size_t str_size)
  262. {
  263. size_t orig_length = dest->length;
  264. int ret;
  265. ret = _gnutls_buffer_resize(dest, dest->length + str_size); /* resize to make space */
  266. if (ret < 0)
  267. return ret;
  268. memmove(&dest->data[pos + str_size], &dest->data[pos],
  269. orig_length - pos);
  270. memcpy(&dest->data[pos], str, str_size);
  271. dest->length += str_size;
  272. return 0;
  273. }
  274. static void
  275. _gnutls_buffer_delete_data(gnutls_buffer_st * dest, int pos,
  276. size_t str_size)
  277. {
  278. memmove(&dest->data[pos], &dest->data[pos + str_size],
  279. dest->length - pos - str_size);
  280. dest->length -= str_size;
  281. return;
  282. }
  283. int
  284. _gnutls_buffer_escape(gnutls_buffer_st * dest, int all,
  285. const char *const invalid_chars)
  286. {
  287. int rv = -1;
  288. char t[5];
  289. unsigned int pos = 0;
  290. while (pos < dest->length) {
  291. if (all != 0
  292. || (dest->data[pos] == '\\'
  293. || strchr(invalid_chars, dest->data[pos])
  294. || !c_isgraph(dest->data[pos]))) {
  295. snprintf(t, sizeof(t), "%%%.2X",
  296. (unsigned int) dest->data[pos]);
  297. _gnutls_buffer_delete_data(dest, pos, 1);
  298. if (_gnutls_buffer_insert_data(dest, pos, t, 3) <
  299. 0) {
  300. rv = -1;
  301. goto cleanup;
  302. }
  303. pos += 3;
  304. } else
  305. pos++;
  306. }
  307. rv = 0;
  308. cleanup:
  309. return rv;
  310. }
  311. int _gnutls_buffer_unescape(gnutls_buffer_st * dest)
  312. {
  313. int rv = -1;
  314. unsigned int pos = 0;
  315. while (pos < dest->length) {
  316. if (dest->data[pos] == '%') {
  317. char b[3];
  318. unsigned int u;
  319. unsigned char x;
  320. b[0] = dest->data[pos + 1];
  321. b[1] = dest->data[pos + 2];
  322. b[2] = 0;
  323. sscanf(b, "%02x", &u);
  324. x = u;
  325. _gnutls_buffer_delete_data(dest, pos, 3);
  326. _gnutls_buffer_insert_data(dest, pos, &x, 1);
  327. }
  328. pos++;
  329. }
  330. rv = 0;
  331. return rv;
  332. }
  333. /* Converts the given string (old) to hex. A buffer must be provided
  334. * to hold the new hex string. The new string will be null terminated.
  335. * If the buffer does not have enough space to hold the string, a
  336. * truncated hex string is returned (always null terminated).
  337. */
  338. char *_gnutls_bin2hex(const void *_old, size_t oldlen,
  339. char *buffer, size_t buffer_size,
  340. const char *separator)
  341. {
  342. unsigned int i, j;
  343. const uint8_t *old = _old;
  344. int step = 2;
  345. const char empty[] = "";
  346. if (separator != NULL && separator[0] != 0)
  347. step = 3;
  348. else
  349. separator = empty;
  350. if (buffer_size < 3) {
  351. gnutls_assert();
  352. return NULL;
  353. }
  354. i = j = 0;
  355. sprintf(&buffer[j], "%.2x", old[i]);
  356. j += 2;
  357. i++;
  358. for (; i < oldlen && j + step < buffer_size; j += step) {
  359. sprintf(&buffer[j], "%s%.2x", separator, old[i]);
  360. i++;
  361. }
  362. buffer[j] = '\0';
  363. return buffer;
  364. }
  365. /**
  366. * gnutls_hex2bin:
  367. * @hex_data: string with data in hex format
  368. * @hex_size: size of hex data
  369. * @bin_data: output array with binary data
  370. * @bin_size: when calling should hold maximum size of @bin_data,
  371. * on return will hold actual length of @bin_data.
  372. *
  373. * Convert a buffer with hex data to binary data.
  374. *
  375. * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
  376. *
  377. * Since: 2.4.0
  378. **/
  379. int
  380. gnutls_hex2bin(const char *hex_data,
  381. size_t hex_size, void *bin_data, size_t * bin_size)
  382. {
  383. return _gnutls_hex2bin(hex_data, hex_size, (void *) bin_data,
  384. bin_size);
  385. }
  386. int
  387. _gnutls_hex2bin(const char *hex_data, size_t hex_size, uint8_t * bin_data,
  388. size_t * bin_size)
  389. {
  390. unsigned int i, j;
  391. uint8_t hex2_data[3];
  392. unsigned long val;
  393. hex2_data[2] = 0;
  394. for (i = j = 0; i < hex_size;) {
  395. if (!isxdigit(hex_data[i])) { /* skip non-hex such as the ':' in 00:FF */
  396. i++;
  397. continue;
  398. }
  399. if (j > *bin_size) {
  400. gnutls_assert();
  401. return GNUTLS_E_SHORT_MEMORY_BUFFER;
  402. }
  403. hex2_data[0] = hex_data[i];
  404. hex2_data[1] = hex_data[i + 1];
  405. i += 2;
  406. val = strtoul((char *) hex2_data, NULL, 16);
  407. if (val == ULONG_MAX) {
  408. gnutls_assert();
  409. return GNUTLS_E_PARSING_ERROR;
  410. }
  411. bin_data[j] = val;
  412. j++;
  413. }
  414. *bin_size = j;
  415. return 0;
  416. }
  417. /**
  418. * gnutls_hex_decode:
  419. * @hex_data: contain the encoded data
  420. * @result: the place where decoded data will be copied
  421. * @result_size: holds the size of the result
  422. *
  423. * This function will decode the given encoded data, using the hex
  424. * encoding used by PSK password files.
  425. *
  426. * Note that hex_data should be null terminated.
  427. *
  428. * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
  429. * long enough, or 0 on success.
  430. **/
  431. int
  432. gnutls_hex_decode(const gnutls_datum_t * hex_data, void *result,
  433. size_t * result_size)
  434. {
  435. int ret;
  436. ret =
  437. _gnutls_hex2bin((char *) hex_data->data, hex_data->size,
  438. (uint8_t *) result, result_size);
  439. if (ret < 0)
  440. return ret;
  441. return 0;
  442. }
  443. /**
  444. * gnutls_hex_encode:
  445. * @data: contain the raw data
  446. * @result: the place where hex data will be copied
  447. * @result_size: holds the size of the result
  448. *
  449. * This function will convert the given data to printable data, using
  450. * the hex encoding, as used in the PSK password files.
  451. *
  452. * Note that the size of the result includes the null terminator.
  453. *
  454. * Returns: %GNUTLS_E_SHORT_MEMORY_BUFFER if the buffer given is not
  455. * long enough, or 0 on success.
  456. **/
  457. int
  458. gnutls_hex_encode(const gnutls_datum_t * data, char *result,
  459. size_t * result_size)
  460. {
  461. size_t res = data->size + data->size + 1;
  462. if (*result_size < res) {
  463. gnutls_assert();
  464. return GNUTLS_E_SHORT_MEMORY_BUFFER;
  465. }
  466. _gnutls_bin2hex(data->data, data->size, result, *result_size,
  467. NULL);
  468. *result_size = res;
  469. return 0;
  470. }
  471. /* compare hostname against certificate, taking account of wildcards
  472. * return 1 on success or 0 on error
  473. *
  474. * note: certnamesize is required as X509 certs can contain embedded NULs in
  475. * the strings such as CN or subjectAltName.
  476. *
  477. * @level: is used for recursion. Use 0 when you call this function.
  478. */
  479. int
  480. _gnutls_hostname_compare(const char *certname,
  481. size_t certnamesize, const char *hostname,
  482. int level)
  483. {
  484. if (level > 5)
  485. return 0;
  486. /* find the first different character */
  487. for (;
  488. *certname && *hostname
  489. && c_toupper(*certname) == c_toupper(*hostname);
  490. certname++, hostname++, certnamesize--);
  491. /* the strings are the same */
  492. if (certnamesize == 0 && *hostname == '\0')
  493. return 1;
  494. if (*certname == '*') {
  495. /* a wildcard certificate */
  496. certname++;
  497. certnamesize--;
  498. while (1) {
  499. /* Use a recursive call to allow multiple wildcards */
  500. if (_gnutls_hostname_compare
  501. (certname, certnamesize, hostname, level + 1))
  502. return 1;
  503. /* wildcards are only allowed to match a single domain
  504. component or component fragment */
  505. if (*hostname == '\0' || *hostname == '.')
  506. break;
  507. hostname++;
  508. }
  509. return 0;
  510. }
  511. return 0;
  512. }
  513. int
  514. _gnutls_buffer_append_prefix(gnutls_buffer_st * buf, int pfx_size,
  515. size_t data_size)
  516. {
  517. uint8_t ss[4];
  518. if (pfx_size == 32) {
  519. _gnutls_write_uint32(data_size, ss);
  520. pfx_size = 4;
  521. } else if (pfx_size == 24) {
  522. _gnutls_write_uint24(data_size, ss);
  523. pfx_size = 3;
  524. } else if (pfx_size == 16) {
  525. _gnutls_write_uint16(data_size, ss);
  526. pfx_size = 2;
  527. } else if (pfx_size == 8) {
  528. ss[0] = data_size;
  529. pfx_size = 1;
  530. } else
  531. return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
  532. return _gnutls_buffer_append_data(buf, ss, pfx_size);
  533. }
  534. /* Reads an uint32 number from the buffer. If check is non zero it will also check whether
  535. * the number read, is less than the data in the buffer
  536. */
  537. int
  538. _gnutls_buffer_pop_prefix(gnutls_buffer_st * buf, size_t * data_size,
  539. int check)
  540. {
  541. size_t size;
  542. if (buf->length < 4) {
  543. gnutls_assert();
  544. return GNUTLS_E_PARSING_ERROR;
  545. }
  546. size = _gnutls_read_uint32(buf->data);
  547. if (check && size > buf->length - 4) {
  548. gnutls_assert();
  549. return GNUTLS_E_PARSING_ERROR;
  550. }
  551. buf->data += 4;
  552. buf->length -= 4;
  553. *data_size = size;
  554. return 0;
  555. }
  556. int
  557. _gnutls_buffer_pop_datum_prefix(gnutls_buffer_st * buf,
  558. gnutls_datum_t * data)
  559. {
  560. size_t size;
  561. int ret;
  562. ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
  563. if (ret < 0) {
  564. gnutls_assert();
  565. return ret;
  566. }
  567. if (size > 0) {
  568. size_t osize = size;
  569. _gnutls_buffer_pop_datum(buf, data, size);
  570. if (osize != data->size) {
  571. gnutls_assert();
  572. return GNUTLS_E_PARSING_ERROR;
  573. }
  574. } else {
  575. data->size = 0;
  576. data->data = NULL;
  577. }
  578. return 0;
  579. }
  580. int
  581. _gnutls_buffer_append_data_prefix(gnutls_buffer_st * buf,
  582. int pfx_size, const void *data,
  583. size_t data_size)
  584. {
  585. int ret = 0, ret1;
  586. ret1 = _gnutls_buffer_append_prefix(buf, pfx_size, data_size);
  587. if (ret1 < 0)
  588. return gnutls_assert_val(ret1);
  589. if (data_size > 0) {
  590. ret = _gnutls_buffer_append_data(buf, data, data_size);
  591. if (ret < 0)
  592. return gnutls_assert_val(ret);
  593. }
  594. return ret + ret1;
  595. }
  596. int _gnutls_buffer_append_mpi(gnutls_buffer_st * buf, int pfx_size,
  597. bigint_t mpi, int lz)
  598. {
  599. gnutls_datum_t dd;
  600. int ret;
  601. if (lz)
  602. ret = _gnutls_mpi_dprint_lz(mpi, &dd);
  603. else
  604. ret = _gnutls_mpi_dprint(mpi, &dd);
  605. if (ret < 0)
  606. return gnutls_assert_val(ret);
  607. ret =
  608. _gnutls_buffer_append_data_prefix(buf, pfx_size, dd.data,
  609. dd.size);
  610. _gnutls_free_datum(&dd);
  611. return ret;
  612. }
  613. int
  614. _gnutls_buffer_pop_data_prefix(gnutls_buffer_st * buf, void *data,
  615. size_t * data_size)
  616. {
  617. size_t size;
  618. int ret;
  619. ret = _gnutls_buffer_pop_prefix(buf, &size, 1);
  620. if (ret < 0) {
  621. gnutls_assert();
  622. return ret;
  623. }
  624. if (size > 0)
  625. _gnutls_buffer_pop_data(buf, data, data_size);
  626. return 0;
  627. }
  628. void
  629. _gnutls_buffer_hexprint(gnutls_buffer_st * str,
  630. const void *_data, size_t len)
  631. {
  632. size_t j;
  633. const unsigned char *data = _data;
  634. if (len == 0)
  635. _gnutls_buffer_append_str(str, "00");
  636. else {
  637. for (j = 0; j < len; j++)
  638. _gnutls_buffer_append_printf(str, "%.2x",
  639. (unsigned) data[j]);
  640. }
  641. }
  642. void
  643. _gnutls_buffer_hexdump(gnutls_buffer_st * str, const void *_data,
  644. size_t len, const char *spc)
  645. {
  646. size_t j;
  647. const unsigned char *data = _data;
  648. if (spc)
  649. _gnutls_buffer_append_str(str, spc);
  650. for (j = 0; j < len; j++) {
  651. if (((j + 1) % 16) == 0) {
  652. _gnutls_buffer_append_printf(str, "%.2x\n",
  653. (unsigned) data[j]);
  654. if (spc && j != (len - 1))
  655. _gnutls_buffer_append_str(str, spc);
  656. } else if (j == (len - 1))
  657. _gnutls_buffer_append_printf(str, "%.2x",
  658. (unsigned) data[j]);
  659. else
  660. _gnutls_buffer_append_printf(str, "%.2x:",
  661. (unsigned) data[j]);
  662. }
  663. if ((j % 16) != 0)
  664. _gnutls_buffer_append_str(str, "\n");
  665. }
  666. void
  667. _gnutls_buffer_asciiprint(gnutls_buffer_st * str,
  668. const char *data, size_t len)
  669. {
  670. size_t j;
  671. for (j = 0; j < len; j++)
  672. if (c_isprint(data[j]))
  673. _gnutls_buffer_append_printf(str, "%c",
  674. (unsigned char)
  675. data[j]);
  676. else
  677. _gnutls_buffer_append_printf(str, ".");
  678. }