Fix SSL handshake functions and SSL_clear() such that SSL_clear()
[openssl.git] / ssl / s3_srvr.c
index dce89bf2bdad8e4deb87227b159fadca0a38400f..8c5b6e8c9cb658343bb6c90b6dbc7bfbd332d441 100644 (file)
  * copied and put under another distribution licence
  * [including the GNU Public Licence.]
  */
+/* ====================================================================
+ * Copyright (c) 1998-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
 
 #define REUSE_CIPHER_BUG
 #define NETSCAPE_HANG_BUG
 #include <openssl/buffer.h>
 #include <openssl/rand.h>
 #include <openssl/objects.h>
-#include <openssl/md5.h>
-#include <openssl/sha.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
+#include <openssl/krb5_asn.h>
 #include "ssl_locl.h"
-
-#ifndef OPENSSL_NO_KRB5
-#include "kssl.h"
-#endif /* OPENSSL_NO_KRB5 */
+#include "kssl_lcl.h"
+#include <openssl/md5.h>
 
 static SSL_METHOD *ssl3_get_server_method(int ver);
 static int ssl3_get_client_hello(SSL *s);
@@ -118,6 +168,7 @@ int ssl3_accept(SSL *s)
        long num1;
        int ret= -1;
        int new_state,state,skip=0;
+       int got_new_session=0;
 
        RAND_add(&Time,sizeof(Time),0);
        ERR_clear_error();
@@ -129,8 +180,8 @@ int ssl3_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)
                {
@@ -184,21 +235,23 @@ int ssl3_accept(SSL *s)
                                goto end;
                                }
 
-                       /* Ok, we now need to push on a buffering BIO so that
-                        * the output is sent in a way that TCP likes :-)
-                        */
-                       if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
-
                        s->init_num=0;
 
                        if (s->state != SSL_ST_RENEGOTIATE)
                                {
+                               /* Ok, we now need to push on a buffering BIO so that
+                                * the output is sent in a way that TCP likes :-)
+                                */
+                               if (!ssl_init_wbio_buffer(s,1)) { ret= -1; goto end; }
+                               
                                ssl3_init_finished_mac(s);
                                s->state=SSL3_ST_SR_CLNT_HELLO_A;
                                s->ctx->stats.sess_accept++;
                                }
                        else
                                {
+                               /* s->state == SSL_ST_RENEGOTIATE,
+                                * we will just send a HelloRequest */
                                s->ctx->stats.sess_accept_renegotiate++;
                                s->state=SSL3_ST_SW_HELLO_REQ_A;
                                }
@@ -219,9 +272,7 @@ int ssl3_accept(SSL *s)
 
                case SSL3_ST_SW_HELLO_REQ_C:
                        s->state=SSL_ST_OK;
-                       ret=1;
-                       goto end;
-                       /* break; */
+                       break;
 
                case SSL3_ST_SR_CLNT_HELLO_A:
                case SSL3_ST_SR_CLNT_HELLO_B:
@@ -230,6 +281,7 @@ int ssl3_accept(SSL *s)
                        s->shutdown=0;
                        ret=ssl3_get_client_hello(s);
                        if (ret <= 0) goto end;
+                       got_new_session=1;
                        s->state=SSL3_ST_SW_SRVR_HELLO_A;
                        s->init_num=0;
                        break;
@@ -271,6 +323,10 @@ int ssl3_accept(SSL *s)
                                && !(l & SSL_KRB5)
 #endif /* OPENSSL_NO_KRB5 */
                                )
+                               /* option SSL_OP_EPHEMERAL_RSA sends temporary RSA key
+                                * even when forbidden by protocol specs
+                                * (handshake may fail as clients are not required to
+                                * be able to handle this) */
                                s->s3->tmp.use_rsa_tmp=1;
                        else
                                s->s3->tmp.use_rsa_tmp=0;
