summaryrefslogtreecommitdiffstats
path: root/authfile.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2011-05-05 14:17:18 +1000
committerDamien Miller <djm@mindrot.org>2011-05-05 14:17:18 +1000
commit2ce12ef1ac96c47b386168459cf7264fdc6faf95 (patch)
treef22a2364e250199fc1c83504b8489a37665c3607 /authfile.c
parent8cb1cda1e3a24c6f73b96822f36762c1c80ae147 (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@
Diffstat (limited to 'authfile.c')
-rw-r--r--authfile.c100
1 files changed, 64 insertions, 36 deletions
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;
}