summaryrefslogtreecommitdiffstats
path: root/net/socket/ssl_client_socket_nss.cc
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket/ssl_client_socket_nss.cc')
-rw-r--r--net/socket/ssl_client_socket_nss.cc61
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