summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog3
-rw-r--r--authfile.c100
-rw-r--r--authfile.h4
-rw-r--r--ssh-add.c33
-rw-r--r--ssh-keygen.c8
5 files changed, 99 insertions, 49 deletions
diff --git a/ChangeLog b/ChangeLog
index 7cc6a234..6a324c71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -65,6 +65,9 @@
certificate options are supposed to be packed in lexical order of
option name (though we don't actually enforce this at present).
Move one up that was out of sequence
+ - 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@
20110221
- (dtucker) [contrib/cygwin/ssh-host-config] From Corinna: revamp of the
diff --git a/authfile.c b/authfile.c
index a49850c8..608d1d06 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.c,v 1.87 2010/11/29 18:57:04 markus Exp $ */
+/* $OpenBSD: authfile.c,v 1.88 2011/05/04 21:15:29 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -69,6 +69,8 @@
#include "misc.h"
#include "atomicio.h"
+#define MAX_KEY_FILE_SIZE (1024 * 1024)
+
/* Version identification string for SSH v1 identity files. */
static const char authfile_id_string[] =
"SSH PRIVATE KEY FILE FORMAT 1.1\n";
@@ -312,12 +314,12 @@ key_parse_public_rsa1(Buffer *blob, char **commentp)
return pub;
}
-/* Load the contents of a key file into a buffer */
-static int
+/* Load a key from a fd into a buffer */
+int
key_load_file(int fd, const char *filename, Buffer *blob)
{
+ u_char buf[1024];
size_t len;
- u_char *cp;
struct stat st;
if (fstat(fd, &st) < 0) {
@@ -325,30 +327,45 @@ key_load_file(int fd, const char *filename, Buffer *blob)
filename == NULL ? "" : filename,
filename == NULL ? "" : " ",
strerror(errno));
- close(fd);
return 0;
}
- if (st.st_size > 1*1024*1024) {
+ if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+ st.st_size > MAX_KEY_FILE_SIZE) {
+ toobig:
error("%s: key file %.200s%stoo large", __func__,
filename == NULL ? "" : filename,
filename == NULL ? "" : " ");
- close(fd);
return 0;
}
- len = (size_t)st.st_size; /* truncated */
-
buffer_init(blob);
- cp = buffer_append_space(blob, len);
-
- if (atomicio(read, fd, cp, len) != len) {
- debug("%s: read from key file %.200s%sfailed: %.100s", __func__,
- filename == NULL ? "" : filename,
- filename == NULL ? "" : " ",
- strerror(errno));
+ for (;;) {
+ if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
+ if (errno == EPIPE)
+ break;
+ debug("%s: read from key file %.200s%sfailed: %.100s",
+ __func__, filename == NULL ? "" : filename,
+ filename == NULL ? "" : " ", strerror(errno));
+ buffer_clear(blob);
+ bzero(buf, sizeof(buf));
+ return 0;
+ }
+ buffer_append(blob, buf, len);
+ if (buffer_len(blob) > MAX_KEY_FILE_SIZE) {
+ buffer_clear(blob);
+ bzero(buf, sizeof(buf));
+ goto toobig;
+ }
+ }
+ bzero(buf, sizeof(buf));
+ if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
+ st.st_size != buffer_len(blob)) {
+ debug("%s: key file %.200s%schanged size while reading",
+ __func__, filename == NULL ? "" : filename,
+ filename == NULL ? "" : " ");
buffer_clear(blob);
- close(fd);
return 0;
}
+
return 1;
}
@@ -670,11 +687,38 @@ key_load_private_type(int type, const char *filename, const char *passphrase,
}
Key *
+key_parse_private(Buffer *buffer, const char *filename,
+ const char *passphrase, char **commentp)
+{
+ Key *pub, *prv;
+ Buffer pubcopy;
+
+ buffer_init(&pubcopy);
+ buffer_append(&pubcopy, buffer_ptr(buffer), buffer_len(buffer));
+ /* it's a SSH v1 key if the public key part is readable */
+ pub = key_parse_public_rsa1(&pubcopy, commentp);
+ buffer_free(&pubcopy);
+ if (pub == NULL) {
+ prv = key_parse_private_type(buffer, KEY_UNSPEC,
+ passphrase, NULL);
+ /* use the filename as a comment for PEM */
+ if (commentp && prv)
+ *commentp = xstrdup(filename);
+ } else {
+ key_free(pub);
+ /* key_parse_public_rsa1() has already loaded the comment */
+ prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
+ NULL);
+ }
+ return prv;
+}
+
+Key *
key_load_private(const char *filename, const char *passphrase,
char **commentp)
{
- Key *pub, *prv;
- Buffer buffer, pubcopy;
+ Key *prv;
+ Buffer buffer;
int fd;
fd = open(filename, O_RDONLY);
@@ -697,23 +741,7 @@ key_load_private(const char *filename, const char *passphrase,
}
close(fd);
- buffer_init(&pubcopy);
- buffer_append(&pubcopy, buffer_ptr(&buffer), buffer_len(&buffer));
- /* it's a SSH v1 key if the public key part is readable */
- pub = key_parse_public_rsa1(&pubcopy, commentp);
- buffer_free(&pubcopy);
- if (pub == NULL) {
- prv = key_parse_private_type(&buffer, KEY_UNSPEC,
- passphrase, NULL);
- /* use the filename as a comment for PEM */
- if (commentp && prv)
- *commentp = xstrdup(filename);
- } else {
- key_free(pub);
- /* key_parse_public_rsa1() has already loaded the comment */
- prv = key_parse_private_type(&buffer, KEY_RSA1, passphrase,
- NULL);
- }
+ prv = key_parse_private(&buffer, filename, passphrase, commentp);
buffer_free(&buffer);
return prv;
}
diff --git a/authfile.h b/authfile.h
index 6745dc06..78349beb 100644
--- a/authfile.h
+++ b/authfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: authfile.h,v 1.15 2010/08/04 05:42:47 djm Exp $ */
+/* $OpenBSD: authfile.h,v 1.16 2011/05/04 21:15:29 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -16,9 +16,11 @@
#define AUTHFILE_H
int key_save_private(Key *, const char *, const char *, const char *);
+int key_load_file(int, const char *, Buffer *);
Key *key_load_cert(const char *);
Key *key_load_public(const char *, char **);
Key *key_load_public_type(int, const char *, char **);
+Key *key_parse_private(Buffer *, const char *, const char *, char **);
Key *key_load_private(const char *, const char *, char **);
Key *key_load_private_cert(int, const char *, const char *, int *);
Key *key_load_private_type(int, const char *, const char *, char **, int *);
diff --git a/ssh-add.c b/ssh-add.c
index 94b68ac1..6d5e2a95 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-add.c,v 1.100 2010/08/31 12:33:38 djm Exp $ */
+/* $OpenBSD: ssh-add.c,v 1.101 2011/05/04 21:15:29 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -145,8 +145,12 @@ add_file(AuthenticationConnection *ac, const char *filename)
char *comment = NULL;
char msg[1024], *certpath;
int fd, perms_ok, ret = -1;
+ Buffer keyblob;
- if ((fd = open(filename, O_RDONLY)) < 0) {
+ if (strcmp(filename, "-") == 0) {
+ fd = STDIN_FILENO;
+ filename = "(stdin)";
+ } else if ((fd = open(filename, O_RDONLY)) < 0) {
perror(filename);
return -1;
}
@@ -155,18 +159,28 @@ add_file(AuthenticationConnection *ac, const char *filename)
* Since we'll try to load a keyfile multiple times, permission errors
* will occur multiple times, so check perms first and bail if wrong.
*/
- perms_ok = key_perm_ok(fd, filename);
- close(fd);
- if (!perms_ok)
+ if (fd != STDIN_FILENO) {
+ perms_ok = key_perm_ok(fd, filename);
+ if (!perms_ok) {
+ close(fd);
+ return -1;
+ }
+ }
+ buffer_init(&keyblob);
+ if (!key_load_file(fd, filename, &keyblob)) {
+ buffer_free(&keyblob);
+ close(fd);
return -1;
+ }
+ close(fd);
/* At first, try empty passphrase */
- private = key_load_private(filename, "", &comment);
+ private = key_parse_private(&keyblob, filename, "", &comment);
if (comment == NULL)
comment = xstrdup(filename);
/* try last */
if (private == NULL && pass != NULL)
- private = key_load_private(filename, pass, NULL);
+ private = key_parse_private(&keyblob, filename, pass, NULL);
if (private == NULL) {
/* clear passphrase since it did not work */
clear_pass();
@@ -177,9 +191,11 @@ add_file(AuthenticationConnection *ac, const char *filename)
if (strcmp(pass, "") == 0) {
clear_pass();
xfree(comment);
+ buffer_free(&keyblob);
return -1;
}
- private = key_load_private(filename, pass, &comment);
+ private = key_parse_private(&keyblob, filename, pass,
+ &comment);
if (private != NULL)
break;
clear_pass();
@@ -187,6 +203,7 @@ add_file(AuthenticationConnection *ac, const char *filename)
"Bad passphrase, try again for %.200s: ", comment);
}
}
+ buffer_free(&keyblob);
if (ssh_add_identity_constrained(ac, private, comment, lifetime,
confirm)) {
diff --git a/ssh-keygen.c b/ssh-keygen.c
index b52fc39c..49e4eee1 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.209 2011/04/12 04:23:50 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.210 2011/04/18 00:46:05 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1454,6 +1454,9 @@ prepare_options_buf(Buffer *c, int which)
certflags_command != NULL)
add_string_option(c, "force-command", certflags_command);
if ((which & OPTIONS_EXTENSIONS) != 0 &&
+ (certflags_flags & CERTOPT_X_FWD) != 0)
+ add_flag_option(c, "permit-X11-forwarding");
+ if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_AGENT_FWD) != 0)
add_flag_option(c, "permit-agent-forwarding");
if ((which & OPTIONS_EXTENSIONS) != 0 &&
@@ -1465,9 +1468,6 @@ prepare_options_buf(Buffer *c, int which)
if ((which & OPTIONS_EXTENSIONS) != 0 &&
(certflags_flags & CERTOPT_USER_RC) != 0)
add_flag_option(c, "permit-user-rc");
- if ((which & OPTIONS_EXTENSIONS) != 0 &&
- (certflags_flags & CERTOPT_X_FWD) != 0)
- add_flag_option(c, "permit-X11-forwarding");
if ((which & OPTIONS_CRITICAL) != 0 &&
certflags_src_addr != NULL)
add_string_option(c, "source-address", certflags_src_addr);