Add OpenSSL 0.9.7d.
[dragonfly.git] / crypto / openssl-0.9.7d / 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 int BIO_read(BIO *b, void *out, int outl)
145         {
146         int i;
147         long (*cb)();
148
149         if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL))
150                 {
151                 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD);
152                 return(-2);
153                 }
154
155         cb=b->callback;
156         if ((cb != NULL) &&
157                 ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0))
158                         return(i);
159
160         if (!b->init)
161                 {
162                 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED);
163                 return(-2);
164                 }
165
166         i=b->method->bread(b,out,outl);
167
168         if (i > 0) b->num_read+=(unsigned long)i;
169
170         if (cb != NULL)
171                 i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl,
172                         0L,(long)i);
173         return(i);
174         }
175
176 int BIO_write(BIO *b, const void *in, int inl)
177         {
178         int i;
179         long (*cb)();
180
181         if (b == NULL)
182                 return(0);
183
184         cb=b->callback;
185         if ((b->method == NULL) || (b->method->bwrite == NULL))
186                 {
187                 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD);
188                 return(-2);
189                 }
190
191         if ((cb != NULL) &&
192                 ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0))
193                         return(i);
194
195         if (!b->init)
196                 {
197                 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED);
198                 return(-2);
199                 }
200
201         i=b->method->bwrite(b,in,inl);
202
203         if (i > 0) b->num_write+=(unsigned long)i;
204
205         if (cb != NULL)
206                 i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl,
207                         0L,(long)i);
208         return(i);
209         }
210
211 int BIO_puts(BIO *b, const char *in)
212         {
213         int i;
214         long (*cb)();
215
216         if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL))
217                 {
218                 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD);
219                 return(-2);
220                 }
221
222         cb=b->callback;
223
224         if ((cb != NULL) &&
225                 ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0))
226                         return(i);
227
228         if (!b->init)
229                 {
230                 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED);
231                 return(-2);
232                 }
233
234         i=b->method->bputs(b,in);
235
236         if (i > 0) b->num_write+=(unsigned long)i;
237
238         if (cb != NULL)
239                 i=(int)cb(b,BIO_CB_PUTS|BIO_CB_RETURN,in,0,
240                         0L,(long)i);
241         return(i);
242         }
243
244 int BIO_gets(BIO *b, char *in, int inl)
245         {
246         int i;
247         long (*cb)();
248
249         if ((b == NULL) || (b->method == NULL) || (b->method->bgets == NULL))
250                 {
251                 BIOerr(BIO_F_BIO_GETS,BIO_R_UNSUPPORTED_METHOD);
252                 return(-2);
253                 }
254
255         cb=b->callback;
256
257         if ((cb != NULL) &&
258                 ((i=(int)cb(b,BIO_CB_GETS,in,inl,0L,1L)) <= 0))
259                         return(i);
260
261         if (!b->init)
262                 {
263                 BIOerr(BIO_F_BIO_GETS,BIO_R_UNINITIALIZED);
264                 return(-2);
265                 }
266
267         i=b->method->bgets(b,in,inl);
268
269         if (cb != NULL)
270                 i=(int)cb(b,BIO_CB_GETS|BIO_CB_RETURN,in,inl,
271                         0L,(long)i);
272         return(i);
273         }
274
275 int BIO_indent(BIO *b,int indent,int max)
276         {
277         if(indent < 0)
278                 indent=0;
279         if(indent > max)
280                 indent=max;
281         while(indent--)
282                 if(BIO_puts(b," ") != 1)
283                         return 0;
284         return 1;
285         }
286
287 long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg)
288         {
289         int i;
290
291         i=iarg;
292         return(BIO_ctrl(b,cmd,larg,(char *)&i));
293         }
294
295 char *BIO_ptr_ctrl(BIO *b, int cmd, long larg)
296         {
297         char *p=NULL;
298
299         if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0)
300                 return(NULL);
301         else
302                 return(p);
303         }
304
305 long BIO_ctrl(BIO *b, int cmd, long larg, void *parg)
306         {
307         long ret;
308         long (*cb)();
309
310         if (b == NULL) return(0);
311
312         if ((b->method == NULL) || (b->method->ctrl == NULL))
313                 {
314                 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
315                 return(-2);
316                 }
317
318         cb=b->callback;
319
320         if ((cb != NULL) &&
321                 ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0))
322                 return(ret);
323
324         ret=b->method->ctrl(b,cmd,larg,parg);
325
326         if (cb != NULL)
327                 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd,
328                         larg,ret);
329         return(ret);
330         }
331
332 long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)(struct bio_st *, int, const char *, int, long, long))
333         {
334         long ret;
335         long (*cb)();
336
337         if (b == NULL) return(0);
338
339         if ((b->method == NULL) || (b->method->callback_ctrl == NULL))
340                 {
341                 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD);
342                 return(-2);
343                 }
344
345         cb=b->callback;
346
347         if ((cb != NULL) &&
348                 ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0))
349                 return(ret);
350
351         ret=b->method->callback_ctrl(b,cmd,fp);
352
353         if (cb != NULL)
354                 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd,
355                         0,ret);
356         return(ret);
357         }
358
359 /* It is unfortunate to duplicate in functions what the BIO_(w)pending macros
360  * do; but those macros have inappropriate return type, and for interfacing
361  * from other programming languages, C macros aren't much of a help anyway. */
362 size_t BIO_ctrl_pending(BIO *bio)
363         {
364         return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL);
365         }
366
367 size_t BIO_ctrl_wpending(BIO *bio)
368         {
369         return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL);
370         }
371
372
373 /* put the 'bio' on the end of b's list of operators */
374 BIO *BIO_push(BIO *b, BIO *bio)
375         {
376         BIO *lb;
377
378         if (b == NULL) return(bio);
379         lb=b;
380         while (lb->next_bio != NULL)
381                 lb=lb->next_bio;
382         lb->next_bio=bio;
383         if (bio != NULL)
384                 bio->prev_bio=lb;
385         /* called to do internal processing */
386         BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL);
387         return(b);
388         }
389
390 /* Remove the first and return the rest */
391 BIO *BIO_pop(BIO *b)
392         {
393         BIO *ret;
394
395         if (b == NULL) return(NULL);
396         ret=b->next_bio;
397
398         BIO_ctrl(b,BIO_CTRL_POP,0,NULL);
399
400         if (b->prev_bio != NULL)
401                 b->prev_bio->next_bio=b->next_bio;
402         if (b->next_bio != NULL)
403                 b->next_bio->prev_bio=b->prev_bio;
404
405         b->next_bio=NULL;
406         b->prev_bio=NULL;
407         return(ret);
408         }
409
410 BIO *BIO_get_retry_BIO(BIO *bio, int *reason)
411         {
412         BIO *b,*last;
413
414         b=last=bio;
415         for (;;)
416                 {
417                 if (!BIO_should_retry(b)) break;
418                 last=b;
419                 b=b->next_bio;
420                 if (b == NULL) break;
421                 }
422         if (reason != NULL) *reason=last->retry_reason;
423         return(last);
424         }
425
426 int BIO_get_retry_reason(BIO *bio)
427         {
428         return(bio->retry_reason);
429         }
430
431 BIO *BIO_find_type(BIO *bio, int type)
432         {
433         int mt,mask;
434
435         if(!bio) return NULL;
436         mask=type&0xff;
437         do      {
438                 if (bio->method != NULL)
439                         {
440                         mt=bio->method->type;
441
442                         if (!mask)
443                                 {
444                                 if (mt & type) return(bio);
445                                 }
446                         else if (mt == type)
447                                 return(bio);
448                         }
449                 bio=bio->next_bio;
450                 } while (bio != NULL);
451         return(NULL);
452         }
453
454 BIO *BIO_next(BIO *b)
455         {
456         if(!b) return NULL;
457         return b->next_bio;
458         }
459
460 void BIO_free_all(BIO *bio)
461         {
462         BIO *b;
463         int ref;
464
465         while (bio != NULL)
466                 {
467                 b=bio;
468                 ref=b->references;
469                 bio=bio->next_bio;
470                 BIO_free(b);
471                 /* Since ref count > 1, don't free anyone else. */
472                 if (ref > 1) break;
473                 }
474         }
475
476 BIO *BIO_dup_chain(BIO *in)
477         {
478         BIO *ret=NULL,*eoc=NULL,*bio,*new;
479
480         for (bio=in; bio != NULL; bio=bio->next_bio)
481                 {
482                 if ((new=BIO_new(bio->method)) == NULL) goto err;
483                 new->callback=bio->callback;
484                 new->cb_arg=bio->cb_arg;
485                 new->init=bio->init;
486                 new->shutdown=bio->shutdown;
487                 new->flags=bio->flags;
488
489                 /* This will let SSL_s_sock() work with stdin/stdout */
490                 new->num=bio->num;
491
492                 if (!BIO_dup_state(bio,(char *)new))
493                         {
494                         BIO_free(new);
495                         goto err;
496                         }
497
498                 /* copy app data */
499                 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data,
500                                         &bio->ex_data))
501                         goto err;
502
503                 if (ret == NULL)
504                         {
505                         eoc=new;
506                         ret=eoc;
507                         }
508                 else
509                         {
510                         BIO_push(eoc,new);
511                         eoc=new;
512                         }
513                 }
514         return(ret);
515 err:
516         if (ret != NULL)
517                 BIO_free(ret);
518         return(NULL);   
519         }
520
521 void BIO_copy_next_retry(BIO *b)
522         {
523         BIO_set_flags(b,BIO_get_retry_flags(b->next_bio));
524         b->retry_reason=b->next_bio->retry_reason;
525         }
526
527 int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
528              CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
529         {
530         return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp,
531                                 new_func, dup_func, free_func);
532         }
533
534 int BIO_set_ex_data(BIO *bio, int idx, void *data)
535         {
536         return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data));
537         }
538
539 void *BIO_get_ex_data(BIO *bio, int idx)
540         {
541         return(CRYPTO_get_ex_data(&(bio->ex_data),idx));
542         }
543
544 unsigned long BIO_number_read(BIO *bio)
545 {
546         if(bio) return bio->num_read;
547         return 0;
548 }
549
550 unsigned long BIO_number_written(BIO *bio)
551 {
552         if(bio) return bio->num_write;
553         return 0;
554 }
555
556 IMPLEMENT_STACK_OF(BIO)