Updates to the new SSL compression code
[openssl.git] / ssl / s3_srvr.c
index a827a58d4932666d0c70f9be874b49f53a6c505f..a4c0744488405d4ffbb97cf774a2d39e770bb463 100644 (file)
@@ -135,7 +135,6 @@ SSL *s;
        long num1;
        int ret= -1;
        CERT *ct;
-       BIO *under;
        int new_state,state,skip=0;
 
        RAND_seed(&Time,sizeof(Time));
@@ -178,6 +177,7 @@ SSL *s;
                case SSL_ST_BEFORE|SSL_ST_ACCEPT:
                case SSL_ST_OK|SSL_ST_ACCEPT:
 
+                       s->server=1;
                        if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
                        if ((s->version>>8) != 3)
@@ -217,11 +217,11 @@ SSL *s;
                                {
                                s->state=SSL3_ST_SR_CLNT_HELLO_A;
                                ssl3_init_finished_mac(s);
-                               s->ctx->sess_accept++;
+                               s->ctx->stats.sess_accept++;
                                }
                        else
                                {
-                               s->ctx->sess_accept_renegotiate++;
+                               s->ctx->stats.sess_accept_renegotiate++;
                                s->state=SSL3_ST_SW_HELLO_REQ_A;
                                }
                        break;
@@ -240,15 +240,6 @@ SSL *s;
                        break;
 
                case SSL3_ST_SW_HELLO_REQ_C:
-                       /* remove buffering on output */
-                       under=BIO_pop(s->wbio);
-                       if (under != NULL)
-                               s->wbio=under;
-                       else
-                               abort(); /* ok */
-                       BIO_free(s->bbio);
-                       s->bbio=NULL;
-
                        s->state=SSL_ST_OK;
                        ret=1;
                        goto end;
@@ -480,20 +471,14 @@ SSL *s;
                        s->init_buf=NULL;
 
                        /* remove buffering on output */
-                       under=BIO_pop(s->wbio);
-                       if (under != NULL)
-                               s->wbio=under;
-                       else
-                               abort(); /* ok */
-                       BIO_free(s->bbio);
-                       s->bbio=NULL;
+                       ssl_free_wbio_buffer(s);
 
                        s->new_session=0;
                        s->init_num=0;
 
                        ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
 
-                       s->ctx->sess_accept_good++;
+                       s->ctx->stats.sess_accept_good++;
                        /* s->server=1; */
                        s->handshake_func=ssl3_accept;
                        ret=1;
@@ -567,8 +552,9 @@ SSL *s;
        int i,j,ok,al,ret= -1;
        long n;
        unsigned long id;
-       unsigned char *p,*d;
+       unsigned char *p,*d,*q;
        SSL_CIPHER *c;
+       SSL_COMP *comp=NULL;
        STACK *ciphers=NULL;
 
        /* We do this so that we will respond with our native type.
@@ -595,6 +581,7 @@ SSL *s;
        /* The version number has already been checked in ssl3_get_message.
         * I a native TLSv1/SSLv3 method, the match must be correct except
         * perhaps for the first message */
+/*     s->client_version=(((int)p[0])<<8)|(int)p[1]; */
        p+=2;
 
        /* load the client random */
@@ -653,9 +640,16 @@ SSL *s;
                j=0;
                id=s->session->cipher->id;
 
+#ifdef CIPHER_DEBUG
+               printf("client sent %d ciphers\n",sk_num(ciphers));
+#endif
                for (i=0; i<sk_num(ciphers); i++)
                        {
                        c=(SSL_CIPHER *)sk_value(ciphers,i);
+#ifdef CIPHER_DEBUG
+                       printf("client [%2d of %2d]:%s\n",
+                               i,sk_num(ciphers),SSL_CIPHER_get_name(c));
+#endif
                        if (c->id == id)
                                {
                                j=1;
@@ -683,8 +677,11 @@ SSL *s;
 
        /* compression */
        i= *(p++);
+       q=p;
        for (j=0; j<i; j++)
+               {
                if (p[j] == 0) break;
+               }
 
        p+=i;
        if (j >= i)
@@ -695,6 +692,35 @@ SSL *s;
                goto f_err;
                }
 
+       /* Worst case, we will use the NULL compression, but if we have other
+        * options, we will now look for them.  We have i-1 compression
+        * algorithms from the client, starting at q. */
+       s->s3->tmp.new_compression=NULL;
+       if (s->ctx->comp_methods != NULL)
+               { /* See if we have a match */
+               int m,nn,o,v,done=0;
+
+               nn=sk_num(s->ctx->comp_methods);
+               for (m=0; m<nn; m++)
+                       {
+                       comp=(SSL_COMP *)sk_value(s->ctx->comp_methods,m);
+                       v=comp->id;
+                       for (o=0; o<i; o++)
+                               {
+                               if (v == q[o])
+                                       {
+                                       done=1;
+                                       break;
+                                       }
+                               }
+                       if (done) break;
+                       }
+               if (done)
+                       s->s3->tmp.new_compression=comp;
+               else
+                       comp=NULL;
+               }
+
        /* TLS does not mind if there is extra stuff */
        if (s->version == SSL3_VERSION)
                {
@@ -708,13 +734,12 @@ SSL *s;
                        }
                }
 
-       /* do nothing with compression */
-
        /* Given s->session->ciphers and ssl_get_ciphers_by_id(s), we must
         * pick a cipher */
 
        if (!s->hit)
                {
+               s->session->compress_meth=(comp == NULL)?0:comp->id;
                if (s->session->ciphers != NULL)
                        sk_free(s->session->ciphers);
                s->session->ciphers=ciphers;
@@ -835,7 +860,10 @@ SSL *s;
                p+=i;
 
                /* put the compression method */
-               *(p++)=0;
+               if (s->s3->tmp.new_compression == NULL)
+                       *(p++)=0;
+               else
+                       *(p++)=s->s3->tmp.new_compression->id;
 
                /* do the header */
                l=(p-d);
@@ -1266,13 +1294,26 @@ SSL *s;
 #if 1
                /* If a bad decrypt, use a random master key */
                if ((i != SSL_MAX_MASTER_KEY_LENGTH) ||
-                       ((p[0] != (s->version>>8)) ||
-                        (p[1] != (s->version & 0xff))))
+                       ((p[0] != (s->client_version>>8)) ||
+                        (p[1] != (s->client_version & 0xff))))
                        {
-                       p[0]=(s->version>>8);
-                       p[1]=(s->version & 0xff);
-                       RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2);
-                       i=SSL_MAX_MASTER_KEY_LENGTH;
+                       int bad=1;
+
+                       if ((i == SSL_MAX_MASTER_KEY_LENGTH) &&
+                               (p[0] == (s->version>>8)) &&
+                               (p[1] == 0))
+                               {
+                               if (s->options & SSL_OP_TLS_ROLLBACK_BUG)
+                                       bad=0;
+                               }
+                       if (bad)
+                               {
+                               p[0]=(s->version>>8);
+                               p[1]=(s->version & 0xff);
+                               RAND_bytes(&(p[2]),SSL_MAX_MASTER_KEY_LENGTH-2);
+                               i=SSL_MAX_MASTER_KEY_LENGTH;
+                               }
+                       /* else, an SSLeay bug, ssl only server, tls client */
                        }
 #else
                if (i != SSL_MAX_MASTER_KEY_LENGTH)