Skip to content

Commit e17e8cd

Browse files
committed
Merge pull request cpp-netlib#530 from theopolis/ssl_method
Add HTTP client options for SSL/TLS methods
2 parents 284b643 + 4f7fb06 commit e17e8cd

14 files changed

+132
-47
lines changed

boost/network/protocol/http/client/async_impl.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ struct async_client
4242
optional<string_type> const& certificate_filename,
4343
optional<string_type> const& verify_path,
4444
optional<string_type> const& certificate_file,
45-
optional<string_type> const& private_key_file)
45+
optional<string_type> const& private_key_file,
46+
optional<string_type> const& ciphers, long ssl_options)
4647
: connection_base(cache_resolved, follow_redirect, timeout),
4748
service_ptr(service.get()
4849
? service
@@ -54,6 +55,8 @@ struct async_client
5455
verify_path_(verify_path),
5556
certificate_file_(certificate_file),
5657
private_key_file_(private_key_file),
58+
ciphers_(ciphers),
59+
ssl_options_(ssl_options),
5760
always_verify_peer_(always_verify_peer) {
5861
connection_base::resolver_strand_.reset(
5962
new boost::asio::io_service::strand(service_));
@@ -79,7 +82,8 @@ struct async_client
7982
typename connection_base::connection_ptr connection_;
8083
connection_ = connection_base::get_connection(
8184
resolver_, request_, always_verify_peer_, certificate_filename_,
82-
verify_path_, certificate_file_, private_key_file_);
85+
verify_path_, certificate_file_, private_key_file_, ciphers_,
86+
ssl_options_);
8387
return connection_->send_request(method, request_, get_body, callback,
8488
generator);
8589
}
@@ -93,6 +97,8 @@ struct async_client
9397
optional<string_type> verify_path_;
9498
optional<string_type> certificate_file_;
9599
optional<string_type> private_key_file_;
100+
optional<string_type> ciphers_;
101+
long ssl_options_;
96102
bool always_verify_peer_;
97103
};
98104
} // namespace impl

boost/network/protocol/http/client/connection/async_base.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ struct async_connection_base {
4343
optional<string_type> certificate_filename = optional<string_type>(),
4444
optional<string_type> const &verify_path = optional<string_type>(),
4545
optional<string_type> certificate_file = optional<string_type>(),
46-
optional<string_type> private_key_file = optional<string_type>()) {
46+
optional<string_type> private_key_file = optional<string_type>(),
47+
optional<string_type> ciphers = optional<string_type>(),
48+
long ssl_options = 0) {
4749
typedef http_async_connection<Tag, version_major, version_minor>
4850
async_connection;
4951
typedef typename delegate_factory<Tag>::type delegate_factory_type;
@@ -53,7 +55,7 @@ struct async_connection_base {
5355
delegate_factory_type::new_connection_delegate(
5456
resolver.get_io_service(), https, always_verify_peer,
5557
certificate_filename, verify_path, certificate_file,
56-
private_key_file)));
58+
private_key_file, ciphers, ssl_options)));
5759
BOOST_ASSERT(temp.get() != 0);
5860
return temp;
5961
}

boost/network/protocol/http/client/connection/connection_delegate_factory.hpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ struct connection_delegate_factory {
3535
asio::io_service& service, bool https, bool always_verify_peer,
3636
optional<string_type> certificate_filename,
3737
optional<string_type> verify_path, optional<string_type> certificate_file,
38-
optional<string_type> private_key_file) {
38+
optional<string_type> private_key_file, optional<string_type> ciphers,
39+
long ssl_options) {
3940
connection_delegate_ptr delegate;
4041
if (https) {
4142
#ifdef BOOST_NETWORK_ENABLE_HTTPS
42-
delegate.reset(new ssl_delegate(service, always_verify_peer,
43-
certificate_filename, verify_path,
44-
certificate_file, private_key_file));
43+
delegate.reset(new ssl_delegate(
44+
service, always_verify_peer, certificate_filename, verify_path,
45+
certificate_file, private_key_file, ciphers, ssl_options));
4546
#else
4647
BOOST_THROW_EXCEPTION(std::runtime_error("HTTPS not supported."));
4748
#endif /* BOOST_NETWORK_ENABLE_HTTPS */

boost/network/protocol/http/client/connection/ssl_delegate.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ struct ssl_delegate : connection_delegate,
2626
optional<std::string> certificate_filename,
2727
optional<std::string> verify_path,
2828
optional<std::string> certificate_file,
29-
optional<std::string> private_key_file);
29+
optional<std::string> private_key_file,
30+
optional<std::string> ciphers, long ssl_options);
3031