@@ -312,7 +368,9 @@ int ssl3_accept(SSL *s)
                                ((s->s3->tmp.new_cipher->algorithms & SSL_aNULL) &&
                                 /* ... except when the application insists on verification
                                  * (against the specs, but s3_clnt.c accepts this for SSL 3) */
-                                !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))
+                                !(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) ||
+                                 /* never request cert in Kerberos ciphersuites */
+                                (s->s3->tmp.new_cipher->algorithms & SSL_aKRB5))
                                {
                                /* no cert request */
                                skip=1;
@@ -464,18 +522,25 @@ int ssl3_accept(SSL *s)
                        /* remove buffering on output */
                        ssl_free_wbio_buffer(s);
 
-                       s->new_session=0;
                        s->init_num=0;
 
-                       ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
-
-                       s->ctx->stats.sess_accept_good++;
-                       /* s->server=1; */
-                       s->handshake_func=ssl3_accept;
-                       ret=1;
-
-                       if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
-
+                       if (got_new_session) /* skipped if we just sent a HelloRequest */
+                               {
+                               /* actually not necessarily a 'new' session unless
+                                * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+                               
+                               s->new_session=0;
+                               
+                               ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
+                               
+                               s->ctx->stats.sess_accept_good++;
+                               /* s->server=1; */
+                               s->handshake_func=ssl3_accept;
+
+                               if (cb != NULL) cb(s,SSL_CB_HANDSHAKE_DONE,1);
+                               }
+                       
+                       ret = 1;
                        goto end;
                        /* break; */
 
@@ -541,11 +606,13 @@ static int ssl3_check_client_hello(SSL *s)
        int ok;
        long n;
 
+       /* this function is called when we really expect a Certificate message,
+        * so permit appropriate message length */
        n=ssl3_get_message(s,
                SSL3_ST_SR_CERT_A,
                SSL3_ST_SR_CERT_B,
                -1,
-               SSL3_RT_MAX_PLAIN_LENGTH,
+               s->max_cert_list,
                &ok);
        if (!ok) return((int)n);
        s->s3->tmp.reuse_message = 1;
@@ -596,13 +663,25 @@ static int ssl3_get_client_hello(SSL *s)
                &ok);
 
        if (!ok) return((int)n);
-       d=p=(unsigned char *)s->init_buf->data;
+       d=p=(unsigned char *)s->init_msg;
 
        /* use version from inside client hello, not from record header
         * (may differ: see RFC 2246, Appendix E, second paragraph) */
        s->client_version=(((int)p[0])<<8)|(int)p[1];
        p+=2;
 
+       if (s->client_version < s->version)
+               {
+               SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_WRONG_VERSION_NUMBER);
+               if ((s->client_version>>8) == SSL3_VERSION_MAJOR) 
+                       {
+                       /* similar to ssl3_get_record, send alert using remote version number */
+                       s->version = s->client_version;
+                       }
+               al = SSL_AD_PROTOCOL_VERSION;
+               goto f_err;
+               }
+
        /* load the client random */
        memcpy(s->s3->client_random,p,SSL3_RANDOM_SIZE);
        p+=SSL3_RANDOM_SIZE;
@@ -611,7 +690,15 @@ static int ssl3_get_client_hello(SSL *s)
        j= *(p++);
 
        s->hit=0;
-       if (j == 0)
+       /* Versions before 0.9.7 always allow session reuse during renegotiation
+        * (i.e. when s->new_session is true), option
+        * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is new with 0.9.7.
+        * Maybe this optional behaviour should always have been the default,
+        * but we cannot safely change the default behaviour (or new applications
+        * might be written that become totally unsecure when compiled with
+        * an earlier library version)
+        */
+       if (j == 0 || (s->new_session && (s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)))
                {
                if (!ssl_get_new_session(s,1))
                        goto err;
@@ -948,6 +1035,7 @@ static int ssl3_send_server_key_exchange(SSL *s)
        BUF_MEM *buf;
        EVP_MD_CTX md_ctx;
 
+       EVP_MD_CTX_init(&md_ctx);
        if (s->state == SSL3_ST_SW_KEY_EXCH_A)
                {
                type=s->s3->tmp.new_cipher->algorithms & SSL_MKEY_MASK;
@@ -972,7 +1060,7 @@ static int ssl3_send_server_key_exchange(SSL *s)
                                        SSLerr(SSL_F_SSL3_SEND_SERVER_KEY_EXCHANGE,SSL_R_ERROR_GENERATING_TMP_RSA_KEY);
                                        goto f_err;
                                }
-                               CRYPTO_add(&rsa->references,1,CRYPTO_LOCK_RSA);
+                               RSA_up_ref(rsa);
                                cert->rsa_tmp=rsa;
                                }
                        if (rsa == NULL)
