X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Fs3_srvr.c;h=bae14c17e59ceb8921f12922e006dcad3c8bc777;hb=2d4c9ab51898c3773a9f4138b3c3d47a5016c464;hp=af9ed3ff5fb28b6e0ebb82e9842c063bca575d94;hpb=3c3f0259238594d77264a78944d409f2127642c4;p=oweals%2Fopenssl.git diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index af9ed3ff5f..bae14c17e5 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -180,11 +180,11 @@ static const SSL_METHOD *ssl3_get_server_method(int ver) } #ifndef OPENSSL_NO_SRP -static int SSL_check_srp_ext_ClientHello(SSL *s, int *ad) +static int ssl_check_srp_ext_ClientHello(SSL *s, int *al) { int ret = SSL_ERROR_NONE; - *ad = SSL_AD_UNRECOGNIZED_NAME; + *al = SSL_AD_UNRECOGNIZED_NAME; if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) && (s->srp_ctx.TLS_ext_srp_username_callback != NULL)) @@ -192,12 +192,12 @@ static int SSL_check_srp_ext_ClientHello(SSL *s, int *ad) if(s->srp_ctx.login == NULL) { /* There isn't any srp login extension !!! */ - ret = SSL3_AL_WARNING; - *ad = SSL_AD_MISSING_SRP_USERNAME; + ret = SSL3_AL_FATAL; + *al = SSL_AD_UNKNOWN_PSK_IDENTITY; } else { - ret = SSL_srp_server_param_with_username(s,ad); + ret = SSL_srp_server_param_with_username(s,al); } } return ret; @@ -216,10 +216,6 @@ int ssl3_accept(SSL *s) void (*cb)(const SSL *ssl,int type,int val)=NULL; int ret= -1; int new_state,state,skip=0; -#ifndef OPENSSL_NO_SRP - int srp_no_username=0; - int extension_error,al; -#endif RAND_add(&Time,sizeof(Time),0); ERR_clear_error(); @@ -340,35 +336,24 @@ int ssl3_accept(SSL *s) case SSL3_ST_SR_CLNT_HELLO_A: case SSL3_ST_SR_CLNT_HELLO_B: case SSL3_ST_SR_CLNT_HELLO_C: -#ifndef OPENSSL_NO_SRP - case SSL3_ST_SR_CLNT_HELLO_SRP_USERNAME: -#endif s->shutdown=0; + ret=ssl3_get_client_hello(s); if (ret <= 0) goto end; #ifndef OPENSSL_NO_SRP - extension_error = 0; - if ((al = SSL_check_srp_ext_ClientHello(s,&extension_error)) != SSL_ERROR_NONE) + { + int al; + if ((ret = ssl_check_srp_ext_ClientHello(s,&al)) != SSL_ERROR_NONE) { - ssl3_send_alert(s,al,extension_error); - if (extension_error == SSL_AD_MISSING_SRP_USERNAME) - { - if (srp_no_username) goto end; - ERR_clear_error(); - srp_no_username = 1; - s->state=SSL3_ST_SR_CLNT_HELLO_SRP_USERNAME; - if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1); - if ((ret=BIO_flush(s->wbio)) <= 0) goto end; - s->init_num=0; - break; - } - ret = -1; - SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT); - goto end; + ssl3_send_alert(s,SSL3_AL_FATAL,al); + SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLSEXT); + ret = SSL_TLSEXT_ERR_ALERT_FATAL; + ret= -1; + goto end; } -#endif - + } +#endif s->renegotiate = 2; s->state=SSL3_ST_SW_SRVR_HELLO_A; s->init_num=0; @@ -598,7 +583,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 if (TLS1_get_version(s) >= TLS1_2_VERSION) @@ -659,10 +651,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, @@ -730,7 +739,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; @@ -881,9 +899,6 @@ int ssl3_get_client_hello(SSL *s) * TLSv1. */ if (s->state == SSL3_ST_SR_CLNT_HELLO_A -#ifndef OPENSSL_NO_SRP - || (s->state == SSL3_ST_SR_CLNT_HELLO_SRP_USERNAME) -#endif ) { s->state=SSL3_ST_SR_CLNT_HELLO_B; @@ -3467,4 +3482,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_NEXTPROTONEG +/* 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