3132
virtual void connect(asio::ip::tcp::endpoint &endpoint, std::string host,
3233
function<void(system::error_code const &)> handler);
@@ -45,6 +46,8 @@ struct ssl_delegate : connection_delegate,
4546
optional<std::string> verify_path_;
4647
optional<std::string> certificate_file_;
4748
optional<std::string> private_key_file_;
49+
optional<std::string> ciphers_;
50+
long ssl_options_;
4851
scoped_ptr<asio::ssl::context> context_;
4952
scoped_ptr<asio::ssl::stream<asio::ip::tcp::socket> > socket_;
5053
bool always_verify_peer_;

boost/network/protocol/http/client/connection/ssl_delegate.ipp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,31 @@
1414
boost::network::http::impl::ssl_delegate::ssl_delegate(
1515
asio::io_service &service, bool always_verify_peer,
1616
optional<std::string> certificate_filename,
17-
optional<std::string> verify_path, optional<std::string> certificate_file,
18-
optional<std::string> private_key_file)
17+
optional<std::string> verify_path,
18+
optional<std::string> certificate_file,
19+
optional<std::string> private_key_file,
20+
optional<std::string> ciphers,
21+
long ssl_options)
1922
: service_(service),
2023
certificate_filename_(certificate_filename),
2124
verify_path_(verify_path),
2225
certificate_file_(certificate_file),
2326
private_key_file_(private_key_file),
27+
ciphers_(ciphers),
28+
ssl_options_(ssl_options),
2429
always_verify_peer_(always_verify_peer) {}
2530

2631
void boost::network::http::impl::ssl_delegate::connect(
2732
asio::ip::tcp::endpoint &endpoint, std::string host,
2833
function<void(system::error_code const &)> handler) {
2934
context_.reset(
3035
new asio::ssl::context(service_, asio::ssl::context::sslv23_client));
36+
if (ciphers_) {
37+
::SSL_CTX_set_cipher_list(context_->native_handle(), ciphers_->c_str());
38+
}
39+
if (ssl_options_ != 0) {
40+
context_->set_options(ssl_options_);
41+
}
3142
if (certificate_filename_ || verify_path_) {
3243
context_->set_verify_mode(asio::ssl::context::verify_peer);
3344
if (certificate_filename_)
@@ -36,9 +47,10 @@ void boost::network::http::impl::ssl_delegate::connect(
3647
} else {
3748
if (always_verify_peer_) {
3849
context_->set_verify_mode(asio::ssl::context::verify_peer);
39-
context_->set_default_verify_paths(); // use openssl default verify paths. uses openssl environment variables SSL_CERT_DIR, SSL_CERT_FILE
40-
}
41-
else
50+
// use openssl default verify paths. uses openssl environment variables
51+
// SSL_CERT_DIR, SSL_CERT_FILE
52+
context_->set_default_verify_paths();
53+
} else
4254
context_->set_verify_mode(asio::ssl::context::verify_none);
4355
}
4456
if (certificate_file_)

boost/network/protocol/http/client/connection/sync_base.hpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -245,22 +245,26 @@ struct sync_connection_base {
245245
// optional
246246
// ranges
247247
static sync_connection_base<Tag, version_major, version_minor>*
248-
new_connection(
249-
resolver_type& resolver, resolver_function_type resolve, bool https,
250-
bool always_verify_peer, int timeout,
251-
optional<string_type> const& certificate_filename =
252-
optional<string_type>(),
253-
optional<string_type> const& verify_path = optional<string_type>(),
254-
optional<string_type> const& certificate_file = optional<string_type>(),
255-
optional<string_type> const& private_key_file = optional<string_type>()) {
248+
new_connection(
249+
resolver_type& resolver, resolver_function_type resolve, bool https,
250+
bool always_verify_peer, int timeout,
251+
optional<string_type> const& certificate_filename =
252+
optional<string_type>(),
253+
optional<string_type> const& verify_path = optional<string_type>(),
254+
optional<string_type> const& certificate_file =
255+
optional<string_type>(),
256+
optional<string_type> const& private_key_file =
257+
optional<string_type>(),
258+
optional<string_type> const& ciphers = optional<string_type>(),
259+
long ssl_options = 0) {
256260
if (https) {
257261
#ifdef BOOST_NETWORK_ENABLE_HTTPS
258262
return dynamic_cast<
259263
sync_connection_base<Tag, version_major, version_minor>*>(
260264
new https_sync_connection<Tag, version_major, version_minor>(
261265
resolver, resolve, always_verify_peer, timeout,
262266
certificate_filename, verify_path, certificate_file,
263-
private_key_file));
267+
private_key_file, ciphers, ssl_options));
264268
#else
265269
throw std::runtime_error("HTTPS not supported.");
266270
#endif

boost/network/protocol/http/client/connection/sync_ssl.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ struct https_sync_connection
5656
optional<string_type>(),
5757
optional<string_type> const& verify_path = optional<string_type>(),
5858
optional<string_type> const& certificate_file = optional<string_type>(),
59-
optional<string_type> const& private_key_file = optional<string_type>())
59+
optional<string_type> const& private_key_file = optional<string_type>(),
60+
optional<string_type> const& ciphers = optional<string_type>(),
61+
long ssl_options = 0)
6062
: connection_base(),
6163
timeout_(timeout),
6264
timer_(resolver.get_io_service()),
@@ -65,6 +67,12 @@ struct https_sync_connection
6567
context_(resolver.get_io_service(),
6668
boost::asio::ssl::context::sslv23_client),
6769
socket_(resolver.get_io_service(), context_) {
70+
if (ciphers) {
71+
::SSL_CTX_set_cipher_list(context_.native_handle(), ciphers->c_str());
72+
}
73+
if (ssl_options != 0) {
74+
context_.set_options(ssl_options);
75+
}
6876
if (certificate_filename || verify_path) {
6977
context_.set_verify_mode(boost::asio::ssl::context::verify_peer);
7078
// FIXME make the certificate filename and verify path parameters

boost/network/protocol/http/client/facade.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ struct basic_client_facade {
162162
options.cache_resolved(), options.follow_redirects(),
163163
options.always_verify_peer(), options.openssl_certificate(),
164164
options.openssl_verify_path(), options.openssl_certificate_file(),
165-
options.openssl_private_key_file(), options.io_service(),
166-
options.timeout()));
165+
options.openssl_private_key_file(), options.openssl_ciphers(),
166+
options.openssl_options(), options.io_service(), options.timeout()));
167167
}
168168
};
169169

