Add support for magic cipher suite value (MCSV). Make secure renegotiation
[openssl.git] / ssl / ssl_lib.c
index 31fd26d41bc8aaf4a93a98ef0a58fbdd7d620a24..e0a592619243fbcd5b678d173c1fd1367affd16a 100644 (file)
 #include <openssl/lhash.h>
 #include <openssl/x509v3.h>
 #include <openssl/rand.h>
+#include <openssl/ocsp.h>
 #ifndef OPENSSL_NO_DH
 #include <openssl/dh.h>
 #endif
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
 
 const char *SSL_version_str=OPENSSL_VERSION_TEXT;
 
@@ -311,6 +315,12 @@ SSL *SSL_new(SSL_CTX *ctx)
        s->tlsext_debug_cb = 0;
        s->tlsext_debug_arg = NULL;
        s->tlsext_ticket_expected = 0;
+       s->tlsext_status_type = -1;
+       s->tlsext_status_expected = 0;
+       s->tlsext_ocsp_ids = NULL;
+       s->tlsext_ocsp_exts = NULL;
+       s->tlsext_ocsp_resp = NULL;
+       s->tlsext_ocsp_resplen = -1;
        CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
        s->initial_ctx=ctx;
 #endif
@@ -498,15 +508,25 @@ void SSL_free(SSL *s)
        if (s->cert != NULL) ssl_cert_free(s->cert);
        /* Free up if allocated */
 
-       if (s->ctx) SSL_CTX_free(s->ctx);
 #ifndef OPENSSL_NO_TLSEXT
+       if (s->tlsext_hostname)
+               OPENSSL_free(s->tlsext_hostname);
        if (s->initial_ctx) SSL_CTX_free(s->initial_ctx);
+       if (s->tlsext_ocsp_exts)
+               sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+                                               X509_EXTENSION_free);
+       if (s->tlsext_ocsp_ids)
+               sk_OCSP_RESPID_pop_free(s->tlsext_ocsp_ids, OCSP_RESPID_free);
+       if (s->tlsext_ocsp_resp)
+               OPENSSL_free(s->tlsext_ocsp_resp);
 #endif
        if (s->client_CA != NULL)
                sk_X509_NAME_pop_free(s->client_CA,X509_NAME_free);
 
        if (s->method != NULL) s->method->ssl_free(s);
 
+       if (s->ctx) SSL_CTX_free(s->ctx);
+
 #ifndef        OPENSSL_NO_KRB5
        if (s->kssl_ctx != NULL)
                kssl_ctx_free(s->kssl_ctx);
@@ -976,7 +996,8 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
                s->max_cert_list=larg;
                return(l);
        case SSL_CTRL_SET_MTU:
