1*0Sstevel@tonic-gate /* ssl/bio_ssl.c */ 2*0Sstevel@tonic-gate /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 3*0Sstevel@tonic-gate * All rights reserved. 4*0Sstevel@tonic-gate * 5*0Sstevel@tonic-gate * This package is an SSL implementation written 6*0Sstevel@tonic-gate * by Eric Young (eay@cryptsoft.com). 7*0Sstevel@tonic-gate * The implementation was written so as to conform with Netscapes SSL. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * This library is free for commercial and non-commercial use as long as 10*0Sstevel@tonic-gate * the following conditions are aheared to. The following conditions 11*0Sstevel@tonic-gate * apply to all code found in this distribution, be it the RC4, RSA, 12*0Sstevel@tonic-gate * lhash, DES, etc., code; not just the SSL code. The SSL documentation 13*0Sstevel@tonic-gate * included with this distribution is covered by the same copyright terms 14*0Sstevel@tonic-gate * except that the holder is Tim Hudson (tjh@cryptsoft.com). 15*0Sstevel@tonic-gate * 16*0Sstevel@tonic-gate * Copyright remains Eric Young's, and as such any Copyright notices in 17*0Sstevel@tonic-gate * the code are not to be removed. 18*0Sstevel@tonic-gate * If this package is used in a product, Eric Young should be given attribution 19*0Sstevel@tonic-gate * as the author of the parts of the library used. 20*0Sstevel@tonic-gate * This can be in the form of a textual message at program startup or 21*0Sstevel@tonic-gate * in documentation (online or textual) provided with the package. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 24*0Sstevel@tonic-gate * modification, are permitted provided that the following conditions 25*0Sstevel@tonic-gate * are met: 26*0Sstevel@tonic-gate * 1. Redistributions of source code must retain the copyright 27*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 28*0Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 29*0Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 30*0Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 31*0Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 32*0Sstevel@tonic-gate * must display the following acknowledgement: 33*0Sstevel@tonic-gate * "This product includes cryptographic software written by 34*0Sstevel@tonic-gate * Eric Young (eay@cryptsoft.com)" 35*0Sstevel@tonic-gate * The word 'cryptographic' can be left out if the rouines from the library 36*0Sstevel@tonic-gate * being used are not cryptographic related :-). 37*0Sstevel@tonic-gate * 4. If you include any Windows specific code (or a derivative thereof) from 38*0Sstevel@tonic-gate * the apps directory (application code) you must include an acknowledgement: 39*0Sstevel@tonic-gate * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 40*0Sstevel@tonic-gate * 41*0Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 42*0Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43*0Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44*0Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 45*0Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46*0Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47*0Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48*0Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49*0Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50*0Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51*0Sstevel@tonic-gate * SUCH DAMAGE. 52*0Sstevel@tonic-gate * 53*0Sstevel@tonic-gate * The licence and distribution terms for any publically available version or 54*0Sstevel@tonic-gate * derivative of this code cannot be changed. i.e. this code cannot simply be 55*0Sstevel@tonic-gate * copied and put under another distribution licence 56*0Sstevel@tonic-gate * [including the GNU Public Licence.] 57*0Sstevel@tonic-gate */ 58*0Sstevel@tonic-gate 59*0Sstevel@tonic-gate #include <stdio.h> 60*0Sstevel@tonic-gate #include <stdlib.h> 61*0Sstevel@tonic-gate #include <string.h> 62*0Sstevel@tonic-gate #include <errno.h> 63*0Sstevel@tonic-gate #include <openssl/crypto.h> 64*0Sstevel@tonic-gate #include <openssl/bio.h> 65*0Sstevel@tonic-gate #include <openssl/err.h> 66*0Sstevel@tonic-gate #include <openssl/ssl.h> 67*0Sstevel@tonic-gate 68*0Sstevel@tonic-gate static int ssl_write(BIO *h, const char *buf, int num); 69*0Sstevel@tonic-gate static int ssl_read(BIO *h, char *buf, int size); 70*0Sstevel@tonic-gate static int ssl_puts(BIO *h, const char *str); 71*0Sstevel@tonic-gate static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); 72*0Sstevel@tonic-gate static int ssl_new(BIO *h); 73*0Sstevel@tonic-gate static int ssl_free(BIO *data); 74*0Sstevel@tonic-gate static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); 75*0Sstevel@tonic-gate typedef struct bio_ssl_st 76*0Sstevel@tonic-gate { 77*0Sstevel@tonic-gate SSL *ssl; /* The ssl handle :-) */ 78*0Sstevel@tonic-gate /* re-negotiate every time the total number of bytes is this size */ 79*0Sstevel@tonic-gate int num_renegotiates; 80*0Sstevel@tonic-gate unsigned long renegotiate_count; 81*0Sstevel@tonic-gate unsigned long byte_count; 82*0Sstevel@tonic-gate unsigned long renegotiate_timeout; 83*0Sstevel@tonic-gate unsigned long last_time; 84*0Sstevel@tonic-gate } BIO_SSL; 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate static BIO_METHOD methods_sslp= 87*0Sstevel@tonic-gate { 88*0Sstevel@tonic-gate BIO_TYPE_SSL,"ssl", 89*0Sstevel@tonic-gate ssl_write, 90*0Sstevel@tonic-gate ssl_read, 91*0Sstevel@tonic-gate ssl_puts, 92*0Sstevel@tonic-gate NULL, /* ssl_gets, */ 93*0Sstevel@tonic-gate ssl_ctrl, 94*0Sstevel@tonic-gate ssl_new, 95*0Sstevel@tonic-gate ssl_free, 96*0Sstevel@tonic-gate ssl_callback_ctrl, 97*0Sstevel@tonic-gate }; 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate BIO_METHOD *BIO_f_ssl(void) 100*0Sstevel@tonic-gate { 101*0Sstevel@tonic-gate return(&methods_sslp); 102*0Sstevel@tonic-gate } 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate static int ssl_new(BIO *bi) 105*0Sstevel@tonic-gate { 106*0Sstevel@tonic-gate BIO_SSL *bs; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate bs=(BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL)); 109*0Sstevel@tonic-gate if (bs == NULL) 110*0Sstevel@tonic-gate { 111*0Sstevel@tonic-gate BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE); 112*0Sstevel@tonic-gate return(0); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate memset(bs,0,sizeof(BIO_SSL)); 115*0Sstevel@tonic-gate bi->init=0; 116*0Sstevel@tonic-gate bi->ptr=(char *)bs; 117*0Sstevel@tonic-gate bi->flags=0; 118*0Sstevel@tonic-gate return(1); 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate static int ssl_free(BIO *a) 122*0Sstevel@tonic-gate { 123*0Sstevel@tonic-gate BIO_SSL *bs; 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate if (a == NULL) return(0); 126*0Sstevel@tonic-gate bs=(BIO_SSL *)a->ptr; 127*0Sstevel@tonic-gate if (bs->ssl != NULL) SSL_shutdown(bs->ssl); 128*0Sstevel@tonic-gate if (a->shutdown) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate if (a->init && (bs->ssl != NULL)) 131*0Sstevel@tonic-gate SSL_free(bs->ssl); 132*0Sstevel@tonic-gate a->init=0; 133*0Sstevel@tonic-gate a->flags=0; 134*0Sstevel@tonic-gate } 135*0Sstevel@tonic-gate if (a->ptr != NULL) 136*0Sstevel@tonic-gate OPENSSL_free(a->ptr); 137*0Sstevel@tonic-gate return(1); 138*0Sstevel@tonic-gate } 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate static int ssl_read(BIO *b, char *out, int outl) 141*0Sstevel@tonic-gate { 142*0Sstevel@tonic-gate int ret=1; 143*0Sstevel@tonic-gate BIO_SSL *sb; 144*0Sstevel@tonic-gate SSL *ssl; 145*0Sstevel@tonic-gate int retry_reason=0; 146*0Sstevel@tonic-gate int r=0; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (out == NULL) return(0); 149*0Sstevel@tonic-gate sb=(BIO_SSL *)b->ptr; 150*0Sstevel@tonic-gate ssl=sb->ssl; 151*0Sstevel@tonic-gate 152*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate #if 0 155*0Sstevel@tonic-gate if (!SSL_is_init_finished(ssl)) 156*0Sstevel@tonic-gate { 157*0Sstevel@tonic-gate /* ret=SSL_do_handshake(ssl); */ 158*0Sstevel@tonic-gate if (ret > 0) 159*0Sstevel@tonic-gate { 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); 162*0Sstevel@tonic-gate ret= -1; 163*0Sstevel@tonic-gate goto end; 164*0Sstevel@tonic-gate } 165*0Sstevel@tonic-gate } 166*0Sstevel@tonic-gate #endif 167*0Sstevel@tonic-gate /* if (ret > 0) */ 168*0Sstevel@tonic-gate ret=SSL_read(ssl,out,outl); 169*0Sstevel@tonic-gate 170*0Sstevel@tonic-gate switch (SSL_get_error(ssl,ret)) 171*0Sstevel@tonic-gate { 172*0Sstevel@tonic-gate case SSL_ERROR_NONE: 173*0Sstevel@tonic-gate if (ret <= 0) break; 174*0Sstevel@tonic-gate if (sb->renegotiate_count > 0) 175*0Sstevel@tonic-gate { 176*0Sstevel@tonic-gate sb->byte_count+=ret; 177*0Sstevel@tonic-gate if (sb->byte_count > sb->renegotiate_count) 178*0Sstevel@tonic-gate { 179*0Sstevel@tonic-gate sb->byte_count=0; 180*0Sstevel@tonic-gate sb->num_renegotiates++; 181*0Sstevel@tonic-gate SSL_renegotiate(ssl); 182*0Sstevel@tonic-gate r=1; 183*0Sstevel@tonic-gate } 184*0Sstevel@tonic-gate } 185*0Sstevel@tonic-gate if ((sb->renegotiate_timeout > 0) && (!r)) 186*0Sstevel@tonic-gate { 187*0Sstevel@tonic-gate unsigned long tm; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate tm=(unsigned long)time(NULL); 190*0Sstevel@tonic-gate if (tm > sb->last_time+sb->renegotiate_timeout) 191*0Sstevel@tonic-gate { 192*0Sstevel@tonic-gate sb->last_time=tm; 193*0Sstevel@tonic-gate sb->num_renegotiates++; 194*0Sstevel@tonic-gate SSL_renegotiate(ssl); 195*0Sstevel@tonic-gate } 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate break; 199*0Sstevel@tonic-gate case SSL_ERROR_WANT_READ: 200*0Sstevel@tonic-gate BIO_set_retry_read(b); 201*0Sstevel@tonic-gate break; 202*0Sstevel@tonic-gate case SSL_ERROR_WANT_WRITE: 203*0Sstevel@tonic-gate BIO_set_retry_write(b); 204*0Sstevel@tonic-gate break; 205*0Sstevel@tonic-gate case SSL_ERROR_WANT_X509_LOOKUP: 206*0Sstevel@tonic-gate BIO_set_retry_special(b); 207*0Sstevel@tonic-gate retry_reason=BIO_RR_SSL_X509_LOOKUP; 208*0Sstevel@tonic-gate break; 209*0Sstevel@tonic-gate case SSL_ERROR_WANT_ACCEPT: 210*0Sstevel@tonic-gate BIO_set_retry_special(b); 211*0Sstevel@tonic-gate retry_reason=BIO_RR_ACCEPT; 212*0Sstevel@tonic-gate break; 213*0Sstevel@tonic-gate case SSL_ERROR_WANT_CONNECT: 214*0Sstevel@tonic-gate BIO_set_retry_special(b); 215*0Sstevel@tonic-gate retry_reason=BIO_RR_CONNECT; 216*0Sstevel@tonic-gate break; 217*0Sstevel@tonic-gate case SSL_ERROR_SYSCALL: 218*0Sstevel@tonic-gate case SSL_ERROR_SSL: 219*0Sstevel@tonic-gate case SSL_ERROR_ZERO_RETURN: 220*0Sstevel@tonic-gate default: 221*0Sstevel@tonic-gate break; 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate b->retry_reason=retry_reason; 225*0Sstevel@tonic-gate return(ret); 226*0Sstevel@tonic-gate } 227*0Sstevel@tonic-gate 228*0Sstevel@tonic-gate static int ssl_write(BIO *b, const char *out, int outl) 229*0Sstevel@tonic-gate { 230*0Sstevel@tonic-gate int ret,r=0; 231*0Sstevel@tonic-gate int retry_reason=0; 232*0Sstevel@tonic-gate SSL *ssl; 233*0Sstevel@tonic-gate BIO_SSL *bs; 234*0Sstevel@tonic-gate 235*0Sstevel@tonic-gate if (out == NULL) return(0); 236*0Sstevel@tonic-gate bs=(BIO_SSL *)b->ptr; 237*0Sstevel@tonic-gate ssl=bs->ssl; 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 240*0Sstevel@tonic-gate 241*0Sstevel@tonic-gate /* ret=SSL_do_handshake(ssl); 242*0Sstevel@tonic-gate if (ret > 0) */ 243*0Sstevel@tonic-gate ret=SSL_write(ssl,out,outl); 244*0Sstevel@tonic-gate 245*0Sstevel@tonic-gate switch (SSL_get_error(ssl,ret)) 246*0Sstevel@tonic-gate { 247*0Sstevel@tonic-gate case SSL_ERROR_NONE: 248*0Sstevel@tonic-gate if (ret <= 0) break; 249*0Sstevel@tonic-gate if (bs->renegotiate_count > 0) 250*0Sstevel@tonic-gate { 251*0Sstevel@tonic-gate bs->byte_count+=ret; 252*0Sstevel@tonic-gate if (bs->byte_count > bs->renegotiate_count) 253*0Sstevel@tonic-gate { 254*0Sstevel@tonic-gate bs->byte_count=0; 255*0Sstevel@tonic-gate bs->num_renegotiates++; 256*0Sstevel@tonic-gate SSL_renegotiate(ssl); 257*0Sstevel@tonic-gate r=1; 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate } 260*0Sstevel@tonic-gate if ((bs->renegotiate_timeout > 0) && (!r)) 261*0Sstevel@tonic-gate { 262*0Sstevel@tonic-gate unsigned long tm; 263*0Sstevel@tonic-gate 264*0Sstevel@tonic-gate tm=(unsigned long)time(NULL); 265*0Sstevel@tonic-gate if (tm > bs->last_time+bs->renegotiate_timeout) 266*0Sstevel@tonic-gate { 267*0Sstevel@tonic-gate bs->last_time=tm; 268*0Sstevel@tonic-gate bs->num_renegotiates++; 269*0Sstevel@tonic-gate SSL_renegotiate(ssl); 270*0Sstevel@tonic-gate } 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate break; 273*0Sstevel@tonic-gate case SSL_ERROR_WANT_WRITE: 274*0Sstevel@tonic-gate BIO_set_retry_write(b); 275*0Sstevel@tonic-gate break; 276*0Sstevel@tonic-gate case SSL_ERROR_WANT_READ: 277*0Sstevel@tonic-gate BIO_set_retry_read(b); 278*0Sstevel@tonic-gate break; 279*0Sstevel@tonic-gate case SSL_ERROR_WANT_X509_LOOKUP: 280*0Sstevel@tonic-gate BIO_set_retry_special(b); 281*0Sstevel@tonic-gate retry_reason=BIO_RR_SSL_X509_LOOKUP; 282*0Sstevel@tonic-gate break; 283*0Sstevel@tonic-gate case SSL_ERROR_WANT_CONNECT: 284*0Sstevel@tonic-gate BIO_set_retry_special(b); 285*0Sstevel@tonic-gate retry_reason=BIO_RR_CONNECT; 286*0Sstevel@tonic-gate case SSL_ERROR_SYSCALL: 287*0Sstevel@tonic-gate case SSL_ERROR_SSL: 288*0Sstevel@tonic-gate default: 289*0Sstevel@tonic-gate break; 290*0Sstevel@tonic-gate } 291*0Sstevel@tonic-gate 292*0Sstevel@tonic-gate b->retry_reason=retry_reason; 293*0Sstevel@tonic-gate return(ret); 294*0Sstevel@tonic-gate } 295*0Sstevel@tonic-gate 296*0Sstevel@tonic-gate static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) 297*0Sstevel@tonic-gate { 298*0Sstevel@tonic-gate SSL **sslp,*ssl; 299*0Sstevel@tonic-gate BIO_SSL *bs; 300*0Sstevel@tonic-gate BIO *dbio,*bio; 301*0Sstevel@tonic-gate long ret=1; 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate bs=(BIO_SSL *)b->ptr; 304*0Sstevel@tonic-gate ssl=bs->ssl; 305*0Sstevel@tonic-gate if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) 306*0Sstevel@tonic-gate return(0); 307*0Sstevel@tonic-gate switch (cmd) 308*0Sstevel@tonic-gate { 309*0Sstevel@tonic-gate case BIO_CTRL_RESET: 310*0Sstevel@tonic-gate SSL_shutdown(ssl); 311*0Sstevel@tonic-gate 312*0Sstevel@tonic-gate if (ssl->handshake_func == ssl->method->ssl_connect) 313*0Sstevel@tonic-gate SSL_set_connect_state(ssl); 314*0Sstevel@tonic-gate else if (ssl->handshake_func == ssl->method->ssl_accept) 315*0Sstevel@tonic-gate SSL_set_accept_state(ssl); 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate SSL_clear(ssl); 318*0Sstevel@tonic-gate 319*0Sstevel@tonic-gate if (b->next_bio != NULL) 320*0Sstevel@tonic-gate ret=BIO_ctrl(b->next_bio,cmd,num,ptr); 321*0Sstevel@tonic-gate else if (ssl->rbio != NULL) 322*0Sstevel@tonic-gate ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); 323*0Sstevel@tonic-gate else 324*0Sstevel@tonic-gate ret=1; 325*0Sstevel@tonic-gate break; 326*0Sstevel@tonic-gate case BIO_CTRL_INFO: 327*0Sstevel@tonic-gate ret=0; 328*0Sstevel@tonic-gate break; 329*0Sstevel@tonic-gate case BIO_C_SSL_MODE: 330*0Sstevel@tonic-gate if (num) /* client mode */ 331*0Sstevel@tonic-gate SSL_set_connect_state(ssl); 332*0Sstevel@tonic-gate else 333*0Sstevel@tonic-gate SSL_set_accept_state(ssl); 334*0Sstevel@tonic-gate break; 335*0Sstevel@tonic-gate case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: 336*0Sstevel@tonic-gate ret=bs->renegotiate_timeout; 337*0Sstevel@tonic-gate if (num < 60) num=5; 338*0Sstevel@tonic-gate bs->renegotiate_timeout=(unsigned long)num; 339*0Sstevel@tonic-gate bs->last_time=(unsigned long)time(NULL); 340*0Sstevel@tonic-gate break; 341*0Sstevel@tonic-gate case BIO_C_SET_SSL_RENEGOTIATE_BYTES: 342*0Sstevel@tonic-gate ret=bs->renegotiate_count; 343*0Sstevel@tonic-gate if ((long)num >=512) 344*0Sstevel@tonic-gate bs->renegotiate_count=(unsigned long)num; 345*0Sstevel@tonic-gate break; 346*0Sstevel@tonic-gate case BIO_C_GET_SSL_NUM_RENEGOTIATES: 347*0Sstevel@tonic-gate ret=bs->num_renegotiates; 348*0Sstevel@tonic-gate break; 349*0Sstevel@tonic-gate case BIO_C_SET_SSL: 350*0Sstevel@tonic-gate if (ssl != NULL) 351*0Sstevel@tonic-gate ssl_free(b); 352*0Sstevel@tonic-gate b->shutdown=(int)num; 353*0Sstevel@tonic-gate ssl=(SSL *)ptr; 354*0Sstevel@tonic-gate ((BIO_SSL *)b->ptr)->ssl=ssl; 355*0Sstevel@tonic-gate bio=SSL_get_rbio(ssl); 356*0Sstevel@tonic-gate if (bio != NULL) 357*0Sstevel@tonic-gate { 358*0Sstevel@tonic-gate if (b->next_bio != NULL) 359*0Sstevel@tonic-gate BIO_push(bio,b->next_bio); 360*0Sstevel@tonic-gate b->next_bio=bio; 361*0Sstevel@tonic-gate CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO); 362*0Sstevel@tonic-gate } 363*0Sstevel@tonic-gate b->init=1; 364*0Sstevel@tonic-gate break; 365*0Sstevel@tonic-gate case BIO_C_GET_SSL: 366*0Sstevel@tonic-gate if (ptr != NULL) 367*0Sstevel@tonic-gate { 368*0Sstevel@tonic-gate sslp=(SSL **)ptr; 369*0Sstevel@tonic-gate *sslp=ssl; 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate else 372*0Sstevel@tonic-gate ret=0; 373*0Sstevel@tonic-gate break; 374*0Sstevel@tonic-gate case BIO_CTRL_GET_CLOSE: 375*0Sstevel@tonic-gate ret=b->shutdown; 376*0Sstevel@tonic-gate break; 377*0Sstevel@tonic-gate case BIO_CTRL_SET_CLOSE: 378*0Sstevel@tonic-gate b->shutdown=(int)num; 379*0Sstevel@tonic-gate break; 380*0Sstevel@tonic-gate case BIO_CTRL_WPENDING: 381*0Sstevel@tonic-gate ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); 382*0Sstevel@tonic-gate break; 383*0Sstevel@tonic-gate case BIO_CTRL_PENDING: 384*0Sstevel@tonic-gate ret=SSL_pending(ssl); 385*0Sstevel@tonic-gate if (ret == 0) 386*0Sstevel@tonic-gate ret=BIO_pending(ssl->rbio); 387*0Sstevel@tonic-gate break; 388*0Sstevel@tonic-gate case BIO_CTRL_FLUSH: 389*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 390*0Sstevel@tonic-gate ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); 391*0Sstevel@tonic-gate BIO_copy_next_retry(b); 392*0Sstevel@tonic-gate break; 393*0Sstevel@tonic-gate case BIO_CTRL_PUSH: 394*0Sstevel@tonic-gate if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) 395*0Sstevel@tonic-gate { 396*0Sstevel@tonic-gate SSL_set_bio(ssl,b->next_bio,b->next_bio); 397*0Sstevel@tonic-gate CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO); 398*0Sstevel@tonic-gate } 399*0Sstevel@tonic-gate break; 400*0Sstevel@tonic-gate case BIO_CTRL_POP: 401*0Sstevel@tonic-gate /* ugly bit of a hack */ 402*0Sstevel@tonic-gate if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */ 403*0Sstevel@tonic-gate { 404*0Sstevel@tonic-gate BIO_free_all(ssl->wbio); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate if (b->next_bio != NULL) 407*0Sstevel@tonic-gate { 408*0Sstevel@tonic-gate CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO); 409*0Sstevel@tonic-gate } 410*0Sstevel@tonic-gate ssl->wbio=NULL; 411*0Sstevel@tonic-gate ssl->rbio=NULL; 412*0Sstevel@tonic-gate break; 413*0Sstevel@tonic-gate case BIO_C_DO_STATE_MACHINE: 414*0Sstevel@tonic-gate BIO_clear_retry_flags(b); 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate b->retry_reason=0; 417*0Sstevel@tonic-gate ret=(int)SSL_do_handshake(ssl); 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate switch (SSL_get_error(ssl,(int)ret)) 420*0Sstevel@tonic-gate { 421*0Sstevel@tonic-gate case SSL_ERROR_WANT_READ: 422*0Sstevel@tonic-gate BIO_set_flags(b, 423*0Sstevel@tonic-gate BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); 424*0Sstevel@tonic-gate break; 425*0Sstevel@tonic-gate case SSL_ERROR_WANT_WRITE: 426*0Sstevel@tonic-gate BIO_set_flags(b, 427*0Sstevel@tonic-gate BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); 428*0Sstevel@tonic-gate break; 429*0Sstevel@tonic-gate case SSL_ERROR_WANT_CONNECT: 430*0Sstevel@tonic-gate BIO_set_flags(b, 431*0Sstevel@tonic-gate BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); 432*0Sstevel@tonic-gate b->retry_reason=b->next_bio->retry_reason; 433*0Sstevel@tonic-gate break; 434*0Sstevel@tonic-gate default: 435*0Sstevel@tonic-gate break; 436*0Sstevel@tonic-gate } 437*0Sstevel@tonic-gate break; 438*0Sstevel@tonic-gate case BIO_CTRL_DUP: 439*0Sstevel@tonic-gate dbio=(BIO *)ptr; 440*0Sstevel@tonic-gate if (((BIO_SSL *)dbio->ptr)->ssl != NULL) 441*0Sstevel@tonic-gate SSL_free(((BIO_SSL *)dbio->ptr)->ssl); 442*0Sstevel@tonic-gate ((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl); 443*0Sstevel@tonic-gate ((BIO_SSL *)dbio->ptr)->renegotiate_count= 444*0Sstevel@tonic-gate ((BIO_SSL *)b->ptr)->renegotiate_count; 445*0Sstevel@tonic-gate ((BIO_SSL *)dbio->ptr)->byte_count= 446*0Sstevel@tonic-gate ((BIO_SSL *)b->ptr)->byte_count; 447*0Sstevel@tonic-gate ((BIO_SSL *)dbio->ptr)->renegotiate_timeout= 448*0Sstevel@tonic-gate ((BIO_SSL *)b->ptr)->renegotiate_timeout; 449*0Sstevel@tonic-gate ((BIO_SSL *)dbio->ptr)->last_time= 450*0Sstevel@tonic-gate ((BIO_SSL *)b->ptr)->last_time; 451*0Sstevel@tonic-gate ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL); 452*0Sstevel@tonic-gate break; 453*0Sstevel@tonic-gate case BIO_C_GET_FD: 454*0Sstevel@tonic-gate ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); 455*0Sstevel@tonic-gate break; 456*0Sstevel@tonic-gate case BIO_CTRL_SET_CALLBACK: 457*0Sstevel@tonic-gate { 458*0Sstevel@tonic-gate #if 0 /* FIXME: Should this be used? -- Richard Levitte */ 459*0Sstevel@tonic-gate BIOerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); 460*0Sstevel@tonic-gate ret = -1; 461*0Sstevel@tonic-gate #else 462*0Sstevel@tonic-gate ret=0; 463*0Sstevel@tonic-gate #endif 464*0Sstevel@tonic-gate } 465*0Sstevel@tonic-gate break; 466*0Sstevel@tonic-gate case BIO_CTRL_GET_CALLBACK: 467*0Sstevel@tonic-gate { 468*0Sstevel@tonic-gate void (**fptr)(); 469*0Sstevel@tonic-gate 470*0Sstevel@tonic-gate fptr=(void (**)())ptr; 471*0Sstevel@tonic-gate *fptr=SSL_get_info_callback(ssl); 472*0Sstevel@tonic-gate } 473*0Sstevel@tonic-gate break; 474*0Sstevel@tonic-gate default: 475*0Sstevel@tonic-gate ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); 476*0Sstevel@tonic-gate break; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate return(ret); 479*0Sstevel@tonic-gate } 480*0Sstevel@tonic-gate 481*0Sstevel@tonic-gate static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) 482*0Sstevel@tonic-gate { 483*0Sstevel@tonic-gate SSL *ssl; 484*0Sstevel@tonic-gate BIO_SSL *bs; 485*0Sstevel@tonic-gate long ret=1; 486*0Sstevel@tonic-gate 487*0Sstevel@tonic-gate bs=(BIO_SSL *)b->ptr; 488*0Sstevel@tonic-gate ssl=bs->ssl; 489*0Sstevel@tonic-gate switch (cmd) 490*0Sstevel@tonic-gate { 491*0Sstevel@tonic-gate case BIO_CTRL_SET_CALLBACK: 492*0Sstevel@tonic-gate { 493*0Sstevel@tonic-gate /* FIXME: setting this via a completely different prototype 494*0Sstevel@tonic-gate seems like a crap idea */ 495*0Sstevel@tonic-gate SSL_set_info_callback(ssl,(void (*)(const SSL *,int,int))fp); 496*0Sstevel@tonic-gate } 497*0Sstevel@tonic-gate break; 498*0Sstevel@tonic-gate default: 499*0Sstevel@tonic-gate ret=BIO_callback_ctrl(ssl->rbio,cmd,fp); 500*0Sstevel@tonic-gate break; 501*0Sstevel@tonic-gate } 502*0Sstevel@tonic-gate return(ret); 503*0Sstevel@tonic-gate } 504*0Sstevel@tonic-gate 505*0Sstevel@tonic-gate static int ssl_puts(BIO *bp, const char *str) 506*0Sstevel@tonic-gate { 507*0Sstevel@tonic-gate int n,ret; 508*0Sstevel@tonic-gate 509*0Sstevel@tonic-gate n=strlen(str); 510*0Sstevel@tonic-gate ret=BIO_write(bp,str,n); 511*0Sstevel@tonic-gate return(ret); 512*0Sstevel@tonic-gate } 513*0Sstevel@tonic-gate 514*0Sstevel@tonic-gate BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) 515*0Sstevel@tonic-gate { 516*0Sstevel@tonic-gate #ifndef OPENSSL_NO_SOCK 517*0Sstevel@tonic-gate BIO *ret=NULL,*buf=NULL,*ssl=NULL; 518*0Sstevel@tonic-gate 519*0Sstevel@tonic-gate if ((buf=BIO_new(BIO_f_buffer())) == NULL) 520*0Sstevel@tonic-gate return(NULL); 521*0Sstevel@tonic-gate if ((ssl=BIO_new_ssl_connect(ctx)) == NULL) 522*0Sstevel@tonic-gate goto err; 523*0Sstevel@tonic-gate if ((ret=BIO_push(buf,ssl)) == NULL) 524*0Sstevel@tonic-gate goto err; 525*0Sstevel@tonic-gate return(ret); 526*0Sstevel@tonic-gate err: 527*0Sstevel@tonic-gate if (buf != NULL) BIO_free(buf); 528*0Sstevel@tonic-gate if (ssl != NULL) BIO_free(ssl); 529*0Sstevel@tonic-gate #endif 530*0Sstevel@tonic-gate return(NULL); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate BIO *BIO_new_ssl_connect(SSL_CTX *ctx) 534*0Sstevel@tonic-gate { 535*0Sstevel@tonic-gate BIO *ret=NULL,*con=NULL,*ssl=NULL; 536*0Sstevel@tonic-gate 537*0Sstevel@tonic-gate if ((con=BIO_new(BIO_s_connect())) == NULL) 538*0Sstevel@tonic-gate return(NULL); 539*0Sstevel@tonic-gate if ((ssl=BIO_new_ssl(ctx,1)) == NULL) 540*0Sstevel@tonic-gate goto err; 541*0Sstevel@tonic-gate if ((ret=BIO_push(ssl,con)) == NULL) 542*0Sstevel@tonic-gate goto err; 543*0Sstevel@tonic-gate return(ret); 544*0Sstevel@tonic-gate err: 545*0Sstevel@tonic-gate if (con != NULL) BIO_free(con); 546*0Sstevel@tonic-gate if (ret != NULL) BIO_free(ret); 547*0Sstevel@tonic-gate return(NULL); 548*0Sstevel@tonic-gate } 549*0Sstevel@tonic-gate 550*0Sstevel@tonic-gate BIO *BIO_new_ssl(SSL_CTX *ctx, int client) 551*0Sstevel@tonic-gate { 552*0Sstevel@tonic-gate BIO *ret; 553*0Sstevel@tonic-gate SSL *ssl; 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate if ((ret=BIO_new(BIO_f_ssl())) == NULL) 556*0Sstevel@tonic-gate return(NULL); 557*0Sstevel@tonic-gate if ((ssl=SSL_new(ctx)) == NULL) 558*0Sstevel@tonic-gate { 559*0Sstevel@tonic-gate BIO_free(ret); 560*0Sstevel@tonic-gate return(NULL); 561*0Sstevel@tonic-gate } 562*0Sstevel@tonic-gate if (client) 563*0Sstevel@tonic-gate SSL_set_connect_state(ssl); 564*0Sstevel@tonic-gate else 565*0Sstevel@tonic-gate SSL_set_accept_state(ssl); 566*0Sstevel@tonic-gate 567*0Sstevel@tonic-gate BIO_set_ssl(ret,ssl,BIO_CLOSE); 568*0Sstevel@tonic-gate return(ret); 569*0Sstevel@tonic-gate } 570*0Sstevel@tonic-gate 571*0Sstevel@tonic-gate int BIO_ssl_copy_session_id(BIO *t, BIO *f) 572*0Sstevel@tonic-gate { 573*0Sstevel@tonic-gate t=BIO_find_type(t,BIO_TYPE_SSL); 574*0Sstevel@tonic-gate f=BIO_find_type(f,BIO_TYPE_SSL); 575*0Sstevel@tonic-gate if ((t == NULL) || (f == NULL)) 576*0Sstevel@tonic-gate return(0); 577*0Sstevel@tonic-gate if ( (((BIO_SSL *)t->ptr)->ssl == NULL) || 578*0Sstevel@tonic-gate (((BIO_SSL *)f->ptr)->ssl == NULL)) 579*0Sstevel@tonic-gate return(0); 580*0Sstevel@tonic-gate SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl); 581*0Sstevel@tonic-gate return(1); 582*0Sstevel@tonic-gate } 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate void BIO_ssl_shutdown(BIO *b) 585*0Sstevel@tonic-gate { 586*0Sstevel@tonic-gate SSL *s; 587*0Sstevel@tonic-gate 588*0Sstevel@tonic-gate while (b != NULL) 589*0Sstevel@tonic-gate { 590*0Sstevel@tonic-gate if (b->method->type == BIO_TYPE_SSL) 591*0Sstevel@tonic-gate { 592*0Sstevel@tonic-gate s=((BIO_SSL *)b->ptr)->ssl; 593*0Sstevel@tonic-gate SSL_shutdown(s); 594*0Sstevel@tonic-gate break; 595*0Sstevel@tonic-gate } 596*0Sstevel@tonic-gate b=b->next_bio; 597*0Sstevel@tonic-gate } 598*0Sstevel@tonic-gate } 599