AsyncSSLSocket::get/setClientCertValidationResult API.
authorXiangyu Bu <xbu@fb.com>
Mon, 14 Aug 2017 17:13:58 +0000 (10:13 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Mon, 14 Aug 2017 17:26:54 +0000 (10:26 -0700)
Summary:
The added API will be used for storing and retrieving validation result of client cert.

At some point we may change "client" to "peer" to make it generic.

Reviewed By: anirudhvr

Differential Revision: D5610404

fbshipit-source-id: 2feb03abc0594af4c68db33d8885ea214867148a

folly/io/async/AsyncSSLSocket.h
folly/io/async/test/AsyncSSLSocketTest.cpp

index 33cfb62be54e7e42e79999a9bffbd4d0bc3b1ef2..044155dcbca6a37b749dce087197a34aa5d61e96 100644 (file)
@@ -685,6 +685,36 @@ class AsyncSSLSocket : public virtual AsyncSocket {
     return ssl::X509UniquePtr(cert);
   }
 
+  /**
+   * A set of possible outcomes of certificate validation.
+   */
+  enum class CertValidationResult {
+    CERT_VALID, // Cert is valid.
+    CERT_MISSING, // No cert is provided.
+    CERT_INVALID_FUTURE, // Cert has start datetime in the future.
+    CERT_INVALID_EXPIRED, // Cert has expired.
+    CERT_INVALID_BAD_CHAIN, // Cert has bad chain.
+    CERT_INVALID_OTHER, // Cert is invalid due to other reasons.
+  };
+
+  /**
+   * Get the validation result of client cert. If the server side has not
+   * set this value, it will return folly::none; otherwise a value in
+   * CertValidationResult.
+   */
+  const Optional<CertValidationResult> getClientCertValidationResult() {
+    return clientCertValidationResult_;
+  }
+
+  /**
+   * Set the validation result of client cert. Used by server side.
+   * @param result A value of CertValidationResult wrapped by folly::Optional.
+   */
+  void setClientCertValidationResult(
+      const Optional<CertValidationResult>& result) {
+    clientCertValidationResult_ = result;
+  }
+
   /**
    * Force AsyncSSLSocket object to cache local and peer socket addresses.
    * If called with "true" before connect() this function forces full local
@@ -857,6 +887,8 @@ class AsyncSSLSocket : public virtual AsyncSocket {
   folly::SSLContext::SSLVerifyPeerEnum
     verifyPeer_{folly::SSLContext::SSLVerifyPeerEnum::USE_CTX};
 
+  Optional<CertValidationResult> clientCertValidationResult_{none};
+
   // Callback for SSL_CTX_set_verify()
   static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx);
 
index 3dd62e5debd52b06769340aa84029ef8ef025183..d476f885cf21cd3bf9fee24edcbcb24ebe1ea638 100644 (file)
@@ -138,6 +138,24 @@ std::string getCommonName(X509* cert) {
   return cn;
 }
 
+TEST(AsyncSSLSocketTest, ClientCertValidationResultTest) {
+  EventBase ev;
+  int fd = 0;
+
+  AsyncSSLSocket::UniquePtr sock(
+      new AsyncSSLSocket(std::make_shared<SSLContext>(), &ev, fd, false));
+
+  // Initially the cert is not validated, so no result is available.
+  EXPECT_EQ(nullptr, get_pointer(sock->getClientCertValidationResult()));
+
+  sock->setClientCertValidationResult(
+      make_optional(AsyncSSLSocket::CertValidationResult::CERT_VALID));
+
+  EXPECT_EQ(
+      AsyncSSLSocket::CertValidationResult::CERT_VALID,
+      *sock->getClientCertValidationResult());
+}
+
 /**
  * Test connecting to, writing to, reading from, and closing the
  * connection to the SSL server.