Skip to content

Added a client certificate support. #361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions boost/network/protocol/http/client/async_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ struct async_client
bool always_verify_peer,
boost::shared_ptr<boost::asio::io_service> service,
optional<string_type> const& certificate_filename,
optional<string_type> const& verify_path)
optional<string_type> const& verify_path,
optional<string_type> const& certificate_file,
optional<string_type> const& private_key_file)
: connection_base(cache_resolved, follow_redirect),
service_ptr(service.get()
? service
Expand All @@ -50,6 +52,8 @@ struct async_client
sentinel_(new boost::asio::io_service::work(service_)),
certificate_filename_(certificate_filename),
verify_path_(verify_path),
certificate_file_(certificate_file),
private_key_file_(private_key_file),
always_verify_peer_(always_verify_peer) {
connection_base::resolver_strand_.reset(
new boost::asio::io_service::strand(service_));
Expand All @@ -71,8 +75,9 @@ struct async_client
body_generator_function_type generator) {
typename connection_base::connection_ptr connection_;
connection_ = connection_base::get_connection(
resolver_, request_, always_verify_peer_, certificate_filename_,
verify_path_);
resolver_, request_, always_verify_peer_,
certificate_filename_, verify_path_,
certificate_file_, private_key_file_);
return connection_->send_request(method, request_, get_body, callback,
generator);
}
Expand All @@ -82,7 +87,10 @@ struct async_client
resolver_type resolver_;
boost::shared_ptr<boost::asio::io_service::work> sentinel_;
boost::shared_ptr<boost::thread> lifetime_thread_;
optional<string_type> certificate_filename_, verify_path_;
optional<string_type> certificate_filename_;
optional<string_type> verify_path_;
optional<string_type> certificate_file_;
optional<string_type> private_key_file_;
bool always_verify_peer_;
};
} // namespace impl
Expand Down
8 changes: 6 additions & 2 deletions boost/network/protocol/http/client/connection/async_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ namespace boost { namespace network { namespace http { namespace impl {
bool always_verify_peer,
bool https,
optional<string_type> certificate_filename=optional<string_type>(),
optional<string_type> const & verify_path=optional<string_type>()) {
optional<string_type> const & verify_path=optional<string_type>(),
optional<string_type> certificate_file=optional<string_type>(),
optional<string_type> private_key_file=optional<string_type>()) {
typedef http_async_connection<Tag,version_major,version_minor>
async_connection;
typedef typename delegate_factory<Tag>::type delegate_factory_type;
Expand All @@ -55,7 +57,9 @@ namespace boost { namespace network { namespace http { namespace impl {
https,
always_verify_peer,
certificate_filename,
verify_path)));
verify_path,
certificate_file,
private_key_file)));
BOOST_ASSERT(temp.get() != 0);
return temp;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,18 @@ struct connection_delegate_factory {
bool https,
bool always_verify_peer,
optional<string_type> certificate_filename,
optional<string_type> verify_path) {
optional<string_type> verify_path,
optional<string_type> certificate_file,
optional<string_type> private_key_file) {
connection_delegate_ptr delegate;
if (https) {
#ifdef BOOST_NETWORK_ENABLE_HTTPS
delegate.reset(new ssl_delegate(service,
always_verify_peer,
certificate_filename,
verify_path));
verify_path,
certificate_file,
private_key_file));
#else
BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported."));
#endif /* BOOST_NETWORK_ENABLE_HTTPS */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ struct ssl_delegate : connection_delegate,
enable_shared_from_this<ssl_delegate> {
ssl_delegate(asio::io_service &service, bool always_verify_peer,
optional<std::string> certificate_filename,
optional<std::string> verify_path);
optional<std::string> verify_path,
optional<std::string> certificate_file,
optional<std::string> private_key_file);

virtual void connect(asio::ip::tcp::endpoint &endpoint,
function<void(system::error_code const &)> handler);
Expand All @@ -38,7 +40,10 @@ struct ssl_delegate : connection_delegate,

private:
asio::io_service &service_;
optional<std::string> certificate_filename_, verify_path_;
optional<std::string> certificate_filename_;
optional<std::string> verify_path_;
optional<std::string> certificate_file_;
optional<std::string> private_key_file_;
scoped_ptr<asio::ssl::context> context_;
scoped_ptr<asio::ssl::stream<asio::ip::tcp::socket> > socket_;
bool always_verify_peer_;
Expand Down
12 changes: 11 additions & 1 deletion boost/network/protocol/http/client/connection/ssl_delegate.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
boost::network::http::impl::ssl_delegate::ssl_delegate(
asio::io_service &service, bool always_verify_peer,
optional<std::string> certificate_filename,
optional<std::string> verify_path)
optional<std::string> verify_path,
optional<std::string> certificate_file,
optional<std::string> private_key_file)
: service_(service),
certificate_filename_(certificate_filename),
verify_path_(verify_path),
certificate_file_(certificate_file),
private_key_file_(private_key_file),
always_verify_peer_(always_verify_peer) {}

void boost::network::http::impl::ssl_delegate::connect(
Expand All @@ -36,6 +40,12 @@ void boost::network::http::impl::ssl_delegate::connect(
else
context_->set_verify_mode(asio::ssl::context::verify_none);
}
if (certificate_file_)
context_->use_certificate_file(
*certificate_file_, boost::asio::ssl::context::pem);
if (private_key_file_)
context_->use_private_key_file(
*private_key_file_, boost::asio::ssl::context::pem);
socket_.reset(
new asio::ssl::stream<asio::ip::tcp::socket>(service_, *context_));
socket_->lowest_layer().async_connect(
Expand Down
10 changes: 8 additions & 2 deletions boost/network/protocol/http/client/connection/sync_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,16 +240,22 @@ struct sync_connection_base {
static sync_connection_base<Tag, version_major, version_minor>*
new_connection(resolver_type& resolver, resolver_function_type resolve,
bool https, bool always_verify_peer,
optional<string_type> const& cert_filename =
optional<string_type> const& certificate_filename =
optional<string_type>(),
optional<string_type> const& verify_path =
optional<string_type>(),
optional<string_type> const& certificate_file =
optional<string_type>(),
optional<string_type> const& private_key_file =
optional<string_type>()) {
if (https) {
#ifdef BOOST_NETWORK_ENABLE_HTTPS
return dynamic_cast<
sync_connection_base<Tag, version_major, version_minor>*>(
new https_sync_connection<Tag, version_major, version_minor>(
resolver, resolve, cert_filename, verify_path));
resolver, resolve,
certificate_filename, verify_path,
certificate_file, private_key_file));
#else
throw std::runtime_error("HTTPS not supported.");
#endif
Expand Down
10 changes: 10 additions & 0 deletions boost/network/protocol/http/client/connection/sync_ssl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ struct https_sync_connection
optional<string_type> const& certificate_filename =
optional<string_type>(),
optional<string_type> const& verify_path =
optional<string_type>(),
optional<string_type> const& certificate_file =
optional<string_type>(),
optional<string_type> const& private_key_file =
optional<string_type>())
: connection_base(),
resolver_(resolver),
Expand All @@ -71,6 +75,12 @@ struct https_sync_connection
else
context_.set_verify_mode(boost::asio::ssl::context_base::verify_none);
}
if (certificate_file)
context_.use_certificate_file(
*certificate_file, boost::asio::ssl::context::pem);
if (private_key_file)
context_.use_private_key_file(
*private_key_file, boost::asio::ssl::context::pem);
}

void init_socket(string_type const& hostname, string_type const& port) {
Expand Down
2 changes: 2 additions & 0 deletions boost/network/protocol/http/client/facade.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,8 @@ struct basic_client_facade {
options.always_verify_peer(),
options.openssl_certificate(),
options.openssl_verify_path(),
options.openssl_certificate_file(),
options.openssl_private_key_file(),
options.io_service()));
}
};
Expand Down
26 changes: 26 additions & 0 deletions boost/network/protocol/http/client/options.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ struct client_options {
follow_redirects_(false),
openssl_certificate_(),
openssl_verify_path_(),
openssl_certificate_file_(),
openssl_private_key_file_(),
io_service_(),
always_verify_peer_(false) {}

Expand All @@ -33,6 +35,8 @@ struct client_options {
follow_redirects_(other.follow_redirects_),
openssl_certificate_(other.openssl_certificate_),
openssl_verify_path_(other.openssl_verify_path_),
openssl_certificate_file_(other.openssl_certificate_file_),
openssl_private_key_file_(other.openssl_private_key_file_),
io_service_(other.io_service_),
always_verify_peer_(other.always_verify_peer_) {}

Expand All @@ -47,6 +51,8 @@ struct client_options {
swap(follow_redirects_, other.follow_redirects_);
swap(openssl_certificate_, other.openssl_certificate_);
swap(openssl_verify_path_, other.openssl_verify_path_);
swap(openssl_certificate_file_, other.openssl_certificate_file_);
swap(openssl_private_key_file_, other.openssl_private_key_file_);
swap(io_service_, other.io_service_);
swap(always_verify_peer_, other.always_verify_peer_);
}
Expand All @@ -71,6 +77,16 @@ struct client_options {
return *this;
}

client_options& openssl_certificate_file(string_type const& v) {
openssl_certificate_file_ = v;
return *this;
}

client_options& openssl_private_key_file(string_type const& v) {
openssl_private_key_file_ = v;
return *this;
}

client_options& io_service(boost::shared_ptr<boost::asio::io_service> v) {
io_service_ = v;
return *this;
Expand All @@ -88,6 +104,14 @@ struct client_options {
return openssl_verify_path_;
}

boost::optional<string_type> openssl_certificate_file() const {
return openssl_certificate_file_;
}

boost::optional<string_type> openssl_private_key_file() const {
return openssl_private_key_file_;
}

boost::shared_ptr<boost::asio::io_service> io_service() const {
return io_service_;
}
Expand All @@ -99,6 +123,8 @@ struct client_options {
bool follow_redirects_;
boost::optional<string_type> openssl_certificate_;
boost::optional<string_type> openssl_verify_path_;
boost::optional<string_type> openssl_certificate_file_;
boost::optional<string_type> openssl_private_key_file_;
boost::shared_ptr<boost::asio::io_service> io_service_;
bool always_verify_peer_;
};
Expand Down
5 changes: 4 additions & 1 deletion boost/network/protocol/http/client/pimpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ struct basic_client_impl
bool always_verify_peer,
optional<string_type> const& certificate_filename,
optional<string_type> const& verify_path,
optional<string_type> const& certificate_file,
optional<string_type> const& private_key_file,
boost::shared_ptr<boost::asio::io_service> service)
: base_type(cache_resolved, follow_redirect, always_verify_peer, service,
certificate_filename, verify_path) {}
certificate_filename, verify_path,
certificate_file, private_key_file) {}

~basic_client_impl() {}
};
Expand Down
21 changes: 16 additions & 5 deletions boost/network/protocol/http/client/sync_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,32 @@ struct sync_client
boost::shared_ptr<boost::asio::io_service> service_ptr;
boost::asio::io_service& service_;
resolver_type resolver_;
optional<string_type> certificate_file, verify_path;
optional<string_type> certificate_filename_;
optional<string_type> verify_path_;
optional<string_type> certificate_file_;
optional<string_type> private_key_file_;
bool always_verify_peer_;

