Как перехватить SSH STDIN и STDOUT?(не пароль) - PullRequest
1 голос
/ 11 апреля 2011

Я понимаю, что этот вопрос часто задают, в основном, люди, которые хотят перехватить фазу запроса пароля SSH.Это не то, что я хочу.Я после текста после входа в систему.

Я хочу написать оболочку для ssh, который действует как посредник между SSH и терминалом.Я хочу эту конфигурацию:

(typing on keyboard / stdin) ----> (wrapper) ----> (ssh client)

и то же самое для вывода из SSH:

(ssh client) -----> (wrapper) -----> stdout

Кажется, я могудобиться эффекта, которого я хочу для stdout, выполнив стандартный трюк, который я нашел в Интернете (упрощенный код):

pipe(fd)
if (!fork()) {
  close(fd[READ_SIDE]);
  close(STDOUT_FILENO);  // close stdout ( fd #1 )
  dup(fd[WRITE_SIDE]);   // duplicate the writing side of my pipe ( to lowest # free pipe, 1 )
  close(STDERR_FILENO);
  dup(fd[WRITE_SIDE]);
  execv(argv[1], argv + 1); // run ssh
} else {
  close(fd[WRITE_SIDE]);
  output = fdopen(fd[READ_SIDE], "r");
  while ( (c = fgetc(output)) != EOF) {
    printf("%c", c);
    fflush(stdout);
  }
}

Как я уже сказал, я думаю, что это работает.Тем не менее, я не могу сделать наоборот.Я не могу закрыть (STDIN_FILENO) и дублировать канал чтения канала.Кажется, что SSH обнаруживает это и предотвращает это.Я читал, что могу использовать опцию "-t -t", чтобы заставить SSH игнорировать не входящий в stdin характер его ввода;но когда я пытаюсь это сделать, он все равно не работает.

Есть какие-нибудь намеки?

Большое спасибо!

Ответы [ 5 ]

1 голос
/ 12 апреля 2011

Python's Paramiko делает все это с SSH, но это в исходном коде Python. Однако для программиста на Си чтение Python во многом похоже на чтение псевдокода, поэтому перейдите к исходному коду и узнайте, что именно работает.

1 голос
/ 11 апреля 2011

Канал не будет работать, если вы хотите разрешить любое интерактивное использование ssh с перехватчиком на месте.В этом случае вам нужно создать псевдо-tty.Посмотрите на функции posix_openpt, ptsname и grantpt.Также есть нестандартная, но гораздо более интуитивно понятная функция с именем openpty и оболочка для нее с именем forkpty, которая делает то, что вы пытаетесь сделать, чрезвычайно просто.

1 голос
/ 11 апреля 2011

Используйте popen (вместо execv ) для выполнения команды ssh и возможности чтения и записи в сеанс.

0 голосов
/ 11 апреля 2011

Эта строка, вероятно, неверна:

  execv(argv[1], argv + 1); // run ssh

Массив должен заканчиваться указателем NULL, если вы используете argv [] параметр из main() Я не думаю, что тамЭто гарантия того, что это так. Редактировать: только что проверил стандарт C99 и argv завершен на NULL.

execv() не ищет путь к файлу для выполнения, поэтому, если вы передаетеssh как параметр, он эквивалентен ./ssh, что, вероятно, не то, что вы хотите.Вы можете использовать execvp(), но это представляет угрозу безопасности, если вредоносная программа с именем ssh появляется в $ PATH до /bin/ssh.Лучше использовать execv() и заставить правильный путь.

0 голосов
/ 11 апреля 2011

Вот рабочий пример, который пишет в ssh:

#include <unistd.h>

int main(int argc, char **argv)
{
    int pid;
    int fds[2];

    if (pipe(fds))
        return -1;

    pid = fork();

    if (!pid)
    {
        close(fds[1]);
        close(STDERR_FILENO);
        dup2(fds[0], STDIN_FILENO);
        execvp(argv[1], argv + 1);
    }
    else
    {
        char buf[256];
        int rc;

        close(fds[0]);
        while ((rc = read(STDIN_FILENO, buf, 256)) > 0)
        {
            write(fds[1], buf, rc);
        }
    }
    wait(NULL);
    return 0;
}
...