sl@0: /* ssl/bio_ssl.c */ sl@0: /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) sl@0: * All rights reserved. sl@0: * sl@0: * This package is an SSL implementation written sl@0: * by Eric Young (eay@cryptsoft.com). sl@0: * The implementation was written so as to conform with Netscapes SSL. sl@0: * sl@0: * This library is free for commercial and non-commercial use as long as sl@0: * the following conditions are aheared to. The following conditions sl@0: * apply to all code found in this distribution, be it the RC4, RSA, sl@0: * lhash, DES, etc., code; not just the SSL code. The SSL documentation sl@0: * included with this distribution is covered by the same copyright terms sl@0: * except that the holder is Tim Hudson (tjh@cryptsoft.com). sl@0: * sl@0: * Copyright remains Eric Young's, and as such any Copyright notices in sl@0: * the code are not to be removed. sl@0: * If this package is used in a product, Eric Young should be given attribution sl@0: * as the author of the parts of the library used. sl@0: * This can be in the form of a textual message at program startup or sl@0: * in documentation (online or textual) provided with the package. sl@0: * sl@0: * Redistribution and use in source and binary forms, with or without sl@0: * modification, are permitted provided that the following conditions sl@0: * are met: sl@0: * 1. Redistributions of source code must retain the copyright sl@0: * notice, this list of conditions and the following disclaimer. sl@0: * 2. Redistributions in binary form must reproduce the above copyright sl@0: * notice, this list of conditions and the following disclaimer in the sl@0: * documentation and/or other materials provided with the distribution. sl@0: * 3. All advertising materials mentioning features or use of this software sl@0: * must display the following acknowledgement: sl@0: * "This product includes cryptographic software written by sl@0: * Eric Young (eay@cryptsoft.com)" sl@0: * The word 'cryptographic' can be left out if the rouines from the library sl@0: * being used are not cryptographic related :-). sl@0: * 4. If you include any Windows specific code (or a derivative thereof) from sl@0: * the apps directory (application code) you must include an acknowledgement: sl@0: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" sl@0: * sl@0: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND sl@0: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE sl@0: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE sl@0: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE sl@0: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL sl@0: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS sl@0: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) sl@0: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT sl@0: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY sl@0: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF sl@0: * SUCH DAMAGE. sl@0: * sl@0: * The licence and distribution terms for any publically available version or sl@0: * derivative of this code cannot be changed. i.e. this code cannot simply be sl@0: * copied and put under another distribution licence sl@0: * [including the GNU Public Licence.] sl@0: */ sl@0: /* sl@0: © Portions copyright (c) 2006 Nokia Corporation. All rights reserved. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: #if (defined(SYMBIAN) && (defined(__WINSCW__) || defined(__WINS__))) sl@0: #include "libssl_wsd.h" sl@0: #endif sl@0: sl@0: static int ssl_write(BIO *h, const char *buf, int num); sl@0: static int ssl_read(BIO *h, char *buf, int size); sl@0: static int ssl_puts(BIO *h, const char *str); sl@0: static long ssl_ctrl(BIO *h, int cmd, long arg1, void *arg2); sl@0: static int ssl_new(BIO *h); sl@0: static int ssl_free(BIO *data); sl@0: static long ssl_callback_ctrl(BIO *h, int cmd, bio_info_cb *fp); sl@0: typedef struct bio_ssl_st sl@0: { sl@0: SSL *ssl; /* The ssl handle :-) */ sl@0: /* re-negotiate every time the total number of bytes is this size */ sl@0: int num_renegotiates; sl@0: unsigned long renegotiate_count; sl@0: unsigned long byte_count; sl@0: unsigned long renegotiate_timeout; sl@0: unsigned long last_time; sl@0: } BIO_SSL; sl@0: sl@0: #ifdef __cplusplus sl@0: extern "C" sl@0: { sl@0: #endif sl@0: #ifndef EMULATOR sl@0: sl@0: static BIO_METHOD methods_sslp= sl@0: #else sl@0: const BIO_METHOD temp_methods_sslp= sl@0: sl@0: #endif sl@0: { sl@0: BIO_TYPE_SSL,"ssl", sl@0: ssl_write, sl@0: ssl_read, sl@0: ssl_puts, sl@0: NULL, /* ssl_gets, */ sl@0: ssl_ctrl, sl@0: ssl_new, sl@0: ssl_free, sl@0: ssl_callback_ctrl, sl@0: }; sl@0: #ifdef __cplusplus sl@0: } sl@0: #endif sl@0: sl@0: #ifdef EMULATOR sl@0: sl@0: GET_STATIC_VAR_FROM_TLS(methods_sslp,bio_ssl,BIO_METHOD) sl@0: sl@0: #define methods_sslp (*GET_WSD_VAR_NAME(methods_sslp,bio_ssl,s)()) sl@0: sl@0: #endif //EMULATOR sl@0: sl@0: sl@0: sl@0: EXPORT_C BIO_METHOD *BIO_f_ssl(void) sl@0: { sl@0: return(&methods_sslp); sl@0: } sl@0: sl@0: static int ssl_new(BIO *bi) sl@0: { sl@0: BIO_SSL *bs; sl@0: sl@0: bs=(BIO_SSL *)OPENSSL_malloc(sizeof(BIO_SSL)); sl@0: if (bs == NULL) sl@0: { sl@0: BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE); sl@0: return(0); sl@0: } sl@0: memset(bs,0,sizeof(BIO_SSL)); sl@0: bi->init=0; sl@0: bi->ptr=(char *)bs; sl@0: bi->flags=0; sl@0: return(1); sl@0: } sl@0: sl@0: static int ssl_free(BIO *a) sl@0: { sl@0: BIO_SSL *bs; sl@0: sl@0: if (a == NULL) return(0); sl@0: bs=(BIO_SSL *)a->ptr; sl@0: if (bs->ssl != NULL) SSL_shutdown(bs->ssl); sl@0: if (a->shutdown) sl@0: { sl@0: if (a->init && (bs->ssl != NULL)) sl@0: SSL_free(bs->ssl); sl@0: a->init=0; sl@0: a->flags=0; sl@0: } sl@0: if (a->ptr != NULL) sl@0: OPENSSL_free(a->ptr); sl@0: return(1); sl@0: } sl@0: sl@0: static int ssl_read(BIO *b, char *out, int outl) sl@0: { sl@0: int ret=1; sl@0: BIO_SSL *sb; sl@0: SSL *ssl; sl@0: int retry_reason=0; sl@0: int r=0; sl@0: sl@0: if (out == NULL) return(0); sl@0: sb=(BIO_SSL *)b->ptr; sl@0: ssl=sb->ssl; sl@0: sl@0: BIO_clear_retry_flags(b); sl@0: sl@0: #if 0 sl@0: if (!SSL_is_init_finished(ssl)) sl@0: { sl@0: /* ret=SSL_do_handshake(ssl); */ sl@0: if (ret > 0) sl@0: { sl@0: sl@0: outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); sl@0: ret= -1; sl@0: goto end; sl@0: } sl@0: } sl@0: #endif sl@0: /* if (ret > 0) */ sl@0: ret=SSL_read(ssl,out,outl); sl@0: sl@0: switch (SSL_get_error(ssl,ret)) sl@0: { sl@0: case SSL_ERROR_NONE: sl@0: if (ret <= 0) break; sl@0: if (sb->renegotiate_count > 0) sl@0: { sl@0: sb->byte_count+=ret; sl@0: if (sb->byte_count > sb->renegotiate_count) sl@0: { sl@0: sb->byte_count=0; sl@0: sb->num_renegotiates++; sl@0: SSL_renegotiate(ssl); sl@0: r=1; sl@0: } sl@0: } sl@0: if ((sb->renegotiate_timeout > 0) && (!r)) sl@0: { sl@0: unsigned long tm; sl@0: sl@0: tm=(unsigned long)time(NULL); sl@0: if (tm > sb->last_time+sb->renegotiate_timeout) sl@0: { sl@0: sb->last_time=tm; sl@0: sb->num_renegotiates++; sl@0: SSL_renegotiate(ssl); sl@0: } sl@0: } sl@0: sl@0: break; sl@0: case SSL_ERROR_WANT_READ: sl@0: BIO_set_retry_read(b); sl@0: break; sl@0: case SSL_ERROR_WANT_WRITE: sl@0: BIO_set_retry_write(b); sl@0: break; sl@0: case SSL_ERROR_WANT_X509_LOOKUP: sl@0: BIO_set_retry_special(b); sl@0: retry_reason=BIO_RR_SSL_X509_LOOKUP; sl@0: break; sl@0: case SSL_ERROR_WANT_ACCEPT: sl@0: BIO_set_retry_special(b); sl@0: retry_reason=BIO_RR_ACCEPT; sl@0: break; sl@0: case SSL_ERROR_WANT_CONNECT: sl@0: BIO_set_retry_special(b); sl@0: retry_reason=BIO_RR_CONNECT; sl@0: break; sl@0: case SSL_ERROR_SYSCALL: sl@0: case SSL_ERROR_SSL: sl@0: case SSL_ERROR_ZERO_RETURN: sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: b->retry_reason=retry_reason; sl@0: return(ret); sl@0: } sl@0: sl@0: static int ssl_write(BIO *b, const char *out, int outl) sl@0: { sl@0: int ret,r=0; sl@0: int retry_reason=0; sl@0: SSL *ssl; sl@0: BIO_SSL *bs; sl@0: sl@0: if (out == NULL) return(0); sl@0: bs=(BIO_SSL *)b->ptr; sl@0: ssl=bs->ssl; sl@0: sl@0: BIO_clear_retry_flags(b); sl@0: sl@0: /* ret=SSL_do_handshake(ssl); sl@0: if (ret > 0) */ sl@0: ret=SSL_write(ssl,out,outl); sl@0: sl@0: switch (SSL_get_error(ssl,ret)) sl@0: { sl@0: case SSL_ERROR_NONE: sl@0: if (ret <= 0) break; sl@0: if (bs->renegotiate_count > 0) sl@0: { sl@0: bs->byte_count+=ret; sl@0: if (bs->byte_count > bs->renegotiate_count) sl@0: { sl@0: bs->byte_count=0; sl@0: bs->num_renegotiates++; sl@0: SSL_renegotiate(ssl); sl@0: r=1; sl@0: } sl@0: } sl@0: if ((bs->renegotiate_timeout > 0) && (!r)) sl@0: { sl@0: unsigned long tm; sl@0: sl@0: tm=(unsigned long)time(NULL); sl@0: if (tm > bs->last_time+bs->renegotiate_timeout) sl@0: { sl@0: bs->last_time=tm; sl@0: bs->num_renegotiates++; sl@0: SSL_renegotiate(ssl); sl@0: } sl@0: } sl@0: break; sl@0: case SSL_ERROR_WANT_WRITE: sl@0: BIO_set_retry_write(b); sl@0: break; sl@0: case SSL_ERROR_WANT_READ: sl@0: BIO_set_retry_read(b); sl@0: break; sl@0: case SSL_ERROR_WANT_X509_LOOKUP: sl@0: BIO_set_retry_special(b); sl@0: retry_reason=BIO_RR_SSL_X509_LOOKUP; sl@0: break; sl@0: case SSL_ERROR_WANT_CONNECT: sl@0: BIO_set_retry_special(b); sl@0: retry_reason=BIO_RR_CONNECT; sl@0: case SSL_ERROR_SYSCALL: sl@0: case SSL_ERROR_SSL: sl@0: default: sl@0: break; sl@0: } sl@0: sl@0: b->retry_reason=retry_reason; sl@0: return(ret); sl@0: } sl@0: sl@0: static long ssl_ctrl(BIO *b, int cmd, long num, void *ptr) sl@0: { sl@0: SSL **sslp,*ssl; sl@0: BIO_SSL *bs; sl@0: BIO *dbio,*bio; sl@0: long ret=1; sl@0: sl@0: bs=(BIO_SSL *)b->ptr; sl@0: ssl=bs->ssl; sl@0: if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) sl@0: return(0); sl@0: switch (cmd) sl@0: { sl@0: case BIO_CTRL_RESET: sl@0: SSL_shutdown(ssl); sl@0: sl@0: if (ssl->handshake_func == ssl->method->ssl_connect) sl@0: SSL_set_connect_state(ssl); sl@0: else if (ssl->handshake_func == ssl->method->ssl_accept) sl@0: SSL_set_accept_state(ssl); sl@0: sl@0: SSL_clear(ssl); sl@0: sl@0: if (b->next_bio != NULL) sl@0: ret=BIO_ctrl(b->next_bio,cmd,num,ptr); sl@0: else if (ssl->rbio != NULL) sl@0: ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); sl@0: else sl@0: ret=1; sl@0: break; sl@0: case BIO_CTRL_INFO: sl@0: ret=0; sl@0: break; sl@0: case BIO_C_SSL_MODE: sl@0: if (num) /* client mode */ sl@0: SSL_set_connect_state(ssl); sl@0: else sl@0: SSL_set_accept_state(ssl); sl@0: break; sl@0: case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: sl@0: ret=bs->renegotiate_timeout; sl@0: if (num < 60) num=5; sl@0: bs->renegotiate_timeout=(unsigned long)num; sl@0: bs->last_time=(unsigned long)time(NULL); sl@0: break; sl@0: case BIO_C_SET_SSL_RENEGOTIATE_BYTES: sl@0: ret=bs->renegotiate_count; sl@0: if ((long)num >=512) sl@0: bs->renegotiate_count=(unsigned long)num; sl@0: break; sl@0: case BIO_C_GET_SSL_NUM_RENEGOTIATES: sl@0: ret=bs->num_renegotiates; sl@0: break; sl@0: case BIO_C_SET_SSL: sl@0: if (ssl != NULL) sl@0: ssl_free(b); sl@0: b->shutdown=(int)num; sl@0: ssl=(SSL *)ptr; sl@0: ((BIO_SSL *)b->ptr)->ssl=ssl; sl@0: bio=SSL_get_rbio(ssl); sl@0: if (bio != NULL) sl@0: { sl@0: if (b->next_bio != NULL) sl@0: BIO_push(bio,b->next_bio); sl@0: b->next_bio=bio; sl@0: CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO); sl@0: } sl@0: b->init=1; sl@0: break; sl@0: case BIO_C_GET_SSL: sl@0: if (ptr != NULL) sl@0: { sl@0: sslp=(SSL **)ptr; sl@0: *sslp=ssl; sl@0: } sl@0: else sl@0: ret=0; sl@0: break; sl@0: case BIO_CTRL_GET_CLOSE: sl@0: ret=b->shutdown; sl@0: break; sl@0: case BIO_CTRL_SET_CLOSE: sl@0: b->shutdown=(int)num; sl@0: break; sl@0: case BIO_CTRL_WPENDING: sl@0: ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); sl@0: break; sl@0: case BIO_CTRL_PENDING: sl@0: ret=SSL_pending(ssl); sl@0: if (ret == 0) sl@0: ret=BIO_pending(ssl->rbio); sl@0: break; sl@0: case BIO_CTRL_FLUSH: sl@0: BIO_clear_retry_flags(b); sl@0: ret=BIO_ctrl(ssl->wbio,cmd,num,ptr); sl@0: BIO_copy_next_retry(b); sl@0: break; sl@0: case BIO_CTRL_PUSH: sl@0: if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) sl@0: { sl@0: SSL_set_bio(ssl,b->next_bio,b->next_bio); sl@0: CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO); sl@0: } sl@0: break; sl@0: case BIO_CTRL_POP: sl@0: /* ugly bit of a hack */ sl@0: if (ssl->rbio != ssl->wbio) /* we are in trouble :-( */ sl@0: { sl@0: BIO_free_all(ssl->wbio); sl@0: } sl@0: if (b->next_bio != NULL) sl@0: { sl@0: CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO); sl@0: } sl@0: ssl->wbio=NULL; sl@0: ssl->rbio=NULL; sl@0: break; sl@0: case BIO_C_DO_STATE_MACHINE: sl@0: BIO_clear_retry_flags(b); sl@0: sl@0: b->retry_reason=0; sl@0: ret=(int)SSL_do_handshake(ssl); sl@0: sl@0: switch (SSL_get_error(ssl,(int)ret)) sl@0: { sl@0: case SSL_ERROR_WANT_READ: sl@0: BIO_set_flags(b, sl@0: BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); sl@0: break; sl@0: case SSL_ERROR_WANT_WRITE: sl@0: BIO_set_flags(b, sl@0: BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); sl@0: break; sl@0: case SSL_ERROR_WANT_CONNECT: sl@0: BIO_set_flags(b, sl@0: BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); sl@0: b->retry_reason=b->next_bio->retry_reason; sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: break; sl@0: case BIO_CTRL_DUP: sl@0: dbio=(BIO *)ptr; sl@0: if (((BIO_SSL *)dbio->ptr)->ssl != NULL) sl@0: SSL_free(((BIO_SSL *)dbio->ptr)->ssl); sl@0: ((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl); sl@0: ((BIO_SSL *)dbio->ptr)->renegotiate_count= sl@0: ((BIO_SSL *)b->ptr)->renegotiate_count; sl@0: ((BIO_SSL *)dbio->ptr)->byte_count= sl@0: ((BIO_SSL *)b->ptr)->byte_count; sl@0: ((BIO_SSL *)dbio->ptr)->renegotiate_timeout= sl@0: ((BIO_SSL *)b->ptr)->renegotiate_timeout; sl@0: ((BIO_SSL *)dbio->ptr)->last_time= sl@0: ((BIO_SSL *)b->ptr)->last_time; sl@0: ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL); sl@0: break; sl@0: case BIO_C_GET_FD: sl@0: ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); sl@0: break; sl@0: case BIO_CTRL_SET_CALLBACK: sl@0: { sl@0: #if 0 /* FIXME: Should this be used? -- Richard Levitte */ sl@0: SSLerr(SSL_F_SSL_CTRL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); sl@0: ret = -1; sl@0: #else sl@0: ret=0; sl@0: #endif sl@0: } sl@0: break; sl@0: case BIO_CTRL_GET_CALLBACK: sl@0: { sl@0: void (**fptr)(const SSL *xssl,int type,int val); sl@0: sl@0: fptr=(void (**)(const SSL *xssl,int type,int val))ptr; sl@0: *fptr=SSL_get_info_callback(ssl); sl@0: } sl@0: break; sl@0: default: sl@0: ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); sl@0: break; sl@0: } sl@0: return(ret); sl@0: } sl@0: sl@0: static long ssl_callback_ctrl(BIO *b, int cmd, bio_info_cb *fp) sl@0: { sl@0: SSL *ssl; sl@0: BIO_SSL *bs; sl@0: long ret=1; sl@0: sl@0: bs=(BIO_SSL *)b->ptr; sl@0: ssl=bs->ssl; sl@0: switch (cmd) sl@0: { sl@0: case BIO_CTRL_SET_CALLBACK: sl@0: { sl@0: /* FIXME: setting this via a completely different prototype sl@0: seems like a crap idea */ sl@0: SSL_set_info_callback(ssl,(void (*)(const SSL *,int,int))fp); sl@0: } sl@0: break; sl@0: default: sl@0: ret=BIO_callback_ctrl(ssl->rbio,cmd,fp); sl@0: break; sl@0: } sl@0: return(ret); sl@0: } sl@0: sl@0: static int ssl_puts(BIO *bp, const char *str) sl@0: { sl@0: int n,ret; sl@0: sl@0: n=strlen(str); sl@0: ret=BIO_write(bp,str,n); sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) sl@0: { sl@0: #ifndef OPENSSL_NO_SOCK sl@0: BIO *ret=NULL,*buf=NULL,*ssl=NULL; sl@0: sl@0: if ((buf=BIO_new(BIO_f_buffer())) == NULL) sl@0: return(NULL); sl@0: if ((ssl=BIO_new_ssl_connect(ctx)) == NULL) sl@0: goto err; sl@0: if ((ret=BIO_push(buf,ssl)) == NULL) sl@0: goto err; sl@0: return(ret); sl@0: err: sl@0: if (buf != NULL) BIO_free(buf); sl@0: if (ssl != NULL) BIO_free(ssl); sl@0: #endif sl@0: return(NULL); sl@0: } sl@0: sl@0: EXPORT_C BIO *BIO_new_ssl_connect(SSL_CTX *ctx) sl@0: { sl@0: BIO *ret=NULL,*con=NULL,*ssl=NULL; sl@0: sl@0: if ((con=BIO_new(BIO_s_connect())) == NULL) sl@0: return(NULL); sl@0: if ((ssl=BIO_new_ssl(ctx,1)) == NULL) sl@0: goto err; sl@0: if ((ret=BIO_push(ssl,con)) == NULL) sl@0: goto err; sl@0: return(ret); sl@0: err: sl@0: if (con != NULL) BIO_free(con); sl@0: if (ret != NULL) BIO_free(ret); sl@0: return(NULL); sl@0: } sl@0: sl@0: EXPORT_C BIO *BIO_new_ssl(SSL_CTX *ctx, int client) sl@0: { sl@0: BIO *ret; sl@0: SSL *ssl; sl@0: sl@0: if ((ret=BIO_new(BIO_f_ssl())) == NULL) sl@0: return(NULL); sl@0: if ((ssl=SSL_new(ctx)) == NULL) sl@0: { sl@0: BIO_free(ret); sl@0: return(NULL); sl@0: } sl@0: if (client) sl@0: SSL_set_connect_state(ssl); sl@0: else sl@0: SSL_set_accept_state(ssl); sl@0: sl@0: BIO_set_ssl(ret,ssl,BIO_CLOSE); sl@0: return(ret); sl@0: } sl@0: sl@0: EXPORT_C int BIO_ssl_copy_session_id(BIO *t, BIO *f) sl@0: { sl@0: t=BIO_find_type(t,BIO_TYPE_SSL); sl@0: f=BIO_find_type(f,BIO_TYPE_SSL); sl@0: if ((t == NULL) || (f == NULL)) sl@0: return(0); sl@0: if ( (((BIO_SSL *)t->ptr)->ssl == NULL) || sl@0: (((BIO_SSL *)f->ptr)->ssl == NULL)) sl@0: return(0); sl@0: SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl); sl@0: return(1); sl@0: } sl@0: sl@0: EXPORT_C void BIO_ssl_shutdown(BIO *b) sl@0: { sl@0: SSL *s; sl@0: sl@0: while (b != NULL) sl@0: { sl@0: if (b->method->type == BIO_TYPE_SSL) sl@0: { sl@0: s=((BIO_SSL *)b->ptr)->ssl; sl@0: SSL_shutdown(s); sl@0: break; sl@0: } sl@0: b=b->next_bio; sl@0: } sl@0: }