Avoid a race condition.
[openssl.git] / ssl / s2_clnt.c
index b0a656740ce79c8661b4417a2f5df0ba3f020fb4..e4e9660cb4b1f66ad956ac7e86f93bfd27682348 100644 (file)
  * [including the GNU Public Licence.]
  */
 
-#ifndef NO_RSA
+#include "ssl_locl.h"
+#ifndef NO_SSL2
 #include <stdio.h>
 #include <openssl/rand.h>
 #include <openssl/buffer.h>
 #include <openssl/objects.h>
-#include "ssl_locl.h"
 #include <openssl/evp.h>
 
 static SSL_METHOD *ssl2_get_client_method(int ver);
@@ -108,7 +108,7 @@ int ssl2_connect(SSL *s)
        void (*cb)()=NULL;
        int new_state,state;
 
-       RAND_seed(&l,sizeof(l));
+       RAND_add(&l,sizeof(l),0);
        ERR_clear_error();
        clear_sys_error();
 
@@ -435,26 +435,28 @@ static int get_server_hello(SSL *s)
                        return(-1);
                        }
                s->session->cipher=sk_SSL_CIPHER_value(cl,i);
-               }
 
-       if (s->session->peer != NULL)
-               X509_free(s->session->peer);
-
-#if 0 /* What is all this meant to accomplish?? */
-       /* hmmm, can we have the problem of the other session with this
-        * cert, Free's it before we increment the reference count. */
-       CRYPTO_w_lock(CRYPTO_LOCK_X509);
-       s->session->peer=s->session->sess_cert->key->x509;
-       /* Shouldn't do this: already locked */
-       /*CRYPTO_add(&s->session->peer->references,1,CRYPTO_LOCK_X509);*/
-       s->session->peer->references++;
-       CRYPTO_w_unlock(CRYPTO_LOCK_X509);
-#else
-       s->session->peer = s->session->sess_cert->peer_key->x509;
-       /* peer_key->x509 has been set by ssl2_set_certificate. */
-       CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
-#endif
 
+               if (s->session->peer != NULL) /* can't happen*/
+                       {
+                       ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+                       SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_INTERNAL_ERROR);
+                       return(-1);
+                       }
+
+               s->session->peer = s->session->sess_cert->peer_key->x509;
+               /* peer_key->x509 has been set by ssl2_set_certificate. */
+               CRYPTO_add(&s->session->peer->references, 1, CRYPTO_LOCK_X509);
+               }
+
+       if (s->session->peer != s->session->sess_cert->peer_key->x509)
+               /* can't happen */
+               {
+               ssl2_return_error(s, SSL2_PE_UNDEFINED_ERROR);
+               SSLerr(SSL_F_GET_SERVER_HELLO, SSL_R_INTERNAL_ERROR);
+               return(-1);
+               }
+               
        s->s2->conn_id_length=s->s2->tmp.conn_id_length;
        memcpy(s->s2->conn_id,p,s->s2->tmp.conn_id_length);
        return(1);
@@ -515,7 +517,7 @@ static int client_hello(SSL *s)
                s->s2->challenge_length=SSL2_CHALLENGE_LENGTH;
                s2n(SSL2_CHALLENGE_LENGTH,p);           /* challenge length */
                /*challenge id data*/
-               RAND_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH);
+               RAND_pseudo_bytes(s->s2->challenge,SSL2_CHALLENGE_LENGTH);
                memcpy(d,s->s2->challenge,SSL2_CHALLENGE_LENGTH);
                d+=SSL2_CHALLENGE_LENGTH;
 
@@ -557,12 +559,19 @@ static int client_master_key(SSL *s)
                /* make key_arg data */
                i=EVP_CIPHER_iv_length(c);
                sess->key_arg_length=i;
-               if (i > 0) RAND_bytes(sess->key_arg,i);
+               if (i > 0) RAND_pseudo_bytes(sess->key_arg,i);
 
                /* make a master key */
                i=EVP_CIPHER_key_length(c);
                sess->master_key_length=i;
-               if (i > 0) RAND_bytes(sess->master_key,i);
+               if (i > 0)
+                       {
+                       if (RAND_bytes(sess->master_key,i) <= 0)
+                               {
+                               ssl2_return_error(s,SSL2_PE_UNDEFINED_ERROR);
+                               return(-1);
+                               }
+                       }
 
                if (sess->cipher->algorithm2 & SSL2_CF_8_BYTE_ENC)
                        enc=8;
@@ -974,7 +983,7 @@ end:
        EVP_PKEY_free(pkey);
        return(i);
        }
-#else /* !NO_RSA */
+#else /* !NO_SSL2 */
 
 # if PEDANTIC
 static void *dummy=&dummy;