diff --git a/apps/ciphers.c b/apps/ciphers.c index 232fd602fd..47132fdfc5 100644 --- a/apps/ciphers.c +++ b/apps/ciphers.c @@ -94,7 +94,7 @@ int ciphers_main(int argc, char **argv) SSL_CTX *ctx = NULL; SSL *ssl = NULL; STACK_OF(SSL_CIPHER) *sk = NULL; - const SSL_METHOD *meth = SSLv23_server_method(); + const SSL_METHOD *meth = TLS_server_method(); int ret = 1, i, verbose = 0, Verbose = 0, use_supported = 0; #ifndef OPENSSL_NO_SSL_TRACE int stdname = 0; diff --git a/apps/s_server.c b/apps/s_server.c index 2ef902a531..61d13f3e0a 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -987,7 +987,7 @@ int s_server_main(int argc, char *argv[]) ENGINE *e = NULL; EVP_PKEY *s_key = NULL, *s_dkey = NULL; SSL_CONF_CTX *cctx = NULL; - const SSL_METHOD *meth = SSLv23_server_method(); + const SSL_METHOD *meth = TLS_server_method(); SSL_EXCERT *exc = NULL; STACK_OF(OPENSSL_STRING) *ssl_args = NULL; STACK_OF(X509) *s_chain = NULL, *s_dchain = NULL; diff --git a/crypto/threads/mttest.c b/crypto/threads/mttest.c index f6f8df289c..3218c32924 100644 --- a/crypto/threads/mttest.c +++ b/crypto/threads/mttest.c @@ -194,7 +194,7 @@ int main(int argc, char *argv[]) SSL_CTX *c_ctx = NULL; char *scert = TEST_SERVER_CERT; char *ccert = TEST_CLIENT_CERT; - SSL_METHOD *ssl_method = SSLv23_method(); + SSL_METHOD *ssl_method = TLS_method(); RAND_seed(rnd_seed, sizeof rnd_seed); diff --git a/demos/bio/saccept.c b/demos/bio/saccept.c index 505d98b68f..0d173aa039 100644 --- a/demos/bio/saccept.c +++ b/demos/bio/saccept.c @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) /* Add ciphers and message digests */ OpenSSL_add_ssl_algorithms(); - ctx = SSL_CTX_new(SSLv23_server_method()); + ctx = SSL_CTX_new(TLS_server_method()); if (!SSL_CTX_use_certificate_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) goto err; if (!SSL_CTX_use_PrivateKey_file(ctx, CERT_FILE, SSL_FILETYPE_PEM)) diff --git a/demos/bio/server-arg.c b/demos/bio/server-arg.c index b188f6a4ed..242ca6c0af 100644 --- a/demos/bio/server-arg.c +++ b/demos/bio/server-arg.c @@ -29,7 +29,7 @@ int main(int argc, char *argv[]) /* Add ciphers and message digests */ OpenSSL_add_ssl_algorithms(); - ctx = SSL_CTX_new(SSLv23_server_method()); + ctx = SSL_CTX_new(TLS_server_method()); cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); diff --git a/demos/bio/server-conf.c b/demos/bio/server-conf.c index cc9fe8a828..bf3dd067e5 100644 --- a/demos/bio/server-conf.c +++ b/demos/bio/server-conf.c @@ -49,7 +49,7 @@ int main(int argc, char *argv[]) goto err; } - ctx = SSL_CTX_new(SSLv23_server_method()); + ctx = SSL_CTX_new(TLS_server_method()); cctx = SSL_CONF_CTX_new(); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_SERVER); SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CERTIFICATE); diff --git a/demos/easy_tls/easy-tls.c b/demos/easy_tls/easy-tls.c index 9346720dae..2befb657a0 100644 --- a/demos/easy_tls/easy-tls.c +++ b/demos/easy_tls/easy-tls.c @@ -668,7 +668,7 @@ SSL_CTX *tls_create_ctx(struct tls_create_ctx_args a, void *apparg) ret = SSL_CTX_new((a.client_p ? SSLv23_client_method : - SSLv23_server_method) ()); + TLS_server_method) ()); if (ret == NULL) goto err; diff --git a/demos/ssl/serv.cpp b/demos/ssl/serv.cpp index 6d4cefd5d0..9cb77f8275 100644 --- a/demos/ssl/serv.cpp +++ b/demos/ssl/serv.cpp @@ -55,7 +55,7 @@ void main () SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); - meth = SSLv23_server_method(); + meth = TLS_server_method(); ctx = SSL_CTX_new (meth); if (!ctx) { ERR_print_errors_fp(stderr); diff --git a/demos/state_machine/state_machine.c b/demos/state_machine/state_machine.c index 1dd8c2be22..98802a12ec 100644 --- a/demos/state_machine/state_machine.c +++ b/demos/state_machine/state_machine.c @@ -119,7 +119,7 @@ SSLStateMachine *SSLStateMachine_new(const char *szCertificateFile, die_unless(pMachine); - pMachine->pCtx = SSL_CTX_new(SSLv23_server_method()); + pMachine->pCtx = SSL_CTX_new(TLS_server_method()); die_unless(pMachine->pCtx); n = SSL_CTX_use_certificate_file(pMachine->pCtx, szCertificateFile, diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index 27e44cc20f..f169fcd2a9 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1562,13 +1562,18 @@ __owur const SSL_METHOD *SSLv3_server_method(void); /* SSLv3 */ __owur const SSL_METHOD *SSLv3_client_method(void); /* SSLv3 */ # endif -__owur const SSL_METHOD *SSLv23_method(void); /* Negotiate highest available SSL/TLS - * version */ -__owur const SSL_METHOD *SSLv23_server_method(void); /* Negotiate highest available - * SSL/TLS version */ +#ifdef OPENSSL_USE_DEPRECATED +#define SSLv23_method TLS_method +#define SSLv23_server_method TLS_server_method +#endif +/* This next one will be deprecated in a subsequent commit */ __owur const SSL_METHOD *SSLv23_client_method(void); /* Negotiate highest available * SSL/TLS version */ +/* Negotiate highest available SSL/TLS version */ +__owur const SSL_METHOD *TLS_method(void); +__owur const SSL_METHOD *TLS_server_method(void); + __owur const SSL_METHOD *TLSv1_method(void); /* TLSv1.0 */ __owur const SSL_METHOD *TLSv1_server_method(void); /* TLSv1.0 */ __owur const SSL_METHOD *TLSv1_client_method(void); /* TLSv1.0 */ diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h index e1beaf3bbd..d10739690e 100644 --- a/include/openssl/tls1.h +++ b/include/openssl/tls1.h @@ -167,6 +167,9 @@ extern "C" { # define TLS1_2_VERSION 0x0303 # define TLS_MAX_VERSION TLS1_2_VERSION +/* Special value for method supporting multiple versions */ +# define TLS_ANY_VERSION 0x10000 + # define TLS1_VERSION_MAJOR 0x03 # define TLS1_VERSION_MINOR 0x01 diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index eccb5176ba..97f6e900c5 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -1109,6 +1109,21 @@ int ssl3_read_bytes(SSL *s, int type, unsigned char *buf, int len, int peek) * then it was unexpected (Hello Request or Client Hello). */ + /* + * Lets just double check that we've not got an SSLv2 record + */ + if (rr->rec_version == SSL2_VERSION) { + /* + * Should never happen. ssl3_get_record() should only give us an SSLv2 + * record back if this is the first packet and we are looking for an + * initial ClientHello. Therefore |type| should always be equal to + * |rr->type|. If not then something has gone horribly wrong + */ + al = SSL_AD_INTERNAL_ERROR; + SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR); + goto f_err; + } + /* * In case of record types for which we have 'fragment' storage, fill * that so that we can process the data at a fixed place. @@ -1464,4 +1479,12 @@ void ssl3_record_sequence_update(unsigned char *seq) } } +int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl) +{ + return SSL3_RECORD_is_sslv2_record(&rl->rrec); +} +int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl) +{ + return SSL3_RECORD_get_length(&rl->rrec); +} diff --git a/ssl/record/record.h b/ssl/record/record.h index 6bccb71d83..a778998196 100644 --- a/ssl/record/record.h +++ b/ssl/record/record.h @@ -132,6 +132,10 @@ typedef struct ssl3_buffer_st { #define SEQ_NUM_SIZE 8 typedef struct ssl3_record_st { + /* Record layer version */ + /* r */ + int rec_version; + /* type of record */ /* r */ int type; @@ -298,6 +302,8 @@ typedef struct record_layer_st { * * *****************************************************************************/ +#define MIN_SSL2_RECORD_LEN 9 + #define RECORD_LAYER_set_read_ahead(rl, ra) ((rl)->read_ahead = (ra)) #define RECORD_LAYER_get_read_ahead(rl) ((rl)->read_ahead) #define RECORD_LAYER_get_packet(rl) ((rl)->packet) @@ -319,6 +325,8 @@ void RECORD_LAYER_dup(RECORD_LAYER *dst, RECORD_LAYER *src); void RECORD_LAYER_reset_read_sequence(RECORD_LAYER *rl); void RECORD_LAYER_reset_write_sequence(RECORD_LAYER *rl); int RECORD_LAYER_setup_comp_buffer(RECORD_LAYER *rl); +int RECORD_LAYER_is_sslv2_record(RECORD_LAYER *rl); +int RECORD_LAYER_get_rrec_length(RECORD_LAYER *rl); __owur int ssl3_pending(const SSL *s); __owur int ssl23_read_bytes(SSL *s, int n); __owur int ssl23_write_bytes(SSL *s); diff --git a/ssl/record/record_locl.h b/ssl/record/record_locl.h index 72f8e55f3b..b2222d7c22 100644 --- a/ssl/record/record_locl.h +++ b/ssl/record/record_locl.h @@ -186,6 +186,8 @@ int ssl3_release_write_buffer(SSL *s); #define SSL3_RECORD_set_off(r, o) ((r)->off = (o)) #define SSL3_RECORD_add_off(r, o) ((r)->off += (o)) #define SSL3_RECORD_get_epoch(r) ((r)->epoch) +#define SSL3_RECORD_is_sslv2_record(r) \ + ((r)->rec_version == SSL2_VERSION) void SSL3_RECORD_clear(SSL3_RECORD *r); void SSL3_RECORD_release(SSL3_RECORD *r); diff --git a/ssl/record/ssl3_record.c b/ssl/record/ssl3_record.c index 032812772f..190abd26e8 100644 --- a/ssl/record/ssl3_record.c +++ b/ssl/record/ssl3_record.c @@ -166,6 +166,7 @@ void SSL3_RECORD_set_seq_num(SSL3_RECORD *r, const unsigned char *seq_num) */ #define MAX_EMPTY_RECORDS 32 +#define SSL2_RT_HEADER_LENGTH 2 /*- * Call this to get a new input record. * It will return <= 0 if more data is needed, normally due to an error @@ -216,71 +217,121 @@ int ssl3_get_record(SSL *s) RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_BODY); p = RECORD_LAYER_get_packet(&s->rlayer); - if (s->msg_callback) - s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, - s->msg_callback_arg); - /* Pull apart the header into the SSL3_RECORD */ - rr->type = *(p++); - ssl_major = *(p++); - ssl_minor = *(p++); - version = (ssl_major << 8) | ssl_minor; - n2s(p, rr->length); + /* + * Check whether this is a regular record or an SSLv2 style record. The + * latter is only used in an initial ClientHello for old clients. + */ + if (s->first_packet && s->server && !s->read_hash && !s->enc_read_ctx + && (p[0] & 0x80) && (p[2] == SSL2_MT_CLIENT_HELLO)) { + /* SSLv2 style record */ + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, p + 2, + RECORD_LAYER_get_packet_length(&s->rlayer) - 2, + s, s->msg_callback_arg); - /* Lets check version */ - if (!s->first_packet) { - if (version != s->version) { - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); - if ((s->version & 0xFF00) == (version & 0xFF00) - && !s->enc_write_ctx && !s->write_hash) - /* - * Send back error using their minor version number :-) - */ - s->version = (unsigned short)version; - al = SSL_AD_PROTOCOL_VERSION; + rr->type = SSL3_RT_HANDSHAKE; + rr->rec_version = SSL2_VERSION; + + rr->length = ((p[0] & 0x7f) << 8) | p[1]; + + if (rr->length > SSL3_BUFFER_get_len(&s->rlayer.rbuf) + - SSL2_RT_HEADER_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); goto f_err; } - } - if ((version >> 8) != SSL3_VERSION_MAJOR) { - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); - goto err; - } + if (rr->length < MIN_SSL2_RECORD_LEN) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + } else { + /* SSLv3+ style record */ + if (s->msg_callback) + s->msg_callback(0, 0, SSL3_RT_HEADER, p, 5, s, + s->msg_callback_arg); - if (rr->length > - SSL3_BUFFER_get_len(&s->rlayer.rbuf) - - SSL3_RT_HEADER_LENGTH) { - al = SSL_AD_RECORD_OVERFLOW; - SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); - goto f_err; + /* Pull apart the header into the SSL3_RECORD */ + rr->type = *(p++); + ssl_major = *(p++); + ssl_minor = *(p++); + version = (ssl_major << 8) | ssl_minor; + rr->rec_version = version; + n2s(p, rr->length); + + /* Lets check version */ + if (!s->first_packet) { + if (version != s->version) { + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); + if ((s->version & 0xFF00) == (version & 0xFF00) + && !s->enc_write_ctx && !s->write_hash) + /* + * Send back error using their minor version number :-) + */ + s->version = (unsigned short)version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + } + + if ((version >> 8) != SSL3_VERSION_MAJOR) { + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_WRONG_VERSION_NUMBER); + goto err; + } + + if (rr->length > + SSL3_BUFFER_get_len(&s->rlayer.rbuf) + - SSL3_RT_HEADER_LENGTH) { + al = SSL_AD_RECORD_OVERFLOW; + SSLerr(SSL_F_SSL3_GET_RECORD, SSL_R_PACKET_LENGTH_TOO_LONG); + goto f_err; + } } /* now s->rlayer.rstate == SSL_ST_READ_BODY */ } - /* s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data */ - - if (rr->length > - RECORD_LAYER_get_packet_length(&s->rlayer) - SSL3_RT_HEADER_LENGTH) { - /* now s->packet_length == SSL3_RT_HEADER_LENGTH */ + /* + * s->rlayer.rstate == SSL_ST_READ_BODY, get and decode the data. + * Calculate how much more data we need to read for the rest of the record + */ + if (rr->rec_version == SSL2_VERSION) { + i = rr->length + SSL2_RT_HEADER_LENGTH - SSL3_RT_HEADER_LENGTH; + } else { i = rr->length; + } + if (i > 0) { + /* now 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 */ /* - * now n == rr->length, and s->packet_length == SSL3_RT_HEADER_LENGTH - * + rr->length + * now n == rr->length, and + * s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length + * or + * s->packet_length == SSL2_RT_HEADER_LENGTH + rr->length + * (if SSLv2 packet) */ + } else { + n = 0; } /* set state for later operations */ RECORD_LAYER_set_rstate(&s->rlayer, SSL_ST_READ_HEADER); /* - * At this point, s->packet_length == SSL3_RT_HEADER_LNGTH + rr->length, + * At this point, s->packet_length == SSL3_RT_HEADER_LENGTH + rr->length, + * or s->packet_length == SSL2_RT_HEADER_LENGTH + rr->length * and we have that many bytes in s->packet */ - rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]); + if(rr->rec_version == SSL2_VERSION) { + rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[SSL2_RT_HEADER_LENGTH]); + } else { + rr->input = &(RECORD_LAYER_get_packet(&s->rlayer)[SSL3_RT_HEADER_LENGTH]); + } /* * ok, we can now read from 's->packet' data into 'rr' rr->input points diff --git a/ssl/s23_meth.c b/ssl/s23_meth.c index 757c5a9dc9..6080fba150 100644 --- a/ssl/s23_meth.c +++ b/ssl/s23_meth.c @@ -60,6 +60,7 @@ #include #include "ssl_locl.h" +/* static const SSL_METHOD *ssl23_get_method(int ver); static const SSL_METHOD *ssl23_get_method(int ver) { @@ -76,7 +77,5 @@ static const SSL_METHOD *ssl23_get_method(int ver) return (TLSv1_2_method()); else return (NULL); -} +}*/ -IMPLEMENT_ssl23_meth_func(SSLv23_method, - ssl23_accept, ssl23_connect, ssl23_get_method) diff --git a/ssl/s23_srvr.c b/ssl/s23_srvr.c index 50d634e265..58b89a6c93 100644 --- a/ssl/s23_srvr.c +++ b/ssl/s23_srvr.c @@ -134,9 +134,6 @@ static const SSL_METHOD *ssl23_get_server_method(int ver) return (NULL); } -IMPLEMENT_ssl23_meth_func(SSLv23_server_method, - ssl23_accept, - ssl_undefined_function, ssl23_get_server_method) int ssl23_accept(SSL *s) { diff --git a/ssl/s3_both.c b/ssl/s3_both.c index bf5e8c7c2d..193270b315 100644 --- a/ssl/s3_both.c +++ b/ssl/s3_both.c @@ -356,7 +356,7 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) } *ok = 1; s->state = stn; - s->init_msg = s->init_buf->data + 4; + s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; s->init_num = (int)s->s3->tmp.message_size; return s->init_num; } @@ -367,10 +367,9 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) int skip_message; do { - while (s->init_num < 4) { + while (s->init_num < SSL3_HM_HEADER_LENGTH) { i = s->method->ssl_read_bytes(s, SSL3_RT_HANDSHAKE, - &p[s->init_num], - 4 - s->init_num, 0); + &p[s->init_num], SSL3_HM_HEADER_LENGTH - s->init_num, 0); if (i <= 0) { s->rwstate = SSL_READING; *ok = 0; @@ -409,26 +408,49 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) s->s3->tmp.message_type = *(p++); - n2l3(p, l); - if (l > (unsigned long)max) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if (l > (INT_MAX - 4)) { /* BUF_MEM_grow takes an 'int' parameter */ - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); - goto f_err; - } - if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l + 4)) { - SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); - goto err; - } - s->s3->tmp.message_size = l; - s->state = stn; + if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + /* + * Only happens with SSLv3+ in an SSLv2 backward compatible + * ClientHello + */ + /* + * Total message size is the remaining record bytes to read + * plus the SSL3_HM_HEADER_LENGTH bytes that we already read + */ + l = RECORD_LAYER_get_rrec_length(&s->rlayer) + + SSL3_HM_HEADER_LENGTH; + if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l)) { + SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); + goto err; + } + s->s3->tmp.message_size = l; + s->state = stn; - s->init_msg = s->init_buf->data + 4; - s->init_num = 0; + s->init_msg = s->init_buf->data; + s->init_num = SSL3_HM_HEADER_LENGTH; + } else { + n2l3(p, l); + if (l > (unsigned long)max) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); + goto f_err; + } + /* BUF_MEM_grow takes an 'int' parameter */ + if (l > (INT_MAX - SSL3_HM_HEADER_LENGTH)) { + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_MESSAGE, SSL_R_EXCESSIVE_MESSAGE_SIZE); + goto f_err; + } + if (l && !BUF_MEM_grow_clean(s->init_buf, (int)l + 4)) { + SSLerr(SSL_F_SSL3_GET_MESSAGE, ERR_R_BUF_LIB); + goto err; + } + s->s3->tmp.message_size = l; + s->state = stn; + + s->init_msg = s->init_buf->data + SSL3_HM_HEADER_LENGTH; + s->init_num = 0; + } } /* next state (stn) */ @@ -456,10 +478,26 @@ long ssl3_get_message(SSL *s, int st1, int stn, int mt, long max, int *ok) #endif /* Feed this message into MAC computation. */ - ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num + 4); - if (s->msg_callback) - s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, - (size_t)s->init_num + 4, s, s->msg_callback_arg); + if(RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, s->init_num); + /* + * In previous versions we would have rewritten the SSLv2 record into + * something that looked like a SSLv3+ record and passed that to the + * callback. As we're not doing the rewriting anymore it's not clear + * what we should do here. + */ + if (s->msg_callback) + s->msg_callback(0, SSL2_VERSION, 0, s->init_buf->data, + (size_t)s->init_num, s, s->msg_callback_arg); + } else { + ssl3_finish_mac(s, (unsigned char *)s->init_buf->data, + s->init_num + SSL3_HM_HEADER_LENGTH); + if (s->msg_callback) + s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data, + (size_t)s->init_num + SSL3_HM_HEADER_LENGTH, s, + s->msg_callback_arg); + } + *ok = 1; return s->init_num; f_err: diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c index e7f1898e81..d3265f676e 100644 --- a/ssl/s3_lib.c +++ b/ssl/s3_lib.c @@ -3386,9 +3386,9 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg) * Apparently we're using a version-flexible SSL_METHOD (not at its * highest protocol version). */ - if (s->ctx->method->version == SSLv23_method()->version) { + if (s->ctx->method->version == TLS_method()->version) { #if TLS_MAX_VERSION != TLS1_2_VERSION -# error Code needs update for SSLv23_method() support beyond TLS1_2_VERSION. +# error Code needs update for TLS_method() support beyond TLS1_2_VERSION. #endif if (!(s->options & SSL_OP_NO_TLSv1_2)) return s->version == TLS1_2_VERSION; diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 4ee45eb57f..14daf8fe4e 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -256,7 +256,7 @@ int ssl3_accept(SSL *s) if (cb != NULL) cb(s, SSL_CB_HANDSHAKE_START, 1); - if ((s->version >> 8) != 3) { + if ((s->version >> 8 != 3) && s->version != TLS_ANY_VERSION) { SSLerr(SSL_F_SSL3_ACCEPT, ERR_R_INTERNAL_ERROR); s->state = SSL_ST_ERR; return -1; @@ -905,6 +905,7 @@ int ssl3_get_client_hello(SSL *s) SSL_COMP *comp = NULL; #endif STACK_OF(SSL_CIPHER) *ciphers = NULL; + int protverr = 1; if (s->state == SSL3_ST_SR_CLNT_HELLO_C && !s->first_packet) goto retry_cert; @@ -930,29 +931,130 @@ int ssl3_get_client_hello(SSL *s) s->first_packet = 0; d = p = (unsigned char *)s->init_msg; - /* - * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte - * for session id length - */ - if (n < 2 + SSL3_RANDOM_SIZE + 1) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; + /* First lets get s->client_version set correctly */ + if (!s->read_hash && !s->enc_read_ctx + && RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + if (n < MIN_SSL2_RECORD_LEN) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); + al = SSL_AD_DECODE_ERROR; + goto f_err; + } + /*- + * An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2 + * header is sent directly on the wire, not wrapped as a TLS + * record. Our record layer just processes the message length and passes + * the rest right through. Its format is: + * Byte Content + * 0-1 msg_length - decoded by the record layer + * 2 msg_type - s->init_msg points here + * 3-4 version + * 5-6 cipher_spec_length + * 7-8 session_id_length + * 9-10 challenge_length + * ... ... + */ + + if (p[0] != SSL2_MT_CLIENT_HELLO) { + /* + * Should never happen. We should have tested this in the record + * layer in order to have determined that this is a SSLv2 record + * in the first place + */ + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, ERR_R_INTERNAL_ERROR); + goto f_err; + } + + if ((p[1] == 0x00) && (p[2] == 0x02)) { + /* This is real SSLv2. We don't support it. */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + goto err; + } else if (p[1] == SSL3_VERSION_MAJOR) { + /* SSLv3/TLS */ + s->client_version = (((int)p[1]) << 8) | (int)p[2]; + } else { + /* No idea what protocol this is */ + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + goto err; + } + } else { + /* + * 2 bytes for client version, SSL3_RANDOM_SIZE bytes for random, 1 byte + * for session id length + */ + if (n < 2 + SSL3_RANDOM_SIZE + 1) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + + /* + * use version from inside client hello, not from record header (may + * differ: see RFC 2246, Appendix E, second paragraph) + */ + s->client_version = (((int)p[0]) << 8) | (int)p[1]; } - /* - * use version from inside client hello, not from record header (may - * differ: see RFC 2246, Appendix E, second paragraph) - */ - s->client_version = (((int)p[0]) << 8) | (int)p[1]; - p += 2; + /* Do SSL/TLS version negotiation if applicable */ + if (!SSL_IS_DTLS(s)) { + if (s->version != TLS_ANY_VERSION) { + if (s->client_version >= s->version + && (((s->client_version >> 8) & 0xff) == SSL3_VERSION_MAJOR)) { + protverr = 0; + } + } else { + /* + * We already know that this is an SSL3_VERSION_MAJOR protocol, + * so we're just testing the minor versions here + */ + switch(s->client_version) { + default: + case TLS1_2_VERSION: + if(!(s->options & SSL_OP_NO_TLSv1_2)) { + s->version = TLS1_2_VERSION; + s->method = TLSv1_2_server_method(); + protverr = 0; + break; + } + /* Deliberately fall through */ + case TLS1_1_VERSION: + if(!(s->options & SSL_OP_NO_TLSv1_1)) { + s->version = TLS1_1_VERSION; + s->method = TLSv1_1_server_method(); + protverr = 0; + break; + } + /* Deliberately fall through */ + case TLS1_VERSION: + if(!(s->options & SSL_OP_NO_TLSv1)) { + s->version = TLS1_VERSION; + s->method = TLSv1_server_method(); + protverr = 0; + break; + } + /* Deliberately fall through */ + case SSL3_VERSION: + if(!(s->options & SSL_OP_NO_SSLv3)) { + s->version = SSL3_VERSION; + s->method = SSLv3_server_method(); + protverr = 0; + break; + } + } + } + } else if (((s->client_version >> 8) & 0xff) == DTLS1_VERSION_MAJOR && + (s->client_version <= s->version + || s->method->version == DTLS_ANY_VERSION)) { + /* + * For DTLS we just check versions are potentially compatible. Version + * negotiation comes later. + */ + protverr = 0; + } - if (SSL_IS_DTLS(s) ? (s->client_version > s->version && - s->method->version != DTLS_ANY_VERSION) - : (s->client_version < s->version)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER); - if ((s->client_version >> 8) == SSL3_VERSION_MAJOR && - !s->enc_write_ctx && !s->write_hash) { + if (protverr) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_UNKNOWN_PROTOCOL); + if ((!s->enc_write_ctx && !s->write_hash)) { /* * similar to ssl3_get_record, send alert using remote version * number @@ -963,263 +1065,322 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } - /* - * If we require cookies and this ClientHello doesn't contain one, just - * return since we do not want to allocate any memory yet. So check - * cookie length... - */ - if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { - unsigned int session_length, cookie_length; + if (RECORD_LAYER_is_sslv2_record(&s->rlayer)) { + /* + * Handle an SSLv2 backwards compatible ClientHello + * Note, this is only for SSLv3+ using the backward compatible format. + * Real SSLv2 is not supported, and is rejected above. + */ + unsigned int csl, sil, cl; - session_length = *(p + SSL3_RANDOM_SIZE); + p += 3; + n2s(p, csl); + n2s(p, sil); + n2s(p, cl); - if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) { + if (csl + sil + cl + MIN_SSL2_RECORD_LEN != (unsigned int) n) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_RECORD_LENGTH_MISMATCH); al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); goto f_err; } - cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1); - if (cookie_length == 0) - return 1; - } + if (csl == 0) { + /* we need at least one cipher */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } - /* load the client random */ - memcpy(s->s3->client_random, p, SSL3_RANDOM_SIZE); - p += SSL3_RANDOM_SIZE; + if (ssl_bytes_to_cipher_list(s, p, csl, &(ciphers), 1) == NULL) { + goto err; + } - /* get the session-id */ - j = *(p++); + /* + * Ignore any session id. We don't allow resumption in a backwards + * compatible ClientHello + */ + s->hit = 0; - if (p + j > d + n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - - s->hit = 0; - /* - * Versions before 0.9.7 always allow clients to resume sessions in - * renegotiation. 0.9.7 and later allow this by default, but optionally - * ignore resumption requests with flag - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather - * than a change to default behavior so that applications relying on this - * for security won't even compile against older library versions). - * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to - * request renegotiation but not a new session (s->new_session remains - * unset): for servers, this essentially just means that the - * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be ignored. - */ - if ((s->new_session - && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { if (!ssl_get_new_session(s, 1)) goto err; - } else { - i = ssl_get_prev_session(s, p, j, d + n); - /* - * Only resume if the session's version matches the negotiated - * version. - * RFC 5246 does not provide much useful advice on resumption - * with a different protocol version. It doesn't forbid it but - * the sanity of such behaviour would be questionable. - * In practice, clients do not accept a version mismatch and - * will abort the handshake with an error. - */ - if (i == 1 && s->version == s->session->ssl_version) { /* previous - * session */ - s->hit = 1; - } else if (i == -1) - goto err; - else { /* i == 0 */ + /* Load the client random */ + i = (cl > SSL3_RANDOM_SIZE) ? SSL3_RANDOM_SIZE : cl; + memset(s->s3->client_random, 0, SSL3_RANDOM_SIZE); + memcpy(s->s3->client_random, &(p[csl + sil]), i); + + /* Set p to end of packet to ensure we don't look for extensions */ + p = d + n; + + /* No compression, so set i to 0 */ + i = 0; + } else { + /* If we get here we've got SSLv3+ in an SSLv3+ record */ + + p += 2; + + /* + * If we require cookies and this ClientHello doesn't contain one, just + * return since we do not want to allocate any memory yet. So check + * cookie length... + */ + if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) { + unsigned int session_length, cookie_length; + + session_length = *(p + SSL3_RANDOM_SIZE); + + if (p + SSL3_RANDOM_SIZE + session_length + 1 >= d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + cookie_length = *(p + SSL3_RANDOM_SIZE + session_length + 1); + + if (cookie_length == 0) + return 1; + } + + /* load the client random */ + memcpy(s->s3->client_random, p, SSL3_RANDOM_SIZE); + p += SSL3_RANDOM_SIZE; + + /* get the session-id */ + j = *(p++); + + if (p + j > d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + + s->hit = 0; + /* + * Versions before 0.9.7 always allow clients to resume sessions in + * renegotiation. 0.9.7 and later allow this by default, but optionally + * ignore resumption requests with flag + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather + * than a change to default behavior so that applications relying on + * this for security won't even compile against older library versions). + * 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to + * request renegotiation but not a new session (s->new_session remains + * unset): for servers, this essentially just means that the + * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be + * ignored. + */ + if ((s->new_session + && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) { if (!ssl_get_new_session(s, 1)) goto err; - } - } - - p += j; - - if (SSL_IS_DTLS(s)) { - /* cookie stuff */ - if (p + 1 > d + n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - cookie_len = *(p++); - - if (p + cookie_len > d + n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - - /* - * The ClientHello may contain a cookie even if the - * HelloVerify message has not been sent--make sure that it - * does not cause an overflow. - */ - if (cookie_len > sizeof(s->d1->rcvd_cookie)) { - /* too much data */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); - goto f_err; - } - - /* verify the cookie if appropriate option is set. */ - if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) && cookie_len > 0) { - memcpy(s->d1->rcvd_cookie, p, cookie_len); - - if (s->ctx->app_verify_cookie_cb != NULL) { - if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie, - cookie_len) == 0) { - al = SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_COOKIE_MISMATCH); - goto f_err; - } - /* else cookie verification succeeded */ + } else { + i = ssl_get_prev_session(s, p, j, d + n); + /* + * Only resume if the session's version matches the negotiated + * version. + * RFC 5246 does not provide much useful advice on resumption + * with a different protocol version. It doesn't forbid it but + * the sanity of such behaviour would be questionable. + * In practice, clients do not accept a version mismatch and + * will abort the handshake with an error. + */ + if (i == 1 && s->version == s->session->ssl_version) { + /* previous session */ + s->hit = 1; + } else if (i == -1) + goto err; + else { + /* i == 0 */ + if (!ssl_get_new_session(s, 1)) + goto err; } - /* default verification */ - else if (memcmp(s->d1->rcvd_cookie, s->d1->cookie, - s->d1->cookie_len) != 0) { - al = SSL_AD_HANDSHAKE_FAILURE; + } + + p += j; + + if (SSL_IS_DTLS(s)) { + /* cookie stuff */ + if (p + 1 > d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + cookie_len = *(p++); + + if (p + cookie_len > d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; + } + + /* + * The ClientHello may contain a cookie even if the + * HelloVerify message has not been sent--make sure that it + * does not cause an overflow. + */ + if (cookie_len > sizeof(s->d1->rcvd_cookie)) { + /* too much data */ + al = SSL_AD_DECODE_ERROR; SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); goto f_err; } - /* Set to -2 so if successful we return 2 */ - ret = -2; - } - p += cookie_len; - if (s->method->version == DTLS_ANY_VERSION) { - /* Select version to use */ - if (s->client_version <= DTLS1_2_VERSION && - !(s->options & SSL_OP_NO_DTLSv1_2)) { - s->version = DTLS1_2_VERSION; - s->method = DTLSv1_2_server_method(); - } else if (tls1_suiteb(s)) { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; - } else if (s->client_version <= DTLS1_VERSION && - !(s->options & SSL_OP_NO_DTLSv1)) { - s->version = DTLS1_VERSION; - s->method = DTLSv1_server_method(); - } else { - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_WRONG_VERSION_NUMBER); - s->version = s->client_version; - al = SSL_AD_PROTOCOL_VERSION; - goto f_err; + /* verify the cookie if appropriate option is set. */ + if ((SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) + && cookie_len > 0) { + memcpy(s->d1->rcvd_cookie, p, cookie_len); + + if (s->ctx->app_verify_cookie_cb != NULL) { + if (s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie, + cookie_len) == 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* else cookie verification succeeded */ + } + /* default verification */ + else if (memcmp(s->d1->rcvd_cookie, s->d1->cookie, + s->d1->cookie_len) != 0) { + al = SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH); + goto f_err; + } + /* Set to -2 so if successful we return 2 */ + ret = -2; } - s->session->ssl_version = s->version; - } - } - if (p + 2 > d + n) { - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); - goto f_err; - } - n2s(p, i); - - if (i == 0) { - al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); - goto f_err; - } - - /* i bytes of cipher data + 1 byte for compression length later */ - if ((p + i + 1) > (d + n)) { - /* not enough data */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } - if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers)) == NULL) { - goto err; - } - p += i; - - /* If it is a hit, check that the cipher is in the list */ - if (s->hit) { - j = 0; - id = s->session->cipher->id; - -#ifdef CIPHER_DEBUG - fprintf(stderr, "client sent %d ciphers\n", - sk_SSL_CIPHER_num(ciphers)); -#endif - for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { - c = sk_SSL_CIPHER_value(ciphers, i); -#ifdef CIPHER_DEBUG - fprintf(stderr, "client [%2d of %2d]:%s\n", - i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); -#endif - if (c->id == id) { - j = 1; - break; + p += cookie_len; + if (s->method->version == DTLS_ANY_VERSION) { + /* Select version to use */ + if (s->client_version <= DTLS1_2_VERSION && + !(s->options & SSL_OP_NO_DTLSv1_2)) { + s->version = DTLS1_2_VERSION; + s->method = DTLSv1_2_server_method(); + } else if (tls1_suiteb(s)) { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_ONLY_DTLS_1_2_ALLOWED_IN_SUITEB_MODE); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } else if (s->client_version <= DTLS1_VERSION && + !(s->options & SSL_OP_NO_DTLSv1)) { + s->version = DTLS1_VERSION; + s->method = DTLSv1_server_method(); + } else { + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_WRONG_VERSION_NUMBER); + s->version = s->client_version; + al = SSL_AD_PROTOCOL_VERSION; + goto f_err; + } + s->session->ssl_version = s->version; } } - /* - * Disabled because it can be used in a ciphersuite downgrade attack: - * CVE-2010-4180. - */ -#if 0 - if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) - && (sk_SSL_CIPHER_num(ciphers) == 1)) { - /* - * Special case as client bug workaround: the previously used - * cipher may not be in the current list, the client instead - * might be trying to continue using a cipher that before wasn't - * chosen due to server preferences. We'll have to reject the - * connection if the cipher is not enabled, though. - */ - c = sk_SSL_CIPHER_value(ciphers, 0); - if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0) { - s->session->cipher = c; - j = 1; - } + + if (p + 2 > d + n) { + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_TOO_SHORT); + goto f_err; } -#endif - if (j == 0) { - /* - * we need to have the cipher in the cipher list if we are asked - * to reuse it - */ + n2s(p, i); + + if (i == 0) { al = SSL_AD_ILLEGAL_PARAMETER; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, - SSL_R_REQUIRED_CIPHER_MISSING); + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_CIPHERS_SPECIFIED); + goto f_err; + } + + /* i bytes of cipher data + 1 byte for compression length later */ + if ((p + i + 1) > (d + n)) { + /* not enough data */ + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + goto f_err; + } + if (ssl_bytes_to_cipher_list(s, p, i, &(ciphers), 0) == NULL) { + goto err; + } + p += i; + + /* If it is a hit, check that the cipher is in the list */ + if (s->hit) { + j = 0; + id = s->session->cipher->id; + +#ifdef CIPHER_DEBUG + fprintf(stderr, "client sent %d ciphers\n", + sk_SSL_CIPHER_num(ciphers)); +#endif + for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) { + c = sk_SSL_CIPHER_value(ciphers, i); +#ifdef CIPHER_DEBUG + fprintf(stderr, "client [%2d of %2d]:%s\n", + i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c)); +#endif + if (c->id == id) { + j = 1; + break; + } + } + /* + * Disabled because it can be used in a ciphersuite downgrade + * attack: + * CVE-2010-4180. + */ +#if 0 + if (j == 0 && (s->options & SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG) + && (sk_SSL_CIPHER_num(ciphers) == 1)) { + /* + * Special case as client bug workaround: the previously used + * cipher may not be in the current list, the client instead + * might be trying to continue using a cipher that before wasn't + * chosen due to server preferences. We'll have to reject the + * connection if the cipher is not enabled, though. + */ + c = sk_SSL_CIPHER_value(ciphers, 0); + if (sk_SSL_CIPHER_find(SSL_get_ciphers(s), c) >= 0) { + s->session->cipher = c; + j = 1; + } + } +#endif + if (j == 0) { + /* + * we need to have the cipher in the cipher list if we are asked + * to reuse it + */ + al = SSL_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, + SSL_R_REQUIRED_CIPHER_MISSING); + goto f_err; + } + } + + /* compression */ + i = *(p++); + if ((p + i) > (d + n)) { + /* not enough data */ + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); + goto f_err; + } +#ifndef OPENSSL_NO_COMP + q = p; +#endif + for (j = 0; j < i; j++) { + if (p[j] == 0) + break; + } + + p += i; + if (j >= i) { + /* no compress */ + al = SSL_AD_DECODE_ERROR; + SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED); goto f_err; } } - /* compression */ - i = *(p++); - if ((p + i) > (d + n)) { - /* not enough data */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH); - goto f_err; - } -#ifndef OPENSSL_NO_COMP - q = p; -#endif - for (j = 0; j < i; j++) { - if (p[j] == 0) - break; - } - - p += i; - if (j >= i) { - /* no compress */ - al = SSL_AD_DECODE_ERROR; - SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_NO_COMPRESSION_SPECIFIED); - goto f_err; - } #ifndef OPENSSL_NO_TLSEXT /* TLS extensions */ if (s->version >= SSL3_VERSION) { diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index 38280186fa..0969368c46 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -1456,9 +1456,12 @@ int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, return (p - q); } +#define SSLV2_CIPHER_LEN 3 + STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, int num, - STACK_OF(SSL_CIPHER) **skp) + STACK_OF(SSL_CIPHER) **skp, + int sslv2format) { const SSL_CIPHER *c; STACK_OF(SSL_CIPHER) *sk; @@ -1467,7 +1470,11 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, if (s->s3) s->s3->send_connection_binding = 0; - n = ssl_put_cipher_by_char(s, NULL, NULL); + if(sslv2format) { + n = SSLV2_CIPHER_LEN; + } else { + n = ssl_put_cipher_by_char(s, NULL, NULL); + } if (n == 0 || (num % n) != 0) { SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST); @@ -1533,7 +1540,20 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, continue; } - c = ssl_get_cipher_by_char(s, p); + if(sslv2format) { + /* + * We only support SSLv2 format ciphers in SSLv3+ using a + * SSLv2 backward compatible ClientHello. In this case the first + * byte is always 0 for SSLv3 compatible ciphers. Anything else + * is an SSLv2 cipher and we ignore it + */ + if(p[0] == 0) + c = ssl_get_cipher_by_char(s, &p[1]); + else + c = NULL; + } else { + c = ssl_get_cipher_by_char(s, p); + } p += n; if (c != NULL) { if (!sk_SSL_CIPHER_push(sk, c)) { diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h index f9c4e127f4..641fe20b52 100644 --- a/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h @@ -1921,7 +1921,8 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, const SSL_CIPHER *const *bp); __owur STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, unsigned char *p, int num, - STACK_OF(SSL_CIPHER) **skp); + STACK_OF(SSL_CIPHER) **skp, + int sslv2format); __owur int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, unsigned char *p, int (*put_cb) (const SSL_CIPHER *, diff --git a/ssl/t1_meth.c b/ssl/t1_meth.c index 335d57b530..0726274ba3 100644 --- a/ssl/t1_meth.c +++ b/ssl/t1_meth.c @@ -62,6 +62,8 @@ static const SSL_METHOD *tls1_get_method(int ver) { + if (ver == TLS_ANY_VERSION) + return TLS_method(); if (ver == TLS1_2_VERSION) return TLSv1_2_method(); if (ver == TLS1_1_VERSION) @@ -71,14 +73,18 @@ static const SSL_METHOD *tls1_get_method(int ver) return NULL; } +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, TLS_method, + ssl3_accept, + ssl3_connect, tls1_get_method, TLSv1_2_enc_data) + IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_method, ssl3_accept, ssl3_connect, tls1_get_method, TLSv1_2_enc_data) - IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method, +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_method, ssl3_accept, ssl3_connect, tls1_get_method, TLSv1_1_enc_data) - IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_method, +IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_method, ssl3_accept, ssl3_connect, tls1_get_method, TLSv1_enc_data) diff --git a/ssl/t1_srvr.c b/ssl/t1_srvr.c index 8c6b3dff2f..451f384ecc 100644 --- a/ssl/t1_srvr.c +++ b/ssl/t1_srvr.c @@ -67,6 +67,8 @@ static const SSL_METHOD *tls1_get_server_method(int ver); static const SSL_METHOD *tls1_get_server_method(int ver) { + if (ver == TLS_ANY_VERSION) + return TLS_server_method(); if (ver == TLS1_2_VERSION) return TLSv1_2_server_method(); if (ver == TLS1_1_VERSION) @@ -76,17 +78,22 @@ static const SSL_METHOD *tls1_get_server_method(int ver) return NULL; } +IMPLEMENT_tls_meth_func(TLS_ANY_VERSION, TLS_server_method, + ssl3_accept, + ssl_undefined_function, + tls1_get_server_method, TLSv1_2_enc_data) + IMPLEMENT_tls_meth_func(TLS1_2_VERSION, TLSv1_2_server_method, ssl3_accept, ssl_undefined_function, tls1_get_server_method, TLSv1_2_enc_data) - IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_server_method, +IMPLEMENT_tls_meth_func(TLS1_1_VERSION, TLSv1_1_server_method, ssl3_accept, ssl_undefined_function, tls1_get_server_method, TLSv1_1_enc_data) - IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_server_method, +IMPLEMENT_tls_meth_func(TLS1_VERSION, TLSv1_server_method, ssl3_accept, ssl_undefined_function, tls1_get_server_method, TLSv1_enc_data) diff --git a/test/ssltest.c b/test/ssltest.c index 1fa2aa2c72..95ba1a0bf7 100644 --- a/test/ssltest.c +++ b/test/ssltest.c @@ -1417,7 +1417,7 @@ int main(int argc, char *argv[]) if (tls1) meth = TLSv1_method(); else - meth = SSLv23_method(); + meth = TLS_method(); c_ctx = SSL_CTX_new(meth); s_ctx = SSL_CTX_new(meth); diff --git a/util/ssleay.num b/util/ssleay.num index 7fb0714c9e..d0b41915b3 100755 --- a/util/ssleay.num +++ b/util/ssleay.num @@ -96,8 +96,8 @@ SSL_use_certificate_file 107 EXIST::FUNCTION:STDIO SSL_write 108 EXIST::FUNCTION: SSLeay_add_ssl_algorithms 109 NOEXIST::FUNCTION: SSLv23_client_method 110 EXIST::FUNCTION:RSA -SSLv23_method 111 EXIST::FUNCTION:RSA -SSLv23_server_method 112 EXIST::FUNCTION:RSA +SSLv23_method 111 NOEXIST::FUNCTION: +SSLv23_server_method 112 NOEXIST::FUNCTION: SSLv2_client_method 113 NOEXIST::FUNCTION: SSLv2_method 114 NOEXIST::FUNCTION: SSLv2_server_method 115 NOEXIST::FUNCTION: @@ -396,3 +396,5 @@ SSL_set_rbio 430 EXIST::FUNCTION: SSL_CIPHER_get_digest_nid 431 EXIST::FUNCTION: SSL_CIPHER_get_cipher_nid 432 EXIST::FUNCTION: SSL_use_certificate_chain_file 433 EXIST::FUNCTION:STDIO +TLS_server_method 434 EXIST::FUNCTION: +TLS_method 435 EXIST::FUNCTION: