diff --git a/lib/easy.c b/lib/easy.c index b2096fb8d3..a472d6ddc5 100644 --- a/lib/easy.c +++ b/lib/easy.c @@ -1339,6 +1339,8 @@ CURLcode curl_easy_ssls_import(CURL *curl, const char *session_key, struct Curl_easy *data = curl; if(!GOOD_EASY_HANDLE(data)) return CURLE_BAD_FUNCTION_ARGUMENT; + if(Curl_is_in_callback(data) || Curl_ssl_scache_is_locked(data)) + return CURLE_RECURSIVE_API_CALL; return Curl_ssl_session_import(data, session_key, shmac, shmac_len, sdata, sdata_len); #else @@ -1360,6 +1362,8 @@ CURLcode curl_easy_ssls_export(CURL *curl, struct Curl_easy *data = curl; if(!GOOD_EASY_HANDLE(data)) return CURLE_BAD_FUNCTION_ARGUMENT; + if(Curl_is_in_callback(data) || Curl_ssl_scache_is_locked(data)) + return CURLE_RECURSIVE_API_CALL; return Curl_ssl_session_export(data, export_fn, userptr); #else (void)curl; diff --git a/lib/vtls/vtls_scache.c b/lib/vtls/vtls_scache.c index 505b4fe5ec..59fa256bc3 100644 --- a/lib/vtls/vtls_scache.c +++ b/lib/vtls/vtls_scache.c @@ -301,6 +301,7 @@ struct Curl_ssl_scache { size_t peer_count; int default_lifetime_secs; long age; + BIT(is_locked); }; static struct Curl_ssl_scache *cf_ssl_scache_get(struct Curl_easy *data) @@ -583,15 +584,26 @@ bool Curl_ssl_scache_use(struct Curl_cfilter *cf, struct Curl_easy *data) /* Lock shared SSL session data */ void Curl_ssl_scache_lock(struct Curl_easy *data) { - if(CURL_SHARE_ssl_scache(data)) - Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_ACCESS_SINGLE); + struct Curl_ssl_scache *scache = cf_ssl_scache_get(data); + if(scache) { + if(CURL_SHARE_ssl_scache(data)) + Curl_share_lock(data, CURL_LOCK_DATA_SSL_SESSION, + CURL_LOCK_ACCESS_SINGLE); + DEBUGASSERT(!scache->is_locked); + scache->is_locked = TRUE; + } } /* Unlock shared SSL session data */ void Curl_ssl_scache_unlock(struct Curl_easy *data) { - if(CURL_SHARE_ssl_scache(data)) - Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); + struct Curl_ssl_scache *scache = cf_ssl_scache_get(data); + if(scache) { + DEBUGASSERT(scache->is_locked); + scache->is_locked = FALSE; + if(CURL_SHARE_ssl_scache(data)) + Curl_share_unlock(data, CURL_LOCK_DATA_SSL_SESSION); + } } static bool cf_ssl_scache_match_auth(struct Curl_ssl_scache_peer *peer, @@ -1000,6 +1012,12 @@ void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf, #define CURL_SSL_TICKET_MAX (16 * 1024) +bool Curl_ssl_scache_is_locked(struct Curl_easy *data) +{ + struct Curl_ssl_scache *scache = cf_ssl_scache_get(data); + return scache && scache->is_locked; +} + static CURLcode cf_ssl_scache_peer_set_hmac(struct Curl_ssl_scache_peer *peer) { CURLcode result; @@ -1082,7 +1100,6 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data, struct Curl_ssl_scache *scache = cf_ssl_scache_get(data); struct Curl_ssl_scache_peer *peer = NULL; struct Curl_ssl_session *s = NULL; - bool locked = FALSE; CURLcode result; if(!scache) { @@ -1099,7 +1116,6 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data, goto out; Curl_ssl_scache_lock(data); - locked = TRUE; if(ssl_peer_key) { result = cf_ssl_add_peer(data, scache, ssl_peer_key, NULL, &peer); @@ -1140,7 +1156,7 @@ CURLcode Curl_ssl_session_import(struct Curl_easy *data, } out: - if(locked) + if(scache && scache->is_locked) Curl_ssl_scache_unlock(data); Curl_ssl_session_destroy(s); return result; @@ -1163,8 +1179,6 @@ CURLcode Curl_ssl_session_export(struct Curl_easy *data, if(!export_fn) return CURLE_BAD_FUNCTION_ARGUMENT; - if(!scache) - return CURLE_OK; Curl_ssl_scache_lock(data); diff --git a/lib/vtls/vtls_scache.h b/lib/vtls/vtls_scache.h index 916e4b505b..181c2ec333 100644 --- a/lib/vtls/vtls_scache.h +++ b/lib/vtls/vtls_scache.h @@ -199,6 +199,8 @@ void Curl_ssl_scache_remove_all(struct Curl_cfilter *cf, #ifdef USE_SSLS_EXPORT +bool Curl_ssl_scache_is_locked(struct Curl_easy *data); + CURLcode Curl_ssl_session_import(struct Curl_easy *data, const char *ssl_peer_key, const unsigned char *shmac, size_t shmac_len,