stricter session ID context matching
[openssl.git] / ssl / ssl_sess.c
index ffacf94cc7491ea6bb7e1ce0f92f35ec9dbb5bb9..6aba804faad3e0445ca980ebdd3650006a6ca3fa 100644 (file)
  * Hudson (tjh@cryptsoft.com).
  *
  */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
 
 #include <stdio.h>
 #include <openssl/lhash.h>
@@ -177,8 +203,18 @@ SSL_SESSION *SSL_SESSION_new(void)
        ss->compress_meth=0;
 #ifndef OPENSSL_NO_TLSEXT
        ss->tlsext_hostname = NULL; 
+#ifndef OPENSSL_NO_EC
+       ss->tlsext_ecpointformatlist_length = 0;
+       ss->tlsext_ecpointformatlist = NULL;
+       ss->tlsext_ellipticcurvelist_length = 0;
+       ss->tlsext_ellipticcurvelist = NULL;
+#endif
 #endif
        CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
+#ifndef OPENSSL_NO_PSK
+       ss->psk_identity_hint=NULL;
+       ss->psk_identity=NULL;
+#endif
        return(ss);
        }
 
@@ -322,6 +358,32 @@ int ssl_get_new_session(SSL *s, int session)
                                return 0;
                                }
                        }
+#ifndef OPENSSL_NO_EC
+               if (s->tlsext_ecpointformatlist)
+                       {
+                       if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
+                       if ((ss->tlsext_ecpointformatlist = OPENSSL_malloc(s->tlsext_ecpointformatlist_length)) == NULL)
+                               {
+                               SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
+                               SSL_SESSION_free(ss);
+                               return 0;
+                               }
+                       ss->tlsext_ecpointformatlist_length = s->tlsext_ecpointformatlist_length;
+                       memcpy(ss->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist, s->tlsext_ecpointformatlist_length);
+                       }
+               if (s->tlsext_ellipticcurvelist)
+                       {
+                       if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
+                       if ((ss->tlsext_ellipticcurvelist = OPENSSL_malloc(s->tlsext_ellipticcurvelist_length)) == NULL)
+                               {
+                               SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_MALLOC_FAILURE);
+                               SSL_SESSION_free(ss);
+                               return 0;
+                               }
+                       ss->tlsext_ellipticcurvelist_length = s->tlsext_ellipticcurvelist_length;
+                       memcpy(ss->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist, s->tlsext_ellipticcurvelist_length);
+                       }
+#endif
 #endif
                }
        else
@@ -400,33 +462,35 @@ int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
 
        /* Now ret is non-NULL, and we own one of its reference counts. */
 
