Поддержка SFTP в midnight commander
Это перевод заметки о моем тестировании поддержки SFTP в midnight commander. Оригинал на английском опубликован в моем блоге (http://blog.tataranovich.com/2011/12/sftp-suppot-in-midnight-commander.html) .
Продолжаю следить за разработкой поддержки SFTP в midnight commander, на этой неделе общался с автором — в поддержке sftp появилась авторизация через ssh-agent. На радостях я быстренько накидал пакет и затестил его.
И первое разочарование — midnight не может авторизоваться через агента. Я попробовал предыдущие схемы авторизации, которые работали в предыдущей версии:
- по паролю — работает без проблем;
- по ключу — работает, но только для ключей, которые не защищены паролем (судя по всему это ограничение библиотеки).
Испробовав разные варианты с агентом — поинтересовался у автора, как работает у него. Оказалось, что без проблем. Позже нашел пример авторизации через ssh-agent (http://www.libssh2.org/examples/ssh2_agent.html) на сайте разработчиков libssh2 и попробовал его скомпилировать
$ 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
Сообщение об ошибке навело на мысль, что пример рассчитан на версию, которая новее той, что находится в репозитарии debian squeeze. Попробовал собрать текущую версию libssh2 (1.3.0) и пересобрать пример с уже новой библиотекой.
$ 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!
zsh: segmentation fault ./agent_auth localhost andrey
Запуск под strace показал, что во-первых соединение идет на 255.255.255.255 вместо 127.0.0.1, а во вторых код примера пытается освобождать ресурсы без проверки их использования. Отсюда и segfault при выходе.
munmap(0xb7813000, 4096) = 0
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(22), sin_addr=inet_addr("255.255.255.255")}, 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
Добавил проверку перед освобождением ресурсов
--- 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[])
*/
shutdown:
-
- libssh2_agent_disconnect(agent);
- libssh2_agent_free(agent);
+ if (agent) {
+ libssh2_agent_disconnect(agent);
+
+ libssh2_agent_free(agent);
+ }
if(session) {
После чего пересобрал и запустил.
$ 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!
Уже лучше — segfault на выходе исчез, но ругается на невозможность подключиться. Снова смотрю в код. Для преобразования хоста в формат понятный функции connect() используется inet_addr()
if (argc > 1) {
hostaddr = inet_addr(argv[1]);
} else {
hostaddr = htonl(0x7F000001);
}
Смотрю в man 3 inet_addr и вижу, что функция преобразует символьную запись ip адреса в его бинарное представление. Bingo! Я ведь передаю имя хоста как localhost. Заменив localhost на 127.0.0.1 получаю работающий пример.
$ LD_LIBRARY_PATH=$PWD/libssh2/lib ./agent_auth 127.0.0.1 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!
Теперь дело за малым — собрать версию libssh2 (1.3.0) для squeeze и пересобрать midnight с новой версией библиотеки. Готовую сборку можно забрать тут (http://www.tataranovich.com/public/mc-sftp/2011-12-08/)