delete unimplemented function from header file, update ordinals
[oweals/openssl.git] / ssl / s3_srvr.c
index af9ed3ff5fb28b6e0ebb82e9842c063bca575d94..bae14c17e59ceb8921f12922e006dcad3c8bc777 100644 (file)
@@ -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