strongbox-password-safe / Strongbox

A KeePass/Password Safe Client for iOS and OS X
https://strongboxsafe.com
GNU Affero General Public License v3.0
1.3k stars 100 forks source link

Support for SSH certificates for SFTP connections #663

Open jacobgreenleaf opened 1 year ago

jacobgreenleaf commented 1 year ago

It would be nice if SSH certificates were supported. It doesn't appear that NMSSH supports them either.

Steps to reproduce:

  1. Set up a server with an authorized_keys entry, generate SSH key / certificate, etc:
cert-authority ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOsnMdx6l51DRmpiiwkYfV2Q4188uNmUpt2tlhSPxMDx
$ ssh-keygen -l -f ca_ed25519 
256 SHA256:2T/jkmqk3aDU8VdjSggGkFKL9QkyYaadmR4jAwpufxo ca (ED25519)
$ ssh-keygen -y -f ca_ed25519
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOsnMdx6l51DRmpiiwkYfV2Q4188uNmUpt2tlhSPxMDx ca
$ ssh-keygen -l -f iphone-12-mini
3072 SHA256:JL8FiEPY/mM/q46zsAukgVBcK1V6Lyz/su20abcaJ88 iphone12mini (RSA)
$ ssh-keygen -L -f iphone-12-mini-cert.pub 
iphone-12-mini-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:JL8FiEPY/mM/q46zsAukgVBcK1V6Lyz/su20abcaJ88
        Signing CA: ED25519 SHA256:2T/jkmqk3aDU8VdjSggGkFKL9QkyYaadmR4jAwpufxo (using ssh-ed25519)
        Key ID: "iphone-12-mini"
        Serial: 4
        Valid: from 2022-12-04T17:54:00 to 2023-01-03T17:55:58
        Principals: (none)
        Critical Options: (none)
        Extensions: 
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
  1. Validate that certificate is accepted using ssh:
$ ssh -i iphone-12-mini jacob@server "echo Hello!"
Hello!
$ 
  1. Copy SSH certificate and private key over to device & configure Strongbox SFTP to use the private key from Files, with the OpenSSH convention of having the certificate present at keyname-cert.pub

  2. Connect (Test & Save)

Expected result: Connects OK

Actual result: auth fail

iOS app: Pro 1.57.1

OpenSSH server logs below. It appears to be using the key as-is and not looking for the -cert.pub certificate file.

Dec 05 02:06:24 server sshd[2141870]: debug1: Local version string SSH-2.0-OpenSSH_9.1
Dec 05 02:06:24 server sshd[2141870]: debug1: Remote protocol version 2.0, remote software version libssh2_1.10.0
...
Dec 05 02:06:24 server sshd[2141870]: debug1: userauth_pubkey: publickey test pkalg ssh-rsa pkblob RSA SHA256:JL8FiEPY/mM/q46zsAukgVBcK1V6Lyz/su20abcaJ88 [preauth]
...
Dec 05 02:06:24 server sshd[2141870]: Failed publickey for jacob from 10.0.0.66 port 64699 ssh2: RSA SHA256:JL8FiEPY/mM/q46zsAukgVBcK1V6Lyz/su20abcaJ88
Dec 05 02:06:43 server sshd[2133659]: fatal: Timeout before authentication for 10.0.0.66 port 64698

Compared to ssh -i iphone-12-mini jacob@server:

Dec 05 02:14:52 server sshd[2153516]: debug1: Local version string SSH-2.0-OpenSSH_9.1
Dec 05 02:14:52 server sshd[2153516]: debug1: Remote protocol version 2.0, remote software version OpenSSH_9.0
...
Dec 05 02:14:53 server sshd[2153516]: debug1: userauth_pubkey: publickey test pkalg rsa-sha2-512-cert-v01@openssh.com pkblob RSA-CERT SHA256:JL8FiEPY/mM/q46zsAukgVBcK1V6Lyz/su20abcaJ88 CA ED25519 SHA2>
...
Dec 05 02:14:53 server sshd[2153516]: debug1: /etc/ssh/authorized_keys.d/jacob:1: matching CA found: ED25519 SHA256:2T/jkmqk3aDU8VdjSggGkFKL9QkyYaadmR4jAwpufxo
...
Dec 05 02:14:53 server sshd[2153516]: Accepted certificate ID "iphone-12-mini" (serial 4) signed by CA ED25519 SHA256:2T/jkmqk3aDU8VdjSggGkFKL9QkyYaadmR4jAwpufxo found at /etc/ssh/authorized_keys.d/ja>
...
Dec 05 02:14:53 server sshd[2153516]: Accepted publickey for jacob from 100.64.0.6 port 53278 ssh2: RSA-CERT SHA256:JL8FiEPY/mM/q46zsAukgVBcK1V6Lyz/su20abcaJ88 ID iphone-12-mini (serial 4) CA ED25519 >
...
Dec 05 02:14:53 server sshd[2153516]: pam_unix(sshd:session): session opened for user jacob(uid=1000) by (uid=0)
strongbox-mark commented 1 year ago

Hi there, I'm not familiar with SSH Certificates at all. Is this a new proposal? Do you know of any other clients supporting this technology? We use libssh2 and openssl, do you happen to know if these libraries support these certificates? Thanks.

jacobgreenleaf commented 1 year ago

Hi there, I'm not familiar with SSH Certificates at all. Is this a new proposal?

SSH certificates are not new (I believe first added in OpenSSH 5.4 around March 2010), but they have perhaps gained a bit of popularity in recent years.

The key difference is that you continue to generate a public/private key pair as before, but when you connect to the server you also provide the certificate in addition. Here are a few things that describe it in more detail from a user perspective:

It might be related to #522 but I wanted to open this ticket separately. I think SSH certificates can be provided by ssh-agent (also part of OpenSSH), but I don't think ssh-agent is present on iOS. That is, it depends on what "SSH agent support" means. If it means that you can push keys that are stored in the KeePass database into ssh-agent, then it's a different issue. If it means that when using Strongbox on some platform where you also are using ssh-agent, that the keys you use for SFTP authentication can be fetched from ssh-agent (such as if you leave both the password and private key fields empty), then that may be applicable (see https://www.libssh2.org/libssh2_agent_userauth.html)

Do you know of any other clients supporting this technology? We use libssh2 and openssl, do you happen to know if these libraries support these certificates?

They're unrelated to SSL except that they're a similar idea (PKI / certificates) but SSH certificates are much simpler than X.509.

libssh2 does support SSH certificates, at least as of the latest release (ECDSA as of the latest 1.10 release in May 2021, and RSA as of this June although unreleased. It looks like you are supposed to pass the certificate as the public key? see https://github.com/libssh2/libssh2/pull/570/files#diff-ad4324fdd7637be818cceffb6bc77116b79729b326f4983d86c40cf4afb815a5R10. It's definitely confusing as far as the API goes though, and I'm not familiar with it (e.g. https://github.com/libssh2/libssh2/issues/652)

I brought up NMSSH since you use that which wraps libssh2, but I think it may just work if you do as above (passing the certificate as public key), since NMSSH does have APIs for passing down both the public and private key separately? Unclear to me.

See also for example:

strongbox-mark commented 1 year ago

OK, thanks for the extra info. We can add to our backlog.