Import of old SSLeay release: SSLeay 0.8.1b
[openssl.git] / crypto / bio / bio_lib.c
1 /* crypto/bio/bio_lib.c */
2 /* Copyright (C) 1995-1997 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 "cryptlib.h"
62 #include "bio.h"
63
64 BIO *BIO_new(method)
65 BIO_METHOD *method;
66         {
67         BIO *ret=NULL;
68
69         ret=(BIO *)Malloc(sizeof(BIO));
70         if (ret == NULL)
71                 {
72                 BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE);
73                 return(NULL);
74                 }
75         if (!BIO_set(ret,method))
76                 {
77                 Free(ret);
78                 ret=NULL;
79                 }
80         return(ret);
81         }
82
83 int BIO_set(bio,method)
84 BIO *bio;
85 BIO_METHOD *method;
86         {
87         bio->method=method;
88         bio->callback=NULL;
89         bio->cb_arg=NULL;
90         bio->init=0;
91         bio->shutdown=1;
92         bio->num=0;
93         bio->flags=0;
94         bio->retry_reason=0;
95         bio->ptr=NULL;
96         bio->prev_bio=NULL;
97         bio->next_bio=NULL;
98         bio->references=1;
99         bio->num_read=0L;
100         bio->num_write=0L;
101         if (method->create != NULL)
102                 if (!method->create(bio))
103                         return(0);
104         return(1);
105         }
106
107 int BIO_free(a)
108 BIO *a;
109         {
110         int ret=0,i;
111
112         if (a == NULL) return(0);
113
114         i=CRYPTO_add(&a->references,-1,CRYPTO_LOCK_BIO);
115
116         if (i > 0) return(1);
117 #ifdef REF_CHECK
118         if (i < 0)
119                 {
120                 fprintf(stderr,"BIO_free, bad reference count\n");
121                 abort();
122                 }
123 #endif
124         if ((a->callback != NULL) &&
125                 ((i=(int)a->callback(a,BIO_CB_FREE,NULL,0,0L,1L)) <= 0))
126                         return(i);
127
128         if ((a->method == NULL) || (a->method->destroy == NULL)) return(1);
129         ret=a->method->destroy(a);
130         Free(a);
131         return(1);
132         }
133
134 int BIO_read(b,out,outl)
135 BIO *b;
136 char *out;
137 int outl;
138         {
139         int i;
140
141         if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
142                 {
143                 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
144                 return(-2);
145                 }
146
147         if ((b->callback != NULL) &&
148                 ((i=(int)b->callback(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
149                         return(i);
150
151         if (!b->init)
152                 {
153                 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITALISED);
154                 return(-2);
155                 }
156
157         i=b->method->bread(b,out,outl);
158         if (i > 0) b->num_read+=(unsigned long)i;
159
160         if (b->callback != NULL)
161                 i=(int)b->callback(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
162                         0L,(long)i);
163         return(i);
164         }
165
166 int BIO_write(b,in,inl)
167 BIO *b;
168 char *in;
169 int inl;
170         {
171         int i;
172
173         if ((b == NULL) || (b->method == NULL) || (b->method->bwrite == NULL))
174                 {
175                 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
176                 return(-2);
177                 }
178
179         if ((b->callback != NULL) &&
180                 ((i=(int)b->callback(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
181                         return(i);
182
183         if (!b->init)
184                 {
185                 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITALISED);
186                 return(-2);
187                 }
188
189         i=b->method->bwrite(b,in,inl);
190         if (i > 0) b->num_write+=(unsigned long)i;
191
192         if (b->callback != NULL)
193                 i=(int)b->callback(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
194                         0L,(long)i);
195         return(i);
196         }
197
198 int BIO_puts(b,in)
199 BIO *b;
200 char *in;
201         {
202         int i;
203
204         if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
205                 {
206                 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
207                 return(-2);
208                 }
209
210         if ((b->callback != NULL) &&
211                 ((i=(int)b->callback(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
212                         return(i);
213
214         if (!b->init)
215                 {
216                 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITALISED);
217                 return(-2);
218                 }
219
220         i=b->method->bputs(b,in);
221
222         if (b->callback != NULL)
223                 i=(int)b->callback(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
224                         0L,(long)i);
225         return(i);
226         }
227
228 int BIO_gets(b,in,inl)
229 BIO *b;
230 char *in;
231 int inl;
232         {
233         int i;
234
235         if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
236                 {
237                 BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
238                 return(-2);
239                 }
240
241         if ((b->callback != NULL) &&
242                 ((i=(int)b->callback(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
243                         return(i);
244
245         if (!b->init)
246                 {
247                 BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITALISED);
248                 return(-2);
249                 }
250
251         i=b->method->bgets(b,in,inl);
252
253         if (b->callback != NULL)
254                 i=(int)b->callback(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
255                         0L,(long)i);
256         return(i);
257         }
258
259 long BIO_ctrl_int(b,cmd,larg,iarg)
260 BIO *b;
261 int cmd;
262 long larg;
263 int iarg;
264         {
265         int i;
266
267         i=iarg;
268         return(BIO_ctrl(b,cmd,larg,(char *)&i));
269         }
270
271 long BIO_ctrl(b,cmd,larg,parg)
272 BIO *b;
273 int cmd;
274 long larg;
275 char *parg;
276         {
277         long ret;
278
279         if (b == NULL) return(0);
280
281         if ((b->method == NULL) || (b->method->ctrl == NULL))
282                 {
283                 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
284                 return(-2);
285                 }
286
287         if ((b->callback != NULL) &&
288                 ((ret=b->callback(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
289                 return(ret);
290
291         ret=b->method->ctrl(b,cmd,larg,parg);
292
293         if (b->callback != NULL)
294                 ret=b->callback(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
295                         larg,ret);
296         return(ret);
297         }
298
299 /* put the 'bio' on the end of b's list of operators */
300 BIO *BIO_push(b,bio)
301 BIO *b,*bio;
302         {
303         BIO *lb;
304
305         if (b == NULL) return(bio);
306         lb=b;
307         while (lb->next_bio != NULL)
308                 lb=lb->next_bio;
309         lb->next_bio=bio;
310         if (bio != NULL)
311                 bio->prev_bio=lb;
312         BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
313         return(b);
314         }
315
316 /* Remove the first and return the rest */
317 BIO *BIO_pop(b)
318 BIO *b;
319         {
320         BIO *ret;
321
322         if (b == NULL) return(NULL);
323         ret=b->next_bio;
324
325         if (b->prev_bio != NULL)
326                 b->prev_bio->next_bio=b->next_bio;
327         if (b->next_bio != NULL)
328                 b->next_bio->prev_bio=b->prev_bio;
329
330         b->next_bio=NULL;
331         b->prev_bio=NULL;
332         BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
333         return(ret);
334         }
335
336 BIO *BIO_get_retry_BIO(bio,reason)
337 BIO *bio;
338 int *reason;
339         {
340         BIO *b,*last;
341
342         b=last=bio;
343         for (;;)
344                 {
345                 if (!BIO_should_retry(b)) break;
346                 last=b;
347                 b=b->next_bio;
348                 if (b == NULL) break;
349                 }
350         if (reason != NULL) *reason=last->retry_reason;
351         return(last);
352         }
353
354 int BIO_get_retry_reason(bio)
355 BIO *bio;
356         {
357         return(bio->retry_reason);
358         }
359
360 BIO *BIO_find_type(bio,type)
361 BIO *bio;
362 int type;
363         {
364         int mt,mask;
365
366         mask=type&0xff;
367         do      {
368                 if (bio->method != NULL)
369                         {
370                         mt=bio->method->type;
371
372                         if (!mask)
373                                 {
374                                 if (mt & type) return(bio);
375                                 }
376                         else if (mt == type)
377                                 return(bio);
378                         }
379                 bio=bio->next_bio;
380                 } while (bio != NULL);
381         return(NULL);
382         }
383
384 void BIO_free_all(bio)
385 BIO *bio;
386         {
387         BIO *b;
388         int ref;
389
390         while (bio != NULL)
391                 {
392                 b=bio;
393                 ref=b->references;
394                 bio=bio->next_bio;
395                 BIO_free(b);
396                 /* Since ref count > 1, don't free anyone else. */
397                 if (ref > 1) break;
398                 }
399         }
400
401 BIO *BIO_dup_chain(in)
402 BIO *in;
403         {
404         BIO *ret=NULL,*eoc=NULL,*bio,*new;
405
406         for (bio=in; bio != NULL; bio=bio->next_bio)
407                 {
408                 if ((new=BIO_new(bio->method)) == NULL) goto err;
409                 new->callback=bio->callback;
410                 new->cb_arg=bio->cb_arg;
411                 new->init=bio->init;
412                 new->shutdown=bio->shutdown;
413                 new->flags=bio->flags;
414
415                 /* This will let SSL_s_sock() work with stdin/stdout */
416                 new->num=bio->num;
417
418                 if (!BIO_dup_state(bio,(char *)new))
419                         {
420                         BIO_free(new);
421                         goto err;
422                         }
423                 if (ret == NULL)
424                         {
425                         eoc=new;
426                         ret=eoc;
427                         }
428                 else
429                         {
430                         BIO_push(eoc,new);
431                         eoc=new;
432                         }
433                 }
434         return(ret);
435 err:
436         if (ret != NULL)
437                 BIO_free(ret);
438         return(NULL);   
439         }
440
441 void BIO_copy_next_retry(b)
442 BIO *b;
443         {
444         BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
445         b->retry_reason=b->next_bio->retry_reason;
446         }
447