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