diff options
author | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 1999-11-25 00:26:21 +1100 |
commit | 95def09838fc61b37b6ea7cd5c234a465b4b129b (patch) | |
tree | 042744f76f40a326b873cb1c3690a6d7d966bc3e /ssh-add.c | |
parent | 4d2f15f895f4c795afc008aeff3fd2ceffbc44f4 (diff) |
- Merged very large OpenBSD source code reformat
- OpenBSD CVS updates
- [channels.c cipher.c compat.c log-client.c scp.c serverloop.c]
[ssh.h sshd.8 sshd.c]
syslog changes:
* Unified Logmessage for all auth-types, for success and for failed
* Standard connections get only ONE line in the LOG when level==LOG:
Auth-attempts are logged only, if authentication is:
a) successfull or
b) with passwd or
c) we had more than AUTH_FAIL_LOG failues
* many log() became verbose()
* old behaviour with level=VERBOSE
- [readconf.c readconf.h ssh.1 ssh.h sshconnect.c sshd.c]
tranfer s/key challenge/response data in SSH_SMSG_AUTH_TIS_CHALLENGE
messages. allows use of s/key in windows (ttssh, securecrt) and
ssh-1.2.27 clients without 'ssh -v', ok: niels@
- [sshd.8]
-V, for fallback to openssh in SSH2 compatibility mode
- [sshd.c]
fix sigchld race; cjc5@po.cwru.edu
Diffstat (limited to 'ssh-add.c')
-rw-r--r-- | ssh-add.c | 515 |
1 files changed, 248 insertions, 267 deletions
@@ -1,20 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | 2 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | |
3 | ssh-add.c | 3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | 4 | * All rights reserved | |
5 | Author: Tatu Ylonen <ylo@cs.hut.fi> | 5 | * Created: Thu Apr 6 00:52:24 1995 ylo |
6 | 6 | * Adds an identity to the authentication server, or removes an identity. | |
7 | Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 7 | */ |
8 | All rights reserved | ||
9 | |||
10 | Created: Thu Apr 6 00:52:24 1995 ylo | ||
11 | |||
12 | Adds an identity to the authentication server, or removes an identity. | ||
13 | |||
14 | */ | ||
15 | 8 | ||
16 | #include "includes.h" | 9 | #include "includes.h" |
17 | RCSID("$Id: ssh-add.c,v 1.12 1999/11/23 00:24:32 damien Exp $"); | 10 | RCSID("$Id: ssh-add.c,v 1.13 1999/11/24 13:26:22 damien Exp $"); |
18 | 11 | ||
19 | #include "rsa.h" | 12 | #include "rsa.h" |
20 | #include "ssh.h" | 13 | #include "ssh.h" |
@@ -35,291 +28,279 @@ const char *__progname = "ssh-add"; | |||
35 | void | 28 | void |
36 | delete_file(AuthenticationConnection *ac, const char *filename) | 29 | delete_file(AuthenticationConnection *ac, const char *filename) |
37 | { | 30 | { |
38 | RSA *key; | 31 | RSA *key; |
39 | char *comment; | 32 | char *comment; |
40 | 33 | ||
41 | key = RSA_new(); | 34 | key = RSA_new(); |
42 | if (!load_public_key(filename, key, &comment)) | 35 | if (!load_public_key(filename, key, &comment)) { |
43 | { | 36 | printf("Bad key file %s: %s\n", filename, strerror(errno)); |
44 | printf("Bad key file %s: %s\n", filename, strerror(errno)); | 37 | return; |
45 | return; | 38 | } |
46 | } | 39 | if (ssh_remove_identity(ac, key)) |
47 | 40 | fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); | |
48 | if (ssh_remove_identity(ac, key)) | 41 | else |
49 | fprintf(stderr, "Identity removed: %s (%s)\n", filename, comment); | 42 | fprintf(stderr, "Could not remove identity: %s\n", filename); |
50 | else | 43 | RSA_free(key); |
51 | fprintf(stderr, "Could not remove identity: %s\n", filename); | 44 | xfree(comment); |
52 | RSA_free(key); | ||
53 | xfree(comment); | ||
54 | } | 45 | } |
55 | 46 | ||
56 | void | 47 | void |
57 | delete_all(AuthenticationConnection *ac) | 48 | delete_all(AuthenticationConnection *ac) |
58 | { | 49 | { |
59 | /* Send a request to remove all identities. */ | 50 | /* Send a request to remove all identities. */ |
60 | if (ssh_remove_all_identities(ac)) | 51 | if (ssh_remove_all_identities(ac)) |
61 | fprintf(stderr, "All identities removed.\n"); | 52 | fprintf(stderr, "All identities removed.\n"); |
62 | else | 53 | else |
63 | fprintf(stderr, "Failed to remove all identitities.\n"); | 54 | fprintf(stderr, "Failed to remove all identitities.\n"); |
64 | } | 55 | } |
65 | 56 | ||
66 | void | 57 | void |
67 | add_file(AuthenticationConnection *ac, const char *filename) | 58 | add_file(AuthenticationConnection *ac, const char *filename) |
68 | { | 59 | { |
69 | RSA *key; | 60 | RSA *key; |
70 | RSA *public_key; | 61 | RSA *public_key; |
71 | char *saved_comment, *comment; | 62 | char *saved_comment, *comment; |
72 | int success; | 63 | int success; |
73 | 64 | ||
74 | key = RSA_new(); | 65 | key = RSA_new(); |
75 | public_key = RSA_new(); | 66 | public_key = RSA_new(); |
76 | if (!load_public_key(filename, public_key, &saved_comment)) | 67 | if (!load_public_key(filename, public_key, &saved_comment)) { |
77 | { | 68 | printf("Bad key file %s: %s\n", filename, strerror(errno)); |
78 | printf("Bad key file %s: %s\n", filename, strerror(errno)); | 69 | return; |
79 | return; | 70 | } |
80 | } | 71 | RSA_free(public_key); |
81 | RSA_free(public_key); | ||
82 | |||
83 | /* At first, try empty passphrase */ | ||
84 | success = load_private_key(filename, "", key, &comment); | ||
85 | if (!success) { | ||
86 | printf("Need passphrase for %s (%s).\n", filename, saved_comment); | ||
87 | if (!isatty(STDIN_FILENO)) { | ||
88 | #ifdef USE_EXTERNAL_ASKPASS | ||
89 | int prompts = 3; | ||
90 | 72 | ||
91 | while (prompts && !success) | 73 | /* At first, try empty passphrase */ |
92 | { | 74 | success = load_private_key(filename, "", key, &comment); |
93 | success = askpass(filename, key, saved_comment, &comment); | 75 | if (!success) { |
94 | prompts--; | 76 | printf("Need passphrase for %s (%s).\n", filename, saved_comment); |
95 | } | 77 | if (!isatty(STDIN_FILENO)) { |
96 | if (!success) | 78 | #ifdef USE_EXTERNAL_ASKPASS |
97 | { | 79 | int prompts = 3; |
98 | xfree(saved_comment); | 80 | while (prompts && !success) { |
99 | return; | 81 | success = askpass(filename, key, saved_comment, &comment); |
100 | } | 82 | prompts--; |
83 | } | ||
84 | if (!success) { | ||
85 | xfree(saved_comment); | ||
86 | return; | ||
87 | } | ||
101 | #else /* !USE_EXTERNAL_ASKPASS */ | 88 | #else /* !USE_EXTERNAL_ASKPASS */ |
102 | xfree(saved_comment); | 89 | xfree(saved_comment); |
103 | return; | 90 | return; |
104 | #endif /* USE_EXTERNAL_ASKPASS */ | 91 | #endif /* USE_EXTERNAL_ASKPASS */ |
105 | } | 92 | } |
106 | 93 | ||
107 | while (!success) { | 94 | while (!success) { |
108 | char *pass = read_passphrase("Enter passphrase: ", 1); | 95 | char *pass = read_passphrase("Enter passphrase: ", 1); |
109 | if (strcmp(pass, "") == 0){ | 96 | if (strcmp(pass, "") == 0) { |
110 | xfree(pass); | 97 | xfree(pass); |
111 | xfree(saved_comment); | 98 | xfree(saved_comment); |
112 | return; | 99 | return; |
113 | } | 100 | } |
114 | success = load_private_key(filename, pass, key, &comment); | 101 | success = load_private_key(filename, pass, key, &comment); |
115 | memset(pass, 0, strlen(pass)); | 102 | memset(pass, 0, strlen(pass)); |
116 | xfree(pass); | 103 | xfree(pass); |
117 | if (success) | 104 | if (success) |
118 | break; | 105 | break; |
119 | printf("Bad passphrase.\n"); | 106 | printf("Bad passphrase.\n"); |
120 | } | 107 | } |
121 | } | 108 | } |
122 | xfree(saved_comment); | 109 | xfree(saved_comment); |
123 | 110 | ||
124 | if (ssh_add_identity(ac, key, comment)) | 111 | if (ssh_add_identity(ac, key, comment)) |
125 | fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); | 112 | fprintf(stderr, "Identity added: %s (%s)\n", filename, comment); |
126 | else | 113 | else |
127 | fprintf(stderr, "Could not add identity: %s\n", filename); | 114 | fprintf(stderr, "Could not add identity: %s\n", filename); |
128 | RSA_free(key); | 115 | RSA_free(key); |
129 | xfree(comment); | 116 | xfree(comment); |
130 | } | 117 | } |
131 | 118 | ||
132 | void | 119 | void |
133 | list_identities(AuthenticationConnection *ac, int fp) | 120 | list_identities(AuthenticationConnection *ac, int fp) |
134 | { | 121 | { |
135 | BIGNUM *e, *n; | 122 | BIGNUM *e, *n; |
136 | int status; | 123 | int status; |
137 | char *comment; | 124 | char *comment; |
138 | int had_identities; | 125 | int had_identities; |
139 | 126 | ||
140 | e = BN_new(); | 127 | e = BN_new(); |
141 | n = BN_new(); | 128 | n = BN_new(); |
142 | had_identities = 0; | 129 | had_identities = 0; |
143 | for (status = ssh_get_first_identity(ac, e, n, &comment); | 130 | for (status = ssh_get_first_identity(ac, e, n, &comment); |
144 | status; | 131 | status; |
145 | status = ssh_get_next_identity(ac, e, n, &comment)) | 132 | status = ssh_get_next_identity(ac, e, n, &comment)) { |
146 | { | 133 | unsigned int bits = BN_num_bits(n); |
147 | unsigned int bits = BN_num_bits(n); | 134 | had_identities = 1; |
148 | had_identities = 1; | 135 | if (fp) { |
149 | if (fp) { | 136 | printf("%d %s %s\n", bits, fingerprint(e, n), comment); |
150 | printf("%d %s %s\n", bits, fingerprint(e, n), comment); | 137 | } else { |
151 | } else { | 138 | char *ebuf, *nbuf; |
152 | char *ebuf, *nbuf; | 139 | ebuf = BN_bn2dec(e); |
153 | ebuf = BN_bn2dec(e); | 140 | if (ebuf == NULL) { |
154 | if (ebuf == NULL) { | 141 | error("list_identities: BN_bn2dec(e) failed."); |
155 | error("list_identities: BN_bn2dec(e) failed."); | 142 | } else { |
156 | }else{ | 143 | nbuf = BN_bn2dec(n); |
157 | nbuf = BN_bn2dec(n); | 144 | if (nbuf == NULL) { |
158 | if (nbuf == NULL) { | 145 | error("list_identities: BN_bn2dec(n) failed."); |
159 | error("list_identities: BN_bn2dec(n) failed."); | 146 | } else { |
160 | }else{ | 147 | printf("%d %s %s %s\n", bits, ebuf, nbuf, comment); |
161 | printf("%d %s %s %s\n", bits, ebuf, nbuf, comment); | 148 | free(nbuf); |
162 | free(nbuf); | 149 | } |
163 | } | 150 | free(ebuf); |
164 | free(ebuf); | 151 | } |
152 | } | ||
153 | xfree(comment); | ||
165 | } | 154 | } |
166 | } | 155 | BN_clear_free(e); |
167 | xfree(comment); | 156 | BN_clear_free(n); |
168 | } | 157 | if (!had_identities) |
169 | BN_clear_free(e); | 158 | printf("The agent has no identities.\n"); |
170 | BN_clear_free(n); | ||
171 | if (!had_identities) | ||
172 | printf("The agent has no identities.\n"); | ||
173 | } | 159 | } |
174 | 160 | ||
175 | int | 161 | int |
176 | main(int argc, char **argv) | 162 | main(int argc, char **argv) |
177 | { | 163 | { |
178 | AuthenticationConnection *ac = NULL; | 164 | AuthenticationConnection *ac = NULL; |
179 | struct passwd *pw; | 165 | struct passwd *pw; |
180 | char buf[1024]; | 166 | char buf[1024]; |
181 | int no_files = 1; | 167 | int no_files = 1; |
182 | int i; | 168 | int i; |
183 | int deleting = 0; | 169 | int deleting = 0; |
184 | 170 | ||
185 | /* check if RSA support exists */ | 171 | /* check if RSA support exists */ |
186 | if (rsa_alive() == 0) { | 172 | if (rsa_alive() == 0) { |
187 | fprintf(stderr, | 173 | extern char *__progname; |
188 | "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", | 174 | |
189 | __progname); | 175 | fprintf(stderr, |
190 | exit(1); | 176 | "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", |
191 | } | 177 | __progname); |
192 | 178 | exit(1); | |
193 | /* At first, get a connection to the authentication agent. */ | ||
194 | ac = ssh_get_authentication_connection(); | ||
195 | if (ac == NULL) { | ||
196 | fprintf(stderr, "Could not open a connection to your authentication agent.\n"); | ||
197 | exit(1); | ||
198 | } | ||
199 | |||
200 | for (i = 1; i < argc; i++) | ||
201 | { | ||
202 | if ((strcmp(argv[i], "-l") == 0) || | ||
203 | (strcmp(argv[i], "-L") == 0)) | ||
204 | { | ||
205 | list_identities(ac, argv[i][1] == 'l' ? 1 : 0); | ||
206 | no_files = 0; /* Don't default-add/delete if -l. */ | ||
207 | continue; | ||
208 | } | 179 | } |
209 | if (strcmp(argv[i], "-d") == 0) | 180 | /* At first, get a connection to the authentication agent. */ |
210 | { | 181 | ac = ssh_get_authentication_connection(); |
211 | deleting = 1; | 182 | if (ac == NULL) { |
212 | continue; | 183 | fprintf(stderr, "Could not open a connection to your authentication agent.\n"); |
184 | exit(1); | ||
213 | } | 185 | } |
214 | if (strcmp(argv[i], "-D") == 0) | 186 | for (i = 1; i < argc; i++) { |
215 | { | 187 | if ((strcmp(argv[i], "-l") == 0) || |
216 | delete_all(ac); | 188 | (strcmp(argv[i], "-L") == 0)) { |
217 | no_files = 0; | 189 | list_identities(ac, argv[i][1] == 'l' ? 1 : 0); |
218 | continue; | 190 | /* Don't default-add/delete if -l. */ |
191 | no_files = 0; | ||
192 | continue; | ||
193 | } | ||
194 | if (strcmp(argv[i], "-d") == 0) { | ||
195 | deleting = 1; | ||
196 | continue; | ||
197 | } | ||
198 | if (strcmp(argv[i], "-D") == 0) { | ||
199 | delete_all(ac); | ||
200 | no_files = 0; | ||
201 | continue; | ||
202 | } | ||
203 | no_files = 0; | ||
204 | if (deleting) | ||
205 | delete_file(ac, argv[i]); | ||
206 | else | ||
207 | add_file(ac, argv[i]); | ||
219 | } | 208 | } |
220 | no_files = 0; | 209 | if (no_files) { |
221 | if (deleting) | 210 | pw = getpwuid(getuid()); |
222 | delete_file(ac, argv[i]); | 211 | if (!pw) { |
223 | else | 212 | fprintf(stderr, "No user found with uid %d\n", (int) getuid()); |
224 | add_file(ac, argv[i]); | 213 | ssh_close_authentication_connection(ac); |
225 | } | 214 | exit(1); |
226 | if (no_files) | 215 | } |
227 | { | 216 | snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY); |
228 | pw = getpwuid(getuid()); | 217 | if (deleting) |
229 | if (!pw) | 218 | delete_file(ac, buf); |
230 | { | 219 | else |
231 | fprintf(stderr, "No user found with uid %d\n", (int)getuid()); | 220 | add_file(ac, buf); |
232 | ssh_close_authentication_connection(ac); | ||
233 | exit(1); | ||
234 | } | 221 | } |
235 | snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, SSH_CLIENT_IDENTITY); | 222 | ssh_close_authentication_connection(ac); |
236 | if (deleting) | 223 | exit(0); |
237 | delete_file(ac, buf); | ||
238 | else | ||
239 | add_file(ac, buf); | ||
240 | } | ||
241 | ssh_close_authentication_connection(ac); | ||
242 | exit(0); | ||
243 | } | 224 | } |
244 | 225 | ||
245 | #ifdef USE_EXTERNAL_ASKPASS | 226 | #ifdef USE_EXTERNAL_ASKPASS |
246 | int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment) | 227 | int askpass(const char *filename, RSA *key, const char *saved_comment, char **comment) |
247 | { | 228 | { |
248 | int pipes[2]; | 229 | int pipes[2]; |
249 | char buf[1024]; | 230 | char buf[1024]; |
250 | int tmp; | 231 | int tmp; |
251 | pid_t child; | 232 | pid_t child; |
252 | FILE *pipef; | 233 | FILE *pipef; |
253 | 234 | ||
254 | /* Check that we are X11-capable */ | 235 | /* Check that we are X11-capable */ |
255 | if (getenv("DISPLAY") == NULL) | 236 | if (getenv("DISPLAY") == NULL) |
256 | exit(1); | 237 | exit(1); |
257 | 238 | ||
258 | if (pipe(pipes) == -1) { | 239 | if (pipe(pipes) == -1) { |
259 | fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno)); | 240 | fprintf(stderr, "Creating pipes failed: %s\n", strerror(errno)); |
260 | exit(1); | 241 | exit(1); |
261 | } | 242 | } |
262 | 243 | ||
263 | if (fflush(NULL) == EOF) { | 244 | if (fflush(NULL) == EOF) { |
264 | fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno)); | 245 | fprintf(stderr, "Cannot flush buffers: %s\n", strerror(errno)); |
265 | exit(1); | 246 | exit(1); |
266 | } | 247 | } |
267 | 248 | ||
268 | child = fork(); | 249 | child = fork(); |
269 | if (child == -1) { | 250 | if (child == -1) { |
270 | fprintf(stderr, "Cannot fork: %s\n", strerror(errno)); | 251 | fprintf(stderr, "Cannot fork: %s\n", strerror(errno)); |
271 | exit(1); | 252 | exit(1); |
272 | } | 253 | } |
273 | 254 | ||
274 | if (child == 0) { | 255 | if (child == 0) { |
275 | /* In child */ | 256 | /* In child */ |
276 | 257 | ||
277 | close(pipes[0]); | 258 | close(pipes[0]); |
278 | if (dup2(pipes[1], 1) ==-1) { | 259 | if (dup2(pipes[1], 1) ==-1) { |
279 | fprintf(stderr, "dup2 failed: %s\n", strerror(errno)); | 260 | fprintf(stderr, "dup2 failed: %s\n", strerror(errno)); |
280 | exit(1); | 261 | exit(1); |
281 | } | 262 | } |
282 | 263 | ||
283 | tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment); | 264 | tmp = snprintf(buf, sizeof(buf), "Need passphrase for %s", saved_comment); |
284 | /* skip the prompt if it won't fit */ | 265 | /* skip the prompt if it won't fit */ |
285 | if ((tmp < 0) || (tmp >= sizeof(buf))) | 266 | if ((tmp < 0) || (tmp >= sizeof(buf))) |
286 | tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0); | 267 | tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", 0); |
287 | else | 268 | else |
288 | tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0); | 269 | tmp = execlp(ASKPASS_PROGRAM, "ssh-askpass", buf, 0); |
289 | 270 | ||
290 | /* Shouldn't get this far */ | 271 | /* Shouldn't get this far */ |
291 | fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno)); | 272 | fprintf(stderr, "Executing ssh-askpass failed: %s\n", strerror(errno)); |
292 | exit(1); | 273 | exit(1); |
293 | } | 274 | } |
294 | 275 | ||
295 | /* In parent */ | 276 | /* In parent */ |
296 | close(pipes[1]); | 277 | close(pipes[1]); |
297 | 278 | ||
298 | if ((pipef = fdopen(pipes[0], "r")) == NULL) { | 279 | if ((pipef = fdopen(pipes[0], "r")) == NULL) { |
299 | fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); | 280 | fprintf(stderr, "fdopen failed: %s\n", strerror(errno)); |
300 | exit(1); | 281 | exit(1); |
301 | } | 282 | } |
302 | 283 | ||
303 | /* Read passphrase back from child, abort if none presented */ | 284 | /* Read passphrase back from child, abort if none presented */ |
304 | if(fgets(buf, sizeof(buf), pipef) == NULL) | 285 | if(fgets(buf, sizeof(buf), pipef) == NULL) |
305 | exit(1); | 286 | exit(1); |
306 | 287 | ||
307 | fclose(pipef); | 288 | fclose(pipef); |
308 | 289 | ||
309 | if (strchr(buf, '\n')) | 290 | if (strchr(buf, '\n')) |
310 | *strchr(buf, '\n') = 0; | 291 | *strchr(buf, '\n') = 0; |
311 | 292 | ||
312 | if (waitpid(child, NULL, 0) == -1) { | 293 | if (waitpid(child, NULL, 0) == -1) { |
313 | fprintf(stderr, "Waiting for child failed: %s\n", | 294 | fprintf(stderr, "Waiting for child failed: %s\n", |
314 | strerror(errno)); | 295 | strerror(errno)); |
315 | exit(1); | 296 | exit(1); |
316 | } | 297 | } |
317 | 298 | ||
318 | /* Try password as it was presented */ | 299 | /* Try password as it was presented */ |
319 | tmp = load_private_key(filename, buf, key, comment); | 300 | tmp = load_private_key(filename, buf, key, comment); |
320 | 301 | ||
321 | memset(buf, 0, sizeof(buf)); | 302 | memset(buf, 0, sizeof(buf)); |
322 | 303 | ||
323 | return(tmp); | 304 | return(tmp); |
324 | } | 305 | } |
325 | #endif /* USE_EXTERNAL_ASKPASS */ | 306 | #endif /* USE_EXTERNAL_ASKPASS */ |