X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fbio_ssl.c;h=f62cde4e5d5111726537e1b79c66110d1ab214fb;hp=6c0babaf30ccca03f6cbcd3fc6b03d7ac1f74ebb;hb=48c843c3672c49724b3ccb11204b7ae67b17c9cb;hpb=d02b48c63a58ea4367a0e905979f140b7d090f86 diff --git a/ssl/bio_ssl.c b/ssl/bio_ssl.c index 6c0babaf30..f62cde4e5d 100644 --- a/ssl/bio_ssl.c +++ b/ssl/bio_ssl.c @@ -1,5 +1,5 @@ /* ssl/bio_ssl.c */ -/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) +/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written @@ -57,27 +57,30 @@ */ #include +#include #include #include -#include "bio.h" -#include "err.h" -#include "ssl.h" +#include +#include +#include +#include -#ifndef NOPROTO static int ssl_write(BIO *h,char *buf,int num); static int ssl_read(BIO *h,char *buf,int size); static int ssl_puts(BIO *h,char *str); static long ssl_ctrl(BIO *h,int cmd,long arg1,char *arg2); static int ssl_new(BIO *h); static int ssl_free(BIO *data); -#else -static int ssl_write(); -static int ssl_read(); -static int ssl_puts(); -static long ssl_ctrl(); -static int ssl_new(); -static int ssl_free(); -#endif +typedef struct bio_ssl_st + { + SSL *ssl; /* The ssl handle :-) */ + /* re-negotiate every time the total number of bytes is this size */ + int num_renegotiates; + unsigned long renegotiate_count; + unsigned long byte_count; + unsigned long renegotiate_timeout; + unsigned long last_time; + } BIO_SSL; static BIO_METHOD methods_sslp= { @@ -91,84 +94,118 @@ static BIO_METHOD methods_sslp= ssl_free, }; -BIO_METHOD *BIO_f_ssl() +BIO_METHOD *BIO_f_ssl(void) { return(&methods_sslp); } -static int ssl_new(bi) -BIO *bi; +static int ssl_new(BIO *bi) { + BIO_SSL *bs; + + bs=(BIO_SSL *)Malloc(sizeof(BIO_SSL)); + if (bs == NULL) + { + BIOerr(BIO_F_SSL_NEW,ERR_R_MALLOC_FAILURE); + return(0); + } + memset(bs,0,sizeof(BIO_SSL)); bi->init=0; - bi->ptr=NULL; /* The SSL structure */ + bi->ptr=(char *)bs; bi->flags=0; return(1); } -static int ssl_free(a) -BIO *a; +static int ssl_free(BIO *a) { + BIO_SSL *bs; + if (a == NULL) return(0); - if (a->ptr != NULL) SSL_shutdown((SSL *)a->ptr); + bs=(BIO_SSL *)a->ptr; + if (bs->ssl != NULL) SSL_shutdown(bs->ssl); if (a->shutdown) { - if (a->init) SSL_free((SSL *)a->ptr); + if (a->init && (bs->ssl != NULL)) + SSL_free(bs->ssl); a->init=0; a->flags=0; - a->ptr=NULL; } + if (a->ptr != NULL) + Free(a->ptr); return(1); } -static int ssl_read(b,out,outl) -BIO *b; -char *out; -int outl; +static int ssl_read(BIO *b, char *out, int outl) { int ret=1; - int inflags,outflags; + BIO_SSL *sb; SSL *ssl; int retry_reason=0; + int r=0; if (out == NULL) return(0); - ssl=(SSL *)b->ptr; + sb=(BIO_SSL *)b->ptr; + ssl=sb->ssl; - inflags=outflags=b->flags; - - outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY); + BIO_clear_retry_flags(b); +#if 0 if (!SSL_is_init_finished(ssl)) { - ret=SSL_do_handshake(ssl); -#if 0 +/* ret=SSL_do_handshake(ssl); */ if (ret > 0) { + outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); ret= -1; goto end; } -#endif } - if (ret > 0) - ret=SSL_read(ssl,out,outl); +#endif +/* if (ret > 0) */ + ret=SSL_read(ssl,out,outl); switch (SSL_get_error(ssl,ret)) { case SSL_ERROR_NONE: if (ret <= 0) break; + if (sb->renegotiate_count > 0) + { + sb->byte_count+=ret; + if (sb->byte_count > sb->renegotiate_count) + { + sb->byte_count=0; + sb->num_renegotiates++; + SSL_renegotiate(ssl); + r=1; + } + } + if ((sb->renegotiate_timeout > 0) && (!r)) + { + unsigned long tm; + + tm=(unsigned long)time(NULL); + if (tm > sb->last_time+sb->renegotiate_timeout) + { + sb->last_time=tm; + sb->num_renegotiates++; + SSL_renegotiate(ssl); + } + } + break; case SSL_ERROR_WANT_READ: - outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_read(b); break; case SSL_ERROR_WANT_WRITE: - outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_write(b); break; case SSL_ERROR_WANT_X509_LOOKUP: - outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_special(b); retry_reason=BIO_RR_SSL_X509_LOOKUP; break; case SSL_ERROR_WANT_CONNECT: - outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_special(b); retry_reason=BIO_RR_CONNECT; break; case SSL_ERROR_SYSCALL: @@ -179,47 +216,66 @@ int outl; } b->retry_reason=retry_reason; - b->flags=outflags; return(ret); } -static int ssl_write(b,out,outl) -BIO *b; -char *out; -int outl; +static int ssl_write(BIO *b, char *out, int outl) { - int ret; - int inflags,outflags,retry_reason=0; + int ret,r=0; + int retry_reason=0; SSL *ssl; + BIO_SSL *bs; if (out == NULL) return(0); - ssl=(SSL *)b->ptr; + bs=(BIO_SSL *)b->ptr; + ssl=bs->ssl; - inflags=outflags=b->flags; + BIO_clear_retry_flags(b); - outflags&= ~(BIO_FLAGS_RWS|BIO_FLAGS_SHOULD_RETRY); - - ret=SSL_do_handshake(ssl); - if (ret > 0) - ret=SSL_write(ssl,out,outl); +/* ret=SSL_do_handshake(ssl); + if (ret > 0) */ + ret=SSL_write(ssl,out,outl); switch (SSL_get_error(ssl,ret)) { case SSL_ERROR_NONE: if (ret <= 0) break; + if (bs->renegotiate_count > 0) + { + bs->byte_count+=ret; + if (bs->byte_count > bs->renegotiate_count) + { + bs->byte_count=0; + bs->num_renegotiates++; + SSL_renegotiate(ssl); + r=1; + } + } + if ((bs->renegotiate_timeout > 0) && (!r)) + { + unsigned long tm; + + tm=(unsigned long)time(NULL); + if (tm > bs->last_time+bs->renegotiate_timeout) + { + bs->last_time=tm; + bs->num_renegotiates++; + SSL_renegotiate(ssl); + } + } break; case SSL_ERROR_WANT_WRITE: - outflags=(BIO_FLAGS_WRITE|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_write(b); break; case SSL_ERROR_WANT_READ: - outflags=(BIO_FLAGS_READ|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_read(b); break; case SSL_ERROR_WANT_X509_LOOKUP: - outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_special(b); retry_reason=BIO_RR_SSL_X509_LOOKUP; break; case SSL_ERROR_WANT_CONNECT: - outflags=(BIO_FLAGS_IO_SPECIAL|BIO_FLAGS_SHOULD_RETRY); + BIO_set_retry_special(b); retry_reason=BIO_RR_CONNECT; case SSL_ERROR_SYSCALL: case SSL_ERROR_SSL: @@ -228,21 +284,20 @@ int outl; } b->retry_reason=retry_reason; - b->flags=outflags; return(ret); } -static long ssl_ctrl(b,cmd,num,ptr) -BIO *b; -int cmd; -long num; -char *ptr; +static long ssl_ctrl(BIO *b, int cmd, long num, char *ptr) { SSL **sslp,*ssl; + BIO_SSL *bs; BIO *dbio,*bio; long ret=1; - ssl=(SSL *)b->ptr; + bs=(BIO_SSL *)b->ptr; + ssl=bs->ssl; + if ((ssl == NULL) && (cmd != BIO_C_SET_SSL)) + return(0); switch (cmd) { case BIO_CTRL_RESET: @@ -262,7 +317,6 @@ char *ptr; else ret=1; break; - case BIO_CTRL_EOF: case BIO_CTRL_INFO: ret=0; break; @@ -272,17 +326,33 @@ char *ptr; else SSL_set_accept_state(ssl); break; + case BIO_C_SET_SSL_RENEGOTIATE_TIMEOUT: + ret=bs->renegotiate_timeout; + if (num < 60) num=5; + bs->renegotiate_timeout=(unsigned long)num; + bs->last_time=(unsigned long)time(NULL); + break; + case BIO_C_SET_SSL_RENEGOTIATE_BYTES: + ret=bs->renegotiate_count; + if ((long)num >=512) + bs->renegotiate_count=(unsigned long)num; + break; + case BIO_C_GET_SSL_NUM_RENEGOTIATES: + ret=bs->num_renegotiates; + break; case BIO_C_SET_SSL: - ssl_free(b); + if (ssl != NULL) + ssl_free(b); b->shutdown=(int)num; - b->ptr=ptr; ssl=(SSL *)ptr; + ((BIO_SSL *)b->ptr)->ssl=ssl; bio=SSL_get_rbio(ssl); if (bio != NULL) { if (b->next_bio != NULL) BIO_push(bio,b->next_bio); b->next_bio=bio; + CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO); } b->init=1; break; @@ -292,6 +362,8 @@ char *ptr; sslp=(SSL **)ptr; *sslp=ssl; } + else + ret=0; break; case BIO_CTRL_GET_CLOSE: ret=b->shutdown; @@ -313,10 +385,10 @@ char *ptr; BIO_copy_next_retry(b); break; case BIO_CTRL_PUSH: - if (b->next_bio != NULL) + if ((b->next_bio != NULL) && (b->next_bio != ssl->rbio)) { SSL_set_bio(ssl,b->next_bio,b->next_bio); - b->next_bio->references++; + CRYPTO_add(&b->next_bio->references,1,CRYPTO_LOCK_BIO); } break; case BIO_CTRL_POP: @@ -355,21 +427,41 @@ char *ptr; break; case BIO_CTRL_DUP: dbio=(BIO *)ptr; - if (dbio->ptr != NULL) - SSL_free((SSL *)dbio->ptr); - dbio->ptr=(char *)SSL_dup(ssl); - ret=(dbio->ptr != NULL); + if (((BIO_SSL *)dbio->ptr)->ssl != NULL) + SSL_free(((BIO_SSL *)dbio->ptr)->ssl); + ((BIO_SSL *)dbio->ptr)->ssl=SSL_dup(ssl); + ((BIO_SSL *)dbio->ptr)->renegotiate_count= + ((BIO_SSL *)b->ptr)->renegotiate_count; + ((BIO_SSL *)dbio->ptr)->byte_count= + ((BIO_SSL *)b->ptr)->byte_count; + ((BIO_SSL *)dbio->ptr)->renegotiate_timeout= + ((BIO_SSL *)b->ptr)->renegotiate_timeout; + ((BIO_SSL *)dbio->ptr)->last_time= + ((BIO_SSL *)b->ptr)->last_time; + ret=(((BIO_SSL *)dbio->ptr)->ssl != NULL); + break; + case BIO_C_GET_FD: + ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); + break; + case BIO_CTRL_SET_CALLBACK: + SSL_set_info_callback(ssl,(void (*)())ptr); + break; + case BIO_CTRL_GET_CALLBACK: + { + void (**fptr)(); + + fptr=(void (**)())ptr; + *fptr=SSL_get_info_callback(ssl); + } break; default: - return(0); + ret=BIO_ctrl(ssl->rbio,cmd,num,ptr); break; } return(ret); } -static int ssl_puts(bp,str) -BIO *bp; -char *str; +static int ssl_puts(BIO *bp, char *str) { int n,ret; @@ -378,9 +470,41 @@ char *str; return(ret); } -BIO *BIO_new_ssl(ctx,client) -SSL_CTX *ctx; -int client; +BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx) + { + BIO *ret=NULL,*buf=NULL,*ssl=NULL; + + if ((buf=BIO_new(BIO_f_buffer())) == NULL) + return(NULL); + if ((ssl=BIO_new_ssl_connect(ctx)) == NULL) + goto err; + if ((ret=BIO_push(buf,ssl)) == NULL) + goto err; + return(ret); +err: + if (buf != NULL) BIO_free(buf); + if (ssl != NULL) BIO_free(ssl); + return(NULL); + } + +BIO *BIO_new_ssl_connect(SSL_CTX *ctx) + { + BIO *ret=NULL,*con=NULL,*ssl=NULL; + + if ((con=BIO_new(BIO_s_connect())) == NULL) + return(NULL); + if ((ssl=BIO_new_ssl(ctx,1)) == NULL) + goto err; + if ((ret=BIO_push(ssl,con)) == NULL) + goto err; + return(ret); +err: + if (con != NULL) BIO_free(con); + if (ret != NULL) BIO_free(ret); + return(NULL); + } + +BIO *BIO_new_ssl(SSL_CTX *ctx, int client) { BIO *ret; SSL *ssl; @@ -401,21 +525,20 @@ int client; return(ret); } -int BIO_ssl_copy_session_id(t,f) -BIO *t,*f; +int BIO_ssl_copy_session_id(BIO *t, BIO *f) { t=BIO_find_type(t,BIO_TYPE_SSL); f=BIO_find_type(f,BIO_TYPE_SSL); if ((t == NULL) || (f == NULL)) return(0); - if ((t->ptr == NULL) || (f->ptr == NULL)) + if ( (((BIO_SSL *)t->ptr)->ssl == NULL) || + (((BIO_SSL *)f->ptr)->ssl == NULL)) return(0); - SSL_copy_session_id((SSL *)t->ptr,(SSL *)f->ptr); + SSL_copy_session_id(((BIO_SSL *)t->ptr)->ssl,((BIO_SSL *)f->ptr)->ssl); return(1); } -void BIO_ssl_shutdown(b) -BIO *b; +void BIO_ssl_shutdown(BIO *b) { SSL *s; @@ -423,7 +546,7 @@ BIO *b; { if (b->method->type == BIO_TYPE_SSL) { - s=(SSL *)b->ptr; + s=((BIO_SSL *)b->ptr)->ssl; SSL_shutdown(s); break; }