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