【问题标题】:JSch: what am i doing wrong, with JSCH tty code for executing interactive commands?JSch:我做错了什么,使用 JSCH tty 代码执行交互式命令?
【发布时间】:2012-06-18 15:32:24
【问题描述】:

我正在尝试通过 JSch 连接到服务器,然后执行交互式 su 命令。

你能告诉我我错过了什么吗?这些东西每次都挂起,我看不出这种行为的原因。 特别是我在发送密码之前专门等待密码字符串(实际上是 assword 没有 : )。

这就是我正在做的:

  1. 以 user1/pass1 身份登录
  2. 然后执行su - user2 -c commandline
  3. 在频道输入流中传递密码。

总之,这里是主要的执行函数,它需要user1/pass1、user2/pass2和commandLine。

public String execute (String host, String nuser, String npass,
                       String puser, String ppass, String commandLine)
    {
      try{
        synchronized(this) 
        {
          session = jsch.getSession(nuser,host,22);
          session.setConfig("StrictHostKeyChecking", "no");
          pstr=npass;
          //session.setPassword(npass);
          String authmethods=  session.getConfig("PreferredAuthentications");
          System.out.println(authmethods);
          UserInfo ui=new SUSessionExecution.UInfo();
          Thread.sleep(150);
          if(authmethods.contains("keyboard-interactive"))
          { System.out.print("keyboard-interactive"); session.setUserInfo(ui); } 
          else if ( authmethods.contains("password") )
          { System.out.print("password"); session.setPassword(pstr);  }

          session.connect();
          channel = session.openChannel("exec");
          nuser=null;
          npass=null;


          ((ChannelExec)channel).setPty(true);
          ((ChannelExec)channel).setPtyType("vt100");
          String command= "su - " + puser + " -c " + commandLine  + "\n";
          //((ChannelExec)channel).setCommand(commandLine);

          byte[] cmdBuffer=command.getBytes();
          ByteArrayInputStream bi = new ByteArrayInputStream(cmdBuffer);
          channel.setInputStream(bi);

          ByteArrayOutputStream bo = new ByteArrayOutputStream();
          ((ChannelExec)channel).setErrStream(bo);

          sessionOutput = channel.getInputStream();
          //sessionError = channel.getExtInputStream();


          channel.connect();

          session_open=true;
          // it is only here our session is fully functional.

          boolean sustatus;//=establishSU(commandIO, channel,puser,ppass);
          // NEEDS REPLACE

          //commandIO.write(command.getBytes());
          //commandIO.flush();



          String standardOutBuffer="";
          String standardErrBuffer="";

          int counter;
          byte[] byteBuffer = new byte[1024];


          while(sessionOutput.available() > 0)
            { counter=0; //byteBuffer=null;
              counter=sessionOutput.read(byteBuffer, 0, byteBuffer.length);
              if(counter < 0) { throw new java.io.IOException(); }
              standardOutBuffer += new String(byteBuffer,0,counter);
              if(standardOutBuffer.contains("assword")){break;}
            }

            /*if(sessionError.available() > 0)
            { counter=0; //byteBuffer=null;
              counter=sessionError.read(byteBuffer, 0, byteBuffer.length);
              if(counter < 0) { throw new java.io.IOException(); }
              standardErrBuffer += new String(byteBuffer,0,counter);
              if(standardErrBuffer.contains("assword")){break;}}*/


        commandIO = new PipedOutputStream();
        sessionInput = new PipedInputStream(commandIO);
        channel.setInputStream(sessionInput);
        commandIO.write(new String(ppass+"\n").getBytes());
        commandIO.flush();

        counter=0; standardOutBuffer="";
        while((counter = sessionOutput.read(byteBuffer,0,byteBuffer.length)) != -1)
        { standardOutBuffer += new String(byteBuffer,0,counter); }

        closeComponents();
        return standardOutBuffer;
        }
      }
      catch(com.jcraft.jsch.JSchException jse) 
      { session_open=false;su_space_open=false;jse.printStackTrace();
        closeComponents(); return null; }
      catch(java.io.IOException ioe)
      { session_open=false;su_space_open=false;ioe.printStackTrace();
        closeComponents(); return null; }
      catch(InterruptedException ie)
      { ie.printStackTrace(); }

        return null;
    }

