From c51ae173a653c346fd8138a44b7009e08e192e92 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bodo=20M=C3=B6ller?= Date: Tue, 11 Jan 2000 01:07:26 +0000 Subject: [PATCH] Clean up some of the SSL server code. --- CHANGES | 5 ++ ssl/s23_srvr.c | 13 +++- ssl/s3_pkt.c | 192 +++++++++++++++++++++++++++++-------------------- ssl/s3_srvr.c | 2 +- ssl/ssl.h | 7 +- ssl/ssl3.h | 28 ++------ ssl/ssl_err.c | 2 +- 7 files changed, 143 insertions(+), 106 deletions(-) diff --git a/CHANGES b/CHANGES index 49ed7aef5a..c1edb5c2e3 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,11 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 1999] + *) Rewrite ssl3_read_n (ssl/s3_pkt.c) avoiding a couple of bugs, + including a possible buffer overflow when the 'read_ahead' + flag is set. + [Bodo Moeller] + *) New function X509_CTX_rget_chain(), this returns the chain from an X509_CTX structure with a dup of the stack and all the X509 reference counts upped: so the stack will exist diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c index a9fefef354..3aec65dd4f 100644 --- a/ssl/s23_srvr.c +++ b/ssl/s23_srvr.c @@ -186,7 +186,18 @@ end: int ssl23_get_client_hello(SSL *s) { - char buf_space[11]; /* request this many bytes in initial read */ + char buf_space[11]; /* Request this many bytes in initial read. + * We can detect SSL 3.0/TLS 1.0 Client Hellos only + * when the following is in a single record + * (not guaranteed by protocol specs): + * Byte Content + * 0 type \ + * 1/2 version > record header + * 3/4 length / + * 5 msg_type \ + * 6-8 length > Client Hello message + * 9/10 client_version / + */ char *buf= &(buf_space[0]); unsigned char *p,*d,*dd; unsigned int i; diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c index 1ce30ff5a1..38063b50d5 100644 --- a/ssl/s3_pkt.c +++ b/ssl/s3_pkt.c @@ -55,6 +55,59 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-1999 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ #include #include @@ -71,104 +124,91 @@ static int ssl3_get_record(SSL *s); static int do_compress(SSL *ssl); static int do_uncompress(SSL *ssl); static int do_change_cipher_spec(SSL *ssl); + static int ssl3_read_n(SSL *s, int n, int max, int extend) { + /* If extend == 0, obtain new n-byte packet; if extend == 1, increase + * packet by another n bytes. + * The packet will be in the sub-array of s->s3->rbuf.buf specified + * by s->packet and s->packet_length. + * (If s->read_ahead is set, 'max' bytes may be stored in rbuf + * [plus s->packet_length bytes if extend == 1].) + */ int i,off,newb; - /* if there is stuff still in the buffer from a previous read, - * and there is more than we want, take some. */ + if (!extend) + { + /* start with empty packet ... */ + if (s->s3->rbuf.left == 0) + s->s3->rbuf.offset = 0; + s->packet = s->s3->rbuf.buf + s->s3->rbuf.offset; + s->packet_length = 0; + /* ... now we can act as if 'extend' was set */ + } + + /* if there is enough in the buffer from a previous read, take some */ if (s->s3->rbuf.left >= (int)n) { - if (extend) - s->packet_length+=n; - else - { - s->packet= &(s->s3->rbuf.buf[s->s3->rbuf.offset]); - s->packet_length=n; - } + s->packet_length+=n; s->s3->rbuf.left-=n; s->s3->rbuf.offset+=n; return(n); } /* else we need to read more data */ - if (!s->read_ahead) max=n; - if (max > SSL3_RT_MAX_PACKET_SIZE) - max=SSL3_RT_MAX_PACKET_SIZE; - - /* First check if there is some left or we want to extend */ - off=0; - if ( (s->s3->rbuf.left != 0) || - ((s->packet_length != 0) && extend)) - { - newb=s->s3->rbuf.left; - if (extend) - { - /* Copy bytes back to the front of the buffer - * Take the bytes already pointed to by 'packet' - * and take the extra ones on the end. */ - off=s->packet_length; - if (s->packet != s->s3->rbuf.buf) - memcpy(s->s3->rbuf.buf,s->packet,newb+off); - } - else if (s->s3->rbuf.offset != 0) - { /* so the data is not at the start of the buffer */ - memcpy(s->s3->rbuf.buf, - &(s->s3->rbuf.buf[s->s3->rbuf.offset]),newb); - s->s3->rbuf.offset=0; - } - - s->s3->rbuf.left=0; - } - else - newb=0; + if (!s->read_ahead) + max=n; - /* So we now have 'newb' bytes at the front of - * s->s3->rbuf.buf and need to read some more in on the end - * We start reading into the buffer at 's->s3->rbuf.offset' - */ - s->packet=s->s3->rbuf.buf; + { + /* avoid buffer overflow */ + int max_max = SSL3_RT_MAX_PACKET_SIZE - s->packet_length; + if (s->options & SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER) + max_max += SSL3_RT_MAX_EXTRA; + if (max > max_max) + max = max_max; + } + off = s->packet_length; + newb = s->s3->rbuf.left; + /* Move any available bytes to front of buffer: + * 'off' bytes already pointed to by 'packet', + * 'newb' extra ones at the end */ + if (s->packet != s->s3->rbuf.buf) + { + /* off > 0 */ + memmove(s->s3->rbuf.buf, s->packet, off+newb); + s->packet = s->s3->rbuf.buf; + } + while (newb < n) { + /* Now we have off+newb bytes at the front of s->s3->rbuf.buf and need + * to read in more until we have off+n (up to off+max if possible) */ + clear_sys_error(); if (s->rbio != NULL) { s->rwstate=SSL_READING; - i=BIO_read(s->rbio, - (char *)&(s->s3->rbuf.buf[off+newb]), - max-newb); + i=BIO_read(s->rbio, &(s->s3->rbuf.buf[off+newb]), max-newb); } else { SSLerr(SSL_F_SSL3_READ_N,SSL_R_READ_BIO_NOT_SET); - i= -1; + i = -1; } if (i <= 0) { - s->s3->rbuf.left+=newb; + s->s3->rbuf.left = newb; return(i); } newb+=i; } - /* record used data read */ - if (newb > n) - { - s->s3->rbuf.offset=n+off; - s->s3->rbuf.left=newb-n; - } - else - { - s->s3->rbuf.offset=0; - s->s3->rbuf.left=0; - } - - if (extend) - s->packet_length+=n; - else - s->packet_length+=n; + /* done reading, now the book-keeping */ + s->s3->rbuf.offset = off + n; + s->s3->rbuf.left = newb - n; + s->packet_length += n; return(n); } @@ -176,8 +216,8 @@ static int ssl3_read_n(SSL *s, int n, int max, int extend) * It will return <= 0 if more data is needed, normally due to an error * or non-blocking IO. * When it finishes, one packet has been decoded and can be found in - * ssl->s3->rrec.type - is the type of record - * ssl->s3->rrec.data, - data + * ssl->s3->rrec.type - is the type of record + * ssl->s3->rrec.data, - data * ssl->s3->rrec.length, - number of bytes */ static int ssl3_get_record(SSL *s) @@ -262,7 +302,6 @@ again: if (rr->length > (s->packet_length-SSL3_RT_HEADER_LENGTH)) { i=rr->length; - /*-(s->packet_length-SSL3_RT_HEADER_LENGTH); */ n=ssl3_read_n(s,i,i,1); if (n <= 0) return(n); /* error or non-blocking io */ } @@ -645,7 +684,7 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) void (*cb)()=NULL; BIO *bio; - if (s->s3->rbuf.buf == NULL) /* Not initialize yet */ + if (s->s3->rbuf.buf == NULL) /* Not initialized yet */ if (!ssl3_setup_buffers(s)) return(-1); @@ -662,10 +701,10 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len) start: s->rwstate=SSL_NOTHING; - /* s->s3->rrec.type - is the type of record - * s->s3->rrec.data, - data - * s->s3->rrec.off, - ofset into 'data' for next read - * s->s3->rrec.length, - number of bytes. */ + /* s->s3->rrec.type - is the type of record + * s->s3->rrec.data, - data + * s->s3->rrec.off, - offset into 'data' for next read + * s->s3->rrec.length, - number of bytes. */ rr= &(s->s3->rrec); /* get new packet */ @@ -692,16 +731,16 @@ start: return(0); } - /* Check for an incoming 'Client Request' message */ + /* Check for an incoming 'Hello Request' message from client */ if ((rr->type == SSL3_RT_HANDSHAKE) && (rr->length == 4) && - (rr->data[0] == SSL3_MT_CLIENT_REQUEST) && + (rr->data[0] == SSL3_MT_HELLO_REQUEST) && (s->session != NULL) && (s->session->cipher != NULL)) { if ((rr->data[1] != 0) || (rr->data[2] != 0) || (rr->data[3] != 0)) { al=SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_CLIENT_REQUEST); + SSLerr(SSL_F_SSL3_READ_BYTES,SSL_R_BAD_HELLO_REQUEST); goto err; } @@ -1038,4 +1077,3 @@ int ssl3_dispatch_alert(SSL *s) } return(i); } - diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 85b0f5e9ef..5ba3a28e63 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -503,7 +503,7 @@ static int ssl3_send_hello_request(SSL *s) if (s->state == SSL3_ST_SW_HELLO_REQ_A) { p=(unsigned char *)s->init_buf->data; - *(p++)=SSL3_MT_CLIENT_REQUEST; + *(p++)=SSL3_MT_HELLO_REQUEST; *(p++)=0; *(p++)=0; *(p++)=0; diff --git a/ssl/ssl.h b/ssl/ssl.h index 636b8bc2a2..94a06572a2 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -441,7 +441,7 @@ struct ssl_ctx_st /* get client cert callback */ /**/ int (*client_cert_cb)(/* SSL *ssl, X509 **x509, EVP_PKEY **pkey */); - /* what we put in client requests */ + /* what we put in client cert requests */ STACK_OF(X509_NAME) *client_CA; /**/ int quiet_shutdown; @@ -575,7 +575,8 @@ struct ssl_st struct ssl2_ctx_st *s2; /* SSLv2 variables */ struct ssl3_ctx_st *s3; /* SSLv3 variables */ - int read_ahead; /* Read as many input bytes as possible */ + int read_ahead; /* Read as many input bytes as possible + * (for non-blocking reads) */ int hit; /* reusing a previous session */ int purpose; /* Purpose setting */ @@ -1310,7 +1311,7 @@ int SSL_COMP_add_compression_method(int id,char *cm); #define SSL_R_BAD_AUTHENTICATION_TYPE 102 #define SSL_R_BAD_CHANGE_CIPHER_SPEC 103 #define SSL_R_BAD_CHECKSUM 104 -#define SSL_R_BAD_CLIENT_REQUEST 105 +#define SSL_R_BAD_HELLO_REQUEST 105 #define SSL_R_BAD_DATA_RETURNED_BY_CALLBACK 106 #define SSL_R_BAD_DECOMPRESSION 107 #define SSL_R_BAD_DH_G_LENGTH 108 diff --git a/ssl/ssl3.h b/ssl/ssl3.h index 322acaf0b6..da47377e57 100644 --- a/ssl/ssl3.h +++ b/ssl/ssl3.h @@ -158,22 +158,6 @@ extern "C" { #define SSL3_RT_MAX_PACKET_SIZE (SSL3_RT_MAX_ENCRYPTED_LENGTH+SSL3_RT_HEADER_LENGTH) #define SSL3_RT_MAX_DATA_SIZE (1024*1024) -/* the states that a SSL3_RECORD can be in - * For SSL_read it goes - * rbuf->ENCODED -> read - * ENCODED -> we need to decode everything - call decode_record - */ - -#define SSL3_RS_BLANK 1 -#define SSL3_RS_DATA - -#define SSL3_RS_ENCODED 2 -#define SSL3_RS_READ_MORE 3 -#define SSL3_RS_WRITE_MORE -#define SSL3_RS_PLAIN 3 -#define SSL3_RS_PART_READ 4 -#define SSL3_RS_PART_WRITE 5 - #define SSL3_MD_CLIENT_FINISHED_CONST "\x43\x4C\x4E\x54" #define SSL3_MD_SERVER_FINISHED_CONST "\x53\x52\x56\x52" @@ -205,7 +189,6 @@ extern "C" { typedef struct ssl3_record_st { /*r */ int type; /* type of record */ -/* */ /*int state;*/ /* any data in it? */ /*rw*/ unsigned int length; /* How many bytes available */ /*r */ unsigned int off; /* read/write offset into 'buf' */ /*rw*/ unsigned char *data; /* pointer to the record data */ @@ -215,11 +198,10 @@ typedef struct ssl3_record_st typedef struct ssl3_buffer_st { -/*r */ int total; /* used in non-blocking writes */ -/*r */ int wanted; /* how many more bytes we need */ -/*rw*/ int left; /* how many bytes left */ -/*rw*/ int offset; /* where to 'copy from' */ -/*rw*/ unsigned char *buf; /* SSL3_RT_MAX_PACKET_SIZE bytes */ + unsigned char *buf; /* SSL3_RT_MAX_PACKET_SIZE bytes (more if + * SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER is set) */ + int offset; /* where to 'copy from' */ + int left; /* how many bytes left */ } SSL3_BUFFER; #define SSL3_CT_RSA_SIGN 1 @@ -436,7 +418,7 @@ typedef struct ssl3_ctx_st #define SSL3_ST_SW_FINISHED_A (0x1E0|SSL_ST_ACCEPT) #define SSL3_ST_SW_FINISHED_B (0x1E1|SSL_ST_ACCEPT) -#define SSL3_MT_CLIENT_REQUEST 0 +#define SSL3_MT_HELLO_REQUEST 0 #define SSL3_MT_CLIENT_HELLO 1 #define SSL3_MT_SERVER_HELLO 2 #define SSL3_MT_CERTIFICATE 11 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 7c611650f3..9dd483d112 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -205,7 +205,7 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_BAD_AUTHENTICATION_TYPE ,"bad authentication type"}, {SSL_R_BAD_CHANGE_CIPHER_SPEC ,"bad change cipher spec"}, {SSL_R_BAD_CHECKSUM ,"bad checksum"}, -{SSL_R_BAD_CLIENT_REQUEST ,"bad client request"}, +{SSL_R_BAD_HELLO_REQUEST ,"bad hello request"}, {SSL_R_BAD_DATA_RETURNED_BY_CALLBACK ,"bad data returned by callback"}, {SSL_R_BAD_DECOMPRESSION ,"bad decompression"}, {SSL_R_BAD_DH_G_LENGTH ,"bad dh g length"}, -- 2.25.1