removing user interaction from java jsch

814 views Asked by At

I'm trying to write a Java code that can ssh to a unix server and reset a user's password. I use jsch for the connection and command execution. I tested on few servers (CentOS, Ubuntu, HP-UX) and it works fine.

When I tested on AIX, I got this problem where it prompt for user's New password. My program will just hang until a timeout occured. Then an error will comeout. I did google on how to prevent the user interaction here, but unfortunately, the AIX that I'm working on doesn't have chpasswd. While googling more about the error code here, I found out about expect4j library that can be used for this case.

I tried following some example like here and applied into my code.

This is my code:

public void executeSetPassword(final String userName, final GuardedString password)  {
    JSch.setLogger(new JSCHLogger());
    if ((userName != null) && (password != null)) {
        JSch jsch = new JSch();
        String host = configuration.getHost();
        String remoteUser = configuration.getRemoteUser();
        GuardedString passwd = configuration.getPassword();

        final Session session;
        try {
            session = jsch.getSession(remoteUser, host, 22);

            passwd.access(new Accessor(){
                @Override
                public void access(char[] clearChars) {
                    session.setPassword(new String(clearChars));
                }});

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.connect();

            logger.info("sessionStatus is " + session.isConnected());
            final ChannelExec channel=(ChannelExec) session.openChannel("exec");

            password.access(new Accessor() {
              @Override
              public void access(char[] clearChars) {
              channel.setCommand("echo -e " + "\"" + new String(clearChars) + "\\n" + new String(clearChars) + "\"" + " | passwd " + userName + ";pwdadm -c " + userName);
                    }});

            channel.setErrStream(System.err);
            channel.setPty(true);

            final Expect4j expect = new Expect4j(channel.getInputStream(), channel.getOutputStream());
            channel.connect();

            final StringBuilder buffer = new StringBuilder();
            Closure closure = new Closure() {
                        public void run(ExpectState expectState) throws Exception {
                            buffer.append(expectState.getBuffer());//string buffer for appending output of executed command
                        }
            };

            expect.expect("New password");
            password.access(new Accessor() {
                @Override
                public void access(char[] clearChars) {
                    try {
                        expect.send(new String(clearChars));
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }});

            BufferedReader reader;
            try {
                reader = new BufferedReader(new InputStreamReader(channel.getInputStream()));
                String line;
                while ((line = reader.readLine()) != null) {
                    logger.info(line);
                    if( line.contains("New password:") == true) {
                        logger.info("set something here");
                    }
                }
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            if(channel.isClosed()) {
                channel.disconnect();
                session.disconnect();
                expect.close();
                logger.info("Exit status = " + channel.getExitStatus());
            }

        }
        catch ( Exception e) {
            throw new RuntimeException(e);
        }
    }

When I tried running it, the same thing happens. Does it mean that my expect is not working correctly?

This is the log:

INFO: Connecting to 192.168.1.39 port 22
INFO: Connection established
INFO: Remote version string: SSH-1.99-OpenSSH_3.8.1p1
INFO: Local version string: SSH-2.0-JSCH-0.1.53
INFO: CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256
INFO: aes256-ctr is not available.
INFO: aes192-ctr is not available.
INFO: aes256-cbc is not available.
INFO: aes192-cbc is not available.
INFO: CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521
INFO: CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
INFO: SSH_MSG_KEXINIT sent
INFO: SSH_MSG_KEXINIT received
INFO: kex: server: diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1
INFO: kex: server: ssh-rsa,ssh-dss
INFO: kex: server: aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,[email protected],aes128-ctr,aes192-ctr,aes256-ctr
INFO: kex: server: aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc,[email protected],aes128-ctr,aes192-ctr,aes256-ctr
INFO: kex: server: hmac-md5,hmac-sha1,hmac-ripemd160,[email protected],hmac-sha1-96,hmac-md5-96
INFO: kex: server: hmac-md5,hmac-sha1,hmac-ripemd160,[email protected],hmac-sha1-96,hmac-md5-96
INFO: kex: server: none,zlib
INFO: kex: server: none,zlib
INFO: kex: server: 
INFO: kex: server: 
INFO: kex: client: diffie-hellman-group1-sha1
INFO: kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521
INFO: kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc
INFO: kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc
INFO: kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
INFO: kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96
INFO: kex: client: none
INFO: kex: client: none
INFO: kex: client: 
INFO: kex: client: 
INFO: kex: server->client aes128-ctr hmac-md5 none
INFO: kex: client->server aes128-ctr hmac-md5 none
INFO: SSH_MSG_KEXDH_INIT sent
INFO: expecting SSH_MSG_KEXDH_REPLY
INFO: ssh_rsa_verify: signature true
WARN: Permanently added '192.168.1.39' (RSA) to the list of known hosts.
INFO: SSH_MSG_NEWKEYS sent
INFO: SSH_MSG_NEWKEYS received
INFO: SSH_MSG_SERVICE_REQUEST sent
INFO: SSH_MSG_SERVICE_ACCEPT received
INFO: Authentications that can continue: publickey,keyboard-interactive,password
INFO: Next authentication method: publickey
INFO: Authentications that can continue: keyboard-interactive,password
INFO: Next authentication method: keyboard-interactive
INFO: Authentications that can continue: password
INFO: Next authentication method: password
INFO: Authentication succeeded (password).
Thread Id: 1    Time: 2015-06-18 13:44:07.318   Class: com.mastersam.connectors.unix.UnixConnector  Method: executeSetPassword(UnixConnector.java:421)  Level: INFO Message: 3004-709 Error changing password for "fikrie".

I also tried changing ssh channel instead of exec. This is the code after changing it:

    final ChannelShell channel=(ChannelShell) session.openChannel("shell");

    channel.setPty(true);
    final Expect4j expect = new Expect4j(channel.getInputStream(), channel.getOutputStream());
    channel.connect();
    final StringBuilder buffer = new StringBuilder();
    Closure closure = new Closure() {
              public void run(ExpectState expectState) throws Exception {
                    buffer.append(expectState.getBuffer());
              }
    };

    password.access(new Accessor() {
                @Override
                public void access(char[] clearChars) {
                    try {
                        expect.send(echo -e " + "\"" + new String(clearChars) + "\\n" + new String(clearChars) + "\"" + " | passwd " + userName);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }});
0

There are 0 answers