├── doc
├── .gitignore
├── images
│ ├── logo.png
│ ├── vs-attach.png
│ ├── vs-output-tab.png
│ ├── vs-continue-without-code.png
│ ├── vs-attach-to-process-keepass.png
│ ├── vs-dotnet-desktop-development.png
│ ├── win10-keeagent-zip-contents.png
│ ├── win10-keepass2-plugins-folder.png
│ └── win10-keepass2-plugins-folder-drag-and-drop.png
├── integrations
│ ├── images
│ │ ├── win10-keepass-help-menu.png
│ │ ├── win10-keepass-group-menu.png
│ │ ├── win10-keepass-tools-menu.png
│ │ ├── win10-keepass-application-menu.png
│ │ ├── win10-keepass-entry-menu-expanded.png
│ │ ├── win10-keepass-group-context-menu.png
│ │ ├── win10-keepass-context-menu-expanded.png
│ │ └── win10-keepass-notification-tray-menu.png
│ ├── index.rst
│ └── menu-items.rst
├── usage
│ ├── images
│ │ ├── win10-keepass-keeagent-dialog.png
│ │ ├── win10-keepass-add-entry-entry-tab.png
│ │ ├── win10-keepass-entry-keeagent-tab.png
│ │ ├── win10-keepass-add-entry-advanced-tab.png
│ │ ├── win10-keepass-add-entry-keeagent-tab.png
│ │ ├── win10-keepass-context-menu-load-ssh-key.png
│ │ ├── win10-keepass-global-options-keeagent-tab.png
│ │ ├── win10-keepass-keeagent-manager-agent-mode.png
│ │ ├── win10-keepass-keeagent-manager-client-mode.png
│ │ ├── win10-keepass-keeagent-manager-file-browser.png
│ │ ├── win10-keepass-keeagent-manager-select-entry-dialog.png
│ │ └── win10-keepass-entry-keeagent-tab-private-key-file-location.png
│ ├── index.rst
│ ├── quick-start.rst
│ ├── keeagent-manager.rst
│ └── tips-and-tricks.rst
├── pyproject.toml
├── index.rst
├── README.md
├── installation.rst
└── troubleshooting.rst
├── KeeAgent
├── Test.kdbx
├── Resources
│ ├── help-3.png
│ ├── KeeAgent-icon.ico
│ ├── KeeAgent-icon.png
│ ├── KeeAgent-icon-mono.ico
│ └── CREDIT.txt
├── KeePass.exe.config
├── PublicKeyRequiredException.cs
├── Properties
│ ├── DataSources
│ │ ├── EntrySettings.datasource
│ │ ├── DatabaseSettings.datasource
│ │ ├── EntrySettings.LocationData.datasource
│ │ ├── EntrySettings.DestinationConstraint.datasource
│ │ └── EntrySettings.DestinationConstraint.KeySpec.datasource
│ ├── AssemblyInfo.cs
│ └── Resources.Designer.cs
├── UI
│ ├── AttachmentBindingList.cs
│ ├── InPlaceMessage.cs
│ ├── DatabaseSettingsPanel.cs
│ ├── ManageKeyFileDialog.cs
│ ├── DecryptProgressDialog.cs
│ ├── PasswordDialog.cs
│ ├── UIHelper.cs
│ ├── TreeViewEx.cs
│ ├── PasswordDialog.Designer.cs
│ ├── SystemIcon.cs
│ ├── InPlaceMessage.Designer.cs
│ ├── DecryptProgressDialog.Designer.cs
│ ├── GroupBoxEx.cs
│ ├── DatabaseSettingsPanel.Designer.cs
│ ├── HostKeysDialog.cs
│ ├── Validate.cs
│ ├── ManageDialog.Designer.cs
│ ├── ManageKeyFileDialog.Designer.cs
│ ├── ManageDialog.cs
│ ├── EntryPickerDialog.resx
│ ├── ManageKeyFileDialog.resx
│ ├── DecryptProgressDialog.resx
│ └── HostKeysDialog.resx
├── NoAttachmentException.cs
├── NotificationOptions.cs
├── DatabaseSettings.cs
├── KeeAgentUiThread.cs
├── KeePass.config.xml
├── Options.cs
└── KeeAgentColumnProvider.cs
├── graphics
└── KeeAgent-icon.xcf
├── .gitmodules
├── LICENSE.txt
├── .vscode
├── settings.json
├── extensions.json
├── tasks.json
└── launch.json
├── scripts
└── msbuild.ps1
├── .gitignore
├── KeeAgentTestProject
├── Resources
│ ├── dsa.ppk
│ ├── withoutPassphrase.ppk
│ ├── withPassphrase.ppk
│ ├── ssh2-rsa-non-ascii-passphrase.ppk
│ └── 4095-bits.ppk
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── KeeAgentExtInitTest.cs
├── KeeAgentTestProject.csproj
├── OptionsTest.cs
└── IOProtocolExtTest.cs
├── .github
└── workflows
│ └── build.yml
├── README.md
├── .readthedocs.yml
├── HACKING.md
├── KeeAgent.sln
└── .editorconfig
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | .venv/
2 | _build/
3 |
--------------------------------------------------------------------------------
/KeeAgent/Test.kdbx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/KeeAgent/Test.kdbx
--------------------------------------------------------------------------------
/doc/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/logo.png
--------------------------------------------------------------------------------
/doc/images/vs-attach.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/vs-attach.png
--------------------------------------------------------------------------------
/graphics/KeeAgent-icon.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/graphics/KeeAgent-icon.xcf
--------------------------------------------------------------------------------
/KeeAgent/Resources/help-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/KeeAgent/Resources/help-3.png
--------------------------------------------------------------------------------
/doc/images/vs-output-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/vs-output-tab.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "SshAgentLib"]
2 | path = SshAgentLib
3 | url = https://github.com/dlech/SshAgentLib.git
4 |
--------------------------------------------------------------------------------
/KeeAgent/Resources/KeeAgent-icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/KeeAgent/Resources/KeeAgent-icon.ico
--------------------------------------------------------------------------------
/KeeAgent/Resources/KeeAgent-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/KeeAgent/Resources/KeeAgent-icon.png
--------------------------------------------------------------------------------
/doc/images/vs-continue-without-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/vs-continue-without-code.png
--------------------------------------------------------------------------------
/KeeAgent/Resources/KeeAgent-icon-mono.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/KeeAgent/Resources/KeeAgent-icon-mono.ico
--------------------------------------------------------------------------------
/doc/images/vs-attach-to-process-keepass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/vs-attach-to-process-keepass.png
--------------------------------------------------------------------------------
/doc/images/vs-dotnet-desktop-development.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/vs-dotnet-desktop-development.png
--------------------------------------------------------------------------------
/doc/images/win10-keeagent-zip-contents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/win10-keeagent-zip-contents.png
--------------------------------------------------------------------------------
/doc/images/win10-keepass2-plugins-folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/win10-keepass2-plugins-folder.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-help-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-help-menu.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-keeagent-dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-keeagent-dialog.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-group-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-group-menu.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-tools-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-tools-menu.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-add-entry-entry-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-add-entry-entry-tab.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-entry-keeagent-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-entry-keeagent-tab.png
--------------------------------------------------------------------------------
/doc/images/win10-keepass2-plugins-folder-drag-and-drop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/images/win10-keepass2-plugins-folder-drag-and-drop.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-application-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-application-menu.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-add-entry-advanced-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-add-entry-advanced-tab.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-add-entry-keeagent-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-add-entry-keeagent-tab.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-entry-menu-expanded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-entry-menu-expanded.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-group-context-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-group-context-menu.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-context-menu-load-ssh-key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-context-menu-load-ssh-key.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-context-menu-expanded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-context-menu-expanded.png
--------------------------------------------------------------------------------
/doc/integrations/images/win10-keepass-notification-tray-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/integrations/images/win10-keepass-notification-tray-menu.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-global-options-keeagent-tab.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-global-options-keeagent-tab.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-keeagent-manager-agent-mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-keeagent-manager-agent-mode.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-keeagent-manager-client-mode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-keeagent-manager-client-mode.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-keeagent-manager-file-browser.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-keeagent-manager-file-browser.png
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-keeagent-manager-select-entry-dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-keeagent-manager-select-entry-dialog.png
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | KeeAgent is licensed under GPLv2 (see GPL2.txt).
2 |
3 | It also includes lots of other software with varying licenses.
4 |
5 | See SshAgentLib/LICENSE.txt for more information.
6 |
--------------------------------------------------------------------------------
/doc/usage/images/win10-keepass-entry-keeagent-tab-private-key-file-location.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dlech/KeeAgent/HEAD/doc/usage/images/win10-keepass-entry-keeagent-tab-private-key-file-location.png
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "restructuredtext.confPath": "${workspaceFolder}/doc",
3 | "restructuredtext.builtDocumentationPath": "${workspaceRoot}/doc/_build/html",
4 | "omnisharp.useModernNet": false
5 | }
6 |
--------------------------------------------------------------------------------
/doc/integrations/index.rst:
--------------------------------------------------------------------------------
1 | ====================
2 | KeePass Integrations
3 | ====================
4 |
5 | This section gives detailed information on all of the ways KeeAgent is integrated
6 | into KeePass.
7 |
8 | .. toctree::
9 | :maxdepth: 2
10 |
11 | menu-items
12 |
--------------------------------------------------------------------------------
/doc/usage/index.rst:
--------------------------------------------------------------------------------
1 | =====
2 | Usage
3 | =====
4 |
5 | Read the :doc:`quick-start` for a basic introduction or jump ahead to the more
6 | detailed information.
7 |
8 | .. toctree::
9 | :maxdepth: 2
10 |
11 | quick-start
12 | options
13 | keeagent-manager
14 | tips-and-tricks
15 |
--------------------------------------------------------------------------------
/KeeAgent/KeePass.exe.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/KeeAgent/Resources/CREDIT.txt:
--------------------------------------------------------------------------------
1 | KeeAgent*.*
2 | Copyright (C) 2013 David Lechner
3 | Derived from http://openclipart.org/detail/10458/hat-outline-by-rygle-10458
4 | and Ext/Icons/Finals/key-bw.png from the KeePass 2.x
5 | source code.
6 |
7 | help-3.png
8 | Copyright (C) ???? David Vignoni
9 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See http://go.microsoft.com/fwlink/?LinkId=827846
3 | // for the documentation about the extensions.json format
4 | "recommendations": [
5 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
6 | "ms-dotnettools.csharp",
7 | "ms-vscode.mono-debug",
8 | "lextudio.restructuredtext"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/KeeAgent/PublicKeyRequiredException.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System;
5 |
6 | namespace KeeAgent
7 | {
8 | [Serializable]
9 | internal sealed class PublicKeyRequiredException : Exception
10 | {
11 | public PublicKeyRequiredException()
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/scripts/msbuild.ps1:
--------------------------------------------------------------------------------
1 | # Convience script to find msbuild.exe when it is not in $env:PATH
2 | # from https://github.com/microsoft/vswhere/wiki/Find-MSBuild#powershell
3 |
4 | $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
5 | $path = & "$vswhere" -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | select-object -first 1
6 | if ($path) {
7 | & $path $args
8 | }
9 |
--------------------------------------------------------------------------------
/doc/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.poetry]
2 | package-mode = false
3 | name = "keeagent-doc"
4 | version = "0.1.0"
5 | description = "KeeAgent Documentation"
6 | authors = ["David Lechner "]
7 |
8 | [tool.poetry.dependencies]
9 | python = "^3.10"
10 | sphinx = "^7.3.7"
11 | sphinx-rtd-theme = "^2.0.0"
12 |
13 | [tool.poetry.dev-dependencies]
14 |
15 | [build-system]
16 | requires = ["poetry>=0.12"]
17 | build-backend = "poetry.masonry.api"
18 |
--------------------------------------------------------------------------------
/doc/index.rst:
--------------------------------------------------------------------------------
1 | .. KeeAgent documentation master file, created by
2 | sphinx-quickstart on Fri Jan 26 10:42:29 2018.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to KeeAgent's documentation!
7 | ====================================
8 |
9 | Contents:
10 |
11 | .. toctree::
12 | :maxdepth: 2
13 |
14 | installation
15 | usage/index
16 | integrations/index
17 | troubleshooting
18 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | # Building docs locally
2 |
3 | ## Prerequisites
4 |
5 | - [Python 3.x](https://python.org)
6 | - [Poetry](https://python-poetry.org)
7 |
8 | ## Commands
9 |
10 | ### Windows
11 |
12 | cd doc
13 | poetry install # one time setup of virtual environment
14 | poetry run make.bat html # build docs
15 | Invoke-Item .\_build\html\index.html # open in browser
16 |
17 | ### Linux
18 |
19 | cd doc
20 | poetry install # one time setup of virtual environment
21 | poetry run make html # build docs
22 | xdg-open _build/html/index.html # open in browser
23 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | KeeAgent*.tar.gz
2 | KeeAgent*.zip
3 | KeeAgent.plgx
4 | Local.proj
5 |
6 | #ignore thumbnails created by windows
7 | Thumbs.db
8 | #Ignore files build by Visual Studio
9 | *.obj
10 | *.exe
11 | *.pdb
12 | *.user
13 | *.aps
14 | *.pch
15 | *.vspscc
16 | *_i.c
17 | *_p.c
18 | *.ncb
19 | *.suo
20 | *.tlb
21 | *.tlh
22 | *.bak
23 | *.cache
24 | *.ilk
25 | *.log
26 | [Bb]in
27 | [Dd]ebug*/
28 | *.lib
29 | *.sbr
30 | obj/
31 | [Rr]elease*/
32 | _ReSharper*/
33 | [Tt]est[Rr]esult*
34 | _UpgradeReport*
35 | *.zip
36 | .vs/
37 |
38 | *.resources
39 | *.userprefs
40 | test-results*/
41 | [Pp]ackages/
42 |
43 | #ignore jetbrains rider files
44 | .idea/
45 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/DataSources/EntrySettings.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | KeeAgent.EntrySettings, KeeAgent, Version=0.3.1.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/DataSources/DatabaseSettings.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | KeeAgent.DatabaseSettings, KeeAgent, Version=0.2.0.2, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/DataSources/EntrySettings.LocationData.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | KeeAgent.EntrySettings+LocationData, KeeAgent, Version=0.3.3.0, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/DataSources/EntrySettings.DestinationConstraint.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | KeeAgent.EntrySettings+DestinationConstraint, KeeAgent, Version=0.13.0.20997, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/DataSources/EntrySettings.DestinationConstraint.KeySpec.datasource:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 | KeeAgent.EntrySettings+DestinationConstraint+KeySpec, KeeAgent, Version=0.13.0.20997, Culture=neutral, PublicKeyToken=null
10 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Resources/dsa.ppk:
--------------------------------------------------------------------------------
1 | PuTTY-User-Key-File-2: ssh-dss
2 | Encryption: aes256-cbc
3 | Comment: KeeAgent SSH2-DSA, with pass
4 | Public-Lines: 10
5 | AAAAB3NzaC1kc3MAAACBAKBYHO7twBGbR3dv+eRr8RNjLd42gq5RglXTtzJ9wQzA
6 | ivz7glbaJObFSGK68FekUhNWY6bLUCSZdj71g/MNKzqhZdfBdgWMScIWzOyOu3ip
7 | vrlKetq3/KbZsgmeDbeterPj+NBQDrercqMxXqHjgz0WCjPLlo4Kb7u7cfa6djdP
8 | AAAAFQDGY/dtGLZuX55XFqZM886xuUCg8QAAAIBBwAdPjFe1KLrIPrpV3qw4+kee
9 | nVGnfVKc4zOe3ntri6cViv7XJXi9W38bUTjIxIIX9BBlUnkG0Z1iaYP8p3qlqhzW
10 | 7wL8cjg/S2i+sCSlq8lLTXt58+aoIshazPpVteauF5Q6H60MkFhC7E1Tay2oTo5w
11 | MuNv8INSoyXMzFK+NwAAAIEAh5atc6nmvZEjqQnUI/WnCOd7nFnn0lKqjIb2JzZn
12 | T3UwKSyh9sQvegtOCQjmS4zkfBUx4iP/JRAgc4mCuhrDQiZiQPj7CyYQTyUccti9
13 | 9yDQ7qnbivqJRQfV6I48Jcy0K/u7PDJAsHjpym7lnn8HBa0BahwUM6enAazraiY0
14 | 5No=
15 | Private-Lines: 1
16 | vBygW8EkAVj/vHoUkmIytDmtSC52ka2Oz0kT2HxJ67U=
17 | Private-MAC: d40042812cebee69616b63528eb3c707dae09b7e
18 |
--------------------------------------------------------------------------------
/KeeAgent/UI/AttachmentBindingList.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System.Collections.Generic;
5 | using System.ComponentModel;
6 | using System.Linq;
7 | using KeePassLib.Collections;
8 | using KeePassLib.Security;
9 |
10 | namespace KeeAgent.UI
11 | {
12 | ///
13 | /// Binding list wrapper for PwEntry attachments.
14 | ///
15 | public class AttachmentBindingList : BindingList>
16 | {
17 | ///
18 | /// Creates a new list.
19 | ///
20 | /// The binary dictionary.
21 | public AttachmentBindingList(ProtectedBinaryDictionary binaries) : base(binaries.ToList())
22 | {
23 | AllowEdit = false;
24 | AllowNew = false;
25 | AllowRemove = false;
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Resources/withoutPassphrase.ppk:
--------------------------------------------------------------------------------
1 | PuTTY-User-Key-File-2: ssh-rsa
2 | Encryption: none
3 | Comment: KeeAgent test file, without passphrase
4 | Public-Lines: 4
5 | AAAAB3NzaC1yc2EAAAABJQAAAIEAlBEmrFXHVcN7Go43z4fdJz9uP2hSEgc/rEur
6 | aHoRGAvi3dPyH3IOyUwK3dfRLWnxMyK3yeHLlFLyMYwEIgFJVXGER+4ooywRPCk0
7 | S9vISRY54cxQkIVWCZ/QKhSB+W7OnU4yWmorFmXNg5+7HPwlf+sL0VbxdI0SoYBV
8 | oK3decU=
9 | Private-Lines: 8
10 | AAAAgBwDPqr7eL0y0hnH4QuWPpi4+S6XMh8WIM2RxnuMtyA5mZ+WzPExQRFTk1pn
11 | Gbx706+6dcw/eYrDlZqryW43mEBNcotbs38w1MNPy5fWNqt0Aj3aMCWONEKyg4/E
12 | C5JpftrbIiLUQftjx21FtXzNljAbTspGKuAEfNipQiz1KrDtAAAAQQDzDrB6hyAP
13 | U3l9a88tnMOBjN/enEWyBukFpeTZAwrYFP1qX0pxuRh9IEGPDdBtHI/VSz8ZJSWi
14 | OY/5o/LEcOjVAAAAQQCb85JFyCv2EANzuOxmeER4oSi1kTsszS3GBSjBiuiyP61d
15 | jFffp4P92EmgNyaZgV+FaUCBxRyJ/AYICsBHQcUxAAAAQFCEMyHDV9+eu6AUkkIH
16 | EsGWtbmkLvkNClNXdtzzZLnsMmBiImsubWYWzkO8nzeR8qO3rgl2wTW6YtP46Zet
17 | c9w=
18 | Private-MAC: 889afa7412587789dc6d023054cb09eafe63a7bb
19 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Resources/withPassphrase.ppk:
--------------------------------------------------------------------------------
1 | PuTTY-User-Key-File-2: ssh-rsa
2 | Encryption: aes256-cbc
3 | Comment: KeeAgent test file, with passphrase
4 | Public-Lines: 4
5 | AAAAB3NzaC1yc2EAAAABJQAAAIEA2y6R3DB+rdDe9CKPvVJPKGeJIZ0KkuF6o3hm
6 | 3dYHduIfJtDOx5HJXE1Mx7sRgfsMtZuQi9Su2BOZa9N4CoqdCdYS7cuKJxKUds2d
7 | Ca9oKNy5bhUTpBDGMcXJKETzEdwQw0q+opUUdASLFkmompVEttYZIGwmFxVr40Tq
8 | ZjnJ4aM=
9 | Private-Lines: 8
10 | APLGzZsv1OQ3kHVWqUXc15PF8zKIXKHUX0vGR3ZShPl4vuPHJqBwBFxsQ+TZjCur
11 | DBuCVAvVNonH7JHRIwKE20Pxzx+A9DN9p+8lZCeg8ZlqgQ6HN3FgZhbGcWySDiLm
12 | ghulnPK8VX72V9EOB/r1lWIGBcCoAhWHamf8PQ7xiOKgxB9aLh0hSz9r7pDumnH2
13 | 4yHMychAcMx/YVgxUbpvIZ57L2hwzioP/3s8Xzt56lUeV2b80eWodkgh6hWcyE1I
14 | 60PIQQ62LSXmiN+jpMjE4+X9cWkfvY6OaxOAHiDeiWErK36zqhdiSr64sjIBCMQt
15 | LH1GznycalVaZyPXNH4Wagohznzj/eF6pNVzRhBrp5NG9f9oU4LG5G+VS1RNgeLv
16 | c6B1Jlhfji44cYWTqVqTcgWHRbV/tyr7xWXWrmqwTeWhwxmXeUrxLCw4gGP4qGVE
17 | R0C7fsKX02kNS62vABUK8w==
18 | Private-MAC: 716800c0c9c188f1f586c7a979b7c62ca94fc8f8
19 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Resources/ssh2-rsa-non-ascii-passphrase.ppk:
--------------------------------------------------------------------------------
1 | PuTTY-User-Key-File-2: ssh-rsa
2 | Encryption: aes256-cbc
3 | Comment: rsa-key-20120818
4 | Public-Lines: 4
5 | AAAAB3NzaC1yc2EAAAABJQAAAIBzAyJ8l/gz/x+rv+H06+G0u3jsMfnerDEAnbt+
6 | MkUmoNE1T/zupE4tnojTmTv+d9qrb930iz3vKqgHHK3YfCN4OsSl043e1hvQiSaV
7 | QKdXrlVASRyJ9gavHhKndx1mb5aV8C4SFD5/3sEUFJU5yH6bPUhmPphzSswGoNY1
8 | S3qdlQ==
9 | Private-Lines: 8
10 | FDyEqyZ12/KIckibxhC678DjVptE17L9ROTRN7vCMQmU70c1xOfAKDiT6vM7Uggu
11 | jM2Cnjd6A+iAVlF2238la6R7UJ4zsFwome3nEaKtXbxmWG3VLMcxLSCFsuTZOI69
12 | L615GflzHnm1pZMifIUvyLpsg9DwC7ElGounU8fb2U69BtCsWEbm+w8nS8ypeXnZ
13 | yu0JNEzqaoQJqpoPoXdDYZ3eKaLLLOlmKK8kj6GwYqTgboUhU49iAX6yz2PeRinK
14 | S2tYu+eChBgJGLpD7HAMk8eT5gaUrlGK571PCwVoC5rwKjHWB95zDgoNNPyQ6RZG
15 | fGQ4VTw2bxXQoWkQpnt9incQTq1oouEtXXWyKv7UcO/+JHKcujTe1FjpzmdHlHrt
16 | FV+RbHPHtx8h6q4CacOTWFYGAZEAIPmtlfuit32HKQGbrKJ6eDe73nkaovgZZ6sT
17 | G9F/SOUy8DAPxkJKVoz27w==
18 | Private-MAC: e9ee3de8e33405272b75d36b7efdba5680c91978
19 |
--------------------------------------------------------------------------------
/KeeAgent/NoAttachmentException.cs:
--------------------------------------------------------------------------------
1 | //
2 | // NoAttachmentException.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 |
24 | namespace KeeAgent
25 | {
26 | class NoAttachmentException : Exception
27 | {
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/KeeAgent/NotificationOptions.cs:
--------------------------------------------------------------------------------
1 | //
2 | // NotificationOptions.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | namespace KeeAgent
23 | {
24 | public enum NotificationOptions
25 | {
26 | AlwaysAsk,
27 | AskOnce,
28 | Balloon,
29 | Never
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build DLL/PLGX
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: windows-2022
9 |
10 | steps:
11 | - uses: actions/checkout@v4
12 | with:
13 | submodules: true
14 |
15 | - name: Install prerequisites
16 | run: |
17 | choco install keepass.install --version=2.50
18 | nuget restore
19 |
20 | - name: Setup MSBuild.exe
21 | uses: microsoft/setup-msbuild@v2
22 |
23 | - name: Build DLL
24 | run: msbuild /property:Configuration=ReleaseDll /t:build KeeAgent.sln
25 |
26 | - uses: actions/upload-artifact@v4
27 | with:
28 | name: KeeAgent.dll
29 | path: KeeAgent/bin/ReleaseDll/KeeAgent.dll
30 |
31 | - name: Build PLGX
32 | run: msbuild /property:Configuration=ReleasePlgx /t:build KeeAgent.sln
33 |
34 | - name: List PLGX
35 | run: ~\.nuget\packages\plgxtool\1.0.3\tools\PlgxTool.exe -l .\KeeAgent\bin\ReleasePlgx\KeeAgent.plgx
36 |
37 | - uses: actions/upload-artifact@v4
38 | with:
39 | name: KeeAgent.plgx
40 | path: KeeAgent/bin/ReleasePlgx/KeeAgent.plgx
41 |
--------------------------------------------------------------------------------
/KeeAgent/DatabaseSettings.cs:
--------------------------------------------------------------------------------
1 | //
2 | // DatabaseSettings.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2013-2014 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 |
24 | namespace KeeAgent
25 | {
26 | public class DatabaseSettings
27 | {
28 | public DatabaseSettings()
29 | {
30 | }
31 |
32 | public bool AllowAutoLoadExpiredEntryKey { get; set; }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("KeeAgent")]
8 | [assembly: AssemblyDescription("SSH authentication agent plugin for KeePass 2.x")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("David Lechner")]
11 | [assembly: AssemblyProduct("KeePass Plugin")]
12 | [assembly: AssemblyCopyright("2012-2024")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("73dddcd4-0cae-4744-b87f-d65f835a3264")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | [assembly: AssemblyVersion("0.13.8.0")]
32 | [assembly: AssemblyFileVersion("0.13.8.0")]
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | KeeAgent is a plugin for KeePass 2.x. It allows other programs to access SSH
4 | keys stored in your KeePass database for authentication. It can either act as a
5 | stand-alone agent or it can interface with an external agent.
6 |
7 |
8 | DOWNLOAD
9 | --------
10 |
11 | #### Official release
12 |
13 | Get the latest stable official release of KeeAgent at .
14 |
15 | #### Chocolatey 📦
16 |
17 | You can [use Chocolatey to install](https://community.chocolatey.org/packages/keepass-plugin-keeagent#install) it in a more automated manner:
18 |
19 | ```
20 | choco install keepass-plugin-keeagent
21 | ```
22 |
23 | To [upgrade KeePass Plugin KeeAgent](https://community.chocolatey.org/packages/keepass-plugin-keeagent#upgrade) to the [latest release version](https://community.chocolatey.org/packages/keepass-plugin-keeagent#versionhistory) for enjoying the newest features, run the following command from the command line or from PowerShell:
24 |
25 | ```
26 | choco upgrade keepass-plugin-keeagent
27 | ```
28 |
29 |
30 | USAGE
31 | -----
32 |
33 | Documentation is at https://keeagent.readthedocs.io/en/latest/
34 |
35 |
36 | HACKING
37 | -------
38 |
39 | Pull requests are welcome! See [HACKING.md](./HACKING.md) for more info.
40 |
41 |
42 | COPYRIGHT
43 | ---------
44 |
45 | (C) 2012-2024 David Lechner
46 |
--------------------------------------------------------------------------------
/KeeAgent/UI/InPlaceMessage.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System.ComponentModel;
5 | using System.Windows.Forms;
6 |
7 | namespace KeeAgent.UI
8 | {
9 | ///
10 | /// Label-like control for displaying an in-place message with icon.
11 | ///
12 | public partial class InPlaceMessage : UserControl
13 | {
14 | ///
15 | /// Creates a new in-place message control.
16 | ///
17 | public InPlaceMessage()
18 | {
19 | InitializeComponent();
20 | label1.TextChanged += (s, e) => OnTextChanged(e);
21 | }
22 |
23 | ///
24 | /// Gets and sets the icon.
25 | ///
26 | [Category("Appearance"), DefaultValue(SystemIcon.StockIconId.Info)]
27 | public SystemIcon.StockIconId StockIcon {
28 | get { return systemIcon1.StockIcon; }
29 | set { systemIcon1.StockIcon = value; }
30 | }
31 |
32 | ///
33 | /// Gets and sets the message text.
34 | ///
35 | [Bindable(true)]
36 | [Browsable(true)]
37 | [DefaultValue("")]
38 | [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
39 | public override string Text {
40 | get { return label1.Text; }
41 | set { label1.Text = value; }
42 | }
43 |
44 | public override void ResetText()
45 | {
46 | Text = "";
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/.readthedocs.yml:
--------------------------------------------------------------------------------
1 |
2 |
3 | # Read the Docs configuration file for Sphinx projects
4 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
5 |
6 | # Required
7 | version: 2
8 |
9 | # Set the OS, Python version and other tools you might need
10 | build:
11 | os: ubuntu-22.04
12 | tools:
13 | python: "3.12"
14 | # You can also specify other tool versions:
15 | # nodejs: "20"
16 | # rust: "1.70"
17 | # golang: "1.20"
18 | jobs:
19 | post_create_environment:
20 | # Install poetry
21 | # https://python-poetry.org/docs/#installing-manually
22 | - pip install poetry
23 | post_install:
24 | # VIRTUAL_ENV needs to be set manually for now.
25 | # See https://github.com/readthedocs/readthedocs.org/pull/11152/
26 | - cd doc && VIRTUAL_ENV=$READTHEDOCS_VIRTUALENV_PATH poetry install
27 |
28 | # Build documentation in the "docs/" directory with Sphinx
29 | sphinx:
30 | configuration: doc/conf.py
31 | # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
32 | # builder: "dirhtml"
33 | # Fail on all warnings to avoid broken references
34 | # fail_on_warning: true
35 |
36 | # Optionally build your docs in additional formats such as PDF and ePub
37 | formats:
38 | - pdf
39 | # - epub
40 |
41 | # Optional but recommended, declare the Python requirements required
42 | # to build your documentation
43 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
44 | # python:
45 | # install:
46 | # - requirements: docs/requirements.txt
--------------------------------------------------------------------------------
/HACKING.md:
--------------------------------------------------------------------------------
1 |
2 | ### Building KeeAgent in Visual Studio (Windows)
3 |
4 | #### Setting up the KeeAgent solution in Visual Studio
5 |
6 | ##### Setup Debug Properties
7 |
8 | These are not saved in KeeAgent.csproj, so you have to manually set them up.
9 | * Open the project properties for the KeeAgent project.
10 | * On the *Debug* tab, in the *Start Action* section, select *Start external
11 | program:* and enter `/bin/Debug/KeePass.exe`, where
12 | `` is the actual path on your machine.
13 |
14 | If you have not tried to build the project yet, then you will get an error
15 | that the program does not exist. Ignore the error.
16 | * Then in the *Start Options* section, set *Command line arguments* to
17 | `--debug --pw:test Test.kdbx`.
18 | * Do the same for the *Release* and *ReleasePlgx* configurations, substituting
19 | the configuration name for *Debug* in `bin/Debug/KeePass.exe`.
20 |
21 | Also leave out the `--debug` command line argument for these configurations.
22 |
23 |
24 | ### Building KeeAgent in Visual Studio Code (Linux/MacOS/Windows)
25 |
26 | * Get the code and open it in Visual Studio Code:
27 |
28 | git clone --recursive https://github.com/dlech/KeeAgent.git
29 | cd KeeAgent
30 | nuget restore
31 | code .
32 |
33 | * Install suggested extensions in VS Code
34 |
35 | * Run using VS Code debugger (F5)
36 |
37 | If `msbuild` is not present, change `tasks.json` to us `xbuild` instead.
38 |
39 |
40 | ### Building KeeAgent from the Command Line (Linux/MacOS)
41 |
42 | * Make sure you have mono (>= v3.2.x)
43 |
44 | * Get the code:
45 |
46 | git clone --recursive https://github.com/dlech/KeeAgent.git
47 | cd KeeAgent
48 |
49 | * Restore the nuget packages:
50 |
51 | wget https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
52 | mono nuget.exe restore
53 |
54 | * And build:
55 |
56 | xbuild /property:Configuration=ReleasePlgx KeeAgent.sln
57 |
58 | * The plgx file will be at `bin/ReleasePlgx/KeeAgent.plgx`.
59 |
--------------------------------------------------------------------------------
/KeeAgent/KeeAgentUiThread.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Windows.Forms;
4 |
5 | namespace KeeAgent
6 | {
7 | ///
8 | /// Provides a separate UI thread for interactive communication without interlocking with the MainWindow.
9 | ///
10 | public sealed class KeeAgentUiThread : IDisposable
11 | {
12 | private const string ComponentName = "KeeAgent Interactive UI";
13 | private SynchronizationContext _synchronizationContext;
14 |
15 | public KeeAgentUiThread()
16 | {
17 | var uiThread = new Thread(UiThreadMain) {
18 | Name = ComponentName,
19 | IsBackground = true // active background thread will not block the application shutdown process
20 | };
21 | uiThread.SetApartmentState(ApartmentState.STA);
22 | uiThread.Start();
23 | }
24 |
25 | private void UiThreadMain()
26 | {
27 | _synchronizationContext = new WindowsFormsSynchronizationContext();
28 | SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
29 | Application.Run();
30 | }
31 |
32 | ///
33 | /// Performs message loop shutdown.
34 | ///
35 | public void Dispose()
36 | {
37 | if (_synchronizationContext == null) {
38 | return;
39 | }
40 |
41 | var synchronizationContext = _synchronizationContext;
42 | _synchronizationContext = null;
43 | synchronizationContext.Post(_ => Application.ExitThread(), null);
44 | }
45 |
46 | ///
47 | /// Invokes a delegate on a separate UI Thread, dedicated for the KeeAgent Plugin
48 | ///
49 | /// The delegate to call.
50 | /// The method was called in while the SynchronizationContext is not
51 | /// captured yet or have been disposed already
52 | public void Invoke(Action action)
53 | {
54 | if (_synchronizationContext == null) {
55 | throw new InvalidOperationException(
56 | "KeeAgentInteractiveUi: the SynchronizationContext is not captured yet or have been disposed already");
57 | }
58 |
59 | _synchronizationContext.Send(_ => action.Invoke(), null);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/KeeAgent/UI/DatabaseSettingsPanel.cs:
--------------------------------------------------------------------------------
1 | //
2 | // DatabaseSettingsPanel.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2013-2014 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.Diagnostics;
24 | using System.Drawing;
25 | using System.Windows.Forms;
26 | using KeePassLib;
27 |
28 | namespace KeeAgent.UI
29 | {
30 | public partial class DatabaseSettingsPanel : UserControl
31 | {
32 |
33 | private PwDatabase mDatabase;
34 |
35 | public DatabaseSettingsPanel(PwDatabase aDatabase)
36 | {
37 | mDatabase = aDatabase;
38 |
39 | InitializeComponent();
40 |
41 | // make transparent so tab styling shows
42 | SetStyle(ControlStyles.SupportsTransparentBackColor, true);
43 | BackColor = Color.Transparent;
44 |
45 | mDatabaseSettingsBindingSource.DataSource = mDatabase.GetKeeAgentSettings();
46 | }
47 |
48 | protected override void OnLoad(EventArgs e)
49 | {
50 | base.OnLoad(e);
51 | if (ParentForm != null) {
52 | ParentForm.FormClosing += (s, e2) => {
53 | if (ParentForm.DialogResult == DialogResult.OK) {
54 | var settings = mDatabaseSettingsBindingSource.DataSource as DatabaseSettings;
55 | mDatabase.SetKeeAgentSettings(settings);
56 | }
57 | };
58 | }
59 | }
60 |
61 | private void mHelpButton_Click(object sender, EventArgs e)
62 | {
63 | Process.Start(Properties.Resources.WebHelpDatabaseSettings);
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/KeeAgent/UI/ManageKeyFileDialog.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System;
5 | using System.Linq;
6 | using System.Windows.Forms;
7 | using KeePassLib.Security;
8 |
9 | namespace KeeAgent.UI
10 | {
11 | ///
12 | /// Dialog box for managing SSH key file locations.
13 | ///
14 | public partial class ManageKeyFileDialog : Form
15 | {
16 | ///
17 | /// Creates a new key file dialog.
18 | ///
19 | public ManageKeyFileDialog()
20 | {
21 | InitializeComponent();
22 |
23 | if (Type.GetType("Mono.Runtime") == null) {
24 | Icon = Properties.Resources.KeeAgent_icon;
25 | }
26 | else {
27 | Icon = Properties.Resources.KeeAgent_icon_mono;
28 | }
29 |
30 | // Each key panel needs it's own binding context, otherwise
31 | // the two combo boxes will be magically linked because they
32 | // share the same data source.
33 | privateKeyLocationPanel.BindingContext = new BindingContext();
34 |
35 | var getAttachment = new Func(name => {
36 | if (Attachments == null) {
37 | return null;
38 | }
39 |
40 | return Attachments.FirstOrDefault(a => a.Key == name).Value;
41 | });
42 |
43 | privateKeyLocationPanel.KeyLocationChanged += (s, e) => {
44 | privateKeyLocationPanel.ErrorMessage = UI.Validate.Location(
45 | privateKeyLocationPanel.KeyLocation, getAttachment);
46 | };
47 | }
48 |
49 | ///
50 | /// Gets and sets the attachments data source.
51 | ///
52 | public AttachmentBindingList Attachments {
53 | get {
54 | return privateKeyLocationPanel.Attachments;
55 | }
56 | set {
57 | privateKeyLocationPanel.Attachments = value;
58 | }
59 | }
60 |
61 | ///
62 | /// Gets and sets the private key location data source.
63 | ///
64 | public EntrySettings.LocationData KeyLocation {
65 | get {
66 | return privateKeyLocationPanel.KeyLocation;
67 | }
68 | set {
69 | privateKeyLocationPanel.KeyLocation = value;
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "build",
8 | "type": "shell",
9 | "command": "${workspaceFolder}/scripts/msbuild.ps1",
10 | "args": [
11 | "/property:GenerateFullPaths=true",
12 | "/t:build",
13 | "KeeAgent.sln"
14 | ],
15 | "group": "build",
16 | "presentation": {
17 | "reveal": "silent"
18 | },
19 | "problemMatcher": "$msCompile"
20 | },
21 | {
22 | "label": "release",
23 | "type": "shell",
24 | "command": "${workspaceFolder}/scripts/msbuild.ps1",
25 | "args": [
26 | "/property:GenerateFullPaths=true",
27 | "/property:Configuration=ReleasePlgx",
28 | "/t:build",
29 | "KeeAgent.sln"
30 | ],
31 | "group": "build",
32 | "presentation": {
33 | "reveal": "silent"
34 | },
35 | "problemMatcher": "$msCompile"
36 | },
37 | {
38 | "label": "build-mono",
39 | "type": "shell",
40 | "command": "xbuild",
41 | "args": [
42 | "/property:GenerateFullPaths=true",
43 | "/t:build",
44 | "KeeAgent.sln"
45 | ],
46 | "group": "build",
47 | "presentation": {
48 | "reveal": "silent"
49 | },
50 | "problemMatcher": "$msCompile"
51 | },
52 | {
53 | "label": "release-mono",
54 | "type": "shell",
55 | "command": "xbuild",
56 | "args": [
57 | "/property:GenerateFullPaths=true",
58 | "/property:Configuration=ReleasePlgx",
59 | "/t:build",
60 | "KeeAgent.sln"
61 | ],
62 | "group": "build",
63 | "presentation": {
64 | "reveal": "silent"
65 | },
66 | "problemMatcher": "$msCompile"
67 | }
68 | ]
69 | }
70 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //
2 | // AssemblyInfo.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System.Reflection;
23 | using System.Runtime.CompilerServices;
24 | using System.Runtime.InteropServices;
25 |
26 | // General Information about an assembly is controlled through the following
27 | // set of attributes. Change these attribute values to modify the information
28 | // associated with an assembly.
29 | [assembly: AssemblyTitle("KeeAgentTestProject")]
30 | [assembly: AssemblyDescription("")]
31 | [assembly: AssemblyConfiguration("")]
32 | [assembly: AssemblyCompany("David Lechner")]
33 | [assembly: AssemblyProduct("KeeAgentTestProject")]
34 | [assembly: AssemblyCopyright("Copyright \u00A9 2012-2013")]
35 | [assembly: AssemblyTrademark("")]
36 | [assembly: AssemblyCulture("")]
37 |
38 | // Setting ComVisible to false makes the types in this assembly not visible
39 | // to COM components. If you need to access a type in this assembly from
40 | // COM, set the ComVisible attribute to true on that type.
41 | [assembly: ComVisible(false)]
42 |
43 | // The following GUID is for the ID of the typelib if this project is exposed to COM
44 | [assembly: Guid("dd62eb00-76ed-484d-a67e-1c32bf265ca8")]
45 |
46 | // Version information for an assembly consists of the following four values:
47 | //
48 | // Major Version
49 | // Minor Version
50 | // Build Number
51 | // Revision
52 | //
53 | // You can specify all the values or you can default the Build and Revision Numbers
54 | // by using the '*' as shown below:
55 | [assembly: AssemblyVersion("1.0.0.0")]
56 | [assembly: AssemblyFileVersion("1.0.0.0")]
57 |
--------------------------------------------------------------------------------
/KeeAgent/KeePass.config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 | true
7 |
8 |
9 |
10 |
11 |
12 | false
13 | false
14 | true
15 |
16 |
17 |
18 |
19 |
20 | Title
21 | 90
22 |
23 |
24 | PluginExt
25 | SSH Key Status
26 | 90
27 |
28 |
29 | UserName
30 | 90
31 |
32 |
33 | Password
34 | 90
35 | true
36 |
37 |
38 | Url
39 | 90
40 |
41 |
42 |
43 |
44 | false
45 |
46 |
47 | -
48 | KeeAgent.AlwaysConfirm
49 | false
50 |
51 | -
52 | KeeAgent.ShowBalloon
53 | true
54 |
55 | -
56 | KeeAgent.AgentMode
57 | Auto
58 |
59 | -
60 | KeeAgent.UnlockOnActivity
61 | true
62 |
63 | -
64 | KeeAgent.UseCygwinSocket
65 | false
66 |
67 | -
68 | KeeAgent.UseMsysSocket
69 | false
70 |
71 | -
72 | KeeAgent.UseWindowsOpenSshPipe
73 | false
74 |
75 | -
76 | KeeAgent.UnixSocketPath
77 |
78 |
79 | -
80 | KeeAgent.UserPicksKeyOnRequestIdentities
81 | false
82 |
83 | -
84 | KeeAgent.IgnoreMissingExternalKeyFilesName
85 | false
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/KeeAgent/UI/DecryptProgressDialog.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Windows.Forms;
4 |
5 | namespace KeeAgent.UI
6 | {
7 | public partial class DecryptProgressDialog : Form
8 | {
9 | private class BackgroundProgress : IProgress
10 | {
11 | private BackgroundWorker worker;
12 |
13 | public BackgroundProgress(BackgroundWorker worker)
14 | {
15 | this.worker = worker;
16 | }
17 |
18 | public void Report(double value)
19 | {
20 | var percent = (int)(100 * value);
21 | worker.ReportProgress(percent);
22 | }
23 | }
24 |
25 | public delegate object DecryptFunc(IProgress progress);
26 |
27 | public DecryptProgressDialog()
28 | {
29 | InitializeComponent();
30 | }
31 |
32 | public int Progress { get { return progressBar.Value; } }
33 |
34 | public Exception Error { get; private set; }
35 |
36 | public object Result { get; private set; }
37 |
38 | public void Start(DecryptFunc decrypt)
39 | {
40 | if (decrypt == null) {
41 | throw new ArgumentNullException("decrypt");
42 | }
43 |
44 | backgroundWorker.RunWorkerAsync(decrypt);
45 | }
46 |
47 | private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
48 | {
49 | var decrypt = (DecryptFunc)e.Argument;
50 | var progress = new BackgroundProgress(backgroundWorker);
51 | e.Result = decrypt(progress);
52 | }
53 |
54 | private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
55 | {
56 | progressBar.Style = ProgressBarStyle.Continuous;
57 | progressBar.Value = e.ProgressPercentage;
58 |
59 | // HACK: avoid lag due to animation
60 | // https://stackoverflow.com/q/6071626/1976323
61 | if (e.ProgressPercentage > 0) {
62 | progressBar.Value = e.ProgressPercentage - 1;
63 | progressBar.Value = e.ProgressPercentage;
64 | }
65 | }
66 |
67 | private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
68 | {
69 | if (e.Cancelled) {
70 | throw new NotSupportedException();
71 | }
72 |
73 | if (e.Error == null) {
74 | DialogResult = DialogResult.OK;
75 | }
76 | else {
77 | DialogResult = DialogResult.Abort;
78 | }
79 |
80 | Error = e.Error;
81 | Result = e.Result;
82 |
83 | Close();
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/KeeAgent/UI/PasswordDialog.cs:
--------------------------------------------------------------------------------
1 | //
2 | // PasswordDialog.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.Windows.Forms;
24 | using dlech.SshAgentLib;
25 |
26 | namespace KeeAgent.UI
27 | {
28 | public partial class PasswordDialog : Form
29 | {
30 | readonly SecureEdit secureEdit;
31 |
32 | public PasswordDialog()
33 | {
34 | InitializeComponent();
35 |
36 | if (Type.GetType("Mono.Runtime") == null) {
37 | Icon = Properties.Resources.KeeAgent_icon;
38 | }
39 | else {
40 | Icon = Properties.Resources.KeeAgent_icon_mono;
41 | }
42 |
43 | secureEdit = new SecureEdit();
44 | secureEdit.Attach(passwordTextBox, null, true);
45 | }
46 |
47 | public PasswordDialog(string message) : this()
48 | {
49 | SetMessage(message);
50 | }
51 |
52 | public void SetMessage(string message)
53 | {
54 | messageLabel.Text = message;
55 | }
56 |
57 | public byte[] GetPassword()
58 | {
59 | return secureEdit.ToUtf8();
60 | }
61 |
62 | ///
63 | /// Clean up any resources being used.
64 | ///
65 | ///
66 | /// true if managed resources should be disposed; otherwise, false.
67 | ///
68 | protected override void Dispose(bool disposing)
69 | {
70 | secureEdit.Detach();
71 | if (disposing && (components != null)) {
72 | components.Dispose();
73 | }
74 | base.Dispose(disposing);
75 | }
76 |
77 | private void okButton_Click(object sender, EventArgs e)
78 | {
79 | DialogResult = DialogResult.OK;
80 | Close();
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/KeeAgent/UI/UIHelper.cs:
--------------------------------------------------------------------------------
1 | //
2 | // UIHelper.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System.Windows.Forms;
23 | using KeePass.Plugins;
24 |
25 | namespace KeeAgent.UI
26 | {
27 | public class UIHelper
28 | {
29 | private IPluginHost mPluginHost;
30 |
31 | public UIHelper(IPluginHost pluginHost)
32 | {
33 | this.mPluginHost = pluginHost;
34 | }
35 |
36 | ///
37 | /// Shows message using the preferred notification method.
38 | /// Currently, this is only via the notification icon.
39 | ///
40 | /// The message to display
41 | public void ShowBalloonNotification(string aMessage)
42 | {
43 | MethodInvoker invoker = delegate () {
44 | if (mPluginHost.MainWindow.MainNotifyIcon != null) {
45 | mPluginHost.MainWindow.MainNotifyIcon.ShowBalloonTip(
46 | 5000, Translatable.KeeAgent,
47 | aMessage, ToolTipIcon.Info);
48 | }
49 | };
50 | InvokeMainWindow(invoker, true);
51 | }
52 |
53 | ///
54 | /// Invokes a method on the main window thread
55 | ///
56 | /// the method to invoke
57 | /// set to true to invoke asynchronously
58 | private void InvokeMainWindow(MethodInvoker aInvoker, bool aAsync)
59 | {
60 | if (this.mPluginHost.MainWindow.InvokeRequired) {
61 | if (aAsync) {
62 | mPluginHost.MainWindow.BeginInvoke(aInvoker);
63 | }
64 | else {
65 | mPluginHost.MainWindow.Invoke(aInvoker);
66 | }
67 | }
68 | else {
69 | aInvoker.Invoke();
70 | }
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/doc/usage/quick-start.rst:
--------------------------------------------------------------------------------
1 | ===========
2 | Quick Start
3 | ===========
4 |
5 | This is a quick walk-through of the basics using KeeAgent.
6 |
7 | 1. Add a new entry to your database (**Edit > Add Entry**...).
8 |
9 | 2. On the **Entry** tab, give the entry a title.
10 |
11 | 3. Enter the passphrase for the SSH key you are going to use in the **Password**
12 | field. The plugin needs this to decrypt the file. Leave the **Password**
13 | field blank if the key is not encrypted.
14 |
15 | .. figure:: images/win10-keepass-add-entry-entry-tab.png
16 | :alt: screenshot of the KeePass Add Entry dialog on the Entry tab
17 |
18 | .. tip:: The remaining fields in the **Entry**, such as **User name** and
19 | **URL**, are not used by KeeAgent and can be left blank or used for
20 | anything you want.
21 |
22 | .. todo:: Add new tip about use of URL field by KeeAgent.
23 |
24 | 4. On the **Advanced** tab, attach your private key file using the **Attach**
25 | button. Select the key using the file dialog. This can be a PuTTY private key
26 | file (.ppk) or an OpenSSH private key file. After you have selected key and
27 | clicked **OK**, the file will appear in the list of attachments.
28 |
29 | .. figure:: images/win10-keepass-add-entry-advanced-tab.png
30 | :alt: screenshot of the KeePass Add Entry dialog on the Advanced tab
31 |
32 | 5. On the **KeeAgent** tab, check the box that says **Allow KeeAgent to use this
33 | entry**.
34 |
35 | 6. In the Location group, the file that you just attached should be
36 | automatically selected as the **Attachment**. Verify that this happened.
37 | If you have more than one attachment, you may have to select the correct
38 | file.
39 |
40 | .. figure:: images/win10-keepass-add-entry-keeagent-tab.png
41 | :alt: screenshot of the KeePass Add Entry dialog on the KeeAgent tab
42 |
43 | 7. Click **OK** to save the entry and close the **Edit Entry** dialog.
44 |
45 | 8. Right-click on the new entry and select **Load SSH Key**. The key is now
46 | loaded into the agent and can be used by client programs such as PuTTY.
47 |
48 | .. figure:: images/win10-keepass-context-menu-load-ssh-key.png
49 | :alt: Screenshot of KeePass with the context menu open showing "Load SSH
50 | Key" selected.
51 |
52 | 9. Click on **Tools > KeeAgent**. This displays a list of currently loaded keys
53 | and allows you to add or remove keys.
54 |
55 | .. figure:: images/win10-keepass-keeagent-dialog.png
56 | :alt: Screenshot of the KeeAgent manager dialog window
57 |
--------------------------------------------------------------------------------
/KeeAgent/UI/TreeViewEx.cs:
--------------------------------------------------------------------------------
1 | //
2 | // TreeViewEx.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System.Drawing;
23 | using System.Windows.Forms;
24 |
25 | namespace KeeAgent.UI
26 | {
27 | ///
28 | /// nodes can be disabled by setting ForeColor to SystemColors.GrayText
29 | ///
30 | public class TreeViewEx : TreeView
31 | {
32 | // used to prevent clicking on disabled nodes
33 | protected override void WndProc(ref Message m)
34 | {
35 | const int WM_LBUTTONDOWN = 0x0201;
36 | const int WM_LBUTTONUP = 0x0202;
37 | const int WM_LBUTTONDBLCLK = 0x0203;
38 | const int WM_RBUTTONDOWN = 0x0204;
39 | const int WM_RBUTTONUP = 0x0205;
40 | const int WM_RBUTTONDBLCLK = 0x0206;
41 |
42 |
43 | if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_LBUTTONUP ||
44 | m.Msg == WM_LBUTTONDBLCLK || m.Msg == WM_RBUTTONDOWN ||
45 | m.Msg == WM_RBUTTONUP || m.Msg == WM_RBUTTONDBLCLK) {
46 |
47 | var posData = m.LParam.ToInt32();
48 | var xPos = posData & 0xFF;
49 | var yPos = posData >> 16;
50 |
51 | var pos = new Point(xPos, yPos);
52 | var node = GetNodeAt(pos);
53 | if (node != null) {
54 | var bounds = node.Bounds;
55 | bounds.X -= 19;
56 | bounds.Width += 20;
57 | if (bounds.Contains(pos) && node.ForeColor == SystemColors.GrayText) {
58 | return;
59 | }
60 | }
61 | }
62 | base.WndProc(ref m);
63 | }
64 |
65 | // cancel selection just in case we get selected somehow
66 | protected override void OnBeforeSelect(TreeViewCancelEventArgs e)
67 | {
68 | base.OnBeforeSelect(e);
69 | if (e.Node.ForeColor == SystemColors.GrayText) {
70 | e.Cancel = true;
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": "Debug .dll",
9 | "type": "clr",
10 | "request": "launch",
11 | "program": "${workspaceRoot}/KeeAgent/bin/Debug/KeePass.exe",
12 | "cwd": "${workspaceRoot}",
13 | "args": [
14 | "--pw=test",
15 | "${workspaceRoot}/KeeAgent/bin/Debug/Test.kdbx"
16 | ],
17 | "preLaunchTask": "build"
18 | },
19 | {
20 | "name": "Debug .plgx",
21 | "type": "clr",
22 | "request": "launch",
23 | "program": "${workspaceRoot}/KeeAgent/bin/ReleasePlgx/KeePass.exe",
24 | "cwd": "${workspaceRoot}",
25 | "args": [
26 | "--pw=test",
27 | "${workspaceRoot}/KeeAgent/bin/ReleasePlgx/Test.kdbx"
28 | ],
29 | "preLaunchTask": "release"
30 | },
31 | {
32 | "name": "Mono: Debug .dll",
33 | "type": "mono",
34 | "request": "launch",
35 | "program": "${workspaceRoot}/KeeAgent/bin/Debug/KeePass.exe",
36 | "cwd": "${workspaceRoot}",
37 | "args": [
38 | "--pw=test",
39 | "${workspaceRoot}/KeeAgent/bin/Debug/Test.kdbx"
40 | ],
41 | "preLaunchTask": "build-mono"
42 | },
43 | {
44 | "name": "Mono: Debug .dll - Agent mode",
45 | "type": "mono",
46 | "request": "launch",
47 | "program": "${workspaceRoot}/KeeAgent/bin/Debug/KeePass.exe",
48 | "cwd": "${workspaceRoot}",
49 | "env": { "SSH_AUTH_SOCK": null },
50 | "args": [
51 | "--pw=test",
52 | "${workspaceRoot}/KeeAgent/bin/Debug/Test.kdbx"
53 | ],
54 | "preLaunchTask": "build-mono"
55 | },
56 | {
57 | "name": "Mono: Debug .plgx",
58 | "type": "mono",
59 | "request": "launch",
60 | "program": "${workspaceRoot}/KeeAgent/bin/ReleasePlgx/KeePass.exe",
61 | "cwd": "${workspaceRoot}",
62 | "args": [
63 | "--pw=test",
64 | "${workspaceRoot}/KeeAgent/bin/ReleasePlgx/Test.kdbx"
65 | ],
66 | "preLaunchTask": "release-mono"
67 | }
68 | ]
69 | }
70 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Resources/4095-bits.ppk:
--------------------------------------------------------------------------------
1 | PuTTY-User-Key-File-2: ssh-rsa
2 | Encryption: aes256-cbc
3 | Comment: rsa-key-20120523
4 | Public-Lines: 12
5 | AAAAB3NzaC1yc2EAAAABJQAAAgB4UTbZk7x8cZbGi17+bXaEqp4b4GL0rHUtV4Zh
6 | NuwQcqP87glOzkNJ4W/ifr3P3VE4TMtB8lPdUy89ahHm+4eIK8C7MCFAgJJbz4ah
7 | GwccLyP1pM9u7SbAfKBeG+e56PXBxWfV+HvRAd+9dt3swicvkjVM840krcEmKwKI
8 | hdnvLj9vKNZLJ0Al5a1CTcABuHOCP+5//9UhoytBvRBpNEuGbis91US50f1OQHe0
9 | 7rl/Iu57tPRObOi82ItNzvOzec49LRifTg/vT3yNlnGfaeapPtNGLgVaPcPS7yrE
10 | 1DjsZoQ1T8Dpw3MVIaL8QCjihEo63oTZnmaXKU+UFiCfp8QmukzteXBAqutZFDlQ
11 | MDQjGWi3YgZV8miz4k3+LKUNH4iYlTMKirz804ww0Uj9819YRgNU8G7FjlPSHoDD
12 | Uc6KE0fGsmJ1hXfgQYQKwsJQjvNTOgbN/DLHfeaZroko14O306KGx74Eoqk5WV3B
13 | g1AHtEGwSojXmHVDiw4DRM7hQB30KrMFBurIPdzR7MgO9Db9OK8df3zixMLPjwCu
14 | E5ocdGJqqKz0lV3oeaSjEgU423RE/xNZpxxTohM49h7U9DEN3cZ4+/B3U8BEc/Hk
15 | /hyE/a3wtutZGWhslqhtp7bI+gygBoNnnFqa1pMGY6/xkLDr+HDgIVKWLwEtUImy
16 | qojEqQ==
17 | Private-Lines: 28
18 | lZZiGDyhbYjVa9/42LaG/u0UJEosYOFA0/YRrTJ6tHT8YyzR54CFOEQA9Qnh8eKt
19 | YNnqaK8KE8dgXQlrf2yrOpeHSfg11VbRh/SmNpVusp3jIMgGljFH4jRSaXlZM1Fs
20 | 3gWyqw8HnibGytFtO++eaMNeRoFs6V2dgy+Pgv6x6oT5Bf7YUC5MIgRFXEpFR9Ic
21 | 4g/Bw8kpUhCqkfJHVgoISsDE5tqvrGKVvn5jCbOHSfRvnXaDcgEOYk7MurfZQ/p4
22 | r+ZDqfPDvVVue3BOVvKSXF57gCrNP36wFYj4/5QJBvhaaQIiSuH6yAn7Te1gdBjy
23 | OcCn8bfSv37vVqs+eXTxa0dkQwTmuTpYdYBdpu1PD4fo2eTU4l1xyrrnfReQJlmO
24 | FY1IEHq+PdmpLufdOXfK+yRmrbjAQeMSCBFfJag6v85dnwi2uRIkyNZQ/ZiWKZEb
25 | UoYbX8NL666+Wf9G8sF0sTpwqWYpO/NEtlv2BszlKnk7VWzaotIgzilehV0O8hlg
26 | 0y0+Vl1laDVhKkkPsSAnFKJywCGDKxejulpAjDz+JjvlKH3BpjTciUZgPfDnD6Lg
27 | krTfaZBqaVtA5FDfhinvzia4rsksajV2uy4Qn9rqwhXzopMpS7TPJdkQAcm2pijV
28 | uvUZ8tvEbnBtQsw/xUp+lrgt7gtZ1pelfD92xxYryBviewiQi8tqOAmh2n+jN+/V
29 | idNQOcp68Xa6vOzbnnXjlIV0qXmaDrYHwRkFet/yITiUd6IhqiCRginmiWTv6DdQ
30 | wLjrvouDBYP+KfdlxsM/Hu0hM8heAqntWOWmL2TxP+mHX6BhSUsisJaeP12SlLIf
31 | 1IK+KdDP13XZFg1QGa2FX4oWTCFxJJFthqf37/GSYVbHI9j63o2HxCJc/A6aiJ0r
32 | sKHFL25S9omTiUfS7PqBMk63vUO3tShNWdD1j0fNGoiAiHTk15/u9KVKwGnkGZhD
33 | tRDou+wEHAGXZRqZCteRuOuDZfP6h8qoxCW3WiCrFE+k+mn8TYTVUuUsoFXu/pdC
34 | qSfjPJAEVqT4HnyKqUcPx01AN8YUBHe/JPHTHZOvHGw9bECNm9xOpP0RxDLghFOh
35 | ma0BESjCabqfr7OVRCm7NTAfLuNVriNjawq9Hb6ayUal2iho/GeaVKeUy/Ambp6M
36 | ijr/vUQFFAiTI8nO8p8qND8m3wKxFaYEM6qRJpj4mhSqmb8x8ltAGcDEPTNaTbLx
37 | Riq55TwynepFBj8FwIT725VCSdyR7O/5Jra+7rtrxRmuG6W/oPm9tTvRKWcq8ei4
38 | MlceHGc+/UMK+NoFpV3dJhuybpOyfPl58HsutOyDwDUJLf0b5ebAMCdZNCSktbZo
39 | rooi61KRqwMnTCxib9FCw4wqBMsDio2DXH4Q2MU46w01L0aKsdjZq3twWxNIYN4W
40 | 0PrpZPqNXXNE+807pAzOOV2AlhacjtNSeB8Vmp/jmpP8rnDxpU+/NunsYOdzVP4J
41 | dQyJHGfE96n8JnjIH0L5/mDYr0C86r84TN71WQB6e8hPpiRVE1OaG5AfXikf9JTb
42 | CveEG9ZNhNZI9eQGnTTjE9pJLsjUTWJCBw93aCjlZEDijNEKZlFpOS6hhYd6YZ00
43 | UqazKqVQ7KQrwJB+YEuY4aG5ArQhj93xphVF16ttTwvRSDjSUBy5Oyx2qcM8Cmck
44 | GQVfGBvwFzMCUYyuNv+y3GwjYhKJ+pzFMJASfAK9SVYqWNRjzuFBsfNnZkZ3G+za
45 | 9FCv0WFBZs1MkKWWETk8gA==
46 | Private-MAC: 5d0ef7ed9eebc515454c344d79ddeb8ab365b3f8
47 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/KeeAgentExtInitTest.cs:
--------------------------------------------------------------------------------
1 | //
2 | // KeeAgentExtInitTest.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.Windows.Forms;
24 | using KeeAgent;
25 | using KeePass.Plugins;
26 | using KeePassPluginDevTools.Control;
27 | using NUnit.Framework;
28 |
29 | namespace KeeAgentTestProject
30 | {
31 | ///
32 | ///This is a test class for KeeAgentExtTest and is intended
33 | ///to contain all KeeAgentExtTest Unit Tests
34 | ///
35 | [TestFixture()]
36 | public class KeeAgentExtInitTest
37 | {
38 |
39 | //Use ClassCleanup to run code after all tests in a class have run
40 | [TestFixtureTearDown()]
41 | public static void Cleanup()
42 | {
43 | KeePassControl.ExitAll();
44 | }
45 |
46 | ///
47 | ///A test for Initialize and Terminate
48 | ///
49 | [Test()]
50 | public void InitializeTest()
51 | {
52 | const string initalizeResultName = "KEEAGENT_INIT_RESULT";
53 |
54 | using (KeePassAppDomain testDomain1 = new KeePassAppDomain()) {
55 | testDomain1.StartKeePass(true, true, 1, true);
56 | testDomain1.DoCallBack(delegate()
57 | {
58 | IPluginHost td1PluginHost = KeePass.Program.MainForm.PluginHost;
59 | try {
60 | KeeAgentExt td1KeeAgentExt = new KeeAgentExt();
61 | KeePass.Program.MainForm.Invoke((MethodInvoker)delegate()
62 | {
63 | bool td1InitalizeResult = td1KeeAgentExt.Initialize(td1PluginHost);
64 | td1KeeAgentExt.Terminate();
65 | AppDomain.CurrentDomain.SetData(initalizeResultName,
66 | td1InitalizeResult);
67 | });
68 | } catch (Exception) {
69 | // TODO do we want to pass this exception back to test?
70 | }
71 | });
72 |
73 | bool expected = true;
74 | bool actual = (bool)testDomain1.GetData(initalizeResultName);
75 | Assert.AreEqual(expected, actual);
76 | }
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/KeeAgent/UI/PasswordDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KeeAgent.UI
2 | {
3 | partial class PasswordDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 |
11 | #region Windows Form Designer generated code
12 |
13 | ///
14 | /// Required method for Designer support - do not modify
15 | /// the contents of this method with the code editor.
16 | ///
17 | private void InitializeComponent()
18 | {
19 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(PasswordDialog));
20 | this.passwordTextBox = new System.Windows.Forms.TextBox();
21 | this.messageLabel = new System.Windows.Forms.Label();
22 | this.okButton = new System.Windows.Forms.Button();
23 | this.cancelButton = new System.Windows.Forms.Button();
24 | this.SuspendLayout();
25 | //
26 | // passwordTextBox
27 | //
28 | resources.ApplyResources(this.passwordTextBox, "passwordTextBox");
29 | this.passwordTextBox.Name = "passwordTextBox";
30 | //
31 | // messageLabel
32 | //
33 | resources.ApplyResources(this.messageLabel, "messageLabel");
34 | this.messageLabel.Name = "messageLabel";
35 | //
36 | // okButton
37 | //
38 | resources.ApplyResources(this.okButton, "okButton");
39 | this.okButton.Name = "okButton";
40 | this.okButton.UseVisualStyleBackColor = true;
41 | //
42 | // cancelButton
43 | //
44 | resources.ApplyResources(this.cancelButton, "cancelButton");
45 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
46 | this.cancelButton.Name = "cancelButton";
47 | this.cancelButton.UseVisualStyleBackColor = true;
48 | //
49 | // PasswordDialog
50 | //
51 | this.AcceptButton = this.okButton;
52 | resources.ApplyResources(this, "$this");
53 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
54 | this.CancelButton = this.cancelButton;
55 | this.ControlBox = false;
56 | this.Controls.Add(this.cancelButton);
57 | this.Controls.Add(this.okButton);
58 | this.Controls.Add(this.messageLabel);
59 | this.Controls.Add(this.passwordTextBox);
60 | this.MaximizeBox = false;
61 | this.MinimizeBox = false;
62 | this.Name = "PasswordDialog";
63 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
64 | this.ResumeLayout(false);
65 | this.PerformLayout();
66 |
67 | }
68 |
69 | #endregion
70 |
71 | private System.Windows.Forms.TextBox passwordTextBox;
72 | private System.Windows.Forms.Label messageLabel;
73 | private System.Windows.Forms.Button okButton;
74 | private System.Windows.Forms.Button cancelButton;
75 | }
76 | }
--------------------------------------------------------------------------------
/doc/installation.rst:
--------------------------------------------------------------------------------
1 | ============
2 | Installation
3 | ============
4 |
5 | KeeAgent, like any other KeePass 2.x plugin, is installed by copying the ``.plgx``
6 | file to the ``Plugins`` folder of the KeePass 2.x installation. The location
7 | of this folder depends on how you installed KeePass 2.x (e.g. using an installer
8 | or using the portable version).
9 |
10 |
11 | Windows
12 | =======
13 |
14 | .. tip:: Users of the Chocolatey package manager may find a `KeeAgent package`__
15 | there (maintained by a 3rd party).
16 |
17 | .. __: https://chocolatey.org/packages/keepass-plugin-keeagent
18 |
19 |
20 | 1. Download KeeAgent from https://lechnology.com/software/keeagent
21 |
22 | 2. Open the zip file
23 |
24 | .. figure:: images/win10-keeagent-zip-contents.png
25 | :alt: screenshot of Windows Explorer showing the contents of the
26 | downloaded KeeAgent zip file
27 |
28 | 3. In another Explorer window, open the KeePass 2.x Plugins folder.
29 |
30 | .. figure:: images/win10-keepass2-plugins-folder.png
31 | :alt: screenshot of Windows Explorer showing KeePass 2.x Plugins directory
32 |
33 | .. note:: If you used the Windows installer to install KeePass, then the folder
34 | will be ``C:\Program Files\KeePass Password Safe 2\Plugins`` (or
35 | ``Program Files (x86)`` for older versions of KeePass).
36 |
37 | If you are using the portable version of KeePass 2.x, then hopefully
38 | you remember where you installed it.
39 |
40 | 4. Drag and drop the ``KeeAgent.plgx`` file from the zip file to the KeePass 2.x
41 | Plugins folder, replacing the existing file if you have previously installed
42 | KeeAgent.
43 |
44 | .. figure:: images/win10-keepass2-plugins-folder-drag-and-drop.png
45 | :alt: screenshot of Windows Explorer showing dropping a file into the
46 | KeePass 2.x Plugins directory
47 |
48 |
49 | Linux
50 | =====
51 |
52 | Packaging for Linux distributions is maintained by 3rd parties.
53 |
54 | Arch
55 | ----
56 |
57 | There are several 3rd party AUR packages for KeeAgent.
58 |
59 | And, you may find something about `KeeAgent on the Arch Wiki`__.
60 |
61 | .. __: https://wiki.archlinux.org/index.php/SSH_keys#KeePass2_with_KeeAgent_plugin
62 |
63 |
64 | Everyone Else
65 | -------------
66 |
67 | This assumes that you already have KeePass 2.x (and therefore Mono) already
68 | successfully installed. If you have not already, install the ``mono-complete``
69 | package from your distro. Then extract ``KeeAgent.plgx`` from the zip file
70 | and copy it to the ``Plugins`` folder where ``KeePass.exe`` is located. This
71 | is usually at ``/usr/lib/keepass2/Plugins/`` unless you are using the portable
72 | version of KeePass 2.x, in which case, hopefully you remember where you
73 | installed it.
74 |
75 |
76 | macOS
77 | =====
78 |
79 | On macOS, it is assumed that you are using the portable version of KeePass 2.x.
80 |
81 | * Open the folder that contains ``KeePass.exe``.
82 | * Drag and drop ``KeeAgent.plgx`` into the ``Plugins`` subdirectory.
83 | * Restart KeePass if it was already running.
84 |
--------------------------------------------------------------------------------
/KeeAgent/UI/SystemIcon.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System;
5 | using System.ComponentModel;
6 | using System.Drawing;
7 | using System.Runtime.InteropServices;
8 | using System.Windows.Forms;
9 |
10 | namespace KeeAgent.UI
11 | {
12 | ///
13 | /// A control that gets a properly scaled system icon.
14 | ///
15 | public class SystemIcon : PictureBox
16 | {
17 | [DllImport("Comctl32.dll")]
18 | private static extern int LoadIconWithScaleDown(
19 | IntPtr hinstance,
20 | IntPtr pszName,
21 | int cx,
22 | int cy,
23 | out IntPtr phico);
24 |
25 | [DllImport("User32.dll")]
26 | private static extern bool DestroyIcon(IntPtr hIcon);
27 |
28 | public enum StockIconId : uint
29 | {
30 | Info = 32516, // IDI_INFORMATION
31 | Warning = 32515, // IDI_WARNING
32 | Error = 32513, // IDI_ERROR,
33 | Help = 32514, // IDI_QUESTION
34 | }
35 |
36 | ///
37 | /// Creates a new system icon.
38 | ///
39 | public SystemIcon()
40 | {
41 | BackColor = Color.Transparent;
42 | SizeMode = PictureBoxSizeMode.CenterImage;
43 |
44 | stockIconId = StockIconId.Info;
45 | SizeChanged += (s, e) => UpdateImage();
46 | UpdateImage();
47 | }
48 |
49 | private StockIconId stockIconId;
50 |
51 | ///
52 | /// Gets and sets the stock icon type.
53 | ///
54 | [Category("Appearance"), DefaultValue(StockIconId.Info)]
55 | public StockIconId StockIcon {
56 | get {
57 | return stockIconId;
58 | }
59 | set {
60 | stockIconId = value;
61 | UpdateImage();
62 | }
63 | }
64 |
65 | private void UpdateImage()
66 | {
67 | // Use ugly icons on mono - it's the best we can do
68 | if (Type.GetType("Mono.Runtime") != null) {
69 | Icon icon;
70 |
71 | switch (stockIconId) {
72 | case StockIconId.Info:
73 | icon = SystemIcons.Information;
74 | break;
75 | case StockIconId.Warning:
76 | icon = SystemIcons.Warning;
77 | break;
78 | case StockIconId.Error:
79 | icon = SystemIcons.Error;
80 | break;
81 | case StockIconId.Help:
82 | icon = SystemIcons.Question;
83 | break;
84 | default:
85 | throw new NotSupportedException("unsupported icon id");
86 | }
87 |
88 | Image = new Icon(icon, Size.Width, Size.Height).ToBitmap();
89 |
90 | return;
91 | }
92 |
93 | IntPtr handle;
94 |
95 | Marshal.ThrowExceptionForHR(
96 | LoadIconWithScaleDown(IntPtr.Zero, (IntPtr)stockIconId, Size.Width, Size.Height, out handle));
97 |
98 | try {
99 | Image = Icon.FromHandle(handle).ToBitmap();
100 | }
101 | finally {
102 | DestroyIcon(handle);
103 | }
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/KeeAgent/UI/InPlaceMessage.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KeeAgent.UI
2 | {
3 | partial class InPlaceMessage
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null)) {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Component Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InPlaceMessage));
31 | this.systemIcon1 = new KeeAgent.UI.SystemIcon();
32 | this.label1 = new System.Windows.Forms.Label();
33 | ((System.ComponentModel.ISupportInitialize)(this.systemIcon1)).BeginInit();
34 | this.SuspendLayout();
35 | //
36 | // systemIcon1
37 | //
38 | this.systemIcon1.BackColor = System.Drawing.Color.Transparent;
39 | this.systemIcon1.Image = ((System.Drawing.Image)(resources.GetObject("systemIcon1.Image")));
40 | this.systemIcon1.Location = new System.Drawing.Point(3, 3);
41 | this.systemIcon1.Name = "systemIcon1";
42 | this.systemIcon1.Size = new System.Drawing.Size(16, 16);
43 | this.systemIcon1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
44 | this.systemIcon1.TabIndex = 0;
45 | this.systemIcon1.TabStop = false;
46 | //
47 | // label1
48 | //
49 | this.label1.AutoSize = true;
50 | this.label1.Location = new System.Drawing.Point(25, 4);
51 | this.label1.Name = "label1";
52 | this.label1.Size = new System.Drawing.Size(61, 13);
53 | this.label1.TabIndex = 1;
54 | this.label1.Text = "";
55 | //
56 | // InPlaceMessage
57 | //
58 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
59 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
60 | this.BackColor = System.Drawing.Color.Transparent;
61 | this.Controls.Add(this.label1);
62 | this.Controls.Add(this.systemIcon1);
63 | this.Name = "InPlaceMessage";
64 | this.Size = new System.Drawing.Size(406, 26);
65 | ((System.ComponentModel.ISupportInitialize)(this.systemIcon1)).EndInit();
66 | this.ResumeLayout(false);
67 | this.PerformLayout();
68 |
69 | }
70 |
71 | #endregion
72 |
73 | private SystemIcon systemIcon1;
74 | private System.Windows.Forms.Label label1;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/doc/integrations/menu-items.rst:
--------------------------------------------------------------------------------
1 | ==========
2 | Menu Items
3 | ==========
4 |
5 | KeeAgent adds several menu items to KeePass.
6 |
7 |
8 | Main / Application Menu
9 | =======================
10 |
11 | This is the KeePass application menu.
12 |
13 | .. figure:: images/win10-keepass-application-menu.png
14 | :alt: KeePass - Application Menu
15 |
16 |
17 | Group Menu
18 | ----------
19 |
20 | The *Group Menu* is accessed by clicking on *Group* in the main application menu
21 | or by right-clicking on an group in the group navigation pane on the left side
22 | of the main window in KeePass.
23 |
24 | .. figure:: images/win10-keepass-group-menu.png
25 | :alt: Screenshot of KeePass main window group menu on Windows 10
26 |
27 | .. figure:: images/win10-keepass-group-context-menu.png
28 | :alt: Screenshot of KeePass main window group context menu on Windows 10
29 |
30 | **Load SSH Keys** (Ctrl+M)
31 | Loads keys from the selected group in to the agent.
32 |
33 | .. note:: This menu item is only visible if the selected group contains any
34 | SSH keys.
35 |
36 |
37 | Entry Menu
38 | ----------
39 |
40 | The *Entry Menu* is accessed by clicking *Entry* in the main application menu
41 | or by right-clicking on an entry in the entry list.
42 |
43 | .. figure:: images/win10-keepass-entry-menu-expanded.png
44 | :alt: Screenshot of KeePass main window entry menu on Windows 10
45 |
46 | .. figure:: images/win10-keepass-context-menu-expanded.png
47 | :alt: Screenshot of KeePass main window entry context menu on Windows 10
48 |
49 | **Load SSH Key** (Ctrl+M)
50 | Loads key from the selected entry in to the agent.
51 |
52 | .. note:: This menu item is only visible if the selected entry has the *Allow
53 | KeeAgent to use this entry* option checked.
54 |
55 | .. warning:: If the key is already loaded in the agent, it will be replaced.
56 | This could potentially change any constraints the key has.
57 |
58 | **URL(s) > Load SSH Key and Open URL** (Ctrl+Shift+M)
59 | Loads key from the selected entry in to the agent and then opens the URL
60 | for the entry.
61 |
62 | This item is basically a shortcut for the combination of the *Load SSH Key*
63 | and *URL(s) > Open* menu items.
64 |
65 |
66 | Tools Menu
67 | ----------
68 |
69 | KeeAgent adds one item to the Tools menu.
70 |
71 | .. figure:: images/win10-keepass-tools-menu.png
72 | :alt: KeePass - Tools menu - KeeAgent
73 |
74 | KeeAgent
75 | Opens the KeeAgent Manager dialog.
76 |
77 | .. todo:: Add link to page on KeeAgent manager.
78 |
79 |
80 | Help Menu
81 | ---------
82 |
83 | KeeAgent adds one item to the Help menu.
84 |
85 | .. figure:: images/win10-keepass-help-menu.png
86 | :alt: KeePass - Help menu - KeeAgent
87 |
88 | KeeAgent
89 | Opens the KeeAgent documentation in a web browser.
90 |
91 |
92 | Notification Tray Icon Menu
93 | ===========================
94 |
95 | .. figure:: images/win10-keepass-notification-tray-menu.png
96 | :alt: KeePass - Tray Icon Menu - KeeAgent
97 |
98 | KeeAgent
99 | Opens the KeeAgent Manager dialog. (Same as *Tools > KeeAgent* in the application menu.)
100 |
101 | .. tip:: If you are missing this icon on your Linux desktop, check out `this
102 | plugin`__.
103 |
104 | .. __: https://github.com/dlech/Keebuntu
105 |
--------------------------------------------------------------------------------
/KeeAgent/UI/DecryptProgressDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KeeAgent.UI
2 | {
3 | partial class DecryptProgressDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null)) {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Windows Form Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | this.progressBar = new System.Windows.Forms.ProgressBar();
31 | this.backgroundWorker = new System.ComponentModel.BackgroundWorker();
32 | this.SuspendLayout();
33 | //
34 | // progressBar
35 | //
36 | this.progressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
37 | | System.Windows.Forms.AnchorStyles.Right)));
38 | this.progressBar.Location = new System.Drawing.Point(12, 12);
39 | this.progressBar.MarqueeAnimationSpeed = 10;
40 | this.progressBar.Name = "progressBar";
41 | this.progressBar.Size = new System.Drawing.Size(231, 23);
42 | this.progressBar.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
43 | this.progressBar.TabIndex = 0;
44 | //
45 | // backgroundWorker
46 | //
47 | this.backgroundWorker.WorkerReportsProgress = true;
48 | this.backgroundWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this.backgroundWorker_DoWork);
49 | this.backgroundWorker.ProgressChanged += new System.ComponentModel.ProgressChangedEventHandler(this.backgroundWorker_ProgressChanged);
50 | this.backgroundWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this.backgroundWorker_RunWorkerCompleted);
51 | //
52 | // DecryptProgressDialog
53 | //
54 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
55 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
56 | this.AutoSize = true;
57 | this.ClientSize = new System.Drawing.Size(255, 49);
58 | this.ControlBox = false;
59 | this.Controls.Add(this.progressBar);
60 | this.MaximizeBox = false;
61 | this.MinimizeBox = false;
62 | this.Name = "DecryptProgressDialog";
63 | this.ShowInTaskbar = false;
64 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
65 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
66 | this.Text = "Decrypting SSH Private Key";
67 | this.ResumeLayout(false);
68 |
69 | }
70 |
71 | #endregion
72 |
73 | private System.Windows.Forms.ProgressBar progressBar;
74 | private System.ComponentModel.BackgroundWorker backgroundWorker;
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/KeeAgent/UI/GroupBoxEx.cs:
--------------------------------------------------------------------------------
1 | //
2 | // GroupBoxEx.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.ComponentModel;
24 | using System.Windows.Forms;
25 |
26 | namespace KeeAgent.UI
27 | {
28 | public class GroupBoxEx : GroupBox
29 | {
30 | private string pSelectedRadioButton = string.Empty;
31 |
32 | public event EventHandler SelectedRadioButtonChanged;
33 |
34 | ///
35 | ///
36 | ///
37 | [Category("Appearance")]
38 | public string SelectedRadioButton {
39 | get {
40 | return pSelectedRadioButton;
41 | }
42 | set {
43 | if (value == null) {
44 | value = string.Empty;
45 | }
46 | if (value == pSelectedRadioButton) {
47 | return;
48 | }
49 | if (value == string.Empty) {
50 | foreach (var control in Controls) {
51 | var radioButton = Controls[value] as RadioButton;
52 | if (radioButton != null) {
53 | radioButton.Checked = false;
54 | }
55 | }
56 | }
57 | else {
58 | var selectedRadioButton = Controls[value] as RadioButton;
59 | if (selectedRadioButton == null) {
60 | throw new ArgumentException("unknown radio button");
61 | }
62 | selectedRadioButton.Checked = true;
63 | pSelectedRadioButton = value;
64 | OnSelectedRadioButtonChanged();
65 | }
66 | }
67 | }
68 |
69 | private void OnSelectedRadioButtonChanged()
70 | {
71 | if (SelectedRadioButtonChanged != null) {
72 | SelectedRadioButtonChanged(this, new EventArgs());
73 | }
74 | // Workaround for strange behavior of data binding:
75 | // If we change the SelecteRadioButton property and then change another
76 | // data bound property in this group box, the SelectedRadioButton changes
77 | // will be reverted by the data binding code. To get around this, after we
78 | // have notified the the listeners, we select a control outside of the
79 | // group box and then select the usual next control.
80 | Parent.SelectNextControl(this, true, false, false, true);
81 | SelectNextControl(this, true, true, true, true);
82 | }
83 |
84 | protected override void OnControlAdded(ControlEventArgs e)
85 | {
86 | base.OnControlAdded(e);
87 | var radioButton = e.Control as RadioButton;
88 | if (radioButton != null) {
89 | radioButton.CheckedChanged += (s, e2) => {
90 | if (radioButton.Checked) {
91 | SelectedRadioButton = radioButton.Name;
92 | }
93 | };
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/KeeAgent/UI/DatabaseSettingsPanel.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KeeAgent.UI
2 | {
3 | partial class DatabaseSettingsPanel
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null)) {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Windows Form Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | this.components = new System.ComponentModel.Container();
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DatabaseSettingsPanel));
32 | this.mHelpButton = new System.Windows.Forms.Button();
33 | this.allowAutoLoadExpiredCheckBox = new System.Windows.Forms.CheckBox();
34 | this.mDatabaseSettingsBindingSource = new System.Windows.Forms.BindingSource(this.components);
35 | ((System.ComponentModel.ISupportInitialize)(this.mDatabaseSettingsBindingSource)).BeginInit();
36 | this.SuspendLayout();
37 | //
38 | // mHelpButton
39 | //
40 | resources.ApplyResources(this.mHelpButton, "mHelpButton");
41 | this.mHelpButton.Image = global::KeeAgent.Properties.Resources.Help_png;
42 | this.mHelpButton.Name = "mHelpButton";
43 | this.mHelpButton.UseVisualStyleBackColor = true;
44 | this.mHelpButton.Click += new System.EventHandler(this.mHelpButton_Click);
45 | //
46 | // allowAutoLoadExpiredCheckBox
47 | //
48 | resources.ApplyResources(this.allowAutoLoadExpiredCheckBox, "allowAutoLoadExpiredCheckBox");
49 | this.allowAutoLoadExpiredCheckBox.DataBindings.Add(new System.Windows.Forms.Binding("Checked", this.mDatabaseSettingsBindingSource, "AllowAutoLoadExpiredEntryKey", true));
50 | this.allowAutoLoadExpiredCheckBox.Name = "allowAutoLoadExpiredCheckBox";
51 | this.allowAutoLoadExpiredCheckBox.UseVisualStyleBackColor = true;
52 | //
53 | // mDatabaseSettingsBindingSource
54 | //
55 | this.mDatabaseSettingsBindingSource.DataSource = typeof(KeeAgent.DatabaseSettings);
56 | //
57 | // DatabaseSettingsPanel
58 | //
59 | resources.ApplyResources(this, "$this");
60 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
61 | this.Controls.Add(this.allowAutoLoadExpiredCheckBox);
62 | this.Controls.Add(this.mHelpButton);
63 | this.Name = "DatabaseSettingsPanel";
64 | ((System.ComponentModel.ISupportInitialize)(this.mDatabaseSettingsBindingSource)).EndInit();
65 | this.ResumeLayout(false);
66 | this.PerformLayout();
67 |
68 | }
69 |
70 | #endregion
71 |
72 | private System.Windows.Forms.BindingSource mDatabaseSettingsBindingSource;
73 | private System.Windows.Forms.Button mHelpButton;
74 | private System.Windows.Forms.CheckBox allowAutoLoadExpiredCheckBox;
75 |
76 | }
77 | }
--------------------------------------------------------------------------------
/KeeAgent.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.6.33815.320
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeeAgent", "KeeAgent\KeeAgent.csproj", "{742863F2-52ED-41E0-92A1-8EEA60EB75EF}"
7 | EndProject
8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A3C09426-AEFA-4170-B530-3A0F3B13903D}"
9 | ProjectSection(SolutionItems) = preProject
10 | .editorconfig = .editorconfig
11 | CHANGELOG.txt = CHANGELOG.txt
12 | LICENSE.txt = LICENSE.txt
13 | README.md = README.md
14 | EndProjectSection
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SshAgentLib", "SshAgentLib\SshAgentLib\SshAgentLib.csproj", "{9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SshAgentLib.Ui.WinForms", "SshAgentLib\Ui\WinForms\SshAgentLib.Ui.WinForms.csproj", "{3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}"
19 | EndProject
20 | Global
21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
22 | Debug|Any CPU = Debug|Any CPU
23 | Release|Any CPU = Release|Any CPU
24 | ReleaseDll|Any CPU = ReleaseDll|Any CPU
25 | ReleasePlgx|Any CPU = ReleasePlgx|Any CPU
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.ReleaseDll|Any CPU.ActiveCfg = ReleaseDll|Any CPU
33 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.ReleaseDll|Any CPU.Build.0 = ReleaseDll|Any CPU
34 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.ReleasePlgx|Any CPU.ActiveCfg = ReleasePlgx|Any CPU
35 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}.ReleasePlgx|Any CPU.Build.0 = ReleasePlgx|Any CPU
36 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.ReleaseDll|Any CPU.ActiveCfg = Release|Any CPU
41 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.ReleaseDll|Any CPU.Build.0 = Release|Any CPU
42 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.ReleasePlgx|Any CPU.ActiveCfg = Release|Any CPU
43 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}.ReleasePlgx|Any CPU.Build.0 = Release|Any CPU
44 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.ReleaseDll|Any CPU.ActiveCfg = Release|Any CPU
49 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.ReleaseDll|Any CPU.Build.0 = Release|Any CPU
50 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.ReleasePlgx|Any CPU.ActiveCfg = Release|Any CPU
51 | {3BEB6FAE-B14D-4281-8168-DB2A4A0C5FC4}.ReleasePlgx|Any CPU.Build.0 = Release|Any CPU
52 | EndGlobalSection
53 | GlobalSection(SolutionProperties) = preSolution
54 | HideSolutionNode = FALSE
55 | EndGlobalSection
56 | EndGlobal
57 |
--------------------------------------------------------------------------------
/KeeAgent/UI/HostKeysDialog.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System;
5 | using System.Data;
6 | using System.Linq;
7 | using System.Windows.Forms;
8 | using SshAgentLib.Keys;
9 |
10 | namespace KeeAgent.UI
11 | {
12 | public partial class HostKeysDialog : Form
13 | {
14 | public HostKeysDialog()
15 | {
16 | InitializeComponent();
17 |
18 | // fix up layout in Mono
19 | if (Type.GetType("Mono.Runtime") != null) {
20 | dataGridView1.Anchor = AnchorStyles.Top | AnchorStyles.Left;
21 | dataGridView1.Height -= 20;
22 | okButton.Top -= 20;
23 | cancelButton.Top -= 20;
24 | }
25 | }
26 |
27 | public void AddKeySpec(EntrySettings.DestinationConstraint.KeySpec spec)
28 | {
29 | keySpecBindingSource.Add(spec.DeepCopy());
30 | }
31 |
32 | public EntrySettings.DestinationConstraint.KeySpec[] GetKeySpecs()
33 | {
34 | return keySpecBindingSource.Cast()
35 | .Where(x => !string.IsNullOrWhiteSpace(x.HostKey)).Select(x => x.DeepCopy()).ToArray();
36 | }
37 |
38 | private void dataGridView1_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
39 | {
40 | var view = (DataGridView)sender;
41 |
42 | foreach (DataGridViewRow row in view.Rows) {
43 |
44 | if (row.IsNewRow) {
45 | continue;
46 | }
47 |
48 | try {
49 | var k = row.DataBoundItem as EntrySettings.DestinationConstraint.KeySpec;
50 |
51 | if (string.IsNullOrWhiteSpace(k.HostKey)) {
52 | row.ErrorText = "host key is required";
53 | continue;
54 | }
55 |
56 | SshPublicKey.Parse(k.HostKey);
57 |
58 | // no error, so hide error badge
59 | row.ErrorText = string.Empty;
60 | }
61 | catch (Exception ex) {
62 | row.ErrorText = ex.Message;
63 | }
64 | }
65 | }
66 |
67 | private void dataGridView1_MouseUp(object sender, MouseEventArgs e)
68 | {
69 | var grid = sender as DataGridView;
70 |
71 | var hitTest = grid.HitTest(e.X, e.Y);
72 |
73 | if (hitTest.Type == DataGridViewHitTestType.RowHeader) {
74 | var clickedRow = grid.Rows[hitTest.RowIndex];
75 |
76 | grid.CurrentCell = clickedRow.Cells[0];
77 |
78 | if (grid.CurrentRow.IsNewRow) {
79 | // can't remove uncommitted new row
80 | deleteToolStripMenuItem.Enabled = false;
81 | }
82 | else {
83 | deleteToolStripMenuItem.Enabled = true;
84 | }
85 | }
86 | else if (hitTest.Type == DataGridViewHitTestType.Cell) {
87 | var clickedCell = grid.Rows[hitTest.RowIndex].Cells[hitTest.ColumnIndex];
88 |
89 | grid.CurrentCell = clickedCell;
90 |
91 | if (grid.CurrentRow.IsNewRow) {
92 | // can't remove uncommitted new row
93 | deleteToolStripMenuItem.Enabled = false;
94 | }
95 | else {
96 | deleteToolStripMenuItem.Enabled = true;
97 | }
98 | }
99 | else {
100 | deleteToolStripMenuItem.Enabled = false;
101 | }
102 | }
103 |
104 | private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
105 | {
106 | try {
107 | dataGridView1.Rows.Remove(dataGridView1.CurrentRow);
108 | }
109 | catch {
110 | // don't crash the program
111 | }
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/KeeAgent/UI/Validate.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2022 David Lechner
3 |
4 | using System;
5 | using System.IO;
6 | using KeePassLib.Security;
7 | using SshAgentLib.Keys;
8 |
9 | namespace KeeAgent.UI
10 | {
11 | ///
12 | /// Miscellaneous validators.
13 | ///
14 | public static class Validate
15 | {
16 | ///
17 | /// Validates the location data.
18 | ///
19 | ///
20 | /// The location data to check.
21 | ///
22 | ///
23 | /// Callback function to get the attachment by name.
24 | ///
25 | ///
26 | /// null if the data is valid, otherwise an error message suitable for display to the user.
27 | ///
28 | public static string Location(
29 | EntrySettings.LocationData location,
30 | Func getAttachment)
31 | {
32 | // we don't actually expect this to happen
33 | if (location == null) {
34 | return null;
35 | }
36 |
37 | if (!location.SelectedType.HasValue) {
38 | return "No private key file type is selected. Select an option and try again.";
39 | }
40 |
41 | if (location.SelectedType.Value == EntrySettings.LocationType.Attachment) {
42 | var attachment = getAttachment(location.AttachmentName);
43 |
44 | if (attachment == null) {
45 | return string.Format(
46 | "Attachment '{0}' is missing.", location.AttachmentName);
47 | }
48 |
49 | SshPrivateKey privateKey;
50 |
51 | try {
52 | privateKey = SshPrivateKey.Read(new MemoryStream(attachment.ReadData()));
53 | }
54 | catch {
55 | return string.Format(
56 | "attachment '{0}' is not a supported private key file.", location.AttachmentName);
57 | }
58 |
59 | SshPublicKey publicKey = privateKey.PublicKey;
60 |
61 | var certAttachment = getAttachment(location.AttachmentName + "-cert.pub");
62 |
63 | if (certAttachment != null) {
64 | publicKey = SshPublicKey.Read(new MemoryStream(certAttachment.ReadData()));
65 | }
66 |
67 | var pubAttachment = getAttachment(location.AttachmentName + ".pub");
68 |
69 | if (pubAttachment != null) {
70 | publicKey = SshPublicKey.Read(new MemoryStream(pubAttachment.ReadData()));
71 | }
72 |
73 | if (publicKey == null) {
74 | return string.Format(
75 | "This file uses a legacy format that requires a '{0}.pub' file in the same location.",
76 | location.AttachmentName);
77 | }
78 | }
79 |
80 | if (location.SelectedType.Value == EntrySettings.LocationType.File) {
81 | var file = location.FileName.ExpandEnvironmentVariables();
82 |
83 | if (!File.Exists(file)) {
84 | return string.Format("The private key file '{0}' does not exist.", file);
85 | }
86 |
87 | SshPrivateKey privateKey;
88 |
89 | try {
90 | privateKey = SshPrivateKey.Read(File.OpenRead(file));
91 | }
92 | catch {
93 | return string.Format("'{0}' is not a supported private key file.", file);
94 | }
95 |
96 | SshPublicKey publicKey = privateKey.PublicKey;
97 |
98 | if (File.Exists(file + "-cert.pub")) {
99 | publicKey = SshPublicKey.Read(File.OpenRead(file + "-cert.pub"));
100 | }
101 | else if (File.Exists(file + ".pub")) {
102 | publicKey = SshPublicKey.Read(File.OpenRead(file + ".pub"));
103 | }
104 |
105 | if (publicKey == null) {
106 | return string.Format(
107 | "This file uses a legacy format that requires a '{0}.pub' file in the same location.",
108 | file);
109 | }
110 | }
111 |
112 | return null;
113 | }
114 | }
115 | }
116 |
--------------------------------------------------------------------------------
/KeeAgent/Options.cs:
--------------------------------------------------------------------------------
1 | // SPDX-License-Identifier: GPL-2.0-only
2 | // Copyright (c) 2012-2017,2022 David Lechner
3 |
4 | using System;
5 | using dlech.SshAgentLib;
6 |
7 | namespace KeeAgent
8 | {
9 | [Serializable]
10 | public class Options
11 | {
12 | public Options()
13 | {
14 | /* set default values */
15 | }
16 |
17 | ///
18 | /// Show notification balloon when client uses keys (Agent mode only)
19 | ///
20 | public bool ShowBalloon { get; set; }
21 |
22 | ///
23 | /// Cause all keys to have confirm constraint set even if it is not requested (Agent mode only)
24 | ///
25 | public bool AlwaysConfirm { get; set; }
26 |
27 | ///
28 | /// Replaced by ShowBalloon and AlwaysConfirm
29 | ///
30 | [Obsolete()]
31 | public NotificationOptions Notification { get; set; }
32 |
33 | ///
34 | /// Turns on debug logging - currently not working
35 | ///
36 | public bool LoggingEnabled { get; set; }
37 |
38 | ///
39 | /// The file name for the debug log file
40 | ///
41 | public string LogFileName { get; set; }
42 |
43 | ///
44 | /// Specifies which mode to run the agent in.
45 | ///
46 | public AgentMode AgentMode { get; set; }
47 |
48 | ///
49 | /// When true, all databases will be unlocked when an SSH keys is requested (Agent mode only).
50 | ///
51 | public bool UnlockOnActivity { get; set; }
52 |
53 | ///
54 | /// When true and using PageantAgent, a socket file will be created at
55 | /// CygwinSocketPath that can be used with cygwin
56 | ///
57 | public bool UseCygwinSocket { get; set; }
58 |
59 | ///
60 | /// The path for the file created when is enabled.
61 | ///
62 | public string CygwinSocketPath { get; set; }
63 |
64 | ///
65 | /// When true and using PageantAgent, a socket file will be created at
66 | /// MsysSocketPath that can be used with msys
67 | ///
68 | public bool UseMsysSocket { get; set; }
69 |
70 | ///
71 | /// The path for the file created when is enabled.
72 | ///
73 | public string MsysSocketPath { get; set; }
74 |
75 | ///
76 | /// When true and using PageantAgent, a socket file will be created at
77 | /// UnixSocketPath that can be used with WSL
78 | ///
79 | public bool UseWslSocket { get; set; }
80 |
81 | ///
82 | /// The path for the file created when is enabled.
83 | ///
84 | public string WslSocketPath { get; set; }
85 |
86 | ///
87 | /// When true and using PageantAgent, a named pipe will be created
88 | /// at //./pipe/openssh-ssh-agent that can be used with Windows OpenSSH
89 | ///
90 | public bool UseWindowsOpenSshPipe { get; set; }
91 |
92 | ///
93 | /// The path for creating a unix socket in Agent mode on unix-like platforms
94 | ///
95 | /// The unix socket path.
96 | public string UnixSocketPath { get; set; }
97 |
98 | ///
99 | /// When true, the user will be prompted to select a keys from the
100 | /// loaded keys in response to a client program requesting a list of
101 | /// identities.
102 | ///
103 | public static bool UserPicksKeyOnRequestIdentities { get; set; }
104 |
105 | ///
106 | /// When true, we will not display a warning about missing keyfiles
107 | /// in the filesystem.
108 | ///
109 | public static bool IgnoreMissingExternalKeyFiles { get; set; }
110 |
111 | ///
112 | /// When true, we will not display a progress bar during SSH key decryption.
113 | ///
114 | public bool DisableKeyDecryptionProgressBar { get; set; }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/doc/usage/keeagent-manager.rst:
--------------------------------------------------------------------------------
1 | ================
2 | KeeAgent Manager
3 | ================
4 |
5 | The KeeAgent Manager lists the keys that are currently loaded into the agent.
6 | From here, you can lock and unlock the agent as well as add and remove keys.
7 | The KeeAgent manager is opened from Tools > KeeAgent or from the notification
8 | tray icon menu.
9 |
10 | .. figure:: images/win10-keepass-keeagent-manager-client-mode.png
11 | :alt: Screenshot of the KeeAgent Manager window in Agent Mode
12 |
13 | .. figure:: images/win10-keepass-keeagent-manager-client-mode.png
14 | :alt: Screenshot of the KeeAgent Manager window in Client Mode
15 |
16 | **Mode Indication**
17 |
18 | The "mode" being used by KeeAgent is displayed in the title bar of the
19 | KeeAgent manager. *Agent Mode* indicates that KeeAgent is acting as the SSH
20 | agent. *Client Mode* indicates that KeeAgent is using an external SSH agent.
21 | See Global Options for more information.
22 |
23 | **List Columns**
24 |
25 | - **C** (Confirm Constraint - Agent mode only): Checked indicates that the
26 | user must confirm the use of the key every time a client requests to use
27 | the key for authentication.
28 |
29 | - **L** (Lifetime Constraint - Agent mode only): Checked indicates that the
30 | key will be automatically removed after a period of time.
31 |
32 | - **Type**: The encryption algorithm used by the key.
33 |
34 | - **Size**: The size (in bits) of the key.
35 |
36 | - **Fingerprint**: The MD5 hash of the key.
37 |
38 | - **Comment**: The comment associated with the key.
39 |
40 | - **Source**: (Agent mode only): The source of the key. This can be one of
41 | the following: the name of a database and the path of the entry in the
42 | database, the name of a file or "External client" if the key was loaded
43 | through a utility such as ``ssh-add``.
44 |
45 | **Lock and Unlock Buttons**
46 |
47 | Clicking *Lock* will prompt you for a passphrase. The passphrase can be
48 | anything - it is temporary. After entering a passphrase, the agent will be
49 | locked. This means that no keys can be added or removed or used for
50 | authentication until the agent is unlocked. To unlock, click *Unlock* and
51 | enter the same passphrase that you used when you locked the agent.
52 |
53 | .. note:: Locking and unlocking the agent is completely independent of
54 | locking and unlocking databases in KeePass.
55 |
56 | .. note:: Pageant does not support locking/unlocking, so if you are in
57 | *Client Mode* and connecting to Pageant, these buttons will not be shown.
58 |
59 | **Add.. Button**
60 |
61 | - **From KeePass...**: Shows a dialog that allows you to load a key from
62 | an entry in any of the databases currently open in KeePass. Select an
63 | entry and optionally select constrains, then click *OK* to load the key
64 | into the agent.
65 |
66 | .. note:: If you are in Client Mode and using Pageant, the checkboxes
67 | for constraints will not be shown. Pageant does not support constraints.
68 |
69 | .. figure:: images/win10-keepass-keeagent-manager-select-entry-dialog.png
70 | :alt: Screenshot of the KeeAgent Manager Select Entry dialog box
71 |
72 | - **From File...**: Shows a file browser dialog that allows you to load a
73 | key from an external file. You can also selectively add constraints to
74 | the keys.
75 |
76 | .. note:: Constraint checkboxes are integrated into the file dialog on
77 | Windows only. If you are on another OS, hold down the Control key
78 | when you click OK and you will get a separate dialog to enter
79 | constraints.
80 |
81 | .. note:: If you are in Client Mode and using Pageant, the checkboxes
82 | for constraints will not be shown. Pageant does not support constraints.
83 |
84 | .. figure:: images/win10-keepass-keeagent-manager-file-browser.png
85 | :alt: Screenshot of KeeAgent Manager file browser dialog box
86 |
87 | **Remove Button**
88 |
89 | Removes the selected key(s) from the agent.
90 |
91 | **Remove All Button**
92 |
93 | Removes all keys from the agent.
94 |
95 | **Refresh Button** (Client mode only)
96 |
97 | Sends a request to the agent for a current list of keys.
98 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/KeeAgentTestProject.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {D181A56F-743F-429F-BA31-1827C39A176C}
7 | Library
8 | Properties
9 | KeeAgentTestProject
10 | KeeAgentTestProject
11 | 512
12 |
13 |
14 | True
15 | full
16 | False
17 | bin\Debug\
18 | DEBUG;TRACE
19 | prompt
20 | 4
21 |
22 |
23 | pdbonly
24 | True
25 | bin\Release\
26 | TRACE
27 | prompt
28 | 4
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ..\lib\NUnit\nunit.framework.dll
43 |
44 |
45 | ..\lib\IOProtocolExt\IOProtocolExt.dll
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | True
54 | True
55 | Resources.resx
56 |
57 |
58 |
59 |
60 |
61 | {742863F2-52ED-41E0-92A1-8EEA60EB75EF}
62 | KeeAgent
63 |
64 |
65 | {10938016-dee2-4a25-9a5a-8fd3444379ca}
66 | KeePass
67 |
68 |
69 | {9163B6B6-0603-4C6E-BC67-7111ED8CDDE1}
70 | SshAgentLib
71 |
72 |
73 |
74 |
75 | PublicResXFileCodeGenerator
76 | Resources.Designer.cs
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
94 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.269
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace KeeAgentTestProject.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KeeAgentTestProject.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | public static byte[] _4095_bits_ppk {
64 | get {
65 | object obj = ResourceManager.GetObject("_4095_bits_ppk", resourceCulture);
66 | return ((byte[])(obj));
67 | }
68 | }
69 |
70 | public static byte[] dsa_ppk {
71 | get {
72 | object obj = ResourceManager.GetObject("dsa_ppk", resourceCulture);
73 | return ((byte[])(obj));
74 | }
75 | }
76 |
77 | public static byte[] non_ascii_passphrase_ppk {
78 | get {
79 | object obj = ResourceManager.GetObject("non_ascii_passphrase_ppk", resourceCulture);
80 | return ((byte[])(obj));
81 | }
82 | }
83 |
84 | public static byte[] withoutPassphrase_ppk {
85 | get {
86 | object obj = ResourceManager.GetObject("withoutPassphrase_ppk", resourceCulture);
87 | return ((byte[])(obj));
88 | }
89 | }
90 |
91 | public static byte[] withPassphrase_ppk {
92 | get {
93 | object obj = ResourceManager.GetObject("withPassphrase_ppk", resourceCulture);
94 | return ((byte[])(obj));
95 | }
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/doc/troubleshooting.rst:
--------------------------------------------------------------------------------
1 | ===============
2 | Troubleshooting
3 | ===============
4 |
5 | Here are some suggestions for troubleshooting KeeAgent.
6 |
7 |
8 | Common issues
9 | =============
10 |
11 | **Problem:**
12 |
13 | After upgrading my OS, my 1024-bit RSA key no longer works with KeeAgent in
14 | Client mode.
15 |
16 | **Solution:**
17 |
18 | OpenSSH dropped support for RSA keys <= 1024-bit in v7.6 because they are
19 | no longer considered secure. This version of OpenSSH ships with Ubuntu 18.04
20 | and macOS High Sierra. Create a new, larger key.
21 |
22 | **Problem:**
23 |
24 | Connecting to a server fails when too many keys are loaded in KeeAgent. For
25 | example, you might get an error message like this::
26 |
27 | Server sent disconnect message type 2 (protocol error): "Too many authentication failures for user"
28 |
29 | Many servers will only try the first 6 keys before returning an error. This
30 | number will vary from server to server though.
31 |
32 | **Solution:**
33 |
34 | To work around this, limit the number of keys that load automatically, use
35 | the *Show selection dialog when a client program requests a list of keys*
36 | option or consider having the keys saved to a temporary file as described
37 | in :doc:`usage/tips-and-tricks`.
38 |
39 | **Problem:**
40 |
41 | When I start KeePass, I get an error message like this::
42 |
43 | The following plugin is incompatible with the current KeePass version:
44 | Have a look at the plugin's website for an appropriate version.
45 |
46 | **Solution:**
47 |
48 | Run KeePass.exe from a command prompt with the ``--debug`` option (and ``--saveplgxcr``
49 | for KeePass versions older than 2.31). This should give more detailed information
50 | on the cause of the error. Report the error using the link for other issues below.
51 |
52 | **Problem:**
53 |
54 | Keys will not load with the confirm constraint.
55 |
56 | **Solution:**
57 |
58 | On Windows, if you are using Pageant and running KeeAgent in client mode, then
59 | constraints will not work. Pageant does not support constraints.
60 |
61 | On Linux, if you are using a GNOME based desktop (includes Cinnamon, MATE, Unity,
62 | others), follow the instructions for disabling the SSH agent in GNOME keyring.
63 |
64 | **Problem:**
65 |
66 | "The plugin cannot be loaded A newer .NET framework is required." error on Linux
67 | and KeePass version is less than 2.52.
68 |
69 | **Solution:**
70 |
71 | Use workaround described in `issue #343 `_.
72 |
73 |
74 | Other issues
75 | ============
76 |
77 | Read everything here and still having problems?
78 |
79 | Report your issues on `GitHub`_.
80 |
81 | .. _`GitHub`: https://github.com/dlech/keeagent/issues
82 |
83 |
84 | Debugging
85 | =========
86 |
87 | You can use Visual Studio to see a limited amount of debug information.
88 |
89 | Prerequisite: `Visual Studio 2022 `_
90 | with the *.NET desktop development* workload installed.
91 |
92 | .. figure:: images/vs-dotnet-desktop-development.png
93 | :alt: screenshot of Visual Studio Installer with .NET desktop development workload selected
94 |
95 | 1. Start *KeePass*.
96 |
97 | 2. Start *Visual Studio*.
98 |
99 | 3. Select *Continue without code*.
100 |
101 | .. figure:: images/vs-continue-without-code.png
102 | :alt: screenshot of Visual Studio 2022 start screen "Continue without code" hyperlink
103 |
104 | 4. Click the *Attach* button.
105 |
106 | .. figure:: images/vs-attach.png
107 | :alt: screenshot of Visual Studio 2022 start screen "Attach" button
108 |
109 | 5. Select *KeePass* from the list of processes. Use the filter to find it quickly.
110 |
111 | .. figure:: images/vs-attach-to-process-keepass.png
112 | :alt: screenshot of Visual Studio 2022 "Attach to Process" dialog with "KeePass.exe" selected.
113 |
114 | 6. Click the *Attach* button.
115 |
116 | 7. Select the *Output* tab.
117 |
118 | .. figure:: images/vs-output-tab.png
119 | :alt: screenshot of Visual Studio 2022 "Output" tab
120 |
121 | 8. Reproduce the issue in KeePass/KeeAgent.
122 |
123 | 9. Look for any useful information in the *Output* tab.
124 |
--------------------------------------------------------------------------------
/KeeAgent/UI/ManageDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KeeAgent.UI
2 | {
3 | partial class ManageDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null)) {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Windows Form Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | this.components = new System.ComponentModel.Container();
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ManageDialog));
32 | this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
33 | this.addButtonMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
34 | this.addButtonFromKeePassMenuItem = new System.Windows.Forms.ToolStripMenuItem();
35 | this.addButtonFromFileMenuItem = new System.Windows.Forms.ToolStripMenuItem();
36 | this.keyInfoView = new dlech.SshAgentLib.WinForms.KeyInfoView();
37 | this.addButtonMenuStrip.SuspendLayout();
38 | this.SuspendLayout();
39 | //
40 | // dataGridViewTextBoxColumn1
41 | //
42 | this.dataGridViewTextBoxColumn1.DataPropertyName = "Value";
43 | resources.ApplyResources(this.dataGridViewTextBoxColumn1, "dataGridViewTextBoxColumn1");
44 | this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1";
45 | this.dataGridViewTextBoxColumn1.ReadOnly = true;
46 | //
47 | // addButtonMenuStrip
48 | //
49 | this.addButtonMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
50 | this.addButtonFromKeePassMenuItem,
51 | this.addButtonFromFileMenuItem});
52 | this.addButtonMenuStrip.Name = "addButtonMenuStrip";
53 | this.addButtonMenuStrip.ShowImageMargin = false;
54 | resources.ApplyResources(this.addButtonMenuStrip, "addButtonMenuStrip");
55 | //
56 | // addButtonFromKeePassMenuItem
57 | //
58 | this.addButtonFromKeePassMenuItem.Name = "addButtonFromKeePassMenuItem";
59 | resources.ApplyResources(this.addButtonFromKeePassMenuItem, "addButtonFromKeePassMenuItem");
60 | this.addButtonFromKeePassMenuItem.Click += new System.EventHandler(this.addButtonFromKeePassMenuItem_Click);
61 | //
62 | // addButtonFromFileMenuItem
63 | //
64 | this.addButtonFromFileMenuItem.Name = "addButtonFromFileMenuItem";
65 | resources.ApplyResources(this.addButtonFromFileMenuItem, "addButtonFromFileMenuItem");
66 | this.addButtonFromFileMenuItem.Click += new System.EventHandler(this.addButtonFromFileMenuItem_Click);
67 | //
68 | // keyInfoView
69 | //
70 | this.keyInfoView.AddButtonSplitMenu = this.addButtonMenuStrip;
71 | resources.ApplyResources(this.keyInfoView, "keyInfoView");
72 | this.keyInfoView.Name = "keyInfoView";
73 | this.keyInfoView.AddFromFileHelpRequested += new System.EventHandler(this.keyInfoView_AddFromFileHelpRequested);
74 | //
75 | // ManageDialog
76 | //
77 | resources.ApplyResources(this, "$this");
78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
79 | this.Controls.Add(this.keyInfoView);
80 | this.HelpButton = true;
81 | this.KeyPreview = true;
82 | this.MaximizeBox = false;
83 | this.MinimizeBox = false;
84 | this.Name = "ManageDialog";
85 | this.ShowInTaskbar = false;
86 | this.HelpButtonClicked += new System.ComponentModel.CancelEventHandler(this.ManageDialog_HelpButtonClicked);
87 | this.HelpRequested += new System.Windows.Forms.HelpEventHandler(this.ManageDialog_HelpRequested);
88 | this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ManageDialog_KeyDown);
89 | this.addButtonMenuStrip.ResumeLayout(false);
90 | this.ResumeLayout(false);
91 |
92 | }
93 |
94 | #endregion
95 |
96 | private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
97 | private dlech.SshAgentLib.WinForms.KeyInfoView keyInfoView;
98 | private System.Windows.Forms.ContextMenuStrip addButtonMenuStrip;
99 | private System.Windows.Forms.ToolStripMenuItem addButtonFromKeePassMenuItem;
100 | private System.Windows.Forms.ToolStripMenuItem addButtonFromFileMenuItem;
101 | }
102 | }
--------------------------------------------------------------------------------
/doc/usage/tips-and-tricks.rst:
--------------------------------------------------------------------------------
1 | ===============
2 | Tips and Tricks
3 | ===============
4 |
5 | Creating URL Overrides to Open a Connection
6 | ===========================================
7 |
8 | Having lots of SSH keys loaded in KeeAgent can be a problem for many servers.
9 | To work around this, many ssh programs allow you to specify an identity file when
10 | connecting so that it knows which key to use instead of having to try all the
11 | keys that are loaded.
12 |
13 | Since SSH keys in KeeAgent are usually saved as attachments embedded in the
14 | database, there is an option in the *Entry Settings* to save the key to an actual
15 | file on disk when the key is loaded in KeeAgent.
16 |
17 | .. figure:: images/win10-keepass-entry-keeagent-tab-private-key-file-location.png
18 | :alt: Screenshot of Private Key File Location with "Save attachments to
19 | temporary file when key is loaded" checked
20 |
21 | Once you have selected this option, there will be two placeholders available for
22 | use in KeePass.
23 |
24 | - ``{KEEAGENT:KEYFILEPATH}`` returns the full path. e.g. ``C:\path\to\keyfile.ppk``
25 | - ``{KEEAGENT:IDENTFILEOPT}`` returns the identity file command line option
26 | that is used by both PuTTY.exe and ssh. e.g. ``-i "C:\path\to\keyfile.ppk"``
27 |
28 | You can use these placeholders to create URL overrides. Global overrides are at
29 | *Tools > Options > Integration (tab) > URL Scheme Overrides...* or they can be
30 | specified per-entry on the *Properties* tab of *Entry Settings*.
31 |
32 | .. note:: The placeholders also work with the *External File* location in
33 | addition to attachments.
34 |
35 | Example:
36 |
37 | Open an ssh connection using PuTTY with the username and host specified in
38 | the database entry. The entry must have the Username and URL fields filled
39 | out for this to work.
40 | ::
41 |
42 | cmd://"C:\Program Files (x86)\PuTTY\PuTTY.exe" -ssh {USERNAME}@{URL:RMVSCM} {KEEAGENT:IDENTFILEOPT}
43 |
44 | .. tip:: Read more about the PuTTY command line `here`__. For example, the
45 | ``-load`` option is useful to load a saved session associated with the key.
46 |
47 | .. __: http://the.earth.li/~sgtatham/putty/latest/htmldoc/Chapter3.html#using-cmdline
48 |
49 |
50 | Using KeeAgent on Windows
51 | =========================
52 |
53 |
54 | Client mode with Pageant
55 | ------------------------
56 |
57 | KeeAgent (in Agent Mode) is designed to work much like ``ssh-agent`` on Linux/BSD/etc...
58 | Pageant is very similar, but there are some notable differences. Because of the
59 | more limited features of Pageant, it is recommended to run in Agent mode on
60 | Windows instead of using Pageant. However, if you have a good reason to run
61 | KeeAgent in Client Mode along with Pageant, here are some things to be aware of:
62 |
63 | - Pageant does not support locking.
64 | - Pageant does not support constraints.
65 | - Pageant does not support ECDSA or Ed25519 keys (except in the development version).
66 |
67 |
68 | Cygwin and MSYS
69 | ---------------
70 |
71 | KeeAgent can natively communicate with ssh programs running in Cygwin and
72 | MSYS. It is enabled in the :ref:`global-options` dialog.
73 |
74 | There are two implementations of sockets that are found in the various versions
75 | of Cygwin and MSYS. MSYS is really just a fork of Cygwin, so it depends on which
76 | fork the code is based on. So, unless you are using msysGit, try the "Cygwin
77 | socket file" first and if that does not work, try the "msysGit socket file".
78 | In some cases, you may need both enabled to support multiple versions of
79 | Cygwin/MSYS.
80 |
81 |
82 | Windows OpenSSH
83 | ---------------
84 |
85 | Although recent versions of Windows ship with OpenSSH out of the box, the
86 | included version is quite out of date. Consider installing the latest version
87 | with ``winget`` or ``choco`` instead or get them straight from the source from the
88 | `GitHub releases `_ page.
89 |
90 | These tools are compatible with KeeAgent when **Enable agent for Windows OpenSSH**
91 | is selected in the :ref:`global-options`.
92 |
93 |
94 | Windows Subsystem for Linux (WSL)
95 | ---------------------------------
96 |
97 | KeeAgent can be used with `WSL `_.
98 |
99 | For WSL1, simply select **Create WSL1 compatible socket file** in the
100 | :ref:`global-options` and set the ``SSH_AUTH_SOCK`` environment variable
101 | in your WSL1 shell to match.
102 |
103 | For WSL2, the environment is more isolated from Windows, so it is not possible
104 | to use the WSL1 socket. Instead, you can use the Windows OpenSSH programs
105 | from inside a WSL2 shell by running ``ssh.exe`` instead of ``ssh``.
106 |
107 | .. tip:: You can make a bash alias or symlink to make ``ssh`` an alias for
108 | ``ssh.exe``. For example::
109 |
110 | sudo ln -s $(which ssh.exe) /usr/local/bin/
111 |
112 | Alternately, there are a number of 3rd party solutions for providing a socket
113 | bridge to connect programs inside of WSL2 to an external SSH agent.
114 |
--------------------------------------------------------------------------------
/KeeAgent/UI/ManageKeyFileDialog.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KeeAgent.UI
2 | {
3 | partial class ManageKeyFileDialog
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null)) {
17 | components.Dispose();
18 | }
19 | base.Dispose(disposing);
20 | }
21 |
22 | #region Windows Form Designer generated code
23 |
24 | ///
25 | /// Required method for Designer support - do not modify
26 | /// the contents of this method with the code editor.
27 | ///
28 | private void InitializeComponent()
29 | {
30 | this.cancelButton = new System.Windows.Forms.Button();
31 | this.okButton = new System.Windows.Forms.Button();
32 | this.privateKeyLocationPanel = new KeeAgent.UI.KeyLocationPanel();
33 | this.SuspendLayout();
34 | //
35 | // cancelButton
36 | //
37 | this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
38 | this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
39 | this.cancelButton.Location = new System.Drawing.Point(456, 143);
40 | this.cancelButton.Margin = new System.Windows.Forms.Padding(2);
41 | this.cancelButton.Name = "cancelButton";
42 | this.cancelButton.Size = new System.Drawing.Size(75, 23);
43 | this.cancelButton.TabIndex = 2;
44 | this.cancelButton.Text = "&Cancel";
45 | this.cancelButton.UseVisualStyleBackColor = true;
46 | //
47 | // okButton
48 | //
49 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
50 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
51 | this.okButton.Location = new System.Drawing.Point(377, 143);
52 | this.okButton.Margin = new System.Windows.Forms.Padding(2);
53 | this.okButton.Name = "okButton";
54 | this.okButton.Size = new System.Drawing.Size(75, 23);
55 | this.okButton.TabIndex = 3;
56 | this.okButton.Text = "&OK";
57 | this.okButton.UseVisualStyleBackColor = true;
58 | //
59 | // privateKeyLocationPanel
60 | //
61 | this.privateKeyLocationPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
62 | | System.Windows.Forms.AnchorStyles.Right)));
63 | this.privateKeyLocationPanel.Attachments = null;
64 | this.privateKeyLocationPanel.BackColor = System.Drawing.Color.Transparent;
65 | this.privateKeyLocationPanel.ErrorMessage = "";
66 | this.privateKeyLocationPanel.KeyLocation = null;
67 | this.privateKeyLocationPanel.Location = new System.Drawing.Point(15, 15);
68 | this.privateKeyLocationPanel.Margin = new System.Windows.Forms.Padding(6);
69 | this.privateKeyLocationPanel.Name = "privateKeyLocationPanel";
70 | this.privateKeyLocationPanel.Size = new System.Drawing.Size(512, 118);
71 | this.privateKeyLocationPanel.TabIndex = 0;
72 | this.privateKeyLocationPanel.Title = "Private Key File Location";
73 | //
74 | // ManageKeyFilesDialog
75 | //
76 | this.AcceptButton = this.okButton;
77 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
78 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
79 | this.CancelButton = this.cancelButton;
80 | this.ClientSize = new System.Drawing.Size(542, 177);
81 | this.Controls.Add(this.okButton);
82 | this.Controls.Add(this.cancelButton);
83 | this.Controls.Add(this.privateKeyLocationPanel);
84 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
85 | this.Margin = new System.Windows.Forms.Padding(2);
86 | this.MaximizeBox = false;
87 | this.MinimizeBox = false;
88 | this.Name = "ManageKeyFilesDialog";
89 | this.ShowInTaskbar = false;
90 | this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
91 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
92 | this.Text = "Manage Private Key File";
93 | this.ResumeLayout(false);
94 |
95 | }
96 |
97 | #endregion
98 |
99 | private KeyLocationPanel privateKeyLocationPanel;
100 | private System.Windows.Forms.Button cancelButton;
101 | private System.Windows.Forms.Button okButton;
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/KeeAgent/KeeAgentColumnProvider.cs:
--------------------------------------------------------------------------------
1 | //
2 | // KeyStatusColumnProvider.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2014 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.Diagnostics;
24 | using System.Linq;
25 | using System.Windows.Forms;
26 |
27 | using dlech.SshAgentLib;
28 | using KeePass.UI;
29 | using SshAgentLib.Keys;
30 |
31 | namespace KeeAgent
32 | {
33 | class KeeAgentColumnProvider : ColumnProvider, IDisposable
34 | {
35 | const string sshKeyStatusColumnName = "SSH Key Status";
36 | readonly string[] columnNames = {
37 | sshKeyStatusColumnName
38 | };
39 |
40 | KeeAgentExt ext;
41 |
42 | public override string[] ColumnNames {
43 | get { return columnNames.ToArray(); }
44 | }
45 |
46 | public KeeAgentColumnProvider(KeeAgentExt ext)
47 | {
48 | if (ext == null)
49 | throw new ArgumentNullException("ext");
50 | this.ext = ext;
51 | ext.agent.KeyAdded += Agent_KeyAddedOrRemoved;
52 | ext.agent.KeyRemoved += Agent_KeyAddedOrRemoved;
53 | var agentModeAgent = ext.agent as Agent;
54 | if (agentModeAgent != null) {
55 | agentModeAgent.Locked += Agent_Locked;
56 | }
57 | }
58 |
59 | ~KeeAgentColumnProvider()
60 | {
61 | Dispose(false);
62 | }
63 |
64 | public override string GetCellData(string columnName, KeePassLib.PwEntry entry)
65 | {
66 | switch (columnName) {
67 | case sshKeyStatusColumnName:
68 | var agentModeAgent = ext.agent as Agent;
69 | if (agentModeAgent != null && agentModeAgent.IsLocked) {
70 | return "Agent Locked";
71 | }
72 | try {
73 | var key = entry.TryGetSshPublicKey();
74 |
75 | if (key == null) {
76 | return "Missing .pub file";
77 | }
78 |
79 | if (ext.agent.Contains(key)) {
80 | return "Loaded";
81 | }
82 | }
83 | catch (FormatException) {
84 | return "Error";
85 | }
86 | catch (InvalidOperationException) {
87 | return "";
88 | }
89 | catch (Exception ex) {
90 | Debug.Fail(ex.Message);
91 | return "*Error";
92 | }
93 | return "Not Loaded";
94 | }
95 | Debug.Fail(string.Format("Unknown column name: {0}", columnName));
96 | return string.Empty;
97 | }
98 |
99 | public override bool SupportsCellAction(string columnName)
100 | {
101 | switch (columnName) {
102 | case sshKeyStatusColumnName:
103 | return true;
104 | default:
105 | return false;
106 | }
107 | }
108 |
109 | public override void PerformCellAction(string columnName, KeePassLib.PwEntry entry)
110 | {
111 | switch (columnName) {
112 | case sshKeyStatusColumnName:
113 | try {
114 | var key = entry.TryGetSshPublicKey();
115 |
116 | var agentKey = ext.agent.ListKeys().SingleOrDefault(k => key.Matches(k.GetPublicKeyBlob()));
117 |
118 | if (agentKey == null) {
119 | ext.AddEntry(entry, null);
120 | }
121 | else {
122 | ext.RemoveKey(agentKey);
123 | }
124 | }
125 | catch (Exception ex) {
126 | Debug.Fail(ex.Message);
127 | }
128 | break;
129 | default:
130 | Debug.Fail(string.Format("Unsupported column: {0}", columnName));
131 | break;
132 | }
133 | }
134 |
135 | internal void Agent_KeyAddedOrRemoved(object sender, SshKeyEventArgs e)
136 | {
137 | UpdateUI();
138 | }
139 |
140 | private void Agent_Locked(object sender, Agent.LockEventArgs e)
141 | {
142 | UpdateUI();
143 | }
144 |
145 | void UpdateUI()
146 | {
147 | ext.pluginHost.MainWindow.Invoke((MethodInvoker)delegate () {
148 | // only update the entry list
149 | ext.pluginHost.MainWindow.UpdateUI(false, null, false, null, true, null, false);
150 | });
151 | }
152 |
153 | private void Dispose(bool disposing)
154 | {
155 | if (disposing) {
156 | ext.agent.KeyAdded -= Agent_KeyAddedOrRemoved;
157 | ext.agent.KeyRemoved -= Agent_KeyAddedOrRemoved;
158 | var agentModeAgent = ext.agent as Agent;
159 | if (agentModeAgent != null) {
160 | agentModeAgent.Locked -= Agent_Locked;
161 | }
162 | }
163 | }
164 |
165 | public void Dispose()
166 | {
167 | GC.SuppressFinalize(this);
168 | Dispose(true);
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/OptionsTest.cs:
--------------------------------------------------------------------------------
1 | //
2 | // OptionsTest.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.IO;
24 | using System.Reflection;
25 | using System.Windows.Forms;
26 | using KeeAgent;
27 | using KeePass.Plugins;
28 | using KeePassPluginDevTools.Control;
29 | using NUnit.Framework;
30 |
31 | namespace KeeAgentTestProject
32 | {
33 | [TestFixture]
34 | public class OptionsTest
35 | {
36 | [TestFixtureTearDown()]
37 | public static void MyClassCleanup()
38 | {
39 | KeePassControl.ExitAll();
40 | }
41 |
42 | ///
43 | /// Tests if options are saved when KeePass is closed and reopened
44 | ///
45 | [Test]
46 | public void TestOptionsPersistance()
47 | {
48 | // used for passing Options objects to/from AppDomain
49 | const string optionsPropertyName = "KEEAGENT_OPTIONS";
50 |
51 | /* test case options */
52 |
53 | bool requestedLoggingEnabled = true;
54 | string requestedLogFileName =
55 | Environment.GetEnvironmentVariable("TEMP");
56 | if (string.IsNullOrEmpty(requestedLogFileName)) {
57 | requestedLogFileName =
58 | Environment.GetEnvironmentVariable("TMP");
59 | }
60 | if (string.IsNullOrEmpty(requestedLogFileName)) {
61 | requestedLogFileName = "/tmp";
62 | }
63 | Assert.That (Directory.Exists (requestedLogFileName));
64 |
65 | // verify that requested options are not default to ensure a
66 | // valid test
67 | Options requestedOptions = new Options();
68 | Assert.AreNotEqual(requestedOptions.LoggingEnabled,
69 | requestedLoggingEnabled);
70 | Assert.AreNotEqual(requestedOptions.LogFileName,
71 | requestedLogFileName);
72 |
73 | requestedOptions.LoggingEnabled = requestedLoggingEnabled;
74 | requestedOptions.LogFileName = requestedLogFileName;
75 |
76 |
77 | /* first instance of KeePass is used to set options to
78 | * requested values */
79 |
80 | using (KeePassAppDomain testDomain1 = new KeePassAppDomain()) {
81 | testDomain1.StartKeePass(true, false, 1, true);
82 | testDomain1.SetData(optionsPropertyName, requestedOptions);
83 | testDomain1.DoCallBack(delegate()
84 | {
85 | KeePass.Program.MainForm.Invoke((MethodInvoker)delegate()
86 | {
87 | KeeAgentExt td1KeeAgentExt = new KeeAgentExt();
88 | IPluginHost td1PluginHost =
89 | KeePass.Program.MainForm.PluginHost;
90 | Options td1RequestedOptions = (Options)AppDomain
91 | .CurrentDomain.GetData(optionsPropertyName);
92 | td1KeeAgentExt.Initialize(td1PluginHost);
93 | td1KeeAgentExt.Options.Notification =
94 | td1RequestedOptions.Notification;
95 | td1KeeAgentExt.Options.LoggingEnabled =
96 | td1RequestedOptions.LoggingEnabled;
97 | td1KeeAgentExt.Options.LogFileName =
98 | td1RequestedOptions.LogFileName;
99 | var extType = td1KeeAgentExt.GetType ();
100 | var saveGlobalOptionsMethod =
101 | extType.GetMethod ("SaveGlobalOptions",
102 | BindingFlags.Instance | BindingFlags.NonPublic);
103 | saveGlobalOptionsMethod.Invoke (td1KeeAgentExt, null);
104 | td1PluginHost.MainWindow.SaveConfig();
105 | AppDomain.CurrentDomain.SetData(optionsPropertyName,
106 | td1KeeAgentExt.Options);
107 | });
108 | });
109 | }
110 |
111 | /* second instance of KeePass reads options to verify that they
112 | * were saved in the .config file */
113 |
114 | using (KeePassAppDomain testDomain2 = new KeePassAppDomain()) {
115 | testDomain2.StartKeePass(true, false, 1, false);
116 | testDomain2.DoCallBack(delegate()
117 | {
118 | KeePass.Program.MainForm.Invoke((MethodInvoker)delegate()
119 | {
120 | KeeAgentExt td2KeeAgentExt = new KeeAgentExt();
121 | IPluginHost td2PluginHost =
122 | KeePass.Program.MainForm.PluginHost;
123 | td2KeeAgentExt.Initialize(td2PluginHost);
124 | AppDomain.CurrentDomain.SetData(optionsPropertyName,
125 | td2KeeAgentExt.Options);
126 | });
127 | });
128 | Options actual = (Options)testDomain2.GetData(optionsPropertyName);
129 | Assert.AreEqual(requestedLoggingEnabled, actual.LoggingEnabled);
130 | Assert.AreEqual(requestedLogFileName, actual.LogFileName);
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/KeeAgent/UI/ManageDialog.cs:
--------------------------------------------------------------------------------
1 | //
2 | // ManageDialog.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2014 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.ComponentModel;
24 | using System.Diagnostics;
25 | using System.Drawing;
26 | using System.Windows.Forms;
27 | using dlech.SshAgentLib;
28 | using KeePassLib.Utility;
29 |
30 | namespace KeeAgent.UI
31 | {
32 | public partial class ManageDialog : Form
33 | {
34 | private KeeAgentExt mExt;
35 |
36 | public ManageDialog(KeeAgentExt aExt)
37 | {
38 | InitializeComponent();
39 |
40 | if (Type.GetType("Mono.Runtime") == null) {
41 | Icon = Properties.Resources.KeeAgent_icon;
42 | }
43 | else {
44 | Icon = Properties.Resources.KeeAgent_icon_mono;
45 |
46 | // on windows, help button is displayed in the title bar
47 | // on mono, we need to add one in the window
48 | var helpButton = new Button();
49 | helpButton.Size = new Size(25, 25);
50 | helpButton.Image = Properties.Resources.Help_png;
51 | helpButton.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
52 | helpButton.Location = new Point(10, Height - 10);
53 | helpButton.Click += (sender, e) => OnHelpRequested();
54 | var foundControls =
55 | keyInfoView.Controls.Find("buttonTableLayoutPanel", true);
56 | if (foundControls.Length > 0) {
57 | var buttonTableLayout = foundControls[0];
58 | var buttonTableLayoutParent = buttonTableLayout.Parent;
59 | buttonTableLayoutParent.Controls.Remove(buttonTableLayout);
60 | var buttonTableLayoutWrapper = new TableLayoutPanel();
61 | buttonTableLayoutWrapper.RowCount = 1;
62 | buttonTableLayoutWrapper.ColumnCount = 2;
63 | buttonTableLayoutWrapper.Anchor =
64 | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom;
65 | buttonTableLayoutWrapper.Width = keyInfoView.dataGridView.Width;
66 | buttonTableLayoutWrapper.Height = helpButton.Height + 8;
67 | buttonTableLayoutWrapper.Controls.Add(helpButton);
68 | buttonTableLayoutWrapper.Controls.Add(buttonTableLayout);
69 | buttonTableLayoutParent.Controls.Add(buttonTableLayoutWrapper);
70 | }
71 | }
72 |
73 | // update title depending on Agent Mode
74 | mExt = aExt;
75 | if (mExt.agent is Agent) {
76 | Text += Translatable.TitleSuffixAgentMode;
77 | }
78 | else {
79 | Text += Translatable.TitleSuffixClientMode;
80 | }
81 | keyInfoView.SetAgent(mExt.agent);
82 | }
83 |
84 | protected override void OnShown(EventArgs e)
85 | {
86 | base.OnShown(e);
87 | keyInfoView.dataGridView.ClearSelection();
88 | }
89 |
90 | private void addButtonFromFileMenuItem_Click(object sender, EventArgs e)
91 | {
92 | keyInfoView.ShowFileOpenDialog();
93 | }
94 |
95 | private void addButtonFromKeePassMenuItem_Click(object sender, EventArgs e)
96 | {
97 | var openDatabaseCount =
98 | mExt.pluginHost.MainWindow.DocumentManager.GetOpenDatabases().Count;
99 | if (openDatabaseCount == 0) {
100 | MessageService.ShowWarning("No open databases found.",
101 | "Please open or unlock a database and then try again.");
102 | return;
103 | }
104 |
105 | var showConstraintControls = !(mExt.agent is PageantClient);
106 | var entryPicker =
107 | new EntryPickerDialog(mExt, showConstraintControls);
108 | var result = entryPicker.ShowDialog(ParentForm);
109 | if (result == DialogResult.OK) {
110 | try {
111 | mExt.AddEntry(entryPicker.SelectedEntry, entryPicker.Constraints);
112 | }
113 | catch (Exception) {
114 | // error message already shown
115 | }
116 | }
117 | if (mExt.agent is AgentClient) {
118 | keyInfoView.ReloadKeyListView();
119 | }
120 | }
121 |
122 | private void keyInfoView_AddFromFileHelpRequested(object sender, EventArgs e)
123 | {
124 | Process.Start(Properties.Resources.WebHelpAddFromFile);
125 | }
126 |
127 | private void ManageDialog_HelpRequested(object sender, HelpEventArgs hlpevent)
128 | {
129 | OnHelpRequested();
130 | }
131 |
132 | private void ManageDialog_HelpButtonClicked(object sender, CancelEventArgs e)
133 | {
134 | OnHelpRequested();
135 | e.Cancel = true;
136 | }
137 |
138 | private void OnHelpRequested()
139 | {
140 | Process.Start(Properties.Resources.WebHelpKeeAgentManager);
141 | }
142 |
143 | private void ManageDialog_KeyDown(object sender, KeyEventArgs e)
144 | {
145 | if (e.KeyCode == Keys.Escape) {
146 | e.Handled = true;
147 | Close();
148 | }
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/KeeAgent/UI/EntryPickerDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/KeeAgent/UI/ManageKeyFileDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # To learn more about .editorconfig see https://aka.ms/editorconfigdocs
2 | ###############################
3 | # Core EditorConfig Options #
4 | ###############################
5 |
6 | root = true
7 |
8 | # All files
9 | [*]
10 | indent_style = space
11 |
12 | # Code files
13 | [*.{cs,csx,vb,vbx}]
14 | indent_size = 2
15 | insert_final_newline = true
16 | trim_trailing_whitespace = true
17 | charset = utf-8-bom
18 |
19 | ###############################
20 | # .NET Coding Conventions #
21 | ###############################
22 |
23 | [*.{cs,vb}]
24 | # Organize usings
25 | dotnet_sort_system_directives_first = true
26 | dotnet_separate_import_directive_groups = false
27 |
28 | # this. preferences
29 | dotnet_style_qualification_for_field = false:silent
30 | dotnet_style_qualification_for_property = false:silent
31 | dotnet_style_qualification_for_method = false:silent
32 | dotnet_style_qualification_for_event = false:silent
33 |
34 | # Language keywords vs BCL types preferences
35 | dotnet_style_predefined_type_for_locals_parameters_members = true:silent
36 | dotnet_style_predefined_type_for_member_access = true:silent
37 |
38 | # Parentheses preferences
39 | dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
40 | dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
41 | dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
42 | dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
43 |
44 | # Modifier preferences
45 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
46 | dotnet_style_readonly_field = true:suggestion
47 |
48 | # Expression-level preferences
49 | dotnet_style_object_initializer = true:suggestion
50 | dotnet_style_collection_initializer = true:suggestion
51 | dotnet_style_explicit_tuple_names = true:suggestion
52 | dotnet_style_null_propagation = true:suggestion
53 | dotnet_style_coalesce_expression = true:suggestion
54 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
55 | dotnet_style_prefer_inferred_tuple_names = true:suggestion
56 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
57 | dotnet_style_prefer_auto_properties = true:silent
58 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
59 | dotnet_style_prefer_conditional_expression_over_return = true:silent
60 |
61 | ###############################
62 | # Naming Conventions #
63 | ###############################
64 |
65 | # Style Definitions
66 | dotnet_naming_style.pascal_case_style.capitalization = pascal_case
67 |
68 | # Use PascalCase for constant fields
69 | dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
70 | dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
71 | dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
72 | dotnet_naming_symbols.constant_fields.applicable_kinds = field
73 | dotnet_naming_symbols.constant_fields.applicable_accessibilities = *
74 | dotnet_naming_symbols.constant_fields.required_modifiers = const
75 |
76 | ###############################
77 | # C# Code Style Rules #
78 | ###############################
79 |
80 | [*.cs]
81 | # var preferences
82 | csharp_style_var_for_built_in_types = true:silent
83 | csharp_style_var_when_type_is_apparent = true:silent
84 | csharp_style_var_elsewhere = true:silent
85 |
86 | # Expression-bodied members
87 | csharp_style_expression_bodied_methods = false:silent
88 | csharp_style_expression_bodied_constructors = false:silent
89 | csharp_style_expression_bodied_operators = false:silent
90 | csharp_style_expression_bodied_properties = true:silent
91 | csharp_style_expression_bodied_indexers = true:silent
92 | csharp_style_expression_bodied_accessors = true:silent
93 |
94 | # Pattern-matching preferences
95 | csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
96 | csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
97 |
98 | # Null-checking preferences
99 | csharp_style_throw_expression = true:suggestion
100 | csharp_style_conditional_delegate_call = true:suggestion
101 |
102 | # Modifier preferences
103 | csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
104 |
105 | # Expression-level preferences
106 | csharp_prefer_braces = true:silent
107 | csharp_style_deconstructed_variable_declaration = true:suggestion
108 | csharp_prefer_simple_default_expression = true:suggestion
109 | csharp_style_pattern_local_over_anonymous_function = true:suggestion
110 | csharp_style_inlined_variable_declaration = true:suggestion
111 |
112 | ###############################
113 | # C# Formatting Rules #
114 | ###############################
115 |
116 | # New line preferences
117 | csharp_new_line_before_open_brace = methods, types
118 | csharp_new_line_before_else = true
119 | csharp_new_line_before_catch = true
120 | csharp_new_line_before_finally = true
121 | csharp_new_line_before_members_in_object_initializers = true
122 | csharp_new_line_before_members_in_anonymous_types = true
123 | csharp_new_line_between_query_expression_clauses = true
124 |
125 | # Indentation preferences
126 | csharp_indent_case_contents = true
127 | csharp_indent_switch_labels = true
128 | csharp_indent_labels = flush_left
129 |
130 | # Space preferences
131 | csharp_space_after_cast = false
132 | csharp_space_after_keywords_in_control_flow_statements = true
133 | csharp_space_between_method_call_parameter_list_parentheses = false
134 | csharp_space_between_method_declaration_parameter_list_parentheses = false
135 | csharp_space_between_parentheses = false
136 | csharp_space_before_colon_in_inheritance_clause = true
137 | csharp_space_after_colon_in_inheritance_clause = true
138 | csharp_space_around_binary_operators = before_and_after
139 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
140 | csharp_space_between_method_call_name_and_opening_parenthesis = false
141 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
142 | csharp_space_after_comma = true
143 | csharp_space_after_dot = false
144 |
145 | # Wrapping preferences
146 | csharp_preserve_single_line_statements = true
147 | csharp_preserve_single_line_blocks = true
148 |
--------------------------------------------------------------------------------
/KeeAgent/UI/DecryptProgressDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
--------------------------------------------------------------------------------
/KeeAgent/UI/HostKeysDialog.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 335, 17
122 |
123 |
124 | 17, 17
125 |
126 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/IOProtocolExtTest.cs:
--------------------------------------------------------------------------------
1 | //
2 | // OptionsTest.cs
3 | //
4 | // Author(s):
5 | // David Lechner
6 | //
7 | // Copyright (C) 2012-2013 David Lechner
8 | //
9 | // This program is free software; you can redistribute it and/or
10 | // modify it under the terms of the GNU General Public License
11 | // as published by the Free Software Foundation; either version 2
12 | // of the License, or (at your option) any later version.
13 | //
14 | // This program is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this program; if not, see
21 |
22 | using System;
23 | using System.Collections.Generic;
24 | using System.IO;
25 | using System.Reflection;
26 | using System.Security;
27 | using System.Threading;
28 | using System.Windows.Forms;
29 | using dlech.SshAgentLib;
30 | using IOProtocolExt;
31 | using KeeAgent;
32 | using KeePass.Plugins;
33 | using KeePassLib.Serialization;
34 | using KeePassPluginDevTools.Control;
35 | using NUnit.Framework;
36 |
37 | namespace KeeAgentTestProject
38 | {
39 | [TestFixture]
40 | public class IOProtocolExtTest
41 | {
42 |
43 | [TestFixtureSetUp()]
44 | public static void Setup()
45 | {
46 | // copy WinSCP to working directory
47 |
48 | string solutionDir = Path.GetFullPath(
49 | Path.Combine(Environment.CurrentDirectory, "..", "..", ".."));
50 | string winSCPSourceDir = Path.Combine(solutionDir, "lib", "IOProtocolExt",
51 | "WinSCP");
52 |
53 | Assert.IsTrue(File.Exists(Path.Combine(winSCPSourceDir, "WinSCP.exe")));
54 | Assert.IsTrue(File.Exists(Path.Combine(winSCPSourceDir, "WinSCP.com")));
55 |
56 | Assembly assembly = Assembly.GetAssembly(typeof(KeePass.Program));
57 | string keepassDir = Path.GetDirectoryName(assembly.Location);
58 |
59 | string winSCPDestDir = Path.Combine(keepassDir, "IOProtocolExt_WinSCP");
60 | if (Directory.Exists(winSCPDestDir)) {
61 | Directory.Delete(winSCPDestDir, true);
62 | int count = 0;
63 | while (Directory.Exists(winSCPDestDir)) {
64 | // wait for directory to delete
65 | count++;
66 | Assert.IsTrue(count < 20,
67 | "Failed to delete IOProtocolExt_WinSCP folder.");
68 | Thread.Sleep(100);
69 | }
70 | }
71 | Directory.CreateDirectory(winSCPDestDir);
72 | foreach (string filePath in Directory.GetFiles(winSCPSourceDir)) {
73 | string fileName = Path.GetFileName(filePath);
74 | string sourceFile = Path.Combine(winSCPSourceDir, fileName);
75 | string destFile = Path.Combine(winSCPDestDir, fileName);
76 | File.Copy(sourceFile, destFile);
77 | }
78 | }
79 |
80 | [TestFixtureTearDown()]
81 | public static void TearDown()
82 | {
83 | KeePassControl.ExitAll();
84 | }
85 |
86 | ///
87 | /// Tests interaction of KeeAgent with IOProtocolExt
88 | ///
89 | [Test]
90 | public void TestIOProtocolExt()
91 | {
92 | using (KeePassAppDomain testDomain1 = new KeePassAppDomain()) {
93 | testDomain1.StartKeePass(true, false, 1, true);
94 | testDomain1.DoCallBack(delegate()
95 | {
96 | KeePass.Program.MainForm.Invoke((MethodInvoker)delegate()
97 | {
98 | /* initialize plugins */
99 |
100 | KeeAgentExt td1KeeAgentExt = new KeeAgentExt();
101 | IOProtocolExtExt td1IOProtocolExt = new IOProtocolExtExt();
102 |
103 | IPluginHost td1PluginHost = KeePass.Program.MainForm.PluginHost;
104 | td1KeeAgentExt.Initialize(td1PluginHost);
105 | td1IOProtocolExt.Initialize(td1PluginHost);
106 | KeePass.Program.MainForm.FormClosing += delegate(
107 | Object source, FormClosingEventArgs args)
108 | {
109 | td1KeeAgentExt.Terminate();
110 | td1IOProtocolExt.Terminate();
111 | };
112 |
113 | var extType = td1KeeAgentExt.GetType ();
114 | var mAgentField = extType.GetField ("mAgent",
115 | BindingFlags.Instance | BindingFlags.NonPublic);
116 | var agent = mAgentField.GetValue (td1KeeAgentExt) as IAgent;
117 |
118 | // test not valid in client mode
119 | Assert.That(agent, Is.AssignableTo());
120 |
121 | // override confirm callback so we don't have to click OK
122 | (agent as Agent).ConfirmUserPermissionCallback =
123 | delegate(ISshKey aKey)
124 | {
125 | return true;
126 | };
127 |
128 | /* load ssh key */
129 | var keyFileDir = Path.GetFullPath (Path.Combine (
130 | "..", "..", "..", "SshAgentLib", "SshAgentLibTests", "Resources"));
131 | var keyFilePath = Path.Combine(keyFileDir, "rsa_with_passphrase");
132 | Assert.That(File.Exists(keyFilePath), "Cannot locate key file: " + keyFilePath);
133 |
134 | KeyFormatter.GetPassphraseCallback getPassphraseCallback =
135 | delegate()
136 | {
137 | var passphrase = "passphrase";
138 | var securePassphrase = new SecureString();
139 | foreach (char c in passphrase) {
140 | securePassphrase.AppendChar(c);
141 | }
142 | return securePassphrase;
143 | };
144 | var constraints = new List();
145 | constraints.addConfirmConstraint();
146 | agent.AddKeyFromFile(keyFilePath, getPassphraseCallback, constraints);
147 |
148 | /* run test */
149 | IOConnectionInfo ioConnectionInfo = new IOConnectionInfo();
150 | ioConnectionInfo.Path = "sftp://satest/test.kdbx";
151 | ioConnectionInfo.UserName = "tc";
152 | bool fileExists = IOConnection.FileExists(ioConnectionInfo);
153 | Assert.IsTrue(fileExists, "Is satest VM running?");
154 |
155 | /* the problem we are checking for is that IOConnection.FileExists
156 | * does not lock up. Originally, in KeeAgent, WinPageant ran on main
157 | * thread and caused lock-up here. So, we are looking to see if the
158 | * test times out or not. */
159 | });
160 | });
161 | }
162 | }
163 |
164 | }
165 | }
166 |
--------------------------------------------------------------------------------
/KeeAgent/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace KeeAgent.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KeeAgent.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized resource of type System.Drawing.Bitmap.
65 | ///
66 | internal static System.Drawing.Bitmap Help_png {
67 | get {
68 | object obj = ResourceManager.GetObject("Help_png", resourceCulture);
69 | return ((System.Drawing.Bitmap)(obj));
70 | }
71 | }
72 |
73 | ///
74 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
75 | ///
76 | internal static System.Drawing.Icon KeeAgent_icon {
77 | get {
78 | object obj = ResourceManager.GetObject("KeeAgent_icon", resourceCulture);
79 | return ((System.Drawing.Icon)(obj));
80 | }
81 | }
82 |
83 | ///
84 | /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
85 | ///
86 | internal static System.Drawing.Icon KeeAgent_icon_mono {
87 | get {
88 | object obj = ResourceManager.GetObject("KeeAgent_icon_mono", resourceCulture);
89 | return ((System.Drawing.Icon)(obj));
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized resource of type System.Drawing.Bitmap.
95 | ///
96 | internal static System.Drawing.Bitmap KeeAgentIcon_png {
97 | get {
98 | object obj = ResourceManager.GetObject("KeeAgentIcon_png", resourceCulture);
99 | return ((System.Drawing.Bitmap)(obj));
100 | }
101 | }
102 |
103 | ///
104 | /// Looks up a localized string similar to https://keeagent.readthedocs.io/en/v0.12.1/usage/keeagent-manager.html.
105 | ///
106 | internal static string WebHelpAddFromFile {
107 | get {
108 | return ResourceManager.GetString("WebHelpAddFromFile", resourceCulture);
109 | }
110 | }
111 |
112 | ///
113 | /// Looks up a localized string similar to https://keeagent.readthedocs.io/en/v0.12.1/usage/options.html.
114 | ///
115 | internal static string WebHelpDatabaseSettings {
116 | get {
117 | return ResourceManager.GetString("WebHelpDatabaseSettings", resourceCulture);
118 | }
119 | }
120 |
121 | ///
122 | /// Looks up a localized string similar to https://keeagent.readthedocs.io/en/v0.12.1/usage/options.html#entry-settings.
123 | ///
124 | internal static string WebHelpEntryOptions {
125 | get {
126 | return ResourceManager.GetString("WebHelpEntryOptions", resourceCulture);
127 | }
128 | }
129 |
130 | ///
131 | /// Looks up a localized string similar to https://keeagent.readthedocs.io/en/v0.12.1/usage/keeagent-manager.html.
132 | ///
133 | internal static string WebHelpEntryPicker {
134 | get {
135 | return ResourceManager.GetString("WebHelpEntryPicker", resourceCulture);
136 | }
137 | }
138 |
139 | ///
140 | /// Looks up a localized string similar to https://keeagent.readthedocs.io/en/v0.12.1/usage/options.html#global-options.
141 | ///
142 | internal static string WebHelpGlobalOptions {
143 | get {
144 | return ResourceManager.GetString("WebHelpGlobalOptions", resourceCulture);
145 | }
146 | }
147 |
148 | ///
149 | /// Looks up a localized string similar to https://keeagent.readthedocs.io.
150 | ///
151 | internal static string WebHelpHome {
152 | get {
153 | return ResourceManager.GetString("WebHelpHome", resourceCulture);
154 | }
155 | }
156 |
157 | ///
158 | /// Looks up a localized string similar to https://keeagent.readthedocs.io/en/v0.12.1/usage/keeagent-manager.html.
159 | ///
160 | internal static string WebHelpKeeAgentManager {
161 | get {
162 | return ResourceManager.GetString("WebHelpKeeAgentManager", resourceCulture);
163 | }
164 | }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/KeeAgentTestProject/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
122 | ..\Resources\withoutPassphrase.ppk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
123 |
124 |
125 | ..\Resources\withPassphrase.ppk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
126 |
127 |
128 | ..\Resources\dsa.ppk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
129 |
130 |
131 | ..\Resources\4095-bits.ppk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
132 |
133 |
134 | ..\Resources\ssh2-rsa-non-ascii-passphrase.ppk;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
135 |
136 |
--------------------------------------------------------------------------------