Commit aad93cf4 authored by Matthieu Tanon's avatar Matthieu Tanon
Browse files

Only allow error IMDNs when LIMEv2 is enabled at message reception

parent a6a500eb
......@@ -128,8 +128,8 @@ public:
void enableSenderAuthentication (bool value) { senderAuthenticationEnabled = value; }
void setAuthorisationWarning (bool value) { authorizationWarning = value; } // TODO find better name
bool getAuthorisationWarning () { return authorizationWarning; } // TODO find better name
void setAuthorizationWarning (bool value) { authorizationWarning = value; } // TODO find better name
bool getAuthorizationWarning () { return authorizationWarning; } // TODO find better name
// -----------------------------------------------------------------------------
// Deprecated methods only used for C wrapper, to be removed some day...
......
......@@ -535,11 +535,13 @@ LinphoneReason ChatMessagePrivate::receive () {
currentRecvStep |= ChatMessagePrivate::Step::Cpim;
}
// Message Authorisation
if (getAuthorisationWarning()) {
lWarning() << "Message authorisation warning raised by LIMEv2";
// TODO Allow error IMDN exclusively
if (q->getSharedFromThis()->getInternalContent().getContentType() != ContentType::Imdn) {
// Message Authorization
if (getAuthorizationWarning()) {
lWarning() << "Message authorization warning raised by LIMEv2";
// Allow error IMDN exclusively
if (q->getSharedFromThis()->getInternalContent().getContentType() != ContentType::Imdn && !Imdn::isError(q->getSharedFromThis())) {
lWarning() << "Discarding message of type " << q->getSharedFromThis()->getInternalContent().getContentType();
errorCode = 415;
return linphone_error_code_to_reason(errorCode);
......
......@@ -139,6 +139,7 @@ ChatMessageModifier::Result LimeV2::processOutgoingMessage (const shared_ptr<Cha
if (linphone_config_get_int(linphone_core_get_config(chatRoom->getCore()->getCCore()), "lime", "allow_message_in_unsafe_chatroom", 0) == 0) {
if (chatRoom->getSecurityLevel() == ClientGroupChatRoom::SecurityLevel::Unsafe) {
lWarning() << "Sending encrypted message in an unsafe chatroom";
errorCode = 488; // Not Acceptable
return ChatMessageModifier::Result::Error;
}
}
......@@ -194,6 +195,7 @@ ChatMessageModifier::Result LimeV2::processOutgoingMessage (const shared_ptr<Cha
shared_ptr<ConferenceSecurityEvent> securityEvent = make_shared<ConferenceSecurityEvent>(time(nullptr), chatRoom->getConferenceId(), securityEventType);
confListener->onSecurityEvent(securityEvent);
}
errorCode = 488; // Not Acceptable
return ChatMessageModifier::Result::Error;
}
......@@ -202,7 +204,7 @@ ChatMessageModifier::Result LimeV2::processOutgoingMessage (const shared_ptr<Cha
shared_ptr<vector<uint8_t>> cipherMessage = make_shared<vector<uint8_t>>();
try {
belleSipLimeManager->encrypt(localDeviceId, recipientUserId, recipients, plainMessage, cipherMessage, [localDeviceId, recipients, cipherMessage, message, result] (lime::CallbackReturn returnCode, string errorMessage) {
belleSipLimeManager->encrypt(localDeviceId, recipientUserId, recipients, plainMessage, cipherMessage, [localDeviceId, recipients, cipherMessage, message, result, &errorCode] (lime::CallbackReturn returnCode, string errorMessage) {
if (returnCode == lime::CallbackReturn::success) {
list<Content *> contents;
......@@ -250,14 +252,15 @@ ChatMessageModifier::Result LimeV2::processOutgoingMessage (const shared_ptr<Cha
}
} else {
lError() << "Lime operation failed: " << errorMessage;
errorCode = 503; // IO Error
*result = ChatMessageModifier::Result::Error;
}
}, lime::EncryptionPolicy::cipherMessage);
} catch (const exception &e) {
lError() << e.what() << " while encrypting message";
errorCode = 503; // IO Error
*result = ChatMessageModifier::Result::Error;
}
return *result;
}
......@@ -281,7 +284,7 @@ ChatMessageModifier::Result LimeV2::processIncomingMessage (const shared_ptr<Cha
if (incomingContentType != expectedContentType) {
lError() << "LIMEv2 unexpected content-type: " << incomingContentType;
// Set authorisation warning flag because incoming message type is unexpected
message->getPrivate()->setAuthorisationWarning(true);
message->getPrivate()->setAuthorizationWarning(true);
// Disable sender authentication otherwise the unexpected message will always be discarded
message->getPrivate()->enableSenderAuthentication(false);
return ChatMessageModifier::Result::Skipped;
......@@ -314,7 +317,7 @@ ChatMessageModifier::Result LimeV2::processIncomingMessage (const shared_ptr<Cha
// Discard incoming messages from unsafe peer devices
if (peerDeviceStatus == lime::PeerDeviceStatus::unsafe) {
lWarning() << "LIMEv2 discard incoming message from unsafe sender device";
// TODO Result::Error causes a notifyUndecryptableChatMessageReceived + IMDN
errorCode = 488; // Not Acceptable
return ChatMessageModifier::Result::Error;
}
......@@ -326,7 +329,6 @@ ChatMessageModifier::Result LimeV2::processIncomingMessage (const shared_ptr<Cha
continue;
Header headerDeviceId = content.getHeader("Content-Id");
if (headerDeviceId.getValueWithParams() == localDeviceId) {
const vector<uint8_t> &cipherHeader = vector<uint8_t>(content.getBody().begin(), content.getBody().end());
return cipherHeader;
......@@ -365,7 +367,8 @@ ChatMessageModifier::Result LimeV2::processIncomingMessage (const shared_ptr<Cha
if (peerDeviceStatus == lime::PeerDeviceStatus::fail) {
lError() << "Failed to decrypt message from " << senderDeviceId;
return ChatMessageModifier::Result::Error;
errorCode = 488; // Not Acceptable
return ChatMessageModifier::Result::Done;
}
// Prepare decrypted message for next modifier
......@@ -380,7 +383,6 @@ ChatMessageModifier::Result LimeV2::processIncomingMessage (const shared_ptr<Cha
IdentityAddress sipfragAddress(senderDeviceId);
message->getPrivate()->setAuthenticatedFromAddress(sipfragAddress);
// Test errorCode
return ChatMessageModifier::Result::Done;
}
......
......@@ -173,8 +173,7 @@ ChatMessageModifier::Result CpimChatMessageModifier::decode (const shared_ptr<Ch
if (cpimFromAddress.isValid() && (cpimFromAddress == message->getAuthenticatedFromAddress())) {
message->getPrivate()->forceFromAddress(cpimFromAddress);
lInfo() << "[CPIM] Sender authentication successful";
}
else {
} else {
lWarning() << "[CPIM] Sender authentication failed";
errorCode = 488;
return ChatMessageModifier::Result::Error;
......
......@@ -191,6 +191,22 @@ void Imdn::parse (const shared_ptr<ChatMessage> &chatMessage) {
}
}
bool Imdn::isError (const shared_ptr<ChatMessage> &chatMessage) {
for (const auto &content : chatMessage->getPrivate()->getContents()) {
istringstream data(content->getBodyAsString());
unique_ptr<Xsd::Imdn::Imdn> imdn(Xsd::Imdn::parseImdn(data, Xsd::XmlSchema::Flags::dont_validate));
if (!imdn)
continue;
auto &deliveryNotification = imdn->getDeliveryNotification();
if (deliveryNotification.present()) {
auto &status = deliveryNotification.get().getStatus();
if (status.getFailed().present() || status.getError().present())
return true;
}
}
return false;
}
// -----------------------------------------------------------------------------
int Imdn::timerExpired (void *data, unsigned int revents) {
......
......@@ -73,6 +73,7 @@ public:
static std::string createXml (const std::string &id, time_t time, Imdn::Type imdnType, LinphoneReason reason);
static void parse (const std::shared_ptr<ChatMessage> &chatMessage);
static bool isError (const std::shared_ptr<ChatMessage> &chatMessage);
private:
static int timerExpired (void *data, unsigned int revents);
......
......@@ -5266,8 +5266,6 @@ static void group_chat_lime_v2_message_while_network_unreachable (void) {
// Simulate pauline has disconnected
linphone_core_set_network_reachable(pauline->lc, FALSE);
wait_for_list(coresList, &dummy, 1, 2000);
// Marie starts composing a message
linphone_chat_room_compose(marieCr);
......@@ -5275,13 +5273,10 @@ static void group_chat_lime_v2_message_while_network_unreachable (void) {
const char *marieMessage = "Hey ! What's up ?";
_send_message(marieCr, marieMessage);
wait_for_list(coresList, &dummy, 1, 4000);
// Reconnect pauline
linphone_core_set_network_reachable(pauline->lc, TRUE);
// Check if messages are received and correcty decrypted
BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneIsComposingActiveReceived, initialPaulineStats.number_of_LinphoneIsComposingActiveReceived + 1, 10000));
// Check if the message is received
BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 10000));
LinphoneChatMessage *paulineLastMsg = pauline->stat.last_received_chat_message;
if (!BC_ASSERT_PTR_NOT_NULL(paulineLastMsg))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment