2011-04-11 31 views
1

我意識到這個問題經常被問到,主要是想攔截SSH的密碼詢問階段的人。這不是我想要的。我在登錄後的文本後。如何攔截SSH stdin和stdout? (不是密碼)

我想寫一個ssh的包裝器,它充當SSH和終端之間的中介。我想這個配置:

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

和同樣來自SSH來輸出:

(ssh client) -----> (wrapper) -----> 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忽略其輸入的非標準輸入性質;但是當我嘗試這個時,它仍然不起作用。

任何提示?

非常感謝!

+1

你真的應該使用'dup2'而不是'dup'來代替stdout/stdin等。 – Hasturkun 2011-04-11 14:25:03

+0

如果你使用私鑰而不是密碼,'ssh'不應該關心stdin的文件類型。你可以試試嗎? – 2011-04-11 15:44:04

回答

1

使用popen(而不是execv)執行ssh cmd並能夠讀取和寫入會話。

+1

從所顯示的代碼中以不同的方式執行'popen'是否有任何顯着的不同(即'dup2' vs'dup')? – 2011-04-11 15:42:18

0

這裏有一個工作的例子,寫入到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; 
} 
0

此行可能是錯誤的:

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

數組必須由一個NULL指針終止,如果您使用的argv [ ]從main()的參數我不認爲有這種情況的任何保證。編輯:剛剛檢查了C99標準,argv是NULL終止。

execv()不搜索要執行的文件的路徑,所以如果您傳遞的參數是ssh,那麼它相當於./ssh,這可能不是您想要的。您可以使用execvp(),但如果在/bin/ssh之前出現一個名爲ssh的惡意程序出現在$ PATH中,則存在安全風險。最好使用execv()並強制正確的路徑。

1

如果你想允許交互使用ssh和攔截器,管道將不起作用。在這種情況下,您需要創建一個僞tty。查看posix_openpt,ptsnamegrantpt函數。還有一個非標準但更直觀的功能,稱爲openpty,它的包裝稱爲forkpty,它使您非常容易做到的事情。

1

Python的Paramiko用SSH來完成這一切,但它是在Python源代碼中完成的。然而,對於一個C程序員來說,閱讀Python很像閱讀僞代碼,所以去源代碼並且確切地知道什麼可行。