Commit b92ead1b authored by agl@chromium.org's avatar agl@chromium.org

net: lookup OCSP cache function with dlsym.

Weak symbols are either broken or they don't work the way that we need.
Either way, the current weak symbol based scheme is causing
runtime-linker aborts on systems without NSS 3.12.6.

This change switches to using dlsym to lookup the symbol at runtime.

BUG=69345
TEST=Run chrome on systems with libnss.so < 3.12.6

http://codereview.chromium.org/6250008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@71796 0039d316-1c4b-4281-b951-d872f2087c98
parent 24b55c5a
...@@ -60,12 +60,17 @@ ...@@ -60,12 +60,17 @@
#include <sslerr.h> #include <sslerr.h>
#include <sslproto.h> #include <sslproto.h>
#if defined(OS_LINUX) || defined(USE_SYSTEM_SSL)
#include <dlfcn.h>
#endif
#include <limits> #include <limits>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/metrics/histogram.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/nss_util.h" #include "base/nss_util.h"
#include "base/singleton.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "base/stringprintf.h" #include "base/stringprintf.h"
...@@ -92,9 +97,6 @@ ...@@ -92,9 +97,6 @@
#include "net/socket/ssl_error_params.h" #include "net/socket/ssl_error_params.h"
#include "net/socket/ssl_host_info.h" #include "net/socket/ssl_host_info.h"
#if defined(USE_SYSTEM_SSL)
#include <dlfcn.h>
#endif
#if defined(OS_WIN) #if defined(OS_WIN)
#include <windows.h> #include <windows.h>
#include <wincrypt.h> #include <wincrypt.h>
...@@ -112,26 +114,54 @@ static const int kRecvBufferSize = 4096; ...@@ -112,26 +114,54 @@ static const int kRecvBufferSize = 4096;
// and some will time out such sockets quite aggressively. // and some will time out such sockets quite aggressively.
static const int kCorkTimeoutMs = 200; static const int kCorkTimeoutMs = 200;
typedef SECStatus
(*CacheOCSPResponseFromSideChannelFunction)(
CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time,
SECItem *encodedResponse, void *pwArg);
#if defined(OS_LINUX) #if defined(OS_LINUX)
// On Linux, we dynamically link against the system version of libnss3.so. In // On Linux, we dynamically link against the system version of libnss3.so. In
// order to continue working on systems without up-to-date versions of NSS we // order to continue working on systems without up-to-date versions of NSS we
// declare CERT_CacheOCSPResponseFromSideChannel to be a weak symbol. If, at // lookup CERT_CacheOCSPResponseFromSideChannel with dlsym.
// run time, we find that the symbol didn't resolve then we can avoid calling
// the function. // RuntimeLibNSSFunctionPointers is a singleton which caches the results of any
extern SECStatus // runtime symbol resolution that we need.
CERT_CacheOCSPResponseFromSideChannel( class RuntimeLibNSSFunctionPointers {
CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, public:
SECItem *encodedResponse, void *pwArg) __attribute__((weak)); CacheOCSPResponseFromSideChannelFunction
GetCacheOCSPResponseFromSideChannelFunction() {
return cache_ocsp_response_from_side_channel_;
}
static RuntimeLibNSSFunctionPointers* GetInstance() {
return Singleton<RuntimeLibNSSFunctionPointers>::get();
}
private:
friend struct DefaultSingletonTraits<RuntimeLibNSSFunctionPointers>;
static bool HaveCacheOCSPResponseFromSideChannelFunction() { RuntimeLibNSSFunctionPointers() {
return CERT_CacheOCSPResponseFromSideChannel != NULL; cache_ocsp_response_from_side_channel_ =
(CacheOCSPResponseFromSideChannelFunction)
dlsym(RTLD_DEFAULT, "CERT_CacheOCSPResponseFromSideChannel");
}
CacheOCSPResponseFromSideChannelFunction
cache_ocsp_response_from_side_channel_;
};
static CacheOCSPResponseFromSideChannelFunction
GetCacheOCSPResponseFromSideChannelFunction() {
return RuntimeLibNSSFunctionPointers::GetInstance()
->GetCacheOCSPResponseFromSideChannelFunction();
} }
#else #else
// On other platforms we use the system's certificate validation functions. // On other platforms we use the system's certificate validation functions.
// Thus we need, in the future, to plumb the OCSP response into those system // Thus we need, in the future, to plumb the OCSP response into those system
// functions. Until then, we act as if we didn't support OCSP stapling. // functions. Until then, we act as if we didn't support OCSP stapling.
static bool HaveCacheOCSPResponseFromSideChannelFunction() { static CacheOCSPResponseFromSideChannelFunction
return false; GetCacheOCSPResponseFromSideChannelFunction() {
return NULL;
} }
#endif #endif
...@@ -659,7 +689,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() { ...@@ -659,7 +689,7 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
#endif #endif
#ifdef SSL_ENABLE_OCSP_STAPLING #ifdef SSL_ENABLE_OCSP_STAPLING
if (HaveCacheOCSPResponseFromSideChannelFunction() && if (GetCacheOCSPResponseFromSideChannelFunction() &&
!ssl_config_.snap_start_enabled) { !ssl_config_.snap_start_enabled) {
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE);
if (rv != SECSuccess) if (rv != SECSuccess)
...@@ -1990,11 +2020,12 @@ int SSLClientSocketNSS::DoHandshake() { ...@@ -1990,11 +2020,12 @@ int SSLClientSocketNSS::DoHandshake() {
} }
#if defined(SSL_ENABLE_OCSP_STAPLING) #if defined(SSL_ENABLE_OCSP_STAPLING)
const CacheOCSPResponseFromSideChannelFunction cache_ocsp_response =
GetCacheOCSPResponseFromSideChannelFunction();
// TODO: we need to be able to plumb an OCSP response into the system // TODO: we need to be able to plumb an OCSP response into the system
// libraries. When we do, HaveCacheOCSPResponseFromSideChannelFunction // libraries. When we do, GetOCSPResponseFromSideChannelFunction
// needs to be updated for those platforms. // needs to be updated for those platforms.
if (!predicted_cert_chain_correct_ && if (!predicted_cert_chain_correct_ && cache_ocsp_response) {
HaveCacheOCSPResponseFromSideChannelFunction()) {
unsigned int len = 0; unsigned int len = 0;
SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len); SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len);
if (len) { if (len) {
...@@ -2008,7 +2039,7 @@ int SSLClientSocketNSS::DoHandshake() { ...@@ -2008,7 +2039,7 @@ int SSLClientSocketNSS::DoHandshake() {
ocsp_response_item.data = ocsp_response.get(); ocsp_response_item.data = ocsp_response.get();
ocsp_response_item.len = len; ocsp_response_item.len = len;
CERT_CacheOCSPResponseFromSideChannel( cache_ocsp_response(
CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(), CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(),
&ocsp_response_item, NULL); &ocsp_response_item, NULL);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment