]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: ssh-add support for U2F/FIDO keys
authordjm@openbsd.org <djm@openbsd.org>
Thu, 31 Oct 2019 21:19:56 +0000 (21:19 +0000)
committerDamien Miller <djm@mindrot.org>
Thu, 31 Oct 2019 22:46:09 +0000 (09:46 +1100)
OpenBSD-Commit-ID: 7f88a5181c982687afedf3130c6ab2bba60f7644

ssh-add.1
ssh-add.c

index d4e1c603be6d4a15cf14bd36e940dc2ff3f00497..9dc44fa74dca9bca603196d0a79da80f7fbc5df1 100644 (file)
--- a/ssh-add.1
+++ b/ssh-add.1
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ssh-add.1,v 1.69 2019/01/21 12:53:35 djm Exp $
+.\"    $OpenBSD: ssh-add.1,v 1.70 2019/10/31 21:19:56 djm Exp $
 .\"
 .\" Author: Tatu Ylonen <ylo@cs.hut.fi>
 .\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
 .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd $Mdocdate: January 21 2019 $
+.Dd $Mdocdate: October 31 2019 $
 .Dt SSH-ADD 1
 .Os
 .Sh NAME
@@ -46,6 +46,7 @@
 .Op Fl cDdkLlqvXx
 .Op Fl E Ar fingerprint_hash
 .Op Fl t Ar life
+.Op Fl S Ar provider
 .Op Ar
 .Nm ssh-add
 .Fl s Ar pkcs11
@@ -134,6 +135,11 @@ Be quiet after a successful operation.
 .It Fl s Ar pkcs11
 Add keys provided by the PKCS#11 shared library
 .Ar pkcs11 .
+.It Fl S Ar provider
+Specifies a path to a security key provider library that will be used when
+adding any security key-hosted keys, overriding the default of using the
+.Ev "SSH_SK_PROVIDER"
+environment variable to specify a provider.
 .It Fl T Ar pubkey ...
 Tests whether the private keys that correspond to the specified
 .Ar pubkey
@@ -189,6 +195,9 @@ to make this work.)
 Identifies the path of a
 .Ux Ns -domain
 socket used to communicate with the agent.
+.It Ev SSH_SK_PROVIDER
+Specifies the path to a security key provider library used to interact with
+hardware security keys.
 .El
 .Sh FILES
 .Bl -tag -width Ds
index 2c65d0272a302caa8fcd748445125ce1afe73646..3c8849ac423d20b87aef019237df4460ba0c5997 100644 (file)
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.142 2019/10/31 21:19:15 djm Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.143 2019/10/31 21:19:56 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -77,6 +77,7 @@ static char *default_files[] = {
        _PATH_SSH_CLIENT_ID_DSA,
 #ifdef OPENSSL_HAS_ECC
        _PATH_SSH_CLIENT_ID_ECDSA,
+       _PATH_SSH_CLIENT_ID_ECDSA_SK,
 #endif
 #endif /* WITH_OPENSSL */
        _PATH_SSH_CLIENT_ID_ED25519,
@@ -191,7 +192,8 @@ delete_all(int agent_fd, int qflag)
 }
 
 static int
-add_file(int agent_fd, const char *filename, int key_only, int qflag)
+add_file(int agent_fd, const char *filename, int key_only, int qflag,
+    const char *skprovider)
 {
        struct sshkey *private, *cert;
        char *comment = NULL;
@@ -310,8 +312,16 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
                ssh_free_identitylist(idlist);
        }
 
+       if (sshkey_type_plain(private->type) != KEY_ECDSA_SK)
+               skprovider = NULL; /* Don't send constraint for other keys */
+       else if (skprovider == NULL) {
+               fprintf(stderr, "Cannot load security key %s without "
+                   "provider\n", filename);
+               goto out;
+       }
+
        if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
-           lifetime, confirm, maxsign, NULL)) == 0) {
+           lifetime, confirm, maxsign, skprovider)) == 0) {
                ret = 0;
                if (!qflag) {
                        fprintf(stderr, "Identity added: %s (%s)\n",
@@ -364,7 +374,7 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag)
        sshkey_free(cert);
 
        if ((r = ssh_add_identity_constrained(agent_fd, private, comment,
-           lifetime, confirm, maxsign, NULL)) != 0) {
+           lifetime, confirm, maxsign, skprovider)) != 0) {
                error("Certificate %s (%s) add failed: %s", certpath,
                    private->cert->key_id, ssh_err(r));
                goto out;
@@ -529,13 +539,14 @@ lock_agent(int agent_fd, int lock)
 }
 
 static int
-do_file(int agent_fd, int deleting, int key_only, char *file, int qflag)
+do_file(int agent_fd, int deleting, int key_only, char *file, int qflag,
+    const char *skprovider)
 {
        if (deleting) {
                if (delete_file(agent_fd, file, key_only, qflag) == -1)
                        return -1;
        } else {
-               if (add_file(agent_fd, file, key_only, qflag) == -1)
+               if (add_file(agent_fd, file, key_only, qflag, skprovider) == -1)
                        return -1;
        }
        return 0;
@@ -561,6 +572,7 @@ usage(void)
        fprintf(stderr, "  -s pkcs11   Add keys from PKCS#11 provider.\n");
        fprintf(stderr, "  -e pkcs11   Remove keys provided by PKCS#11 provider.\n");
        fprintf(stderr, "  -T pubkey   Test if ssh-agent can access matching private key.\n");
+       fprintf(stderr, "  -S provider Specify security key provider.\n");
        fprintf(stderr, "  -q          Be quiet after a successful operation.\n");
        fprintf(stderr, "  -v          Be more verbose.\n");
 }
@@ -571,7 +583,7 @@ main(int argc, char **argv)
        extern char *optarg;
        extern int optind;
        int agent_fd;
-       char *pkcs11provider = NULL;
+       char *pkcs11provider = NULL, *skprovider = NULL;
        int r, i, ch, deleting = 0, ret = 0, key_only = 0;
        int xflag = 0, lflag = 0, Dflag = 0, qflag = 0, Tflag = 0;
        SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
@@ -600,7 +612,9 @@ main(int argc, char **argv)
                exit(2);
        }
 
-       while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:t:")) != -1) {
+       skprovider = getenv("SSH_SK_PROVIDER");
+
+       while ((ch = getopt(argc, argv, "vklLcdDTxXE:e:M:m:qs:S:t:")) != -1) {
                switch (ch) {
                case 'v':
                        if (log_level == SYSLOG_LEVEL_INFO)
@@ -656,6 +670,9 @@ main(int argc, char **argv)
                case 's':
                        pkcs11provider = optarg;
                        break;
+               case 'S':
+                       skprovider = optarg;
+                       break;
                case 'e':
                        deleting = 1;
                        pkcs11provider = optarg;
@@ -732,7 +749,7 @@ main(int argc, char **argv)
                        if (stat(buf, &st) == -1)
                                continue;
                        if (do_file(agent_fd, deleting, key_only, buf,
-                           qflag) == -1)
+                           qflag, skprovider) == -1)
                                ret = 1;
                        else
                                count++;
@@ -742,7 +759,7 @@ main(int argc, char **argv)
        } else {
                for (i = 0; i < argc; i++) {
                        if (do_file(agent_fd, deleting, key_only,
-                           argv[i], qflag) == -1)
+                           argv[i], qflag, skprovider) == -1)
                                ret = 1;
                }
        }