bio_lib.c revision 160814
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)(BIO *,int,const char *,int,long,long); 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)(BIO *,int,const char *,int,long,long); 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)(BIO *,int,const char *,int,long,long); 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)(BIO *,int,const char *,int,long,long); 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)(BIO *,int,const char *,int,long,long); 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)(BIO *,int,const char *,int,long,long); 336 337 if (b == NULL) return(0); 338 339 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) 340 { 341 BIOerr(BIO_F_BIO_CALLBACK_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 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 410BIO *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 426int BIO_get_retry_reason(BIO *bio) 427 { 428 return(bio->retry_reason); 429 } 430 431BIO *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 454BIO *BIO_next(BIO *b) 455 { 456 if(!b) return NULL; 457 return b->next_bio; 458 } 459 460void 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 476BIO *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); 515err: 516 if (ret != NULL) 517 BIO_free(ret); 518 return(NULL); 519 } 520 521void 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 527int 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 534int BIO_set_ex_data(BIO *bio, int idx, void *data) 535 { 536 return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); 537 } 538 539void *BIO_get_ex_data(BIO *bio, int idx) 540 { 541 return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); 542 } 543 544unsigned long BIO_number_read(BIO *bio) 545{ 546 if(bio) return bio->num_read; 547 return 0; 548} 549 550unsigned long BIO_number_written(BIO *bio) 551{ 552 if(bio) return bio->num_write; 553 return 0; 554} 555 556IMPLEMENT_STACK_OF(BIO) 557