2121
2222#include " P_OCSPStapling.h"
2323
24+ #include < mutex>
25+ #include < shared_mutex>
26+
2427#include < openssl/ssl.h>
2528#include < openssl/x509v3.h>
2629#include < openssl/asn1.h>
@@ -284,12 +287,15 @@ struct certinfo {
284287 char *uri; // Responder details
285288 char *certname;
286289 char *user_agent;
287- ink_mutex stapling_mutex;
288- unsigned char resp_der[MAX_STAPLING_DER ];
289- unsigned int resp_derlen;
290290 bool is_prefetched;
291- bool is_expire;
292- time_t expire_time;
291+
292+ // OCSP response data, protected by resp_mutex.
293+ // Readers take a shared lock; the updater takes an exclusive lock.
294+ unsigned char resp_der[MAX_STAPLING_DER ];
295+ unsigned int resp_derlen;
296+ bool is_expire;
297+ time_t expire_time;
298+ mutable std::shared_mutex resp_mutex;
293299};
294300
295301class HTTPRequest : public Continuation
@@ -737,15 +743,20 @@ certinfo_map_free(void * /*parent*/, void *ptr, CRYPTO_EX_DATA * /*ad*/, int /*i
737743
738744 for (auto &iter : *map) {
739745 certinfo *cinf = iter.second ;
746+ if (cinf->cid ) {
747+ TS_OCSP_CERTID_free (cinf->cid );
748+ }
740749 if (cinf->uri ) {
741750 OPENSSL_free (cinf->uri );
742751 }
743752
744753 ats_free (cinf->certname );
745754 ats_free (cinf->user_agent );
746755
747- ink_mutex_destroy (&cinf->stapling_mutex );
748- OPENSSL_free (cinf);
756+ #ifdef OPENSSL_IS_BORINGSSL
757+ X509_free (iter.first );
758+ #endif
759+ delete cinf;
749760 }
750761 delete map;
751762}
@@ -831,12 +842,13 @@ stapling_cache_response(TS_OCSP_RESPONSE *rsp, certinfo *cinf)
831842 return false ;
832843 }
833844
834- ink_mutex_acquire (&cinf->stapling_mutex );
835- memcpy (cinf->resp_der , resp_der, resp_derlen);
836- cinf->resp_derlen = resp_derlen;
837- cinf->is_expire = false ;
838- cinf->expire_time = time (nullptr ) + SSLConfigParams::ssl_ocsp_cache_timeout;
839- ink_mutex_release (&cinf->stapling_mutex );
845+ {
846+ std::lock_guard lock (cinf->resp_mutex );
847+ memcpy (cinf->resp_der , resp_der, resp_derlen);
848+ cinf->resp_derlen = resp_derlen;
849+ cinf->is_expire = false ;
850+ cinf->expire_time = time (nullptr ) + SSLConfigParams::ssl_ocsp_cache_timeout;
851+ }
840852
841853 Dbg (dbg_ctl_ssl_ocsp, " stapling_cache_response: success to cache response" );
842854 return true ;
@@ -860,15 +872,12 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
860872 return false ;
861873 }
862874
875+ bool map_is_new = false ;
863876 if (!map) {
864- map = new certinfo_map;
865- }
866- certinfo *cinf = static_cast <certinfo *>(OPENSSL_malloc (sizeof (certinfo)));
867- if (!cinf) {
868- Error (" error allocating memory for %s" , certname);
869- delete map;
870- return false ;
877+ map = new certinfo_map;
878+ map_is_new = true ;
871879 }
880+ certinfo *cinf = new certinfo ();
872881
873882 // Initialize certinfo
874883 cinf->cid = nullptr ;
@@ -877,8 +886,7 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
877886 if (SSLConfigParams::ssl_ocsp_user_agent != nullptr ) {
878887 cinf->user_agent = ats_strdup (SSLConfigParams::ssl_ocsp_user_agent);
879888 }
880- cinf->resp_derlen = 0 ;
881- ink_mutex_init (&cinf->stapling_mutex );
889+ cinf->resp_derlen = 0 ;
882890 cinf->is_prefetched = rsp_file ? true : false ;
883891 cinf->is_expire = true ;
884892 cinf->expire_time = 0 ;
@@ -963,10 +971,11 @@ ssl_stapling_init_cert(SSL_CTX *ctx, X509 *cert, const char *certname, const cha
963971 ats_free (cinf->certname );
964972 ats_free (cinf->user_agent );
965973
966- if (cinf) {
967- OPENSSL_free (cinf);
968- }
969- if (map) {
974+ delete cinf;
975+
976+ // Only tear down the map if this call created it; an existing map is still
977+ // owned by the SSL_CTX.
978+ if (map_is_new) {
970979 delete map;
971980 }
972981
@@ -1327,20 +1336,21 @@ ocsp_update()
13271336 if (map) {
13281337 // Walk over all certs associated with this CTX
13291338 for (auto &iter : *map) {
1330- cinf = iter.second ;
1331- ink_mutex_acquire (&cinf->stapling_mutex );
1339+ cinf = iter.second ;
13321340 current_time = time (nullptr );
1333- if (cinf->resp_derlen == 0 || cinf->is_expire || cinf->expire_time < current_time) {
1334- ink_mutex_release (&cinf->stapling_mutex );
1341+ bool needs_refresh;
1342+ {
1343+ std::shared_lock lock (cinf->resp_mutex );
1344+ needs_refresh = cinf->resp_derlen == 0 || cinf->is_expire || cinf->expire_time < current_time;
1345+ }
1346+ if (needs_refresh) {
13351347 if (stapling_refresh_response (cinf, &resp)) {
13361348 Dbg (dbg_ctl_ssl_ocsp, " Successfully refreshed OCSP for %s certificate. url=%s" , cinf->certname , cinf->uri );
13371349 Metrics::Counter::increment (ssl_rsb.ocsp_refreshed_cert );
13381350 } else {
13391351 Error (" Failed to refresh OCSP for %s certificate. url=%s" , cinf->certname , cinf->uri );
13401352 Metrics::Counter::increment (ssl_rsb.ocsp_refresh_cert_failure );
13411353 }
1342- } else {
1343- ink_mutex_release (&cinf->stapling_mutex );
13441354 }
13451355 }
13461356 }
@@ -1402,24 +1412,31 @@ ssl_callback_ocsp_stapling(SSL *ssl, void *)
14021412 return SSL_TLSEXT_ERR_NOACK ;
14031413 }
14041414
1405- ink_mutex_acquire (&cinf->stapling_mutex );
1406- time_t current_time = time (nullptr );
1407- if ((cinf->resp_derlen == 0 || cinf->is_expire ) || (cinf->expire_time < current_time && !cinf->is_prefetched )) {
1408- ink_mutex_release (&cinf->stapling_mutex );
1409- Error (" ssl_callback_ocsp_stapling: failed to get certificate status for %s" , cinf->certname );
1410- return SSL_TLSEXT_ERR_NOACK ;
1411- } else {
1412- unsigned char *p = static_cast <unsigned char *>(OPENSSL_malloc (cinf->resp_derlen ));
1413- if (p == nullptr ) {
1414- ink_mutex_release (&cinf->stapling_mutex );
1415- Dbg (dbg_ctl_ssl_ocsp, " ssl_callback_ocsp_stapling: failed to allocate memory for %s" , cinf->certname );
1415+ unsigned char resp_copy[MAX_STAPLING_DER ];
1416+ unsigned int resp_copylen;
1417+
1418+ {
1419+ std::shared_lock lock (cinf->resp_mutex );
1420+
1421+ time_t current_time = time (nullptr );
1422+ if (cinf->resp_derlen == 0 || cinf->is_expire || (cinf->expire_time < current_time && !cinf->is_prefetched )) {
1423+ Error (" ssl_callback_ocsp_stapling: failed to get certificate status for %s" , cinf->certname );
14161424 return SSL_TLSEXT_ERR_NOACK ;
14171425 }
1418- memcpy (p, cinf->resp_der , cinf->resp_derlen );
1419- ink_mutex_release (&cinf->stapling_mutex );
1420- SSL_set_tlsext_status_ocsp_resp (ssl, p, cinf->resp_derlen );
1421- Dbg (dbg_ctl_ssl_ocsp, " ssl_callback_ocsp_stapling: successfully got certificate status for %s" , cinf->certname );
1422- Dbg (dbg_ctl_ssl_ocsp, " is_prefetched:%d uri:%s" , cinf->is_prefetched , cinf->uri );
1423- return SSL_TLSEXT_ERR_OK ;
1426+
1427+ resp_copylen = cinf->resp_derlen ;
1428+ memcpy (resp_copy, cinf->resp_der , resp_copylen);
1429+ }
1430+
1431+ unsigned char *p = static_cast <unsigned char *>(OPENSSL_malloc (resp_copylen));
1432+ if (p == nullptr ) {
1433+ Dbg (dbg_ctl_ssl_ocsp, " ssl_callback_ocsp_stapling: failed to allocate memory for %s" , cinf->certname );
1434+ return SSL_TLSEXT_ERR_NOACK ;
14241435 }
1436+ memcpy (p, resp_copy, resp_copylen);
1437+ SSL_set_tlsext_status_ocsp_resp (ssl, p, resp_copylen);
1438+
1439+ Dbg (dbg_ctl_ssl_ocsp, " ssl_callback_ocsp_stapling: successfully got certificate status for %s" , cinf->certname );
1440+ Dbg (dbg_ctl_ssl_ocsp, " is_prefetched:%d uri:%s" , cinf->is_prefetched , cinf->uri );
1441+ return SSL_TLSEXT_ERR_OK ;
14251442}
0 commit comments