diff options
Diffstat (limited to 'net/socket/ssl_client_socket_nss.cc')
-rw-r--r-- | net/socket/ssl_client_socket_nss.cc | 61 |
1 files changed, 60 insertions, 1 deletions
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc index 333fe67..b12c59d 100644 --- a/net/socket/ssl_client_socket_nss.cc +++ b/net/socket/ssl_client_socket_nss.cc @@ -52,6 +52,7 @@ #include <keyhi.h> #include <nspr.h> #include <nss.h> +#include <ocsp.h> #include <pk11pub.h> #include <secerr.h> #include <sechash.h> @@ -68,7 +69,7 @@ #include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/stringprintf.h" -#include "base/thread_restrictions.h" +#include "base/threading/thread_restrictions.h" #include "base/values.h" #include "net/base/address_list.h" #include "net/base/cert_status_flags.h" @@ -111,6 +112,29 @@ static const int kRecvBufferSize = 4096; // and some will time out such sockets quite aggressively. static const int kCorkTimeoutMs = 200; +#if defined(OS_LINUX) +// 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 +// declare CERT_CacheOCSPResponseFromSideChannel to be a weak symbol. If, at +// run time, we find that the symbol didn't resolve then we can avoid calling +// the function. +extern SECStatus +CERT_CacheOCSPResponseFromSideChannel( + CERTCertDBHandle *handle, CERTCertificate *cert, PRTime time, + SECItem *encodedResponse, void *pwArg) __attribute__((weak)); + +static bool HaveCacheOCSPResponseFromSideChannelFunction() { + return CERT_CacheOCSPResponseFromSideChannel != NULL; +} +#else +// 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 +// functions. Until then, we act as if we didn't support OCSP stapling. +static bool HaveCacheOCSPResponseFromSideChannelFunction() { + return false; +} +#endif + namespace net { // State machines are easier to debug if you log state transitions. @@ -641,6 +665,15 @@ int SSLClientSocketNSS::InitializeSSLOptions() { } #endif +#ifdef SSL_ENABLE_OCSP_STAPLING + if (HaveCacheOCSPResponseFromSideChannelFunction() && + !ssl_config_.snap_start_enabled) { + rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_OCSP_STAPLING, PR_TRUE); + if (rv != SECSuccess) + LogFailedNSSFunction(net_log_, "SSL_OptionSet (OCSP stapling)", ""); + } +#endif + rv = SSL_OptionSet(nss_fd_, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); if (rv != SECSuccess) { LogFailedNSSFunction(net_log_, "SSL_OptionSet", "SSL_HANDSHAKE_AS_CLIENT"); @@ -1963,6 +1996,32 @@ int SSLClientSocketNSS::DoHandshake() { } } +#if defined(SSL_ENABLE_OCSP_STAPLING) + // TODO: we need to be able to plumb an OCSP response into the system + // libraries. When we do, HaveCacheOCSPResponseFromSideChannelFunction + // needs to be updated for those platforms. + if (!predicted_cert_chain_correct_ && + HaveCacheOCSPResponseFromSideChannelFunction()) { + unsigned int len = 0; + SSL_GetStapledOCSPResponse(nss_fd_, NULL, &len); + if (len) { + const unsigned int orig_len = len; + scoped_array<uint8> ocsp_response(new uint8[orig_len]); + SSL_GetStapledOCSPResponse(nss_fd_, ocsp_response.get(), &len); + DCHECK_EQ(orig_len, len); + + SECItem ocsp_response_item; + ocsp_response_item.type = siBuffer; + ocsp_response_item.data = ocsp_response.get(); + ocsp_response_item.len = len; + + CERT_CacheOCSPResponseFromSideChannel( + CERT_GetDefaultCertDB(), server_cert_nss_, PR_Now(), + &ocsp_response_item, NULL); + } + } +#endif + SaveSnapStartInfo(); // SSL handshake is completed. It's possible that we mispredicted the // NPN agreed protocol. In this case, we've just sent a request in the |