Skip to content

Commit

Permalink
SYNERGY-1032 - Send secure input notifications to client (#7043)
Browse files Browse the repository at this point in the history
* SYNERGY-1017 - Try usnig NSUserNotification

* SYNERGY-1032 - Use UNUserNotificationCenter instead of deprecated notifications

* SYNERGY-1032 - Update app delegate and add log after notification access

* SYNERGY-1032 - Try using deprecated notification

* SYNERGY-1032 - Add notifications to the platform dependant code

* SYNERGY-1032 - Check for development builds before asking permission for notifications

* SYNERGY-1032 - Remove old notification and secure input detection

* SYNERGY-1032 - Add permission request to the main app

* SYNERGY-1032 - Only show notifications on server

* SYNERGY-1032 - Request and show notification from main app

* SYNERGY-1032 - Remove logging from OSX helpers

* SYNERGY-1032 - Add UN notification for testing

* SYNERGY-1032 - Show notification once

* SYNERGY-1032 - Try replicating old flow

* SYNERGY-1032 - Reuse notification center

* SYNERGY-1032 - Send notification after granting permission

* SYNERGY-1032 - Update app delegate

* SYNERGY-1032 - Remove deprecated property

* SYNERGY-1032 - Add output for debugging

* SYNERGY-1032 - Try updating delegate

* SYNERGY-1032 - Print current bundle name

* SYNERGY-1032 - Add AppDelegate to the server

* SYNERGY-1032 - Move notification creation to synergy app

* SYNERGY-1032 - Update notification text

* SYNERGY-1032 - Fix QString conversion for notification

* SYNERGY-1032 - Move notification creation outside the handler

* SYNERGY-1032 - Remove debug notification, show notification with no delay

* SYNERGY-1032 - Show notification inside the completion handler

* SYNERGY-1032 - Remove timed notification trigger

* SYNERGY-1032 - Request permissions on synergy start

* SYNERGY-1032 - Remove unused includes

* SYNERGY-1032 - Update changelog

* SYNERGY-1032 - Add empty notification implementations for Windows and Linux

* SYNERGY-1032 - Removed temporary debug messages

* SYNERGY-1032 - Resolve code smell

* SYNERGY-1032 - Add base code for handling sending secure input notification

* SYNERGY-1032 - Compile on Mac

* SYNERGY-1032 - Allow client downgrade for 1.7 down to 1.6

* SYNERGY-1032 - Add utility to show notifications. Update secure input message format

* SYNERGY-1032 - Update notification util on Mac

* SYNERGY-1032 - Don't disconnect on invalid message from client

* SYNERGY-1032 - Remove unused code

* SYNERGY-1032 - Update changelog

* SYNERGY-1032 - Update secure input notification message

* SYNERGY-1032 - Better formatting for debug comments

* SYNERGY-1032 - Resolve code smells

* SYNERGY-1032 - Resolve more code smells

* SYNERGY-1032 - Revert log level change

* SYNERGY-1032 - Resolve merge error
  • Loading branch information
igor-sikachyna committed Jun 29, 2021
1 parent 5843230 commit 2fdde93
Show file tree
Hide file tree
Showing 30 changed files with 417 additions and 227 deletions.
2 changes: 1 addition & 1 deletion ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Enhancements:
- #7026 Update the way we package OpenSSL for Windows build
- #7035 Add Fedora 34 build
- #7037 Add Ubuntu 21.04 build
- #7030 | #7041 Add user nofication for secure input on Mac
- #7030 | #7041 | #7043 Add user notification for secure input on Mac
===========

v1.14.0-stable
Expand Down
15 changes: 11 additions & 4 deletions src/lib/client/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,14 @@ Client::handleHello(const Event&, void*)

// check versions
LOG((CLOG_DEBUG1 "got hello version %d.%d", major, minor));
if (major < kProtocolMajorVersion ||
SInt16 helloBackMajor = kProtocolMajorVersion;
SInt16 helloBackMinor = kProtocolMinorVersion;
if (major == kProtocolMajorVersion && minor == 6 && kProtocolMinorVersion == 7) {
//because 1.6 and 1.7 is comptable - downgrading protocol for server
LOG((CLOG_NOTE "Downgrading protocol version for server"));
helloBackMinor = minor;
}
else if (major < kProtocolMajorVersion ||
(major == kProtocolMajorVersion && minor < kProtocolMinorVersion)) {
sendConnectionFailedEvent(XIncompatibleClient(major, minor).what());
cleanupTimer();
Expand All @@ -739,10 +746,10 @@ Client::handleHello(const Event&, void*)
}

// say hello back
LOG((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion));
LOG((CLOG_DEBUG1 "say hello version %d.%d", helloBackMajor, helloBackMinor));
ProtocolUtil::writef(m_stream, kMsgHelloBack,
kProtocolMajorVersion,
kProtocolMinorVersion, &m_name);
helloBackMajor,
helloBackMinor, & m_name);

// now connected but waiting to complete handshake
setupScreen();
Expand Down
26 changes: 24 additions & 2 deletions src/lib/client/ServerProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "synergy/ProtocolUtil.h"
#include "synergy/option_types.h"
#include "synergy/protocol_types.h"
#include "synergy/AppUtil.h"
#include "io/IStream.h"
#include "base/Log.h"
#include "base/IEventQueue.h"
Expand Down Expand Up @@ -129,8 +130,10 @@ ServerProxy::handleData(const Event&, void*)

case kUnknown:
LOG((CLOG_ERR "invalid message from server: %c%c%c%c", code[0], code[1], code[2], code[3]));
m_client->disconnect("invalid message from server");
return;
// not possible to determine message boundaries
// read the whole stream to discard unkonwn data
while (m_stream->read(nullptr, 4));
break;

case kDisconnect:
return;
Expand Down Expand Up @@ -303,6 +306,9 @@ ServerProxy::parseMessage(const UInt8* code)
else if (memcmp(code, kMsgDDragInfo, 4) == 0) {
dragInfoReceived();
}
else if (memcmp(code, kMsgDSecureInputNotification, 4) == 0) {
secureInputNotification();
}

else if (memcmp(code, kMsgCClose, 4) == 0) {
// server wants us to hangup
Expand Down Expand Up @@ -906,3 +912,19 @@ ServerProxy::sendDragInfo(UInt32 fileCount, const char* info, size_t size)
String data(info, size);
ProtocolUtil::writef(m_stream, kMsgDDragInfo, fileCount, &data);
}

void
ServerProxy::secureInputNotification()
{
String app;
ProtocolUtil::readf(m_stream, kMsgDSecureInputNotification + 4, &app);

String secureInputNotificationBody =
"'Secure input' enabled by " + app + " on the server. " \
"To fix the keyboard, " + app + " must be closed.";

// display this notification on the client
AppUtil::instance().showNotification(
"The keyboard may stop working.",
secureInputNotificationBody);
}
1 change: 1 addition & 0 deletions src/lib/client/ServerProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ class ServerProxy {
void fileChunkReceived();
void dragInfoReceived();
void handleClipboardSendingEvent(const Event&, void*);
void secureInputNotification();

private:
typedef EResult (ServerProxy::*MessageParser)(const UInt8*);
Expand Down
7 changes: 4 additions & 3 deletions src/lib/platform/MSWindowsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1988,10 +1988,11 @@ MSWindowsScreen::getDropTarget() const
return m_desktopPath;
}

void
MSWindowsScreen::createNotification(const String& title, const String& content) const
String
MSWindowsScreen::getSecureInputApp() const
{
// TODO: implement notification
// ignore on Windows
return "";
}

bool
Expand Down
2 changes: 1 addition & 1 deletion src/lib/platform/MSWindowsScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class MSWindowsScreen : public PlatformScreen {
virtual String& getDraggingFilename();
virtual const String&
getDropTarget() const;
void createNotification(const String& title, const String& content) const override;
String getSecureInputApp() const override;

protected:
// IPlatformScreen overrides
Expand Down
80 changes: 39 additions & 41 deletions src/lib/platform/OSXScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,55 +59,55 @@ class OSXScreen : public PlatformScreen {
IEventQueue* getEvents() const { return m_events; }

// IScreen overrides
virtual void* getEventTarget() const;
virtual bool getClipboard(ClipboardID id, IClipboard*) const;
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const;
virtual void getCursorPos(SInt32& x, SInt32& y) const;
void* getEventTarget() const override;
bool getClipboard(ClipboardID id, IClipboard*) const override;
void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const override;
void getCursorPos(SInt32& x, SInt32& y) const override;

// IPrimaryScreen overrides
virtual void reconfigure(UInt32 activeSides);
virtual void warpCursor(SInt32 x, SInt32 y);
virtual UInt32 registerHotKey(KeyID key, KeyModifierMask mask);
virtual void unregisterHotKey(UInt32 id);
virtual void fakeInputBegin();
virtual void fakeInputEnd();
virtual SInt32 getJumpZoneSize() const;
virtual bool isAnyMouseButtonDown(UInt32& buttonID) const;
virtual void getCursorCenter(SInt32& x, SInt32& y) const;
void reconfigure(UInt32 activeSides) override;
void warpCursor(SInt32 x, SInt32 y) override;
UInt32 registerHotKey(KeyID key, KeyModifierMask mask) override;
void unregisterHotKey(UInt32 id) override;
void fakeInputBegin() override;
void fakeInputEnd() override;
SInt32 getJumpZoneSize() const override;
bool isAnyMouseButtonDown(UInt32& buttonID) const override;
void getCursorCenter(SInt32& x, SInt32& y) const override;

// ISecondaryScreen overrides
virtual void fakeMouseButton(ButtonID id, bool press);
virtual void fakeMouseMove(SInt32 x, SInt32 y);
virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;
virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;
void fakeMouseButton(ButtonID id, bool press) override;
void fakeMouseMove(SInt32 x, SInt32 y) override;
void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const override;
void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const override;

// IPlatformScreen overrides
virtual void enable();
virtual void disable();
virtual void enter();
virtual bool leave();
virtual bool setClipboard(ClipboardID, const IClipboard*);
virtual void checkClipboards();
virtual void openScreensaver(bool notify);
virtual void closeScreensaver();
virtual void screensaver(bool activate);
virtual void resetOptions();
virtual void setOptions(const OptionsList& options);
virtual void setSequenceNumber(UInt32);
virtual bool isPrimary() const;
virtual void fakeDraggingFiles(DragFileList fileList);
virtual String& getDraggingFilename();
void enable() override;
void disable() override;
void enter() override;
bool leave() override;
bool setClipboard(ClipboardID, const IClipboard*) override;
void checkClipboards() override;
void openScreensaver(bool notify) override;
void closeScreensaver() override;
void screensaver(bool activate) override;
void resetOptions() override;
void setOptions(const OptionsList& options) override;
void setSequenceNumber(UInt32) override;
bool isPrimary() const override;
void fakeDraggingFiles(DragFileList fileList) override;
String& getDraggingFilename() override;
String getSecureInputApp() const override;

const String& getDropTarget() const { return m_dropTarget; }
void waitForCarbonLoop() const;
void createNotification(const String& title, const String& content) const override;
const String& getDropTarget() const override { return m_dropTarget; }
void waitForCarbonLoop() const;

protected:
// IPlatformScreen overrides
virtual void handleSystemEvent(const Event&, void*);
virtual void updateButtons();
virtual IKeyState* getKeyState() const;
void handleSystemEvent(const Event&, void*) override;
void updateButtons() override;
IKeyState* getKeyState() const override;

private:
bool updateScreenShape();
Expand Down Expand Up @@ -203,8 +203,6 @@ class OSXScreen : public PlatformScreen {
static char* CFStringRefToUTF8String(CFStringRef aString);

void getDropTargetThread(void*);

void createSecureInputNotification();

private:
struct HotKeyItem {
Expand Down
32 changes: 19 additions & 13 deletions src/lib/platform/OSXScreen.mm
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
kCarbonLoopWaitTimeout = 10
};

void createSecureInputNotification();
int getSecureInputEventPID();
String getProcessName(int pid);

Expand Down Expand Up @@ -2158,26 +2159,31 @@

}

void
OSXScreen::createNotification(const String& title, const String& content) const
String
OSXScreen::getSecureInputApp() const
{
LOG((CLOG_INFO "OSX Notification: %s|%s", title.c_str(), content.c_str()));
if(IsSecureEventInputEnabled()) {
int secureInputProcessPID = getSecureInputEventPID();
if(secureInputProcessPID == 0) return "unknown";
return getProcessName(secureInputProcessPID);
}
return "";
}

void
OSXScreen::createSecureInputNotification()
createSecureInputNotification()
{
std::string secureInputNotificationBody =
"Secure input was enabled in your system. " \
"Synergy may not be able to send keyboard strokes. ";

int secureInputProcessPID = getSecureInputEventPID();
std::string infringingProcessName = getProcessName(secureInputProcessPID);
if(secureInputProcessPID == 0) infringingProcessName = "unknown";
secureInputNotificationBody += "Infringing process is " + infringingProcessName;
String app = getProcessName(secureInputProcessPID);
if(secureInputProcessPID == 0) app = "unknown";

String secureInputNotificationBody =
"'Secure input' enabled by " + app + ". " \
"Close " + app + " to continue using keyboards on the clients.";

createNotification(
"Keyboard may not work correctly",
// display this notification on the server
AppUtil::instance().showNotification(
"The client keyboards may stop working.",
secureInputNotificationBody);
}

Expand Down
7 changes: 4 additions & 3 deletions src/lib/platform/XWindowsScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,11 @@ XWindowsScreen::isPrimary() const
return m_isPrimary;
}

void
XWindowsScreen::createNotification(const String& title, const String& content) const
String
XWindowsScreen::getSecureInputApp() const
{
// TODO: implement notification
// ignore on Linux
return "";
}

void*
Expand Down
2 changes: 1 addition & 1 deletion src/lib/platform/XWindowsScreen.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class XWindowsScreen : public PlatformScreen {
virtual void setOptions(const OptionsList& options);
virtual void setSequenceNumber(UInt32);
virtual bool isPrimary() const;
void createNotification(const String& title, const String& content) const override;
String getSecureInputApp() const override;

protected:
// IPlatformScreen overrides
Expand Down
2 changes: 2 additions & 0 deletions src/lib/server/BaseClientProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ class BaseClientProxy : public IClient {
virtual void sendDragInfo(UInt32 fileCount, const char* info,
size_t size) = 0;
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
virtual String getSecureInputApp() const = 0;
virtual void secureInputNotification(const String& app) const = 0;
virtual String getName() const;
virtual synergy::IStream*
getStream() const = 0;
Expand Down
55 changes: 28 additions & 27 deletions src/lib/server/ClientProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,40 +56,41 @@ class ClientProxy : public BaseClientProxy {
/*!
Returns the original stream passed to the c'tor.
*/
synergy::IStream* getStream() const;
synergy::IStream* getStream() const override;

//@}

// IScreen
virtual void* getEventTarget() const;
virtual bool getClipboard(ClipboardID id, IClipboard*) const = 0;
virtual void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const = 0;
virtual void getCursorPos(SInt32& x, SInt32& y) const = 0;
void* getEventTarget() const override;
bool getClipboard(ClipboardID id, IClipboard*) const override = 0;
void getShape(SInt32& x, SInt32& y,
SInt32& width, SInt32& height) const override = 0;
void getCursorPos(SInt32& x, SInt32& y) const override = 0;

// IClient overrides
virtual void enter(SInt32 xAbs, SInt32 yAbs,
void enter(SInt32 xAbs, SInt32 yAbs,
UInt32 seqNum, KeyModifierMask mask,
bool forScreensaver) = 0;
virtual bool leave() = 0;
virtual void setClipboard(ClipboardID, const IClipboard*) = 0;
virtual void grabClipboard(ClipboardID) = 0;
virtual void setClipboardDirty(ClipboardID, bool) = 0;
virtual void keyDown(KeyID, KeyModifierMask, KeyButton) = 0;
virtual void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton) = 0;
virtual void keyUp(KeyID, KeyModifierMask, KeyButton) = 0;
virtual void mouseDown(ButtonID) = 0;
virtual void mouseUp(ButtonID) = 0;
virtual void mouseMove(SInt32 xAbs, SInt32 yAbs) = 0;
virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel) = 0;
virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta) = 0;
virtual void screensaver(bool activate) = 0;
virtual void resetOptions() = 0;
virtual void setOptions(const OptionsList& options) = 0;
virtual void sendDragInfo(UInt32 fileCount, const char* info,
size_t size) = 0;
virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize) = 0;
bool forScreensaver) override = 0;
bool leave() override = 0;
void setClipboard(ClipboardID, const IClipboard*) override = 0;
void grabClipboard(ClipboardID) override = 0;
void setClipboardDirty(ClipboardID, bool) override = 0;
void keyDown(KeyID, KeyModifierMask, KeyButton) override = 0;
void keyRepeat(KeyID, KeyModifierMask,
SInt32 count, KeyButton) override = 0;
void keyUp(KeyID, KeyModifierMask, KeyButton) override = 0;
void mouseDown(ButtonID) override = 0;
void mouseUp(ButtonID) override = 0;
void mouseMove(SInt32 xAbs, SInt32 yAbs) override = 0;
void mouseRelativeMove(SInt32 xRel, SInt32 yRel) override = 0;
void mouseWheel(SInt32 xDelta, SInt32 yDelta) override = 0;
void screensaver(bool activate) override = 0;
void resetOptions() override = 0;
void setOptions(const OptionsList& options) override = 0;
void sendDragInfo(UInt32 fileCount, const char* info,
size_t size) override = 0;
void fileChunkSending(UInt8 mark, char* data, size_t dataSize) override = 0;
void secureInputNotification(const String& app) const override = 0;

private:
synergy::IStream* m_stream;
Expand Down

0 comments on commit 2fdde93

Please sign in to comment.