|
1 | 1 | # SSH Agent
|
2 | 2 |
|
3 |
| -An ssh agent acts as a program that holds a set of private keys and provides a way to sign |
| 3 | +An SSH agent acts as a program that holds a set of private keys and provides a way to sign |
4 | 4 | challenges with those keys, without ever letting the private keys leave the vault. These challenges
|
5 |
| -can be sign in requests for logging into a server, and in newer SSH versions, they can also be used |
6 |
| -to sign arbitrary data (git commits, but also regular files). |
| 5 | +can be sign-in requests for logging into a server and in newer SSH versions they can also be used to |
| 6 | +sign arbitrary data e.g. Git commits, but also regular files. |
7 | 7 |
|
8 | 8 | ## OS interface
|
9 | 9 |
|
10 |
| -On Unix-like systems (Mac, Linux, BSDs), the ssh-agent is provided via a Unix domain socket. The |
| 10 | +On Unix-like systems (Mac, Linux, BSDs) the `ssh-agent` is provided via a Unix domain socket. The |
11 | 11 | agent provides this socket and any application that wants to use the agent connects via this socket.
|
12 | 12 | This is done by getting the socket path from the `SSH_AUTH_SOCK` environment variable.
|
13 | 13 |
|
14 |
| -On Windows, the agent is provided via a global named pipe at `\\.\pipe\openssh-ssh-agent`. Since |
15 |
| -only a single application can act as the pipe server, the OpenSSH agent service first needs to be |
16 |
| -disabled in Windows. After which the Bitwarden desktop app can start the agent listening on this |
17 |
| -pipe. |
| 14 | +On Windows the agent is provided via a global named pipe at `\\.\pipe\openssh-ssh-agent`. Since only |
| 15 | +a single application can act as the pipe server, the OpenSSH agent service first needs to be |
| 16 | +disabled in Windows, after which the desktop app can start the agent listening on this pipe. |
18 | 17 |
|
19 |
| -## SSH Agent Protocol |
| 18 | +## SSH agent Protocol |
20 | 19 |
|
21 |
| -The ssh-agent protocol is specified at |
22 |
| -[SSH-Agent Spec](https://tools.ietf.org/html/draft-miller-ssh-agent-00). However, Bitwarden Desktop |
23 |
| -only implements a subset of this protocol, specifically the sign and list operations. List |
24 |
| -operations are always allowed by default, while sign operations require user verification. |
| 20 | +The `ssh-agent` protocol is specified as a |
| 21 | +[spec](https://tools.ietf.org/html/draft-miller-ssh-agent-00) however the desktop app only |
| 22 | +implements a subset of this protocol, specifically the sign and list operations. List operations are |
| 23 | +always allowed by default while sign operations require user verification. |
25 | 24 |
|
26 | 25 | ### Signing during login
|
27 | 26 |
|
28 |
| -When logging into a server, the client and server first exchange the set of algorithms they support |
29 |
| -for key exchange and signing. The server has a host key, which is saved locally. Since - in contrast |
30 |
| -to TLS - we don't have central authorities proving the authenticity of a server, the first time |
31 |
| -connecting to a server the client will ask the user to verify the fingerprint of the server, saving |
32 |
| -it subsequently to the `known_hosts` file. In subsequent authentication requests the client will |
| 27 | +When logging into a server the client and server first exchange the set of algorithms they support |
| 28 | +for key exchange and signing. The server has a host key which is saved locally. In contrast to TLS, |
| 29 | +we don't have central authorities proving the authenticity of a server; the first time connecting to |
| 30 | +a server the client will ask the user to verify the fingerprint of the server, saving it |
| 31 | +subsequently to the `known_hosts` file. In subsequent authentication requests the client will |
33 | 32 | compare the fingerprint against the saved one, to prevent subsequent machine-in-the-middle attacks.
|
34 | 33 |
|
35 |
| -The client and server then agree on authentication methods that they can continue with (for instance |
36 |
| -public key, password). For public keys, the client then offers the public keys to the server, and |
37 |
| -the server will reply which keys it accepts. To prevent leaking the set of keys the client has, they |
38 |
| -can additionally configure to offer specific keys to a specific server. |
| 34 | +The client and server then agree on authentication methods that they can continue with e.g. public |
| 35 | +key, password. For public keys the client then offers the public keys to the server and the server |
| 36 | +will reply which keys it accepts. To prevent leaking the set of keys the client has they can |
| 37 | +additionally configure to offer specific keys to a specific server. |
39 | 38 |
|
40 |
| -The ssh client then, for all accepted keys - one by one - asks the agent to sign the login request |
41 |
| -for that specific key. This means that if a server accepts multiple keys, the agent might be asked |
| 39 | +The SSH client then for all accepted keys, one by one, asks the agent to sign the login request for |
| 40 | +that specific key. This means that if a server accepts multiple keys the agent might be asked |
42 | 41 | multiple times to provide UV with different keys. These might be detectable by parsing the login
|
43 |
| -request to sign, since it contains the user and server host key. The sign request does not contain |
44 |
| -the IP or hostname of the server, but this could be inferred using the `known_hosts` file. |
| 42 | +request to sign since it contains the user and server host key. The sign request does not contain |
| 43 | +the IP or hostname of the server but this could be inferred using the `known_hosts` file. |
45 | 44 |
|
46 |
| -Only if public key authentication fails will it fallback to password. |
| 45 | +Only if public key authentication fails will it fall back to password. |
47 | 46 |
|
48 | 47 | ## Agent forwarding
|
49 | 48 |
|
50 |
| -Any clients can access the agent via the socket / pipe. Further SSH supports a feature called agent |
51 |
| -forwarding. Forwarding can be used to log into a remote server A, and allow that server to access |
52 |
| -server B and authenticate to it, without ever giving the keys to server A. While convenient, care |
53 |
| -has to be taken, both about which servers the agent is forwarded to, but also to always require user |
54 |
| -verification for signing operations. |
| 49 | +Any clients can access the agent via the socket / pipe. Furthermore, SSH supports a feature called |
| 50 | +agent forwarding -- forwarding can be used to log into a remote server A and allow that server to |
| 51 | +access server B and authenticate to it without ever giving the keys to server A. While convenient |
| 52 | +care has to be taken, both about which servers the agent is forwarded to, but also to always require |
| 53 | +user verification for signing operations. |
55 | 54 |
|
56 |
| -## SSH Signatures |
| 55 | +## SSH signatures |
57 | 56 |
|
58 |
| -The ssh agent can not only sign login requests but also arbitrary data. The format for these |
| 57 | +The SSH agent can not only sign login requests but also arbitrary data. The format for these |
59 | 58 | signature requests is specified at
|
60 | 59 | [`Protocol.sshsig`](https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.sshsig). During
|
61 |
| -a signature request, the desktop client detects `SSHSIG` requests and parses the namespace, passing |
62 |
| -it on to the UI to present. |
| 60 | +a signature request the desktop app detects `SSHSIG` requests and parses the namespace, passing it |
| 61 | +on to the UI to present. |
63 | 62 |
|
64 |
| -## Verifying SSH Client Processes |
| 63 | +## Verifying SSH client processes |
65 | 64 |
|
66 | 65 | In order to present details about which application is requesting access to the any SSH key,
|
67 |
| -information about the connecting process is gathered. On unix, this works via the `SO_PEERCRED` |
68 |
| -`socketopt`. This provides the PID of the connecting process. On Windows, |
| 66 | +information about the connecting process is gathered. On \*nix this works via the `SO_PEERCRED` |
| 67 | +`socketopt`; this provides the PID of the connecting process. On Windows, |
69 | 68 | [`GetNamedPipeClientPRocessId`](https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getnamedpipeclientprocessid)
|
70 | 69 | is used.
|
71 | 70 |
|
72 |
| -Using the process id, further information about the process (process name, signature, application |
73 |
| -name, application logo) can be acquired, but for now, just process name is used. Depending on the |
74 |
| -client application, the process hierarchy might look different, and the process connecting might be |
75 |
| -a one-time child process of the application that the user expects to connect. |
| 71 | +Using the process ID further information about the process (process name, signature, application |
| 72 | +name, and application logo) can be acquired, but for now just the process name is used. Depending on |
| 73 | +the client application the process hierarchy might look different and the process connecting might |
| 74 | +be a one-time child process of the application that the user expects to connect. |
76 | 75 |
|
77 |
| -When agent forwarding is used, an `EXTENSION` command is sent to the client with the |
78 |
| -`extension_name` set to |
| 76 | +When agent forwarding is used an `EXTENSION` command is sent to the client with the `extension_name` |
| 77 | +set to |
79 | 78 | [`session-bind@openssh.com`](https://raw.githubusercontent.com/openssh/openssh-portable/refs/heads/master/PROTOCOL.agent).
|
80 |
| -This is detected and noted on the connection, so that the clients can handle this appropriately. |
| 79 | +This is detected and noted on the connection so that the clients can handle this appropriately. |
81 | 80 |
|
82 |
| -## Architecture in Bitwarden Desktop |
| 81 | +## Architecture in the desktop app |
83 | 82 |
|
84 |
| -Bitwarden desktop provides an ssh-agent implementation that provides signing functionality to |
85 |
| -applications running on the system. Since the applications running on the system, and remote |
| 83 | +The desktop app provides an `ssh-agent` implementation that provides signing functionality to |
| 84 | +applications running on the system. Since the applications running on the system and remote |
86 | 85 | applications when forwarding the agent are untrusted, the agent requires user verification for
|
87 |
| -signing operations. In total, the ssh agent feature consists of multiple components: |
| 86 | +signing operations. In total, the SSH agent feature consists of multiple components: |
88 | 87 |
|
89 |
| -- [Desktop Native] The agent itself, handling the socket / pipe and signing requests |
90 |
| -- [Desktop Native] A key store that holds the private keys and corresponding cipher id's for the |
91 |
| - keys of the active and unlocked account |
92 |
| -- [Desktop Native & Desktop Electron] A communication layer that allows the native module to show UV |
93 |
| - prompts in the UI |
94 |
| -- [Desktop Electron] A UI component that shows the UV prompts and allows the user to accept or deny |
95 |
| - the signing request |
| 88 | +- **Desktop Native:** the agent itself, handling the socket / pipe and signing requests. |
| 89 | +- **Desktop Native:** a key store that holds the private keys and corresponding cipher IDs for the |
| 90 | + keys of the active and unlocked account. |
| 91 | +- **Desktop Native and Electron:** a communication layer that allows the native module to show UV |
| 92 | + prompts in the UI. |
| 93 | +- **Desktop Electron:** a UI component that shows the UV prompts and allows the user to accept or |
| 94 | + deny the signing request. |
96 | 95 |
|
97 | 96 | The key store is synced on an interval from the renderer process and receives the decrypted private
|
98 |
| -keys from the vault ciphers. When locking / changing users, the private keys of the keystore are |
99 |
| -wiped. When locking, the public keys are kept, so that listing still works. This means that when |
100 |
| -locked after unlocking once, the correct ssh key for a server can be chosen, and a signing request |
101 |
| -made. This then prompts the user to unlock their vault in order to approve the request. |
| 97 | +keys from the vault ciphers. When locking / changing users the private keys of the keystore are |
| 98 | +wiped. When locking the public keys are kept so that listing still works -- this means that when |
| 99 | +locked after unlocking once the correct SSH key for a server can be chosen and a signing request |
| 100 | +made; this then prompts the user to unlock their vault in order to approve the request. |
0 commit comments