Changeset 87 for trunk/sources/thelib/src/protocols/ssl/basesslprotocol.cpp
- Timestamp:
- 08/21/10 19:30:35 (21 months ago)
- Location:
- trunk/sources/thelib/src/protocols/ssl
- Files:
-
- 1 added
- 1 moved
-
. (added)
-
basesslprotocol.cpp (moved) (moved from trunk/sources/thelib/src/protocols/sslprotocol.cpp) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/sources/thelib/src/protocols/ssl/basesslprotocol.cpp
r56 r87 18 18 */ 19 19 20 #include "protocols/ssl protocol.h"21 22 #define MAX_SSL_READ_BUFFER 819223 24 map<string, SSL_CTX *> SSLProtocol::_pGlobalContexts;25 bool SSLProtocol::_libraryInitialized = false;26 27 SSLProtocol::SSLProtocol()28 : BaseProtocol( PT_SSL) {29 _pGlobalSSLContext 1= NULL;20 #include "protocols/ssl/basesslprotocol.h" 21 22 #define MAX_SSL_READ_BUFFER 65536 23 24 map<string, SSL_CTX *> BaseSSLProtocol::_pGlobalContexts; 25 bool BaseSSLProtocol::_libraryInitialized = false; 26 27 BaseSSLProtocol::BaseSSLProtocol(uint64_t type) 28 : BaseProtocol(type) { 29 _pGlobalSSLContext = NULL; 30 30 _pSSL = NULL; 31 _sslHandshakeCompleted = false; 31 32 _pReadBuffer = new uint8_t[MAX_SSL_READ_BUFFER]; 32 FINEST("SSL protocol created"); 33 } 34 35 SSLProtocol::~SSLProtocol() { 33 } 34 35 BaseSSLProtocol::~BaseSSLProtocol() { 36 36 if (_pSSL != NULL) { 37 37 SSL_free(_pSSL); … … 39 39 } 40 40 delete[] _pReadBuffer; 41 FINEST("SSL protocol deleted"); 42 } 43 44 bool SSLProtocol::Initialize(Variant ¶meters) { 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 43 bool BaseSSLProtocol::Initialize(Variant ¶meters) { 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); 124 72 if (_pSSL == NULL) { 125 73 FATAL("Unable to create SSL connection context"); … … 127 75 } 128 76 77 //4. setup the I/O buffers 129 78 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 83 bool BaseSSLProtocol::AllowFarProtocol(uint64_t type) { 136 84 if (type == PT_TCP) 137 85 return true; … … 140 88 } 141 89 142 bool SSLProtocol::AllowNearProtocol(uint64_t type) {90 bool BaseSSLProtocol::AllowNearProtocol(uint64_t type) { 143 91 return true; 144 92 } 145 93 146 bool SSLProtocol::EnqueueForOutbound() { 94 bool 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? 147 101 IOBuffer *pBuffer = _pNearProtocol->GetOutputBuffer(); 148 102 if (pBuffer == NULL) 149 103 return true; 104 105 //3. Encrypt the outstanding data 150 106 if (SSL_write(_pSSL, GETIBPOINTER(*pBuffer), GETAVAILABLEBYTESCOUNT(*pBuffer)) 151 107 != (int32_t) GETAVAILABLEBYTESCOUNT(*pBuffer)) { … … 154 110 } 155 111 pBuffer->IgnoreAll(); 112 113 //4. Do the actual I/O 156 114 return PerformIO(); 157 115 } 158 116 159 IOBuffer * SSLProtocol::GetOutputBuffer() {117 IOBuffer * BaseSSLProtocol::GetOutputBuffer() { 160 118 if (GETAVAILABLEBYTESCOUNT(_outputBuffer) > 0) 161 119 return &_outputBuffer; … … 163 121 } 164 122 165 IOBuffer * SSLProtocol::GetInputBuffer() {123 IOBuffer * BaseSSLProtocol::GetInputBuffer() { 166 124 return &_inputBuffer; 167 125 } 168 126 169 bool SSLProtocol::SignalInputData(int32_t recvAmount) {127 bool BaseSSLProtocol::SignalInputData(int32_t recvAmount) { 170 128 ASSERT("OPERATION NOT SUPPORTED"); 171 129 return false; 172 130 } 173 131 174 bool SSLProtocol::SignalInputData(IOBuffer &buffer) {175 // 2. get the SSL input buffer132 bool BaseSSLProtocol::SignalInputData(IOBuffer &buffer) { 133 //1. get the SSL input buffer 176 134 BIO *pInBio = SSL_get_rbio(_pSSL); 177 135 178 // 3. dump all the data from the network inside the ssl input136 //2. dump all the data from the network inside the ssl input 179 137 BIO_write(pInBio, GETIBPOINTER(buffer), 180 138 GETAVAILABLEBYTESCOUNT(buffer)); 181 139 buffer.IgnoreAll(); 182 140 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)); 217 169 if (GETAVAILABLEBYTESCOUNT(_inputBuffer) > 0) { 218 170 if (_pNearProtocol != NULL) { … … 225 177 226 178 //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. 229 180 return PerformIO(); 230 181 } 231 182 232 string SSLProtocol::DumpBIO(BIO *pBIO) { 183 bool 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 201 string 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 215 string BaseSSLProtocol::DumpBIO(BIO *pBIO) { 233 216 string formatString; 234 217 formatString = "method: %p\n"; … … 263 246 } 264 247 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() { 248 void BaseSSLProtocol::InitRandGenerator() { 280 249 srand((uint32_t) time(NULL)); 281 250 … … 294 263 } 295 264 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.
