LCOV - code coverage report
Current view: top level - eventdispatcher - tcp_private.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 99 0.0 %
Date: 2019-08-08 02:52:36 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.12