25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

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