Skip to content

Single instance#510

Merged
TheZ3ro merged 3 commits intokeepassxreboot:developfrom
antongulenko:single-instance
May 27, 2017
Merged

Single instance#510
TheZ3ro merged 3 commits intokeepassxreboot:developfrom
antongulenko:single-instance

Conversation

@antongulenko
Copy link
Copy Markdown
Contributor

@antongulenko antongulenko commented Apr 18, 2017

Description

This PR merges an older KeepassX PR that implements a single-instance mode, meaning that an existing keepassxc instance is raised instead of starting a second one. This has been proposed here, but I did not find a corresponding pull request.
For flexibility, a command line switch should probably be added to disable the single-instance mode if desired.

Motivation and context

Single-instance mode allows raising keepassxc from the tray by running keepassxc from a script or a global keyboard shortcut.
Resolves #14.

How has this been tested?

Compiled with the following cmake flags:
-DWITH_TESTS=OFF -DWITH_XC_AUTOTYPE=ON -DWITH_XC_HTTP=ON -DWITH_ASAN=ON
Everything seems to work fine. When running keepassxc repeatedly, it prints a message, notifies the running instance, and exits.

Types of changes

  • ✅ New feature (non-breaking change which adds functionality)

Checklist:

  • ✅ I have read the CONTRIBUTING document. [REQUIRED]
  • ✅ My code follows the code style of this project. [REQUIRED]
  • ✅ All new and existing tests passed. [REQUIRED]
  • ✅ I have compiled and verified my code with -DWITH_ASAN=ON. [REQUIRED]

if (userName.isEmpty()) {
userName = qgetenv("USERNAME");
}
QString identifier = "keepassx2";
Copy link
Copy Markdown
Contributor

@TheZ3ro TheZ3ro Apr 18, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be changed to keepassxc

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit pushed.

@droidmonkey
Copy link
Copy Markdown
Member

droidmonkey commented Apr 18, 2017

I do not agree with this implementation as it adds the networking dependency to all builds. We explicitly moved networking out of the core build so that a totally unconnected app can be built.

@phoerious
Copy link
Copy Markdown
Member

Can't we do that via DBus instead?

@vsvyatski
Copy link
Copy Markdown
Contributor

Just an idea: it can be theoretically done via a mutex. Some of you may not like Microsoft, but nevertheless I've found that idea on their site (it's MFC most likely, but the idea can be borrowed) https://support.microsoft.com/en-us/help/243953/how-to-limit-32-bit-applications-to-one-instance-in-visual-c
Qt has the QMutex class.

@antongulenko
Copy link
Copy Markdown
Contributor Author

Thanks for the feedback!
Unfortunately I lack the know-how to quickly re-implement this with another mechanism.
I hope that one of the devs will take this on, I think it would really increase the usability of keepassxc.

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented Apr 24, 2017

Better doing this with DBus or Mutex? @phoerious @droidmonkey

@droidmonkey
Copy link
Copy Markdown
Member

Yes i think so. I do not want to reintroduce a network dependency for this feature. There are better ways to handle this.

@nicwortel
Copy link
Copy Markdown

I just wanted to point out that I stumbled upon this PR because I was looking for a solution to limit KeePassXC to a single instance. I often accidentally open a second instance instead of opening the existing one.

