最近遇到一个使用aarch64_be-gcc编译的ssh服务器出现不能通过ssh1协议使用密钥+passphrase不能正常登陆的问题。
(⊙o⊙)…不要奇怪为啥还在用SSH1,我也在奇怪。。
一顿捣鼓(重现问题),发现是64位的ssh-keygen生成的密钥的不能使用设置passphrase解密,于是问题就好办了,用x86_64的ssh-keygen生成一个密钥使用,ok,正常登陆了。
那么问题就结束了嘛,当然没有,怎么也得看一下为啥arm64的ssh-keygen就不正常了。
于是编译一个debug版本,去掉-O3优化,aarch64_be-gcc的-O3优化相当crazy,已经给我造成成吨的伤害了。。。
调试发现:
1 Breakpoint 5, sshkey_private_rsa1_to_blob (key=0x556955a610, 2 blob=0x556955ad60, passphrase=0x556955ac20 "123456", 3 comment=0x7fffffc758 "root@trait") at sshkey.c:3474 4 3474 sshkey.c: No such file or directory. 5 (gdb) p cp 6 $10 = (u_char *) 0x556955aaa0 ">*" 7 (gdb) n 8 3482 in sshkey.c 9 (gdb) p cp 10 $11 = (u_char *) 0x556955aaa0 ">*>*" 11 (gdb) n 12 3483 in sshkey.c 13 (gdb) n 14 3482 in sshkey.c 15 (gdb) n 16 3484 in sshkey.c 17 (gdb) n 18 3483 in sshkey.c 19 (gdb) n 20 3485 in sshkey.c 21 (gdb) n 22 3484 in sshkey.c 23 (gdb) n 24 25 Breakpoint 6, sshkey_private_rsa1_to_blob (key=0x556955a610, 26 blob=0x556955ad60, passphrase=0x556955ac20 "123456", 27 comment=0x7fffffc758 "trait@trait") at sshkey.c:3489 28 3489 in sshkey.c 29 (gdb) p cp 30 $12 = (u_char *) 0x556955aaa0 "" 31 (gdb) p buf 32 $13 = " 00 00 00UiU255`" 33 (gdb) n 34 3490 in sshkey.c 35 (gdb) p buf 36 $14 = " 00 00 00 00 00 00 00" 37 (gdb) p cp 38 $15 = (u_char *) 0x556955aaa0 "" 39 (gdb) bt 40 #0 sshkey_private_rsa1_to_blob (key=0x556955a610, blob=0x556955ad60, 41 passphrase=0x556955ac20 "123456", comment=0x7fffffc758 "trait@trait") 42 at sshkey.c:3490 43 #1 0x00000055694fef48 in sshkey_private_to_fileblob (key=0x556955a610, 44 blob=0x556955ad60, passphrase=0x556955ac20 "123456", 45 comment=<optimized out>, force_new_format=<optimized out>, 46 new_format_cipher=<optimized out>, new_format_rounds=<optimized out>) 47 at sshkey.c:3610 48 #2 0x0000005569505024 in sshkey_save_private (key=0x556955a610, 49 filename=0x5569553168 <identity_file> "testpass1", 50 passphrase=0x556955ac20 "123456", comment=0x7fffffc758 "trait@trait", 51 force_new_format=0, new_format_cipher=0x0, new_format_rounds=0) 52 at authfile.c:85 53 #3 0x00000055694f6f30 in main (argc=<optimized out>, argv=0x3d4) 54 at ssh-keygen.c:2672
发现cp这个变量变成空字符串了,这里openssh的代码我就不分析了,因为我也没这么读,完全是因为这个三不管的ssh服务出问题了。
这么就变成空的了呢。。。
在X86的虚拟机上面也调试了一下:
1 Breakpoint 1, sshkey_private_rsa1_to_blob (key=0x17c658, blob=0x17eaf8, passphrase=0x17ee20 "123456", comment=0xbffff139 "trait@trait") 2 at sshkey.c:3449 3 3449 { 4 (gdb) b sshkey.c:3490 5 Breakpoint 2 at 0x11dbea: file sshkey.c, line 3490. 6 (gdb) c 7 Continuing. 8 9 Breakpoint 2, sshkey_private_rsa1_to_blob (key=0x17c658, blob=0x17eaf8, passphrase=0x17ee20 "123456", comment=0xbffff139 "trait@trait") 10 at sshkey.c:3490 11 3490 if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0) 12 (gdb) p cp 13 $1 = (u_char *) 0x17eb28 "310 65327267310 65327267 353 27" 14 (gdb) bt 15 #0 sshkey_private_rsa1_to_blob (key=0x17c658, blob=0x17eaf8, passphrase=0x17ee20 "123456", comment=0xbffff139 "trait@trait") at sshkey.c:3490 16 #1 0x001244a5 in sshkey_private_to_fileblob (key=0x17c658, blob=0x17eaf8, passphrase=0x17ee20 "123456", comment=0xbffff139 "trait@trait", 17 force_new_format=0, new_format_cipher=0x0, new_format_rounds=0) at sshkey.c:3610 18 #2 0x0012d250 in sshkey_save_private (key=0x17c658, filename=0x17a0e0 "testpass", passphrase=0x17ee20 "123456", comment=0xbffff139 "trait@trait", 19 force_new_format=0, new_format_cipher=0x0, new_format_rounds=0) at authfile.c:85 20 #3 0x0011be51 in main (argc=1398664, argv=0xbffff618) at ssh-keygen.c:2672 21 22 Breakpoint 1, sshkey_private_rsa1_to_blob (key=0x17c658, blob=0x17eaf8, passphrase=0x17ee20 "123456", comment=0xbffff139 "trait@trait") 23 at sshkey.c:3449 24 3449 { 25 (gdb) b sshbuf.c:350 26 Breakpoint 3 at 0x11c9e5: file sshbuf.c, line 350. 27 (gdb) c 28 Continuing.
同样的代码,不同的结果,好吧
继续调试arm64的版本:
1 Breakpoint 9, sshbuf_reserve (buf=0x5584d5c2e0, len=258, dpp=0x7fffffba60) 2 at sshbuf.c:347 3 347 in sshbuf.c 4 (gdb) p (u_char *) 0x5584d5baa0 5 $36 = (u_char *) 0x5584d5baa0 "322316322316" 6 (gdb) n 7 348 in sshbuf.c 8 (gdb) n 9 350 in sshbuf.c 10 (gdb) p (u_char *) 0x5584d5baa0 11 $37 = (u_char *) 0x5584d5baa0 "322316322316" 12 (gdb) n 13 356 in sshbuf.c 14 (gdb) p (u_char *) 0x5584d5baa0 15 $38 = (u_char *) 0x5584d5baa0 "" 16 (gdb) p rlen 17 $39 = 512 18 (gdb) p buf->d 19 $40 = (u_char *) 0x5584d5baa0 "" 20 (gdb) p dp 21 $41 = (u_char *) 0x5584d5cf70 "322316322316"
上面的cp指针与buf->d是同一个地址。openssh6.9p1 代码如下:
1 if ((dp = realloc(buf->d, rlen)) == NULL) { 2 SSHBUF_DBG(("realloc fail")); 3 if (dpp != NULL) 4 *dpp = NULL; 5 return SSH_ERR_ALLOC_FAIL; 6 }
发现buf->d拷贝给了dp,但是自己内容被清空了,于是查看realloc的说明,只有一种情况貌似符合这种情况,就是buf->d指向的内存区域被移动了,这会是谁干的?realloc???