diff options
author | Aleksandr Galiuzov <AGaliuzov@luxoft.com> | 2015-09-25 01:18:22 +0300 |
---|---|---|
committer | Aleksandr Galiuzov <AGaliuzov@luxoft.com> | 2015-10-04 21:03:54 +0300 |
commit | 16a6b3e7b686382370d8d9ddd6d4e8519aea94be (patch) | |
tree | 162ed6360d3ef4fadfffb05933a3042b4e5aadc9 /src/components/security_manager/src/ssl_context_impl.cc | |
parent | d656eb202c2c1060adf2e700bc2719f131d9f8bb (diff) | |
download | sdl_core-16a6b3e7b686382370d8d9ddd6d4e8519aea94be.tar.gz |
Refactor security things and add additional logging
Add logging for certificates dates as well as current host time.
Refactor cryptomanger and modify tests.
Closes-bug: APPLINK-16448
Diffstat (limited to 'src/components/security_manager/src/ssl_context_impl.cc')
-rw-r--r-- | src/components/security_manager/src/ssl_context_impl.cc | 198 |
1 files changed, 143 insertions, 55 deletions
diff --git a/src/components/security_manager/src/ssl_context_impl.cc b/src/components/security_manager/src/ssl_context_impl.cc index 3361711b13..e49d631092 100644 --- a/src/components/security_manager/src/ssl_context_impl.cc +++ b/src/components/security_manager/src/ssl_context_impl.cc @@ -134,69 +134,131 @@ std::map<std::string, CryptoManagerImpl::SSLContextImpl::BlockSizeGetter> CryptoManagerImpl::SSLContextImpl::max_block_sizes = CryptoManagerImpl::SSLContextImpl::create_max_block_sizes(); -SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: -DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, - const uint8_t** const out_data, size_t* out_data_size) { - DCHECK(out_data); - DCHECK(out_data_size); - *out_data = NULL; - *out_data_size = 0; - - // TODO(Ezamakhov): add test - hanshake fail -> restart StartHandshake - sync_primitives::AutoLock locker(bio_locker); - if (SSL_is_init_finished(connection_)) { - is_handshake_pending_ = false; - return Handshake_Result_Success; - } - - if (in_data && in_data_size) { - const int ret = BIO_write(bioIn_, in_data, in_data_size); - if (ret <= 0) { - is_handshake_pending_ = false; - ResetConnection(); - return Handshake_Result_AbnormalFail; - } - } - - bool cn_found; - bool sn_found; - STACK_OF(X509 ) *peer_certs = SSL_get_peer_cert_chain(connection_); - while (sk_X509_num(peer_certs) > 0) { - X509* cert = sk_X509_pop(peer_certs); - const bool last_step = (sk_X509_num(peer_certs) == 0); +void CryptoManagerImpl::SSLContextImpl::PrintCertData(X509* cert, + const std::string& cert_owner) { + if (cert) { X509_NAME* subj_name = X509_get_subject_name(cert); char *subj = X509_NAME_oneline(subj_name, NULL, 0); if (subj) { std::replace(subj, subj + strlen(subj), '/', ' '); - LOG4CXX_DEBUG(logger_, "Mobile cert subject:" << subj); + LOG4CXX_DEBUG(logger_, cert_owner <<" subject:" << subj); OPENSSL_free(subj); } char *issuer = X509_NAME_oneline(X509_get_issuer_name(cert), NULL, 0); if (issuer) { std::replace(issuer, issuer + strlen(issuer), '/', ' '); - LOG4CXX_DEBUG(logger_, "Mobile cert issuer:" << issuer); + LOG4CXX_DEBUG(logger_, cert_owner << " issuer:" << issuer); OPENSSL_free(issuer); } const std::string& cn = GetTextBy(subj_name, NID_commonName); const std::string& sn = GetTextBy(subj_name, NID_serialNumber); - cn_found = cn_found || (hsh_context_.expected_cn == cn); - sn_found = sn_found || (hsh_context_.expected_sn == sn); + LOG4CXX_DEBUG(logger_, "CN: " << cn << ". SERIALNUMBER: " << sn); + + ASN1_TIME* notBefore = X509_get_notBefore(cert); + ASN1_TIME* notAfter = X509_get_notAfter(cert); - if (!cn_found && last_step) { - LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app name"); - return Handshake_Result_AppNameMismatch; + if (notBefore) { + LOG4CXX_DEBUG(logger_, " Start date: " << (char*)notBefore->data); } + if (notAfter) { + LOG4CXX_DEBUG(logger_, " End date: " << (char*)notAfter->data); + } + } +} - if (!sn_found && last_step) { - LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app id"); - return Handshake_Result_AppIDMismatch; +void CryptoManagerImpl::SSLContextImpl::PrintCertInfo() { + PrintCertData(SSL_get_certificate(connection_), "HU's"); + + STACK_OF(X509 ) *peer_certs = SSL_get_peer_cert_chain(connection_); + while (sk_X509_num(peer_certs) > 0) { + X509* cert = sk_X509_pop(peer_certs); + PrintCertData(cert, "SERVERS"); + } +} + +SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: +CheckCertContext() { + X509* cert = SSL_get_peer_certificate(connection_); + if (!cert) { + // According to the openssl documentation the peer certificate + // might be ommitted for the SERVER but required for the cient. + return CLIENT == mode_ ? Handshake_Result_Fail : Handshake_Result_Success; + } + + X509_NAME* subj_name = + X509_get_subject_name(cert); + + const std::string& cn = GetTextBy(subj_name, NID_commonName); + const std::string& sn = GetTextBy(subj_name, NID_serialNumber); + + if (hsh_context_.expected_cn.compare(cn) != 0) { + LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app name: " << cn + << ". Expected app name: " << hsh_context_.expected_cn); + return Handshake_Result_AppNameMismatch; + } + + if (hsh_context_.expected_sn.compare(sn) != 0) { + LOG4CXX_ERROR(logger_,"Trying to run handshake with wrong app id: " << sn + << ". Expected app id: " << hsh_context_.expected_sn); + return Handshake_Result_AppIDMismatch; + } + return Handshake_Result_Success; +} + +bool CryptoManagerImpl::SSLContextImpl::ReadHandshakeData( + const uint8_t** const out_data, size_t* out_data_size) { + LOG4CXX_AUTO_TRACE(logger_); + const size_t pend = BIO_ctrl_pending(bioOut_); + LOG4CXX_DEBUG(logger_, "Available " << pend << " bytes for handshake"); + + if (pend > 0) { + LOG4CXX_DEBUG(logger_, "Reading handshake data"); + EnsureBufferSizeEnough(pend); + + const int read_count = BIO_read(bioOut_, buffer_, pend); + if (read_count == static_cast<int>(pend)) { + *out_data_size = read_count; + *out_data = buffer_; + } else { + LOG4CXX_WARN(logger_, "BIO read fail"); + is_handshake_pending_ = false; + ResetConnection(); + return false; } } + return true; +} + +bool CryptoManagerImpl::SSLContextImpl:: +WriteHandshakeData(const uint8_t* const in_data, size_t in_data_size) { + LOG4CXX_AUTO_TRACE(logger_); + if (in_data && in_data_size) { + const int ret = BIO_write(bioIn_, in_data, in_data_size); + if (ret <= 0) { + is_handshake_pending_ = false; + ResetConnection(); + return Handshake_Result_AbnormalFail; + } + } + return true; +} + + +SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: +PerformHandshake() { const int handshake_result = SSL_do_handshake(connection_); if (handshake_result == 1) { + const HandshakeResult result = CheckCertContext(); + if (result != Handshake_Result_Success) { + ResetConnection(); + is_handshake_pending_ = false; + return result; + } + + LOG4CXX_DEBUG(logger_, "SSL handshake successfully finished"); // Handshake is successful bioFilter_ = BIO_new(BIO_f_ssl()); BIO_set_ssl(bioFilter_, connection_, BIO_NOCLOSE); @@ -204,6 +266,7 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, const SSL_CIPHER *cipher = SSL_get_current_cipher(connection_); max_block_size_ = max_block_sizes[SSL_CIPHER_get_name(cipher)]; is_handshake_pending_ = false; + } else if (handshake_result == 0) { SSL_clear(connection_); is_handshake_pending_ = false; @@ -217,6 +280,7 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, << " \"" << LastError() << '"'); ResetConnection(); is_handshake_pending_ = false; + // In case error happened but ssl verification shows OK // method will return AbnormalFail. if (X509_V_OK == error) { @@ -225,24 +289,43 @@ DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, return openssl_error_convert_to_internal(error); } } + return Handshake_Result_Success; +} - const size_t pend = BIO_ctrl_pending(bioOut_); - if (pend) { - EnsureBufferSizeEnough(pend); +SSLContext::HandshakeResult CryptoManagerImpl::SSLContextImpl:: +DoHandshakeStep(const uint8_t* const in_data, size_t in_data_size, + const uint8_t** const out_data, size_t* out_data_size) { + LOG4CXX_AUTO_TRACE(logger_); + DCHECK(out_data); + DCHECK(out_data_size); + *out_data = NULL; + *out_data_size = 0; - const int read_count = BIO_read(bioOut_, buffer_, pend); - if (read_count == static_cast<int>(pend)) { - *out_data_size = read_count; - *out_data = buffer_; - } else { - is_handshake_pending_ = false; - ResetConnection(); - return Handshake_Result_AbnormalFail; - } + // TODO(Ezamakhov): add test - hanshake fail -> restart StartHandshake + sync_primitives::AutoLock locker(bio_locker); + if (SSL_is_init_finished(connection_)) { + LOG4CXX_DEBUG(logger_, "SSL initilization is finished"); + is_handshake_pending_ = false; + return Handshake_Result_Success; } - return Handshake_Result_Success; + if (!WriteHandshakeData(in_data, in_data_size)) { + return Handshake_Result_AbnormalFail; + } + + PrintCertInfo(); + + const HandshakeResult res = PerformHandshake(); + if (res != Handshake_Result_Success) { + return res; + } + + if (!ReadHandshakeData(out_data, out_data_size)) { + return Handshake_Result_AbnormalFail; + } + + return res; } bool CryptoManagerImpl::SSLContextImpl::Encrypt( @@ -399,6 +482,8 @@ std::string CryptoManagerImpl::SSLContextImpl::GetTextBy( const int req_len = X509_NAME_get_text_by_NID(name, object, NULL, 0); if (-1 == req_len) { + LOG4CXX_WARN(logger_, "Unable to obtain object: " << object + << " from certificate"); return std::string(); } @@ -406,8 +491,11 @@ std::string CryptoManagerImpl::SSLContextImpl::GetTextBy( data.resize(req_len + 1); X509_NAME_get_text_by_NID(name, object, &data.front(), data.size()); - return std::string(data.begin(), data.end() - 1); -} + std::string str (data.begin(), data.end() - 1); + std::transform(str.begin(), str.end(), + str.begin(), ::tolower); + return str; +} } // namespace security_manager |