boost/network/protocol/http/client/options.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct client_options {
2727
openssl_verify_path_(),
2828
openssl_certificate_file_(),
2929
openssl_private_key_file_(),
30+
openssl_ciphers_(),
31+
openssl_options_(0),
3032
io_service_(),
3133
always_verify_peer_(false),
3234
timeout_(0) {}
@@ -38,6 +40,8 @@ struct client_options {
3840
openssl_verify_path_(other.openssl_verify_path_),
3941
openssl_certificate_file_(other.openssl_certificate_file_),
4042
openssl_private_key_file_(other.openssl_private_key_file_),
43+
openssl_ciphers_(other.openssl_ciphers_),
44+
openssl_options_(other.openssl_options_),
4145
io_service_(other.io_service_),
4246
always_verify_peer_(other.always_verify_peer_),
4347
timeout_(other.timeout_) {}
@@ -55,6 +59,8 @@ struct client_options {
5559
swap(openssl_verify_path_, other.openssl_verify_path_);
5660
swap(openssl_certificate_file_, other.openssl_certificate_file_);
5761
swap(openssl_private_key_file_, other.openssl_private_key_file_);
62+
swap(openssl_ciphers_, other.openssl_ciphers_);
63+
swap(openssl_options_, other.openssl_options_);
5864
swap(io_service_, other.io_service_);
5965
swap(always_verify_peer_, other.always_verify_peer_);
6066
swap(timeout_, other.timeout_);
@@ -90,6 +96,16 @@ struct client_options {
9096
return *this;
9197
}
9298

99+
client_options& openssl_ciphers(string_type const& v) {
100+
openssl_ciphers_ = v;
101+
return *this;
102+
}
103+
104+
client_options& openssl_options(long o) {
105+
openssl_options_ = o;
106+
return *this;
107+
}
108+
93109
client_options& io_service(boost::shared_ptr<boost::asio::io_service> v) {
94110
io_service_ = v;
95111
return *this;
@@ -125,6 +141,12 @@ struct client_options {
125141
return openssl_private_key_file_;
126142
}
127143

144+
boost::optional<string_type> openssl_ciphers() const {
145+
return openssl_ciphers_;
146+
}
147+
148+
long openssl_options() const { return openssl_options_; }
149+
128150
boost::shared_ptr<boost::asio::io_service> io_service() const {
129151
return io_service_;
130152
}
@@ -140,6 +162,8 @@ struct client_options {
140162
boost::optional<string_type> openssl_verify_path_;
141163
boost::optional<string_type> openssl_certificate_file_;
142164
boost::optional<string_type> openssl_private_key_file_;
165+
boost::optional<string_type> openssl_ciphers_;
166+
long openssl_options_;
143167
boost::shared_ptr<boost::asio::io_service> io_service_;
144168
bool always_verify_peer_;
145169
int timeout_;

boost/network/protocol/http/client/pimpl.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ struct basic_client_impl
7171
optional<string_type> const& verify_path,
7272
optional<string_type> const& certificate_file,
7373
optional<string_type> const& private_key_file,
74+
optional<string_type> const& ciphers, long ssl_options,
7475
boost::shared_ptr<boost::asio::io_service> service,
7576
int timeout)
7677
: base_type(cache_resolved, follow_redirect, always_verify_peer, timeout,
7778
service, certificate_filename, verify_path, certificate_file,
78-
private_key_file) {}
79+
private_key_file, ciphers, ssl_options) {}
7980

8081
~basic_client_impl() {}
8182
};

boost/network/protocol/http/client/sync_impl.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ struct sync_client
4444
optional<string_type> verify_path_;
4545
optional<string_type> certificate_file_;
4646
optional<string_type> private_key_file_;
47+
optional<string_type> ciphers_;
48+
long ssl_options_;
4749
bool always_verify_peer_;
4850

4951
sync_client(
@@ -53,7 +55,9 @@ struct sync_client
5355
optional<string_type>(),
5456
optional<string_type> const& verify_path = optional<string_type>(),
5557
optional<string_type> const& certificate_file = optional<string_type>(),
56-
optional<string_type> const& private_key_file = optional<string_type>())
58+
optional<string_type> const& private_key_file = optional<string_type>(),
59+
optional<string_type> const& ciphers = optional<string_type>(),
60+
long ssl_options = 0)
5761
: connection_base(cache_resolved, follow_redirect, timeout),
5862
service_ptr(service.get() ? service
5963
: make_shared<boost::asio::io_service>()),
@@ -63,6 +67,8 @@ struct sync_client
6367
verify_path_(verify_path),
6468
certificate_file_(certificate_file),
6569
private_key_file_(private_key_file),
70+
ciphers_(ciphers),
71+
ssl_options_(ssl_options),
6672
always_verify_peer_(always_verify_peer) {}
6773

6874
~sync_client() {
@@ -79,7 +85,7 @@ struct sync_client
7985
typename connection_base::connection_ptr connection_;
8086
connection_ = connection_base::get_connection(
8187
resolver_, request_, always_verify_peer_, certificate_filename_,
82-
verify_path_, certificate_file_, private_key_file_);
88+
verify_path_, certificate_file_, private_key_file_, ciphers_);
8389
return connection_->send_request(method, request_, get_body, callback,
8490
generator);
8591
}

