diff options
Diffstat (limited to 'src/components/protocol_handler/src/protocol_handler_impl.cc')
-rw-r--r-- | src/components/protocol_handler/src/protocol_handler_impl.cc | 370 |
1 files changed, 172 insertions, 198 deletions
diff --git a/src/components/protocol_handler/src/protocol_handler_impl.cc b/src/components/protocol_handler/src/protocol_handler_impl.cc index 23ac2927ef..47d546657f 100644 --- a/src/components/protocol_handler/src/protocol_handler_impl.cc +++ b/src/components/protocol_handler/src/protocol_handler_impl.cc @@ -77,8 +77,9 @@ ProtocolHandlerImpl::ProtocolHandlerImpl( security_manager_(NULL) , #endif // ENABLE_SECURITY - raw_ford_messages_from_mobile_( - "PH FromMobile", this, threads::ThreadOptions(kStackSize)) + is_ptu_triggered_(false) + , raw_ford_messages_from_mobile_( + "PH FromMobile", this, threads::ThreadOptions(kStackSize)) , raw_ford_messages_to_mobile_( "PH ToMobile", this, threads::ThreadOptions(kStackSize)) , start_session_frame_map_lock_() @@ -838,6 +839,59 @@ void ProtocolHandlerImpl::OnConnectionClosed( multiframe_builder_.RemoveConnection(connection_id); } +void ProtocolHandlerImpl::OnPTUFinished(const bool ptu_result) { + LOG4CXX_AUTO_TRACE(logger_); + +#ifdef ENABLE_SECURITY + sync_primitives::AutoLock lock(ptu_handlers_lock_); + + if (!is_ptu_triggered_) { + LOG4CXX_ERROR(logger_, + "PTU was not triggered by service starting. Ignored"); + return; + } + + const bool is_cert_expired = security_manager_->IsCertificateUpdateRequired(); + for (auto handler : ptu_pending_handlers_) { + security_manager::SSLContext* ssl_context = + is_cert_expired + ? NULL + : security_manager_->CreateSSLContext(handler->connection_key()); + + if (!ssl_context) { + const std::string error("CreateSSLContext failed"); + LOG4CXX_ERROR(logger_, error); + security_manager_->SendInternalError( + handler->connection_key(), + security_manager::SecurityManager::ERROR_INTERNAL, + error); + + handler->OnHandshakeDone( + handler->connection_key(), + security_manager::SSLContext::Handshake_Result_Fail); + + continue; + } + + if (ssl_context->IsInitCompleted()) { + handler->OnHandshakeDone( + handler->connection_key(), + security_manager::SSLContext::Handshake_Result_Success); + } else { + security_manager_->AddListener(new HandshakeHandler(*handler)); + if (!ssl_context->IsHandshakePending()) { + // Start handshake process + security_manager_->StartHandshake(handler->connection_key()); + } + } + } + + LOG4CXX_DEBUG(logger_, "Handshake handlers were notified"); + ptu_pending_handlers_.clear(); + is_ptu_triggered_ = false; +#endif // ENABLE_SECURITY +} + RESULT_CODE ProtocolHandlerImpl::SendFrame(const ProtocolFramePtr packet) { LOG4CXX_AUTO_TRACE(logger_); if (!packet) { @@ -1173,12 +1227,12 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndServiceACK( LOG4CXX_AUTO_TRACE(logger_); const uint8_t current_session_id = packet.session_id(); - const uint32_t hash_id = get_hash_id(packet); + uint32_t hash_id = get_hash_id(packet); const ServiceType service_type = ServiceTypeFromByte(packet.service_type()); const ConnectionID connection_id = packet.connection_id(); const uint32_t session_key = session_observer_.OnSessionEndedCallback( - connection_id, current_session_id, hash_id, service_type); + connection_id, current_session_id, &hash_id, service_type); if (0 == session_key) { LOG4CXX_WARN(logger_, "Refused to end service"); @@ -1188,126 +1242,9 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageEndServiceACK( return RESULT_OK; } -#ifdef ENABLE_SECURITY -namespace { -/** - * \brief SecurityManagerListener for send Ack/NAck on success or fail - * SSL handshake - */ -class StartSessionHandler : public security_manager::SecurityManagerListener { - public: - StartSessionHandler(uint32_t connection_key, - ProtocolHandlerImpl* protocol_handler, - SessionObserver& session_observer, - ConnectionID connection_id, - int32_t session_id, - uint8_t protocol_version, - uint32_t hash_id, - ServiceType service_type, - const std::vector<int>& force_protected_service) - : connection_key_(connection_key) - , protocol_handler_(protocol_handler) - , session_observer_(session_observer) - , connection_id_(connection_id) - , session_id_(session_id) - , protocol_version_(protocol_version) - , hash_id_(hash_id) - , service_type_(service_type) - , force_protected_service_(force_protected_service) - , full_version_() - , payload_(NULL) {} - StartSessionHandler(uint32_t connection_key, - ProtocolHandlerImpl* protocol_handler, - SessionObserver& session_observer, - ConnectionID connection_id, - int32_t session_id, - uint8_t protocol_version, - uint32_t hash_id, - ServiceType service_type, - const std::vector<int>& force_protected_service, - ProtocolPacket::ProtocolVersion& full_version, - uint8_t* payload) - : connection_key_(connection_key) - , protocol_handler_(protocol_handler) - , session_observer_(session_observer) - , connection_id_(connection_id) - , session_id_(session_id) - , protocol_version_(protocol_version) - , hash_id_(hash_id) - , service_type_(service_type) - , force_protected_service_(force_protected_service) - , full_version_(full_version) - , payload_(payload) {} - - bool OnHandshakeDone( - const uint32_t connection_key, - security_manager::SSLContext::HandshakeResult result) OVERRIDE { - if (connection_key != connection_key_) { - delete[] payload_; - return false; - } - const bool success = - result == security_manager::SSLContext::Handshake_Result_Success; - // check current service protection - const bool was_service_protection_enabled = - session_observer_.GetSSLContext(connection_key_, service_type_) != NULL; - if (was_service_protection_enabled) { - if (!success) { - protocol_handler_->SendStartSessionNAck( - connection_id_, session_id_, protocol_version_, service_type_); - } else { - // Could not be success handshake and not already protected service - NOTREACHED(); - } - } else { - if (success) { - session_observer_.SetProtectionFlag(connection_key_, service_type_); - } - BsonObject params; - if (payload_ != NULL) { - params = bson_object_from_bytes(payload_); - } else { - bson_object_initialize_default(¶ms); - } - protocol_handler_->SendStartSessionAck(connection_id_, - session_id_, - protocol_version_, - hash_id_, - service_type_, - success, - full_version_, - params); - bson_object_deinitialize(¶ms); - } - delete[] payload_; - delete this; - return true; - } - - void OnCertificateUpdateRequired() OVERRIDE {} - - virtual const std::vector<int>& force_protected_service() const { - return force_protected_service_; - } - - private: - const uint32_t connection_key_; - ProtocolHandlerImpl* protocol_handler_; - SessionObserver& session_observer_; - - const ConnectionID connection_id_; - const int32_t session_id_; - const uint8_t protocol_version_; - const uint32_t hash_id_; - const ServiceType service_type_; - const std::vector<int> force_protected_service_; - ProtocolPacket::ProtocolVersion full_version_; - uint8_t* payload_; -}; -} // namespace -#endif // ENABLE_SECURITY - -// DEPRECATED +// Suppress warning for deprecated method used within another deprecated method +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( const ProtocolPacket& packet) { LOG4CXX_AUTO_TRACE(logger_); @@ -1402,17 +1339,18 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( *fullVersion); } else { security_manager_->AddListener( - new StartSessionHandler(connection_key, - this, - session_observer_, - connection_id, - session_id, - packet.protocol_version(), - hash_id, - service_type, - get_settings().force_protected_service(), - *fullVersion, - NULL)); + new HandshakeHandler(*this, + session_observer_, + connection_key, + connection_id, + session_id, + packet.protocol_version(), + hash_id, + service_type, + get_settings().force_protected_service(), + false, + *fullVersion, + NULL)); if (!ssl_context->IsHandshakePending()) { // Start handshake process security_manager_->StartHandshake(connection_key); @@ -1461,6 +1399,7 @@ RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( } return RESULT_OK; } +#pragma GCC diagnostic pop RESULT_CODE ProtocolHandlerImpl::HandleControlMessageStartSession( const ProtocolFramePtr packet) { @@ -1509,11 +1448,25 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( uint32_t hash_id, bool protection, std::vector<std::string>& rejected_params) { + LOG4CXX_AUTO_TRACE(logger_); + protocol_handler::SessionContext context(connection_id, + session_id, + generated_session_id, + ServiceType::kInvalidServiceType, + hash_id, + protection); + NotifySessionStarted(context, rejected_params); +} + +void ProtocolHandlerImpl::NotifySessionStarted( + const SessionContext& context, std::vector<std::string>& rejected_params) { + LOG4CXX_AUTO_TRACE(logger_); + ProtocolFramePtr packet; { sync_primitives::AutoLock auto_lock(start_session_frame_map_lock_); StartSessionFrameMap::iterator it = start_session_frame_map_.find( - std::make_pair(connection_id, session_id)); + std::make_pair(context.connection_id_, context.initial_session_id_)); if (it == start_session_frame_map_.end()) { LOG4CXX_ERROR(logger_, "Cannot find Session Started packet"); return; @@ -1525,11 +1478,11 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( const ServiceType service_type = ServiceTypeFromByte(packet->service_type()); const uint8_t protocol_version = packet->protocol_version(); - if (0 == generated_session_id) { + if (0 == context.new_session_id_) { LOG4CXX_WARN(logger_, "Refused by session_observer to create service " << static_cast<int32_t>(service_type) << " type."); - SendStartSessionNAck(connection_id, + SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, packet->service_type(), @@ -1537,8 +1490,9 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( return; } - BsonObject start_session_ack_params; - bson_object_initialize_default(&start_session_ack_params); + std::shared_ptr<BsonObject> start_session_ack_params( + new BsonObject(), [](BsonObject* obj) { bson_object_deinitialize(obj); }); + bson_object_initialize_default(start_session_ack_params.get()); // when video service is successfully started, copy input parameters // ("width", "height", "videoProtocol", "videoCodec") to the ACK packet if (packet->service_type() == kMobileNav && packet->data() != NULL) { @@ -1547,13 +1501,13 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( if ((element = bson_object_get(&req_param, strings::height)) != NULL && element->type == TYPE_INT32) { - bson_object_put_int32(&start_session_ack_params, + bson_object_put_int32(start_session_ack_params.get(), strings::height, bson_object_get_int32(&req_param, strings::height)); } if ((element = bson_object_get(&req_param, strings::width)) != NULL && element->type == TYPE_INT32) { - bson_object_put_int32(&start_session_ack_params, + bson_object_put_int32(start_session_ack_params.get(), strings::width, bson_object_get_int32(&req_param, strings::width)); } @@ -1561,17 +1515,17 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( bson_object_get_string(&req_param, strings::video_protocol); if (protocol != NULL) { bson_object_put_string( - &start_session_ack_params, strings::video_protocol, protocol); + start_session_ack_params.get(), strings::video_protocol, protocol); } char* codec = bson_object_get_string(&req_param, strings::video_codec); if (codec != NULL) { bson_object_put_string( - &start_session_ack_params, strings::video_codec, codec); + start_session_ack_params.get(), strings::video_codec, codec); } bson_object_deinitialize(&req_param); } - ProtocolPacket::ProtocolVersion* fullVersion; + std::shared_ptr<ProtocolPacket::ProtocolVersion> fullVersion; // Can't check protocol_version because the first packet is v1, but there // could still be a payload, in which case we can get the real protocol @@ -1581,24 +1535,68 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( char* version_param = bson_object_get_string(&request_params, strings::protocol_version); std::string version_string(version_param == NULL ? "" : version_param); - fullVersion = new ProtocolPacket::ProtocolVersion(version_string); + fullVersion = + std::make_shared<ProtocolPacket::ProtocolVersion>(version_string); // Constructed payloads added in Protocol v5 if (fullVersion->majorVersion < PROTOCOL_VERSION_5) { rejected_params.push_back(std::string(strings::protocol_version)); } bson_object_deinitialize(&request_params); } else { - fullVersion = new ProtocolPacket::ProtocolVersion(); + fullVersion = std::make_shared<ProtocolPacket::ProtocolVersion>(); } #ifdef ENABLE_SECURITY // for packet is encrypted and security plugin is enable - if (protection && security_manager_) { - const uint32_t connection_key = - session_observer_.KeyFromPair(connection_id, generated_session_id); + if (context.is_protected_ && security_manager_) { + const uint32_t connection_key = session_observer_.KeyFromPair( + context.connection_id_, context.new_session_id_); + + std::shared_ptr<uint8_t> bson_object_bytes( + bson_object_to_bytes(start_session_ack_params.get()), + [](uint8_t* p) { delete[] p; }); + + std::shared_ptr<HandshakeHandler> handler = + std::make_shared<HandshakeHandler>(*this, + session_observer_, + *fullVersion, + context, + packet->protocol_version(), + bson_object_bytes); + + const bool is_certificate_empty = + security_manager_->IsPolicyCertificateDataEmpty(); + + const bool is_certificate_expired = + is_certificate_empty || + security_manager_->IsCertificateUpdateRequired(); + + if (context.is_ptu_required_ && is_certificate_empty) { + LOG4CXX_DEBUG(logger_, + "PTU for StartSessionHandler " + << handler.get() + << " is required and certificate data is empty"); + + sync_primitives::AutoLock lock(ptu_handlers_lock_); + if (!is_ptu_triggered_) { + LOG4CXX_DEBUG(logger_, + "PTU is not triggered yet. " + << "Starting PTU and postponing SSL handshake"); + + ptu_pending_handlers_.push_back(handler); + is_ptu_triggered_ = true; + security_manager_->NotifyOnCertificateUpdateRequired(); + } else { + LOG4CXX_DEBUG(logger_, "PTU has been triggered. Added to pending."); + ptu_pending_handlers_.push_back(handler); + } + return; + } security_manager::SSLContext* ssl_context = - security_manager_->CreateSSLContext(connection_key); + is_certificate_expired + ? NULL + : security_manager_->CreateSSLContext(connection_key); if (!ssl_context) { const std::string error("CreateSSLContext failed"); LOG4CXX_ERROR(logger_, error); @@ -1606,22 +1604,15 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( connection_key, security_manager::SecurityManager::ERROR_INTERNAL, error); - // Start service without protection - SendStartSessionAck(connection_id, - generated_session_id, - packet->protocol_version(), - hash_id, - packet->service_type(), - PROTECTION_OFF, - *fullVersion, - start_session_ack_params); - delete fullVersion; - bson_object_deinitialize(&start_session_ack_params); + + handler->OnHandshakeDone( + connection_key, security_manager::SSLContext::Handshake_Result_Fail); + return; } if (!rejected_params.empty()) { - SendStartSessionNAck(connection_id, + SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, packet->service_type(), @@ -1630,36 +1621,21 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( // mark service as protected session_observer_.SetProtectionFlag(connection_key, service_type); // Start service as protected with current SSLContext - SendStartSessionAck(connection_id, - generated_session_id, + SendStartSessionAck(context.connection_id_, + context.new_session_id_, packet->protocol_version(), - hash_id, + context.hash_id_, packet->service_type(), PROTECTION_ON, *fullVersion, - start_session_ack_params); + *start_session_ack_params); } else { - // Need a copy because fullVersion will be deleted - ProtocolPacket::ProtocolVersion fullVersionCopy(*fullVersion); - security_manager_->AddListener(new StartSessionHandler( - connection_key, - this, - session_observer_, - connection_id, - generated_session_id, - packet->protocol_version(), - hash_id, - service_type, - get_settings().force_protected_service(), - fullVersionCopy, - bson_object_to_bytes(&start_session_ack_params))); + security_manager_->AddListener(new HandshakeHandler(*handler)); if (!ssl_context->IsHandshakePending()) { // Start handshake process security_manager_->StartHandshake(connection_key); } } - delete fullVersion; - bson_object_deinitialize(&start_session_ack_params); LOG4CXX_DEBUG(logger_, "Protection establishing for connection " << connection_key << " is in progress"); @@ -1667,23 +1643,21 @@ void ProtocolHandlerImpl::NotifySessionStartedResult( } #endif // ENABLE_SECURITY if (rejected_params.empty()) { - SendStartSessionAck(connection_id, - generated_session_id, + SendStartSessionAck(context.connection_id_, + context.new_session_id_, packet->protocol_version(), - hash_id, + context.hash_id_, packet->service_type(), PROTECTION_OFF, *fullVersion, - start_session_ack_params); + *start_session_ack_params); } else { - SendStartSessionNAck(connection_id, + SendStartSessionNAck(context.connection_id_, packet->session_id(), protocol_version, packet->service_type(), rejected_params); } - delete fullVersion; - bson_object_deinitialize(&start_session_ack_params); } RESULT_CODE ProtocolHandlerImpl::HandleControlMessageHeartBeat( @@ -1895,11 +1869,11 @@ RESULT_CODE ProtocolHandlerImpl::EncryptFrame(ProtocolFramePtr packet) { connection_key, security_manager::SecurityManager::ERROR_ENCRYPTION_FAILED, error_text); + + uint32_t hash_id = packet->message_id(); // Close session to prevent usage unprotected service/session - session_observer_.OnSessionEndedCallback(packet->connection_id(), - packet->session_id(), - packet->message_id(), - kRpc); + session_observer_.OnSessionEndedCallback( + packet->connection_id(), packet->session_id(), &hash_id, kRpc); return RESULT_OK; } LOG4CXX_DEBUG(logger_, @@ -1948,11 +1922,11 @@ RESULT_CODE ProtocolHandlerImpl::DecryptFrame(ProtocolFramePtr packet) { connection_key, security_manager::SecurityManager::ERROR_DECRYPTION_FAILED, error_text); + + uint32_t hash_id = packet->message_id(); // Close session to prevent usage unprotected service/session - session_observer_.OnSessionEndedCallback(packet->connection_id(), - packet->session_id(), - packet->message_id(), - kRpc); + session_observer_.OnSessionEndedCallback( + packet->connection_id(), packet->session_id(), &hash_id, kRpc); return RESULT_ENCRYPTION_FAILED; } LOG4CXX_DEBUG(logger_, |