perform sanity checks on server certificate type as soon as it is received instead of waiting until server key exchange
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index 81e45a7..b5c939f 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -1225,6 +1225,15 @@
 
 	if (need_cert)
 		{
+		int exp_idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+		if (exp_idx >= 0 && i != exp_idx)
+			{
+			x=NULL;
+			al=SSL_AD_ILLEGAL_PARAMETER;
+			SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,
+				SSL_R_WRONG_CERTIFICATE_TYPE);
+			goto f_err;
+			}
 		sc->peer_cert_type=i;
 		CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
 		/* Why would the following ever happen?
diff --git a/ssl/ssl.h b/ssl/ssl.h
index c5d4504..857cbf0 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -2800,6 +2800,7 @@
 #define SSL_R_UNSUPPORTED_STATUS_TYPE			 329
 #define SSL_R_USE_SRTP_NOT_NEGOTIATED			 369
 #define SSL_R_WRITE_BIO_NOT_SET				 260
+#define SSL_R_WRONG_CERTIFICATE_TYPE			 383
 #define SSL_R_WRONG_CIPHER_RETURNED			 261
 #define SSL_R_WRONG_CURVE				 378
 #define SSL_R_WRONG_MESSAGE_TYPE			 262
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index e00c452..5e1f27c 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1889,5 +1889,47 @@
 		return comp->name;
 	return NULL;
 	}
-
 #endif
+/* For a cipher return the index corresponding to the certificate type */
+int ssl_cipher_get_cert_index(const SSL_CIPHER *c)
+	{
+ 	unsigned long alg_k, alg_a;
+
+	alg_k = c->algorithm_mkey;
+	alg_a = c->algorithm_auth;
+
+	if (alg_k & (SSL_kECDHr|SSL_kECDHe))
+		{
+		/* we don't need to look at SSL_kEECDH
+		 * since no certificate is needed for
+		 * anon ECDH and for authenticated
+		 * EECDH, the check for the auth
+		 * algorithm will set i correctly
+		 * NOTE: For ECDH-RSA, we need an ECC
+		 * not an RSA cert but for EECDH-RSA
+		 * we need an RSA cert. Placing the
+		 * checks for SSL_kECDH before RSA
+		 * checks ensures the correct cert is chosen.
+		 */
+		return SSL_PKEY_ECC;
+		}
+	else if (alg_a & SSL_aECDSA)
+		return SSL_PKEY_ECC;
+	else if (alg_k & SSL_kDHr)
+		return SSL_PKEY_DH_RSA;
+	else if (alg_k & SSL_kDHd)
+		return SSL_PKEY_DH_DSA;
+	else if (alg_a & SSL_aDSS)
+		return SSL_PKEY_DSA_SIGN;
+	else if (alg_a & SSL_aRSA)
+		return SSL_PKEY_RSA_ENC;
+	else if (alg_a & SSL_aKRB5)
+		/* VRS something else here? */
+		return -1;
+	else if (alg_a & SSL_aGOST94) 
+		return SSL_PKEY_GOST94;
+	else if (alg_a & SSL_aGOST01)
+		return SSL_PKEY_GOST01;
+	return -1;
+	}
+
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 119a43c..a816af0 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -607,6 +607,7 @@
 {ERR_REASON(SSL_R_UNSUPPORTED_STATUS_TYPE),"unsupported status type"},
 {ERR_REASON(SSL_R_USE_SRTP_NOT_NEGOTIATED),"use srtp not negotiated"},
 {ERR_REASON(SSL_R_WRITE_BIO_NOT_SET)     ,"write bio not set"},
+{ERR_REASON(SSL_R_WRONG_CERTIFICATE_TYPE),"wrong certificate type"},
 {ERR_REASON(SSL_R_WRONG_CIPHER_RETURNED) ,"wrong cipher returned"},
 {ERR_REASON(SSL_R_WRONG_CURVE)           ,"wrong curve"},
 {ERR_REASON(SSL_R_WRONG_MESSAGE_TYPE)    ,"wrong message type"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index f2318f1..4289a74 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -2336,56 +2336,15 @@
 
 #endif
 
-/* THIS NEEDS CLEANING UP */
 static int ssl_get_server_cert_index(SSL *s)
 	{
- 	unsigned long alg_k, alg_a;
-
-	alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
-	alg_a = s->s3->tmp.new_cipher->algorithm_auth;
-
-	if (alg_k & (SSL_kECDHr|SSL_kECDHe))
-		{
-		/* we don't need to look at SSL_kEECDH
-		 * since no certificate is needed for
-		 * anon ECDH and for authenticated
-		 * EECDH, the check for the auth
-		 * algorithm will set i correctly
-		 * NOTE: For ECDH-RSA, we need an ECC
-		 * not an RSA cert but for EECDH-RSA
-		 * we need an RSA cert. Placing the
-		 * checks for SSL_kECDH before RSA
-		 * checks ensures the correct cert is chosen.
-		 */
-		return SSL_PKEY_ECC;
-		}
-	else if (alg_a & SSL_aECDSA)
-		return SSL_PKEY_ECC;
-	else if (alg_k & SSL_kDHr)
-		return SSL_PKEY_DH_RSA;
-	else if (alg_k & SSL_kDHd)
-		return SSL_PKEY_DH_DSA;
-	else if (alg_a & SSL_aDSS)
-		return SSL_PKEY_DSA_SIGN;
-	else if (alg_a & SSL_aRSA)
-		{
-		if (s->cert->pkeys[SSL_PKEY_RSA_ENC].x509 == NULL)
-			return SSL_PKEY_RSA_SIGN;
-		else
-			return SSL_PKEY_RSA_ENC;
-		}
-	else if (alg_a & SSL_aKRB5)
-		/* VRS something else here? */
-		return -1;
-	else if (alg_a & SSL_aGOST94) 
-		return SSL_PKEY_GOST94;
-	else if (alg_a & SSL_aGOST01)
-		return SSL_PKEY_GOST01;
-	else /* if (alg_a & SSL_aNULL) */
-		{
+	int idx;
+	idx = ssl_cipher_get_cert_index(s->s3->tmp.new_cipher);
+	if (idx == SSL_PKEY_RSA_ENC && !s->cert->pkeys[SSL_PKEY_RSA_ENC].x509)
+		idx = SSL_PKEY_RSA_SIGN;
+	if (idx == -1)
 		SSLerr(SSL_F_SSL_GET_SERVER_CERT_INDEX,ERR_R_INTERNAL_ERROR);
-		return -1;
-		}
+	return idx;
 	}
 
 CERT_PKEY *ssl_get_server_send_pkey(SSL *s)
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 39ee16b..eb6ef4c 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -919,7 +919,8 @@
 void ssl_update_cache(SSL *s, int mode);
 int ssl_cipher_get_evp(const SSL_SESSION *s,const EVP_CIPHER **enc,
 		       const EVP_MD **md,int *mac_pkey_type,int *mac_secret_size, SSL_COMP **comp);
-int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);			   
+int ssl_get_handshake_digest(int i,long *mask,const EVP_MD **md);
+int ssl_cipher_get_cert_index(const SSL_CIPHER *c);
 int ssl_cert_set0_chain(CERT *c, STACK_OF(X509) *chain);
 int ssl_cert_set1_chain(CERT *c, STACK_OF(X509) *chain);
 int ssl_cert_add0_chain_cert(CERT *c, X509 *x);