Set next version.
[oweals/openssl.git] / ssl / ssl_lib.c
index c3a9a6d70658e818a7a3e91f8a6a4e638b5f92eb..8b6b601cabd88da639489dad0443abc02f3f92da 100644 (file)
@@ -508,7 +508,6 @@ 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);
@@ -526,6 +525,8 @@ void SSL_free(SSL *s)
 
        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);
@@ -986,8 +987,12 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
 
        case SSL_CTRL_OPTIONS:
                return(s->options|=larg);
+       case SSL_CTRL_CLEAR_OPTIONS:
+               return(s->options&=~larg);
        case SSL_CTRL_MODE:
                return(s->mode|=larg);
+       case SSL_CTRL_CLEAR_MODE:
+               return(s->mode &=~larg);
        case SSL_CTRL_GET_MAX_CERT_LIST:
                return(s->max_cert_list);
        case SSL_CTRL_SET_MAX_CERT_LIST:
@@ -995,6 +1000,11 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
                s->max_cert_list=larg;
                return(l);
        case SSL_CTRL_SET_MTU:
+#ifndef OPENSSL_NO_DTLS1
+               if (larg < (long)dtls1_min_mtu())
+                       return 0;
+#endif
+
                if (SSL_version(s) == DTLS1_VERSION ||
                    SSL_version(s) == DTLS1_BAD_VER)
                        {
@@ -1002,6 +1012,10 @@ long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
                        return larg;
                        }
                return 0;
+       case SSL_CTRL_GET_RI_SUPPORT:
+               if (s->s3)
+                       return s->s3->send_connection_binding;
+               else return 0;
        default:
                return(s->method->ssl_ctrl(s,cmd,larg,parg));
                }
@@ -1088,8 +1102,12 @@ long SSL_CTX_ctrl(SSL_CTX *ctx,int cmd,long larg,void *parg)
                return(ctx->stats.sess_cache_full);
        case SSL_CTRL_OPTIONS:
                return(ctx->options|=larg);
+       case SSL_CTRL_CLEAR_OPTIONS:
+               return(ctx->options&=~larg);
        case SSL_CTRL_MODE:
                return(ctx->mode|=larg);
+       case SSL_CTRL_CLEAR_MODE:
+               return(ctx->mode&=~larg);
        default:
                return(ctx->method->ssl_ctx_ctrl(ctx,cmd,larg,parg));
                }
@@ -1286,6 +1304,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 SCSV if not renegotiating.
+        */
+       if (p != q && !s->new_session)
+               {
+               static SSL_CIPHER scsv =
+                       {
+                       0, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0,
+                       };
+               j = put_cb ? put_cb(&scsv,p) : ssl_put_cipher_by_char(s,&scsv,p);
+               p+=j;
+#ifdef OPENSSL_RI_DEBUG
+               fprintf(stderr, "SCSV sent by client\n");
+#endif
+               }
+
        return(p-q);
        }
 
@@ -1295,6 +1329,8 @@ STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s,unsigned char *p,int num,
        SSL_CIPHER *c;
        STACK_OF(SSL_CIPHER) *sk;
        int i,n;
+       if (s->s3)
+               s->s3->send_connection_binding = 0;
 
        n=ssl_put_cipher_by_char(s,NULL,NULL);
        if ((num%n) != 0)
@@ -1312,6 +1348,26 @@ 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 SCSV */
+               if (s->s3 && (n != 3 || !p[0]) &&
+                       (p[n-2] == ((SSL3_CK_SCSV >> 8) & 0xff)) &&
+                       (p[n-1] == (SSL3_CK_SCSV & 0xff)))
+                       {
+                       /* SCSV fatal if renegotiating */
+                       if (s->new_session)
+                               {
+                               SSLerr(SSL_F_SSL_BYTES_TO_CIPHER_LIST,SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
+                               ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); 
+                               goto err;
+                               }
+                       s->s3->send_connection_binding = 1;
+                       p += n;
+#ifdef OPENSSL_RI_DEBUG
+                       fprintf(stderr, "SCSV received by server\n");
+#endif
+                       continue;
+                       }
+
                c=ssl_get_cipher_by_char(s,p);
                p+=n;
                if (c != NULL)
@@ -1547,6 +1603,10 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
        }
 #endif
 #endif
+       /* Default is to connect to non-RI servers. When RI is more widely
+        * deployed might change this.
+        */
+       ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
 
        return(ret);
 err:
@@ -1883,17 +1943,15 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs)
        }
 
 /* THIS NEEDS CLEANING UP */
-X509 *ssl_get_server_send_cert(SSL *s)
+CERT_PKEY *ssl_get_server_send_pkey(const SSL *s)
        {
-       unsigned long alg,mask,kalg;
+       unsigned long alg,kalg;
        CERT *c;
-       int i,is_export;
+       int i;
 
        c=s->cert;
        ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
        alg=s->s3->tmp.new_cipher->algorithms;
-       is_export=SSL_C_IS_EXPORT(s->s3->tmp.new_cipher);
-       mask=is_export?c->export_mask:c->mask;
        kalg=alg&(SSL_MKEY_MASK|SSL_AUTH_MASK);
 
        if (kalg & SSL_kECDH)
@@ -1935,12 +1993,20 @@ X509 *ssl_get_server_send_cert(SSL *s)
                }
        else /* if (kalg & SSL_aNULL) */
                {
-               SSLerr(SSL_F_SSL_GET_SERVER_SEND_CERT,ERR_R_INTERNAL_ERROR);
+               SSLerr(SSL_F_SSL_GET_SERVER_SEND_PKEY,ERR_R_INTERNAL_ERROR);
                return(NULL);
                }
-       if (c->pkeys[i].x509 == NULL) return(NULL);
 
-       return(c->pkeys[i].x509);
+       return c->pkeys + i;
+       }
+
+X509 *ssl_get_server_send_cert(const SSL *s)
+       {
+       CERT_PKEY *cpk;
+       cpk = ssl_get_server_send_pkey(s);
+       if (!cpk)
+               return NULL;
+       return cpk->x509;
        }
 
 EVP_PKEY *ssl_get_sign_pkey(SSL *s,SSL_CIPHER *cipher)
@@ -2362,7 +2428,9 @@ void ssl_clear_cipher_ctx(SSL *s)
 /* Fix this function so that it takes an optional type parameter */
 X509 *SSL_get_certificate(const SSL *s)
        {
-       if (s->cert != NULL)
+       if (s->server)
+               return(ssl_get_server_send_cert(s));
+       else if (s->cert != NULL)
                return(s->cert->key->x509);
        else
                return(NULL);