bio_lib.c revision 109998
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 66BIO *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 84int 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 111int 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 141void BIO_vfree(BIO *a) 142 { BIO_free(a); } 143 144int 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 176int 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 211int 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 244int 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 275int 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 287long 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 295char *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 305long 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 332long 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. */ 362size_t BIO_ctrl_pending(BIO *bio) 363 { 364 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 365 } 366 367size_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 */ 374BIO *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 */ 391BIO *BIO_pop(BIO *b) 392 { 393 BIO *ret; 394 395 if (b == NULL) return(NULL); 396 ret=b->next_bio; 397 398 if (b->prev_bio != NULL) 399 b->prev_bio->next_bio=b->next_bio; 400 if (b->next_bio != NULL) 401 b->next_bio->prev_bio=b->prev_bio; 402 403 b->next_bio=NULL; 404 b->prev_bio=NULL; 405 BIO_ctrl(b,BIO_CTRL_POP,0,NULL); 406 return(ret); 407 } 408 409BIO *BIO_get_retry_BIO(BIO *bio, int *reason) 410 { 411 BIO *b,*last; 412 413 b=last=bio; 414 for (;;) 415 { 416 if (!BIO_should_retry(b)) break; 417 last=b; 418 b=b->next_bio; 419 if (b == NULL) break; 420 } 421 if (reason != NULL) *reason=last->retry_reason; 422 return(last); 423 } 424 425int BIO_get_retry_reason(BIO *bio) 426 { 427 return(bio->retry_reason); 428 } 429 430BIO *BIO_find_type(BIO *bio, int type) 431 { 432 int mt,mask; 433 434 if(!bio) return NULL; 435 mask=type&0xff; 436 do { 437 if (bio->method != NULL) 438 { 439 mt=bio->method->type; 440 441 if (!mask) 442 { 443 if (mt & type) return(bio); 444 } 445 else if (mt == type) 446 return(bio); 447 } 448 bio=bio->next_bio; 449 } while (bio != NULL); 450 return(NULL); 451 } 452 453BIO *BIO_next(BIO *b) 454 { 455 if(!b) return NULL; 456 return b->next_bio; 457 } 458 459void BIO_free_all(BIO *bio) 460 { 461 BIO *b; 462 int ref; 463 464 while (bio != NULL) 465 { 466 b=bio; 467 ref=b->references; 468 bio=bio->next_bio; 469 BIO_free(b); 470 /* Since ref count > 1, don't free anyone else. */ 471 if (ref > 1) break; 472 } 473 } 474 475BIO *BIO_dup_chain(BIO *in) 476 { 477 BIO *ret=NULL,*eoc=NULL,*bio,*new; 478 479 for (bio=in; bio != NULL; bio=bio->next_bio) 480 { 481 if ((new=BIO_new(bio->method)) == NULL) goto err; 482 new->callback=bio->callback; 483 new->cb_arg=bio->cb_arg; 484 new->init=bio->init; 485 new->shutdown=bio->shutdown; 486 new->flags=bio->flags; 487 488 /* This will let SSL_s_sock() work with stdin/stdout */ 489 new->num=bio->num; 490 491 if (!BIO_dup_state(bio,(char *)new)) 492 { 493 BIO_free(new); 494 goto err; 495 } 496 497 /* copy app data */ 498 if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_BIO, &new->ex_data, 499 &bio->ex_data)) 500 goto err; 501 502 if (ret == NULL) 503 { 504 eoc=new; 505 ret=eoc; 506 } 507 else 508 { 509 BIO_push(eoc,new); 510 eoc=new; 511 } 512 } 513 return(ret); 514err: 515 if (ret != NULL) 516 BIO_free(ret); 517 return(NULL); 518 } 519 520void BIO_copy_next_retry(BIO *b) 521 { 522 BIO_set_flags(b,BIO_get_retry_flags(b->next_bio)); 523 b->retry_reason=b->next_bio->retry_reason; 524 } 525 526int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 527 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 528 { 529 return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_BIO, argl, argp, 530 new_func, dup_func, free_func); 531 } 532 533int BIO_set_ex_data(BIO *bio, int idx, void *data) 534 { 535 return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); 536 } 537 538void *BIO_get_ex_data(BIO *bio, int idx) 539 { 540 return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); 541 } 542 543unsigned long BIO_number_read(BIO *bio) 544{ 545 if(bio) return bio->num_read; 546 return 0; 547} 548 549unsigned long BIO_number_written(BIO *bio) 550{ 551 if(bio) return bio->num_write; 552 return 0; 553} 554 555IMPLEMENT_STACK_OF(BIO) 556