You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pulsar.apache.org by GitBox <gi...@apache.org> on 2018/12/15 00:42:40 UTC

[GitHub] aahmed-se closed pull request #2475: Add host name verification

aahmed-se closed pull request #2475: Add host name verification
URL: https://github.com/apache/pulsar/pull/2475
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/pulsar-client-cpp/docker-build.sh b/pulsar-client-cpp/docker-build.sh
index b0439b10d1..ba21625040 100755
--- a/pulsar-client-cpp/docker-build.sh
+++ b/pulsar-client-cpp/docker-build.sh
@@ -41,4 +41,4 @@ DOCKER_CMD="docker run -i -v $ROOT_DIR:/pulsar $IMAGE"
 find . -name CMakeCache.txt | xargs rm -f
 find . -name CMakeFiles | xargs rm -rf
 
-$DOCKER_CMD bash -c "cd /pulsar/pulsar-client-cpp && cmake . $CMAKE_ARGS && make check-format && make"
+$DOCKER_CMD bash -c "cd /pulsar/pulsar-client-cpp && cmake . $CMAKE_ARGS && make check-format && make"
\ No newline at end of file
diff --git a/pulsar-client-cpp/include/pulsar/ClientConfiguration.h b/pulsar-client-cpp/include/pulsar/ClientConfiguration.h
index eedf716240..bea6c0ad6b 100644
--- a/pulsar-client-cpp/include/pulsar/ClientConfiguration.h
+++ b/pulsar-client-cpp/include/pulsar/ClientConfiguration.h
@@ -135,6 +135,9 @@ class ClientConfiguration {
     ClientConfiguration& setTlsAllowInsecureConnection(bool allowInsecure);
     bool isTlsAllowInsecureConnection() const;
 
+    ClientConfiguration& setValidateHostName(bool validateHostName);
+    bool isValidateHostName() const;
+
     /*
      * Initialize stats interval in seconds. Stats are printed and reset after every 'statsIntervalInSeconds'.
      * Set to 0 in order to disable stats collection.
diff --git a/pulsar-client-cpp/include/pulsar/c/client_configuration.h b/pulsar-client-cpp/include/pulsar/c/client_configuration.h
index d1979c480b..5b1c880488 100644
--- a/pulsar-client-cpp/include/pulsar/c/client_configuration.h
+++ b/pulsar-client-cpp/include/pulsar/c/client_configuration.h
@@ -130,6 +130,11 @@ int pulsar_client_configuration_is_tls_allow_insecure_connection(pulsar_client_c
 void pulsar_client_configuration_set_stats_interval_in_seconds(pulsar_client_configuration_t *conf,
                                                                const unsigned int interval);
 
+int pulsar_client_configuration_is_validate_hostname(pulsar_client_configuration_t *conf);
+
+void pulsar_client_configuration_set_validate_hostname(pulsar_client_configuration_t *conf,
+                                                       const unsigned int validateHostName);
+
 /*
  * Get the stats interval set in the client.
  */
diff --git a/pulsar-client-cpp/lib/ClientConfiguration.cc b/pulsar-client-cpp/lib/ClientConfiguration.cc
index 246c7af932..cc8f989931 100644
--- a/pulsar-client-cpp/lib/ClientConfiguration.cc
+++ b/pulsar-client-cpp/lib/ClientConfiguration.cc
@@ -68,6 +68,13 @@ ClientConfiguration& ClientConfiguration::setUseTls(bool useTls) {
 
 bool ClientConfiguration::isUseTls() const { return impl_->useTls; }
 
+ClientConfiguration& ClientConfiguration::setValidateHostName(bool validateHostName) {
+    impl_->validateHostName = validateHostName;
+    return *this;
+}
+
+bool ClientConfiguration::isValidateHostName() const { return impl_->validateHostName; }
+
 ClientConfiguration& ClientConfiguration::setTlsTrustCertsFilePath(const std::string& filePath) {
     impl_->tlsTrustCertsFilePath = filePath;
     return *this;
diff --git a/pulsar-client-cpp/lib/ClientConfigurationImpl.h b/pulsar-client-cpp/lib/ClientConfigurationImpl.h
index cb23a14088..60e4ae6efe 100644
--- a/pulsar-client-cpp/lib/ClientConfigurationImpl.h
+++ b/pulsar-client-cpp/lib/ClientConfigurationImpl.h
@@ -35,6 +35,7 @@ struct ClientConfigurationImpl {
     bool tlsAllowInsecureConnection;
     unsigned int statsIntervalInSeconds;
     LoggerFactoryPtr loggerFactory;
+    bool validateHostName;
 
     ClientConfigurationImpl()
         : authenticationPtr(AuthFactory::Disabled()),
@@ -46,7 +47,8 @@ struct ClientConfigurationImpl {
           useTls(false),
           tlsAllowInsecureConnection(false),
           statsIntervalInSeconds(600),  // 10 minutes
-          loggerFactory() {}
+          loggerFactory(),
+          validateHostName(false) {}
 };
 }  // namespace pulsar
 
diff --git a/pulsar-client-cpp/lib/ConnectionPool.cc b/pulsar-client-cpp/lib/ConnectionPool.cc
index 36ce4a5180..68be397d68 100644
--- a/pulsar-client-cpp/lib/ConnectionPool.cc
+++ b/pulsar-client-cpp/lib/ConnectionPool.cc
@@ -20,6 +20,14 @@
 
 #include "LogUtils.h"
 
+#include <boost/iostreams/stream.hpp>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+using boost::asio::ip::tcp;
+namespace ssl = boost::asio::ssl;
+typedef ssl::stream<tcp::socket> ssl_socket;
+
 DECLARE_LOG_OBJECT()
 
 namespace pulsar {
@@ -37,6 +45,27 @@ Future<Result, ClientConnectionWeakPtr> ConnectionPool::getConnectionAsync(
     const std::string& logicalAddress, const std::string& physicalAddress) {
     boost::unique_lock<boost::mutex> lock(mutex_);
 
+    if (clientConfiguration_.isValidateHostName()) {
+        // Create a context that uses the default paths for
+        // finding CA certificates.
+        ssl::context ctx(ssl::context::sslv23);
+        ctx.set_default_verify_paths();
+
+        // Open a socket and connect it to the remote host.
+        boost::asio::io_service io_service;
+        ssl_socket sock(io_service, ctx);
+        tcp::resolver resolver(io_service);
+        tcp::resolver::query query(physicalAddress, "https");
+        boost::asio::connect(sock.lowest_layer(), resolver.resolve(query));
+        sock.lowest_layer().set_option(tcp::no_delay(true));
+
+        // Perform SSL handshake and verify the remote host's
+        // certificate.
+        sock.set_verify_mode(ssl::verify_peer);
+        sock.set_verify_callback(ssl::rfc2818_verification(physicalAddress));
+        sock.handshake(ssl_socket::client);
+    }
+
     if (poolConnections_) {
         PoolMap::iterator cnxIt = pool_.find(logicalAddress);
         if (cnxIt != pool_.end()) {
@@ -70,4 +99,5 @@ Future<Result, ClientConnectionWeakPtr> ConnectionPool::getConnectionAsync(
     cnx->tcpConnectAsync();
     return future;
 }
+
 }  // namespace pulsar
diff --git a/pulsar-client-cpp/lib/LogUtils.h b/pulsar-client-cpp/lib/LogUtils.h
index 81de443b46..1791fef83d 100644
--- a/pulsar-client-cpp/lib/LogUtils.h
+++ b/pulsar-client-cpp/lib/LogUtils.h
@@ -91,4 +91,4 @@ class LogUtils {
 };
 
 #pragma GCC visibility pop
-}
+}  // namespace pulsar
diff --git a/pulsar-client-cpp/lib/c/c_ClientConfiguration.cc b/pulsar-client-cpp/lib/c/c_ClientConfiguration.cc
index 935e908530..13b4bf9a30 100644
--- a/pulsar-client-cpp/lib/c/c_ClientConfiguration.cc
+++ b/pulsar-client-cpp/lib/c/c_ClientConfiguration.cc
@@ -110,6 +110,15 @@ int pulsar_client_configuration_is_use_tls(pulsar_client_configuration_t *conf)
     return conf->conf.isUseTls();
 }
 
+void pulsar_client_configuration_set_validate_hostname(pulsar_client_configuration_t *conf,
+                                                       int validateHostName) {
+    conf->conf.setValidateHostName(validateHostName);
+}
+
+int pulsar_client_configuration_is_validate_hostname(pulsar_client_configuration_t *conf) {
+    return conf->conf.isValidateHostName();
+}
+
 void pulsar_client_configuration_set_tls_trust_certs_file_path(pulsar_client_configuration_t *conf,
                                                                const char *tlsTrustCertsFilePath) {
     conf->conf.setTlsTrustCertsFilePath(tlsTrustCertsFilePath);
diff --git a/pulsar-client-cpp/python/src/config.cc b/pulsar-client-cpp/python/src/config.cc
index c1bfeef9c8..aa1e30dac2 100644
--- a/pulsar-client-cpp/python/src/config.cc
+++ b/pulsar-client-cpp/python/src/config.cc
@@ -95,6 +95,7 @@ void export_config() {
             .def("tls_trust_certs_file_path", &ClientConfiguration::setTlsTrustCertsFilePath, return_self<>())
             .def("tls_allow_insecure_connection", &ClientConfiguration::isTlsAllowInsecureConnection)
             .def("tls_allow_insecure_connection", &ClientConfiguration::setTlsAllowInsecureConnection, return_self<>())
+            .def("tls_validate_hostname", &ClientConfiguration::setValidateHostName, return_self<>())
             ;
 
     class_<ProducerConfiguration>("ProducerConfiguration")
diff --git a/pulsar-client-cpp/tests/AuthPluginTest.cc b/pulsar-client-cpp/tests/AuthPluginTest.cc
index 295e624b4c..51e7641875 100644
--- a/pulsar-client-cpp/tests/AuthPluginTest.cc
+++ b/pulsar-client-cpp/tests/AuthPluginTest.cc
@@ -120,6 +120,34 @@ TEST(AuthPluginTest, testTls) {
     ASSERT_EQ(i, numOfMessages);
 }
 
+TEST(AuthPluginTest, testTlsWithHostNameValidation) {
+    ClientConfiguration config = ClientConfiguration();
+    config.setUseTls(true);
+    config.setTlsTrustCertsFilePath("../../pulsar-broker/src/test/resources/authentication/tls/cacert.pem");
+    config.setTlsAllowInsecureConnection(false);
+    AuthenticationPtr auth =
+        pulsar::AuthTls::create("../../pulsar-broker/src/test/resources/authentication/tls/client-cert.pem",
+                                "../../pulsar-broker/src/test/resources/authentication/tls/client-key.pem");
+
+    ASSERT_TRUE(auth != NULL);
+    ASSERT_EQ(auth->getAuthMethodName(), "tls");
+
+    pulsar::AuthenticationDataPtr data;
+    ASSERT_EQ(auth->getAuthData(data), pulsar::ResultOk);
+    ASSERT_EQ(data->getCommandData(), "none");
+    ASSERT_EQ(data->hasDataForTls(), true);
+    ASSERT_EQ(auth.use_count(), 1);
+
+    config.setAuth(auth);
+    config.setValidateHostName(true);
+    Client client(lookupUrlTls, config);
+    std::string topicName = "persistent://property/cluster/namespace/test-tls";
+    Producer producer;
+    Promise<Result, Producer> producerPromise;
+
+    ASSERT_ANY_THROW(client.createProducerAsync(topicName, WaitForCallbackValue<Producer>(producerPromise)));
+}
+
 TEST(AuthPluginTest, testTlsDetectPulsarSsl) {
     ClientConfiguration config = ClientConfiguration();
     config.setTlsTrustCertsFilePath("../../pulsar-broker/src/test/resources/authentication/tls/cacert.pem");
@@ -141,6 +169,23 @@ TEST(AuthPluginTest, testTlsDetectPulsarSsl) {
     ASSERT_EQ(ResultOk, result);
 }
 
+TEST(AuthPluginTest, testTlsDetectPulsarSslWithHostNameValidation) {
+    ClientConfiguration config = ClientConfiguration();
+    config.setTlsTrustCertsFilePath("../../pulsar-broker/src/test/resources/authentication/tls/cacert.pem");
+    config.setTlsAllowInsecureConnection(false);
+    AuthenticationPtr auth =
+        pulsar::AuthTls::create("../../pulsar-broker/src/test/resources/authentication/tls/client-cert.pem",
+                                "../../pulsar-broker/src/test/resources/authentication/tls/client-key.pem");
+    config.setAuth(auth);
+    config.setValidateHostName(true);
+
+    Client client("pulsar+ssl://localhost:9886", config);
+    std::string topicName = "persistent://property/cluster/namespace/test-tls-detect";
+    Producer producer;
+    Promise<Result, Producer> producerPromise;
+    ASSERT_ANY_THROW(client.createProducerAsync(topicName, WaitForCallbackValue<Producer>(producerPromise)));
+}
+
 TEST(AuthPluginTest, testTlsDetectHttps) {
     ClientConfiguration config = ClientConfiguration();
     config.setUseTls(true);  // shouldn't be needed soon


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services