Fix SSL handshake functions and SSL_clear() such that SSL_clear()
[openssl.git] / ssl / s2_srvr.c
index 332e28445118091f2e7d9995ff308382d02f32cd..f849e2b32a5b68f0d0b00e6526676a873793e6fb 100644 (file)
@@ -57,7 +57,7 @@
  */
 
 #include "ssl_locl.h"
-#ifndef NO_SSL2
+#ifndef OPENSSL_NO_SSL2
 #include <stdio.h>
 #include <openssl/bio.h>
 #include <openssl/rand.h>
@@ -119,8 +119,8 @@ int ssl2_accept(SSL *s)
                cb=s->ctx->info_callback;
 
        /* init things to blank */
-       if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
        s->in_handshake++;
+       if (!SSL_in_init(s) || SSL_in_before(s)) SSL_clear(s);
 
        if (s->cert == NULL)
                {
@@ -405,12 +405,13 @@ static int get_client_master_key(SSL *s)
        /* bad decrypt */
 #if 1
        /* If a bad decrypt, continue with protocol but with a
-        * dud master secret */
+        * random master secret (Bleichenbacher attack) */
        if ((i < 0) ||
                ((!is_export && (i != EVP_CIPHER_key_length(c)))
                || (is_export && ((i != ek) || (s->s2->tmp.clear+i !=
                        EVP_CIPHER_key_length(c))))))
                {
+               ERR_clear_error();
                if (is_export)
                        i=ek;
                else
@@ -450,6 +451,7 @@ static int get_client_hello(SSL *s)
        unsigned char *p;
        STACK_OF(SSL_CIPHER) *cs; /* a stack of SSL_CIPHERS */
        STACK_OF(SSL_CIPHER) *cl; /* the ones we want to use */
+       STACK_OF(SSL_CIPHER) *prio, *allow;
        int z;
 
        /* This is a bit of a hack to check for the correct packet
@@ -555,21 +557,37 @@ static int get_client_hello(SSL *s)
                        &s->session->ciphers);
                if (cs == NULL) goto mem_err;
 
-               cl=ssl_get_ciphers_by_id(s);
+               cl=SSL_get_ciphers(s);
 
-               for (z=0; z<sk_SSL_CIPHER_num(cs); z++)
+               if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+                   {
+                   prio=sk_SSL_CIPHER_dup(cl);
+                   if (prio == NULL) goto mem_err;
+                   allow = cs;
+                   }
+               else
+                   {
+                   prio = cs;
+                   allow = cl;
+                   }
+               for (z=0; z<sk_SSL_CIPHER_num(prio); z++)
                        {
-                       if (sk_SSL_CIPHER_find(cl,sk_SSL_CIPHER_value(cs,z)) < 0)
+                       if (sk_SSL_CIPHER_find(allow,sk_SSL_CIPHER_value(prio,z)) < 0)
                                {
-                               sk_SSL_CIPHER_delete(cs,z);
+                               sk_SSL_CIPHER_delete(prio,z);
                                z--;
                                }
                        }
-
+               if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE)
+                   {
+                   sk_SSL_CIPHER_free(s->session->ciphers);
+                   s->session->ciphers = prio;
+                   }
                /* s->session->ciphers should now have a list of
                 * ciphers that are on both the client and server.
                 * This list is ordered by the order the client sent
-                * the ciphers.
+                * the ciphers or in the order of the server's preference
+                * if SSL_OP_CIPHER_SERVER_PREFERENCE was set.
                 */
                }
        p+=s->s2->tmp.cipher_spec_length;
@@ -892,13 +910,14 @@ static int request_certificate(SSL *s)
                EVP_MD_CTX ctx;
                EVP_PKEY *pkey=NULL;
 
-               EVP_VerifyInit(&ctx,s->ctx->rsa_md5);
+               EVP_MD_CTX_init(&ctx);
+               EVP_VerifyInit_ex(&ctx,s->ctx->rsa_md5, NULL);
                EVP_VerifyUpdate(&ctx,s->s2->key_material,
                        (unsigned int)s->s2->key_material_length);
                EVP_VerifyUpdate(&ctx,ccd,SSL2_MIN_CERT_CHALLENGE_LENGTH);
 
                i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,NULL);
-               buf2=Malloc((unsigned int)i);
+               buf2=OPENSSL_malloc((unsigned int)i);
                if (buf2 == NULL)
                        {
                        SSLerr(SSL_F_REQUEST_CERTIFICATE,ERR_R_MALLOC_FAILURE);
@@ -907,13 +926,13 @@ static int request_certificate(SSL *s)
                p2=buf2;
                i=i2d_X509(s->cert->pkeys[SSL_PKEY_RSA_ENC].x509,&p2);
                EVP_VerifyUpdate(&ctx,buf2,(unsigned int)i);
-               Free(buf2);
+               OPENSSL_free(buf2);
 
                pkey=X509_get_pubkey(x509);
                if (pkey == NULL) goto end;
                i=EVP_VerifyFinal(&ctx,p,s->s2->tmp.rlen,pkey);
                EVP_PKEY_free(pkey);
-               memset(&ctx,0,sizeof(ctx));
+               EVP_MD_CTX_cleanup(&ctx);
 
                if (i) 
                        {
@@ -966,7 +985,7 @@ static int ssl_rsa_private_decrypt(CERT *c, int len, unsigned char *from,
                SSLerr(SSL_F_SSL_RSA_PRIVATE_DECRYPT,ERR_R_RSA_LIB);
        return(i);
        }
-#else /* !NO_SSL2 */
+#else /* !OPENSSL_NO_SSL2 */
 
 # if PEDANTIC
 static void *dummy=&dummy;