You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

331 lines
8.6 KiB

  1. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  2. * All rights reserved.
  3. *
  4. * This package is an SSL implementation written
  5. * by Eric Young (eay@cryptsoft.com).
  6. * The implementation was written so as to conform with Netscapes SSL.
  7. *
  8. * This library is free for commercial and non-commercial use as long as
  9. * the following conditions are aheared to. The following conditions
  10. * apply to all code found in this distribution, be it the RC4, RSA,
  11. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  12. * included with this distribution is covered by the same copyright terms
  13. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  14. *
  15. * Copyright remains Eric Young's, and as such any Copyright notices in
  16. * the code are not to be removed.
  17. * If this package is used in a product, Eric Young should be given attribution
  18. * as the author of the parts of the library used.
  19. * This can be in the form of a textual message at program startup or
  20. * in documentation (online or textual) provided with the package.
  21. *
  22. * Redistribution and use in source and binary forms, with or without
  23. * modification, are permitted provided that the following conditions
  24. * are met:
  25. * 1. Redistributions of source code must retain the copyright
  26. * notice, this list of conditions and the following disclaimer.
  27. * 2. Redistributions in binary form must reproduce the above copyright
  28. * notice, this list of conditions and the following disclaimer in the
  29. * documentation and/or other materials provided with the distribution.
  30. * 3. All advertising materials mentioning features or use of this software
  31. * must display the following acknowledgement:
  32. * "This product includes cryptographic software written by
  33. * Eric Young (eay@cryptsoft.com)"
  34. * The word 'cryptographic' can be left out if the rouines from the library
  35. * being used are not cryptographic related :-).
  36. * 4. If you include any Windows specific code (or a derivative thereof) from
  37. * the apps directory (application code) you must include an acknowledgement:
  38. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  39. *
  40. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  41. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  43. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  44. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  45. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  46. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  47. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  48. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  49. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  50. * SUCH DAMAGE.
  51. *
  52. * The licence and distribution terms for any publically available version or
  53. * derivative of this code cannot be changed. i.e. this code cannot simply be
  54. * copied and put under another distribution licence
  55. * [including the GNU Public Licence.] */
  56. #include <openssl/bio.h>
  57. #include <limits.h>
  58. #include <string.h>
  59. #include <openssl/buf.h>
  60. #include <openssl/err.h>
  61. #include <openssl/mem.h>
  62. #include "../internal.h"
  63. BIO *BIO_new_mem_buf(const void *buf, int len) {
  64. BIO *ret;
  65. BUF_MEM *b;
  66. const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
  67. if (!buf && len != 0) {
  68. OPENSSL_PUT_ERROR(BIO, BIO_R_NULL_PARAMETER);
  69. return NULL;
  70. }
  71. ret = BIO_new(BIO_s_mem());
  72. if (ret == NULL) {
  73. return NULL;
  74. }
  75. b = (BUF_MEM *)ret->ptr;
  76. // BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to.
  77. b->data = (void *)buf;
  78. b->length = size;
  79. b->max = size;
  80. ret->flags |= BIO_FLAGS_MEM_RDONLY;
  81. // |num| is used to store the value that this BIO will return when it runs
  82. // out of data. If it's negative then the retry flags will also be set. Since
  83. // this is static data, retrying wont help
  84. ret->num = 0;
  85. return ret;
  86. }
  87. static int mem_new(BIO *bio) {
  88. BUF_MEM *b;
  89. b = BUF_MEM_new();
  90. if (b == NULL) {
  91. return 0;
  92. }
  93. // |shutdown| is used to store the close flag: whether the BIO has ownership
  94. // of the BUF_MEM.
  95. bio->shutdown = 1;
  96. bio->init = 1;
  97. bio->num = -1;
  98. bio->ptr = (char *)b;
  99. return 1;
  100. }
  101. static int mem_free(BIO *bio) {
  102. BUF_MEM *b;
  103. if (bio == NULL) {
  104. return 0;
  105. }
  106. if (!bio->shutdown || !bio->init || bio->ptr == NULL) {
  107. return 1;
  108. }
  109. b = (BUF_MEM *)bio->ptr;
  110. if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
  111. b->data = NULL;
  112. }
  113. BUF_MEM_free(b);
  114. bio->ptr = NULL;
  115. return 1;
  116. }
  117. static int mem_read(BIO *bio, char *out, int outl) {
  118. int ret;
  119. BUF_MEM *b = (BUF_MEM*) bio->ptr;
  120. BIO_clear_retry_flags(bio);
  121. ret = outl;
  122. if (b->length < INT_MAX && ret > (int)b->length) {
  123. ret = b->length;
  124. }
  125. if (ret > 0) {
  126. OPENSSL_memcpy(out, b->data, ret);
  127. b->length -= ret;
  128. if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
  129. b->data += ret;
  130. } else {
  131. OPENSSL_memmove(b->data, &b->data[ret], b->length);
  132. }
  133. } else if (b->length == 0) {
  134. ret = bio->num;
  135. if (ret != 0) {
  136. BIO_set_retry_read(bio);
  137. }
  138. }
  139. return ret;
  140. }
  141. static int mem_write(BIO *bio, const char *in, int inl) {
  142. int ret = -1;
  143. int blen;
  144. BUF_MEM *b;
  145. b = (BUF_MEM *)bio->ptr;
  146. if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
  147. OPENSSL_PUT_ERROR(BIO, BIO_R_WRITE_TO_READ_ONLY_BIO);
  148. goto err;
  149. }
  150. BIO_clear_retry_flags(bio);
  151. blen = b->length;
  152. if (INT_MAX - blen < inl) {
  153. goto err;
  154. }
  155. if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
  156. goto err;
  157. }
  158. OPENSSL_memcpy(&b->data[blen], in, inl);
  159. ret = inl;
  160. err:
  161. return ret;
  162. }
  163. static int mem_gets(BIO *bio, char *buf, int size) {
  164. int i, j;
  165. char *p;
  166. BUF_MEM *b = (BUF_MEM *)bio->ptr;
  167. BIO_clear_retry_flags(bio);
  168. j = b->length;
  169. if (size - 1 < j) {
  170. j = size - 1;
  171. }
  172. if (j <= 0) {
  173. if (size > 0) {
  174. *buf = 0;
  175. }
  176. return 0;
  177. }
  178. p = b->data;
  179. for (i = 0; i < j; i++) {
  180. if (p[i] == '\n') {
  181. i++;
  182. break;
  183. }
  184. }
  185. // i is now the max num of bytes to copy, either j or up to and including the
  186. // first newline
  187. i = mem_read(bio, buf, i);
  188. if (i > 0) {
  189. buf[i] = '\0';
  190. }
  191. return i;
  192. }
  193. static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
  194. long ret = 1;
  195. char **pptr;
  196. BUF_MEM *b = (BUF_MEM *)bio->ptr;
  197. switch (cmd) {
  198. case BIO_CTRL_RESET:
  199. if (b->data != NULL) {
  200. // For read only case reset to the start again
  201. if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
  202. b->data -= b->max - b->length;
  203. b->length = b->max;
  204. } else {
  205. OPENSSL_memset(b->data, 0, b->max);
  206. b->length = 0;
  207. }
  208. }
  209. break;
  210. case BIO_CTRL_EOF:
  211. ret = (long)(b->length == 0);
  212. break;
  213. case BIO_C_SET_BUF_MEM_EOF_RETURN:
  214. bio->num = (int)num;
  215. break;
  216. case BIO_CTRL_INFO:
  217. ret = (long)b->length;
  218. if (ptr != NULL) {
  219. pptr = (char **)ptr;
  220. *pptr = (char *)&b->data[0];
  221. }
  222. break;
  223. case BIO_C_SET_BUF_MEM:
  224. mem_free(bio);
  225. bio->shutdown = (int)num;
  226. bio->ptr = ptr;
  227. break;
  228. case BIO_C_GET_BUF_MEM_PTR:
  229. if (ptr != NULL) {
  230. pptr = (char **)ptr;
  231. *pptr = (char *)b;
  232. }
  233. break;
  234. case BIO_CTRL_GET_CLOSE:
  235. ret = (long)bio->shutdown;
  236. break;
  237. case BIO_CTRL_SET_CLOSE:
  238. bio->shutdown = (int)num;
  239. break;
  240. case BIO_CTRL_WPENDING:
  241. ret = 0L;
  242. break;
  243. case BIO_CTRL_PENDING:
  244. ret = (long)b->length;
  245. break;
  246. case BIO_CTRL_FLUSH:
  247. ret = 1;
  248. break;
  249. default:
  250. ret = 0;
  251. break;
  252. }
  253. return ret;
  254. }
  255. static const BIO_METHOD mem_method = {
  256. BIO_TYPE_MEM, "memory buffer",
  257. mem_write, mem_read,
  258. NULL /* puts */, mem_gets,
  259. mem_ctrl, mem_new,
  260. mem_free, NULL /* callback_ctrl */,
  261. };
  262. const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
  263. int BIO_mem_contents(const BIO *bio, const uint8_t **out_contents,
  264. size_t *out_len) {
  265. const BUF_MEM *b;
  266. if (bio->method != &mem_method) {
  267. return 0;
  268. }
  269. b = (BUF_MEM *)bio->ptr;
  270. *out_contents = (uint8_t *)b->data;
  271. *out_len = b->length;
  272. return 1;
  273. }
  274. long BIO_get_mem_data(BIO *bio, char **contents) {
  275. return BIO_ctrl(bio, BIO_CTRL_INFO, 0, (char *) contents);
  276. }
  277. int BIO_get_mem_ptr(BIO *bio, BUF_MEM **out) {
  278. return BIO_ctrl(bio, BIO_C_GET_BUF_MEM_PTR, 0, (char *) out);
  279. }
  280. int BIO_set_mem_buf(BIO *bio, BUF_MEM *b, int take_ownership) {
  281. return BIO_ctrl(bio, BIO_C_SET_BUF_MEM, take_ownership, (char *) b);
  282. }
  283. int BIO_set_mem_eof_return(BIO *bio, int eof_value) {
  284. return BIO_ctrl(bio, BIO_C_SET_BUF_MEM_EOF_RETURN, eof_value, NULL);
  285. }