sync_client(bool cache_resolved, bool follow_redirect,
bool always_verify_peer,
boost::shared_ptr<boost::asio::io_service> service,
optional<string_type> const& certificate_file =
optional<string_type> const& certificate_filename =
optional<string_type>(),
optional<string_type> const& verify_path =
optional<string_type>(),
optional<string_type> const& certificate_file =
optional<string_type>(),
optional<string_type> const& private_key_file =
optional<string_type>())
: connection_base(cache_resolved, follow_redirect),
service_ptr(service.get() ? service
: make_shared<boost::asio::io_service>()),
service_(*service_ptr),
resolver_(service_),
certificate_file(certificate_file),
verify_path(verify_path),
certificate_filename_(certificate_filename),
verify_path_(verify_path),
certificate_file_(certificate_file),
private_key_file_(private_key_file),
always_verify_peer_(always_verify_peer) {}

~sync_client() {
Expand All @@ -70,7 +79,9 @@ struct sync_client
body_generator_function_type generator) {
typename connection_base::connection_ptr connection_;
connection_ = connection_base::get_connection(
resolver_, request_, certificate_file, verify_path);
resolver_, request_,
certificate_filename_, verify_path_,
certificate_file_, private_key_file_);
return connection_->send_request(method, request_, get_body, callback,
generator);
}
Expand Down
16 changes: 12 additions & 4 deletions boost/network/protocol/http/policies/async_connection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,15 @@ struct async_connection_policy : resolver_policy<Tag>::type {
resolve_function resolve, resolver_type& resolver,
bool https,
optional<string_type> const& certificate_filename,
optional<string_type> const& verify_path) {
optional<string_type> const& verify_path,
optional<string_type> const& certificate_file,
optional<string_type> const& private_key_file) {
pimpl = impl::async_connection_base<
Tag, version_major,
version_minor>::new_connection(resolve, resolver, follow_redirect,
always_verify_peer, https,
certificate_filename, verify_path);
certificate_filename, verify_path,
certificate_file, private_key_file);
}

basic_response<Tag> send_request(string_type const& method,
Expand All @@ -67,15 +70,20 @@ struct async_connection_policy : resolver_policy<Tag>::type {
bool always_verify_peer,
optional<string_type> const& certificate_filename =
optional<string_type>(),
optional<string_type> const& verify_path = optional<string_type>()) {
optional<string_type> const& verify_path =
optional<string_type>(),
optional<string_type> const& certificate_file =
optional<string_type>(),
optional<string_type> const& private_key_file = optional<string_type>()) {
string_type protocol_ = protocol(request_);
connection_ptr connection_(new connection_impl(
follow_redirect_, always_verify_peer,
boost::bind(&async_connection_policy<Tag, version_major,
version_minor>::resolve,
this, _1, _2, _3, _4),
resolver, boost::iequals(protocol_, string_type("https")),
certificate_filename, verify_path));
certificate_filename, verify_path,
certificate_file, private_key_file));
return connection_;
}

Expand Down
Loading