summaryrefslogtreecommitdiff
path: root/src/components/protocol_handler/src/protocol_handler_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/protocol_handler/src/protocol_handler_impl.cc')
-rw-r--r--src/components/protocol_handler/src/protocol_handler_impl.cc370
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(&params);
- }
- protocol_handler_->SendStartSessionAck(connection_id_,
- session_id_,
- protocol_version_,
- hash_id_,
- service_type_,
- success,
- full_version_,
- params);
- bson_object_deinitialize(&params);
- }
- 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_,