пятница, 9 декабря 2011 г.

SFTP support in midnight commander

Этот пост доступен на русском. Перевод можно найти здесь

Continue watching SFTP support development in midnight commander. This week I had conversation with author and asked him for new features wich ready for packaging. He told me that SSH agent authentication ready for testing. I quickly made debian package and test it.

First disappointment - midnight can't authenticate via ssh-agent. I try to recheck auth schemes which worked in previous build:

  • password auth - works as expected;
  • public key auth - works, but only with keys, that didn't password protected (I think it's libssh2 limitation).
Trying different ssh-agent options I finally asked author how he use it. He told me that agent support works out of the box. Later I found ssh-agent example on libssh2 developers site and try to compile it

$ gcc -o agent_auth -Wall -I/usr/include -I. -lssh2 ssh2_agent.c
ssh2_agent.c: In function ‘main’:
ssh2_agent.c:99: warning: implicit declaration of function ‘libssh2_session_handshake’
/home/andrey/tmp/ccmczn2V.o: In function `main':
ssh2_agent.c:(.text+0x1a8): undefined reference to `libssh2_session_handshake'
collect2: ld returned 1 exit status
Error message points me that example written for newer libssh2 version than debian squeeze has. I try to build current available libssh2 version (1.3.0) and rebuild example against new library.

$ gcc -o agent_auth -Wall -I$PWD/libssh2/include -I. -L$PWD/libssh2/lib -lssh2 ssh2_agent.c
After that example builds without errors, but refused to work, complaining about connection problems.

$ LD_LIBRARY_PATH=$PWD/libssh2/lib ./agent-auth localhost andrey
failed to connect!
zsh: segmentation fault  ./agent_auth localhost andrey
Running under strace shows that example try to connect to instead of and free resources without check if they allocated. This is the reason of segfault on exit.

munmap(0xb7813000, 4096)                = 0
connect(3, {sa_family=AF_INET, sin_port=htons(22), sin_addr=inet_addr("")}, 16) = -1 ENETUNREACH (Network is unreachable)
write(2, "failed to connect!\n", 19failed to connect!
)    = 19
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
zsh: segmentation fault  strace -f ./agent_auth localhost username
I added check before resource freeing

--- ssh2_agent.c.orig   2011-12-08 23:53:41.000000000 +0300
+++ ssh2_agent.c    2011-12-09 00:02:10.000000000 +0300
@@ -231,10 +231,12 @@ int main(int argc, char *argv[])

-    libssh2_agent_disconnect(agent);

-    libssh2_agent_free(agent);
+   if (agent) {
+       libssh2_agent_disconnect(agent);
+       libssh2_agent_free(agent);
+   }

     if(session) {
After that I rebuild example and run it.

$ gcc -o agent_auth -Wall -I$PWD/libssh2/include -I. -L$PWD/libssh2/lib -lssh2 ssh2_agent.c
$ LD_LIBRARY_PATH=$PWD/libssh2/lib ./agent_auth localhost andrey
failed to connect!
Now better - segfault on exit dissapeared, but binary still complaining about connection error. Looking code again - hostname conversion made by inet_addr() function.

if (argc > 1) {
        hostaddr = inet_addr(argv[1]);
    } else {
        hostaddr = htonl(0x7F000001);
Referring to man 3 inet_addr and see that function converts symbolic representation of ip address to it's binary form. Bingo! I do a mistake by supplying localhost as hostname. Replacing localhost with do the thing and example works now.

$ LD_LIBRARY_PATH=$PWD/libssh2/lib ./agent_auth andrey
Fingerprint: FA F3 92 9E C4 AE 14 B4 FC BE ED 2A E8 33 0C 1E 34 09 9F B3 
Authentication methods: publickey,password
 Authentication with username andrey and public key /home/andrey/.ssh/id_rsa failed!
 Authentication with username andrey and public key /home/andrey/.ssh/id_dsa succeeded!
all done!
Now the rest - create libssh2 (1.3.0) package for squeeze and rebuild midnight commander against new library version. Binary builds can be downloaded from there

Этот пост доступен на русском. Перевод можно найти здесь

2 комментария:

  1. Thanks for adding sftp support to mc.

    How to force use arcfour128 cipher for sftp connection in mc? Is it possible?

    1. When I looked in MC's sftp code last time there is no possibility to set this option explicitly. Right now situation may change.