-       if((s->verify_mode&SSL_VERIFY_PEER)
-          && (!s->sid_ctx_length || ret->sid_ctx_length != s->sid_ctx_length
-              || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length)))
-           {
+       if (ret->sid_ctx_length != s->sid_ctx_length
+           || memcmp(ret->sid_ctx,s->sid_ctx,ret->sid_ctx_length))
+               {
                /* We've found the session named by the client, but we don't
                 * want to use it in this context. */
-               
-               if (s->sid_ctx_length == 0)
-                       {
-                       /* application should have used SSL[_CTX]_set_session_id_context
-                        * -- we could tolerate this and just pretend we never heard
-                        * of this session, but then applications could effectively
-                        * disable the session cache by accident without anyone noticing */
 
-                       SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
-                       fatal = 1;
-                       goto err;
-                       }
-               else
-                       {
 #if 0 /* The client cannot always know when a session is not appropriate,
-          * so we shouldn't generate an error message. */
+       * so we shouldn't generate an error message. */
 
-                       SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+               SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
 #endif
-                       goto err; /* treat like cache miss */
-                       }
+               goto err; /* treat like cache miss */
+               }
+       
+       if((s->verify_mode & SSL_VERIFY_PEER) && s->sid_ctx_length == 0)
+               {
+               /* We can't be sure if this session is being used out of
+                * context, which is especially important for SSL_VERIFY_PEER.
+                * The application should have used SSL[_CTX]_set_session_id_context.
+                *
+                * For this error case, we generate an error instead of treating
+                * the event like a cache miss (otherwise it would be easy for
+                * applications to effectively disable the session cache by
+                * accident without anyone noticing).
+                */
+               
+               SSLerr(SSL_F_SSL_GET_PREV_SESSION,SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
+               fatal = 1;
+               goto err;
                }
 
        if (ret->cipher == NULL)
@@ -614,6 +678,18 @@ void SSL_SESSION_free(SSL_SESSION *ss)
        if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
 #ifndef OPENSSL_NO_TLSEXT
        if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
+#ifndef OPENSSL_NO_EC
+       ss->tlsext_ecpointformatlist_length = 0;
+       if (ss->tlsext_ecpointformatlist != NULL) OPENSSL_free(ss->tlsext_ecpointformatlist);
+       ss->tlsext_ellipticcurvelist_length = 0;
+       if (ss->tlsext_ellipticcurvelist != NULL) OPENSSL_free(ss->tlsext_ellipticcurvelist);
+#endif /* OPENSSL_NO_EC */
+#endif
+#ifndef OPENSSL_NO_PSK
+       if (ss->psk_identity_hint != NULL)
+               OPENSSL_free(ss->psk_identity_hint);
+       if (ss->psk_identity != NULL)
+               OPENSSL_free(ss->psk_identity);
 #endif
        OPENSSL_cleanse(ss,sizeof(*ss));
        OPENSSL_free(ss);
@@ -649,7 +725,7 @@ int SSL_set_session(SSL *s, SSL_SESSION *session)
                 if (s->kssl_ctx && !s->kssl_ctx->client_princ &&
                     session->krb5_client_princ_len > 0)
                 {
-                    s->kssl_ctx->client_princ = (char *)malloc(session->krb5_client_princ_len + 1);
+                    s->kssl_ctx->client_princ = (char *)OPENSSL_malloc(session->krb5_client_princ_len + 1);
                     memcpy(s->kssl_ctx->client_princ,session->krb5_client_princ,
                             session->krb5_client_princ_len);
                     s->kssl_ctx->client_princ[session->krb5_client_princ_len] = '\0';
@@ -834,3 +910,72 @@ static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *s)
                }
        }
 
+void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
+       int (*cb)(struct ssl_st *ssl,SSL_SESSION *sess))
+       {
+       ctx->new_session_cb=cb;
+       }
+
+int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(SSL *ssl, SSL_SESSION *sess)
+       {
+       return ctx->new_session_cb;
+       }
+
+void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
+       void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
+       {
+       ctx->remove_session_cb=cb;
+       }
+
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
+       {
+       return ctx->remove_session_cb;
+       }
+
+void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
+       SSL_SESSION *(*cb)(struct ssl_st *ssl,
+                unsigned char *data,int len,int *copy))
+       {
+       ctx->get_session_cb=cb;
+       }
+
+SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(SSL *ssl,
+                unsigned char *data,int len,int *copy)
+       {
+       return ctx->get_session_cb;
+       }
+
+void SSL_CTX_set_info_callback(SSL_CTX *ctx, 
+       void (*cb)(const SSL *ssl,int type,int val))
+       {
+       ctx->info_callback=cb;
+       }
+
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
+       {
+       return ctx->info_callback;
+       }
+
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
+       int (*cb)(SSL *ssl, X509 **x509, EVP_PKEY **pkey))
+       {
+       ctx->client_cert_cb=cb;
+       }
+
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
+       {
+       return ctx->client_cert_cb;
+       }
+
+void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
+       int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
+       {
+       ctx->app_gen_cookie_cb=cb;
+       }
+
+void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
+       int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int cookie_len))
+       {
+       ctx->app_verify_cookie_cb=cb;
+       }
+