Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

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