- dtucker@cvs.openbsd.org 2006/03/13 08:43:16
     [ssh-keygen.c]
     Make ssh-keygen handle CR and CRLF line termination when converting IETF
     format keys, in adition to vanilla LF.  mindrot #1157, tested by Chris
     Pepper, ok djm@
diff --git a/ChangeLog b/ChangeLog
index 7cc666a..74ece78 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -215,6 +215,11 @@
      Set TCP_NODELAY for all connections not just "interactive" ones.  Fixes
      poor performance and protocol stalls under some network conditions (mindrot
      bugs #556 and #981). Patch originally from markus@, ok djm@
+   - dtucker@cvs.openbsd.org 2006/03/13 08:43:16
+     [ssh-keygen.c]
+     Make ssh-keygen handle CR and CRLF line termination when converting IETF
+     format keys, in adition to vanilla LF.  mindrot #1157, tested by Chris
+     Pepper, ok djm@
 
 20060313
  - (dtucker) [configure.ac] Bug #1171: Don't use printf("%lld", longlong)
@@ -4116,4 +4121,4 @@
    - (djm) Trim deprecated options from INSTALL. Mention UsePAM
    - (djm) Fix quote handling in sftp; Patch from admorten AT umich.edu
 
-$Id: ChangeLog,v 1.4201 2006/03/15 01:05:22 djm Exp $
+$Id: ChangeLog,v 1.4202 2006/03/15 01:05:40 djm Exp $
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 8acbf77..bea4ed5 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -12,7 +12,7 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: ssh-keygen.c,v 1.136 2006/02/20 17:19:54 stevesk Exp $");
+RCSID("$OpenBSD: ssh-keygen.c,v 1.137 2006/03/13 08:43:16 dtucker Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -305,13 +305,42 @@
 	return key;
 }
 
+static int
+get_line(FILE *fp, char *line, size_t len)
+{
+	int c;
+	size_t pos = 0;
+
+	line[0] = '\0';
+	while ((c = fgetc(fp)) != EOF) {
+		if (pos >= len - 1) {
+			fprintf(stderr, "input line too long.\n");
+			exit(1);
+		}
+		switch(c) {
+		case '\r':
+			c = fgetc(fp);
+			if (c != EOF && c != '\n' && ungetc(c, fp) == EOF) {
+				fprintf(stderr, "unget: %s\n", strerror(errno));
+				exit(1);
+			}
+			return pos;
+		case '\n':
+			return pos;
+		}
+		line[pos++] = c;
+		line[pos] = '\0';
+	}
+	return pos;
+}
+
 static void
 do_convert_from_ssh2(struct passwd *pw)
 {
 	Key *k;
 	int blen;
 	u_int len;
-	char line[1024], *p;
+	char line[1024];
 	u_char blob[8096];
 	char encoded[8096];
 	struct stat st;
@@ -330,12 +359,8 @@
 		exit(1);
 	}
 	encoded[0] = '\0';
-	while (fgets(line, sizeof(line), fp)) {
-		if (!(p = strchr(line, '\n'))) {
-			fprintf(stderr, "input line too long.\n");
-			exit(1);
-		}
-		if (p > line && p[-1] == '\\')
+	while ((blen = get_line(fp, line, sizeof(line))) != -1) {
+		if (line[blen - 1] == '\\')
 			escaped++;
 		if (strncmp(line, "----", 4) == 0 ||
 		    strstr(line, ": ") != NULL) {
@@ -352,7 +377,6 @@
 			/* fprintf(stderr, "escaped: %s", line); */
 			continue;
 		}
-		*p = '\0';
 		strlcat(encoded, line, sizeof(encoded));
 	}
 	len = strlen(encoded);