2

I am trying to execute commands remotely on a server under su. Specifically, I am remotely executing:

su -c '[command]'

This works when I am logged into the remote server. My code to connect a session and run the command remotely looks something like this:

My question is hopefully pretty simple: How do I check if out.write is replying to the password prompt provided in a su command? Channels seem to be connected, and the program appears to work as long as su is not involved.

Ideally the sequence for action is:

remote command initialized -> prompt for password -> input password remotely [failure point] -> execute command

It must be su. It cannot be sudo.

/**
 * Method to connect to session.  
 */
protected void connectSession(Session session){
    try {

        //connect to session and open exec channel
        session.connect();
        channel=session.openChannel("exec");

        ((ChannelExec)channel).setCommand(command); //set the command 
        ((ChannelExec)channel).setPty(true); //set PTY tru for Password input
        ((ChannelExec)channel).setErrStream(System.err);

        in = channel.getInputStream(); //set input stream
        out=channel.getOutputStream(); //set output stream and connect
        channel.connect();

        System.out.println("Channel was connected");
        out.write((sudo_pass+"\n").getBytes()); //write password upon prompt
        out.flush();

        //I believe the out.write and the out.flush section is not working. It probably breaks right before here. 

        System.out.println("Wrote sudo Pass");

    } catch (JSchException | IOException e) {
        System.out.println("Could not connect to session");
        e.printStackTrace();
    }
}
@Override
protected Integer RunCommand() throws Exception {
    int j = 0;
    System.out.println("Running command: " + command);  
    connectSession(session);

    byte[] tmp=new byte[1024];
    while(in.available()>0){
        int i=in.read(tmp, 0, 1024);
        if(i<0)break;
        System.out.print(new String(tmp, 0, i));
    }

    if(channel.isClosed()){
        if(in.available()>0) continue; 
        System.out.println("exit-status: "+channel.getExitStatus());
        break;
    }

    try{Thread.sleep(1000);}
    catch(Exception ee){}
    channel.disconnect();
}

I've borrowed heavily from:

Hopes this helps anyone with similar problem!

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
andor kesselman
  • 1,089
  • 2
  • 15
  • 26
  • *How do I ensure that I am writing to the Output Stream the password?* - What does that mean? – Martin Prikryl Apr 15 '16 at 05:49
  • On this line: out.write((sudo_pass+"\n").getBytes()); //write password upon prompt I believe that the out is writing the su password to the prompt. The problem is that while this solution works for the http://www.jcraft.com/jsch/examples/Sudo.java.html, "su" does not have the -p option and I do not believe the out.write function is actually inputting the password once prompted. I've considered expect scripts, but looking for a more elegant solution. – andor kesselman Apr 15 '16 at 06:35
  • Edited the question to be more clear. "How do I check if out.write is replying to the password prompt provided in a su command" – andor kesselman Apr 15 '16 at 06:37
  • The `sudo -p` switch just changes the prompt message, it does not affect how the input is read. Both `sudo` and `su` just reads the password when started. They are the same in this respect, ain't they? – Martin Prikryl Apr 15 '16 at 06:39
  • What do you want to check? If there's any prompt *before* you write the password (=if the other side is actually expecting the password)? Or if the password is correctly processed *after* your write it? – Martin Prikryl Apr 15 '16 at 06:40
  • Hi @MartinPrikryl thanks for requesting clarity. I want to make sure the password is correctly processed after the prompt. So ideally, the sequence would be: remote command -> prompt -> password received -> task executed. I have edited the original post to hopefully reflect better clarity. – andor kesselman Apr 15 '16 at 06:50

1 Answers1

1

The su command aborts and returns non-zero exit code, if you enter a wrong password.

So, you simply check, if the "exec" channel closes after you enter the password. If it does close, you have "entered" a wrong password.

If you enter a correct password, the su starts a shell and keeps waiting for commands (or executed the command specified by the -c)


Note that su command is specifically designed not to be automated. Trying to automate is a wrong.

The correct ways include:

  • using password-less sudo command limited to a single script for your particular task
  • using private key for root user limited to a single script for your particular task
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992