-               if (SSL_version(s) == DTLS1_VERSION)
+               if (SSL_version(s) == DTLS1_VERSION ||
+                   SSL_version(s) == DTLS1_BAD_VER)
                        {
                        s->d1->mtu = larg;
                        return larg;
@@ -1210,7 +1231,6 @@ int SSL_set_cipher_list(SSL *s,const char *str)
 char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
        {
        char *p;
-       const char *cp;
        STACK_OF(SSL_CIPHER) *sk;
        SSL_CIPHER *c;
        int i;
@@ -1223,20 +1243,21 @@ char *SSL_get_shared_ciphers(const SSL *s,char *buf,int len)
        sk=s->session->ciphers;
        for (i=0; i<sk_SSL_CIPHER_num(sk); i++)
                {
-               /* Decrement for either the ':' or a '\0' */
-               len--;
+               int n;
+
                c=sk_SSL_CIPHER_value(sk,i);
-               for (cp=c->name; *cp; )
+               n=strlen(c->name);
+               if (n+1 > len)
                        {
-                       if (len-- <= 0)
-                               {
-                               *p='\0';
-                               return(buf);
-                               }
-                       else
-                               *(p++)= *(cp++);
+                       if (p != buf)
+                               --p;
+                       *p='\0';
+                       return buf;
                        }
+               strcpy(p,c->name);
+               p+=n;
                *(p++)=':';
+               len-=n+1;
                }
        p[-1]='\0';
        return(buf);
@@ -1266,6 +1287,22 @@ int ssl_cipher_list_to_bytes(SSL *s,STACK_OF(SSL_CIPHER) *sk,unsigned char *p,
                j = put_cb ? put_cb(c,p) : ssl_put_cipher_by_char(s,c,p);
                p+=j;
                }
+       /* If p == q, no ciphers and caller indicates an error, otherwise
+        * add MCSV
+        */
+       if (p != q)
+               {
+               static SSL_CIPHER msvc =
+                       {
+                       0, NULL, SSL3_CK_MCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                       };
+               j = put_cb ? put_cb(&msvc,p) : ssl_put_cipher_by_char(s,&msvc,p);
+               p+=j;
+#ifdef OPENSSL_RI_DEBUG
+               fprintf(stderr, "MCSV sent by client\n");
+#endif
+               }
+
        return(p-q);
        }
 
@@ -1276,6 +1313,8 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
        STACK_OF(SSL_CIPHER) *sk;
        int i,n;
 
+       s->s3->send_connection_binding = 0;
+
        n=ssl_put_cipher_by_char(s,NULL,NULL);
        if ((num%n) != 0)
                {
@@ -1292,6 +1331,19 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
 
        for (i=0; i<num; i+=n)
                {
+               /* Check for MCSV */
+               if ((n != 3 || !p[0]) &&
+                       (p[n-2] == ((SSL3_CK_MCSV >> 8) & 0xff)) &&
+                       (p[n-1] == (SSL3_CK_MCSV & 0xff)))
+                       {
+                       s->s3->send_connection_binding = 1;
+                       p += n;
+#ifdef OPENSSL_RI_DEBUG
+                       fprintf(stderr, "MCSV received by server\n");
+#endif
+                       continue;
+                       }
+
                c=ssl_get_cipher_by_char(s,p);
                p+=n;
                if (c != NULL)
@@ -1379,6 +1431,14 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
                return(NULL);
                }
 
+#ifdef OPENSSL_FIPS
+       if (FIPS_mode() && (meth->version < TLS1_VERSION))      
+               {
+               SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_ONLY_TLS_ALLOWED_IN_FIPS_MODE);
+               return NULL;
+               }
+#endif
+
        if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0)
                {
                SSLerr(SSL_F_SSL_CTX_NEW,SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
@@ -1494,6 +1554,30 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
                || (RAND_bytes(ret->tlsext_tick_aes_key, 16) <= 0))
                ret->options |= SSL_OP_NO_TICKET;
 
+       ret->tlsext_status_cb = 0;
+       ret->tlsext_status_arg = NULL;
+
+#endif
+
+#ifndef OPENSSL_NO_ENGINE
+       ret->client_cert_engine = NULL;
+#ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
+#define eng_strx(x)    #x
+#define eng_str(x)     eng_strx(x)
+       /* Use specific client engine automatically... ignore errors */
+       {
+       ENGINE *eng;
+       eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+       if (!eng)
+               {
+               ERR_clear_error();
+               ENGINE_load_builtin_engines();
+               eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
+               }
+       if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng))
+               ERR_clear_error();
+       }
+#endif
 #endif
 
        return(ret);
@@ -1565,6 +1649,10 @@ void SSL_CTX_free(SSL_CTX *a)
                sk_SSL_COMP_pop_free(a->comp_methods,SSL_COMP_free);
 #else
        a->comp_methods = NULL;
+#endif
+#ifndef OPENSSL_NO_ENGINE
+       if (a->client_cert_engine)
+               ENGINE_finish(a->client_cert_engine);
 #endif
        OPENSSL_free(a);
        }