Skip to content

Commit 80d1798

Browse files
committed
Support OpenSSL Certificate Filename and Path
The HTTP client implementation gets a couple of new options in the constructor that should allow users to provide a certificate filename to use (_openssl_certificate) or a verification path that contains the certificates (_openssl_verify_path).
1 parent fc4a530 commit 80d1798

File tree

11 files changed

+84
-39
lines changed

11 files changed

+84
-39
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@ namespace boost { namespace network { namespace http {
3131
typename string<Tag>::type
3232
string_type;
3333

34-
async_client(bool cache_resolved, bool follow_redirect)
34+
async_client(bool cache_resolved, bool follow_redirect, optional<string_type> const & certificate_filename, optional<string_type> const & verify_path)
3535
: connection_base(cache_resolved, follow_redirect),
3636
service_ptr(new boost::asio::io_service),
3737
service_(*service_ptr),
3838
resolver_(service_),
39-
sentinel_(new boost::asio::io_service::work(service_))
39+
sentinel_(new boost::asio::io_service::work(service_)),
40+
certificate_filename_(certificate_filename),
41+
verify_path_(verify_path)
4042
{
4143
connection_base::resolver_strand_.reset(new
4244
boost::asio::io_service::strand(service_));
@@ -47,12 +49,14 @@ namespace boost { namespace network { namespace http {
4749
)));
4850
}
4951

50-
async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service)
52+
async_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional<string_type> const & certificate_filename, optional<string_type> const & verify_path)
5153
: connection_base(cache_resolved, follow_redirect),
5254
service_ptr(0),
5355
service_(service),
5456
resolver_(service_),
55-
sentinel_(new boost::asio::io_service::work(service_))
57+
sentinel_(new boost::asio::io_service::work(service_)),
58+
certificate_filename_(certificate_filename),
59+
verify_path_(verify_path)
5660
{
5761
}
5862

@@ -73,7 +77,7 @@ namespace boost { namespace network { namespace http {
7377
)
7478
{
7579
typename connection_base::connection_ptr connection_;
76-
connection_ = connection_base::get_connection(resolver_, request_);
80+
connection_ = connection_base::get_connection(resolver_, request_, certificate_filename_, verify_path_);
7781
return connection_->send_request(method, request_, get_body);
7882
}
7983

@@ -82,6 +86,7 @@ namespace boost { namespace network { namespace http {
8286
resolver_type resolver_;
8387
boost::shared_ptr<boost::asio::io_service::work> sentinel_;
8488
boost::shared_ptr<boost::thread> lifetime_thread_;
89+
optional<string_type> certificate_filename_, verify_path_;
8590
};
8691
} // namespace impl
8792

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ namespace boost { namespace network { namespace http { namespace impl {
2424
typedef basic_request<Tag> request;
2525
typedef basic_response<Tag> response;
2626

27-
static boost::shared_ptr<async_connection_base<Tag,version_major,version_minor> > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https) {
27+
static boost::shared_ptr<async_connection_base<Tag,version_major,version_minor> > new_connection(resolve_function resolve, resolver_type & resolver, bool follow_redirect, bool https, optional<string_type> certificate_filename=optional<string_type>(), optional<string_type> const & verify_path=optional<string_type>()) {
2828
boost::shared_ptr<async_connection_base<Tag,version_major,version_minor> > temp;
2929
if (https) {
3030
#ifdef BOOST_NETWORK_ENABLE_HTTPS
31-
temp.reset(new https_async_connection<Tag,version_major,version_minor>(resolver, resolve, follow_redirect));
31+
temp.reset(new https_async_connection<Tag,version_major,version_minor>(resolver, resolve, follow_redirect, certificate_filename, verify_path));
3232
return temp;
3333
#else
3434
throw std::runtime_error("HTTPS not supported.");

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,13 @@ namespace boost { namespace network { namespace http { namespace impl {
3737
resolver_type & resolver,
3838
resolve_function resolve,
3939
bool follow_redirect,
40-
optional<string_type> const & certificate_filename = optional<string_type>()
40+
optional<string_type> const & certificate_filename = optional<string_type>(),
41+
optional<string_type> const & verify_path = optional<string_type>()
4142
) :
4243
follow_redirect_(follow_redirect),
4344
resolver_(resolver),
4445
certificate_filename_(certificate_filename),
46+
verify_path_(verify_path),
4547
resolve_(resolve),
4648
request_strand_(resolver.get_io_service())
4749
{}
@@ -78,9 +80,10 @@ namespace boost { namespace network { namespace http { namespace impl {
7880
boost::asio::ssl::context::sslv23_client
7981
)
8082
);
81-
if (certificate_filename_) {
83+
if (certificate_filename_ || verify_path_) {
8284
context_->set_verify_mode(boost::asio::ssl::context::verify_peer);
83-
context_->load_verify_file(*certificate_filename_);
85+
if (certificate_filename_) context_->load_verify_file(*certificate_filename_);
86+
if (verify_path_) context_->add_verify_path(*verify_path_);
8487
} else {
8588
context_->set_verify_mode(boost::asio::ssl::context::verify_none);
8689
}
@@ -342,7 +345,7 @@ namespace boost { namespace network { namespace http { namespace impl {
342345

343346
bool follow_redirect_;
344347
resolver_type & resolver_;
345-
optional<string_type> certificate_filename_;
348+
optional<string_type> certificate_filename_, verify_path_;
346349
resolve_function resolve_;
347350
boost::shared_ptr<boost::asio::ssl::context> context_;
348351
boost::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> > socket_;

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,11 @@ namespace boost { namespace network { namespace http { namespace impl {
210210
typedef typename string<Tag>::type string_type;
211211
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type&, string_type const &, string_type const &)> resolver_function_type;
212212

213-
static sync_connection_base<Tag,version_major,version_minor> * new_connection(resolver_type & resolver, resolver_function_type resolve, bool https) {
213+
// FIXME make the certificate filename and verify path parameters be optional ranges
214+
static sync_connection_base<Tag,version_major,version_minor> * new_connection(resolver_type & resolver, resolver_function_type resolve, bool https, optional<string_type> const & cert_filename = optional<string_type>(), optional<string_type> const & verify_path = optional<string_type>()) {
214215
if (https) {
215216
#ifdef BOOST_NETWORK_ENABLE_HTTPS
216-
return dynamic_cast<sync_connection_base<Tag,version_major,version_minor>*>(new https_sync_connection<Tag,version_major,version_minor>(resolver, resolve));
217+
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));
217218
#else
218219
throw std::runtime_error("HTTPS not supported.");
219220
#endif

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ namespace boost { namespace network { namespace http { namespace impl {
2525
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type&, string_type const &, string_type const &)> resolver_function_type;
2626
typedef sync_connection_base_impl<Tag,version_major,version_minor> connection_base;
2727

28-
https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional<string_type> const & certificate_filename = optional<string_type>())
28+
// FIXME make the certificate filename and verify path parameters be optional ranges
29+
https_sync_connection(resolver_type & resolver, resolver_function_type resolve, optional<string_type> const & certificate_filename = optional<string_type>(), optional<string_type> const & verify_path = optional<string_type>())
2930
: connection_base(), resolver_(resolver), resolve_(resolve), context_(resolver.io_service(), boost::asio::ssl::context::sslv23_client), socket_(resolver.io_service(), context_) {
30-
if (certificate_filename) {
31+
if (certificate_filename || verify_path) {
3132
context_.set_verify_mode(boost::asio::ssl::context::verify_peer);
32-
context_.load_verify_file(*certificate_filename);
33+
// FIXME make the certificate filename and verify path parameters be optional ranges
34+
if (certificate_filename) context_.load_verify_file(*certificate_filename);
35+
if (verify_path) context_.add_verify_path(*verify_path);
3336
} else {
3437
context_.set_verify_mode(boost::asio::ssl::context::verify_none);
3538
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ namespace boost { namespace network { namespace http {
3939
no_io_service,
4040
has_io_service
4141
>::type());
42-
4342
}
4443

4544
response const head (request const & request_) {
@@ -117,6 +116,8 @@ namespace boost { namespace network { namespace http {
117116
new pimpl_type(
118117
args[_cache_resolved|false]
119118
, args[_follow_redirects|false]
119+
, args[_openssl_certificate|optional<string_type>()]
120+
, args[_openssl_verify_path|optional<string_type>()]
120121
)
121122
);
122123
}
@@ -128,6 +129,8 @@ namespace boost { namespace network { namespace http {
128129
args[_cache_resolved|false]
129130
, args[_follow_redirects|false]
130131
, args[_io_service]
132+
, args[_openssl_certificate|optional<string_type>()]
133+
, args[_openssl_verify_path|optional<string_type>()]
131134
)
132135
);
133136
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ namespace boost { namespace network { namespace http {
1212

1313
BOOST_PARAMETER_NAME(follow_redirects)
1414
BOOST_PARAMETER_NAME(cache_resolved)
15+
BOOST_PARAMETER_NAME(openssl_certificate)
16+
BOOST_PARAMETER_NAME(openssl_verify_path)
1517

1618
} /* http */
1719

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

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,30 @@ namespace boost { namespace network { namespace http {
3838
boost::asio::io_service * service_ptr;
3939
boost::asio::io_service & service_;
4040
resolver_type resolver_;
41+
optional<string_type> certificate_file, verify_path;
4142

42-
sync_client(bool cache_resolved, bool follow_redirect)
43+
sync_client(bool cache_resolved, bool follow_redirect
44+
, optional<string_type> const & certificate_file = optional<string_type>()
45+
, optional<string_type> const & verify_path = optional<string_type>()
46+
)
4347
: connection_base(cache_resolved, follow_redirect),
4448
service_ptr(new boost::asio::io_service),
4549
service_(*service_ptr),
4650
resolver_(service_)
51+
, certificate_file(certificate_file)
52+
, verify_path(verify_path)
4753
{}
4854

49-
sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service)
55+
sync_client(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service
56+
, optional<string_type> const & certificate_file = optional<string_type>()
57+
, optional<string_type> const & verify_path = optional<string_type>()
58+
)
5059
: connection_base(cache_resolved, follow_redirect),
5160
service_ptr(0),
5261
service_(service),
5362
resolver_(service_)
63+
, certificate_file(certificate_file)
64+
, verify_path(verify_path)
5465
{}
5566

5667
~sync_client() {
@@ -59,7 +70,7 @@ namespace boost { namespace network { namespace http {
5970

6071
basic_response<Tag> const request_skeleton(basic_request<Tag> const & request_, string_type method, bool get_body) {
6172
typename connection_base::connection_ptr connection_;
62-
connection_ = connection_base::get_connection(resolver_, request_);
73+
connection_ = connection_base::get_connection(resolver_, request_, certificate_file, verify_path);
6374
return connection_->send_request(method, request_, get_body);
6475
}
6576

@@ -91,14 +102,16 @@ namespace boost { namespace network { namespace http {
91102
>
92103
>::value
93104
));
94-
105+
95106
typedef typename impl::client_base<Tag,version_major,version_minor>::type base_type;
96-
basic_client_impl(bool cache_resolved, bool follow_redirect)
97-
: base_type(cache_resolved, follow_redirect)
107+
typedef typename base_type::string_type string_type;
108+
109+
basic_client_impl(bool cache_resolved, bool follow_redirect, optional<string_type> const & certificate_filename, optional<string_type> const & verify_path)
110+
: base_type(cache_resolved, follow_redirect, certificate_filename, verify_path)
98111
{}
99112

100-
basic_client_impl(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service)
101-
: base_type(cache_resolved, follow_redirect, service)
113+
basic_client_impl(bool cache_resolved, bool follow_redirect, boost::asio::io_service & service, optional<string_type> const & certificate_filename, optional<string_type> const & verify_path)
114+
: base_type(cache_resolved, follow_redirect, service, certificate_filename, verify_path)
102115
{}
103116

104117
~basic_client_impl()

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ namespace boost { namespace network { namespace http {
3434
bool follow_redirect,
3535
resolve_function resolve,
3636
resolver_type & resolver,
37-
bool https
37+
bool https,
38+
optional<string_type> const & certificate_filename,
39+
optional<string_type> const & verify_path
3840
)
3941
{
40-
pimpl = impl::async_connection_base<Tag,version_major,version_minor>::new_connection(resolve, resolver, follow_redirect, https);
42+
pimpl = impl::async_connection_base<Tag,version_major,version_minor>::new_connection(resolve, resolver, follow_redirect, https, certificate_filename, verify_path);
4143
}
4244

4345
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> const & request_, bool get_body) {
@@ -51,7 +53,7 @@ namespace boost { namespace network { namespace http {
5153
};
5254

5355
typedef boost::shared_ptr<connection_impl> connection_ptr;
54-
connection_ptr get_connection(resolver_type & resolver, basic_request<Tag> const & request_) {
56+
connection_ptr get_connection(resolver_type & resolver, basic_request<Tag> const & request_, optional<string_type> const & certificate_filename = optional<string_type>(), optional<string_type> const & verify_path = optional<string_type>()) {
5557
string_type protocol_ = protocol(request_);
5658
connection_ptr connection_(
5759
new connection_impl(
@@ -62,7 +64,9 @@ namespace boost { namespace network { namespace http {
6264
_1, _2, _3, _4
6365
)
6466
, resolver
65-
, boost::iequals(protocol_, string_type("https"))));
67+
, boost::iequals(protocol_, string_type("https"))
68+
, certificate_filename
69+
, verify_path));
6670
return connection_;
6771
}
6872

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,16 @@ namespace boost { namespace network { namespace http {
3131
typedef function<typename resolver_base::resolver_iterator_pair(resolver_type &, string_type const &, string_type const &)> resolver_function_type;
3232

3333
struct connection_impl {
34-
typedef function<shared_ptr<connection_impl>(resolver_type &,basic_request<Tag> const &)> get_connection_function;
34+
typedef function<shared_ptr<connection_impl>(resolver_type &,basic_request<Tag> const &,optional<string_type> const &, optional<string_type> const &)> get_connection_function;
3535

36-
connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, get_connection_function get_connection, bool https)
37-
: pimpl(impl::sync_connection_base<Tag,version_major,version_minor>::new_connection(resolver, resolve, https))
36+
connection_impl(resolver_type & resolver, bool follow_redirect, string_type const & host, string_type const & port, resolver_function_type resolve, get_connection_function get_connection, bool https, optional<string_type> const & certificate_file=optional<string_type>(), optional<string_type> const & verify_path=optional<string_type>())
37+
: pimpl(impl::sync_connection_base<Tag,version_major,version_minor>::new_connection(resolver, resolve, https, certificate_file, verify_path))
3838
, resolver_(resolver)
3939
, connection_follow_redirect_(follow_redirect)
40-
, get_connection_(get_connection) {}
40+
, get_connection_(get_connection)
41+
, certificate_filename_(certificate_file)
42+
, verify_path_(verify_path)
43+
{}
4144

4245
basic_response<Tag> send_request(string_type const & method, basic_request<Tag> request_, bool get_body) {
4346
return send_request_impl(method, request_, get_body);
@@ -104,7 +107,7 @@ namespace boost { namespace network { namespace http {
104107
if (location_header != boost::end(location_range)) {
105108
request_.uri(location_header->second);
106109
connection_ptr connection_;
107-
connection_ = get_connection_(resolver_, request_);
110+
connection_ = get_connection_(resolver_, request_, certificate_filename_, verify_path_);
108111
++count;
109112
continue;
110113
} else throw std::runtime_error("Location header not defined in redirect response.");
@@ -118,6 +121,7 @@ namespace boost { namespace network { namespace http {
118121
resolver_type & resolver_;
119122
bool connection_follow_redirect_;
120123
get_connection_function get_connection_;
124+
optional<string_type> certificate_filename_, verify_path_;
121125
};
122126

123127
typedef shared_ptr<connection_impl> connection_ptr;
@@ -126,7 +130,7 @@ namespace boost { namespace network { namespace http {
126130
host_connection_map host_connections;
127131
bool follow_redirect_;
128132

129-
connection_ptr get_connection(resolver_type & resolver, basic_request<Tag> const & request_) {
133+
connection_ptr get_connection(resolver_type & resolver, basic_request<Tag> const & request_, optional<string_type> const & certificate_filename = optional<string_type>(), optional<string_type> const & verify_path = optional<string_type>()) {
130134
string_type index = (request_.host() + ':') + lexical_cast<string_type>(request_.port());
131135
connection_ptr connection_;
132136
typename host_connection_map::iterator it =
@@ -145,9 +149,11 @@ namespace boost { namespace network { namespace http {
145149
, boost::bind(
146150
&pooled_connection_policy<Tag,version_major,version_minor>::get_connection,
147151
this,
148-
_1, _2
152+
_1, _2, _3, _4
149153
)
150154
, boost::iequals(request_.protocol(), string_type("https"))
155+
, certificate_filename
156+
, verify_path
151157
)
152158
);
153159
host_connections.insert(std::make_pair(index, connection_));

0 commit comments

Comments
 (0)