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.
 
 
 
 
 
 

501 lines
13 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 <string.h>
  58. #include <openssl/buf.h>
  59. #include <openssl/err.h>
  60. #include <openssl/mem.h>
  61. #define DEFAULT_BUFFER_SIZE 4096
  62. typedef struct bio_f_buffer_ctx_struct {
  63. /* Buffers are setup like this:
  64. *
  65. * <---------------------- size ----------------------->
  66. * +---------------------------------------------------+
  67. * | consumed | remaining | free space |
  68. * +---------------------------------------------------+
  69. * <-- off --><------- len ------->
  70. */
  71. int ibuf_size; /* how big is the input buffer */
  72. int obuf_size; /* how big is the output buffer */
  73. char *ibuf; /* the char array */
  74. int ibuf_len; /* how many bytes are in it */
  75. int ibuf_off; /* write/read offset */
  76. char *obuf; /* the char array */
  77. int obuf_len; /* how many bytes are in it */
  78. int obuf_off; /* write/read offset */
  79. } BIO_F_BUFFER_CTX;
  80. static int buffer_new(BIO *bio) {
  81. BIO_F_BUFFER_CTX *ctx;
  82. ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
  83. if (ctx == NULL) {
  84. return 0;
  85. }
  86. memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX));
  87. ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
  88. if (ctx->ibuf == NULL) {
  89. goto err1;
  90. }
  91. ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
  92. if (ctx->obuf == NULL) {
  93. goto err2;
  94. }
  95. ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
  96. ctx->obuf_size = DEFAULT_BUFFER_SIZE;
  97. bio->init = 1;
  98. bio->ptr = (char *)ctx;
  99. return 1;
  100. err2:
  101. OPENSSL_free(ctx->ibuf);
  102. err1:
  103. OPENSSL_free(ctx);
  104. return 0;
  105. }
  106. static int buffer_free(BIO *bio) {
  107. BIO_F_BUFFER_CTX *ctx;
  108. if (bio == NULL) {
  109. return 0;
  110. }
  111. ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
  112. if (ctx->ibuf != NULL) {
  113. OPENSSL_free(ctx->ibuf);
  114. }
  115. if (ctx->obuf != NULL) {
  116. OPENSSL_free(ctx->obuf);
  117. }
  118. OPENSSL_free(bio->ptr);
  119. bio->ptr = NULL;
  120. bio->init = 0;
  121. bio->flags = 0;
  122. return 1;
  123. }
  124. static int buffer_read(BIO *bio, char *out, int outl) {
  125. int i, num = 0;
  126. BIO_F_BUFFER_CTX *ctx;
  127. ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
  128. if (ctx == NULL || bio->next_bio == NULL) {
  129. return 0;
  130. }
  131. num = 0;
  132. BIO_clear_retry_flags(bio);
  133. for (;;) {
  134. i = ctx->ibuf_len;
  135. /* If there is stuff left over, grab it */
  136. if (i != 0) {
  137. if (i > outl) {
  138. i = outl;
  139. }
  140. memcpy(out, &ctx->ibuf[ctx->ibuf_off], i);
  141. ctx->ibuf_off += i;
  142. ctx->ibuf_len -= i;
  143. num += i;
  144. if (outl == i) {
  145. return num;
  146. }
  147. outl -= i;
  148. out += i;
  149. }
  150. /* We may have done a partial read. Try to do more. We have nothing in the
  151. * buffer. If we get an error and have read some data, just return it and
  152. * let them retry to get the error again. Copy direct to parent address
  153. * space */
  154. if (outl > ctx->ibuf_size) {
  155. for (;;) {
  156. i = BIO_read(bio->next_bio, out, outl);
  157. if (i <= 0) {
  158. BIO_copy_next_retry(bio);
  159. if (i < 0) {
  160. return (num > 0) ? num : i;
  161. }
  162. return num;
  163. }
  164. num += i;
  165. if (outl == i) {
  166. return num;
  167. }
  168. out += i;
  169. outl -= i;
  170. }
  171. }
  172. /* else */
  173. /* we are going to be doing some buffering */
  174. i = BIO_read(bio->next_bio, ctx->ibuf, ctx->ibuf_size);
  175. if (i <= 0) {
  176. BIO_copy_next_retry(bio);
  177. if (i < 0) {
  178. return (num > 0) ? num : i;
  179. }
  180. return num;
  181. }
  182. ctx->ibuf_off = 0;
  183. ctx->ibuf_len = i;
  184. }
  185. }
  186. static int buffer_write(BIO *b, const char *in, int inl) {
  187. int i, num = 0;
  188. BIO_F_BUFFER_CTX *ctx;
  189. ctx = (BIO_F_BUFFER_CTX *)b->ptr;
  190. if (ctx == NULL || b->next_bio == NULL) {
  191. return 0;
  192. }
  193. BIO_clear_retry_flags(b);
  194. for (;;) {
  195. i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len);
  196. /* add to buffer and return */
  197. if (i >= inl) {
  198. memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, inl);
  199. ctx->obuf_len += inl;
  200. return num + inl;
  201. }
  202. /* else */
  203. /* stuff already in buffer, so add to it first, then flush */
  204. if (ctx->obuf_len != 0) {
  205. if (i > 0) {
  206. memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, i);
  207. in += i;
  208. inl -= i;
  209. num += i;
  210. ctx->obuf_len += i;
  211. }
  212. /* we now have a full buffer needing flushing */
  213. for (;;) {
  214. i = BIO_write(b->next_bio, &ctx->obuf[ctx->obuf_off], ctx->obuf_len);
  215. if (i <= 0) {
  216. BIO_copy_next_retry(b);
  217. if (i < 0) {
  218. return (num > 0) ? num : i;
  219. }
  220. return num;
  221. }
  222. ctx->obuf_off += i;
  223. ctx->obuf_len -= i;
  224. if (ctx->obuf_len == 0) {
  225. break;
  226. }
  227. }
  228. }
  229. /* we only get here if the buffer has been flushed and we
  230. * still have stuff to write */
  231. ctx->obuf_off = 0;
  232. /* we now have inl bytes to write */
  233. while (inl >= ctx->obuf_size) {
  234. i = BIO_write(b->next_bio, in, inl);
  235. if (i <= 0) {
  236. BIO_copy_next_retry(b);
  237. if (i < 0) {
  238. return (num > 0) ? num : i;
  239. }
  240. return num;
  241. }
  242. num += i;
  243. in += i;
  244. inl -= i;
  245. if (inl == 0) {
  246. return num;
  247. }
  248. }
  249. /* copy the rest into the buffer since we have only a small
  250. * amount left */
  251. }
  252. }
  253. static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
  254. BIO_F_BUFFER_CTX *ctx;
  255. long ret = 1;
  256. char *p1, *p2;
  257. int r, *ip;
  258. int ibs, obs;
  259. ctx = (BIO_F_BUFFER_CTX *)b->ptr;
  260. switch (cmd) {
  261. case BIO_CTRL_RESET:
  262. ctx->ibuf_off = 0;
  263. ctx->ibuf_len = 0;
  264. ctx->obuf_off = 0;
  265. ctx->obuf_len = 0;
  266. if (b->next_bio == NULL) {
  267. return 0;
  268. }
  269. ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
  270. break;
  271. case BIO_CTRL_INFO:
  272. ret = ctx->obuf_len;
  273. break;
  274. case BIO_CTRL_WPENDING:
  275. ret = (long)ctx->obuf_len;
  276. if (ret == 0) {
  277. if (b->next_bio == NULL) {
  278. return 0;
  279. }
  280. ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
  281. }
  282. break;
  283. case BIO_CTRL_PENDING:
  284. ret = (long)ctx->ibuf_len;
  285. if (ret == 0) {
  286. if (b->next_bio == NULL) {
  287. return 0;
  288. }
  289. ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
  290. }
  291. break;
  292. case BIO_C_SET_BUFF_SIZE:
  293. ip = (int *)ptr;
  294. if (*ip == 0) {
  295. ibs = (int)num;
  296. obs = ctx->obuf_size;
  297. } else /* if (*ip == 1) */ {
  298. ibs = ctx->ibuf_size;
  299. obs = (int)num;
  300. }
  301. p1 = ctx->ibuf;
  302. p2 = ctx->obuf;
  303. if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
  304. p1 = (char *)OPENSSL_malloc(ibs);
  305. if (p1 == NULL) {
  306. goto malloc_error;
  307. }
  308. }
  309. if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
  310. p2 = (char *)OPENSSL_malloc(obs);
  311. if (p2 == NULL) {
  312. if (p1 != ctx->ibuf) {
  313. OPENSSL_free(p1);
  314. }
  315. goto malloc_error;
  316. }
  317. }
  318. if (ctx->ibuf != p1) {
  319. OPENSSL_free(ctx->ibuf);
  320. ctx->ibuf = p1;
  321. ctx->ibuf_size = ibs;
  322. }
  323. ctx->ibuf_off = 0;
  324. ctx->ibuf_len = 0;
  325. if (ctx->obuf != p2) {
  326. OPENSSL_free(ctx->obuf);
  327. ctx->obuf = p2;
  328. ctx->obuf_size = obs;
  329. }
  330. ctx->obuf_off = 0;
  331. ctx->obuf_len = 0;
  332. break;
  333. case BIO_CTRL_FLUSH:
  334. if (b->next_bio == NULL) {
  335. return 0;
  336. }
  337. while (ctx->obuf_len > 0) {
  338. BIO_clear_retry_flags(b);
  339. r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
  340. ctx->obuf_len);
  341. BIO_copy_next_retry(b);
  342. if (r <= 0) {
  343. return r;
  344. }
  345. ctx->obuf_off += r;
  346. ctx->obuf_len -= r;
  347. }
  348. ctx->obuf_len = 0;
  349. ctx->obuf_off = 0;
  350. ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
  351. break;
  352. default:
  353. if (b->next_bio == NULL) {
  354. return 0;
  355. }
  356. BIO_clear_retry_flags(b);
  357. ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
  358. BIO_copy_next_retry(b);
  359. break;
  360. }
  361. return ret;
  362. malloc_error:
  363. OPENSSL_PUT_ERROR(BIO, buffer_ctrl, ERR_R_MALLOC_FAILURE);
  364. return 0;
  365. }
  366. static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) {
  367. long ret = 1;
  368. if (b->next_bio == NULL) {
  369. return 0;
  370. }
  371. switch (cmd) {
  372. default:
  373. ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
  374. break;
  375. }
  376. return ret;
  377. }
  378. static int buffer_gets(BIO *b, char *buf, int size) {
  379. BIO_F_BUFFER_CTX *ctx;
  380. int num = 0, i, flag;
  381. char *p;
  382. ctx = (BIO_F_BUFFER_CTX *)b->ptr;
  383. if (buf == NULL || size <= 0) {
  384. return 0;
  385. }
  386. size--; /* reserve space for a '\0' */
  387. BIO_clear_retry_flags(b);
  388. for (;;) {
  389. if (ctx->ibuf_len > 0) {
  390. p = &ctx->ibuf[ctx->ibuf_off];
  391. flag = 0;
  392. for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
  393. *(buf++) = p[i];
  394. if (p[i] == '\n') {
  395. flag = 1;
  396. i++;
  397. break;
  398. }
  399. }
  400. num += i;
  401. size -= i;
  402. ctx->ibuf_len -= i;
  403. ctx->ibuf_off += i;
  404. if (flag || size == 0) {
  405. *buf = '\0';
  406. return num;
  407. }
  408. } else /* read another chunk */
  409. {
  410. i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
  411. if (i <= 0) {
  412. BIO_copy_next_retry(b);
  413. *buf = '\0';
  414. if (i < 0) {
  415. return (num > 0) ? num : i;
  416. }
  417. return num;
  418. }
  419. ctx->ibuf_len = i;
  420. ctx->ibuf_off = 0;
  421. }
  422. }
  423. }
  424. static int buffer_puts(BIO *b, const char *str) {
  425. return buffer_write(b, str, strlen(str));
  426. }
  427. static const BIO_METHOD methods_buffer = {
  428. BIO_TYPE_BUFFER, "buffer", buffer_write, buffer_read,
  429. buffer_puts, buffer_gets, buffer_ctrl, buffer_new,
  430. buffer_free, buffer_callback_ctrl,
  431. };
  432. const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; }
  433. int BIO_set_read_buffer_size(BIO *bio, int buffer_size) {
  434. return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0);
  435. }
  436. int BIO_set_write_buffer_size(BIO *bio, int buffer_size) {
  437. return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1);
  438. }