Ignore:
Timestamp:
08/21/10 19:30:35 (21 months ago)
Author:
shiretu
Message:

-- work on android apple streaming
-- work on new SSL support

Location:
trunk/sources/thelib/src/protocols/ssl
Files:
1 added
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/sources/thelib/src/protocols/ssl/basesslprotocol.cpp

    r56 r87  
    1818 */ 
    1919 
    20 #include "protocols/sslprotocol.h" 
    21  
    22 #define MAX_SSL_READ_BUFFER 8192 
    23  
    24 map<string, SSL_CTX *> SSLProtocol::_pGlobalContexts; 
    25 bool SSLProtocol::_libraryInitialized = false; 
    26  
    27 SSLProtocol::SSLProtocol() 
    28 : BaseProtocol(PT_SSL) { 
    29         _pGlobalSSLContext1 = NULL; 
     20#include "protocols/ssl/basesslprotocol.h" 
     21 
     22#define MAX_SSL_READ_BUFFER 65536 
     23 
     24map<string, SSL_CTX *> BaseSSLProtocol::_pGlobalContexts; 
     25bool BaseSSLProtocol::_libraryInitialized = false; 
     26 
     27BaseSSLProtocol::BaseSSLProtocol(uint64_t type) 
     28: BaseProtocol(type) { 
     29        _pGlobalSSLContext = NULL; 
    3030        _pSSL = NULL; 
     31        _sslHandshakeCompleted = false; 
    3132        _pReadBuffer = new uint8_t[MAX_SSL_READ_BUFFER]; 
    32         FINEST("SSL protocol created"); 
    33 } 
    34  
    35 SSLProtocol::~SSLProtocol() { 
     33} 
     34 
     35BaseSSLProtocol::~BaseSSLProtocol() { 
    3636        if (_pSSL != NULL) { 
    3737                SSL_free(_pSSL); 
     
    3939        } 
    4040        delete[] _pReadBuffer; 
    41         FINEST("SSL protocol deleted"); 
    42 } 
    43  
    44 bool SSLProtocol::Initialize(Variant &parameters) { 
    45         //1. Comput the hash on key/cert pair and see 
    46         //if we have a global context with that hash 
    47         string hash = ""; 
    48         if (parameters["hash"] != V_STRING) { 
    49                 if (parameters[CONF_SSL_KEY] != V_STRING 
    50                                 || parameters[CONF_SSL_CERT] != V_STRING) { 
    51                         FATAL("No key/cert provided"); 
    52                         return false; 
    53                 } 
    54                 hash = md5((string) parameters[CONF_SSL_KEY] 
    55                                 + (string) parameters[CONF_SSL_CERT], true); 
    56                 parameters["hash"] = hash; 
    57         } else { 
    58                 hash = (string) parameters["hash"]; 
    59         } 
    60         string key = parameters[CONF_SSL_KEY]; 
    61         string cert = parameters[CONF_SSL_CERT]; 
    62         _pGlobalSSLContext1 = _pGlobalContexts[hash]; 
    63  
    64         //2. Initialize the global context based on the specified 
    65         //key/cert pair if we don't have it 
    66         if (_pGlobalSSLContext1 == NULL) { 
    67                 if (!_libraryInitialized) { 
    68                         //3. This is the first time we use the library. So we have to 
    69                         //initialize it first 
    70                         SSL_library_init(); 
    71  
    72                         //init readable error messages 
    73                         SSL_load_error_strings(); 
    74                         ERR_load_SSL_strings(); 
    75                         ERR_load_CRYPTO_strings(); 
    76                         ERR_load_crypto_strings(); 
    77                         OpenSSL_add_all_algorithms(); 
    78                         OpenSSL_add_all_ciphers(); 
    79                         OpenSSL_add_all_digests(); 
    80  
    81                         //initialize the random numbers generator 
    82                         InitRandGenerator(); 
    83                         _libraryInitialized = false; 
    84                 } 
    85  
    86                 //4. prepare the global ssl context 
    87                 _pGlobalSSLContext1 = SSL_CTX_new(SSLv23_method()); 
    88                 if (_pGlobalSSLContext1 == NULL) { 
    89                         FATAL("Unable to create global SSL context"); 
    90                         return false; 
    91                 } 
    92  
    93                 //5. setup the certificate 
    94                 if (SSL_CTX_use_certificate_file(_pGlobalSSLContext1, STR(cert), 
    95                                 SSL_FILETYPE_PEM) <= 0) { 
    96                         FATAL("Unable to load certificate %s; Error(s) was: %s", 
    97                                         STR(cert), 
    98                                         STR(GetSSLErrors())); 
    99                         SSL_CTX_free(_pGlobalSSLContext1); 
    100                         _pGlobalSSLContext1 = NULL; 
    101                         return false; 
    102                 } 
    103  
    104                 //6. setup the private key 
    105                 if (SSL_CTX_use_PrivateKey_file(_pGlobalSSLContext1, STR(key), 
    106                                 SSL_FILETYPE_PEM) <= 0) { 
    107                         FATAL("Unable to load key %s; Error(s) was: %s", 
    108                                         STR(key), 
    109                                         STR(GetSSLErrors())); 
    110                         SSL_CTX_free(_pGlobalSSLContext1); 
    111                         _pGlobalSSLContext1 = NULL; 
    112                         return false; 
    113                 } 
    114  
    115                 //7. disable client certificate authentication 
    116                 SSL_CTX_set_verify(_pGlobalSSLContext1, SSL_VERIFY_NONE, NULL); 
    117  
    118                 //8. Store the global context for later usage 
    119                 _pGlobalContexts[hash] = _pGlobalSSLContext1; 
    120         } 
    121  
    122         //9. create connection SSL context 
    123         _pSSL = SSL_new(_pGlobalSSLContext1); 
     41} 
     42 
     43bool BaseSSLProtocol::Initialize(Variant &parameters) { 
     44        //1. Initialize the SSL library 
     45        if (!_libraryInitialized) { 
     46                //3. This is the first time we use the library. So we have to 
     47                //initialize it first 
     48                SSL_library_init(); 
     49 
     50                //init readable error messages 
     51                SSL_load_error_strings(); 
     52                ERR_load_SSL_strings(); 
     53                ERR_load_CRYPTO_strings(); 
     54                ERR_load_crypto_strings(); 
     55                OpenSSL_add_all_algorithms(); 
     56                OpenSSL_add_all_ciphers(); 
     57                OpenSSL_add_all_digests(); 
     58 
     59                //initialize the random numbers generator 
     60                InitRandGenerator(); 
     61                _libraryInitialized = false; 
     62        } 
     63 
     64        //2. Initialize the global context 
     65        if (!InitGlobalContext(parameters)) { 
     66                FATAL("Unable to initialize global context"); 
     67                return false; 
     68        } 
     69 
     70        //3. create connection SSL context 
     71        _pSSL = SSL_new(_pGlobalSSLContext); 
    12472        if (_pSSL == NULL) { 
    12573                FATAL("Unable to create SSL connection context"); 
     
    12775        } 
    12876 
     77        //4. setup the I/O buffers 
    12978        SSL_set_bio(_pSSL, BIO_new(BIO_s_mem()), BIO_new(BIO_s_mem())); 
    130         SSL_set_accept_state(_pSSL); 
    131  
    132         return true; 
    133 } 
    134  
    135 bool SSLProtocol::AllowFarProtocol(uint64_t type) { 
     79 
     80        return DoHandshake(); 
     81} 
     82 
     83bool BaseSSLProtocol::AllowFarProtocol(uint64_t type) { 
    13684        if (type == PT_TCP) 
    13785                return true; 
     
    14088} 
    14189 
    142 bool SSLProtocol::AllowNearProtocol(uint64_t type) { 
     90bool BaseSSLProtocol::AllowNearProtocol(uint64_t type) { 
    14391        return true; 
    14492} 
    14593 
    146 bool SSLProtocol::EnqueueForOutbound() { 
     94bool BaseSSLProtocol::EnqueueForOutbound() { 
     95        //1. Is the SSL handshake completed? 
     96        if (!_sslHandshakeCompleted) { 
     97                return DoHandshake(); 
     98        } 
     99 
     100        //2. Do we have some outstanding data? 
    147101        IOBuffer *pBuffer = _pNearProtocol->GetOutputBuffer(); 
    148102        if (pBuffer == NULL) 
    149103                return true; 
     104 
     105        //3. Encrypt the outstanding data 
    150106        if (SSL_write(_pSSL, GETIBPOINTER(*pBuffer), GETAVAILABLEBYTESCOUNT(*pBuffer)) 
    151107                        != (int32_t) GETAVAILABLEBYTESCOUNT(*pBuffer)) { 
     
    154110        } 
    155111        pBuffer->IgnoreAll(); 
     112 
     113        //4. Do the actual I/O 
    156114        return PerformIO(); 
    157115} 
    158116 
    159 IOBuffer * SSLProtocol::GetOutputBuffer() { 
     117IOBuffer * BaseSSLProtocol::GetOutputBuffer() { 
    160118        if (GETAVAILABLEBYTESCOUNT(_outputBuffer) > 0) 
    161119                return &_outputBuffer; 
     
    163121} 
    164122 
    165 IOBuffer * SSLProtocol::GetInputBuffer() { 
     123IOBuffer * BaseSSLProtocol::GetInputBuffer() { 
    166124        return &_inputBuffer; 
    167125} 
    168126 
    169 bool SSLProtocol::SignalInputData(int32_t recvAmount) { 
     127bool BaseSSLProtocol::SignalInputData(int32_t recvAmount) { 
    170128        ASSERT("OPERATION NOT SUPPORTED"); 
    171129        return false; 
    172130} 
    173131 
    174 bool SSLProtocol::SignalInputData(IOBuffer &buffer) { 
    175         //2. get the SSL input buffer 
     132bool BaseSSLProtocol::SignalInputData(IOBuffer &buffer) { 
     133        //1. get the SSL input buffer 
    176134        BIO *pInBio = SSL_get_rbio(_pSSL); 
    177135 
    178         //3. dump all the data from the network inside the ssl input 
     136        //2. dump all the data from the network inside the ssl input 
    179137        BIO_write(pInBio, GETIBPOINTER(buffer), 
    180138                        GETAVAILABLEBYTESCOUNT(buffer)); 
    181139        buffer.IgnoreAll(); 
    182140 
    183         //4. Try to do the handshake 
    184         int32_t errorCode = SSL_ERROR_NONE; 
    185         if (!SSL_is_init_finished(_pSSL)) { 
    186                 errorCode = SSL_accept(_pSSL); 
    187                 if (errorCode < 0) { 
    188                         int32_t error = SSL_get_error(_pSSL, errorCode); 
    189                         if (error != SSL_ERROR_WANT_READ && 
    190                                         error != SSL_ERROR_WANT_WRITE) { 
    191                                 FATAL("Unable to accept SSL connection: %d; %s", 
    192                                                 error, STR(GetSSLErrors())); 
    193                                 return false; 
    194                         } 
    195                 } 
    196         } 
    197  
    198         //5. if the init is made, read the actual data an put it in the 
    199         //descrypted input buffer 
    200         if (SSL_is_init_finished(_pSSL)) { 
    201                 int32_t read = 0; 
    202                 while ((read = SSL_read(_pSSL, _pReadBuffer, MAX_SSL_READ_BUFFER)) > 0) { 
    203                         _inputBuffer.ReadFromBuffer(_pReadBuffer, (uint32_t) read); 
    204                 } 
    205                 if (read < 0) { 
    206                         int32_t error = SSL_get_error(_pSSL, read); 
    207                         if (error != SSL_ERROR_WANT_READ && 
    208                                         error != SSL_ERROR_WANT_WRITE) { 
    209                                 FATAL("Unable to read data: %d", error); 
    210                                 return false; 
    211                         } 
    212                 } 
    213         } 
    214  
    215         //6. If we have pending data inside the decrypted buffer, bubble it up 
    216         //on the protocol stack 
     141        //3. Do we have to do some handshake? 
     142        if (!_sslHandshakeCompleted) { 
     143                if (!DoHandshake()) { 
     144                        FATAL("Unable to do the SSL handshake"); 
     145                        return false; 
     146                } 
     147                if (!_sslHandshakeCompleted) { 
     148                        //WARN("SSL handshake not completed yet"); 
     149                        return true; 
     150                } 
     151        } 
     152 
     153        //4. Read the actual data an put it in the descrypted input buffer 
     154        int32_t read = 0; 
     155        while ((read = SSL_read(_pSSL, _pReadBuffer, MAX_SSL_READ_BUFFER)) > 0) { 
     156                _inputBuffer.ReadFromBuffer(_pReadBuffer, (uint32_t) read); 
     157        } 
     158        if (read < 0) { 
     159                int32_t error = SSL_get_error(_pSSL, read); 
     160                if (error != SSL_ERROR_WANT_READ && 
     161                                error != SSL_ERROR_WANT_WRITE) { 
     162                        FATAL("Unable to read data: %d", error); 
     163                        return false; 
     164                } 
     165        } 
     166 
     167        //6. If we have pending data inside the decrypted buffer, bubble it up on the protocol stack 
     168        //FINEST("_inputBuffer:\n%s", STR(_inputBuffer)); 
    217169        if (GETAVAILABLEBYTESCOUNT(_inputBuffer) > 0) { 
    218170                if (_pNearProtocol != NULL) { 
     
    225177 
    226178        //7. After the data was sent on the upper layers, we might have outstanding 
    227         //data that needs to be sent. Also this outstanding data might come from 
    228         //the ssl handshake itself. So we do I/O 
     179        //data that needs to be sent. 
    229180        return PerformIO(); 
    230181} 
    231182 
    232 string SSLProtocol::DumpBIO(BIO *pBIO) { 
     183bool BaseSSLProtocol::PerformIO() { 
     184        //1. Put the data from SSL output buffer inside our protocol output buffer 
     185        if (!_outputBuffer.ReadFromBIO(SSL_get_wbio(_pSSL))) { 
     186                FATAL("Unable to transfer data from outBIO to outputBuffer"); 
     187                return false; 
     188        } 
     189 
     190        //2. Enqueue the protocol for outbound if we have data that needs to be sent 
     191        if (GETAVAILABLEBYTESCOUNT(_outputBuffer) > 0) { 
     192                if (_pFarProtocol != NULL) { 
     193                        return _pFarProtocol->EnqueueForOutbound(); 
     194                } 
     195        } 
     196 
     197        //3. Done 
     198        return true; 
     199} 
     200 
     201string BaseSSLProtocol::GetSSLErrors() { 
     202        string result = ""; 
     203        uint32_t errorCode; 
     204        char *pTempBuffer = new char[4096]; 
     205        while ((errorCode = ERR_get_error()) != 0) { 
     206                memset(pTempBuffer, 0, 4096); 
     207                ERR_error_string_n(errorCode, pTempBuffer, 4095); 
     208                result += "\n"; 
     209                result += pTempBuffer; 
     210        } 
     211        delete[] pTempBuffer; 
     212        return result; 
     213} 
     214 
     215string BaseSSLProtocol::DumpBIO(BIO *pBIO) { 
    233216        string formatString; 
    234217        formatString = "method: %p\n"; 
     
    263246} 
    264247 
    265 string SSLProtocol::GetSSLErrors() { 
    266         string result = ""; 
    267         uint32_t errorCode; 
    268         char *pTempBuffer = new char[4096]; 
    269         while ((errorCode = ERR_get_error()) != 0) { 
    270                 memset(pTempBuffer, 0, 4096); 
    271                 ERR_error_string_n(errorCode, pTempBuffer, 4095); 
    272                 result += "\n"; 
    273                 result += pTempBuffer; 
    274         } 
    275         delete[] pTempBuffer; 
    276         return result; 
    277 } 
    278  
    279 void SSLProtocol::InitRandGenerator() { 
     248void BaseSSLProtocol::InitRandGenerator() { 
    280249        srand((uint32_t) time(NULL)); 
    281250 
     
    294263} 
    295264 
    296 bool SSLProtocol::PerformIO() { 
    297         //1. Put the data from SSL output buffer inside our 
    298         //protocol output buffer 
    299         if (!_outputBuffer.ReadFromBIO(SSL_get_wbio(_pSSL))) { 
    300                 FATAL("Unable to transfer data from outBIO to outputBuffer"); 
    301                 return false; 
    302         } 
    303  
    304         //2. Enqueue the protocol for outbound if we have data that needs 
    305         //to be sent 
    306         if (GETAVAILABLEBYTESCOUNT(_outputBuffer) > 0) { 
    307                 if (_pFarProtocol != NULL) { 
    308                         return _pFarProtocol->EnqueueForOutbound(); 
    309                 } 
    310         } 
    311  
    312         //3. Done 
    313         return true; 
    314 } 
    315  
    316  
     265 
Note: See TracChangeset for help on using the changeset viewer.