A comment.
[openssl.git] / ssl / ssl_lib.c
index 6a80fbe16380245127155e00215c0ecb30322c46..7b9228fdfc27becf6b694da932508e1ae7bb5d4b 100644 (file)
@@ -70,7 +70,7 @@ static STACK *ssl_ctx_meth=NULL;
 static int ssl_meth_num=0;
 static int ssl_ctx_meth_num=0;
 
-SSL3_ENC_METHOD ssl3_undef_enc_method={
+GLOBAL SSL3_ENC_METHOD ssl3_undef_enc_method={
        ssl_undefined_function,
        ssl_undefined_function,
        ssl_undefined_function,
@@ -178,14 +178,24 @@ SSL *SSL_new(SSL_CTX *ctx)
        if (s == NULL) goto err;
        memset(s,0,sizeof(SSL));
 
-       if (ctx->default_cert != NULL)
+       if (ctx->cert != NULL)
                {
-               CRYPTO_add(&ctx->default_cert->references,1,
-                          CRYPTO_LOCK_SSL_CERT);
-               s->cert=ctx->default_cert;
+               /* Earlier library versions used to copy the pointer to
+                * the CERT, not its contents; only when setting new
+                * parameters for the per-SSL copy, ssl_cert_new would be
+                * called (and the direct reference to the per-SSL_CTX
+                * settings would be lost, but those still were indirectly
+                * accessed for various purposes, and for that reason they
+                * used to be known as s->ctx->default_cert).
+                * Now we don't look at the SSL_CTX's CERT after having
+                * duplicated it once. */
+
+               s->cert = ssl_cert_dup(ctx->cert);
+               if (s->cert == NULL)
+                       goto err;
                }
        else
-               s->cert=NULL;
+               s->cert=NULL; /* Cannot really happen (see SSL_CTX_new) */
        s->sid_ctx_length=ctx->sid_ctx_length;
        memcpy(&s->sid_ctx,&ctx->sid_ctx,sizeof(s->sid_ctx));
        s->verify_mode=ctx->verify_mode;
@@ -199,11 +209,7 @@ SSL *SSL_new(SSL_CTX *ctx)
        s->method=ctx->method;
 
        if (!s->method->ssl_new(s))
-               {
-               SSL_CTX_free(ctx);
-               Free(s);
                goto err;
-               }
 
        s->quiet_shutdown=ctx->quiet_shutdown;
        s->references=1;
@@ -215,6 +221,14 @@ SSL *SSL_new(SSL_CTX *ctx)
 
        return(s);
 err:
+       if (s != NULL)
+               {
+               if (s->cert != NULL)
+                       ssl_cert_free(s->cert);
+               if (s->ctx != NULL)
+                       SSL_CTX_free(s->ctx); /* decrement reference count */
+               Free(s);
+               }
        SSLerr(SSL_F_SSL_NEW,ERR_R_MALLOC_FAILURE);
        return(NULL);
        }
@@ -496,10 +510,10 @@ STACK_OF(X509) *SSL_get_peer_cert_chain(SSL *s)
        {
        STACK_OF(X509) *r;
        
-       if ((s == NULL) || (s->session == NULL) || (s->session->cert == NULL))
+       if ((s == NULL) || (s->session == NULL) || (s->session->sess_cert == NULL))
                r=NULL;
        else
-               r=s->session->cert->cert_chain;
+               r=s->session->sess_cert->cert_chain;
 
        return(r);
        }
@@ -538,18 +552,18 @@ void SSL_copy_session_id(SSL *t,SSL *f)
 int SSL_CTX_check_private_key(SSL_CTX *ctx)
        {
        if (    (ctx == NULL) ||
-               (ctx->default_cert == NULL) ||
-               (ctx->default_cert->key->x509 == NULL))
+               (ctx->cert == NULL) ||
+               (ctx->cert->key->x509 == NULL))
                {
                SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_CERTIFICATE_ASSIGNED);
                return(0);
                }
-       if      (ctx->default_cert->key->privatekey == NULL)
+       if      (ctx->cert->key->privatekey == NULL)
                {
                SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY,SSL_R_NO_PRIVATE_KEY_ASSIGNED);
                return(0);
                }
-       return(X509_check_private_key(ctx->default_cert->key->x509, ctx->default_cert->key->privatekey));
+       return(X509_check_private_key(ctx->cert->key->x509, ctx->cert->key->privatekey));
        }
 
 /* Fix this function so that it takes an optional type parameter */
