From 38fb2cd0e2b60d8ab34f08564fec1a83d5e782c8 Mon Sep 17 00:00:00 2001
From: Alessandro Ghedini <alessandro@ghedini.me>
Date: Tue, 24 Jun 2014 23:25:59 +0200
Subject: [PATCH 3/4] nss: add support for the Certificate Status Request TLS
 extension

Also known as "status_request" or OCSP stapling, defined in RFC6066 section 8.

This requires NSS 3.15 or higher.
---
 lib/vtls/nss.c  | 45 +++++++++++++++++++++++++++++++++++++++++++++
 lib/vtls/nssg.h |  3 +++
 2 files changed, 48 insertions(+)

diff --git a/lib/vtls/nss.c b/lib/vtls/nss.c
index 37fe480..0dff268 100644
--- a/lib/vtls/nss.c
+++ b/lib/vtls/nss.c
@@ -639,6 +639,34 @@ static SECStatus nss_auth_cert_hook(void *arg, PRFileDesc *fd, PRBool checksig,
                                     PRBool isServer)
 {
   struct connectdata *conn = (struct connectdata *)arg;
+
+#ifdef SSL_ENABLE_OCSP_STAPLING
+  if(conn->data->set.ssl.verifystatus) {
+    SECStatus cacheResult;
+
+    const SECItemArray *csa = SSL_PeerStapledOCSPResponses(fd);
+    if(!csa) {
+      failf(conn->data, "Invalid OCSP response");
+      return SECFailure;
+    }
+
+    if(csa->len == 0) {
+      failf(conn->data, "No OCSP response received");
+      return SECFailure;
+    }
+
+    cacheResult = CERT_CacheOCSPResponseFromSideChannel(
+      CERT_GetDefaultCertDB(), SSL_PeerCertificate(fd),
+      PR_Now(), &csa->items[0], arg
+    );
+
+    if(cacheResult != SECSuccess) {
+      failf(conn->data, "Invalid OCSP response");
+      return cacheResult;
+    }
+  }
+#endif
+
   if(!conn->data->set.ssl.verifypeer) {
     infof(conn->data, "skipping SSL peer certificate verification\n");
     return SECSuccess;
@@ -1620,6 +1648,14 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
     SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
   }
 
+#ifdef SSL_ENABLE_OCSP_STAPLING
+  if(data->set.ssl.verifystatus) {
+    if(SSL_OptionSet(connssl->handle, SSL_ENABLE_OCSP_STAPLING, PR_TRUE)
+        != SECSuccess)
+      goto error;
+  }
+#endif
+
 #ifdef USE_NGHTTP2
   if(data->set.httpversion == CURL_HTTP_VERSION_2_0) {
 #ifdef SSL_ENABLE_NPN
@@ -1908,4 +1944,13 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
   PK11_DestroyContext(MD5pw, PR_TRUE);
 }
 
+bool Curl_nss_cert_status_request(void)
+{
+#ifdef SSL_ENABLE_OCSP_STAPLING
+  return TRUE;
+#else
+  return FALSE;
+#endif
+}
+
 #endif /* USE_NSS */
diff --git a/lib/vtls/nssg.h b/lib/vtls/nssg.h
index 74840e8..963ce4a 100644
--- a/lib/vtls/nssg.h
+++ b/lib/vtls/nssg.h
@@ -60,6 +60,8 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
                      unsigned char *md5sum, /* output */
                      size_t md5len);
 
+bool Curl_nss_cert_status_request(void);
+
 /* this backend supports the CAPATH option */
 #define have_curlssl_ca_path 1
 
@@ -86,6 +88,7 @@ void Curl_nss_md5sum(unsigned char *tmp, /* input */
 #define curlssl_data_pending(x,y) ((void)x, (void)y, 0)
 #define curlssl_random(x,y,z) Curl_nss_random(x,y,z)
 #define curlssl_md5sum(a,b,c,d) Curl_nss_md5sum(a,b,c,d)
+#define curlssl_cert_status_request() Curl_nss_cert_status_request()
 #define CURL_SSL_BACKEND CURLSSLBACKEND_NSS
 
 #endif /* USE_NSS */
-- 
2.1.4


