Bug 32175

Summary: ssh-keygen -p core dumps
Product: Base System Reporter: AnarCat <AnarCat>
Component: binAssignee: Brian Feldman <green>
Status: Closed FIXED    
Severity: Affects Only Me    
Priority: Normal    
Version: 4.4-STABLE   
Hardware: Any   
OS: Any   

Description AnarCat 2001-11-21 21:50:00 UTC
ssh-keygen core dumps when trying to change my DSA passphrase.

Compiling the program with debugging symbols disables the bug, so it's
tricky to debug.

Here is what I can get from gdb:

anarcat@shall[~]% gdb `which ssh-keygen` ssh-keygen.core 
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you
are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for
details.
This GDB was configured as "i386-unknown-freebsd"...
(no debugging symbols found)...
Core was generated by `ssh-keygen'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libcrypto.so.2...(no debugging symbols
found)...
done.
Reading symbols from /usr/lib/libc.so.4...(no debugging symbols
found)...done.
Reading symbols from /usr/libexec/ld-elf.so.1...(no debugging symbols
found)...
done.
#0  0x2819be32 in vfprintf () from /usr/lib/libc.so.4
(gdb) bt
#0  0x2819be32 in vfprintf () from /usr/lib/libc.so.4
#1  0x281891e4 in printf () from /usr/lib/libc.so.4
#2  0x804b1f8 in sigprocmask ()
#3  0x804ba34 in sigprocmask ()
#4  0x804a215 in sigprocmask ()
(gdb) 

I am no gdb guru, but it seems to me that if I do this:

(gdb) run -p -d
Starting program: /usr/bin/ssh-keygen -p -d
(no debugging symbols found)...(no debugging symbols found)...
Enter file in which the key is (/home/anarcat/.ssh/id_dsa): 
Enter old passphrase: 
(no debugging symbols found)...
Program received signal SIGSEGV, Segmentation fault.
0x2819be32 in vfprintf () from /usr/lib/libc.so.4
(gdb) bt
#0  0x2819be32 in vfprintf () from /usr/lib/libc.so.4
#1  0x281891e4 in printf () from /usr/lib/libc.so.4
#2  0x804b1f8 in sigprocmask ()
#3  0x804ba34 in sigprocmask ()
#4  0x804a215 in sigprocmask ()
(gdb) symbol /usr/obj/usr/src/secure/usr.bin/ssh-keygen/ssh-keygen.debug 
Reading symbols from
/usr/obj/usr/src/secure/usr.bin/ssh-keygen/ssh-keygen.debug...done.

I don't supposed it would work? Anyways, by the results of the tests I
ran here, no.

Is this correct? Is the information from ssh-keygen.debug valid even if
ssh-keygen was run?

Fix: 

Workaround:
Compile the program with debugging symbols:

anarcat@shall[/usr/obj/usr/src/secure/usr.bin/ssh-keygen]%
./ssh-keygen.debug -p -d
Enter file in which the key is (/home/anarcat/.ssh/id_dsa): 
Enter old passphrase: 
Key has comment 'z¸PÕ'
Enter new passphrase (empty for no passphrase): 
sh-keygen.debug in free(): warning: junk pointer, too high to make
sense.
Your identification has been saved with the new passphrase.

Fix:

Unknown. The problem is probably with comment handling code.

I am available for further testing, but I of course cannot disclose my
private keyfile. ;)
How-To-Repeat: 
anarcat@shall[~]% ssh-keygen -p -d
Enter file in which the key is (/home/anarcat/.ssh/id_dsa): 
Enter old passphrase: 
zsh: segmentation fault  ssh-keygen -p -d

It does not affect RSA keys:

anarcat@shall[~]% ssh-keygen -p   
Enter file in which the key is (/home/anarcat/.ssh/identity): 
Enter old passphrase: 
Key has comment 'anarcat@shall.anarcat.dyndns.org'
Enter new passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved with the new passphrase.
Comment 1 ian j hart 2001-12-20 02:08:29 UTC
Printing the comment is the source of the crash.
The error appears to be in /usr/src/crypto/openssh/authfile.c

*** authfile.c.orig     Thu Dec 20 01:17:00 2001
--- authfile.c  Thu Dec 20 01:21:33 2001
***************
*** 556,562 ****
        lseek(fd, (off_t) 0, SEEK_SET);         /* rewind */
        if (pub == NULL) {
                /* closes fd */
!               return key_load_private_pem(fd, KEY_UNSPEC, passphrase,
NULL);
        } else {
                /* it's a SSH v1 key if the public key part is readable
*/
                key_free(pub);
--- 556,562 ----
        lseek(fd, (off_t) 0, SEEK_SET);         /* rewind */
        if (pub == NULL) {
                /* closes fd */
!               return key_load_private_pem(fd, KEY_UNSPEC, passphrase,
commentp);
        } else {
                /* it's a SSH v1 key if the public key part is readable
*/
                key_free(pub);

commentp is the address of a pointer to a heap? allocated
string (for the comment). key_load_private_pem will
allocate memory and intialise commentp, if it gets
a non-null value.

As authfile.c is part of libssl someone who knows about
this stuff should verify this fix. Because of this I
present an alternative workaround.

*** ssh-keygen.c.orig   Thu Dec 20 01:16:52 2001
--- ssh-keygen.c        Thu Dec 20 01:20:49 2001
***************
*** 456,462 ****
  void
  do_change_passphrase(struct passwd *pw)
  {
!       char *comment;
        char *old_passphrase, *passphrase1, *passphrase2;
        struct stat st;
        Key *private;
--- 456,462 ----
  void
  do_change_passphrase(struct passwd *pw)
  {
!       char *comment = NULL;
        char *old_passphrase, *passphrase1, *passphrase2;
        struct stat st;
        Key *private;

This only affects ssh-keygen. The offending printf survives
the null pointer, as does the xfree() later in the function.

Call tree:
ssh-keygen.c:	457:void do_change_passphrase(struct passwd *pw)
		477:private = key_load_private(identity_file, old_passphrase ,
&comment);
authfile.c:	541:Key *key_load_private(const char *filename, const char
*passphrase, char **commentp)
		559:return key_load_private_pem(fd, KEY_UNSPEC, passphrase, NULL); 
<--- error
		435:Key *key_load_private_pem(int fd, int type, const char
*passphrase, char **commentp)
		478:        if (prv != NULL && commentp)
		                *commentp = xstrdup(name);

I wasn't sure whether to quote the whole thing here. Perhaps
someone could advise me on "style".

-- 
ian j hart
Comment 2 ian j hart 2001-12-20 21:02:13 UTC
s/libssl/libssh/
Must remember to sleep.

-- 
ian j hart
Comment 3 Sheldon Hearn freebsd_committer freebsd_triage 2001-12-30 14:14:00 UTC
Responsible Changed
From-To: freebsd-bugs->green

Over to the OpenSSH maintainer, who'll probably just pass the work 
on to Eivind. :-)
Comment 4 Brian Feldman freebsd_committer freebsd_triage 2002-01-07 15:55:33 UTC
State Changed
From-To: open->feedback

Committed to -CURRENT, thanks.
Comment 5 AnarCat 2002-01-22 00:06:19 UTC
On Mon Jan 07, 2002 at 07:56:41AM -0800, green@FreeBSD.org wrote:
> 
> State-Changed-From-To: open->feedback
> Committed to -CURRENT, thanks.


Fix confirmed on -stable.

Please commit fix before release.

A.
Comment 6 AnarCat 2002-04-07 18:58:12 UTC
This pr can be closed.
Comment 7 Doug Barton freebsd_committer freebsd_triage 2003-03-02 04:00:05 UTC
State Changed
From-To: feedback->closed


Originator reports problem solved.