bf_buff.c 12 KB

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