break;
case CURLOPT_SSL_SESSIONID_CACHE:
- data->set.ssl.primary.sessionid = (0 != va_arg(param, long));
+ data->set.ssl.primary.cache_session = (0 != va_arg(param, long));
#ifndef CURL_DISABLE_PROXY
- data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid;
+ data->set.proxy_ssl.primary.cache_session =
+ data->set.ssl.primary.cache_session;
#endif
break;
BIT(verifypeer); /* set TRUE if this is desired */
BIT(verifyhost); /* set TRUE if CN/SAN must match hostname */
BIT(verifystatus); /* set TRUE if certificate status must be checked */
- BIT(sessionid); /* cache session IDs or not */
+ BIT(cache_session); /* cache session or not */
};
struct ssl_config_data {
backend->x509.verifyhost = verifyhost;
br_ssl_engine_set_x509(&backend->ctx.eng, &backend->x509.vtable);
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
void *session;
CURL_TRC_CF(data, cf, "connect_step1, check session cache");
proto? strlen(proto) : 0);
}
- if(ssl_config->primary.sessionid) {
- bool incache;
- void *oldsession;
+ if(ssl_config->primary.cache_session) {
br_ssl_session_parameters *session;
session = malloc(sizeof(*session));
return CURLE_OUT_OF_MEMORY;
br_ssl_engine_get_session_parameters(&backend->ctx.eng, session);
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &oldsession, NULL));
- if(incache)
- Curl_ssl_delsessionid(data, oldsession);
-
- ret = Curl_ssl_addsessionid(cf, data, &connssl->peer, session, 0,
- bearssl_session_free);
+ ret = Curl_ssl_set_sessionid(cf, data, &connssl->peer, session, 0,
+ bearssl_session_free);
Curl_ssl_sessionid_unlock(data);
if(ret)
return ret;
struct ssl_connect_data *connssl = cf->ctx;
CURLcode result = CURLE_OK;
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
/* we always unconditionally get the session id here, as even if we
already got it from the cache and asked to use it in the connection, it
might've been rejected and then a new one is in use now and we need to
return CURLE_OUT_OF_MEMORY;
}
else {
- bool incache;
- void *ssl_sessionid;
-
/* extract session ID to the allocated buffer */
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
CURL_TRC_CF(data, cf, "get session id (len=%zu) and store in cache",
connect_idsize);
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &ssl_sessionid, NULL));
- if(incache) {
- /* there was one before in the cache, so instead of risking that the
- previous one was rejected, we just kill that and store the new */
- Curl_ssl_delsessionid(data, ssl_sessionid);
- }
-
/* store this session id, takes ownership */
- result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
- connect_sessionid, connect_idsize,
- gtls_sessionid_free);
+ result = Curl_ssl_set_sessionid(cf, data, &connssl->peer,
+ connect_sessionid, connect_idsize,
+ gtls_sessionid_free);
Curl_ssl_sessionid_unlock(data);
}
}
/* This might be a reconnect, so we check for a session ID in the cache
to speed up things */
- if(conn_config->sessionid) {
+ if(conn_config->cache_session) {
void *ssl_sessionid;
size_t ssl_idsize;
#endif
/* Check if there is a cached ID we can/should use here! */
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
void *old_session = NULL;
Curl_ssl_sessionid_lock(data);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
int ret;
mbedtls_ssl_session *our_ssl_sessionid;
- void *old_ssl_sessionid = NULL;
our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session));
if(!our_ssl_sessionid)
/* If there is already a matching session in the cache, delete it */
Curl_ssl_sessionid_lock(data);
- if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &old_ssl_sessionid, NULL))
- Curl_ssl_delsessionid(data, old_ssl_sessionid);
-
- retcode = Curl_ssl_addsessionid(cf, data, &connssl->peer,
- our_ssl_sessionid, 0,
- mbedtls_session_free);
+ retcode = Curl_ssl_set_sessionid(cf, data, &connssl->peer,
+ our_ssl_sessionid, 0,
+ mbedtls_session_free);
Curl_ssl_sessionid_unlock(data);
if(retcode)
return retcode;
SSL_SESSION *session)
{
const struct ssl_config_data *config;
- bool isproxy;
- bool added = FALSE;
+ CURLcode result = CURLE_OK;
if(!cf || !data)
goto out;
- isproxy = Curl_ssl_cf_is_proxy(cf);
-
config = Curl_ssl_cf_get_config(cf, data);
- if(config->primary.sessionid) {
- bool incache;
- void *old_session = NULL;
+ if(config->primary.cache_session) {
Curl_ssl_sessionid_lock(data);
- if(isproxy)
- incache = FALSE;
- else
- incache = !(Curl_ssl_getsessionid(cf, data, peer,
- &old_session, NULL));
- if(incache && (old_session != session)) {
- infof(data, "old SSL session ID is stale, removing");
- Curl_ssl_delsessionid(data, old_session);
- incache = FALSE;
- }
-
- if(!incache) {
- added = TRUE;
- Curl_ssl_addsessionid(cf, data, peer, session, 0, ossl_session_free);
- }
+ result = Curl_ssl_set_sessionid(cf, data, peer, session, 0,
+ ossl_session_free);
+ session = NULL; /* call has taken ownership */
Curl_ssl_sessionid_unlock(data);
}
out:
- if(!added)
+ if(session)
ossl_session_free(session, 0);
- return CURLE_OK;
+ return result;
}
/* The "new session" callback must return zero if the session can be removed
#endif
octx->reused_session = FALSE;
- if(ssl_config->primary.sessionid && transport == TRNSPRT_TCP) {
+ if(ssl_config->primary.cache_session && transport == TRNSPRT_TCP) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, peer, &ssl_sessionid, NULL)) {
/* we got a session id, use it! */
backend->cred = NULL;
/* check for an existing reusable credential handle */
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
Curl_ssl_sessionid_lock(data);
if(!Curl_ssl_getsessionid(cf, data, &connssl->peer,
(void **)&old_cred, NULL)) {
#endif
/* save the current session data for possible reuse */
- if(ssl_config->primary.sessionid) {
- bool incache;
- struct Curl_schannel_cred *old_cred = NULL;
-
+ if(ssl_config->primary.cache_session) {
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
- (void **)&old_cred, NULL));
- if(incache) {
- if(old_cred != backend->cred) {
- DEBUGF(infof(data,
- "schannel: old credential handle is stale, removing"));
- /* we are not taking old_cred ownership here, no refcount++ is
- needed */
- Curl_ssl_delsessionid(data, (void *)old_cred);
- incache = FALSE;
- }
- }
- if(!incache) {
- /* Up ref count since call takes ownership */
- backend->cred->refcount++;
- result = Curl_ssl_addsessionid(cf, data, &connssl->peer, backend->cred,
- sizeof(struct Curl_schannel_cred),
- schannel_session_free);
- if(result) {
- Curl_ssl_sessionid_unlock(data);
- return result;
- }
- }
+ /* Up ref count since call takes ownership */
+ backend->cred->refcount++;
+ result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, backend->cred,
+ sizeof(struct Curl_schannel_cred),
+ schannel_session_free);
Curl_ssl_sessionid_unlock(data);
+ if(result)
+ return result;
}
if(data->set.ssl.certinfo) {
#endif /* CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7 */
/* Check if there is a cached ID we can/should use here! */
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
char *ssl_sessionid;
size_t ssl_sessionid_len;
return CURLE_SSL_CONNECT_ERROR;
}
- result = Curl_ssl_addsessionid(cf, data, &connssl->peer, ssl_sessionid,
- ssl_sessionid_len,
- sectransp_session_free);
+ result = Curl_ssl_set_sessionid(cf, data, &connssl->peer, ssl_sessionid,
+ ssl_sessionid_len,
+ sectransp_session_free);
Curl_ssl_sessionid_unlock(data);
if(result)
return result;
*/
data->set.ssl.primary.verifypeer = TRUE;
data->set.ssl.primary.verifyhost = TRUE;
- data->set.ssl.primary.sessionid = TRUE; /* session ID caching by default */
+ data->set.ssl.primary.cache_session = TRUE; /* caching by default */
#ifndef CURL_DISABLE_PROXY
data->set.proxy_ssl = data->set.ssl;
#endif
dest->verifypeer = source->verifypeer;
dest->verifyhost = source->verifyhost;
dest->verifystatus = source->verifystatus;
- dest->sessionid = source->sessionid;
+ dest->cache_session = source->cache_session;
dest->ssl_options = source->ssl_options;
CLONE_BLOB(cert_blob);
if(!ssl_config)
return TRUE;
- DEBUGASSERT(ssl_config->primary.sessionid);
+ DEBUGASSERT(ssl_config->primary.cache_session);
- if(!ssl_config->primary.sessionid || !data->state.session)
+ if(!ssl_config->primary.cache_session || !data->state.session)
/* session ID reuse is disabled or the session cache has not been
setup */
return TRUE;
}
}
-/*
- * Store session id in the session cache. The ID passed on to this function
- * must already have been extracted and allocated the proper way for the SSL
- * layer. Curl_XXXX_session_free() will be called to free/kill the session ID
- * later on.
- */
-CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct ssl_peer *peer,
- void *ssl_sessionid,
- size_t idsize,
- Curl_ssl_sessionid_dtor *sessionid_free_cb)
+CURLcode Curl_ssl_set_sessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const struct ssl_peer *peer,
+ void *ssl_sessionid,
+ size_t idsize,
+ Curl_ssl_sessionid_dtor *sessionid_free_cb)
{
struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data);
struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf);
char *clone_conn_to_host = NULL;
int conn_to_port;
long *general_age;
+ void *old_sessionid;
+ size_t old_size;
CURLcode result = CURLE_OUT_OF_MEMORY;
DEBUGASSERT(ssl_sessionid);
return CURLE_OK;
}
+ if(!Curl_ssl_getsessionid(cf, data, peer, &old_sessionid, &old_size)) {
+ if((old_size == idsize) &&
+ ((old_sessionid == ssl_sessionid) ||
+ (idsize && !memcmp(old_sessionid, ssl_sessionid, idsize)))) {
+ /* the very same */
+ sessionid_free_cb(ssl_sessionid, idsize);
+ return CURLE_OK;
+ }
+ Curl_ssl_delsessionid(data, old_sessionid);
+ }
+
store = &data->state.session[0];
oldest_age = data->state.session[0].age; /* zero if unused */
- DEBUGASSERT(ssl_config->primary.sessionid);
+ DEBUGASSERT(ssl_config->primary.cache_session);
(void)ssl_config;
clone_host = strdup(peer->hostname);
const struct ssl_peer *peer,
void **ssl_sessionid,
size_t *idsize); /* set 0 if unknown */
-/* add a new session ID
+
+/* Set a TLS session ID for `peer`. Replaces an existing session ID if
+ * not already the very same.
* Sessionid mutex must be locked (see Curl_ssl_sessionid_lock).
+ * Call takes ownership of `ssl_sessionid`, using `sessionid_free_cb`
+ * to deallocate it. Is called in all outcomes, either right away or
+ * later when the session cache is cleaned up.
* Caller must ensure that it has properly shared ownership of this sessionid
* object with cache (e.g. incrementing refcount on success)
- * Call takes ownership of `ssl_sessionid`, using `sessionid_free_cb`
- * to destroy it in case of failure or later removal.
*/
-CURLcode Curl_ssl_addsessionid(struct Curl_cfilter *cf,
- struct Curl_easy *data,
- const struct ssl_peer *peer,
- void *ssl_sessionid,
- size_t idsize,
- Curl_ssl_sessionid_dtor *sessionid_free_cb);
+CURLcode Curl_ssl_set_sessionid(struct Curl_cfilter *cf,
+ struct Curl_easy *data,
+ const struct ssl_peer *peer,
+ void *sessionid,
+ size_t sessionid_size,
+ Curl_ssl_sessionid_dtor *sessionid_free_cb);
#include "openssl.h" /* OpenSSL versions */
#include "gtls.h" /* GnuTLS versions */
#endif /* HAVE_SECURE_RENEGOTIATION */
/* Check if there is a cached ID we can/should use here! */
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
void *ssl_sessionid = NULL;
Curl_ssl_sessionid_lock(data);
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
DEBUGASSERT(backend);
- if(ssl_config->primary.sessionid) {
+ if(ssl_config->primary.cache_session) {
/* wolfSSL_get1_session allocates memory that has to be freed. */
WOLFSSL_SESSION *our_ssl_sessionid = wolfSSL_get1_session(backend->handle);
if(our_ssl_sessionid) {
- void *old_ssl_sessionid = NULL;
- bool incache;
Curl_ssl_sessionid_lock(data);
- incache = !(Curl_ssl_getsessionid(cf, data, &connssl->peer,
- &old_ssl_sessionid, NULL));
- if(incache) {
- Curl_ssl_delsessionid(data, old_ssl_sessionid);
- }
-
/* call takes ownership of `our_ssl_sessionid` */
- result = Curl_ssl_addsessionid(cf, data, &connssl->peer,
- our_ssl_sessionid, 0,
- wolfssl_session_free);
+ result = Curl_ssl_set_sessionid(cf, data, &connssl->peer,
+ our_ssl_sessionid, 0,
+ wolfssl_session_free);
Curl_ssl_sessionid_unlock(data);
if(result) {
failf(data, "failed to store ssl session");