如何在Java程序中拦截SSH密码请求

时间:2013-12-22 08:51:44

标签: java ssh passwords tty

我需要使用ProcessBuilder和USERID / PASSWORD组合从JAVA程序生成SSH连接。

我已经使用Ganymed,JSch,JAVA Processbuilder和Expect脚本(也是Expect4J),JAVA ProcessBuilder和SSHPASS脚本以及SSH共享密钥的组合成功实现了SSH连接。

目前,安全性并不是一个问题,而我所追求的只是能够以编程方式支持SSH连接的各种组合。

我的问题是SSH在某个不在STDIN / STDOUT上的地方提示的密码提示(我相信在tty上)。这是我要克服的最后一道障碍。

我的问题是有没有办法拦截SSH密码请求并从我的JAVA代码中提供它?

请注意,这是一个非常狭隘的问题(以上所有信息都是为​​了保证答案不会过于宽泛)。

以下是我正在尝试的示例代码:

import  java.io.*;
import  java.util.*;

public class ProcessBuilderTest {
    public  static void main(String[] args) throws IOException, Exception {

        ProcessBuilder pb = new ProcessBuilder(
                                "/usr/bin/ssh",
                                "nyuser@myserver.com",
                                "export NOME='Jennifer Lawrence'; echo $NOME"
                                );


        pb.redirectErrorStream(); //redirect stderr to stdout
        Process process = pb.start();
        InputStream inputStream = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        String line = null;
        while((line = reader.readLine())!= null) {
            System.out.println(line);
        }
        process.waitFor();
     }
}

但是,当我运行它时,我得到了这个:

[memphis BuilderTest]# java ProcessBuilderTest

myuser@myserver's password: 

在我输入密码后,我得到了剩下的输出:

Jennifer Lawrence

[memphis BuilderTest]# 

同样,具体问题是: 有没有办法使用PasswordAuthentication方法生成外部ssh客户端(OpenSSH,Tectia SSH,SecureCRT等)(没有其他方法可以使用)进程使用JAVA ProcessBuilder接口(不能使用其他语言),拦截/捕获密码提示并响应/交互从我的JAVA代码提供该密码(因此用户不需要输入密码)?

2 个答案:

答案 0 :(得分:0)

假设您在Linux上运行,您需要了解伪ttys。密码提示位于tty设备上。您将需要构建一个针对伪tty运行的单独进程,而不是仅继承您的tty设备,然后您可以拦截密码提示。

这是一个中等复杂的过程。

有一个图书馆支持其中一些:http://www.ganymed.ethz.ch/ssh2/FAQ.html。如果可用,你可能会发现阅读它的来源是有启发性的。

答案 1 :(得分:0)

尽管有人建议使用伪tty(pty)来模拟终端,但可接受的答案并不能提供有效的解决方案-还有很多类似的问题却没有有效的答案。

有两种解决方案,可让您捕获SSH中的“ Password:”提示,并以自动方式输入密码,而无需使用SSH_ASKPASS或Expect。

为什么要同时使用两种编程语言,第一种选择并不理想,但是它展示了解决方案:

ProcessBuilder pb = new ProcessBuilder("/usr/bin/python", "-c", "import pty; pty.spawn(['/usr/bin/ssh', '<hostname>'])");

以上示例利用Python pty模块将SSH包装到PTY中。尽管它很简单,但是它没有提供任何灵活性来允许您修改任何终端属性,例如传递的窗口大小。

另一个更轻便的选择是在C中使用PTY包装器-“UNIX®环境高级编程”一书中的pty工具就是这样-来源可以在{{3}中找到}。

然后,您将以类似的方式使用它,但是引用pty工具而不是Python:

ProcessBuilder pb = new ProcessBuilder("/usr/local/bin/pty", "/usr/bin/ssh", "<hostname>");

这与Expect用于模拟PTY的方法相同,这就是为什么您能够使用Expect拦截它的原因。不用说,隧道明文密码是不安全的,公钥身份验证应该始终是首选方法。