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