netstring.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (C) 2011 Flowroute LLC (flowroute.com)
  3. *
  4. * This file is part of Kamailio, a free SIP server.
  5. *
  6. * This file is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version
  10. *
  11. *
  12. * This file is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <math.h>
  27. #include "netstring.h"
  28. #include "../../sr_module.h"
  29. #include "../../mem/mem.h"
  30. int netstring_read_fd(int fd, char **netstring) {
  31. int i, bytes;
  32. size_t len = 0;
  33. *netstring = NULL;
  34. char buffer[10]={0};
  35. /* Peek at first 10 bytes, to get length and colon */
  36. bytes = recv(fd,buffer,10,MSG_PEEK);
  37. if (bytes<3) return NETSTRING_ERROR_TOO_SHORT;
  38. /* No leading zeros allowed! */
  39. if (buffer[0] == '0' && isdigit(buffer[1]))
  40. return NETSTRING_ERROR_LEADING_ZERO;
  41. /* The netstring must start with a number */
  42. if (!isdigit(buffer[0])) return NETSTRING_ERROR_NO_LENGTH;
  43. /* Read the number of bytes */
  44. for (i = 0; i < bytes && isdigit(buffer[i]); i++) {
  45. /* Error if more than 9 digits */
  46. if (i >= 9) return NETSTRING_ERROR_TOO_LONG;
  47. /* Accumulate each digit, assuming ASCII. */
  48. len = len*10 + (buffer[i] - '0');
  49. }
  50. /* Read the colon */
  51. if (buffer[i++] != ':') return NETSTRING_ERROR_NO_COLON;
  52. /* Read the whole string from the buffer */
  53. size_t read_len = i+len+1;
  54. char *buffer2 = pkg_malloc(read_len);
  55. if (!buffer2) {
  56. LM_ERR("Out of memory!");
  57. return -1;
  58. }
  59. bytes = recv(fd,buffer2,read_len,0);
  60. /* Make sure we got the whole netstring */
  61. if (read_len > bytes) return NETSTRING_ERROR_TOO_SHORT;
  62. /* Test for the trailing comma */
  63. if (buffer2[read_len-1] != ',') return NETSTRING_ERROR_NO_COMMA;
  64. buffer2[read_len-1] = '\0';
  65. int x;
  66. for(x=0;x<=read_len-i-1;x++) {
  67. buffer2[x]=buffer2[x+i];
  68. }
  69. *netstring = buffer2;
  70. return 0;
  71. }
  72. /* Reads a netstring from a `buffer` of length `buffer_length`. Writes
  73. to `netstring_start` a pointer to the beginning of the string in
  74. the buffer, and to `netstring_length` the length of the
  75. string. Does not allocate any memory. If it reads successfully,
  76. then it returns 0. If there is an error, then the return value will
  77. be negative. The error values are:
  78. NETSTRING_ERROR_TOO_LONG More than 999999999 bytes in a field
  79. NETSTRING_ERROR_NO_COLON No colon was found after the number
  80. NETSTRING_ERROR_TOO_SHORT Number of bytes greater than buffer length
  81. NETSTRING_ERROR_NO_COMMA No comma was found at the end
  82. NETSTRING_ERROR_LEADING_ZERO Leading zeros are not allowed
  83. NETSTRING_ERROR_NO_LENGTH Length not given at start of netstring
  84. If you're sending messages with more than 999999999 bytes -- about
  85. 2 GB -- then you probably should not be doing so in the form of a
  86. single netstring. This restriction is in place partially to protect
  87. from malicious or erroneous input, and partly to be compatible with
  88. D. J. Bernstein's reference implementation.
  89. Example:
  90. if (netstring_read("3:foo,", 6, &str, &len) < 0) explode_and_die();
  91. */
  92. int netstring_read(char *buffer, size_t buffer_length,
  93. char **netstring_start, size_t *netstring_length) {
  94. int i;
  95. size_t len = 0;
  96. /* Write default values for outputs */
  97. *netstring_start = NULL; *netstring_length = 0;
  98. /* Make sure buffer is big enough. Minimum size is 3. */
  99. if (buffer_length < 3) return NETSTRING_ERROR_TOO_SHORT;
  100. /* No leading zeros allowed! */
  101. if (buffer[0] == '0' && isdigit(buffer[1]))
  102. return NETSTRING_ERROR_LEADING_ZERO;
  103. /* The netstring must start with a number */
  104. if (!isdigit(buffer[0])) return NETSTRING_ERROR_NO_LENGTH;
  105. /* Read the number of bytes */
  106. for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) {
  107. /* Error if more than 9 digits */
  108. if (i >= 9) return NETSTRING_ERROR_TOO_LONG;
  109. /* Accumulate each digit, assuming ASCII. */
  110. len = len*10 + (buffer[i] - '0');
  111. }
  112. /* Check buffer length once and for all. Specifically, we make sure
  113. that the buffer is longer than the number we've read, the length
  114. of the string itself, and the colon and comma. */
  115. if (i + len + 1 >= buffer_length) return NETSTRING_ERROR_TOO_SHORT;
  116. /* Read the colon */
  117. if (buffer[i++] != ':') return NETSTRING_ERROR_NO_COLON;
  118. /* Test for the trailing comma, and set the return values */
  119. if (buffer[i + len] != ',') return NETSTRING_ERROR_NO_COMMA;
  120. *netstring_start = &buffer[i]; *netstring_length = len;
  121. return 0;
  122. }
  123. /* Return the length, in ASCII characters, of a netstring containing
  124. `data_length` bytes. */
  125. size_t netstring_buffer_size(size_t data_length) {
  126. if (data_length == 0) return 3;
  127. return (size_t)ceil(log10((double)data_length + 1)) + data_length + 2;
  128. }
  129. /* Allocate and create a netstring containing the first `len` bytes of
  130. `data`. This must be manually freed by the client. If `len` is 0
  131. then no data will be read from `data`, and it may be NULL. */
  132. size_t netstring_encode_new(char **netstring, char *data, size_t len) {
  133. char *ns;
  134. size_t num_len = 1;
  135. if (len == 0) {
  136. ns = pkg_malloc(3);
  137. if (!ns) {
  138. LM_ERR("Out of memory!");
  139. return 0;
  140. }
  141. ns[0] = '0';
  142. ns[1] = ':';
  143. ns[2] = ',';
  144. } else {
  145. num_len = (size_t)ceil(log10((double)len + 1));
  146. ns = pkg_malloc(num_len + len + 2);
  147. if (!ns) {
  148. LM_ERR("Out of memory!");
  149. return 0;
  150. }
  151. sprintf(ns, "%lu:", (unsigned long)len);
  152. memcpy(ns + num_len + 1, data, len);
  153. ns[num_len + len + 1] = ',';
  154. }
  155. *netstring = ns;
  156. return num_len + len + 2;
  157. }