Index: net/socket/ssl_client_socket_nss.cc |
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc |
index b9c6dffd046c323f35d551c7b90a2d1a12fd268a..971e4f7fd18d528103aa8a616a7cbb5e01c5ed1c 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> |
@@ -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. |
@@ -801,6 +825,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"); |
@@ -2157,6 +2190,32 @@ int SSLClientSocketNSS::DoHandshake() { |
} |
} |
+#if defined(SSL_ENABLE_OCSP_STAPLING) |
+ // TODO: we need to be able to plumb an OCSP response into the system |
wtc
2010/11/30 19:19:16
Nit: cpplint.py requires that a TODO comment inclu
|
+ // 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 |