Bug 1157 - ssh-keygen doesn't handle DOS line breaks
Summary: ssh-keygen doesn't handle DOS line breaks
Status: CLOSED FIXED
Alias: None
Product: Portable OpenSSH
Classification: Unclassified
Component: ssh-keygen (show other bugs)
Version: 3.8.1p1
Hardware: All All
: P2 normal
Assignee: Assigned to nobody
URL: http://openssh.org/txt/draft-ietf-sec...
Keywords:
Depends on:
Blocks: V_4_4
  Show dependency treegraph
 
Reported: 2006-02-15 08:16 AEDT by Chris Pepper
Modified: 2006-09-28 19:25 AEST (History)
0 users

See Also:


Attachments
Here's a commercial key with DOS-style line endings, which chokes ssh-keygen (1.26 KB, text/plain)
2006-02-15 08:20 AEDT, Chris Pepper
no flags Details
Handle keys with CR termination only. (606 bytes, patch)
2006-02-15 12:36 AEDT, Darren Tucker
no flags Details | Diff
Make ssh-keygen accept CR, LF or CRLF in keys. (1022 bytes, patch)
2006-02-15 14:38 AEDT, Darren Tucker
no flags Details | Diff
Make ssh-keygen accept CR, LF or CRLF in keys take 2. (1.34 KB, patch)
2006-02-15 20:06 AEDT, Darren Tucker
no flags Details | Diff
Make ssh-keygen accept CR, LF or CRLF in keys take 3. (1.77 KB, patch)
2006-02-21 21:41 AEDT, Darren Tucker
no flags Details | Diff
A sample key with Mac line breaks (1.24 KB, text/plain)
2006-02-23 02:20 AEDT, Chris Pepper
no flags Details
Make ssh-keygen accept CR, LF or CRLF in keys take 4 (1.79 KB, patch)
2006-02-26 16:32 AEDT, Darren Tucker
no flags Details | Diff
Make ssh-keygen accept CR, LF or CRLF in keys take 5, with feedback from djm (2.54 KB, patch)
2006-02-27 23:23 AEDT, Darren Tucker
djm: ok+
Details | Diff
Regress test for this (against -portable) (809 bytes, patch)
2006-03-07 23:44 AEDT, Darren Tucker
djm: ok+
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Pepper 2006-02-15 08:16:28 AEDT
ssh-keygen cannot import files with DOS-style line endings (CR/LF). This appears to be a violation of draft-ietf-secsh-publickeyfile-02, which says all line-break styles MUST be supported.

I initially noticed this with a key created on VMS, using DOS-style line breaks, and confirmed with a brand-new key created with ssh-3.2.9.1. ssh-keygen was able to import the key with default UNIX-style line endings, but I got "uudecode failed." with DOS-style line breaks.


pepper@salt:~/.ssh2$ ssh-keygen -i -f id_dsa_2048_a.pub.dos 
uudecode failed.


3.1 Line termination Characters

   In order to achieve the goal of being able to exchange public key
   files between servers, implementations are REQUIRED to read files
   using any of the common line termination sequence, <CR>, <LF> or
   <CR><LF>.

   Implementations may generate files using which ever line termination
   convention is most convenient


My system is:

pepper@salt:~/.ssh$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.4.4
BuildVersion:   8G32
pepper@salt:~/.ssh$ uname -a
Darwin salt.rockefeller.edu 8.4.0 Darwin Kernel Version 8.4.0: Tue Jan  3 18:22:10 PST 2006; root:xnu-792.6.56.obj~1/RELEASE_PPC Power Macintosh powerpc
Comment 1 Chris Pepper 2006-02-15 08:20:44 AEDT
Created attachment 1067 [details]
Here's a commercial key with DOS-style line endings, which chokes ssh-keygen
Comment 2 Darren Tucker 2006-02-15 12:36:45 AEDT
Created attachment 1068 [details]
Handle keys with CR termination only.

Please try this patch.
Comment 3 Darren Tucker 2006-02-15 12:51:56 AEDT
Comment on attachment 1068 [details]
Handle keys with CR termination only.

Ignore this patch, it breaks other key types.
Comment 4 Darren Tucker 2006-02-15 14:38:22 AEDT
Created attachment 1069 [details]
Make ssh-keygen accept CR, LF or CRLF in keys.

Please try this patch instead.
Comment 5 Chris Pepper 2006-02-15 15:18:47 AEDT
This works for the DOS (CR/LF) case, and still works for the UNIX (LF) case, but doesn't work for the (Classic) Mac (CR) case.
Comment 6 Darren Tucker 2006-02-15 20:06:33 AEDT
Created attachment 1070 [details]
Make ssh-keygen accept CR, LF or CRLF in keys take 2.

Alright, please try this one.  It's not all that elegant because fgets slurps the whole thing into the buffer when it doesn't see what it considers a newline so it seeks back for each subsequent line.

The fgets probably wants replacing with a variant of fgetln that accepts all of CR, LF and CRLF.
Comment 7 Damien Miller 2006-02-15 22:50:20 AEDT
Comment on attachment 1069 [details]
Make ssh-keygen accept CR, LF or CRLF in keys.

