bio_lib.c revision 59191
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 *)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 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 Free(a); 137 return(1); 138 } 139 140int BIO_read(BIO *b, void *out, int outl) 141 { 142 int i; 143 long (*cb)(); 144 145 if ((b == NULL) || (b->method == NULL) || (b->method->bread == NULL)) 146 { 147 BIOerr(BIO_F_BIO_READ,BIO_R_UNSUPPORTED_METHOD); 148 return(-2); 149 } 150 151 cb=b->callback; 152 if ((cb != NULL) && 153 ((i=(int)cb(b,BIO_CB_READ,out,outl,0L,1L)) <= 0)) 154 return(i); 155 156 if (!b->init) 157 { 158 BIOerr(BIO_F_BIO_READ,BIO_R_UNINITIALIZED); 159 return(-2); 160 } 161 162 i=b->method->bread(b,out,outl); 163 164 if (i > 0) b->num_read+=(unsigned long)i; 165 166 if (cb != NULL) 167 i=(int)cb(b,BIO_CB_READ|BIO_CB_RETURN,out,outl, 168 0L,(long)i); 169 return(i); 170 } 171 172int BIO_write(BIO *b, const void *in, int inl) 173 { 174 int i; 175 long (*cb)(); 176 177 if (b == NULL) 178 return(0); 179 180 cb=b->callback; 181 if ((b->method == NULL) || (b->method->bwrite == NULL)) 182 { 183 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNSUPPORTED_METHOD); 184 return(-2); 185 } 186 187 if ((cb != NULL) && 188 ((i=(int)cb(b,BIO_CB_WRITE,in,inl,0L,1L)) <= 0)) 189 return(i); 190 191 if (!b->init) 192 { 193 BIOerr(BIO_F_BIO_WRITE,BIO_R_UNINITIALIZED); 194 return(-2); 195 } 196 197 i=b->method->bwrite(b,in,inl); 198 199 if (i > 0) b->num_write+=(unsigned long)i; 200 201 /* This is evil and not thread safe. If the BIO has been freed, 202 * we must not call the callback. The only way to be able to 203 * determine this is the reference count which is now invalid since 204 * the memory has been free()ed. 205 */ 206 if (b->references <= 0) abort(); 207 if (cb != NULL) /* && (b->references >= 1)) */ 208 i=(int)cb(b,BIO_CB_WRITE|BIO_CB_RETURN,in,inl, 209 0L,(long)i); 210 return(i); 211 } 212 213int BIO_puts(BIO *b, const char *in) 214 { 215 int i; 216 long (*cb)(); 217 218 if ((b == NULL) || (b->method == NULL) || (b->method->bputs == NULL)) 219 { 220 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNSUPPORTED_METHOD); 221 return(-2); 222 } 223 224 cb=b->callback; 225 226 if ((cb != NULL) && 227 ((i=(int)cb(b,BIO_CB_PUTS,in,0,0L,1L)) <= 0)) 228 return(i); 229 230 if (!b->init) 231 { 232 BIOerr(BIO_F_BIO_PUTS,BIO_R_UNINITIALIZED); 233 return(-2); 234 } 235 236 i=b->method->bputs(b,in); 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 275long BIO_int_ctrl(BIO *b, int cmd, long larg, int iarg) 276 { 277 int i; 278 279 i=iarg; 280 return(BIO_ctrl(b,cmd,larg,(char *)&i)); 281 } 282 283char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) 284 { 285 char *p=NULL; 286 287 if (BIO_ctrl(b,cmd,larg,(char *)&p) <= 0) 288 return(NULL); 289 else 290 return(p); 291 } 292 293long BIO_ctrl(BIO *b, int cmd, long larg, void *parg) 294 { 295 long ret; 296 long (*cb)(); 297 298 if (b == NULL) return(0); 299 300 if ((b->method == NULL) || (b->method->ctrl == NULL)) 301 { 302 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); 303 return(-2); 304 } 305 306 cb=b->callback; 307 308 if ((cb != NULL) && 309 ((ret=cb(b,BIO_CB_CTRL,parg,cmd,larg,1L)) <= 0)) 310 return(ret); 311 312 ret=b->method->ctrl(b,cmd,larg,parg); 313 314 if (cb != NULL) 315 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,parg,cmd, 316 larg,ret); 317 return(ret); 318 } 319 320long BIO_callback_ctrl(BIO *b, int cmd, void (*fp)()) 321 { 322 long ret; 323 long (*cb)(); 324 325 if (b == NULL) return(0); 326 327 if ((b->method == NULL) || (b->method->callback_ctrl == NULL)) 328 { 329 BIOerr(BIO_F_BIO_CTRL,BIO_R_UNSUPPORTED_METHOD); 330 return(-2); 331 } 332 333 cb=b->callback; 334 335 if ((cb != NULL) && 336 ((ret=cb(b,BIO_CB_CTRL,(void *)&fp,cmd,0,1L)) <= 0)) 337 return(ret); 338 339 ret=b->method->callback_ctrl(b,cmd,fp); 340 341 if (cb != NULL) 342 ret=cb(b,BIO_CB_CTRL|BIO_CB_RETURN,(void *)&fp,cmd, 343 0,ret); 344 return(ret); 345 } 346 347/* It is unfortunate to duplicate in functions what the BIO_(w)pending macros 348 * do; but those macros have inappropriate return type, and for interfacing 349 * from other programming languages, C macros aren't much of a help anyway. */ 350size_t BIO_ctrl_pending(BIO *bio) 351 { 352 return BIO_ctrl(bio, BIO_CTRL_PENDING, 0, NULL); 353 } 354 355size_t BIO_ctrl_wpending(BIO *bio) 356 { 357 return BIO_ctrl(bio, BIO_CTRL_WPENDING, 0, NULL); 358 } 359 360 361/* put the 'bio' on the end of b's list of operators */ 362BIO *BIO_push(BIO *b, BIO *bio) 363 { 364 BIO *lb; 365 366 if (b == NULL) return(bio); 367 lb=b; 368 while (lb->next_bio != NULL) 369 lb=lb->next_bio; 370 lb->next_bio=bio; 371 if (bio != NULL) 372 bio->prev_bio=lb; 373 /* called to do internal processing */ 374 BIO_ctrl(b,BIO_CTRL_PUSH,0,NULL); 375 return(b); 376 } 377 378/* Remove the first and return the rest */ 379BIO *BIO_pop(BIO *b) 380 { 381 BIO *ret; 382 383 if (b == NULL) return(NULL); 384 ret=b->next_bio; 385 386 if (b->prev_bio != NULL) 387 b->prev_bio->next_bio=b->next_bio; 388 if (b->next_bio != NULL) 389 b->next_bio->prev_bio=b->prev_bio; 390 391 b->next_bio=NULL; 392 b->prev_bio=NULL; 393 BIO_ctrl(b,BIO_CTRL_POP,0,NULL); 394 return(ret); 395 } 396 397BIO *BIO_get_retry_BIO(BIO *bio, int *reason) 398 { 399 BIO *b,*last; 400 401 b=last=bio; 402 for (;;) 403 { 404 if (!BIO_should_retry(b)) break; 405 last=b; 406 b=b->next_bio; 407 if (b == NULL) break; 408 } 409 if (reason != NULL) *reason=last->retry_reason; 410 return(last); 411 } 412 413int BIO_get_retry_reason(BIO *bio) 414 { 415 return(bio->retry_reason); 416 } 417 418BIO *BIO_find_type(BIO *bio, int type) 419 { 420 int mt,mask; 421 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 440void BIO_free_all(BIO *bio) 441 { 442 BIO *b; 443 int ref; 444 445 while (bio != NULL) 446 { 447 b=bio; 448 ref=b->references; 449 bio=bio->next_bio; 450 BIO_free(b); 451 /* Since ref count > 1, don't free anyone else. */ 452 if (ref > 1) break; 453 } 454 } 455 456BIO *BIO_dup_chain(BIO *in) 457 { 458 BIO *ret=NULL,*eoc=NULL,*bio,*new; 459 460 for (bio=in; bio != NULL; bio=bio->next_bio) 461 { 462 if ((new=BIO_new(bio->method)) == NULL) goto err; 463 new->callback=bio->callback; 464 new->cb_arg=bio->cb_arg; 465 new->init=bio->init; 466 new->shutdown=bio->shutdown; 467 new->flags=bio->flags; 468 469 /* This will let SSL_s_sock() work with stdin/stdout */ 470 new->num=bio->num; 471 472 if (!BIO_dup_state(bio,(char *)new)) 473 { 474 BIO_free(new); 475 goto err; 476 } 477 478 /* copy app data */ 479 if (!CRYPTO_dup_ex_data(bio_meth,&new->ex_data,&bio->ex_data)) 480 goto err; 481 482 if (ret == NULL) 483 { 484 eoc=new; 485 ret=eoc; 486 } 487 else 488 { 489 BIO_push(eoc,new); 490 eoc=new; 491 } 492 } 493 return(ret); 494err: 495 if (ret != NULL) 496 BIO_free(ret); 497 return(NULL); 498 } 499 500void BIO_copy_next_retry(BIO *b) 501 { 502 BIO_set_flags(b,BIO_get_retry_flags(b->next_bio)); 503 b->retry_reason=b->next_bio->retry_reason; 504 } 505 506int BIO_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, 507 CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) 508 { 509 bio_meth_num++; 510 return(CRYPTO_get_ex_new_index(bio_meth_num-1,&bio_meth, 511 argl,argp,new_func,dup_func,free_func)); 512 } 513 514int BIO_set_ex_data(BIO *bio, int idx, void *data) 515 { 516 return(CRYPTO_set_ex_data(&(bio->ex_data),idx,data)); 517 } 518 519void *BIO_get_ex_data(BIO *bio, int idx) 520 { 521 return(CRYPTO_get_ex_data(&(bio->ex_data),idx)); 522 } 523 524unsigned long BIO_number_read(BIO *bio) 525{ 526 if(bio) return bio->num_read; 527 return 0; 528} 529 530unsigned long BIO_number_written(BIO *bio) 531{ 532 if(bio) return bio->num_write; 533 return 0; 534} 535