Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/asio/ssl/detail/impl/engine.ipp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children | c530137014c0 |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
1 // | |
2 // ssl/detail/impl/engine.ipp | |
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
4 // | |
5 // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) | |
6 // | |
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
9 // | |
10 | |
11 #ifndef BOOST_ASIO_SSL_DETAIL_IMPL_ENGINE_IPP | |
12 #define BOOST_ASIO_SSL_DETAIL_IMPL_ENGINE_IPP | |
13 | |
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) | |
15 # pragma once | |
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) | |
17 | |
18 #include <boost/asio/detail/config.hpp> | |
19 | |
20 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
21 # include <boost/asio/detail/throw_error.hpp> | |
22 # include <boost/asio/error.hpp> | |
23 # include <boost/asio/ssl/detail/engine.hpp> | |
24 # include <boost/asio/ssl/error.hpp> | |
25 # include <boost/asio/ssl/verify_context.hpp> | |
26 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
27 | |
28 #include <boost/asio/detail/push_options.hpp> | |
29 | |
30 namespace boost { | |
31 namespace asio { | |
32 namespace ssl { | |
33 namespace detail { | |
34 | |
35 #if !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
36 | |
37 engine::engine(SSL_CTX* context) | |
38 : ssl_(::SSL_new(context)) | |
39 { | |
40 if (!ssl_) | |
41 { | |
42 boost::system::error_code ec( | |
43 static_cast<int>(::ERR_get_error()), | |
44 boost::asio::error::get_ssl_category()); | |
45 boost::asio::detail::throw_error(ec, "engine"); | |
46 } | |
47 | |
48 accept_mutex().init(); | |
49 | |
50 ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE); | |
51 ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); | |
52 #if defined(SSL_MODE_RELEASE_BUFFERS) | |
53 ::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); | |
54 #endif // defined(SSL_MODE_RELEASE_BUFFERS) | |
55 | |
56 ::BIO* int_bio = 0; | |
57 ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0); | |
58 ::SSL_set_bio(ssl_, int_bio, int_bio); | |
59 } | |
60 | |
61 engine::~engine() | |
62 { | |
63 if (SSL_get_app_data(ssl_)) | |
64 { | |
65 delete static_cast<verify_callback_base*>(SSL_get_app_data(ssl_)); | |
66 SSL_set_app_data(ssl_, 0); | |
67 } | |
68 | |
69 ::BIO_free(ext_bio_); | |
70 ::SSL_free(ssl_); | |
71 } | |
72 | |
73 SSL* engine::native_handle() | |
74 { | |
75 return ssl_; | |
76 } | |
77 | |
78 boost::system::error_code engine::set_verify_mode( | |
79 verify_mode v, boost::system::error_code& ec) | |
80 { | |
81 ::SSL_set_verify(ssl_, v, ::SSL_get_verify_callback(ssl_)); | |
82 | |
83 ec = boost::system::error_code(); | |
84 return ec; | |
85 } | |
86 | |
87 boost::system::error_code engine::set_verify_depth( | |
88 int depth, boost::system::error_code& ec) | |
89 { | |
90 ::SSL_set_verify_depth(ssl_, depth); | |
91 | |
92 ec = boost::system::error_code(); | |
93 return ec; | |
94 } | |
95 | |
96 boost::system::error_code engine::set_verify_callback( | |
97 verify_callback_base* callback, boost::system::error_code& ec) | |
98 { | |
99 if (SSL_get_app_data(ssl_)) | |
100 delete static_cast<verify_callback_base*>(SSL_get_app_data(ssl_)); | |
101 | |
102 SSL_set_app_data(ssl_, callback); | |
103 | |
104 ::SSL_set_verify(ssl_, ::SSL_get_verify_mode(ssl_), | |
105 &engine::verify_callback_function); | |
106 | |
107 ec = boost::system::error_code(); | |
108 return ec; | |
109 } | |
110 | |
111 int engine::verify_callback_function(int preverified, X509_STORE_CTX* ctx) | |
112 { | |
113 if (ctx) | |
114 { | |
115 if (SSL* ssl = static_cast<SSL*>( | |
116 ::X509_STORE_CTX_get_ex_data( | |
117 ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx()))) | |
118 { | |
119 if (SSL_get_app_data(ssl)) | |
120 { | |
121 verify_callback_base* callback = | |
122 static_cast<verify_callback_base*>( | |
123 SSL_get_app_data(ssl)); | |
124 | |
125 verify_context verify_ctx(ctx); | |
126 return callback->call(preverified != 0, verify_ctx) ? 1 : 0; | |
127 } | |
128 } | |
129 } | |
130 | |
131 return 0; | |
132 } | |
133 | |
134 engine::want engine::handshake( | |
135 stream_base::handshake_type type, boost::system::error_code& ec) | |
136 { | |
137 return perform((type == boost::asio::ssl::stream_base::client) | |
138 ? &engine::do_connect : &engine::do_accept, 0, 0, ec, 0); | |
139 } | |
140 | |
141 engine::want engine::shutdown(boost::system::error_code& ec) | |
142 { | |
143 return perform(&engine::do_shutdown, 0, 0, ec, 0); | |
144 } | |
145 | |
146 engine::want engine::write(const boost::asio::const_buffer& data, | |
147 boost::system::error_code& ec, std::size_t& bytes_transferred) | |
148 { | |
149 if (boost::asio::buffer_size(data) == 0) | |
150 { | |
151 ec = boost::system::error_code(); | |
152 return engine::want_nothing; | |
153 } | |
154 | |
155 return perform(&engine::do_write, | |
156 const_cast<void*>(boost::asio::buffer_cast<const void*>(data)), | |
157 boost::asio::buffer_size(data), ec, &bytes_transferred); | |
158 } | |
159 | |
160 engine::want engine::read(const boost::asio::mutable_buffer& data, | |
161 boost::system::error_code& ec, std::size_t& bytes_transferred) | |
162 { | |
163 if (boost::asio::buffer_size(data) == 0) | |
164 { | |
165 ec = boost::system::error_code(); | |
166 return engine::want_nothing; | |
167 } | |
168 | |
169 return perform(&engine::do_read, | |
170 boost::asio::buffer_cast<void*>(data), | |
171 boost::asio::buffer_size(data), ec, &bytes_transferred); | |
172 } | |
173 | |
174 boost::asio::mutable_buffers_1 engine::get_output( | |
175 const boost::asio::mutable_buffer& data) | |
176 { | |
177 int length = ::BIO_read(ext_bio_, | |
178 boost::asio::buffer_cast<void*>(data), | |
179 static_cast<int>(boost::asio::buffer_size(data))); | |
180 | |
181 return boost::asio::buffer(data, | |
182 length > 0 ? static_cast<std::size_t>(length) : 0); | |
183 } | |
184 | |
185 boost::asio::const_buffer engine::put_input( | |
186 const boost::asio::const_buffer& data) | |
187 { | |
188 int length = ::BIO_write(ext_bio_, | |
189 boost::asio::buffer_cast<const void*>(data), | |
190 static_cast<int>(boost::asio::buffer_size(data))); | |
191 | |
192 return boost::asio::buffer(data + | |
193 (length > 0 ? static_cast<std::size_t>(length) : 0)); | |
194 } | |
195 | |
196 const boost::system::error_code& engine::map_error_code( | |
197 boost::system::error_code& ec) const | |
198 { | |
199 // We only want to map the error::eof code. | |
200 if (ec != boost::asio::error::eof) | |
201 return ec; | |
202 | |
203 // If there's data yet to be read, it's an error. | |
204 if (BIO_wpending(ext_bio_)) | |
205 { | |
206 ec = boost::system::error_code( | |
207 ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), | |
208 boost::asio::error::get_ssl_category()); | |
209 return ec; | |
210 } | |
211 | |
212 // SSL v2 doesn't provide a protocol-level shutdown, so an eof on the | |
213 // underlying transport is passed through. | |
214 if (ssl_ && ssl_->version == SSL2_VERSION) | |
215 return ec; | |
216 | |
217 // Otherwise, the peer should have negotiated a proper shutdown. | |
218 if ((::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) == 0) | |
219 { | |
220 ec = boost::system::error_code( | |
221 ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ), | |
222 boost::asio::error::get_ssl_category()); | |
223 } | |
224 | |
225 return ec; | |
226 } | |
227 | |
228 boost::asio::detail::static_mutex& engine::accept_mutex() | |
229 { | |
230 static boost::asio::detail::static_mutex mutex = BOOST_ASIO_STATIC_MUTEX_INIT; | |
231 return mutex; | |
232 } | |
233 | |
234 engine::want engine::perform(int (engine::* op)(void*, std::size_t), | |
235 void* data, std::size_t length, boost::system::error_code& ec, | |
236 std::size_t* bytes_transferred) | |
237 { | |
238 std::size_t pending_output_before = ::BIO_ctrl_pending(ext_bio_); | |
239 int result = (this->*op)(data, length); | |
240 int ssl_error = ::SSL_get_error(ssl_, result); | |
241 int sys_error = static_cast<int>(::ERR_get_error()); | |
242 std::size_t pending_output_after = ::BIO_ctrl_pending(ext_bio_); | |
243 | |
244 if (ssl_error == SSL_ERROR_SSL) | |
245 { | |
246 ec = boost::system::error_code(sys_error, | |
247 boost::asio::error::get_ssl_category()); | |
248 return want_nothing; | |
249 } | |
250 | |
251 if (ssl_error == SSL_ERROR_SYSCALL) | |
252 { | |
253 ec = boost::system::error_code(sys_error, | |
254 boost::asio::error::get_system_category()); | |
255 return want_nothing; | |
256 } | |
257 | |
258 if (result > 0 && bytes_transferred) | |
259 *bytes_transferred = static_cast<std::size_t>(result); | |
260 | |
261 if (ssl_error == SSL_ERROR_WANT_WRITE) | |
262 { | |
263 ec = boost::system::error_code(); | |
264 return want_output_and_retry; | |
265 } | |
266 else if (pending_output_after > pending_output_before) | |
267 { | |
268 ec = boost::system::error_code(); | |
269 return result > 0 ? want_output : want_output_and_retry; | |
270 } | |
271 else if (ssl_error == SSL_ERROR_WANT_READ) | |
272 { | |
273 ec = boost::system::error_code(); | |
274 return want_input_and_retry; | |
275 } | |
276 else if (::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) | |
277 { | |
278 ec = boost::asio::error::eof; | |
279 return want_nothing; | |
280 } | |
281 else | |
282 { | |
283 ec = boost::system::error_code(); | |
284 return want_nothing; | |
285 } | |
286 } | |
287 | |
288 int engine::do_accept(void*, std::size_t) | |
289 { | |
290 boost::asio::detail::static_mutex::scoped_lock lock(accept_mutex()); | |
291 return ::SSL_accept(ssl_); | |
292 } | |
293 | |
294 int engine::do_connect(void*, std::size_t) | |
295 { | |
296 return ::SSL_connect(ssl_); | |
297 } | |
298 | |
299 int engine::do_shutdown(void*, std::size_t) | |
300 { | |
301 int result = ::SSL_shutdown(ssl_); | |
302 if (result == 0) | |
303 result = ::SSL_shutdown(ssl_); | |
304 return result; | |
305 } | |
306 | |
307 int engine::do_read(void* data, std::size_t length) | |
308 { | |
309 return ::SSL_read(ssl_, data, | |
310 length < INT_MAX ? static_cast<int>(length) : INT_MAX); | |
311 } | |
312 | |
313 int engine::do_write(void* data, std::size_t length) | |
314 { | |
315 return ::SSL_write(ssl_, data, | |
316 length < INT_MAX ? static_cast<int>(length) : INT_MAX); | |
317 } | |
318 | |
319 #endif // !defined(BOOST_ASIO_ENABLE_OLD_SSL) | |
320 | |
321 } // namespace detail | |
322 } // namespace ssl | |
323 } // namespace asio | |
324 } // namespace boost | |
325 | |
326 #include <boost/asio/detail/pop_options.hpp> | |
327 | |
328 #endif // BOOST_ASIO_SSL_DETAIL_IMPL_ENGINE_IPP |