> 	while (fgets(line, sizeof(line), fp)) {
>-		if (!(p = strchr(line, '\n'))) {
>+		p = strchr(line, '\n');
>+		q = strchr(line, '\r');


Why not just:

if ((p = strchr(line, '\n')) != NULL)
        *p = '\0';
if ((p = strchr(line, '\r')) != NULL)
        *p = '\0';
Comment 8 Darren Tucker 2006-02-15 23:00:50 AEDT
(In reply to comment #7)
> Why not just:
> 
> if ((p = strchr(line, '\n')) != NULL)
>         *p = '\0';
> if ((p = strchr(line, '\r')) != NULL)
>         *p = '\0';

Well, for one reason, if there's no '\r' in the string, p will now be NULL, and then when we deref it...
Comment 9 Darren Tucker 2006-02-15 23:06:23 AEDT
(In reply to comment #8)
> Well, for one reason, if there's no '\r' in the string, p will now be NULL, and
> then when we deref it...

... although this:
      if (p > line && p[-1] == '\\')
could be restructured to this:
      len = strlen(line);
      if (len > 0 && line[len - 1] == '\\')
which might even work :-)
Comment 10 Chris Pepper 2006-02-21 17:14:33 AEDT
Do y'all have a consensus on the preferred patch I should test?
Comment 11 Darren Tucker 2006-02-21 21:41:54 AEDT
Created attachment 1074 [details]
Make ssh-keygen accept CR, LF or CRLF in keys take 3.
Comment 12 Chris Pepper 2006-02-23 02:20:32 AEDT
Created attachment 1078 [details]
A sample key with Mac line breaks

With patch #1074, ssh-keygen -i fails on this file.
Comment 13 Chris Pepper 2006-02-23 02:22:45 AEDT
Patch 1074 works on UNIX & DOS files, but breaks in the Mac case ("unget error").

pepper@pepperbook:~/port/openssh$ ./ssh-keygen -i -f ~/Desktop/ssh-keygen-bug/id_dsa_2048_a.pub.mac
unget: Unknown error: 0

I attached a sample key with Mac line breaks.
ssh-keygen -i also breaks on < (with or without "-f -"). Is this intended to work?
Comment 14 Darren Tucker 2006-02-26 16:32:36 AEDT
Created attachment 1086 [details]
Make ssh-keygen accept CR, LF or CRLF in keys take 4

OK, this one works with the sample key.  Sooner or later I'll run out of wrong ways to do this :-)

As far as redirection with "-", it's not a supported syntax (for the most part, it works with -T but nothing else).  You can try "ssh-keygen -i -f /dev/stdin", assuming your OS supports it.
Comment 15 Chris Pepper 2006-02-27 12:48:27 AEDT
The latest patch ("take 4") works for all 3 cases (UNIX, DOS, & Mac). Thanks!
Comment 16 Damien Miller 2006-02-27 22:29:00 AEDT
Comment on attachment 1086 [details]
Make ssh-keygen accept CR, LF or CRLF in keys take 4

Looks good, a couple of nits:

>+static int
>+get_line(FILE *fp, char *line, size_t len)
>+{
>+	int c;
>+	size_t pos = 0;
>+
>+	if (len &gt; INT_MAX)
>+		return -1;

I don't think this is necessary in the context.

>+		line[pos++] = c;
>+		line[pos] = '\0';
>+	}
>+	return 0;

Maybe this function should return the length of the string, that would save the strlen() later:

>+	while (get_line(fp, line, sizeof(line)) == 0) {
>+		len = strlen(line);
>+		if (line[len - 1] == '\\')
> 			escaped++;

Regress test? :)
Comment 17 Darren Tucker 2006-02-27 22:47:20 AEDT
(In reply to comment #16)
> >+	if (len &gt; INT_MAX)
> >+		return -1;
> 
> I don't think this is necessary in the context.

I was being paranoid.

> Maybe this function should return the length of the string, that would
> save the strlen() later:

Good idea, I'll change it.

> Regress test? :)

Some people are never happy :-)  Actually I already have one but posting it as a diff is useless because of the line-break differences in the test data.
Comment 18 Darren Tucker 2006-02-27 23:23:26 AEDT
Created attachment 1087 [details]
Make ssh-keygen accept CR, LF or CRLF in keys take 5, with feedback from djm
Comment 19 Chris Pepper 2006-02-28 12:45:22 AEDT
(In reply to comment #18)
> Created an attachment (id=1087) [edit]
> Make ssh-keygen accept CR, LF or CRLF in keys take 5, with feedback from djm

Where do I get v1.141, which patch #5 is against? I don't see it at <http://www.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/ssh-keygen.c>, and the patch doesn't apply against v1.135 from
openssh-4.3.tar.gz or openssh-SNAP-20060213.tar.gz.


Thanks,
Chris
Comment 20 Darren Tucker 2006-02-28 12:51:05 AEDT
(In reply to comment #19)
> Where do I get v1.141, which patch #5 is against?

Try: http://cvsweb.mindrot.org/index.cgi/openssh/ssh-keygen.c

Not sure why it's not in the snaps, though.
Comment 21 Darren Tucker 2006-03-07 23:44:01 AEDT
Created attachment 1091 [details]
Regress test for this (against -portable)

In reply to comment #16)
> Regress test? :)

Happy now?  :-)
Comment 22 Damien Miller 2006-03-12 15:36:18 AEDT
Comment on attachment 1087 [details]
Make ssh-keygen accept CR, LF or CRLF in keys take 5, with feedback from djm

looks sane
Comment 23 Damien Miller 2006-03-12 15:39:26 AEDT
Comment on attachment 1091 [details]
Regress test for this (against -portable)

ok
Comment 24 Darren Tucker 2006-03-13 19:50:58 AEDT
Thanks all.  Patches #1087 and #1091 have been applied and will be in 4.4.
Comment 25 Darren Tucker 2006-09-28 19:25:49 AEST
With the release of 4.4, we believe that this bug is now closed.  For information about the release please see http://www.openssh.com/txt/release-4.4 .