diff options
author | Damien Miller <djm@mindrot.org> | 2011-05-05 14:17:18 +1000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2011-05-05 14:17:18 +1000 |
commit | 2ce12ef1ac96c47b386168459cf7264fdc6faf95 (patch) | |
tree | f22a2364e250199fc1c83504b8489a37665c3607 | |
parent | 8cb1cda1e3a24c6f73b96822f36762c1c80ae147 (diff) |
- djm@cvs.openbsd.org 2011/05/04 21:15:29
[authfile.c authfile.h ssh-add.c]
allow "ssh-add - < key"; feedback and ok markus@
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | authfile.c | 100 | ||||
-rw-r--r-- | authfile.h | 4 | ||||
-rw-r--r-- | ssh-add.c | 33 | ||||
-rw-r--r-- | ssh-keygen.c | 8 |
5 files changed, 99 insertions, 49 deletions
@@ -65,6 +65,9 @@ | |||
65 | certificate options are supposed to be packed in lexical order of | 65 | certificate options are supposed to be packed in lexical order of |
66 | option name (though we don't actually enforce this at present). | 66 | option name (though we don't actually enforce this at present). |
67 | Move one up that was out of sequence | 67 | Move one up that was out of sequence |
68 | - djm@cvs.openbsd.org 2011/05/04 21:15:29 | ||
69 | [authfile.c authfile.h ssh-add.c] | ||
70 | allow "ssh-add - < key"; feedback and ok markus@ | ||
68 | 71 | ||
69 | 20110221 | 72 | 20110221 |
70 | - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the | 73 | - (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the |
diff --git a/authfile.c b/authfile.c index a49850c89..608d1d06f 100644 --- a/authfile.c +++ b/authfile.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.c,v 1.87 2010/11/29 18:57:04 markus Exp $ */ | 1 | /* $OpenBSD: authfile.c,v 1.88 2011/05/04 21:15:29 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 |
@@ -69,6 +69,8 @@ | |||
69 | #include "misc.h" | 69 | #include "misc.h" |
70 | #include "atomicio.h" | 70 | #include "atomicio.h" |
71 | 71 | ||
72 | #define MAX_KEY_FILE_SIZE (1024 * 1024) | ||
73 | |||
72 | /* Version identification string for SSH v1 identity files. */ | 74 | /* Version identification string for SSH v1 identity files. */ |
73 | static const char authfile_id_string[] = | 75 | static const char authfile_id_string[] = |
74 | "SSH PRIVATE KEY FILE FORMAT 1.1\n"; | 76 | "SSH PRIVATE KEY FILE FORMAT 1.1\n"; |
@@ -312,12 +314,12 @@ key_parse_public_rsa1(Buffer *blob, char **commentp) | |||
312 | return pub; | 314 | return pub; |
313 | } | 315 | } |
314 | 316 | ||
315 | /* Load the contents of a key file into a buffer */ | 317 | /* Load a key from a fd into a buffer */ |
316 | static int | 318 | int |
317 | key_load_file(int fd, const char *filename, Buffer *blob) | 319 | key_load_file(int fd, const char *filename, Buffer *blob) |
318 | { | 320 | { |
321 | u_char buf[1024]; | ||
319 | size_t len; | 322 | size_t len; |
320 | u_char *cp; | ||
321 | struct stat st; | 323 | struct stat st; |
322 | 324 | ||
323 | if (fstat(fd, &st) < 0) { | 325 | if (fstat(fd, &st) < 0) { |
@@ -325,30 +327,45 @@ key_load_file(int fd, const char *filename, Buffer *blob) | |||
325 | filename == NULL ? "" : filename, | 327 | filename == NULL ? "" : filename, |
326 | filename == NULL ? "" : " ", | 328 | filename == NULL ? "" : " ", |
327 | strerror(errno)); | 329 | strerror(errno)); |
328 | close(fd); | ||
329 | return 0; | 330 | return 0; |
330 | } | 331 | } |
331 | if (st.st_size > 1*1024*1024) { | 332 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && |
333 | st.st_size > MAX_KEY_FILE_SIZE) { | ||
334 | toobig: | ||
332 | error("%s: key file %.200s%stoo large", __func__, | 335 | error("%s: key file %.200s%stoo large", __func__, |
333 | filename == NULL ? "" : filename, | 336 | filename == NULL ? "" : filename, |
334 | filename == NULL ? "" : " "); | 337 | filename == NULL ? "" : " "); |
335 | close(fd); | ||
336 | return 0; | 338 | return 0; |
337 | } | 339 | } |
338 | len = (size_t)st.st_size; /* truncated */ | ||
339 | |||
340 | buffer_init(blob); | 340 | buffer_init(blob); |
341 | cp = buffer_append_space(blob, len); | 341 | for (;;) { |
342 | 342 | if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { | |
343 | if (atomicio(read, fd, cp, len) != len) { | 343 | if (errno == EPIPE) |
344 | debug("%s: read from key file %.200s%sfailed: %.100s", __func__, | 344 | break; |
345 | filename == NULL ? "" : filename, | 345 | debug("%s: read from key file %.200s%sfailed: %.100s", |
346 | filename == NULL ? "" : " ", | 346 | __func__, filename == NULL ? "" : filename, |
347 | strerror(errno)); | 347 | filename == NULL ? "" : " ", strerror(errno)); |
348 | buffer_clear(blob); | ||
349 | bzero(buf, sizeof(buf)); | ||
350 | return 0; | ||
351 | } | ||
352 | buffer_append(blob, buf, len); | ||
353 | if (buffer_len(blob) > MAX_KEY_FILE_SIZE) { | ||
354 | buffer_clear(blob); | ||
355 | bzero(buf, sizeof(buf)); | ||
356 | goto toobig; | ||
357 | } | ||
358 | } | ||
359 | bzero(buf, sizeof(buf)); | ||
360 | if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && | ||
361 | st.st_size != buffer_len(blob)) { | ||
362 | debug("%s: key file %.200s%schanged size while reading", | ||
363 | __func__, filename == NULL ? "" : filename, | ||
364 | filename == NULL ? "" : " "); | ||
348 | buffer_clear(blob); | 365 | buffer_clear(blob); |
349 | close(fd); | ||
350 | return 0; | 366 | return 0; |
351 | } | 367 | } |
368 | |||
352 | return 1; | 369 | return 1; |
353 | } | 370 | } |
354 | 371 | ||
@@ -670,11 +687,38 @@ key_load_private_type(int type, const char *filename, const char *passphrase, | |||
670 | } | 687 | } |
671 | 688 | ||
672 | Key * | 689 | Key * |
690 | key_parse_private(Buffer *buffer, const char *filename, | ||
691 | const char *passphrase, char **commentp) | ||
692 | { | ||
693 | Key *pub, *prv; | ||
694 | Buffer pubcopy; | ||
695 | |||
696 | buffer_init(&pubcopy); | ||
697 | buffer_append(&pubcopy, buffer_ptr(buffer), buffer_len(buffer)); | ||
698 | /* it's a SSH v1 key if the public key part is readable */ | ||
699 | pub = key_parse_public_rsa1(&pubcopy, commentp); | ||
700 | buffer_free(&pubcopy); | ||
701 | if (pub == NULL) { | ||
702 | prv = key_parse_private_type(buffer, KEY_UNSPEC, | ||
703 | passphrase, NULL); | ||
704 | /* use the filename as a comment for PEM */ | ||
705 | if (commentp && prv) | ||
706 | *commentp = xstrdup(filename); | ||
707 | } else { | ||
708 | key_free(pub); | ||
709 | /* key_parse_public_rsa1() has already loaded the comment */ | ||
710 | prv = key_parse_private_type(buffer, KEY_RSA1, passphrase, | ||
711 | NULL); | ||
712 | } | ||
713 | return prv; | ||
714 | } | ||
715 | |||
716 | Key * | ||
673 | key_load_private(const char *filename, const char *passphrase, | 717 | key_load_private(const char *filename, const char *passphrase, |
674 | char **commentp) | 718 | char **commentp) |
675 | { | 719 | { |
676 | Key *pub, *prv; | 720 | Key *prv; |
677 | Buffer buffer, pubcopy; | 721 | Buffer buffer; |
678 | int fd; | 722 | int fd; |
679 | 723 | ||
680 | fd = open(filename, O_RDONLY); | 724 | fd = open(filename, O_RDONLY); |
@@ -697,23 +741,7 @@ key_load_private(const char *filename, const char *passphrase, | |||
697 | } | 741 | } |
698 | close(fd); | 742 | close(fd); |
699 | 743 | ||
700 | buffer_init(&pubcopy); | 744 | prv = key_parse_private(&buffer, filename, passphrase, commentp); |
701 | buffer_append(&pubcopy, buffer_ptr(&buffer), buffer_len(&buffer)); | ||
702 | /* it's a SSH v1 key if the public key part is readable */ | ||
703 | pub = key_parse_public_rsa1(&pubcopy, commentp); | ||
704 | buffer_free(&pubcopy); | ||
705 | if (pub == NULL) { | ||
706 | prv = key_parse_private_type(&buffer, KEY_UNSPEC, | ||
707 | passphrase, NULL); | ||
708 | /* use the filename as a comment for PEM */ | ||
709 | if (commentp && prv) | ||
710 | *commentp = xstrdup(filename); | ||
711 | } else { | ||
712 | key_free(pub); | ||
713 | /* key_parse_public_rsa1() has already loaded the comment */ | ||
714 | prv = key_parse_private_type(&buffer, KEY_RSA1, passphrase, | ||
715 | NULL); | ||
716 | } | ||
717 | buffer_free(&buffer); | 745 | buffer_free(&buffer); |
718 | return prv; | 746 | return prv; |
719 | } | 747 | } |
diff --git a/authfile.h b/authfile.h index 6745dc062..78349beb5 100644 --- a/authfile.h +++ b/authfile.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: authfile.h,v 1.15 2010/08/04 05:42:47 djm Exp $ */ | 1 | /* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */ |
2 | 2 | ||
3 | /* | 3 | /* |
4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 4 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
@@ -16,9 +16,11 @@ | |||
16 | #define AUTHFILE_H | 16 | #define AUTHFILE_H |
17 | 17 | ||
18 | int key_save_private(Key *, const char *, const char *, const char *); | 18 | int key_save_private(Key *, const char *, const char *, const char *); |
19 | int key_load_file(int, const char *, Buffer *); | ||
19 | Key *key_load_cert(const char *); | 20 | Key *key_load_cert(const char *); |
20 | Key *key_load_public(const char *, char **); | 21 | Key *key_load_public(const char *, char **); |
21 | Key *key_load_public_type(int, const char *, char **); | 22 | Key *key_load_public_type(int, const char *, char **); |
23 | Key *key_parse_private(Buffer *, const char *, const char *, char **); | ||
22 | Key *key_load_private(const char *, const char *, char **); | 24 | Key *key_load_private(const char *, const char *, char **); |
23 | Key *key_load_private_cert(int, const char *, const char *, int *); | 25 | Key *key_load_private_cert(int, const char *, const char *, int *); |
24 | Key *key_load_private_type(int, const char *, const char *, char **, int *); | 26 | Key *key_load_private_type(int, const char *, const char *, char **, int *); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-add.c,v 1.100 2010/08/31 12:33:38 djm Exp $ */ | 1 | /* $OpenBSD: ssh-add.c,v 1.101 2011/05/04 21:15:29 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 |
@@ -145,8 +145,12 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
145 | char *comment = NULL; | 145 | char *comment = NULL; |
146 | char msg[1024], *certpath; | 146 | char msg[1024], *certpath; |
147 | int fd, perms_ok, ret = -1; | 147 | int fd, perms_ok, ret = -1; |
148 | Buffer keyblob; | ||
148 | 149 | ||
149 | if ((fd = open(filename, O_RDONLY)) < 0) { | 150 | if (strcmp(filename, "-") == 0) { |
151 | fd = STDIN_FILENO; | ||
152 | filename = "(stdin)"; | ||
153 | } else if ((fd = open(filename, O_RDONLY)) < 0) { | ||
150 | perror(filename); | 154 | perror(filename); |
151 | return -1; | 155 | return -1; |
152 | } | 156 | } |
@@ -155,18 +159,28 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
155 | * Since we'll try to load a keyfile multiple times, permission errors | 159 | * Since we'll try to load a keyfile multiple times, permission errors |
156 | * will occur multiple times, so check perms first and bail if wrong. | 160 | * will occur multiple times, so check perms first and bail if wrong. |
157 | */ | 161 | */ |
158 | perms_ok = key_perm_ok(fd, filename); | 162 | if (fd != STDIN_FILENO) { |
159 | close(fd); | 163 | perms_ok = key_perm_ok(fd, filename); |
160 | if (!perms_ok) | 164 | if (!perms_ok) { |
165 | close(fd); | ||
166 | return -1; | ||
167 | } | ||
168 | } | ||
169 | buffer_init(&keyblob); | ||
170 | if (!key_load_file(fd, filename, &keyblob)) { | ||
171 | buffer_free(&keyblob); | ||
172 | close(fd); | ||
161 | return -1; | 173 | return -1; |
174 | } | ||
175 | close(fd); | ||
162 | 176 | ||
163 | /* At first, try empty passphrase */ | 177 | /* At first, try empty passphrase */ |
164 | private = key_load_private(filename, "", &comment); | 178 | private = key_parse_private(&keyblob, filename, "", &comment); |
165 | if (comment == NULL) | 179 | if (comment == NULL) |
166 | comment = xstrdup(filename); | 180 | comment = xstrdup(filename); |
167 | /* try last */ | 181 | /* try last */ |
168 | if (private == NULL && pass != NULL) | 182 | if (private == NULL && pass != NULL) |
169 | private = key_load_private(filename, pass, NULL); | 183 | private = key_parse_private(&keyblob, filename, pass, NULL); |
170 | if (private == NULL) { | 184 | if (private == NULL) { |
171 | /* clear passphrase since it did not work */ | 185 | /* clear passphrase since it did not work */ |
172 | clear_pass(); | 186 | clear_pass(); |
@@ -177,9 +191,11 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
177 | if (strcmp(pass, "") == 0) { | 191 | if (strcmp(pass, "") == 0) { |
178 | clear_pass(); | 192 | clear_pass(); |
179 | xfree(comment); | 193 | xfree(comment); |
194 | buffer_free(&keyblob); | ||
180 | return -1; | 195 | return -1; |
181 | } | 196 | } |
182 | private = key_load_private(filename, pass, &comment); | 197 | private = key_parse_private(&keyblob, filename, pass, |
198 | &comment); | ||
183 | if (private != NULL) | 199 | if (private != NULL) |
184 | break; | 200 | break; |
185 | clear_pass(); | 201 | clear_pass(); |
@@ -187,6 +203,7 @@ add_file(AuthenticationConnection *ac, const char *filename) | |||
187 | "Bad passphrase, try again for %.200s: ", comment); | 203 | "Bad passphrase, try again for %.200s: ", comment); |
188 | } | 204 | } |
189 | } | 205 | } |
206 | buffer_free(&keyblob); | ||
190 | 207 | ||
191 | if (ssh_add_identity_constrained(ac, private, comment, lifetime, | 208 | if (ssh_add_identity_constrained(ac, private, comment, lifetime, |
192 | confirm)) { | 209 | confirm)) { |
diff --git a/ssh-keygen.c b/ssh-keygen.c index b52fc39cf..49e4eee10 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keygen.c,v 1.209 2011/04/12 04:23:50 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keygen.c,v 1.210 2011/04/18 00:46:05 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> | 3 | * Author: Tatu Ylonen <ylo@cs.hut.fi> |
4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
@@ -1454,6 +1454,9 @@ prepare_options_buf(Buffer *c, int which) | |||
1454 | certflags_command != NULL) | 1454 | certflags_command != NULL) |
1455 | add_string_option(c, "force-command", certflags_command); | 1455 | add_string_option(c, "force-command", certflags_command); |
1456 | if ((which & OPTIONS_EXTENSIONS) != 0 && | 1456 | if ((which & OPTIONS_EXTENSIONS) != 0 && |
1457 | (certflags_flags & CERTOPT_X_FWD) != 0) | ||
1458 | add_flag_option(c, "permit-X11-forwarding"); | ||
1459 | if ((which & OPTIONS_EXTENSIONS) != 0 && | ||
1457 | (certflags_flags & CERTOPT_AGENT_FWD) != 0) | 1460 | (certflags_flags & CERTOPT_AGENT_FWD) != 0) |
1458 | add_flag_option(c, "permit-agent-forwarding"); | 1461 | add_flag_option(c, "permit-agent-forwarding"); |
1459 | if ((which & OPTIONS_EXTENSIONS) != 0 && | 1462 | if ((which & OPTIONS_EXTENSIONS) != 0 && |
@@ -1465,9 +1468,6 @@ prepare_options_buf(Buffer *c, int which) | |||
1465 | if ((which & OPTIONS_EXTENSIONS) != 0 && | 1468 | if ((which & OPTIONS_EXTENSIONS) != 0 && |
1466 | (certflags_flags & CERTOPT_USER_RC) != 0) | 1469 | (certflags_flags & CERTOPT_USER_RC) != 0) |
1467 | add_flag_option(c, "permit-user-rc"); | 1470 | add_flag_option(c, "permit-user-rc"); |
1468 | if ((which & OPTIONS_EXTENSIONS) != 0 && | ||
1469 | (certflags_flags & CERTOPT_X_FWD) != 0) | ||
1470 | add_flag_option(c, "permit-X11-forwarding"); | ||
1471 | if ((which & OPTIONS_CRITICAL) != 0 && | 1471 | if ((which & OPTIONS_CRITICAL) != 0 && |
1472 | certflags_src_addr != NULL) | 1472 | certflags_src_addr != NULL) |
1473 | add_string_option(c, "source-address", certflags_src_addr); | 1473 | add_string_option(c, "source-address", certflags_src_addr); |