From: Xiangyu Bu Date: Mon, 14 Aug 2017 17:13:58 +0000 (-0700) Subject: AsyncSSLSocket::get/setClientCertValidationResult API. X-Git-Tag: v2017.08.21.00~17 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=7289b921441f3f809b1c65bfd45750277c41afe5;p=folly.git AsyncSSLSocket::get/setClientCertValidationResult API. 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 --- diff --git a/folly/io/async/AsyncSSLSocket.h b/folly/io/async/AsyncSSLSocket.h index 33cfb62b..044155dc 100644 --- a/folly/io/async/AsyncSSLSocket.h +++ b/folly/io/async/AsyncSSLSocket.h @@ -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 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& 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 clientCertValidationResult_{none}; + // Callback for SSL_CTX_set_verify() static int sslVerifyCallback(int preverifyOk, X509_STORE_CTX* ctx); diff --git a/folly/io/async/test/AsyncSSLSocketTest.cpp b/folly/io/async/test/AsyncSSLSocketTest.cpp index 3dd62e5d..d476f885 100644 --- a/folly/io/async/test/AsyncSSLSocketTest.cpp +++ b/folly/io/async/test/AsyncSSLSocketTest.cpp @@ -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(), &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.