diff --git a/ChangeLog b/ChangeLog index 7855debe6..61473aa5b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -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 diff --git a/src/lib/client/Client.cpp b/src/lib/client/Client.cpp index a3bcff046..0ca688cf7 100644 --- a/src/lib/client/Client.cpp +++ b/src/lib/client/Client.cpp @@ -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(); @@ -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(); diff --git a/src/lib/client/ServerProxy.cpp b/src/lib/client/ServerProxy.cpp index 177baa6d5..3d431055b 100644 --- a/src/lib/client/ServerProxy.cpp +++ b/src/lib/client/ServerProxy.cpp @@ -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" @@ -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; @@ -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 @@ -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); +} diff --git a/src/lib/client/ServerProxy.h b/src/lib/client/ServerProxy.h index 463bab790..e9bdae8bb 100644 --- a/src/lib/client/ServerProxy.h +++ b/src/lib/client/ServerProxy.h @@ -112,6 +112,7 @@ private: void fileChunkReceived(); void dragInfoReceived(); void handleClipboardSendingEvent(const Event&, void*); + void secureInputNotification(); private: typedef EResult (ServerProxy::*MessageParser)(const UInt8*); diff --git a/src/lib/platform/MSWindowsScreen.cpp b/src/lib/platform/MSWindowsScreen.cpp index acfc53494..73d1ecd9a 100644 --- a/src/lib/platform/MSWindowsScreen.cpp +++ b/src/lib/platform/MSWindowsScreen.cpp @@ -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 diff --git a/src/lib/platform/MSWindowsScreen.h b/src/lib/platform/MSWindowsScreen.h index 8f2447c90..b8a6e2536 100644 --- a/src/lib/platform/MSWindowsScreen.h +++ b/src/lib/platform/MSWindowsScreen.h @@ -139,7 +139,7 @@ public: 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 diff --git a/src/lib/platform/OSXScreen.h b/src/lib/platform/OSXScreen.h index 1360b96a1..397f61c0b 100644 --- a/src/lib/platform/OSXScreen.h +++ b/src/lib/platform/OSXScreen.h @@ -59,55 +59,55 @@ public: 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(); @@ -203,8 +203,6 @@ private: static char* CFStringRefToUTF8String(CFStringRef aString); void getDropTargetThread(void*); - - void createSecureInputNotification(); private: struct HotKeyItem { diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm old mode 100755 new mode 100644 index f82ede88c..a81e54cf1 --- a/src/lib/platform/OSXScreen.mm +++ b/src/lib/platform/OSXScreen.mm @@ -59,6 +59,7 @@ enum { kCarbonLoopWaitTimeout = 10 }; +void createSecureInputNotification(); int getSecureInputEventPID(); String getProcessName(int pid); @@ -2158,26 +2159,31 @@ OSXScreen::waitForCarbonLoop() const } -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"; - createNotification( - "Keyboard may not work correctly", + String secureInputNotificationBody = + "'Secure input' enabled by " + app + ". " \ + "Close " + app + " to continue using keyboards on the clients."; + + // display this notification on the server + AppUtil::instance().showNotification( + "The client keyboards may stop working.", secureInputNotificationBody); } diff --git a/src/lib/platform/XWindowsScreen.cpp b/src/lib/platform/XWindowsScreen.cpp index 8bbde462e..560d3c7ac 100644 --- a/src/lib/platform/XWindowsScreen.cpp +++ b/src/lib/platform/XWindowsScreen.cpp @@ -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* diff --git a/src/lib/platform/XWindowsScreen.h b/src/lib/platform/XWindowsScreen.h index a0d401a0a..19689a2fc 100644 --- a/src/lib/platform/XWindowsScreen.h +++ b/src/lib/platform/XWindowsScreen.h @@ -84,7 +84,7 @@ public: 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 diff --git a/src/lib/server/BaseClientProxy.h b/src/lib/server/BaseClientProxy.h index 22076c7cb..0e6556b71 100644 --- a/src/lib/server/BaseClientProxy.h +++ b/src/lib/server/BaseClientProxy.h @@ -89,6 +89,8 @@ public: 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; diff --git a/src/lib/server/ClientProxy.h b/src/lib/server/ClientProxy.h index f978783e3..283f70be7 100644 --- a/src/lib/server/ClientProxy.h +++ b/src/lib/server/ClientProxy.h @@ -56,40 +56,41 @@ public: /*! 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; diff --git a/src/lib/server/ClientProxy1_0.cpp b/src/lib/server/ClientProxy1_0.cpp index 429973f18..5aee1278f 100644 --- a/src/lib/server/ClientProxy1_0.cpp +++ b/src/lib/server/ClientProxy1_0.cpp @@ -150,8 +150,9 @@ ClientProxy1_0::handleData(const Event&, void*) LOG((CLOG_DEBUG2 "msg from \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3])); if (!(this->*m_parser)(code)) { LOG((CLOG_ERR "invalid message from client \"%s\": %c%c%c%c", getName().c_str(), code[0], code[1], code[2], code[3])); - disconnect(); - return; + // not possible to determine message boundaries + // read the whole stream to discard unkonwn data + while (getStream()->read(nullptr, 4)); } // next message @@ -365,6 +366,21 @@ ClientProxy1_0::fileChunkSending(UInt8 mark, char* data, size_t dataSize) LOG((CLOG_DEBUG "fileChunkSending not supported")); } +String +ClientProxy1_0::getSecureInputApp() const +{ + // ignore -- not supported on clients + LOG((CLOG_DEBUG "getSecureInputApp not supported")); + return ""; +} + +void +ClientProxy1_0::secureInputNotification(const String& app) const +{ + // ignore -- not supported in protocol 1.0 + LOG((CLOG_DEBUG "secureInputNotification not supported")); +} + void ClientProxy1_0::screensaver(bool on) { diff --git a/src/lib/server/ClientProxy1_0.h b/src/lib/server/ClientProxy1_0.h index edd3ec6f4..ce122332b 100644 --- a/src/lib/server/ClientProxy1_0.h +++ b/src/lib/server/ClientProxy1_0.h @@ -38,33 +38,35 @@ public: ClientProxy1_0& operator=(ClientProxy1_0 &&) =delete; // IScreen - 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; + 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; // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, + void enter(SInt32 xAbs, SInt32 yAbs, UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver); - virtual bool leave(); - virtual void setClipboard(ClipboardID, const IClipboard*); - virtual void grabClipboard(ClipboardID); - virtual void setClipboardDirty(ClipboardID, bool); - virtual void keyDown(KeyID, KeyModifierMask, KeyButton); - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton); - virtual void keyUp(KeyID, KeyModifierMask, KeyButton); - virtual void mouseDown(ButtonID); - virtual void mouseUp(ButtonID); - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel); - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const OptionsList& options); - virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size); - virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize); + bool forScreensaver) override; + bool leave() override; + void setClipboard(ClipboardID, const IClipboard*) override; + void grabClipboard(ClipboardID) override; + void setClipboardDirty(ClipboardID, bool) override; + void keyDown(KeyID, KeyModifierMask, KeyButton) override; + void keyRepeat(KeyID, KeyModifierMask, + SInt32 count, KeyButton) override; + void keyUp(KeyID, KeyModifierMask, KeyButton) override; + void mouseDown(ButtonID) override; + void mouseUp(ButtonID) override; + void mouseMove(SInt32 xAbs, SInt32 yAbs) override; + void mouseRelativeMove(SInt32 xRel, SInt32 yRel) override; + void mouseWheel(SInt32 xDelta, SInt32 yDelta) override; + void screensaver(bool activate) override; + void resetOptions() override; + void setOptions(const OptionsList& options) override; + void sendDragInfo(UInt32 fileCount, const char* info, size_t size) override; + void fileChunkSending(UInt8 mark, char* data, size_t dataSize) override; + String getSecureInputApp() const override; + void secureInputNotification(const String& app) const override; protected: virtual bool parseHandshakeMessage(const UInt8* code); diff --git a/src/lib/server/ClientProxy1_7.cpp b/src/lib/server/ClientProxy1_7.cpp new file mode 100644 index 000000000..bd51778e8 --- /dev/null +++ b/src/lib/server/ClientProxy1_7.cpp @@ -0,0 +1,41 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015-2016 Symless Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "server/ClientProxy1_7.h" +#include "server/Server.h" +#include "synergy/AppUtil.h" +#include "synergy/ProtocolUtil.h" +#include "base/TMethodEventJob.h" +#include "base/Log.h" + +// +// ClientProxy1_7 +// + +ClientProxy1_7::ClientProxy1_7(const String& name, synergy::IStream* stream, Server* server, IEventQueue* events) : + ClientProxy1_6(name, stream, server, events), + m_events(events) +{ + +} + +void +ClientProxy1_7::secureInputNotification(const String& app) const +{ + LOG((CLOG_DEBUG2 "send secure input notification to \"%s\" %s", getName().c_str(), app.c_str())); + ProtocolUtil::writef(getStream(), kMsgDSecureInputNotification, &app); +} diff --git a/src/lib/server/ClientProxy1_7.h b/src/lib/server/ClientProxy1_7.h new file mode 100644 index 000000000..04343edb7 --- /dev/null +++ b/src/lib/server/ClientProxy1_7.h @@ -0,0 +1,33 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2015-2016 Symless Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include "server/ClientProxy1_6.h" + +//! Proxy for client implementing protocol version 1.7 +class ClientProxy1_7 : public ClientProxy1_6 { +public: + ClientProxy1_7(const String& name, synergy::IStream* adoptedStream, Server* server, IEventQueue* events); + ~ClientProxy1_7() override = default; + + void secureInputNotification(const String& app) const override; + +private: + + IEventQueue* m_events; +}; diff --git a/src/lib/server/ClientProxyUnknown.cpp b/src/lib/server/ClientProxyUnknown.cpp index 7df67c0f1..3b7bfc802 100644 --- a/src/lib/server/ClientProxyUnknown.cpp +++ b/src/lib/server/ClientProxyUnknown.cpp @@ -26,6 +26,7 @@ #include "server/ClientProxy1_4.h" #include "server/ClientProxy1_5.h" #include "server/ClientProxy1_6.h" +#include "server/ClientProxy1_7.h" #include "synergy/protocol_types.h" #include "synergy/ProtocolUtil.h" #include "synergy/XSynergy.h" @@ -232,6 +233,10 @@ ClientProxyUnknown::handleData(const Event&, void*) case 6: m_proxy = new ClientProxy1_6(name, m_stream, m_server, m_events); break; + + case 7: + m_proxy = new ClientProxy1_7(name, m_stream, m_server, m_events); + break; } } diff --git a/src/lib/server/PrimaryClient.cpp b/src/lib/server/PrimaryClient.cpp index 76731228e..63d40fe15 100644 --- a/src/lib/server/PrimaryClient.cpp +++ b/src/lib/server/PrimaryClient.cpp @@ -261,6 +261,18 @@ PrimaryClient::fileChunkSending(UInt8 mark, char* data, size_t dataSize) // ignore } +String +PrimaryClient::getSecureInputApp() const +{ + return m_screen->getSecureInputApp(); +} + +void +PrimaryClient::secureInputNotification(const String& app) const +{ + // ignore +} + void PrimaryClient::resetOptions() { diff --git a/src/lib/server/PrimaryClient.h b/src/lib/server/PrimaryClient.h index f63bbf5cf..a4d6fcc97 100644 --- a/src/lib/server/PrimaryClient.h +++ b/src/lib/server/PrimaryClient.h @@ -117,38 +117,40 @@ public: virtual void disable(); // 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; // IClient overrides - virtual void enter(SInt32 xAbs, SInt32 yAbs, + void enter(SInt32 xAbs, SInt32 yAbs, UInt32 seqNum, KeyModifierMask mask, - bool forScreensaver); - virtual bool leave(); - virtual void setClipboard(ClipboardID, const IClipboard*); - virtual void grabClipboard(ClipboardID); - virtual void setClipboardDirty(ClipboardID, bool); - virtual void keyDown(KeyID, KeyModifierMask, KeyButton); - virtual void keyRepeat(KeyID, KeyModifierMask, - SInt32 count, KeyButton); - virtual void keyUp(KeyID, KeyModifierMask, KeyButton); - virtual void mouseDown(ButtonID); - virtual void mouseUp(ButtonID); - virtual void mouseMove(SInt32 xAbs, SInt32 yAbs); - virtual void mouseRelativeMove(SInt32 xRel, SInt32 yRel); - virtual void mouseWheel(SInt32 xDelta, SInt32 yDelta); - virtual void screensaver(bool activate); - virtual void resetOptions(); - virtual void setOptions(const OptionsList& options); - virtual void sendDragInfo(UInt32 fileCount, const char* info, size_t size); - virtual void fileChunkSending(UInt8 mark, char* data, size_t dataSize); + bool forScreensaver) override; + bool leave() override; + void setClipboard(ClipboardID, const IClipboard*) override; + void grabClipboard(ClipboardID) override; + void setClipboardDirty(ClipboardID, bool) override; + void keyDown(KeyID, KeyModifierMask, KeyButton) override; + void keyRepeat(KeyID, KeyModifierMask, + SInt32 count, KeyButton) override; + void keyUp(KeyID, KeyModifierMask, KeyButton) override; + void mouseDown(ButtonID) override; + void mouseUp(ButtonID) override; + void mouseMove(SInt32 xAbs, SInt32 yAbs) override; + void mouseRelativeMove(SInt32 xRel, SInt32 yRel) override; + void mouseWheel(SInt32 xDelta, SInt32 yDelta) override; + void screensaver(bool activate) override; + void resetOptions() override; + void setOptions(const OptionsList& options) override; + void sendDragInfo(UInt32 fileCount, const char* info, size_t size) override; + void fileChunkSending(UInt8 mark, char* data, size_t dataSize) override; + String getSecureInputApp() const override; + void secureInputNotification(const String& app) const override; - virtual synergy::IStream* - getStream() const { return NULL; } - bool isPrimary() const { return true; } + synergy::IStream* + getStream() const override { return nullptr; } + bool isPrimary() const override { return true; } private: synergy::Screen* m_screen; bool m_clipboardDirty[kClipboardEnd]; diff --git a/src/lib/server/Server.cpp b/src/lib/server/Server.cpp index b620e401c..e56b83253 100644 --- a/src/lib/server/Server.cpp +++ b/src/lib/server/Server.cpp @@ -511,6 +511,14 @@ Server::switchScreen(BaseClientProxy* dst, } } + +#if defined(__APPLE__) + String secureInputApplication = m_active->getSecureInputApp(); + if (m_active == m_primaryClient && secureInputApplication != "") { + dst->secureInputNotification(secureInputApplication); + } +#endif + // cut over m_active = dst; diff --git a/src/lib/synergy/IAppUtil.h b/src/lib/synergy/IAppUtil.h index 5f94e82d6..657bbfc82 100644 --- a/src/lib/synergy/IAppUtil.h +++ b/src/lib/synergy/IAppUtil.h @@ -20,6 +20,7 @@ #include "common/IInterface.h" #include "synergy/IApp.h" +#include "base/String.h" class IAppUtil : public IInterface { public: @@ -28,4 +29,5 @@ public: virtual int run(int argc, char** argv) = 0; virtual void beforeAppExit() = 0; virtual void startNode() = 0; + virtual void showNotification(const String& title, const String& text) const = 0; }; diff --git a/src/lib/synergy/IPlatformScreen.h b/src/lib/synergy/IPlatformScreen.h index ccb325f75..6a24019fa 100644 --- a/src/lib/synergy/IPlatformScreen.h +++ b/src/lib/synergy/IPlatformScreen.h @@ -133,11 +133,11 @@ public: //! Change dragging status virtual void setDraggingStarted(bool started) = 0; - //! Send desktop user notification + //! Determine the name of the app causing a secure input state /*! - Creates a platform dependant user notificaiton using native APIs + On MacOS check which app causes a secure input state to be enabled. No alternative on other platforms */ - virtual void createNotification(const String& title, const String& content) const = 0; + virtual String getSecureInputApp() const = 0; //@} //! @name accessors diff --git a/src/lib/synergy/Screen.cpp b/src/lib/synergy/Screen.cpp index 15ab824f4..18245b840 100644 --- a/src/lib/synergy/Screen.cpp +++ b/src/lib/synergy/Screen.cpp @@ -522,10 +522,10 @@ Screen::leaveSecondary() m_screen->fakeAllKeysUp(); } -void -Screen::createNotification(const String& title, const String& content) const +String +Screen::getSecureInputApp() const { - m_screen->createNotification(title, content); + return m_screen->getSecureInputApp(); } } diff --git a/src/lib/synergy/Screen.h b/src/lib/synergy/Screen.h index 15bf2f096..34d5efa89 100644 --- a/src/lib/synergy/Screen.h +++ b/src/lib/synergy/Screen.h @@ -234,11 +234,11 @@ public: void setEnableDragDrop(bool enabled); - //! Send desktop user notification + //! Determine the name of the app causing a secure input state /*! - Creates a platform dependant user notificaiton using native APIs + On MacOS check which app causes a secure input state to be enabled. No alternative on other platforms */ - virtual void createNotification(const String& title, const String& content) const; + String getSecureInputApp() const; //@} //! @name accessors diff --git a/src/lib/synergy/protocol_types.cpp b/src/lib/synergy/protocol_types.cpp index e4834fce0..80f2fe4ec 100644 --- a/src/lib/synergy/protocol_types.cpp +++ b/src/lib/synergy/protocol_types.cpp @@ -18,36 +18,37 @@ #include "synergy/protocol_types.h" -const char* kMsgHello = "Synergy%2i%2i"; -const char* kMsgHelloBack = "Synergy%2i%2i%s"; -const char* kMsgCNoop = "CNOP"; -const char* kMsgCClose = "CBYE"; -const char* kMsgCEnter = "CINN%2i%2i%4i%2i"; -const char* kMsgCLeave = "COUT"; -const char* kMsgCClipboard = "CCLP%1i%4i"; -const char* kMsgCScreenSaver = "CSEC%1i"; -const char* kMsgCResetOptions = "CROP"; -const char* kMsgCInfoAck = "CIAK"; -const char* kMsgCKeepAlive = "CALV"; -const char* kMsgDKeyDown = "DKDN%2i%2i%2i"; -const char* kMsgDKeyDown1_0 = "DKDN%2i%2i"; -const char* kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"; -const char* kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"; -const char* kMsgDKeyUp = "DKUP%2i%2i%2i"; -const char* kMsgDKeyUp1_0 = "DKUP%2i%2i"; -const char* kMsgDMouseDown = "DMDN%1i"; -const char* kMsgDMouseUp = "DMUP%1i"; -const char* kMsgDMouseMove = "DMMV%2i%2i"; -const char* kMsgDMouseRelMove = "DMRM%2i%2i"; -const char* kMsgDMouseWheel = "DMWM%2i%2i"; -const char* kMsgDMouseWheel1_0 = "DMWM%2i"; -const char* kMsgDClipboard = "DCLP%1i%4i%1i%s"; -const char* kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i"; -const char* kMsgDSetOptions = "DSOP%4I"; -const char* kMsgDFileTransfer = "DFTR%1i%s"; -const char* kMsgDDragInfo = "DDRG%2i%s"; -const char* kMsgQInfo = "QINF"; -const char* kMsgEIncompatible = "EICV%2i%2i"; -const char* kMsgEBusy = "EBSY"; -const char* kMsgEUnknown = "EUNK"; -const char* kMsgEBad = "EBAD"; +const char* const kMsgHello = "Synergy%2i%2i"; +const char* const kMsgHelloBack = "Synergy%2i%2i%s"; +const char* const kMsgCNoop = "CNOP"; +const char* const kMsgCClose = "CBYE"; +const char* const kMsgCEnter = "CINN%2i%2i%4i%2i"; +const char* const kMsgCLeave = "COUT"; +const char* const kMsgCClipboard = "CCLP%1i%4i"; +const char* const kMsgCScreenSaver = "CSEC%1i"; +const char* const kMsgCResetOptions = "CROP"; +const char* const kMsgCInfoAck = "CIAK"; +const char* const kMsgCKeepAlive = "CALV"; +const char* const kMsgDKeyDown = "DKDN%2i%2i%2i"; +const char* const kMsgDKeyDown1_0 = "DKDN%2i%2i"; +const char* const kMsgDKeyRepeat = "DKRP%2i%2i%2i%2i"; +const char* const kMsgDKeyRepeat1_0 = "DKRP%2i%2i%2i"; +const char* const kMsgDKeyUp = "DKUP%2i%2i%2i"; +const char* const kMsgDKeyUp1_0 = "DKUP%2i%2i"; +const char* const kMsgDMouseDown = "DMDN%1i"; +const char* const kMsgDMouseUp = "DMUP%1i"; +const char* const kMsgDMouseMove = "DMMV%2i%2i"; +const char* const kMsgDMouseRelMove = "DMRM%2i%2i"; +const char* const kMsgDMouseWheel = "DMWM%2i%2i"; +const char* const kMsgDMouseWheel1_0 = "DMWM%2i"; +const char* const kMsgDClipboard = "DCLP%1i%4i%1i%s"; +const char* const kMsgDInfo = "DINF%2i%2i%2i%2i%2i%2i%2i"; +const char* const kMsgDSetOptions = "DSOP%4I"; +const char* const kMsgDFileTransfer = "DFTR%1i%s"; +const char* const kMsgDDragInfo = "DDRG%2i%s"; +const char* const kMsgDSecureInputNotification = "SECN%s"; +const char* const kMsgQInfo = "QINF"; +const char* const kMsgEIncompatible = "EICV%2i%2i"; +const char* const kMsgEBusy = "EBSY"; +const char* const kMsgEUnknown = "EUNK"; +const char* const kMsgEBad = "EBAD"; diff --git a/src/lib/synergy/protocol_types.h b/src/lib/synergy/protocol_types.h index e3f7f42c1..4fec0ac37 100644 --- a/src/lib/synergy/protocol_types.h +++ b/src/lib/synergy/protocol_types.h @@ -31,7 +31,7 @@ // 1.6: adds clipboard streaming // NOTE: with new version, synergy minor version should increment static const SInt16 kProtocolMajorVersion = 1; -static const SInt16 kProtocolMinorVersion = 6; +static const SInt16 kProtocolMinorVersion = 7; // default contact port number static const UInt16 kDefaultPort = 24800; @@ -103,13 +103,13 @@ enum EDataReceived { // say hello to client; primary -> secondary // $1 = protocol major version number supported by server. $2 = // protocol minor version number supported by server. -extern const char* kMsgHello; +extern const char* const kMsgHello; // respond to hello from server; secondary -> primary // $1 = protocol major version number supported by client. $2 = // protocol minor version number supported by client. $3 = client // name. -extern const char* kMsgHelloBack; +extern const char* const kMsgHelloBack; // @@ -117,10 +117,10 @@ extern const char* kMsgHelloBack; // // no operation; secondary -> primary -extern const char* kMsgCNoop; +extern const char* const kMsgCNoop; // close connection; primary -> secondary -extern const char* kMsgCClose; +extern const char* const kMsgCClose; // enter screen: primary -> secondary // entering screen at screen position $1 = x, $2 = y. x,y are @@ -130,7 +130,7 @@ extern const char* kMsgCClose; // mask. this will have bits set for each toggle modifier key // that is activated on entry to the screen. the secondary screen // should adjust its toggle modifiers to reflect that state. -extern const char* kMsgCEnter; +extern const char* const kMsgCEnter; // leave screen: primary -> secondary // leaving screen. the secondary screen should send clipboard @@ -139,28 +139,28 @@ extern const char* kMsgCEnter; // not received a kMsgCClipboard for with a greater sequence // number) and that were grabbed or have changed since the // last leave. -extern const char* kMsgCLeave; +extern const char* const kMsgCLeave; // grab clipboard: primary <-> secondary // sent by screen when some other app on that screen grabs a // clipboard. $1 = the clipboard identifier, $2 = sequence number. // secondary screens must use the sequence number passed in the // most recent kMsgCEnter. the primary always sends 0. -extern const char* kMsgCClipboard; +extern const char* const kMsgCClipboard; // screensaver change: primary -> secondary // screensaver on primary has started ($1 == 1) or closed ($1 == 0) -extern const char* kMsgCScreenSaver; +extern const char* const kMsgCScreenSaver; // reset options: primary -> secondary // client should reset all of its options to their defaults. -extern const char* kMsgCResetOptions; +extern const char* const kMsgCResetOptions; // resolution change acknowledgment: primary -> secondary // sent by primary in response to a secondary screen's kMsgDInfo. // this is sent for every kMsgDInfo, whether or not the primary // had sent a kMsgQInfo. -extern const char* kMsgCInfoAck; +extern const char* const kMsgCInfoAck; // keep connection alive: primary <-> secondary // sent by the server periodically to verify that connections are still @@ -170,7 +170,7 @@ extern const char* kMsgCInfoAck; // client doesn't receive these (or any message) periodically then it // should disconnect from the server. the appropriate interval is // defined by an option. -extern const char* kMsgCKeepAlive; +extern const char* const kMsgCKeepAlive; // // data codes @@ -187,57 +187,57 @@ extern const char* kMsgCKeepAlive; // the press. this can happen with combining (dead) keys or if // the keyboard layouts are not identical and the user releases // a modifier key before releasing the modified key. -extern const char* kMsgDKeyDown; +extern const char* const kMsgDKeyDown; // key pressed 1.0: same as above but without KeyButton -extern const char* kMsgDKeyDown1_0; +extern const char* const kMsgDKeyDown1_0; // key auto-repeat: primary -> secondary // $1 = KeyID, $2 = KeyModifierMask, $3 = number of repeats, $4 = KeyButton -extern const char* kMsgDKeyRepeat; +extern const char* const kMsgDKeyRepeat; // key auto-repeat 1.0: same as above but without KeyButton -extern const char* kMsgDKeyRepeat1_0; +extern const char* const kMsgDKeyRepeat1_0; // key released: primary -> secondary // $1 = KeyID, $2 = KeyModifierMask, $3 = KeyButton -extern const char* kMsgDKeyUp; +extern const char* const kMsgDKeyUp; // key released 1.0: same as above but without KeyButton -extern const char* kMsgDKeyUp1_0; +extern const char* const kMsgDKeyUp1_0; // mouse button pressed: primary -> secondary // $1 = ButtonID -extern const char* kMsgDMouseDown; +extern const char* const kMsgDMouseDown; // mouse button released: primary -> secondary // $1 = ButtonID -extern const char* kMsgDMouseUp; +extern const char* const kMsgDMouseUp; // mouse moved: primary -> secondary // $1 = x, $2 = y. x,y are absolute screen coordinates. -extern const char* kMsgDMouseMove; +extern const char* const kMsgDMouseMove; // relative mouse move: primary -> secondary // $1 = dx, $2 = dy. dx,dy are motion deltas. -extern const char* kMsgDMouseRelMove; +extern const char* const kMsgDMouseRelMove; // mouse scroll: primary -> secondary // $1 = xDelta, $2 = yDelta. the delta should be +120 for one tick forward // (away from the user) or right and -120 for one tick backward (toward // the user) or left. -extern const char* kMsgDMouseWheel; +extern const char* const kMsgDMouseWheel; // mouse vertical scroll: primary -> secondary // like as kMsgDMouseWheel except only sends $1 = yDelta. -extern const char* kMsgDMouseWheel1_0; +extern const char* const kMsgDMouseWheel1_0; // clipboard data: primary <-> secondary // $2 = sequence number, $3 = mark $4 = clipboard data. the sequence number // is 0 when sent by the primary. secondary screens should use the // sequence number from the most recent kMsgCEnter. $1 = clipboard // identifier. -extern const char* kMsgDClipboard; +extern const char* const kMsgDClipboard; // client data: secondary -> primary // $1 = coordinate of leftmost pixel on secondary screen, @@ -253,25 +253,30 @@ extern const char* kMsgDClipboard; // should ignore any kMsgDMouseMove messages until it receives a // kMsgCInfoAck in order to prevent attempts to move the mouse off // the new screen area. -extern const char* kMsgDInfo; +extern const char* const kMsgDInfo; // set options: primary -> secondary // client should set the given option/value pairs. $1 = option/value // pairs. -extern const char* kMsgDSetOptions; +extern const char* const kMsgDSetOptions; // file data: primary <-> secondary // transfer file data. A mark is used in the first byte. // 0 means the content followed is the file size. // 1 means the content followed is the chunk data. // 2 means the file transfer is finished. -extern const char* kMsgDFileTransfer; +extern const char* const kMsgDFileTransfer; // drag infomation: primary <-> secondary // transfer drag infomation. The first 2 bytes are used for storing // the number of dragging objects. Then the following string consists // of each object's directory. -extern const char* kMsgDDragInfo; +extern const char* const kMsgDDragInfo; + +// secure input notification: primary -> secondary +// $1 = app. app only obtainable on MacOS since that's the only +// platform facing secure input problems +extern const char* const kMsgDSecureInputNotification; // // query codes @@ -279,7 +284,7 @@ extern const char* kMsgDDragInfo; // query screen info: primary -> secondary // client should reply with a kMsgDInfo. -extern const char* kMsgQInfo; +extern const char* const kMsgQInfo; // @@ -288,19 +293,19 @@ extern const char* kMsgQInfo; // incompatible versions: primary -> secondary // $1 = major version of primary, $2 = minor version of primary. -extern const char* kMsgEIncompatible; +extern const char* const kMsgEIncompatible; // name provided when connecting is already in use: primary -> secondary -extern const char* kMsgEBusy; +extern const char* const kMsgEBusy; // unknown client: primary -> secondary // name provided when connecting is not in primary's screen // configuration map. -extern const char* kMsgEUnknown; +extern const char* const kMsgEUnknown; // protocol violation: primary -> secondary // primary should disconnect after sending this message. -extern const char* kMsgEBad; +extern const char* const kMsgEBad; // diff --git a/src/lib/synergy/unix/AppUtilUnix.cpp b/src/lib/synergy/unix/AppUtilUnix.cpp index a052bfd92..7c2adec4d 100644 --- a/src/lib/synergy/unix/AppUtilUnix.cpp +++ b/src/lib/synergy/unix/AppUtilUnix.cpp @@ -18,6 +18,8 @@ #include "synergy/unix/AppUtilUnix.h" #include "synergy/ArgsBase.h" +#include "base/Log.h" +#include "base/log_outputters.h" AppUtilUnix::AppUtilUnix(IEventQueue* events) { @@ -44,3 +46,16 @@ AppUtilUnix::startNode() { app().startNode(); } + +void +AppUtilUnix::showNotification(const String & title, const String & text) const +{ + LOG((CLOG_DEBUG "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str())); +#if WINAPI_XWINDOWS + +#elif WINAPI_CARBON + // synergys and synergyc are not allowed to send native notifications on MacOS + // instead ask main synergy process to show them instead + LOG((CLOG_INFO "OSX Notification: %s|%s", title.c_str(), text.c_str())); +#endif +} diff --git a/src/lib/synergy/unix/AppUtilUnix.h b/src/lib/synergy/unix/AppUtilUnix.h index ba235dcc6..63f5007c0 100644 --- a/src/lib/synergy/unix/AppUtilUnix.h +++ b/src/lib/synergy/unix/AppUtilUnix.h @@ -31,4 +31,5 @@ public: int run(int argc, char** argv); void startNode(); + void showNotification(const String& title, const String& text) const override; }; diff --git a/src/lib/synergy/win32/AppUtilWindows.cpp b/src/lib/synergy/win32/AppUtilWindows.cpp index 7641c94c1..d1c64a467 100644 --- a/src/lib/synergy/win32/AppUtilWindows.cpp +++ b/src/lib/synergy/win32/AppUtilWindows.cpp @@ -180,3 +180,9 @@ AppUtilWindows::startNode() { app().startNode(); } + +void +AppUtilWindows::showNotification(const String & title, const String & text) const +{ + LOG((CLOG_DEBUG "Showing notification. Title: \"%s\". Text: \"%s\"", title.c_str(), text.c_str())); +} diff --git a/src/lib/synergy/win32/AppUtilWindows.h b/src/lib/synergy/win32/AppUtilWindows.h index 04b6d4242..007249bcd 100644 --- a/src/lib/synergy/win32/AppUtilWindows.h +++ b/src/lib/synergy/win32/AppUtilWindows.h @@ -54,6 +54,8 @@ public: void startNode(); + void showNotification(const String& title, const String& text) const override; + private: AppExitMode m_exitMode; IEventQueue* m_events;