diff options
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 92 |
1 files changed, 69 insertions, 23 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.155 2020/03/16 02:17:02 dtucker Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.157 2020/08/31 04:33:17 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -67,6 +67,7 @@ | |||
67 | #include "ssherr.h" | 67 | #include "ssherr.h" |
68 | #include "digest.h" | 68 | #include "digest.h" |
69 | #include "ssh-sk.h" | 69 | #include "ssh-sk.h" |
70 | #include "sk-api.h" | ||
70 | 71 | ||
71 | /* argv0 */ | 72 | /* argv0 */ |
72 | extern char *__progname; | 73 | extern char *__progname; |
@@ -111,25 +112,69 @@ clear_pass(void) | |||
111 | } | 112 | } |
112 | 113 | ||
113 | static int | 114 | static int |
115 | delete_one(int agent_fd, const struct sshkey *key, const char *comment, | ||
116 | const char *path, int qflag) | ||
117 | { | ||
118 | int r; | ||
119 | |||
120 | if ((r = ssh_remove_identity(agent_fd, key)) != 0) { | ||
121 | fprintf(stderr, "Could not remove identity \"%s\": %s\n", | ||
122 | path, ssh_err(r)); | ||
123 | return r; | ||
124 | } | ||
125 | if (!qflag) { | ||
126 | fprintf(stderr, "Identity removed: %s %s (%s)\n", path, | ||
127 | sshkey_type(key), comment); | ||
128 | } | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int | ||
133 | delete_stdin(int agent_fd, int qflag) | ||
134 | { | ||
135 | char *line = NULL, *cp; | ||
136 | size_t linesize = 0; | ||
137 | struct sshkey *key = NULL; | ||
138 | int lnum = 0, r, ret = -1; | ||
139 | |||
140 | while (getline(&line, &linesize, stdin) != -1) { | ||
141 | lnum++; | ||
142 | sshkey_free(key); | ||
143 | key = NULL; | ||
144 | line[strcspn(line, "\n")] = '\0'; | ||
145 | cp = line + strspn(line, " \t"); | ||
146 | if (*cp == '#' || *cp == '\0') | ||
147 | continue; | ||
148 | if ((key = sshkey_new(KEY_UNSPEC)) == NULL) | ||
149 | fatal("%s: sshkey_new", __func__); | ||
150 | if ((r = sshkey_read(key, &cp)) != 0) { | ||
151 | error("(stdin):%d: invalid key: %s", lnum, ssh_err(r)); | ||
152 | continue; | ||
153 | } | ||
154 | if (delete_one(agent_fd, key, cp, "(stdin)", qflag) == 0) | ||
155 | ret = 0; | ||
156 | } | ||
157 | sshkey_free(key); | ||
158 | free(line); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | static int | ||
114 | delete_file(int agent_fd, const char *filename, int key_only, int qflag) | 163 | delete_file(int agent_fd, const char *filename, int key_only, int qflag) |
115 | { | 164 | { |
116 | struct sshkey *public, *cert = NULL; | 165 | struct sshkey *public, *cert = NULL; |
117 | char *certpath = NULL, *comment = NULL; | 166 | char *certpath = NULL, *comment = NULL; |
118 | int r, ret = -1; | 167 | int r, ret = -1; |
119 | 168 | ||
169 | if (strcmp(filename, "-") == 0) | ||
170 | return delete_stdin(agent_fd, qflag); | ||
171 | |||
120 | if ((r = sshkey_load_public(filename, &public, &comment)) != 0) { | 172 | if ((r = sshkey_load_public(filename, &public, &comment)) != 0) { |
121 | printf("Bad key file %s: %s\n", filename, ssh_err(r)); | 173 | printf("Bad key file %s: %s\n", filename, ssh_err(r)); |
122 | return -1; | 174 | return -1; |
123 | } | 175 | } |
124 | if ((r = ssh_remove_identity(agent_fd, public)) == 0) { | 176 | if (delete_one(agent_fd, public, comment, filename, qflag) == 0) |
125 | if (!qflag) { | ||
126 | fprintf(stderr, "Identity removed: %s (%s)\n", | ||
127 | filename, comment); | ||
128 | } | ||
129 | ret = 0; | 177 | ret = 0; |
130 | } else | ||
131 | fprintf(stderr, "Could not remove identity \"%s\": %s\n", | ||
132 | filename, ssh_err(r)); | ||
133 | 178 | ||
134 | if (key_only) | 179 | if (key_only) |
135 | goto out; | 180 | goto out; |
@@ -149,15 +194,8 @@ delete_file(int agent_fd, const char *filename, int key_only, int qflag) | |||
149 | fatal("Certificate %s does not match private key %s", | 194 | fatal("Certificate %s does not match private key %s", |
150 | certpath, filename); | 195 | certpath, filename); |
151 | 196 | ||
152 | if ((r = ssh_remove_identity(agent_fd, cert)) == 0) { | 197 | if (delete_one(agent_fd, cert, comment, certpath, qflag) == 0) |
153 | if (!qflag) { | ||
154 | fprintf(stderr, "Identity removed: %s (%s)\n", | ||
155 | certpath, comment); | ||
156 | } | ||
157 | ret = 0; | 198 | ret = 0; |
158 | } else | ||
159 | fprintf(stderr, "Could not remove identity \"%s\": %s\n", | ||
160 | certpath, ssh_err(r)); | ||
161 | 199 | ||
162 | out: | 200 | out: |
163 | sshkey_free(cert); | 201 | sshkey_free(cert); |
@@ -311,12 +349,20 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, | |||
311 | ssh_free_identitylist(idlist); | 349 | ssh_free_identitylist(idlist); |
312 | } | 350 | } |
313 | 351 | ||
314 | if (!sshkey_is_sk(private)) | 352 | if (sshkey_is_sk(private)) { |
315 | skprovider = NULL; /* Don't send constraint for other keys */ | 353 | if (skprovider == NULL) { |
316 | else if (skprovider == NULL) { | 354 | fprintf(stderr, "Cannot load FIDO key %s " |
317 | fprintf(stderr, "Cannot load authenticator-hosted key %s " | 355 | "without provider\n", filename); |
318 | "without provider\n", filename); | 356 | goto out; |
319 | goto out; | 357 | } |
358 | if ((private->sk_flags & SSH_SK_USER_VERIFICATION_REQD) != 0) { | ||
359 | fprintf(stderr, "FIDO verify-required key %s is not " | ||
360 | "currently supported by ssh-agent\n", filename); | ||
361 | goto out; | ||
362 | } | ||
363 | } else { | ||
364 | /* Don't send provider constraint for other keys */ | ||
365 | skprovider = NULL; | ||
320 | } | 366 | } |
321 | 367 | ||
322 | if ((r = ssh_add_identity_constrained(agent_fd, private, comment, | 368 | if ((r = ssh_add_identity_constrained(agent_fd, private, comment, |