@@ -1098,12 +1186,12 @@ static int ssl3_send_server_key_exchange(SSL *s)
                                j=0;
                                for (num=2; num > 0; num--)
                                        {
-                                       EVP_DigestInit(&md_ctx,(num == 2)
-                                               ?s->ctx->md5:s->ctx->sha1);
+                                       EVP_DigestInit_ex(&md_ctx,(num == 2)
+                                               ?s->ctx->md5:s->ctx->sha1, NULL);
                                        EVP_DigestUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                                        EVP_DigestUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
                                        EVP_DigestUpdate(&md_ctx,&(d[4]),n);
-                                       EVP_DigestFinal(&md_ctx,q,
+                                       EVP_DigestFinal_ex(&md_ctx,q,
                                                (unsigned int *)&i);
                                        q+=i;
                                        j+=i;
@@ -1123,7 +1211,7 @@ static int ssl3_send_server_key_exchange(SSL *s)
                                if (pkey->type == EVP_PKEY_DSA)
                                {
                                /* lets do DSS */
-                               EVP_SignInit(&md_ctx,EVP_dss1());
+                               EVP_SignInit_ex(&md_ctx,EVP_dss1(), NULL);
                                EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE);
                                EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE);
                                EVP_SignUpdate(&md_ctx,&(d[4]),n);
@@ -1156,10 +1244,12 @@ static int ssl3_send_server_key_exchange(SSL *s)
                }
 
        s->state = SSL3_ST_SW_KEY_EXCH_B;
+       EVP_MD_CTX_cleanup(&md_ctx);
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
 f_err:
        ssl3_send_alert(s,SSL3_AL_FATAL,al);
 err:
+       EVP_MD_CTX_cleanup(&md_ctx);
        return(-1);
        }
 
@@ -1277,7 +1367,7 @@ static int ssl3_get_client_key_exchange(SSL *s)
                &ok);
 
        if (!ok) return((int)n);
-       p=(unsigned char *)s->init_buf->data;
+       p=(unsigned char *)s->init_msg;
 
        l=s->s3->tmp.new_cipher->algorithms;
 
@@ -1333,14 +1423,15 @@ static int ssl3_get_client_key_exchange(SSL *s)
 
                i=RSA_private_decrypt((int)n,p,p,rsa,RSA_PKCS1_PADDING);
 
+               al = -1;
+               
                if (i != SSL_MAX_MASTER_KEY_LENGTH)
                        {
                        al=SSL_AD_DECODE_ERROR;
                        SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_BAD_RSA_DECRYPT);
-                       goto f_err;
                        }
 