@@ -578,11 +592,19 @@ int SSL_check_private_key(SSL *ssl)
 
 int SSL_accept(SSL *s)
        {
+       if (s->handshake_func == 0)
+               /* Not properly initialized yet */
+               SSL_set_accept_state(s);
+
        return(s->method->ssl_accept(s));
        }
 
 int SSL_connect(SSL *s)
        {
+       if (s->handshake_func == 0)
+               /* Not properly initialized yet */
+               SSL_set_connect_state(s);
+
        return(s->method->ssl_connect(s));
        }
 
@@ -593,6 +615,12 @@ long SSL_get_default_timeout(SSL *s)
 
 int SSL_read(SSL *s,char *buf,int num)
        {
+       if (s->handshake_func == 0)
+               {
+               SSLerr(SSL_F_SSL_READ, SSL_R_UNINITIALIZED);
+               return -1;
+               }
+
        if (s->shutdown & SSL_RECEIVED_SHUTDOWN)
                {
                s->rwstate=SSL_NOTHING;
@@ -612,6 +640,12 @@ int SSL_peek(SSL *s,char *buf,int num)
 
 int SSL_write(SSL *s,const char *buf,int num)
        {
+       if (s->handshake_func == 0)
+               {
+               SSLerr(SSL_F_SSL_WRITE, SSL_R_UNINITIALIZED);
+               return -1;
+               }
+
        if (s->shutdown & SSL_SENT_SHUTDOWN)
                {
                s->rwstate=SSL_NOTHING;
@@ -623,6 +657,18 @@ int SSL_write(SSL *s,const char *buf,int num)
 
 int SSL_shutdown(SSL *s)
        {
+       /* Note that this function behaves different from what one might
+        * expect.  Return values are 0 for no success (yet),
+        * 1 for success; but calling it once is usually not enough,
+        * even if blocking I/O is used (see ssl3_shutdown).
+        */
+
+       if (s->handshake_func == 0)
+               {
+               SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
+               return -1;
+               }
+
        if ((s != NULL) && !SSL_in_init(s))
                return(s->method->ssl_shutdown(s));
        else
@@ -977,7 +1023,7 @@ SSL_CTX *SSL_CTX_new(SSL_METHOD *meth)
        ret->verify_mode=SSL_VERIFY_NONE;
        ret->verify_depth=-1; /* Don't impose a limit (but x509_lu.c does) */
        ret->default_verify_callback=NULL;
-       if ((ret->default_cert=ssl_cert_new()) == NULL)
+       if ((ret->cert=ssl_cert_new()) == NULL)
                goto err;
 
        ret->default_passwd_callback=NULL;
@@ -1064,8 +1110,8 @@ void SSL_CTX_free(SSL_CTX *a)
                sk_SSL_CIPHER_free(a->cipher_list);
        if (a->cipher_list_by_id != NULL)
                sk_SSL_CIPHER_free(a->cipher_list_by_id);
-       if (a->default_cert != NULL)
-               ssl_cert_free(a->default_cert);
+       if (a->cert != NULL)
+               ssl_cert_free(a->cert);
        if (a->client_CA != NULL)
                sk_X509_NAME_pop_free(a->client_CA,X509_NAME_free);
        if (a->extra_certs != NULL)
@@ -1075,7 +1121,7 @@ void SSL_CTX_free(SSL_CTX *a)
        Free((char *)a);
        }
 
-void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx,int (*cb)())
+void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb)
        {
        ctx->default_passwd_callback=cb;
        }
@@ -1099,10 +1145,7 @@ void SSL_CTX_set_verify_depth(SSL_CTX *ctx,int depth)
        ctx->verify_depth=depth;
        }
 
-/* Need default_cert to check for callbacks, for now (see comment in CERT
-   strucure)
-*/
-void ssl_set_cert_masks(CERT *c,CERT *default_cert,SSL_CIPHER *cipher)
+void ssl_set_cert_masks(CERT *c, SSL_CIPHER *cipher)
        {
        CERT_PKEY *cpk;
        int rsa_enc,rsa_tmp,rsa_sign,dh_tmp,dh_rsa,dh_dsa,dsa_sign;
@@ -1115,15 +1158,15 @@ void ssl_set_cert_masks(CERT *c,CERT *default_cert,SSL_CIPHER *cipher)
        kl=SSL_C_EXPORT_PKEYLENGTH(cipher);
 
 #ifndef NO_RSA
-       rsa_tmp=(c->rsa_tmp != NULL || default_cert->rsa_tmp_cb != NULL);
-       rsa_tmp_export=(default_cert->rsa_tmp_cb != NULL ||
+       rsa_tmp=(c->rsa_tmp != NULL || c->rsa_tmp_cb != NULL);
+       rsa_tmp_export=(c->rsa_tmp_cb != NULL ||
                (rsa_tmp && RSA_size(c->rsa_tmp)*8 <= kl));
 #else
        rsa_tmp=rsa_tmp_export=0;
 #endif
 #ifndef NO_DH
-       dh_tmp=(c->dh_tmp != NULL || default_cert->dh_tmp_cb != NULL);
-       dh_tmp_export=(default_cert->dh_tmp_cb != NULL ||
+       dh_tmp=(c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
+       dh_tmp_export=(c->dh_tmp_cb != NULL ||
                (dh_tmp && DH_size(c->dh_tmp)*8 <= kl));
 #else
        dh_tmp=dh_tmp_export=0;
@@ -1210,7 +1253,7 @@ X509 *ssl_get_server_send_cert(SSL *s)
        int i,export;
 
        c=s->cert;
-       ssl_set_cert_masks(c,s->ctx->default_cert,s->s3->tmp.new_cipher);
+       ssl_set_cert_masks(c, s->s3->tmp.new_cipher);
        alg=s->s3->tmp.new_cipher->algorithms;
        export=SSL_IS_EXPORT(alg);
        mask=export?c->export_mask:c->mask;
@@ -1468,7 +1511,7 @@ char *SSL_get_version(SSL *s)
        }
 
 SSL *SSL_dup(SSL *s)
-        {
+       {
        STACK_OF(X509_NAME) *sk;
        X509_NAME *xn;
         SSL *ret;
@@ -1477,8 +1520,31 @@ SSL *SSL_dup(SSL *s)
        if ((ret=SSL_new(SSL_get_SSL_CTX(s))) == NULL)
            return(NULL);
                          
-       /* This copies version, session-id, SSL_METHOD and 'cert' */
-       SSL_copy_session_id(ret,s);
+       if (s->session != NULL)
+               {
+               /* This copies session-id, SSL_METHOD, sid_ctx, and 'cert' */
+               SSL_copy_session_id(ret,s);
+               }
+       else
+               {
+               /* No session has been established yet, so we have to expect
+                * that s->cert or ret->cert will be changed later --
+                * they should not both point to the same object,
+                * and thus we can't use SSL_copy_session_id. */
+
+               ret->method = s->method;
+               ret->method->ssl_new(ret);
+
+               if (s->cert != NULL)
+                       {
+                       ret->cert = ssl_cert_dup(s->cert);
+                       if (ret->cert == NULL)
+                               goto err;
+                       }
+                               
+               SSL_set_session_id_context(ret,
+                       s->sid_ctx, s->sid_ctx_length);
+               }
 
        SSL_set_read_ahead(ret,SSL_get_read_ahead(s));
        SSL_set_verify(ret,SSL_get_verify_mode(s),
@@ -1554,18 +1620,18 @@ err:
 
 void ssl_clear_cipher_ctx(SSL *s)
        {
-        if (s->enc_read_ctx != NULL)
-                {
-                EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
-                Free(s->enc_read_ctx);
-                s->enc_read_ctx=NULL;
-                }
-        if (s->enc_write_ctx != NULL)
-                {
-                EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
-                Free(s->enc_write_ctx);
-                s->enc_write_ctx=NULL;
-                }
+       if (s->enc_read_ctx != NULL)
+               {
+               EVP_CIPHER_CTX_cleanup(s->enc_read_ctx);
+               Free(s->enc_read_ctx);
+               s->enc_read_ctx=NULL;
+               }
+       if (s->enc_write_ctx != NULL)
+               {
+               EVP_CIPHER_CTX_cleanup(s->enc_write_ctx);
+               Free(s->enc_write_ctx);
+               s->enc_write_ctx=NULL;
+               }
        if (s->expand != NULL)
                {
                COMP_CTX_free(s->expand);
@@ -1704,7 +1770,8 @@ int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
        return(X509_STORE_set_default_paths(ctx->cert_store));
        }
 
-int SSL_CTX_load_verify_locations(SSL_CTX *ctx,char *CAfile,char *CApath)
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
+               const char *CApath)
        {
        return(X509_STORE_load_locations(ctx->cert_store,CAfile,CApath));
        }