diff options
author | Parth Chandra <parthc@apache.org> | 2017-07-10 17:19:12 -0700 |
---|---|---|
committer | Parth Chandra <parthc@apache.org> | 2017-10-11 19:27:47 -0700 |
commit | 414c94ee7e088c89b0c7c8b9d9dde9335cfcbe6d (patch) | |
tree | 4eadcfac32ac19c4a0e4cc1cb2379e9d17d36edd | |
parent | ac3f0ce2683906db908d861e3f93700d8ac0f6d6 (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.txt | 28 | ||||
-rw-r--r-- | contrib/native/client/test/ssl/testClient.cpp | 151 | ||||
-rw-r--r-- | contrib/native/client/test/ssl/testServer.cpp | 177 |
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; +} + |