size_tification.
[openssl.git] / crypto / bio / bio_lib.c
1 /* crypto/bio/bio_lib.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
59 #include <stdio.h>
60 #include <errno.h>
61 #include <openssl/crypto.h>
62 #include "cryptlib.h"
63 #include <openssl/bio.h>
64 #include <openssl/stack.h>
65
66 BIO *BIO_new(BIO_METHOD *method)
67         {
68         BIO *ret=NULL;
69
70         ret=(BIO *)OPENSSL_malloc(sizeof(BIO));
71         if (ret == NULL)
72                 {
73                 BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
74                 return(NULL);
75                 }
76         if (!BIO_set(ret,method))
77                 {
78                 OPENSSL_free(ret);
79                 ret=NULL;
80                 }
81         return(ret);
82         }
83
84 int BIO_set(BIO *bio, BIO_METHOD *method)
85         {
86         bio->method=method;
87         bio->callback=NULL;
88         bio->cb_arg=NULL;
89         bio->init=0;
90         bio->shutdown=1;
91         bio->flags=0;
92         bio->retry_reason=0;
93         bio->num=0;
94         bio->ptr=NULL;
95         bio->prev_bio=NULL;
96         bio->next_bio=NULL;
97         bio->references=1;
98         bio->num_read=0L;
99         bio->num_write=0L;
100         CRYPTO_new_ex_data(CRYPTO_EX_INDEX_BIO, bio, &bio->ex_data);
101         if (method->create != NULL)
102                 if (!method->create(bio))
103                         {
104                         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, bio,
105                                         &bio->ex_data);
106                         return(0);
107                         }
108         return(1);
109         }
110
111 int BIO_free(BIO *a)
112         {
113         int ret=0,i;
114
115         if (a == NULL) return(0);
116
117         i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
118 #ifdef REF_PRINT
119         REF_PRINT("BIO",a);
120 #endif
121         if (i > 0) return(1);
122 #ifdef REF_CHECK
123         if (i < 0)
124                 {
125                 fprintf(stderr,"BIO_free, bad reference count\n");
126                 abort();
127                 }
128 #endif
129         if ((a->callback != NULL) &&
130                 ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
131                         return(i);
132
133         CRYPTO_free_ex_data(CRYPTO_EX_INDEX_BIO, a, &a->ex_data);
134
135         if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
136         ret=a->method->destroy(a);
137         OPENSSL_free(a);
138         return(1);
139         }
140
141 void BIO_vfree(BIO *a)
142     { BIO_free(a); }
143
144 void BIO_clear_flags(BIO *b, int flags)
145         {
146         b->flags &= ~flags;
147         }
148
149 int     BIO_test_flags(const BIO *b, int flags)
150         {
151         return (b->flags & flags);
152         }
153
154 void    BIO_set_flags(BIO *b, int flags)
155         {
156         b->flags |= flags;
157         }
158
159 long (*BIO_get_callback(const BIO *b))(struct bio_st *, int, const char *,
160                                        size_t, long, long)
161         {
162         return b->callback;
163         }
164
165 void BIO_set_callback(BIO *b, long (*cb)(struct bio_st *, int, const char *,
166                                          size_t, long, long))
167         {
168         b->callback = cb;
169         }
170
171 void BIO_set_callback_arg(BIO *b, char *arg)
172         {
173         b->cb_arg = arg;
174         }
175
176 char * BIO_get_callback_arg(const BIO *b)
177         {
178         return b->cb_arg;
179         }
180
181 const char * BIO_method_name(const BIO *b)
182         {
183         return b->method->name;
184         }
185
186 int BIO_method_type(const BIO *b)
187         {
188         return b->method->type;
189         }
190
191
192 int BIO_read(BIO *b, void *out, int outl)
193         {
194         int i;
195         long (*cb)(BIO *, int, const char *, size_t, long, long);
196
197         if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
198                 {
199                 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
200                 return(-2);
201                 }
202
203         cb=b->callback;
204         if ((cb != NULL) &&
205                 ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
206                         return(i);
207
208         if (!b->init)
209                 {
210                 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
211                 return(-2);
212                 }
213
214         i=b->method->bread(b,out,outl);
215
216         if (i > 0) b->num_read+=(unsigned long)i;
217
218         if (cb != NULL)
219                 i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
220                         0L,(long)i);
221         return(i);
222         }
223
224 int BIO_write(BIO *b, const void *in, size_t inl)
225         {
226         int i;
227         long (*cb)(BIO *,int,const char *,size_t,long,long);
228
229         if (b == NULL)
230                 return(0);
231
232         cb=b->callback;
233         if ((b->method == NULL) || (b->method->bwrite == NULL))
234                 {
235                 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
236                 return(-2);
237                 }
238
239         if ((cb != NULL) &&
240                 ((i=cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
241                         return(i);
242
243         if (!b->init)
244                 {
245                 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
246                 return(-2);
247                 }
248
249         i=b->method->bwrite(b,in,inl);
250
251         if (i > 0) b->num_write+=(unsigned long)i;
252
253         if (cb != NULL)
254                 i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
255                         0L,(long)i);
256         return(i);
257         }
258
259 int BIO_puts(BIO *b, const char *in)
260         {
261         int i;
262         long (*cb)(BIO *, int, const char *, size_t, long, long);
263
264         if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
265                 {
266                 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
267                 return(-2);
268                 }
269
270         cb=b->callback;
271
272         if ((cb != NULL) &&
273                 ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
274                         return(i);
275
276         if (!b->init)
277                 {
278                 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
279                 return(-2);
280                 }
281
282         i=b->method->bputs(b,in);
283
284         if (i > 0) b->num_write+=(unsigned long)i;
285
286         if (cb != NULL)
287                 i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
288                         0L,(long)i);
289         return(i);
290         }
291
292 int BIO_gets(BIO *b, char *in, int inl)
293         {
294         int i;
295         long (*cb)(BIO *, int, const char *, size_t, long, long);
296
297         if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
298                 {
299                 BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
300                 return(-2);
301                 }
302
303         cb=b->callback;
304
305         if ((cb != NULL) &&
306                 ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
307                         return(i);
308
309         if (!b->init)
310                 {
311                 BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
312                 return(-2);
313                 }
314
315         i=b->method->bgets(b,in,inl);
316
317         if (cb != NULL)
318                 i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
319                         0L,(long)i);
320         return(i);
321         }
322
323 int BIO_indent(BIO *b,int indent,int max)
324         {
325         if(indent < 0)
326                 indent=0;
327         if(indent > max)
328                 indent=max;
329         while(indent--)
330                 if(BIO_puts(b," ") != 1)
331                         return 0;
332         return 1;
333         }
334
335 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
336         {
337         int i;
338
339         i=iarg;
340         return(BIO_ctrl(b,cmd,larg,(char *)&i));
341         }
342
343 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
344         {
345         char *p=NULL;
346
347         if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
348                 return(NULL);
349         else
350                 return(p);
351         }
352
353 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
354         {
355         long ret;
356         long (*cb)(BIO *, int, const char *, size_t, long, long);
357
358         if (b == NULL) return(0);
359
360         if ((b->method == NULL) || (b->method->ctrl == NULL))
361                 {
362                 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
363                 return(-2);
364                 }
365
366         cb=b->callback;
367
368         if ((cb != NULL) &&
369                 ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
370                 return(ret);
371
372         ret=b->method->ctrl(b,cmd,larg,parg);
373
374         if (cb != NULL)
375                 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
376                         larg,ret);
377         return(ret);
378         }
379
380 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
381         {
382         long ret;
383         long (*cb)(BIO *, int, const char *, size_t, long, long);
384
385         if (b == NULL) return(0);
386
387         if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
388                 {
389                 BIOerr(BIO_F_BIO_CALLBACK_CTRL,BIO_R_UNSUPPORTED_METHOD);
390                 return(-2);
391                 }
392
393         cb=b->callback;
394
395         if ((cb != NULL) &&
396                 ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
397                 return(ret);
398
399         ret=b->method->callback_ctrl(b,cmd,fp);
400
401         if (cb != NULL)
402                 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
403                         0,ret);
404         return(ret);
405         }
406
407 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
408  * do; but those macros have inappropriate return type, and for interfacing
409  * from other programming languages, C macros aren't much of a help anyway. */
410 size_t BIO_ctrl_pending(BIO *bio)
411         {
412         return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
413         }
414
415 size_t BIO_ctrl_wpending(BIO *bio)
416         {
417         return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
418         }
419
420
421 /* put the 'bio' on the end of b's list of operators */
422 BIO *BIO_push(BIO *b, BIO *bio)
423         {
424         BIO *lb;
425
426         if (b == NULL) return(bio);
427         lb=b;
428         while (lb->next_bio != NULL)
429                 lb=lb->next_bio;
430         lb->next_bio=bio;
431         if (bio != NULL)
432                 bio->prev_bio=lb;
433         /* called to do internal processing */
434         BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
435         return(b);
436         }
437
438 /* Remove the first and return the rest */
439 BIO *BIO_pop(BIO *b)
440         {
441         BIO *ret;
442
443         if (b == NULL) return(NULL);
444         ret=b->next_bio;
445
446         BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
447
448         if (b->prev_bio != NULL)
449                 b->prev_bio->next_bio=b->next_bio;
450         if (b->next_bio != NULL)
451                 b->next_bio->prev_bio=b->prev_bio;
452
453         b->next_bio=NULL;
454         b->prev_bio=NULL;
455         return(ret);
456         }
457
458 BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
459         {
460         BIO *b,*last;
461
462         b=last=bio;
463         for (;;)
464                 {
465                 if (!BIO_should_retry(b)) break;
466                 last=b;
467                 b=b->next_bio;
468                 if (b == NULL) break;
469                 }
470         if (reason != NULL) *reason=last->retry_reason;
471         return(last);
472         }
473
474 int BIO_get_retry_reason(BIO *bio)
475         {
476         return(bio->retry_reason);
477         }
478
479 BIO *BIO_find_type(BIO *bio, int type)
480         {
481         int mt,mask;
482
483         if(!bio) return NULL;
484         mask=type&0xff;
485         do      {
486                 if (bio->method != NULL)
487                         {
488                         mt=bio->method->type;
489
490                         if (!mask)
491                                 {
492                                 if (mt & type) return(bio);
493                                 }
494                         else if (mt == type)
495                                 return(bio);
496                         }
497                 bio=bio->next_bio;
498                 } while (bio != NULL);
499         return(NULL);
500         }
501
502 BIO *BIO_next(BIO *b)
503         {
504         if(!b) return NULL;
505         return b->next_bio;
506         }
507
508 void BIO_free_all(BIO *bio)
509         {
510         BIO *b;
511         int ref;
512
513         while (bio != NULL)
514                 {
515                 b=bio;
516                 ref=b->references;
517                 bio=bio->next_bio;
518                 BIO_free(b);
519                 /* Since ref count > 1, don't free anyone else. */
520                 if (ref > 1) break;
521                 }
522         }
523
524 BIO *BIO_dup_chain(BIO *in)
525         {
526         BIO *ret=NULL,*eoc=NULL,*bio,*new;
527
528         for (bio=in; bio != NULL; bio=bio->next_bio)
529                 {
530                 if ((new=BIO_new(bio->method)) == NULL) goto err;
531                 new->callback=bio->callback;
532                 new->cb_arg=bio->cb_arg;
533                 new->init=bio->init;
534                 new->shutdown=bio->shutdown;
535                 new->flags=bio->flags;
536
537                 /* This will let SSL_s_sock() work with stdin/stdout */
538                 new->num=bio->num;
539
540                 if (!BIO_dup_state(bio,(char *)new))
541                         {
542                         BIO_free(new);
543                         goto err;
544                         }
545
546                 /* copy app data */
547                 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
548                                         &bio->ex_data))
549                         goto err;
550
551                 if (ret == NULL)
552                         {
553                         eoc=new;
554                         ret=eoc;
555                         }
556                 else
557                         {
558                         BIO_push(eoc,new);
559                         eoc=new;
560                         }
561                 }
562         return(ret);
563 err:
564         if (ret != NULL)
565                 BIO_free(ret);
566         return(NULL);   
567         }
568
569 void BIO_copy_next_retry(BIO *b)
570         {
571         BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
572         b->retry_reason=b->next_bio->retry_reason;
573         }
574
575 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
576              CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
577         {
578         return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
579                                 new_func, dup_func, free_func);
580         }
581
582 int BIO_set_ex_data(BIO *bio, int idx, void *data)
583         {
584         return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
585         }
586
587 void *BIO_get_ex_data(BIO *bio, int idx)
588         {
589         return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
590         }
591
592 unsigned long BIO_number_read(BIO *bio)
593 {
594         if(bio) return bio->num_read;
595         return 0;
596 }
597
598 unsigned long BIO_number_written(BIO *bio)
599 {
600         if(bio) return bio->num_write;
601         return 0;
602 }
603
604 IMPLEMENT_STACK_OF(BIO)