我意识到这个问题经常被问到,主要是那些想要拦截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忽略其输入的非标准输入特性;但是当我尝试这个时它仍然无效。
任何提示?
非常感谢!
答案 0 :(得分:1)
使用popen(而不是 execv )执行ssh cmd并能够读取和写入会话。
答案 1 :(得分:1)
如果您希望允许任何交互式使用ssh与拦截器,管道将无法工作。在这种情况下,您需要创建一个伪tty。查找posix_openpt
,ptsname
和grantpt
函数。还有一个名为openpty
的非标准但更加直观的函数,以及一个名为forkpty
的包装器,它使你想要做的事情非常容易。
答案 2 :(得分:1)
Python的Paramiko使用SSH完成所有这些操作,但它使用的是Python源代码。但是,对于C程序员来说,阅读Python就像阅读伪代码一样,所以请到源代码并准确了解它的作用。
答案 3 :(得分: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;
}
答案 4 :(得分:0)
这一行可能错了:
execv(argv[1], argv + 1); // run ssh
如果你使用argv []来自编辑:刚刚检查了C99标准,argv被NULL终止。main()
的参数,那么数组必须用NULL指针终止。我认为没有任何保证是这种情况。
execv()
不会搜索要执行的文件的路径,因此如果您将ssh
作为参数传递,则它等同于./ssh
,这可能不是您想要的。您可以使用execvp()
,但如果ssh
之前的$ PATH中出现名为/bin/ssh
的恶意程序,则存在安全风险。最好使用execv()
并强制使用正确的路径。