Change DH_up() -> DH_up_ref()
[openssl.git] / ssl / s2_srvr.c
index 1ed02540aec4d7bdc6521c501801370fbf6a8bd3..3bd83793b71ed00031e24018e7d35b6cecd7627a 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>
@@ -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,6 +910,7 @@ static int request_certificate(SSL *s)
                EVP_MD_CTX ctx;
                EVP_PKEY *pkey=NULL;
 
+               EVP_MD_CTX_init(&ctx);
                EVP_VerifyInit(&ctx,s->ctx->rsa_md5);
                EVP_VerifyUpdate(&ctx,s->s2->key_material,
                        (unsigned int)s->s2->key_material_length);
@@ -913,7 +932,7 @@ static int request_certificate(SSL *s)
                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;