bf_buff.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /* crypto/bio/bf_buff.c */
  2. /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  3. * All rights reserved.
  4. *
  5. * This package is an SSL implementation written
  6. * by Eric Young (eay@cryptsoft.com).
  7. * The implementation was written so as to conform with Netscapes SSL.
  8. *
  9. * This library is free for commercial and non-commercial use as long as
  10. * the following conditions are aheared to. The following conditions
  11. * apply to all code found in this distribution, be it the RC4, RSA,
  12. * lhash, DES, etc., code; not just the SSL code. The SSL documentation
  13. * included with this distribution is covered by the same copyright terms
  14. * except that the holder is Tim Hudson (tjh@cryptsoft.com).
  15. *
  16. * Copyright remains Eric Young's, and as such any Copyright notices in
  17. * the code are not to be removed.
  18. * If this package is used in a product, Eric Young should be given attribution
  19. * as the author of the parts of the library used.
  20. * This can be in the form of a textual message at program startup or
  21. * in documentation (online or textual) provided with the package.
  22. *
  23. * Redistribution and use in source and binary forms, with or without
  24. * modification, are permitted provided that the following conditions
  25. * are met:
  26. * 1. Redistributions of source code must retain the copyright
  27. * notice, this list of conditions and the following disclaimer.
  28. * 2. Redistributions in binary form must reproduce the above copyright
  29. * notice, this list of conditions and the following disclaimer in the
  30. * documentation and/or other materials provided with the distribution.
  31. * 3. All advertising materials mentioning features or use of this software
  32. * must display the following acknowledgement:
  33. * "This product includes cryptographic software written by
  34. * Eric Young (eay@cryptsoft.com)"
  35. * The word 'cryptographic' can be left out if the rouines from the library
  36. * being used are not cryptographic related :-).
  37. * 4. If you include any Windows specific code (or a derivative thereof) from
  38. * the apps directory (application code) you must include an acknowledgement:
  39. * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  40. *
  41. * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  42. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  43. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  44. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  45. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  46. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  47. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  49. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  50. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51. * SUCH DAMAGE.
  52. *
  53. * The licence and distribution terms for any publically available version or
  54. * derivative of this code cannot be changed. i.e. this code cannot simply be
  55. * copied and put under another distribution licence
  56. * [including the GNU Public Licence.]
  57. */
  58. #include <stdio.h>
  59. #include <errno.h>
  60. #include "cryptlib.h"
  61. #include <openssl/bio.h>
  62. static int buffer_write(BIO *h, const char *buf,int num);
  63. static int buffer_read(BIO *h, char *buf, int size);
  64. static int buffer_puts(BIO *h, const char *str);
  65. static int buffer_gets(BIO *h, char *str, int size);
  66. static long buffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
  67. static int buffer_new(BIO *h);
  68. static int buffer_free(BIO *data);
  69. static long buffer_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp);
  70. #define DEFAULT_BUFFER_SIZE 4096
  71. static BIO_METHOD methods_buffer=
  72. {
  73. BIO_TYPE_BUFFER,
  74. "buffer",
  75. buffer_write,
  76. buffer_read,
  77. buffer_puts,
  78. buffer_gets,
  79. buffer_ctrl,
  80. buffer_new,
  81. buffer_free,
  82. buffer_callback_ctrl,
  83. };
  84. BIO_METHOD *BIO_f_buffer(void)
  85. {
  86. return(&methods_buffer);
  87. }
  88. static int buffer_new(BIO *bi)
  89. {
  90. BIO_F_BUFFER_CTX *ctx;
  91. ctx=(BIO_F_BUFFER_CTX *)OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
  92. if (ctx == NULL) return(0);
  93. ctx->ibuf=(char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
  94. if (ctx->ibuf == NULL) { OPENSSL_free(ctx); return(0); }
  95. ctx->obuf=(char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
  96. if (ctx->obuf == NULL) { OPENSSL_free(ctx->ibuf); OPENSSL_free(ctx); return(0); }
  97. ctx->ibuf_size=DEFAULT_BUFFER_SIZE;
  98. ctx->obuf_size=DEFAULT_BUFFER_SIZE;
  99. ctx->ibuf_len=0;
  100. ctx->ibuf_off=0;
  101. ctx->obuf_len=0;
  102. ctx->obuf_off=0;
  103. bi->init=1;
  104. bi->ptr=(char *)ctx;
  105. bi->flags=0;
  106. return(1);
  107. }
  108. static int buffer_free(BIO *a)
  109. {
  110. BIO_F_BUFFER_CTX *b;
  111. if (a == NULL) return(0);
  112. b=(BIO_F_BUFFER_CTX *)a->ptr;
  113. if (b->ibuf != NULL) OPENSSL_free(b->ibuf);
  114. if (b->obuf != NULL) OPENSSL_free(b->obuf);
  115. OPENSSL_free(a->ptr);
  116. a->ptr=NULL;
  117. a->init=0;
  118. a->flags=0;
  119. return(1);
  120. }
  121. static int buffer_read(BIO *b, char *out, int outl)
  122. {
  123. int i,num=0;
  124. BIO_F_BUFFER_CTX *ctx;
  125. if (out == NULL) return(0);
  126. ctx=(BIO_F_BUFFER_CTX *)b->ptr;
  127. if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
  128. num=0;
  129. BIO_clear_retry_flags(b);
  130. start:
  131. i=ctx->ibuf_len;
  132. /* If there is stuff left over, grab it */
  133. if (i != 0)
  134. {
  135. if (i > outl) i=outl;
  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) return(num);
  141. outl-=i;
  142. out+=i;
  143. }
  144. /* We may have done a partial read. try to do more.
  145. * We have nothing in the buffer.
  146. * If we get an error and have read some data, just return it
  147. * and let them retry to get the error again.
  148. * copy direct to parent address space */
  149. if (outl > ctx->ibuf_size)
  150. {
  151. for (;;)
  152. {
  153. i=BIO_read(b->next_bio,out,outl);
  154. if (i <= 0)
  155. {
  156. BIO_copy_next_retry(b);
  157. if (i < 0) return((num > 0)?num:i);
  158. if (i == 0) return(num);
  159. }
  160. num+=i;
  161. if (outl == i) return(num);
  162. out+=i;
  163. outl-=i;
  164. }
  165. }
  166. /* else */
  167. /* we are going to be doing some buffering */
  168. i=BIO_read(b->next_bio,ctx->ibuf,ctx->ibuf_size);
  169. if (i <= 0)
  170. {
  171. BIO_copy_next_retry(b);
  172. if (i < 0) return((num > 0)?num:i);
  173. if (i == 0) return(num);
  174. }
  175. ctx->ibuf_off=0;
  176. ctx->ibuf_len=i;
  177. /* Lets re-read using ourselves :-) */
  178. goto start;
  179. }
  180. static int buffer_write(BIO *b, const char *in, int inl)
  181. {
  182. int i,num=0;
  183. BIO_F_BUFFER_CTX *ctx;
  184. if ((in == NULL) || (inl <= 0)) return(0);
  185. ctx=(BIO_F_BUFFER_CTX *)b->ptr;
  186. if ((ctx == NULL) || (b->next_bio == NULL)) return(0);
  187. BIO_clear_retry_flags(b);
  188. start:
  189. i=ctx->obuf_size-(ctx->obuf_len+ctx->obuf_off);
  190. /* add to buffer and return */
  191. if (i >= inl)
  192. {
  193. memcpy(&(ctx->obuf[ctx->obuf_len]),in,inl);
  194. ctx->obuf_len+=inl;
  195. return(num+inl);
  196. }
  197. /* else */
  198. /* stuff already in buffer, so add to it first, then flush */
  199. if (ctx->obuf_len != 0)
  200. {
  201. if (i > 0) /* lets fill it up if we can */
  202. {
  203. memcpy(&(ctx->obuf[ctx->obuf_len]),in,i);
  204. in+=i;
  205. inl-=i;
  206. num+=i;
  207. ctx->obuf_len+=i;
  208. }
  209. /* we now have a full buffer needing flushing */
  210. for (;;)
  211. {
  212. i=BIO_write(b->next_bio,&(ctx->obuf[ctx->obuf_off]),
  213. ctx->obuf_len);
  214. if (i <= 0)
  215. {
  216. BIO_copy_next_retry(b);
  217. if (i < 0) return((num > 0)?num:i);
  218. if (i == 0) return(num);
  219. }
  220. ctx->obuf_off+=i;
  221. ctx->obuf_len-=i;
  222. if (ctx->obuf_len == 0) break;
  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. {
  231. i=BIO_write(b->next_bio,in,inl);
  232. if (i <= 0)
  233. {
  234. BIO_copy_next_retry(b);
  235. if (i < 0) return((num > 0)?num:i);
  236. if (i == 0) return(num);
  237. }
  238. num+=i;
  239. in+=i;
  240. inl-=i;
  241. if (inl == 0) return(num);
  242. }
  243. /* copy the rest into the buffer since we have only a small
  244. * amount left */
  245. goto start;
  246. }
  247. static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr)
  248. {
  249. BIO *dbio;
  250. BIO_F_BUFFER_CTX *ctx;
  251. long ret=1;
  252. char *p1,*p2;
  253. int r,i,*ip;
  254. int ibs,obs;
  255. ctx=(BIO_F_BUFFER_CTX *)b->ptr;
  256. switch (cmd)
  257. {
  258. case BIO_CTRL_RESET:
  259. ctx->ibuf_off=0;
  260. ctx->ibuf_len=0;
  261. ctx->obuf_off=0;
  262. ctx->obuf_len=0;
  263. if (b->next_bio == NULL) return(0);
  264. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  265. break;
  266. case BIO_CTRL_INFO:
  267. ret=(long)ctx->obuf_len;
  268. break;
  269. case BIO_C_GET_BUFF_NUM_LINES:
  270. ret=0;
  271. p1=ctx->ibuf;
  272. for (i=ctx->ibuf_off; i<ctx->ibuf_len; i++)
  273. {
  274. if (p1[i] == '\n') ret++;
  275. }
  276. break;
  277. case BIO_CTRL_WPENDING:
  278. ret=(long)ctx->obuf_len;
  279. if (ret == 0)
  280. {
  281. if (b->next_bio == NULL) return(0);
  282. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  283. }
  284. break;
  285. case BIO_CTRL_PENDING:
  286. ret=(long)ctx->ibuf_len;
  287. if (ret == 0)
  288. {
  289. if (b->next_bio == NULL) return(0);
  290. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  291. }
  292. break;
  293. case BIO_C_SET_BUFF_READ_DATA:
  294. if (num > ctx->ibuf_size)
  295. {
  296. p1=OPENSSL_malloc((int)num);
  297. if (p1 == NULL) goto malloc_error;
  298. if (ctx->ibuf != NULL) OPENSSL_free(ctx->ibuf);
  299. ctx->ibuf=p1;
  300. }
  301. ctx->ibuf_off=0;
  302. ctx->ibuf_len=(int)num;
  303. memcpy(ctx->ibuf,ptr,(int)num);
  304. ret=1;
  305. break;
  306. case BIO_C_SET_BUFF_SIZE:
  307. if (ptr != NULL)
  308. {
  309. ip=(int *)ptr;
  310. if (*ip == 0)
  311. {
  312. ibs=(int)num;
  313. obs=ctx->obuf_size;
  314. }
  315. else /* if (*ip == 1) */
  316. {
  317. ibs=ctx->ibuf_size;
  318. obs=(int)num;
  319. }
  320. }
  321. else
  322. {
  323. ibs=(int)num;
  324. obs=(int)num;
  325. }
  326. p1=ctx->ibuf;
  327. p2=ctx->obuf;
  328. if ((ibs > DEFAULT_BUFFER_SIZE) && (ibs != ctx->ibuf_size))
  329. {
  330. p1=(char *)OPENSSL_malloc((int)num);
  331. if (p1 == NULL) goto malloc_error;
  332. }
  333. if ((obs > DEFAULT_BUFFER_SIZE) && (obs != ctx->obuf_size))
  334. {
  335. p2=(char *)OPENSSL_malloc((int)num);
  336. if (p2 == NULL)
  337. {
  338. if (p1 != ctx->ibuf) OPENSSL_free(p1);
  339. goto malloc_error;
  340. }
  341. }
  342. if (ctx->ibuf != p1)
  343. {
  344. OPENSSL_free(ctx->ibuf);
  345. ctx->ibuf=p1;
  346. ctx->ibuf_off=0;
  347. ctx->ibuf_len=0;
  348. ctx->ibuf_size=ibs;
  349. }
  350. if (ctx->obuf != p2)
  351. {
  352. OPENSSL_free(ctx->obuf);
  353. ctx->obuf=p2;
  354. ctx->obuf_off=0;
  355. ctx->obuf_len=0;
  356. ctx->obuf_size=obs;
  357. }
  358. break;
  359. case BIO_C_DO_STATE_MACHINE:
  360. if (b->next_bio == NULL) return(0);
  361. BIO_clear_retry_flags(b);
  362. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  363. BIO_copy_next_retry(b);
  364. break;
  365. case BIO_CTRL_FLUSH:
  366. if (b->next_bio == NULL) return(0);
  367. if (ctx->obuf_len <= 0)
  368. {
  369. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  370. break;
  371. }
  372. for (;;)
  373. {
  374. BIO_clear_retry_flags(b);
  375. if (ctx->obuf_len > ctx->obuf_off)
  376. {
  377. r=BIO_write(b->next_bio,
  378. &(ctx->obuf[ctx->obuf_off]),
  379. ctx->obuf_len-ctx->obuf_off);
  380. #if 0
  381. fprintf(stderr,"FLUSH [%3d] %3d -> %3d\n",ctx->obuf_off,ctx->obuf_len-ctx->obuf_off,r);
  382. #endif
  383. BIO_copy_next_retry(b);
  384. if (r <= 0) return((long)r);
  385. ctx->obuf_off+=r;
  386. }
  387. else
  388. {
  389. ctx->obuf_len=0;
  390. ctx->obuf_off=0;
  391. ret=1;
  392. break;
  393. }
  394. }
  395. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  396. break;
  397. case BIO_CTRL_DUP:
  398. dbio=(BIO *)ptr;
  399. if ( !BIO_set_read_buffer_size(dbio,ctx->ibuf_size) ||
  400. !BIO_set_write_buffer_size(dbio,ctx->obuf_size))
  401. ret=0;
  402. break;
  403. default:
  404. if (b->next_bio == NULL) return(0);
  405. ret=BIO_ctrl(b->next_bio,cmd,num,ptr);
  406. break;
  407. }
  408. return(ret);
  409. malloc_error:
  410. BIOerr(BIO_F_BUFFER_CTRL,ERR_R_MALLOC_FAILURE);
  411. return(0);
  412. }
  413. static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp)
  414. {
  415. long ret=1;
  416. if (b->next_bio == NULL) return(0);
  417. switch (cmd)
  418. {
  419. default:
  420. ret=BIO_callback_ctrl(b->next_bio,cmd,fp);
  421. break;
  422. }
  423. return(ret);
  424. }
  425. static int buffer_gets(BIO *b, char *buf, int size)
  426. {
  427. BIO_F_BUFFER_CTX *ctx;
  428. int num=0,i,flag;
  429. char *p;
  430. ctx=(BIO_F_BUFFER_CTX *)b->ptr;
  431. size--; /* reserve space for a '\0' */
  432. BIO_clear_retry_flags(b);
  433. for (;;)
  434. {
  435. if (ctx->ibuf_len > 0)
  436. {
  437. p= &(ctx->ibuf[ctx->ibuf_off]);
  438. flag=0;
  439. for (i=0; (i<ctx->ibuf_len) && (i<size); i++)
  440. {
  441. *(buf++)=p[i];
  442. if (p[i] == '\n')
  443. {
  444. flag=1;
  445. i++;
  446. break;
  447. }
  448. }
  449. num+=i;
  450. size-=i;
  451. ctx->ibuf_len-=i;
  452. ctx->ibuf_off+=i;
  453. if (flag || size == 0)
  454. {
  455. *buf='\0';
  456. return(num);
  457. }
  458. }
  459. else /* read another chunk */
  460. {
  461. i=BIO_read(b->next_bio,ctx->ibuf,ctx->ibuf_size);
  462. if (i <= 0)
  463. {
  464. BIO_copy_next_retry(b);
  465. *buf='\0';
  466. if (i < 0) return((num > 0)?num:i);
  467. if (i == 0) return(num);
  468. }
  469. ctx->ibuf_len=i;
  470. ctx->ibuf_off=0;
  471. }
  472. }
  473. }
  474. static int buffer_puts(BIO *b, const char *str)
  475. {
  476. return(buffer_write(b,str,strlen(str)));
  477. }