X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_clnt.c;h=d0094008918116806a2237b725e5f4e3ea232b50;hp=bf1ef4776648e564b628e96e92588447e2e1377c;hb=3b77f01702cbbb75c7718f876a2053d5a882fe89;hpb=2016265dfbab162ec30718b5e7480add42598158 diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index bf1ef47766..d009400891 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -240,6 +240,13 @@ int ssl3_connect(SSL *s) ret = -1; goto end; } + + if (!ssl_security(s, SSL_SECOP_VERSION, 0, + s->version, NULL)) + { + SSLerr(SSL_F_SSL3_CONNECT, SSL_R_VERSION_TOO_LOW); + return -1; + } /* s->version=SSL3_VERSION; */ s->type=SSL_ST_CONNECT; @@ -543,6 +550,7 @@ int ssl3_connect(SSL *s) s->method->ssl3_enc->client_finished_label, s->method->ssl3_enc->client_finished_label_len); if (ret <= 0) goto end; + s->s3->flags |= SSL3_FLAGS_CCS_OK; s->state=SSL3_ST_CW_FLUSH; /* clear flags */ @@ -592,6 +600,7 @@ int ssl3_connect(SSL *s) case SSL3_ST_CR_FINISHED_A: case SSL3_ST_CR_FINISHED_B: + s->s3->flags |= SSL3_FLAGS_CCS_OK; ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B); if (ret <= 0) goto end; @@ -689,6 +698,7 @@ int ssl3_client_hello(SSL *s) unsigned char *p,*d; int i; unsigned long l; + int al = 0; #ifndef OPENSSL_NO_COMP int j; SSL_COMP *comp; @@ -870,8 +880,7 @@ int ssl3_client_hello(SSL *s) *(p++)=1; #else - if ((s->options & SSL_OP_NO_COMPRESSION) - || !s->ctx->comp_methods) + if (!ssl_allow_compression(s) || !s->ctx->comp_methods) j=0; else j=sk_SSL_COMP_num(s->ctx->comp_methods); @@ -891,8 +900,9 @@ int ssl3_client_hello(SSL *s) SSLerr(SSL_F_SSL3_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT); goto err; } - if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL) + if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH, &al)) == NULL) { + ssl3_send_alert(s,SSL3_AL_FATAL,al); SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR); goto err; } @@ -1028,6 +1038,7 @@ int ssl3_get_server_hello(SSL *s) { s->session->cipher = pref_cipher ? pref_cipher : ssl_get_cipher_by_char(s, p+j); + s->s3->flags |= SSL3_FLAGS_CCS_OK; } } #endif /* OPENSSL_NO_TLSEXT */ @@ -1043,6 +1054,7 @@ int ssl3_get_server_hello(SSL *s) SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT); goto f_err; } + s->s3->flags |= SSL3_FLAGS_CCS_OK; s->hit=1; } else /* a miss or crap from the other end */ @@ -1077,9 +1089,7 @@ int ssl3_get_server_hello(SSL *s) /* If it is a disabled cipher we didn't send it in client hello, * so return an error. */ - if (c->algorithm_ssl & ct->mask_ssl || - c->algorithm_mkey & ct->mask_k || - c->algorithm_auth & ct->mask_a) + if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK)) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_WRONG_CIPHER_RETURNED); @@ -1148,7 +1158,7 @@ int ssl3_get_server_hello(SSL *s) } if (j == 0) comp=NULL; - else if (s->options & SSL_OP_NO_COMPRESSION) + else if (!ssl_allow_compression(s)) { al=SSL_AD_ILLEGAL_PARAMETER; SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_COMPRESSION_DISABLED); @@ -1290,6 +1300,12 @@ int ssl3_get_server_certificate(SSL *s) goto f_err; } ERR_clear_error(); /* but we keep s->verify_result */ + if (i > 1) + { + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, i); + al = SSL_AD_HANDSHAKE_FAILURE; + goto f_err; + } sc=ssl_sess_cert_new(); if (sc == NULL) goto err; @@ -1656,7 +1672,7 @@ int ssl3_get_key_exchange(SSL *s) ; #endif #ifndef OPENSSL_NO_DH - else if (alg_k & SSL_kEDH) + else if (alg_k & SSL_kDHE) { if ((dh=DH_new()) == NULL) { @@ -1709,6 +1725,14 @@ int ssl3_get_key_exchange(SSL *s) p+=i; n-=param_len; + if (!ssl_security(s, SSL_SECOP_TMP_DH, + DH_security_bits(dh), 0, dh)) + { + al=SSL_AD_HANDSHAKE_FAILURE; + SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_DH_KEY_TOO_SMALL); + goto f_err; + } + #ifndef OPENSSL_NO_RSA if (alg_a & SSL_aRSA) pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509); @@ -1734,7 +1758,7 @@ int ssl3_get_key_exchange(SSL *s) #endif /* !OPENSSL_NO_DH */ #ifndef OPENSSL_NO_ECDH - else if (alg_k & SSL_kEECDH) + else if (alg_k & SSL_kECDHE) { EC_GROUP *ngroup; const EC_GROUP *group; @@ -2581,7 +2605,7 @@ int ssl3_send_client_key_exchange(SSL *s) } #endif #ifndef OPENSSL_NO_DH - else if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + else if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd)) { DH *dh_srvr,*dh_clnt; SESS_CERT *scert = s->session->sess_cert; @@ -2685,13 +2709,20 @@ int ssl3_send_client_key_exchange(SSL *s) #endif #ifndef OPENSSL_NO_ECDH - else if (alg_k & (SSL_kEECDH|SSL_kECDHr|SSL_kECDHe)) + else if (alg_k & (SSL_kECDHE|SSL_kECDHr|SSL_kECDHe)) { const EC_GROUP *srvr_group = NULL; EC_KEY *tkey; int ecdh_clnt_cert = 0; int field_size = 0; + if (s->session->sess_cert == NULL) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_UNEXPECTED_MESSAGE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,SSL_R_UNEXPECTED_MESSAGE); + goto err; + } + /* Did we send out the client's * ECDH share for use in premaster * computation as part of client certificate? @@ -3307,11 +3338,20 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_A) { /* Let cert callback update client certificates if required */ - if (s->cert->cert_cb - && s->cert->cert_cb(s, s->cert->cert_cb_arg) <= 0) + if (s->cert->cert_cb) { - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); - return 0; + i = s->cert->cert_cb(s, s->cert->cert_cb_arg); + if (i < 0) + { + s->rwstate=SSL_X509_LOOKUP; + return -1; + } + if (i == 0) + { + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } + s->rwstate=SSL_NOTHING; } if (ssl3_check_client_certificate(s)) s->state=SSL3_ST_CW_CERT_C; @@ -3371,8 +3411,13 @@ int ssl3_send_client_certificate(SSL *s) if (s->state == SSL3_ST_CW_CERT_C) { s->state=SSL3_ST_CW_CERT_D; - ssl3_output_cert_chain(s, - (s->s3->tmp.cert_req == 2)?NULL:s->cert->key); + if (!ssl3_output_cert_chain(s, + (s->s3->tmp.cert_req == 2)?NULL:s->cert->key)) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR); + ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_INTERNAL_ERROR); + return 0; + } } /* SSL3_ST_CW_CERT_D */ return ssl_do_write(s); @@ -3469,7 +3514,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) } #endif #ifndef OPENSSL_NO_DH - if ((alg_k & SSL_kEDH) && + if ((alg_k & SSL_kDHE) && !(has_bits(i,EVP_PK_DH|EVP_PKT_EXCH) || (dh != NULL))) { SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_DH_KEY); @@ -3506,7 +3551,7 @@ int ssl3_check_cert_and_algorithm(SSL *s) else #endif #ifndef OPENSSL_NO_DH - if (alg_k & (SSL_kEDH|SSL_kDHr|SSL_kDHd)) + if (alg_k & (SSL_kDHE|SSL_kDHr|SSL_kDHd)) { if (dh == NULL || DH_size(dh)*8 > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher)) @@ -3613,6 +3658,7 @@ int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey) #ifndef OPENSSL_NO_TLSEXT int tls1_send_client_supplemental_data(SSL *s, int *skip) { + int al = 0; if (s->ctx->cli_supp_data_records_count) { unsigned char *p = NULL; @@ -3632,20 +3678,20 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip) if (!record->fn2) continue; cb_retval = record->fn2(s, record->supp_data_type, - &out, &outlen, - record->arg); + &out, &outlen, &al, + record->arg); if (cb_retval == -1) continue; /* skip this supp data entry */ if (cb_retval == 0) { SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); - return 0; + goto f_err; } if (outlen == 0 || TLSEXT_MAXLEN_supplemental_data < outlen + 4 + length) { SSLerr(SSL_F_TLS1_SEND_CLIENT_SUPPLEMENTAL_DATA,ERR_R_BUF_LIB); return 0; - } + } /* if first entry, write handshake message type */ if (length == 0) { @@ -3694,6 +3740,10 @@ int tls1_send_client_supplemental_data(SSL *s, int *skip) s->init_num = 0; s->init_off = 0; return 1; + + f_err: + ssl3_send_alert(s,SSL3_AL_FATAL,al); + return 0; } int tls1_get_server_supplemental_data(SSL *s) @@ -3703,18 +3753,18 @@ int tls1_get_server_supplemental_data(SSL *s) long n; const unsigned char *p, *d; unsigned short supp_data_entry_type = 0; - unsigned long supp_data_entry_len = 0; + unsigned short supp_data_entry_len = 0; unsigned long supp_data_len = 0; size_t i; int cb_retval = 0; n=s->method->ssl_get_message(s, - SSL3_ST_CR_SUPPLEMENTAL_DATA_A, - SSL3_ST_CR_SUPPLEMENTAL_DATA_B, - SSL3_MT_SUPPLEMENTAL_DATA, - /* use default limit */ - TLSEXT_MAXLEN_supplemental_data, - &ok); + SSL3_ST_CR_SUPPLEMENTAL_DATA_A, + SSL3_ST_CR_SUPPLEMENTAL_DATA_B, + SSL3_MT_SUPPLEMENTAL_DATA, + /* use default limit */ + TLSEXT_MAXLEN_supplemental_data, + &ok); if (!ok) return((int)n); @@ -3735,9 +3785,12 @@ int tls1_get_server_supplemental_data(SSL *s) /* if there is a callback for this supp data type, send it */ for (i=0; i < s->ctx->cli_supp_data_records_count; i++) { - if (s->ctx->cli_supp_data_records[i].supp_data_type == supp_data_entry_type && s->ctx->cli_supp_data_records[i].fn1) + if (s->ctx->cli_supp_data_records[i].supp_data_type == supp_data_entry_type && + s->ctx->cli_supp_data_records[i].fn1) { - cb_retval = s->ctx->cli_supp_data_records[i].fn1(s, supp_data_entry_type, p, supp_data_entry_len, &al, s->ctx->cli_supp_data_records[i].arg); + cb_retval = s->ctx->cli_supp_data_records[i].fn1(s, supp_data_entry_type, p, + supp_data_entry_len, &al, + s->ctx->cli_supp_data_records[i].arg); if (cb_retval == 0) { SSLerr(SSL_F_TLS1_GET_SERVER_SUPPLEMENTAL_DATA, ERR_R_SSL_LIB);