diff options
Diffstat (limited to 'authfile.c')
-rw-r--r-- | authfile.c | 100 |
1 files changed, 64 insertions, 36 deletions
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 | } |