X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=49751a00487eaa72e0a4de2bf055016148f68e6f;hp=92f73b668102828da9d3dfea2f977a4f7159c494;hb=e827b58711ce508f5445a8460f857c71c8ffedcd;hpb=c1ca9d3238ad8aeaaf595c30572f573533693305 diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 92f73b6681..49751a0048 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -218,7 +218,7 @@ int ssl3_accept(SSL *s) switch (s->state) { case SSL_ST_RENEGOTIATE: - s->new_session=1; + s->renegotiate=1; /* s->state=SSL_ST_ACCEPT; */ case SSL_ST_BEFORE: @@ -316,7 +316,7 @@ int ssl3_accept(SSL *s) ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; - s->new_session = 2; + s->renegotiate = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; break; @@ -538,7 +538,14 @@ int ssl3_accept(SSL *s) * the client uses its key from the certificate * for key exchange. */ +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->state=SSL3_ST_SR_FINISHED_A; +#else + if (s->s3->next_proto_neg_seen) + s->state=SSL3_ST_SR_NEXT_PROTO_A; + else + s->state=SSL3_ST_SR_FINISHED_A; +#endif s->init_num = 0; } else @@ -581,10 +588,27 @@ int ssl3_accept(SSL *s) ret=ssl3_get_cert_verify(s); if (ret <= 0) goto end; +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->state=SSL3_ST_SR_FINISHED_A; +#else + if (s->s3->next_proto_neg_seen) + s->state=SSL3_ST_SR_NEXT_PROTO_A; + else + s->state=SSL3_ST_SR_FINISHED_A; +#endif s->init_num=0; break; +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG) + case SSL3_ST_SR_NEXT_PROTO_A: + case SSL3_ST_SR_NEXT_PROTO_B: + ret=ssl3_get_next_proto(s); + if (ret <= 0) goto end; + s->init_num = 0; + s->state=SSL3_ST_SR_FINISHED_A; + break; +#endif + case SSL3_ST_SR_FINISHED_A: case SSL3_ST_SR_FINISHED_B: ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A, @@ -655,7 +679,16 @@ int ssl3_accept(SSL *s) if (ret <= 0) goto end; s->state=SSL3_ST_SW_FLUSH; if (s->hit) + { +#if defined(OPENSSL_NO_TLSEXT) || defined(OPENSSL_NO_NEXTPROTONEG) s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; +#else + if (s->s3->next_proto_neg_seen) + s->s3->tmp.next_state=SSL3_ST_SR_NEXT_PROTO_A; + else + s->s3->tmp.next_state=SSL3_ST_SR_FINISHED_A; +#endif + } else s->s3->tmp.next_state=SSL_ST_OK; s->init_num=0; @@ -673,11 +706,12 @@ int ssl3_accept(SSL *s) s->init_num=0; - if (s->new_session == 2) /* skipped if we just sent a HelloRequest */ + if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */ { /* actually not necessarily a 'new' session unless * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */ + s->renegotiate=0; s->new_session=0; ssl_update_cache(s,SSL_SESS_CACHE_SERVER); @@ -1217,6 +1251,13 @@ int ssl3_get_client_hello(SSL *s) goto f_err; } s->s3->tmp.new_cipher=c; + /* check whether we should disable session resumption */ + if (s->not_resumable_session_cb != NULL) + s->session->not_resumable=s->not_resumable_session_cb(s, + ((c->algorithm_mkey & (SSL_kEDH | SSL_kEECDH)) != 0)); + if (s->session->not_resumable) + /* do not send a session ticket */ + s->tlsext_ticket_expected = 0; } else { @@ -1320,8 +1361,9 @@ int ssl3_send_server_hello(SSL *s) * if session caching is disabled so existing functionality * is unaffected. */ - if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) - && !s->hit) + if (s->session->not_resumable || + (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER) + && !s->hit)) s->session->session_id_length=0; sl=s->session->session_id_length; @@ -2579,12 +2621,19 @@ int ssl3_get_client_key_exchange(SSL *s) { int ret = 0; EVP_PKEY_CTX *pkey_ctx; - EVP_PKEY *client_pub_pkey = NULL; + EVP_PKEY *client_pub_pkey = NULL, *pk = NULL; unsigned char premaster_secret[32], *start; - size_t outlen=32, inlen; + size_t outlen=32, inlen; + unsigned long alg_a; /* Get our certificate private key*/ - pkey_ctx = EVP_PKEY_CTX_new(s->cert->key->privatekey,NULL); + alg_a = s->s3->tmp.new_cipher->algorithm_auth; + if (alg_a & SSL_aGOST94) + pk = s->cert->pkeys[SSL_PKEY_GOST94].privatekey; + else if (alg_a & SSL_aGOST01) + pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey; + + pkey_ctx = EVP_PKEY_CTX_new(pk,NULL); EVP_PKEY_decrypt_init(pkey_ctx); /* If client certificate is present and is of the same type, maybe * use it for key exchange. Don't mind errors from @@ -3177,4 +3226,72 @@ int ssl3_send_cert_status(SSL *s) /* SSL3_ST_SW_CERT_STATUS_B */ return(ssl3_do_write(s,SSL3_RT_HANDSHAKE)); } + +# ifndef OPENSSL_NO_NPN +/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It + * sets the next_proto member in s if found */ +int ssl3_get_next_proto(SSL *s) + { + int ok; + int proto_len, padding_len; + long n; + const unsigned char *p; + + /* Clients cannot send a NextProtocol message if we didn't see the + * extension in their ClientHello */ + if (!s->s3->next_proto_neg_seen) + { + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION); + return -1; + } + + n=s->method->ssl_get_message(s, + SSL3_ST_SR_NEXT_PROTO_A, + SSL3_ST_SR_NEXT_PROTO_B, + SSL3_MT_NEXT_PROTO, + 514, /* See the payload format below */ + &ok); + + if (!ok) + return((int)n); + + /* s->state doesn't reflect whether ChangeCipherSpec has been received + * in this handshake, but s->s3->change_cipher_spec does (will be reset + * by ssl3_get_finished). */ + if (!s->s3->change_cipher_spec) + { + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,SSL_R_GOT_NEXT_PROTO_BEFORE_A_CCS); + return -1; + } + + if (n < 2) + return 0; /* The body must be > 1 bytes long */ + + p=(unsigned char *)s->init_msg; + + /* The payload looks like: + * uint8 proto_len; + * uint8 proto[proto_len]; + * uint8 padding_len; + * uint8 padding[padding_len]; + */ + proto_len = p[0]; + if (proto_len + 2 > s->init_num) + return 0; + padding_len = p[proto_len + 1]; + if (proto_len + padding_len + 2 != s->init_num) + return 0; + + s->next_proto_negotiated = OPENSSL_malloc(proto_len); + if (!s->next_proto_negotiated) + { + SSLerr(SSL_F_SSL3_GET_NEXT_PROTO,ERR_R_MALLOC_FAILURE); + return 0; + } + memcpy(s->next_proto_negotiated, p + 1, proto_len); + s->next_proto_negotiated_len = proto_len; + + return 1; + } +# endif #endif