diff --git a/linphone-desktop/assets/images/call_chat_secure_hovered.svg b/linphone-desktop/assets/images/call_chat_secure_hovered.svg new file mode 100644 index 000000000..06d11d7aa --- /dev/null +++ b/linphone-desktop/assets/images/call_chat_secure_hovered.svg @@ -0,0 +1,15 @@ + + + + chat_secure@x2 + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/linphone-desktop/assets/images/call_chat_secure_normal.svg b/linphone-desktop/assets/images/call_chat_secure_normal.svg new file mode 100644 index 000000000..06d11d7aa --- /dev/null +++ b/linphone-desktop/assets/images/call_chat_secure_normal.svg @@ -0,0 +1,15 @@ + + + + chat_secure@x2 + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/linphone-desktop/assets/images/call_chat_secure_pressed.svg b/linphone-desktop/assets/images/call_chat_secure_pressed.svg new file mode 100644 index 000000000..06d11d7aa --- /dev/null +++ b/linphone-desktop/assets/images/call_chat_secure_pressed.svg @@ -0,0 +1,15 @@ + + + + chat_secure@x2 + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/linphone-desktop/assets/images/call_chat_unsecure_hovered.svg b/linphone-desktop/assets/images/call_chat_unsecure_hovered.svg new file mode 100644 index 000000000..414fe3d76 --- /dev/null +++ b/linphone-desktop/assets/images/call_chat_unsecure_hovered.svg @@ -0,0 +1,15 @@ + + + + chat_unsecure@x2 + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/linphone-desktop/assets/images/call_chat_unsecure_normal.svg b/linphone-desktop/assets/images/call_chat_unsecure_normal.svg new file mode 100644 index 000000000..414fe3d76 --- /dev/null +++ b/linphone-desktop/assets/images/call_chat_unsecure_normal.svg @@ -0,0 +1,15 @@ + + + + chat_unsecure@x2 + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/linphone-desktop/assets/images/call_chat_unsecure_pressed.svg b/linphone-desktop/assets/images/call_chat_unsecure_pressed.svg new file mode 100644 index 000000000..414fe3d76 --- /dev/null +++ b/linphone-desktop/assets/images/call_chat_unsecure_pressed.svg @@ -0,0 +1,15 @@ + + + + chat_unsecure@x2 + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/linphone-desktop/assets/languages/en.ts b/linphone-desktop/assets/languages/en.ts index 5d14a2aa3..3518c737f 100644 --- a/linphone-desktop/assets/languages/en.ts +++ b/linphone-desktop/assets/languages/en.ts @@ -731,6 +731,26 @@ Server url not configured. pendingRequestLabel Please to wait, a request is pending. + + Say: + Say: + + + Your correspondent should say: + Your correspondent should say: + + + Deny + DENY + + + Accept + ACCEPT + + + Confirm the following SAS with peer: + Confirm the following SAS with peer: + InviteFriends diff --git a/linphone-desktop/assets/languages/fr.ts b/linphone-desktop/assets/languages/fr.ts index 228ac12fe..23c45e1d1 100644 --- a/linphone-desktop/assets/languages/fr.ts +++ b/linphone-desktop/assets/languages/fr.ts @@ -731,6 +731,26 @@ Url du serveur non configurée. pendingRequestLabel Merci de patienter, une requête est en attente. + + Say: + Dites : + + + Your correspondent should say: + Votre interlocuteur devrait dire : + + + Deny + REJETER + + + Accept + VALIDER + + + Confirm the following SAS with peer: + Confirmez le SAS suivant avec votre interlocuteur : + InviteFriends diff --git a/linphone-desktop/resources.qrc b/linphone-desktop/resources.qrc index 6b590b9a1..bc822f0d9 100644 --- a/linphone-desktop/resources.qrc +++ b/linphone-desktop/resources.qrc @@ -26,6 +26,12 @@ assets/images/call_accept_hovered.svg assets/images/call_accept_normal.svg assets/images/call_accept_pressed.svg + assets/images/call_chat_secure_hovered.svg + assets/images/call_chat_secure_normal.svg + assets/images/call_chat_secure_pressed.svg + assets/images/call_chat_unsecure_hovered.svg + assets/images/call_chat_unsecure_normal.svg + assets/images/call_chat_unsecure_pressed.svg assets/images/call_hovered.svg assets/images/call_normal.svg assets/images/call_pressed.svg diff --git a/linphone-desktop/src/components/call/CallModel.cpp b/linphone-desktop/src/components/call/CallModel.cpp index 792bc67ec..9dcf31452 100644 --- a/linphone-desktop/src/components/call/CallModel.cpp +++ b/linphone-desktop/src/components/call/CallModel.cpp @@ -263,6 +263,7 @@ void CallModel::handleCallStateChanged (const shared_ptr &call, break; } + emit securityUpdated(); emit statusChanged(getStatus()); } @@ -495,6 +496,56 @@ void CallModel::sendDtmf (const QString &dtmf) { // ----------------------------------------------------------------------------- +CallModel::CallEncryption CallModel::getEncryption () const { + shared_ptr params = mCall->getCurrentParams(); + linphone::MediaEncryption encryption = params->getMediaEncryption(); + switch (encryption) { + case linphone::MediaEncryptionSRTP: + return CallEncryptionSRTP; + case linphone::MediaEncryptionZRTP: + return CallEncryptionZRTP; + case linphone::MediaEncryptionDTLS: + return CallEncryptionDTLS; + case linphone::MediaEncryptionNone: + default: + return CallEncryptionNone; + } +} + +bool CallModel::isSecured () const { + shared_ptr params = mCall->getCurrentParams(); + linphone::MediaEncryption encryption = params->getMediaEncryption(); + return (encryption == linphone::MediaEncryptionZRTP && mCall->getAuthenticationTokenVerified()) + || encryption == linphone::MediaEncryptionSRTP || encryption == linphone::MediaEncryptionDTLS; +} + +QString CallModel::getLocalSAS() const { + QString token = mCall->getAuthenticationToken().c_str(); + linphone::CallDir direction = mCall->getDir(); + if (direction == linphone::CallDirIncoming) { + return token.left(2).toUpper(); + } else { + return token.right(2).toUpper(); + } +} + +QString CallModel::getRemoteSAS() const { + QString token = mCall->getAuthenticationToken().c_str(); + linphone::CallDir direction = mCall->getDir(); + if (direction == linphone::CallDirIncoming) { + return token.right(2).toUpper(); + } else { + return token.left(2).toUpper(); + } +} + +void CallModel::verifyAuthenticationToken(bool verify) { + mCall->setAuthenticationTokenVerified(verify); + emit securityUpdated(); +} + +// ----------------------------------------------------------------------------- + QVariantList CallModel::getAudioStats () const { return mAudioStats; } diff --git a/linphone-desktop/src/components/call/CallModel.hpp b/linphone-desktop/src/components/call/CallModel.hpp index e1a9f30b2..bd9e40762 100644 --- a/linphone-desktop/src/components/call/CallModel.hpp +++ b/linphone-desktop/src/components/call/CallModel.hpp @@ -55,6 +55,11 @@ class CallModel : public QObject { Q_PROPERTY(QVariantList audioStats READ getAudioStats NOTIFY statsUpdated); Q_PROPERTY(QVariantList videoStats READ getVideoStats NOTIFY statsUpdated); + Q_PROPERTY(CallEncryption encryption READ getEncryption NOTIFY securityUpdated); + Q_PROPERTY(bool isSecured READ isSecured NOTIFY securityUpdated); + Q_PROPERTY(QString localSAS READ getLocalSAS NOTIFY securityUpdated); + Q_PROPERTY(QString remoteSAS READ getRemoteSAS NOTIFY securityUpdated); + public: enum CallStatus { CallStatusConnected, @@ -67,6 +72,15 @@ public: Q_ENUM(CallStatus); + enum CallEncryption { + CallEncryptionNone, + CallEncryptionSRTP, + CallEncryptionZRTP, + CallEncryptionDTLS + }; + + Q_ENUM(CallEncryption); + CallModel (std::shared_ptr linphoneCall); ~CallModel (); @@ -100,6 +114,8 @@ public: Q_INVOKABLE void sendDtmf (const QString &dtmf); + Q_INVOKABLE void verifyAuthenticationToken(bool verify); + signals: void callErrorChanged (const QString &callError); void isInConferenceChanged (bool status); @@ -108,6 +124,7 @@ signals: void statsUpdated (); void statusChanged (CallStatus status); void videoRequested (); + void securityUpdated (); private: void handleCallStateChanged (const std::shared_ptr &call, linphone::CallState state); @@ -145,10 +162,16 @@ private: bool getRecording () const; + CallEncryption getEncryption () const; + bool isSecured () const; + QString getLocalSAS () const; + QString getRemoteSAS () const; + QVariantList getAudioStats () const; QVariantList getVideoStats () const; void updateStats (const std::shared_ptr &callStats, QVariantList &statsList); + QString iceStateToString (linphone::IceState state) const; bool mIsInConference = false; diff --git a/linphone-desktop/ui/views/App/Calls/Incall.js b/linphone-desktop/ui/views/App/Calls/Incall.js index 2f3f291ed..afcf0be91 100644 --- a/linphone-desktop/ui/views/App/Calls/Incall.js +++ b/linphone-desktop/ui/views/App/Calls/Incall.js @@ -9,7 +9,7 @@ // ============================================================================= function computeAvatarSize (maxSize) { - var height = container.height + var height = zrtp.visible ? container.height - zrtp.height : container.height var width = container.width var size = height < maxSize && height > 0 ? height : maxSize diff --git a/linphone-desktop/ui/views/App/Calls/Incall.qml b/linphone-desktop/ui/views/App/Calls/Incall.qml index 31fa54faa..1fd01ac0e 100644 --- a/linphone-desktop/ui/views/App/Calls/Incall.qml +++ b/linphone-desktop/ui/views/App/Calls/Incall.qml @@ -102,6 +102,13 @@ Rectangle { onClicked: telKeypad.visible = !telKeypad.visible } + + ActionButton { + id: callSecure + + icon: incall.call.isSecured ? 'call_chat_secure' : 'call_chat_unsecure' + onClicked: incall.call.encryption === CallModel.CallEncryptionZRTP ? zrtp.visible = true : zrtp.visible = false + } } ContactDescription { @@ -228,7 +235,7 @@ Rectangle { Camera { call: incall.call - height: container.height + height: zrtp.visible ? container.height - zrtp.height : container.height width: container.width } } @@ -242,6 +249,92 @@ Rectangle { } } + Item { + id: zrtp + height: CallStyle.zrtpArea.height + visible: false + Layout.fillWidth: true + anchors.top: container.bottom + Layout.margins: CallStyle.container.margins + + GridLayout { + anchors.centerIn: parent + columns: 1 + + Text { + Layout.fillWidth: true + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + text: qsTr("Confirm the following SAS with peer:") + elide: Text.ElideRight + font.pointSize: CallStyle.zrtpArea.fontSize + font.bold: true + color: Colors.j + } + + RowLayout { + anchors.horizontalCenter: parent.horizontalCenter + spacing: CallStyle.zrtpArea.vu.spacing + Layout.fillWidth: true + + Text { + text: qsTr("Say:") + font.pointSize: CallStyle.zrtpArea.fontSize + color: Colors.j + } + + Text { + text: incall.call.localSAS + font.pointSize: CallStyle.zrtpArea.fontSize + font.bold: true + color: Colors.i + } + + Text { + text: "-" + font.pointSize: CallStyle.zrtpArea.fontSize + color: Colors.j + } + + Text { + text: qsTr("Your correspondent should say:") + font.pointSize: CallStyle.zrtpArea.fontSize + color: Colors.j + } + + Text { + text: incall.call.remoteSAS + font.pointSize: CallStyle.zrtpArea.fontSize + font.bold: true + color: Colors.i + } + } + + RowLayout { + anchors.horizontalCenter: parent.horizontalCenter + spacing: CallStyle.zrtpArea.vu.spacing + Layout.fillWidth: true + + TextButtonA { + text: qsTr('Deny') + onClicked: { + zrtp.visible = false + incall.call.verifyAuthenticationToken(false) + } + } + + TextButtonB { + text: qsTr('Accept') + onClicked: { + zrtp.visible = false + incall.call.verifyAuthenticationToken(true) + } + } + } + } + } + // ------------------------------------------------------------------------- // Action Buttons. // ------------------------------------------------------------------------- diff --git a/linphone-desktop/ui/views/App/Styles/Calls/CallStyle.qml b/linphone-desktop/ui/views/App/Styles/Calls/CallStyle.qml index 8b762f51d..2b837dcdf 100644 --- a/linphone-desktop/ui/views/App/Styles/Calls/CallStyle.qml +++ b/linphone-desktop/ui/views/App/Styles/Calls/CallStyle.qml @@ -76,4 +76,13 @@ QtObject { property int relativeY: 90 } } + + property QtObject zrtpArea: QtObject { + property int height: 50 + property int fontSize: 12 + + property QtObject vu: QtObject { + property int spacing: 5 + } + } } diff --git a/submodules/linphone b/submodules/linphone index 87ca1adf5..19a0bf173 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit 87ca1adf5ef967bb3876ea0c060cb9135f36718d +Subproject commit 19a0bf173f7060dec5023292239a715ed807e327