boost/network/protocol/http/policies/async_connection.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ struct async_connection_policy : resolver_policy<Tag>::type {
4242
optional<string_type> const& certificate_filename,
4343
optional<string_type> const& verify_path,
4444
optional<string_type> const& certificate_file,
45-
optional<string_type> const& private_key_file) {
45+
optional<string_type> const& private_key_file,
46+
optional<string_type> const& ciphers, long ssl_options) {
4647
pimpl = impl::async_connection_base<
4748
Tag, version_major,
4849
version_minor>::new_connection(resolve, resolver, follow_redirect,
4950
always_verify_peer, https, timeout,
5051
certificate_filename, verify_path,
51-
certificate_file, private_key_file);
52+
certificate_file, private_key_file,
53+
ciphers, ssl_options);
5254
}
5355

5456
basic_response<Tag> send_request(string_type const& method,
@@ -72,7 +74,9 @@ struct async_connection_policy : resolver_policy<Tag>::type {
7274
optional<string_type>(),
7375
optional<string_type> const& verify_path = optional<string_type>(),
7476
optional<string_type> const& certificate_file = optional<string_type>(),
75-
optional<string_type> const& private_key_file = optional<string_type>()) {
77+
optional<string_type> const& private_key_file = optional<string_type>(),
78+
optional<string_type> const& ciphers = optional<string_type>(),
79+
long ssl_options = 0) {
7680
string_type protocol_ = protocol(request_);
7781
connection_ptr connection_(new connection_impl(
7882
follow_redirect_, always_verify_peer,
@@ -81,7 +85,8 @@ struct async_connection_policy : resolver_policy<Tag>::type {
8185
this, boost::arg<1>(), boost::arg<2>(), boost::arg<3>(),
8286
boost::arg<4>()),
8387
resolver, boost::iequals(protocol_, string_type("https")), timeout_,
84-
certificate_filename, verify_path, certificate_file, private_key_file));
88+
certificate_filename, verify_path, certificate_file, private_key_file,
89+
ciphers, ssl_options));
8590
return connection_;
8691
}
8792

0 commit comments

Comments
 (0)