Store verify_result with sessions to avoid potential security hole.
[openssl.git] / ssl / s3_clnt.c
index 9d85ba4fd9cd0a7a0f61b8f73f4667af840e90c7..eec45cfa485d0d0a7ae6a4f06a3f3abf430d15b4 100644 (file)
@@ -69,7 +69,7 @@ static SSL_METHOD *ssl3_get_client_method(int ver);
 static int ssl3_client_hello(SSL *s);
 static int ssl3_get_server_hello(SSL *s);
 static int ssl3_get_certificate_request(SSL *s);
-static int ca_dn_cmp(X509_NAME **a,X509_NAME **b);
+static int ca_dn_cmp(const X509_NAME * const *a,const X509_NAME * const *b);
 static int ssl3_get_server_done(SSL *s);
 static int ssl3_send_client_verify(SSL *s);
 static int ssl3_send_client_certificate(SSL *s);
@@ -142,7 +142,12 @@ int ssl3_connect(SSL *s)
                        if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_START,1);
 
                        if ((s->version & 0xff00 ) != 0x0300)
-                               abort();
+                               {
+                               SSLerr(SSL_F_SSL3_CONNECT, SSL_R_INTERNAL_ERROR);
+                               ret = -1;
+                               goto end;
+                               }
+                               
                        /* s->version=SSL3_VERSION; */
                        s->type=SSL_ST_CONNECT;
 
@@ -466,7 +471,7 @@ static int ssl3_client_hello(SSL *s)
                p=s->s3->client_random;
                Time=time(NULL);                        /* Time */
                l2n(Time,p);
-               RAND_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+               RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
 
                /* Do the message type and length last */
                d=p= &(buf[4]);
@@ -764,6 +769,7 @@ static int ssl3_get_server_certificate(SSL *s)
                SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_CERTIFICATE_VERIFY_FAILED);
                goto f_err; 
                }
+       ERR_clear_error(); /* but we keep s->verify_result */
 
        sc=ssl_sess_cert_new();
        if (sc == NULL) goto err;
@@ -772,6 +778,8 @@ static int ssl3_get_server_certificate(SSL *s)
        s->session->sess_cert=sc;
 
        sc->cert_chain=sk;
+       /* Inconsistency alert: cert_chain does include the peer's
+        * certificate, which we don't include in s3_srvr.c */
        x=sk_X509_value(sk,0);
        sk=NULL;
 
@@ -807,6 +815,7 @@ static int ssl3_get_server_certificate(SSL *s)
                X509_free(s->session->peer);
        CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
        s->session->peer=x;
+       s->session->verify_result = s->verify_result;
 
        x=NULL;
        ret=1;
@@ -932,10 +941,12 @@ static int ssl3_get_key_exchange(SSL *s)
                s->session->sess_cert->peer_rsa_tmp=rsa;
                rsa=NULL;
                }
-       else
+#else /* NO_RSA */
+       if (0)
+               ;
 #endif
 #ifndef NO_DH
-               if (alg & SSL_kEDH)
+       else if (alg & SSL_kEDH)
                {
                if ((dh=DH_new()) == NULL)
                        {
@@ -991,10 +1002,12 @@ static int ssl3_get_key_exchange(SSL *s)
 #ifndef NO_RSA
                if (alg & SSL_aRSA)
                        pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_RSA_ENC].x509);
-               else
+#else
+               if (0)
+                       ;
 #endif
 #ifndef NO_DSA
-               if (alg & SSL_aDSS)
+               else if (alg & SSL_aDSS)
                        pkey=X509_get_pubkey(s->session->sess_cert->peer_pkeys[SSL_PKEY_DSA_SIGN].x509);
 #endif
                /* else anonymous DH, so no certificate or pkey. */
@@ -1008,7 +1021,7 @@ static int ssl3_get_key_exchange(SSL *s)
                SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE,SSL_R_TRIED_TO_USE_UNSUPPORTED_CIPHER);
                goto f_err;
                }
-#endif
+#endif /* !NO_DH */
        if (alg & SSL_aFZA)
                {
                al=SSL_AD_HANDSHAKE_FAILURE;
@@ -1225,7 +1238,7 @@ fclose(out);
 
                if ((xn=d2i_X509_NAME(NULL,&q,l)) == NULL)
                        {
-                       /* If netscape tollerance is on, ignore errors */
+                       /* If netscape tolerance is on, ignore errors */
                        if (s->options & SSL_OP_NETSCAPE_CA_DN_BUG)
                                goto cont;
                        else
@@ -1258,7 +1271,7 @@ cont:
                ERR_clear_error();
                }
 
-       /* we should setup a certficate to return.... */
+       /* we should setup a certificate to return.... */
        s->s3->tmp.cert_req=1;
        s->s3->tmp.ctype_num=ctype_num;
        if (s->s3->tmp.ca_names != NULL)
@@ -1272,7 +1285,7 @@ err:
        return(ret);
        }
 
-static int ca_dn_cmp(X509_NAME **a, X509_NAME **b)
+static int ca_dn_cmp(const X509_NAME * const *a, const X509_NAME * const *b)
        {
        return(X509_NAME_cmp(*a,*b));
        }
@@ -1341,7 +1354,8 @@ static int ssl3_send_client_key_exchange(SSL *s)
                                
                        tmp_buf[0]=s->client_version>>8;
                        tmp_buf[1]=s->client_version&0xff;
-                       RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2);
+                       if (RAND_bytes(&(tmp_buf[2]),SSL_MAX_MASTER_KEY_LENGTH-2) <= 0)
+                                       goto err;
 
                        s->session->master_key_length=SSL_MAX_MASTER_KEY_LENGTH;
 
@@ -1687,13 +1701,13 @@ static int ssl3_check_cert_and_algorithm(SSL *s)
 #endif
 #endif
 
-       if (SSL_IS_EXPORT(algs) && !has_bits(i,EVP_PKT_EXP))
+       if (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && !has_bits(i,EVP_PKT_EXP))
                {
 #ifndef NO_RSA
                if (algs & SSL_kRSA)
                        {
                        if (rsa == NULL
-                           || RSA_size(rsa) > SSL_EXPORT_PKEYLENGTH(algs))
+                           || RSA_size(rsa) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
                                {
                                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_RSA_KEY);
                                goto f_err;
@@ -1705,7 +1719,7 @@ static int ssl3_check_cert_and_algorithm(SSL *s)
                        if (algs & (SSL_kEDH|SSL_kDHr|SSL_kDHd))
                            {
                            if (dh == NULL
-                               || DH_size(dh) > SSL_EXPORT_PKEYLENGTH(algs))
+                               || DH_size(dh) > SSL_C_EXPORT_PKEYLENGTH(s->s3->tmp.new_cipher))
                                {
                                SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,SSL_R_MISSING_EXPORT_TMP_DH_KEY);
                                goto f_err;