aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParth Chandra <parthc@apache.org>2017-07-10 17:19:12 -0700
committerParth Chandra <parthc@apache.org>2017-10-11 19:27:47 -0700
commit414c94ee7e088c89b0c7c8b9d9dde9335cfcbe6d (patch)
tree4eadcfac32ac19c4a0e4cc1cb2379e9d17d36edd
parentac3f0ce2683906db908d861e3f93700d8ac0f6d6 (diff)
DRILL-5431: SSL Support (C++) - Add boost example code for ssl (small change to the code to pick up the certificate and key files from the test dir). Useful to test the ssl environment.
-rw-r--r--contrib/native/client/test/CMakeLists.txt28
-rw-r--r--contrib/native/client/test/ssl/testClient.cpp151
-rw-r--r--contrib/native/client/test/ssl/testServer.cpp177
3 files changed, 356 insertions, 0 deletions
diff --git a/contrib/native/client/test/CMakeLists.txt b/contrib/native/client/test/CMakeLists.txt
new file mode 100644
index 000000000..38c783e06
--- /dev/null
+++ b/contrib/native/client/test/CMakeLists.txt
@@ -0,0 +1,28 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Drill Client library tests
+include_directories("${OPENSSL_INCLUDE_DIR}")
+include_directories(${CMAKE_SOURCE_DIR}/src)
+add_executable(testSSL ssl/testSSL.cpp )
+target_link_libraries(testSSL ${Boost_LIBRARIES} ${PROTOBUF_LIBRARY} drillClient protomsgs y2038 ${OPENSSL_LIBRARIES} )
+add_executable(testServer ssl/testServer.cpp )
+target_link_libraries(testServer ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} )
+add_executable(testClient ssl/testClient.cpp )
+target_link_libraries(testClient ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} )
+
diff --git a/contrib/native/client/test/ssl/testClient.cpp b/contrib/native/client/test/ssl/testClient.cpp
new file mode 100644
index 000000000..485954f4c
--- /dev/null
+++ b/contrib/native/client/test/ssl/testClient.cpp
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdlib>
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+enum { max_length = 1024 };
+
+class client
+{
+ public:
+ client(boost::asio::io_service& io_service, boost::asio::ssl::context& context,
+ boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
+ : socket_(io_service, context)
+ {
+ boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
+ socket_.lowest_layer().async_connect(endpoint,
+ boost::bind(&client::handle_connect, this,
+ boost::asio::placeholders::error, ++endpoint_iterator));
+ }
+
+ void handle_connect(const boost::system::error_code& error,
+ boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
+ {
+ if (!error)
+ {
+ socket_.async_handshake(boost::asio::ssl::stream_base::client,
+ boost::bind(&client::handle_handshake, this,
+ boost::asio::placeholders::error));
+ }
+ else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator())
+ {
+ socket_.lowest_layer().close();
+ boost::asio::ip::tcp::endpoint endpoint = *endpoint_iterator;
+ socket_.lowest_layer().async_connect(endpoint,
+ boost::bind(&client::handle_connect, this,
+ boost::asio::placeholders::error, ++endpoint_iterator));
+ }
+ else
+ {
+ std::cout << "Connect failed: " << error << "\n";
+ }
+ }
+
+ void handle_handshake(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ std::cout << "Enter message: ";
+ std::cin.getline(request_, max_length);
+ size_t request_length = strlen(request_);
+
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(request_, request_length),
+ boost::bind(&client::handle_write, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ std::cout << "Handshake failed: " << error << "\n";
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_read(socket_,
+ boost::asio::buffer(reply_, bytes_transferred),
+ boost::bind(&client::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ std::cout << "Write failed: " << error << "\n";
+ }
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ std::cout << "Reply: ";
+ std::cout.write(reply_, bytes_transferred);
+ std::cout << "\n";
+ }
+ else
+ {
+ std::cout << "Read failed: " << error << "\n";
+ }
+ }
+
+ private:
+ boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
+ char request_[max_length];
+ char reply_[max_length];
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 3)
+ {
+ std::cerr << "Usage: client <host> <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_service io_service;
+
+ boost::asio::ip::tcp::resolver resolver(io_service);
+ boost::asio::ip::tcp::resolver::query query(argv[1], argv[2]);
+ boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
+
+ boost::asio::ssl::context ctx(io_service, boost::asio::ssl::context::sslv23);
+ ctx.set_verify_mode(boost::asio::ssl::context::verify_peer);
+ ctx.load_verify_file("../../../test/ssl/drillTestCert.pem");
+
+ client c(io_service, ctx, iterator);
+
+ io_service.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
diff --git a/contrib/native/client/test/ssl/testServer.cpp b/contrib/native/client/test/ssl/testServer.cpp
new file mode 100644
index 000000000..98b24a3b6
--- /dev/null
+++ b/contrib/native/client/test/ssl/testServer.cpp
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <cstdlib>
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/asio.hpp>
+#include <boost/asio/ssl.hpp>
+
+typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ssl_socket;
+
+class session
+{
+ public:
+ session(boost::asio::io_service& io_service, boost::asio::ssl::context& context)
+ : socket_(io_service, context)
+ {
+ }
+
+ ssl_socket::lowest_layer_type& socket()
+ {
+ return socket_.lowest_layer();
+ }
+
+ void start()
+ {
+ socket_.async_handshake(boost::asio::ssl::stream_base::server,
+ boost::bind(&session::handle_handshake, this,
+ boost::asio::placeholders::error));
+ }
+
+ void handle_handshake(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ boost::bind(&session::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ void handle_read(const boost::system::error_code& error,
+ size_t bytes_transferred)
+ {
+ if (!error)
+ {
+ boost::asio::async_write(socket_,
+ boost::asio::buffer(data_, bytes_transferred),
+ boost::bind(&session::handle_write, this,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ void handle_write(const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ socket_.async_read_some(boost::asio::buffer(data_, max_length),
+ boost::bind(&session::handle_read, this,
+ boost::asio::placeholders::error,
+ boost::asio::placeholders::bytes_transferred));
+ }
+ else
+ {
+ delete this;
+ }
+ }
+
+ private:
+ ssl_socket socket_;
+ enum { max_length = 1024 };
+ char data_[max_length];
+};
+
+class server
+{
+ public:
+ server(boost::asio::io_service& io_service, unsigned short port)
+ : io_service_(io_service),
+ acceptor_(io_service,
+ boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port)),
+ context_(io_service, boost::asio::ssl::context::sslv23)
+ {
+ context_.set_options(
+ boost::asio::ssl::context::default_workarounds
+ //| boost::asio::ssl::context::no_sslv2
+ | boost::asio::ssl::context::single_dh_use
+ );
+ context_.set_password_callback(boost::bind(&server::get_password, this));
+ context_.use_certificate_chain_file("../../../test/ssl/drillTestCert.pem");
+ context_.use_private_key_file("../../../test/ssl/drillTestServerKeyNoPass.pem", boost::asio::ssl::context::pem);
+ //context_.use_tmp_dh_file("../../../test/ssl/dh512.pem");
+
+ session* new_session = new session(io_service_, context_);
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+
+ std::string get_password() const
+ {
+ return "test";
+ }
+
+ void handle_accept(session* new_session,
+ const boost::system::error_code& error)
+ {
+ if (!error)
+ {
+ new_session->start();
+ new_session = new session(io_service_, context_);
+ acceptor_.async_accept(new_session->socket(),
+ boost::bind(&server::handle_accept, this, new_session,
+ boost::asio::placeholders::error));
+ }
+ else
+ {
+ delete new_session;
+ }
+ }
+
+ private:
+ boost::asio::io_service& io_service_;
+ boost::asio::ip::tcp::acceptor acceptor_;
+ boost::asio::ssl::context context_;
+};
+
+int main(int argc, char* argv[])
+{
+ try
+ {
+ if (argc != 2)
+ {
+ std::cerr << "Usage: server <port>\n";
+ return 1;
+ }
+
+ boost::asio::io_service io_service;
+
+ using namespace std; // For atoi.
+ server s(io_service, atoi(argv[1]));
+
+ io_service.run();
+ }
+ catch (std::exception& e)
+ {
+ std::cerr << "Exception: " << e.what() << "\n";
+ }
+
+ return 0;
+}
+