Since the linked issue (#99) is more about adding a key combination than about (the ability of) limiting to a single instance, I figured I'd drop this comment here.

As a final note, thanks everyone for your work! 👍

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented Apr 28, 2017

Currently DBus is supported only on Linux

Seems that the only cross-platform option are:

  • setting a QLockFile in the user tmp folder
  • using a named QSharedMemory

http://blog.aeguana.com/2015/10/15/how-to-run-a-single-app-instance-in-qt/

The implementation in this PR is already using a QLockFile but add a QLocalServer

@sledgehammer999
Copy link
Copy Markdown

My 2 cents: There is also qtsingleapplication. We use it in qBittorrent and seems to work across all platforms.

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 1, 2017

@sledgehammer999 thanks for the suggestion.
I've seen that but unfortunately QtSimpleApplication is using QLocalServer and QLocalSocket.

From QLocalSocket documentation:

On Windows this is a named pipe and on Unix this is a local domain socket.

But still you will need to compile with Qt5::Network and like @droidmonkey said:

I do not agree with this implementation as it adds the networking dependency to all builds. We explicitly moved networking out of the core build so that a totally unconnected app can be built.

@Keisial
Copy link
Copy Markdown

Keisial commented May 2, 2017

What do you define as as «totally unconnected app»? And what is the goal of getting that?

You could call directly the low-level functions, thus avoiding the usage of Qt5::Network, but it would be doing the same in disguise. It may be worth if you just want to avoid linking with the library, though. It's not as if the lack of linking with Qt5::Network meant that the binary would be unable to perform network calls.

@droidmonkey
Copy link
Copy Markdown
Member

Its more of a symbolic gesture to those individuals that want some greater assurance that their passwords are not potentially exposed to a network interface of any kind.

It seems to me that a temporary lock file could easily do the trick. Just have to be clever about app crashes (store pid in the file and check for running?)

@phoerious
Copy link
Copy Markdown
Member

QLockFile does that already.

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 2, 2017

I was trying to develop a solution without using any Qt5::Network API.

The main thing is:
In the PR implementation the first started instance place a QLockFile. The newer instances will try to lock that file but seeing that is already locked will fail and connect to the QLocalServer socket. The first instance then will catch the connection, close it and raise the window.

I've tried replacing the QLocalServer with unix signals and Win32 messages but that will make things more complicate.

Sincerely, I think we should include QLocalServer and use this PR.
Otherwise, by using only QLockFile we cannot raise the first instance and only detect if KeePassXC is already running.

I agree that a password manager shouldn't use the network stack at all. But like specified in the Qt docs:

QLocalSocket: On Windows this is a named pipe and on Unix this is a local domain socket.

This is not "making network connection", it will works even without a networkadapter

@Keisial
Copy link
Copy Markdown

Keisial commented May 2, 2017

Not linking the Qt5::Network API is indeed symbolic. I would simply accept that library and replace it with an optional module that -on modern Linux- sets up a seccomp sandbox forbidding any socket(2) call where domain is not AF_LOCAL.
Done early enough, that guarantees the keepassxc program won't open a network connection (there are other means of exfiltration, of course). It should be admitted that KeePassHTTP would fail when such extension is enabled.

The main issue I see is that the seccomp filter is inherited through fork+execve. So, if the user opened an url, and that launched a new browser. That browser descendant of keepassxc would be unable to connect to the network (and probably fail bizarrely).

@droidmonkey
Copy link
Copy Markdown
Member

droidmonkey commented May 7, 2017

I think this PR needs to be properly brought up to speed with the KeePassXC code base. We already integrate the Qt5::Network plugin with HTTP so it shouldn't be added to CMake.

Also, this does not resolve #99 since that is asking for a global shortcut that raises and lowers the window similar to autotype shortcut. In fairness that issue was modified several times.

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 7, 2017

@droidmonkey This is not meant to resolve #99 but rather #14

@droidmonkey
Copy link
Copy Markdown
Member

Yah I know, i edited the description to say that 😉

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 7, 2017

Missed the edit in the first post 😄

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 8, 2017

What type of works this PR needs? Can we use QLocalServer for detecting running instances?

@droidmonkey
Copy link
Copy Markdown
Member

Let's do it, makes the most sense

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 8, 2017

This PR already use it. It needs only a rebase and should be fine/ready to merge

@antongulenko
Copy link
Copy Markdown
Contributor Author

I rebased the PR, please check if it matches your expectations.

@phoerious
Copy link
Copy Markdown
Member

So, this still requires QNetworking?

@TheZ3ro
Copy link
Copy Markdown
Contributor

TheZ3ro commented May 14, 2017

@phoerious Yes, for QLocalSocket

@TheZ3ro TheZ3ro requested review from droidmonkey and phoerious May 21, 2017 17:47
mainWindow.raise();
mainWindow.activateWindow();
});
QObject::connect(&app, SIGNAL(openFile(QString)), &mainWindow, SLOT(openDatabase(QString)));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't all the stuff after this be skipped when another instance is already running?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there is a return 0 at line 61 (if another instance is already running).

(Maybe should that be return 1 instead?)

@droidmonkey droidmonkey added this to the v2.2.0 milestone May 26, 2017
@TheZ3ro TheZ3ro requested review from louib and weslly May 26, 2017 08:35
Copy link
Copy Markdown
Member

@droidmonkey droidmonkey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to fix windows compile errors separately in ScreenLockListenerWin.cpp

@TheZ3ro TheZ3ro merged commit 22d533c into keepassxreboot:develop May 27, 2017
droidmonkey added a commit that referenced this pull request Jun 25, 2017
- Added YubiKey 2FA integration for unlocking databases [#127]
- Added TOTP support [#519]
- Added CSV import tool [#146, #490]
- Added KeePassXC CLI tool [#254]
- Added diceware password generator [#373]
- Added support for entry references [#370, #378]
- Added support for Twofish encryption [#167]
- Enabled DEP and ASLR for in-memory protection [#371]
- Enabled single instance mode [#510]
- Enabled portable mode [#645]
- Enabled database lock on screensaver and session lock [#545]
- Redesigned welcome screen with common features and recent databases [#292]
- Multiple updates to search behavior [#168, #213, #374, #471, #603, #654]
- Added auto-type fields {CLEARFIELD}, {SPACE}, {{}, {}} [#267, #427, #480]
- Fixed auto-type errors on Linux [#550]
- Prompt user prior to executing a cmd:// URL [#235]
- Entry attributes can be protected (hidden) [#220]
- Added extended ascii to password generator [#538]
- Added new database icon to toolbar [#289]
- Added context menu entry to empty recycle bin in databases [#520]
- Added "apply" button to entry and group edit windows [#624]
- Added macOS tray icon and enabled minimize on close [#583]
- Fixed issues with unclean shutdowns [#170, #580]
- Changed keyboard shortcut to create new database to CTRL+SHIFT+N [#515]
- Compare window title to entry URLs [#556]
- Implemented inline error messages [#162]
- Ignore group expansion and other minor changes when making database "dirty" [#464]
- Updated license and copyright information on souce files [#632]
- Added contributors list to about dialog [#629]
@maevic maevic mentioned this pull request Aug 1, 2017
@phoerious phoerious added pr: new feature Pull request adds a new feature and removed new feature labels Nov 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: new feature Pull request adds a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for single-window mode like KeePass

10 participants