这是我的错误信息:

Exception in thread "main" java.lang.NullPointerException
  at com.jcraft.jsch.Buffer.putString(Buffer.java:59)
  at com.jcraft.jsch.UserAuthKeyboardInteractive.start(UserAuthKeyboardInteractive.ja‌va:183)
  at com.jcraft.jsch.Session.connect(Session.java:442)
  at com.jcraft.jsch.Session.connect(Session.java:162)
  at susessionexecution.SUExecute.execute(SUExecute.java:53)
  at Tester.<init>(Tester.java:12)
  at Tester.main(Tester.java:17) 

这里是 promptKeyboardInteractive 方法

public String[] promptKeyboardInteractive (String destination, String name,
                                           String instruction, String[] prompt,
                                           boolean[] echo)
{
    System.out.println("\n"+prompt.length+"\n\n");
    String[] response=new String[prompt.length];
    response[0] = passwd;
    return response;
}

【问题讨论】:

  • 伙计们之间,这是错误消息:___________ Exception in thread "main" java.lang.NullPointerException at com.jcraft.jsch.Buffer.putString(Buffer.java:59) at com.jcraft.jsch.UserAuthKeyboardInteractive.start(UserAuthKeyboardInteractive.java:183) at com.jcraft.jsch.Session.connect(Session.java:442) at com.jcraft.jsch.Session.connect(Session.java:162) at susessionexecution.SUExecute.execute(SUExecute.java:53) at Tester.&lt;init&gt;(Tester.java:12) at Tester.main(Tester.java:17) _________________
  • 你能展示你的 UInfo 类的源代码吗?看起来错误就在那里。
  • 请不要将代码放在 cmets 中,那里不清晰。改为编辑您的问题。为什么要创建一个长度为prompt.length 的数组,并且只填充它的第一个元素?
  • @PaŭloEbermann 因为 prompt.length 大多为 1,但是,我尝试过可变长度数组并将它们发送。结果是一样的。有趣的是它运行了一次,没有给出错误。我真的看不出与这里的时间有任何关系,但现在看到这种行为,在我看来,必须对时间做点什么。谢谢,钱丹

标签: java ssh jsch


【解决方案1】:

看来你的实现

  UIKeyboardInteractive#promptKeyboardInteractive()

返回一个字符串数组,其中包含'null'。

至于sudo,我建议参考 http://www.jcraft.com/jsch/examples/Sudo.java.html

【讨论】:

  • 谢谢,我会再次查看 promptKeyboardInteractive hack。从代码中可以看出,使其非交互性是一种令人不快的黑客行为。
  • 在几乎所有情况下,session.setPassword(pstr) 都适用于“键盘交互”身份验证方法。你试过了吗?
  • @paulo,非常感谢您以良好的顺序重新格式化问题。看起来清晰很多。
  • 我刚刚检查了 promptKeyboardInteractive() ,使它简单地传递了一个字符串(因此无法发送 null ),但是,这个错误仍然出现。这是糟糕的测试技巧。 public String[] promptKeyboardInteractive (String destination, String name, String instruction, String[] prompt, boolean[] echo) { System.out.println("\n"+prompt.length+"\n\n"); String[] response=new String[prompt.length]; response[0] = passwd; return response; } 正在尝试其他一些事情,将继续发布此主题。
  • 我猜 response[0] 为空,因为 'passwd' 为空。
猜你喜欢
  • 2012-12-22
  • 2020-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
  • 1970-01-01
  • 2015-07-06
相关资源
最近更新 更多