-               if (!((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
+               if ((al == -1) && !((p[0] == (s->client_version>>8)) && (p[1] == (s->client_version & 0xff))))
                        {
                        /* The premaster secret must contain the same version number as the
                         * ClientHello to detect version rollback attacks (strangely, the
@@ -1358,6 +1449,27 @@ static int ssl3_get_client_key_exchange(SSL *s)
                                }
                        }
 
+               if (al != -1)
+                       {
+#if 0
+                       goto f_err;
+#else
+                       /* Some decryption failure -- use random value instead as countermeasure
+                        * against Bleichenbacher's attack on PKCS #1 v1.5 RSA padding
+                        * (see RFC 2246, section 7.4.7.1).
+                        * But note that due to length and protocol version checking, the
+                        * attack is impractical anyway (see section 5 in D. Bleichenbacher:
+                        * "Chosen Ciphertext Attacks Against Protocols Based on the RSA
+                        * Encryption Standard PKCS #1", CRYPTO '98, LNCS 1462, pp. 1-12).
+                        */
+                       ERR_clear_error();
+                       i = SSL_MAX_MASTER_KEY_LENGTH;
+                       p[0] = s->client_version >> 8;
+                       p[1] = s->client_version & 0xff;
+                       RAND_pseudo_bytes(p+2, i-2); /* should be RAND_bytes, but we cannot work around a failure */
+#endif
+                       }
+       
                s->session->master_key_length=
                        s->method->ssl3_enc->generate_master_secret(s,
                                s->session->master_key,
@@ -1432,13 +1544,47 @@ static int ssl3_get_client_key_exchange(SSL *s)
 #ifndef OPENSSL_NO_KRB5
         if (l & SSL_kKRB5)
                 {
-                krb5_error_code        krb5rc;
-                KSSL_CTX       *kssl_ctx = s->kssl_ctx;
+                krb5_error_code                krb5rc;
+               krb5_data               enc_ticket;
+               krb5_data               authenticator;
+               krb5_data               enc_pms;
+                KSSL_CTX               *kssl_ctx = s->kssl_ctx;
+               EVP_CIPHER_CTX          ciph_ctx;
+               EVP_CIPHER              *enc = NULL;
+               unsigned char           iv[EVP_MAX_IV_LENGTH];
+               unsigned char           pms[SSL_MAX_MASTER_KEY_LENGTH
+                                               + EVP_MAX_IV_LENGTH + 1];
+               int                     padl, outl = sizeof(pms);
+               krb5_timestamp          authtime = 0;
+               krb5_ticket_times       ttimes;
 
                 if (!kssl_ctx)  kssl_ctx = kssl_ctx_new();
-                if ((krb5rc = kssl_sget_tkt(kssl_ctx,
-                        s->init_buf->data, s->init_buf->length,
-                        &kssl_err)) != 0)
+
+               n2s(p,i);
+               enc_ticket.length = i;
+               enc_ticket.data = p;
+               p+=enc_ticket.length;
+
+               n2s(p,i);
+               authenticator.length = i;
+               authenticator.data = p;
+               p+=authenticator.length;
+
+               n2s(p,i);
+               enc_pms.length = i;
+               enc_pms.data = p;
+               p+=enc_pms.length;
+
+               if ((unsigned long)n != enc_ticket.length + authenticator.length +
+                                               enc_pms.length + 6)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_DATA_LENGTH_TOO_LONG);
+                       goto err;
+                       }
+
+                if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes,
+                                       &kssl_err)) != 0)
                         {
 #ifdef KSSL_DEBUG
                         printf("kssl_sget_tkt rtn %d [%d]\n",
@@ -1451,34 +1597,100 @@ static int ssl3_get_client_key_exchange(SSL *s)
                         goto err;
                         }
 
+               /*  Note: no authenticator is not considered an error,
+               **  but will return authtime == 0.
+               */
+               if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator,
+                                       &authtime, &kssl_err)) != 0)
+                       {
+#ifdef KSSL_DEBUG
+                        printf("kssl_check_authent rtn %d [%d]\n",
+                                krb5rc, kssl_err.reason);
+                        if (kssl_err.text)
+                                printf("kssl_err text= %s\n", kssl_err.text);
+#endif /* KSSL_DEBUG */
+                        SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE,
+                                kssl_err.reason);
+                        goto err;
+                       }
+
+               if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0)
+                       {
+                       SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, krb5rc);
+                        goto err;
+                       }
+
 #ifdef KSSL_DEBUG
                 kssl_ctx_show(kssl_ctx);
 #endif /* KSSL_DEBUG */
 
