Line data Source code
1 : // Event Dispatcher
2 : // Copyright (c) 2012-2019 Made to Order Software Corp. All Rights Reserved
3 : //
4 : // This program is free software; you can redistribute it and/or modify
5 : // it under the terms of the GNU General Public License as published by
6 : // the Free Software Foundation; either version 2 of the License, or
7 : // (at your option) any later version.
8 : //
9 : // This program is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : // GNU General Public License for more details.
13 : //
14 : // You should have received a copy of the GNU General Public License
15 : // along with this program; if not, write to the Free Software
16 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 :
18 : // make sure we use OpenSSL with multi-thread support
19 : // (TODO: move to .cpp once we have the impl!)
20 : #define OPENSSL_THREAD_DEFINES
21 :
22 : // self
23 : //
24 : #include "eventdispatcher/tcp_private.h"
25 :
26 : #include "eventdispatcher/exception.h"
27 :
28 :
29 : // cppthread lib
30 : //
31 : #include <cppthread/guard.h>
32 : #include <cppthread/mutex.h>
33 : #include <cppthread/thread.h>
34 :
35 :
36 : // snaplogger lib
37 : //
38 : #include "snaplogger/message.h"
39 :
40 :
41 : //// snapdev lib
42 : ////
43 : ////#include "snapdev/not_reached.h"
44 : #include "snapdev/not_used.h"
45 : ////#include "snapdev/raii_generic_deleter.h"
46 :
47 :
48 : // OpenSSL lib
49 : //
50 : #include <openssl/bio.h>
51 : #include <openssl/err.h>
52 : #include <openssl/ssl.h>
53 :
54 :
55 : //// C++
56 : ////
57 : //#include <sstream>
58 : //#include <iomanip>
59 : //
60 : //
61 : //// C lib
62 : ////
63 : //#include <netdb.h>
64 : //#include <netinet/tcp.h>
65 : //#include <poll.h>
66 : //#include <string.h>
67 : //#include <sys/ioctl.h>
68 : //#include <sys/socket.h>
69 : //#include <sys/types.h>
70 : //#include <unistd.h>
71 :
72 :
73 : // last include
74 : //
75 : #include "snapdev/poison.h"
76 :
77 :
78 :
79 :
80 : #ifndef OPENSSL_THREADS
81 : #error "OPENSSL_THREADS is not defined. Event Dispatcher requires OpenSSL to support multi-threading."
82 : #endif
83 :
84 : namespace ed
85 : {
86 :
87 :
88 : namespace detail
89 : {
90 :
91 :
92 :
93 : ///** \brief Data handled by each lock.
94 : // *
95 : // * This function holds the data handled on a per lock basis.
96 : // * Even if your daemon is not using multiple threads, this
97 : // * is likely to kick in.
98 : // */
99 : //class crypto_lock_t
100 : //{
101 : //public:
102 : // typedef std::vector<crypto_lock_t> vector_t;
103 : //
104 : // crypto_lock_t()
105 : // {
106 : // pthread_mutex_init(&f_mutex, nullptr);
107 : // }
108 : //
109 : // ~crypto_lock_t()
110 : // {
111 : // pthread_mutex_destroy(&f_mutex);
112 : // }
113 : //
114 : // void lock()
115 : // {
116 : // pthread_mutex_lock(&f_mutex);
117 : // }
118 : //
119 : // void unlock()
120 : // {
121 : // pthread_mutex_unlock(&f_mutex);
122 : // }
123 : //
124 : //private:
125 : // pthread_mutex_t f_mutex = pthread_mutex_t();
126 : //};
127 :
128 :
129 : /** \brief The vector of locks.
130 : *
131 : * This function is initialized by the crypto_thread_setup().
132 : *
133 : * It is defined as a pointer in case someone was to try to access this
134 : * pointer before entering main().
135 : */
136 : //crypto_lock_t::vector_t * g_locks = nullptr;
137 : cppthread::mutex::direct_vector_t * g_locks = nullptr;
138 :
139 :
140 : /** \brief Retrieve the system thread identifier.
141 : *
142 : * This function is used by the OpenSSL library to attach an internal thread
143 : * identifier (\p tid) to a system thread identifier.
144 : *
145 : * \param[in] tid The crypto internal thread identifier.
146 : */
147 0 : void pthreads_thread_id(CRYPTO_THREADID * tid)
148 : {
149 : // on 19.04 the macro does not use tid
150 : //
151 0 : snap::NOTUSED(tid);
152 :
153 0 : CRYPTO_THREADID_set_numeric(tid, cppthread::gettid());
154 0 : }
155 :
156 :
157 : /** \brief Handle locks and unlocks.
158 : *
159 : * This function is a callback used to lock and unlock mutexes as required.
160 : *
161 : * \param[in] mode Whether lock or unlock in read or write mode.
162 : * \param[in] type The "type" of lock (i.e. the index).
163 : * \param[in] file The filename of the source asking for a lock/unlock.
164 : * \param[in] line The line number in file where the call was made.
165 : */
166 0 : void pthreads_locking_callback(int mode, int type, char const * file, int line)
167 : {
168 0 : snap::NOTUSED(file);
169 0 : snap::NOTUSED(line);
170 :
171 0 : if(g_locks == nullptr)
172 : {
173 0 : throw event_dispatcher_initialization_missing("g_locks was not initialized");
174 : }
175 :
176 : /*
177 : # ifdef undef
178 : BIO_printf(bio_err, "thread=%4d mode=%s lock=%s %s:%d\n",
179 : CRYPTO_thread_id(),
180 : (mode & CRYPTO_LOCK) ? "l" : "u",
181 : (type & CRYPTO_READ) ? "r" : "w", file, line);
182 : # endif
183 : if (CRYPTO_LOCK_SSL_CERT == type)
184 : BIO_printf(bio_err,"(t,m,f,l) %ld %d %s %d\n",
185 : CRYPTO_thread_id(),
186 : mode,file,line);
187 : */
188 :
189 : // Note: at this point we ignore READ | WRITE because we do not have
190 : // such a concept with a simple mutex; we could take those in
191 : // account with a semaphore though.
192 : //
193 0 : if((mode & CRYPTO_LOCK) != 0)
194 : {
195 0 : (*g_locks)[type].lock();
196 : }
197 : else
198 : {
199 0 : (*g_locks)[type].unlock();
200 : }
201 0 : }
202 :
203 :
204 : /** \brief This function is called once on initialization.
205 : *
206 : * This function is called when the bio_initialize() function. It is
207 : * expected that the bio_initialize() function is called once by the
208 : * main thread before any other thread has a chance to do so.
209 : */
210 0 : void crypto_thread_setup()
211 : {
212 0 : cppthread::guard g(*cppthread::g_system_mutex);
213 :
214 0 : if(g_locks != nullptr)
215 : {
216 : throw event_dispatcher_initialization_error(
217 : "crypto_thread_setup() called for the second time."
218 : " This usually means two threads are initializing"
219 0 : " the BIO environment simultaneously.");
220 : }
221 :
222 0 : g_locks = new cppthread::mutex::direct_vector_t(CRYPTO_num_locks());
223 :
224 0 : CRYPTO_THREADID_set_callback(pthreads_thread_id);
225 0 : CRYPTO_set_locking_callback(pthreads_locking_callback);
226 0 : }
227 :
228 :
229 : /** \brief This function cleans up the thread setup.
230 : *
231 : * This function could be called to clean up the setup created to support
232 : * multiple threads running with the OpenSSL library.
233 : *
234 : * \note
235 : * At this time this function never gets called. So we have a small leak
236 : * but that's only on a quit.
237 : */
238 0 : void thread_cleanup()
239 : {
240 0 : CRYPTO_set_locking_callback(nullptr);
241 :
242 0 : delete g_locks;
243 0 : g_locks = nullptr;
244 0 : }
245 :
246 :
247 : /** \brief This function cleans up the error state of a thread.
248 : *
249 : * Whenever the OpenSSL system runs in a thread, it may create a
250 : * state to save various information, especially its error queue.
251 : *
252 : * \sa cleanup_on_thread_exit()
253 : */
254 0 : void per_thread_cleanup()
255 : {
256 : #if __cplusplus < 201700
257 : // this function is not necessary in newer versions of OpenSSL
258 : //
259 0 : ERR_remove_thread_state(nullptr);
260 : #endif
261 0 : }
262 :
263 :
264 :
265 :
266 :
267 :
268 :
269 : /** \brief Whether the bio_initialize() function was already called.
270 : *
271 : * This flag is used to know whether the bio_initialize() function was
272 : * already called. Only the bio_initialize() function is expected to
273 : * make use of this flag. Other functions should simply call the
274 : * bio_initialize() function (future versions may include addition
275 : * flags or use various bits in an integer instead.)
276 : */
277 : bool g_bio_initialized = false;
278 :
279 :
280 : /** \brief Initialize the BIO library.
281 : *
282 : * This function is called by the BIO implementations to initialize the
283 : * BIO library as required. It can be called any number of times. The
284 : * initialization will happen only once.
285 : */
286 0 : void bio_initialize()
287 : {
288 0 : cppthread::guard g(*cppthread::g_system_mutex);
289 :
290 : // already initialized?
291 : //
292 0 : if(g_bio_initialized)
293 : {
294 0 : return;
295 : }
296 0 : g_bio_initialized = true;
297 :
298 : // Make sure the SSL library gets initialized
299 : //
300 0 : SSL_library_init();
301 :
302 : // TBD: should we call the load string functions only when we
303 : // are about to generate the first error?
304 : //
305 0 : ERR_load_crypto_strings();
306 0 : ERR_load_SSL_strings();
307 0 : SSL_load_error_strings();
308 :
309 : // TODO: define a way to only define safe algorithms?
310 : // (it looks like we can force TLSv1.2 below at least)
311 : //
312 0 : OpenSSL_add_all_algorithms();
313 :
314 : // TBD: need a PRNG seeding before creating a new SSL context?
315 :
316 : // then initialize the library so it works in a multithreaded
317 : // environment
318 : //
319 0 : crypto_thread_setup();
320 : }
321 :
322 :
323 : /** \brief Clean up the BIO environment.
324 : *
325 : * This function cleans up the BIO environment.
326 : *
327 : * \note
328 : * This function is here mainly for documentation rather than to get called.
329 : * Whenever you exit a process that uses the BIO calls it will leak
330 : * a few things. To make the process really spanking clean, you want
331 : * to call this function before exit(3). You have to make sure that
332 : * you call this function only after every single BIO object was
333 : * closed and none must be opened after this call.
334 : */
335 0 : void bio_cleanup()
336 : {
337 : #if __cplusplus < 201700
338 : // this function is not necessary in newer versions of OpenSSL
339 : //
340 0 : ERR_remove_state(0);
341 : #endif
342 :
343 0 : EVP_cleanup();
344 0 : CRYPTO_cleanup_all_ex_data();
345 0 : ERR_free_strings();
346 0 : }
347 :
348 :
349 : /** \brief Get all the error messages and output them in our logs.
350 : *
351 : * This function reads all existing errors from the OpenSSL library
352 : * and send them to our logs.
353 : *
354 : * \param[in] sni Whether SNI is ON (true) or OFF (false).
355 : */
356 0 : int bio_log_errors()
357 : {
358 : // allow for up to 5 errors in one go, but we have a HUGE problem
359 : // at this time as in some cases the same error is repeated forever
360 : //
361 0 : for(int i(0);; ++i)
362 : {
363 0 : char const * filename(nullptr);
364 0 : int line(0);
365 0 : char const * data(nullptr);
366 0 : int flags(0);
367 0 : unsigned long bio_errno(ERR_get_error_line_data(&filename, &line, &data, &flags));
368 0 : if(bio_errno == 0)
369 : {
370 : // no more errors
371 : //
372 0 : return i;
373 : }
374 :
375 : // get corresponding messages too
376 : //
377 : // Note: current OpenSSL documentation on Ubuntu says errmsg[]
378 : // should be at least 120 characters BUT the code actually
379 : // use a limit of 256...
380 : //
381 : char errmsg[256];
382 0 : ERR_error_string_n(bio_errno, errmsg, sizeof(errmsg) / sizeof(errmsg[0]));
383 : // WARNING: the ERR_error_string() function is NOT multi-thread safe
384 :
385 : #pragma GCC diagnostic push
386 : #pragma GCC diagnostic ignored "-Wold-style-cast"
387 0 : int const lib_num(ERR_GET_LIB(bio_errno));
388 0 : int const func_num(ERR_GET_FUNC(bio_errno));
389 : #pragma GCC diagnostic pop
390 0 : char const * lib_name(ERR_lib_error_string(lib_num));
391 0 : char const * func_name(ERR_func_error_string(func_num));
392 0 : int const reason_num(ERR_GET_REASON(bio_errno));
393 0 : char const * reason(ERR_reason_error_string(reason_num));
394 :
395 0 : if(lib_name == nullptr)
396 : {
397 0 : lib_name = "<no libname>";
398 : }
399 0 : if(func_name == nullptr)
400 : {
401 0 : func_name = "<no funcname>";
402 : }
403 0 : if(reason == nullptr)
404 : {
405 0 : reason = "<no reason>";
406 : }
407 :
408 : // the format used by the OpenSSL library is as follow:
409 : //
410 : // [pid]:error:[error code]:[library name]:[function name]:[reason string]:[file name]:[line]:[optional text message]
411 : //
412 : // we do not duplicate the [pid] and "error" but include all the
413 : // other fields
414 : //
415 : SNAP_LOG_ERROR
416 0 : << "OpenSSL: ["
417 0 : << bio_errno // should be shown in hex...
418 0 : << "/"
419 0 : << lib_num
420 0 : << "|"
421 0 : << func_num
422 0 : << "|"
423 0 : << reason_num
424 0 : << "]:["
425 0 : << lib_name
426 0 : << "]:["
427 0 : << func_name
428 0 : << "]:["
429 0 : << reason
430 0 : << "]:["
431 0 : << filename
432 0 : << "]:["
433 0 : << line
434 0 : << "]:["
435 0 : << ((flags & ERR_TXT_STRING) != 0 && data != nullptr ? data : "(no details)")
436 0 : << "]";
437 : }
438 : }
439 :
440 :
441 : /** \brief Free a BIO object.
442 : *
443 : * This deleter is used to make sure that the BIO object gets freed
444 : * whenever the object holding it gets destroyed.
445 : *
446 : * Note that deleting a BIO connection calls shutdown() and close()
447 : * on the socket. In other words, it hangs up.
448 : *
449 : * \param[in] bio The BIO object to be freed.
450 : */
451 0 : void bio_deleter(BIO * bio)
452 : {
453 : // IMPORTANT NOTE:
454 : //
455 : // The BIO_free_all() calls shutdown() on the socket. This is not
456 : // acceptable in a normal Unix application that makes use of fork().
457 : // So... instead we ask the BIO interface to not close the socket,
458 : // and instead we close it ourselves. This means the shutdown()
459 : // never gets called.
460 : //
461 0 : BIO_set_close(bio, BIO_NOCLOSE);
462 :
463 : int c;
464 : #pragma GCC diagnostic push
465 : #pragma GCC diagnostic ignored "-Wold-style-cast"
466 0 : BIO_get_fd(bio, &c);
467 : #pragma GCC diagnostic pop
468 0 : if(c != -1)
469 : {
470 0 : close(c);
471 : }
472 :
473 0 : BIO_free_all(bio);
474 0 : }
475 :
476 :
477 : /** \brief Free an SSL_CTX object.
478 : *
479 : * This deleter is used to make sure that the SSL_CTX object gets
480 : * freed whenever the object holding it gets destroyed.
481 : */
482 0 : void ssl_ctx_deleter(SSL_CTX * ssl_ctx)
483 : {
484 0 : SSL_CTX_free(ssl_ctx);
485 0 : }
486 :
487 :
488 : }
489 : // namespace detail
490 :
491 :
492 :
493 :
494 :
495 :
496 :
497 :
498 :
499 :
500 :
501 :
502 :
503 :
504 : } // namespace ed
505 : // vim: ts=4 sw=4 et
|