bio_lib.c revision 109998
1139825Simp/* crypto/bio/bio_lib.c */ 268549Sbenno/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 368549Sbenno * All rights reserved. 468549Sbenno * 568549Sbenno * This package is an SSL implementation written 668549Sbenno * by Eric Young (eay@cryptsoft.com). 768549Sbenno * The implementation was written so as to conform with Netscapes SSL. 868549Sbenno * 968549Sbenno * This library is free for commercial and non-commercial use as long as 1068549Sbenno * the following conditions are aheared to. The following conditions 1168549Sbenno * apply to all code found in this distribution, be it the RC4, RSA, 1268549Sbenno * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1368549Sbenno * included with this distribution is covered by the same copyright terms 1468549Sbenno * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1568549Sbenno * 1668549Sbenno * Copyright remains Eric Young's, and as such any Copyright notices in 1768549Sbenno * the code are not to be removed. 1868549Sbenno * If this package is used in a product, Eric Young should be given attribution 1968549Sbenno * as the author of the parts of the library used. 2068549Sbenno * This can be in the form of a textual message at program startup or 2168549Sbenno * in documentation (online or textual) provided with the package. 2268549Sbenno * 2368549Sbenno * Redistribution and use in source and binary forms, with or without 2468549Sbenno * modification, are permitted provided that the following conditions 2568549Sbenno * are met: 2668549Sbenno * 1. Redistributions of source code must retain the copyright 2768549Sbenno * notice, this list of conditions and the following disclaimer. 2868549Sbenno * 2. Redistributions in binary form must reproduce the above copyright 2968549Sbenno * notice, this list of conditions and the following disclaimer in the 3070585Sobrien * documentation and/or other materials provided with the distribution. 3170585Sobrien * 3. All advertising materials mentioning features or use of this software 3270585Sobrien * must display the following acknowledgement: 3368549Sbenno * "This product includes cryptographic software written by 3470585Sobrien * Eric Young (eay@cryptsoft.com)" 3568549Sbenno * The word 'cryptographic' can be left out if the rouines from the library 3668549Sbenno * being used are not cryptographic related :-). 3768549Sbenno * 4. If you include any Windows specific code (or a derivative thereof) from 38126474Sgrehan * the apps directory (application code) you must include an acknowledgement: 39126474Sgrehan * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40126474Sgrehan * 41126474Sgrehan * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42126474Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43126474Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44126474Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45295561Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46295561Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47295561Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48295561Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49295561Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50126474Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5168549Sbenno * SUCH DAMAGE. 52209975Snwhitehorn * 53209975Snwhitehorn * The licence and distribution terms for any publically available version or 54209975Snwhitehorn * derivative of this code cannot be changed. i.e. this code cannot simply be 55209975Snwhitehorn * copied and put under another distribution licence 56209975Snwhitehorn * [including the GNU Public Licence.] 57209975Snwhitehorn */ 58209975Snwhitehorn 59209975Snwhitehorn#include <stdio.h> 60209975Snwhitehorn#include <errno.h> 61209975Snwhitehorn#include <openssl/crypto.h> 62209975Snwhitehorn#include "cryptlib.h" 63209975Snwhitehorn#include <openssl/bio.h> 64279937Snwhitehorn#include <openssl/stack.h> 65209975Snwhitehorn 66209975SnwhitehornBIO *BIO_new(BIO_METHOD *method) 67209975Snwhitehorn { 68126474Sgrehan BIO *ret=NULL; 69126474Sgrehan 70126474Sgrehan ret=(BIO *)OPENSSL_malloc(sizeof(BIO)); 71126474Sgrehan if (ret == NULL) 72126474Sgrehan { 73126474Sgrehan BIOerr(BIO_F_BIO_NEW,ERR_R_MALLOC_FAILURE); 74126474Sgrehan return(NULL); 75126474Sgrehan } 76234542Snwhitehorn if (!BIO_set(ret,method)) 77234542Snwhitehorn { 78234542Snwhitehorn OPENSSL_free(ret); 7968549Sbenno ret=NULL; 80126474Sgrehan } 81126474Sgrehan return(ret); 8268549Sbenno } 83126474Sgrehan 84126474Sgrehanint BIO_set(BIO *bio, BIO_METHOD *method) 85126474Sgrehan { 86126474Sgrehan bio->method=method; 87126474Sgrehan bio->callback=NULL; 88132380Sgrehan bio->cb_arg=NULL; 89126474Sgrehan bio->init=0; 9068549Sbenno 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