-                /*     19991013 VRS -  3DES is kind of bogus here,
-                **     at least until Kerberos supports 3DES.  The only
-                **     real secret is the 8-byte Kerberos session key;
-                **     the other key material (client_random, server_random)
-                **     could be sniffed.  Nonces may help against replays though.
-                **
-                **     Alternate code for Kerberos Purists:
-                **
-                **     memcpy(s->session->master_key,  kssl_ctx->key, kssl_ctx->length);
-                **     s->session->master_key_length = kssl_ctx->length;
-                */
+               enc = kssl_map_enc(kssl_ctx->enctype);
+                if (enc == NULL)
+                    goto err;
+
+               memset(iv, 0, EVP_MAX_IV_LENGTH);       /* per RFC 1510 */
+
+               if (!EVP_DecryptInit_ex(&ciph_ctx,enc,NULL,kssl_ctx->key,iv))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_DECRYPTION_FAILED);
+                       goto err;
+                       }
+               if (!EVP_DecryptUpdate(&ciph_ctx, pms,&outl,
+                                       enc_pms.data, enc_pms.length))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_DECRYPTION_FAILED);
+                       goto err;
+                       }
+               if (outl > SSL_MAX_MASTER_KEY_LENGTH)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_DATA_LENGTH_TOO_LONG);
+                       goto err;
+                       }
+               if (!EVP_DecryptFinal_ex(&ciph_ctx,&(pms[outl]),&padl))
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_DECRYPTION_FAILED);
+                       goto err;
+                       }
+               outl += padl;
+               if (outl > SSL_MAX_MASTER_KEY_LENGTH)
+                       {
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_DATA_LENGTH_TOO_LONG);
+                       goto err;
+                       }
+               EVP_CIPHER_CTX_cleanup(&ciph_ctx);
+
                 s->session->master_key_length=
                         s->method->ssl3_enc->generate_master_secret(s,
-                                s->session->master_key, kssl_ctx->key, kssl_ctx->length);
-                /*     Was doing kssl_ctx_free() here, but it caused problems for apache.
-                **     kssl_ctx = kssl_ctx_free(kssl_ctx);
-                **     if (s->kssl_ctx)  s->kssl_ctx = NULL;
+                                s->session->master_key, pms, outl);
+
+                if (kssl_ctx->client_princ)
+                        {
+                        int len = strlen(kssl_ctx->client_princ);
+                        if ( len < SSL_MAX_KRB5_PRINCIPAL_LENGTH ) 
+                                {
+                                s->session->krb5_client_princ_len = len;
+                                memcpy(s->session->krb5_client_princ,kssl_ctx->client_princ,len);
+                                }
+                        }
+
+
+                /*  Was doing kssl_ctx_free() here,
+               **  but it caused problems for apache.
+                **  kssl_ctx = kssl_ctx_free(kssl_ctx);
+                **  if (s->kssl_ctx)  s->kssl_ctx = NULL;
                 */
                 }
        else
 #endif /* OPENSSL_NO_KRB5 */
                {
                al=SSL_AD_HANDSHAKE_FAILURE;
-               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNKNOWN_CIPHER_TYPE);
+               SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
+                               SSL_R_UNKNOWN_CIPHER_TYPE);
                goto f_err;
                }
 
@@ -1556,7 +1768,7 @@ static int ssl3_get_cert_verify(SSL *s)
                }
 
        /* we now have a signature that we need to verify */
-       p=(unsigned char *)s->init_buf->data;
+       p=(unsigned char *)s->init_msg;
        n2s(p,i);
        n-=2;
        if (i > n)
@@ -1641,11 +1853,7 @@ static int ssl3_get_client_certificate(SSL *s)
                SSL3_ST_SR_CERT_A,
                SSL3_ST_SR_CERT_B,
                -1,
-#if defined(OPENSSL_SYS_MSDOS) && !defined(OPENSSL_SYS_WIN32)
-               1024*30, /* 30k max cert list :-) */
-#else
-               1024*100, /* 100k max cert list :-) */
-#endif
+               s->max_cert_list,
                &ok);
 
        if (!ok) return((int)n);
@@ -1676,7 +1884,7 @@ static int ssl3_get_client_certificate(SSL *s)
                SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
                goto f_err;
                }
-       d=p=(unsigned char *)s->init_buf->data;
+       d=p=(unsigned char *)s->init_msg;
 
        if ((sk=sk_X509_new_null()) == NULL)
                {