#include <stdio.h>
#include <openssl/lhash.h>
#include <openssl/rand.h>
+#ifndef OPENSSL_NO_ENGINE
+#include <openssl/engine.h>
+#endif
#include "ssl_locl.h"
static void SSL_SESSION_list_remove(SSL_CTX *ctx, SSL_SESSION *s);
ss->prev=NULL;
ss->next=NULL;
ss->compress_meth=0;
+#ifndef OPENSSL_NO_TLSEXT
+ ss->tlsext_hostname = NULL;
+#endif
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
return(ss);
}
SSL_SESSION_free(ss);
return(0);
}
+#ifndef OPENSSL_NO_TLSEXT
+ /* If RFC4507 ticket use empty session ID */
+ if (s->tlsext_ticket_expected)
+ {
+ ss->session_id_length = 0;
+ goto sess_id_done;
+ }
+#endif
/* Choose which callback will set the session ID */
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
if(s->generate_session_id)
SSL_SESSION_free(ss);
return(0);
}
+#ifndef OPENSSL_NO_TLSEXT
+ sess_id_done:
+ if (s->tlsext_hostname) {
+ ss->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
+ if (ss->tlsext_hostname == NULL) {
+ SSLerr(SSL_F_SSL_GET_NEW_SESSION, ERR_R_INTERNAL_ERROR);
+ SSL_SESSION_free(ss);
+ return 0;
+ }
+ }
+#endif
}
else
{
return(1);
}
-int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len)
+int ssl_get_prev_session(SSL *s, unsigned char *session_id, int len,
+ const unsigned char *limit)
{
/* This is used only by servers. */
- SSL_SESSION *ret=NULL,data;
+ SSL_SESSION *ret=NULL;
int fatal = 0;
-
- data.ssl_version=s->version;
- data.session_id_length=len;
+#ifndef OPENSSL_NO_TLSEXT
+ int r;
+#endif
+
if (len > SSL_MAX_SSL_SESSION_ID_LENGTH)
goto err;
- memcpy(data.session_id,session_id,len);
-
+#ifndef OPENSSL_NO_TLSEXT
+ r = tls1_process_ticket(s, session_id, len, limit, &ret);
+ if (r == -1)
+ {
+ fatal = 1;
+ goto err;
+ }
+ else if (r == 0 || (!ret && !len))
+ goto err;
+ else if (!ret && !(s->session_ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#else
+ if (len == 0)
+ goto err;
if (!(s->ctx->session_cache_mode & SSL_SESS_CACHE_NO_INTERNAL_LOOKUP))
+#endif
{
+ SSL_SESSION data;
+ data.ssl_version=s->version;
+ data.session_id_length=len;
+ if (len == 0)
+ return 0;
+ memcpy(data.session_id,session_id,len);
CRYPTO_r_lock(CRYPTO_LOCK_SSL_CTX);
ret=(SSL_SESSION *)lh_retrieve(s->ctx->sessions,&data);
if (ret != NULL)
/* 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)
if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
if (ss->peer != NULL) X509_free(ss->peer);
if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
+#ifndef OPENSSL_NO_TLSEXT
+ if (ss->tlsext_hostname != NULL) OPENSSL_free(ss->tlsext_hostname);
+ if (ss->tlsext_tick != NULL) OPENSSL_free(ss->tlsext_tick);
+#endif
OPENSSL_cleanse(ss,sizeof(*ss));
OPENSSL_free(ss);
}
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';
ctx->new_session_cb=cb;
}
-int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx))(struct ssl_st */*ssl*/,SSL_SESSION */*sess*/)
+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)(struct ssl_ctx_st *ctx,SSL_SESSION *sess))
+ void (*cb)(SSL_CTX *ctx,SSL_SESSION *sess))
{
ctx->remove_session_cb=cb;
}
-void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(struct ssl_ctx_st */*ctx*/,SSL_SESSION */*sess*/)
+void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx))(SSL_CTX * ctx,SSL_SESSION *sess)
{
return ctx->remove_session_cb;
}
ctx->get_session_cb=cb;
}
-SSL_SESSION * (*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx))(struct ssl_st */*ssl*/,
- unsigned char */*data*/,int /*len*/,int */*copy*/)
+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;
}
ctx->info_callback=cb;
}
-void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL */*ssl*/,int /*type*/,int /*val*/)
+void (*SSL_CTX_get_info_callback(SSL_CTX *ctx))(const SSL *ssl,int type,int val)
{
return ctx->info_callback;
}
ctx->client_cert_cb=cb;
}
-int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * /*ssl */, X509 **/* x509 */, EVP_PKEY **/*pkey*/)
+int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL * ssl, X509 ** x509 , EVP_PKEY **pkey)
{
return ctx->client_cert_cb;
}
+#ifndef OPENSSL_NO_ENGINE
+int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e)
+ {
+ if (!ENGINE_init(e))
+ {
+ SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, ERR_R_ENGINE_LIB);
+ return 0;
+ }
+ if(!ENGINE_get_ssl_client_cert_function(e))
+ {
+ SSLerr(SSL_F_SSL_CTX_SET_CLIENT_CERT_ENGINE, SSL_R_NO_CLIENT_CERT_METHOD);
+ ENGINE_finish(e);
+ return 0;
+ }
+ ctx->client_cert_engine = e;
+ return 1;
+ }
+#endif
+
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
int (*cb)(SSL *ssl, unsigned char *cookie, unsigned int *cookie_len))
{