I’m trying to write a Java code that can ssh into a Unix server and reset a user’s password. So I tried to implement some of the code found in SO.
Eg.
- Sending commands to remote server through ssh by Java with JSch
- Take commands(password) from string and set as InputStream to Unix servers in Java (JSCH)
Using JSch ChannelExec
, I followed this link to get the proper command for resetting user’s password.
When I tried running this code, seems like it doesn’t reset the user’s password. So I tried running the command directly from the Unix’s shell, and the command work perfectly. I assume that the exec didn’t work at all. I changed the exec to run a simple command like mkdir /home/fikrie/testingjsch
which then prove my assumption, seeing that directory were not created.
This is my code:
public void executeSetPassword(final String userName, final GuardedString password) { JSch jsch = new JSch(); String host = configuration.getHost(); String remoteUser = configuration.getRemoteUser(); GuardedString passwd = configuration.getPassword(); String command = "echo " + userName + ":" + password + " | chpasswd"; Boolean sessionStatus, channelStatus; logger.info("userName is " + userName); logger.info("password is " + password); logger.info("command is " + command); 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(); sessionStatus = session.isConnected(); logger.info("sessionStatus is " + sessionStatus); ChannelExec channel=(ChannelExec) session.openChannel("exec"); channel.setCommand(command); channel.connect(); channelStatus = channel.isConnected(); logger.info("channelStatus is " + channelStatus); logger.info("Exit status = " + channel.getExitStatus()); channel.disconnect(); session.disconnect(); } catch (Exception e) { throw new RuntimeException(e); } }
What am I missing actually? The session and channel seems to be alive but it doesn’t execute the command. This is the log for the code:
Method: executeSetPassword(UnixConnector.java:230) Level: INFO Message: userName is anne Method: executeSetPassword(UnixConnector.java:231) Level: INFO Message: password is org.identityconnectors.common.security.GuardedString@e492109 Method: executeSetPassword(UnixConnector.java:232) Level: INFO Message: command is echo anne:org.identityconnectors.common.security.GuardedString@e492109 | chpasswd Method: executeSetPassword(UnixConnector.java:249) Level: INFO Message: sessionStatus is true Method: executeSetPassword(UnixConnector.java:257) Level: INFO Message: channelStatus is true Method: executeSetPassword(UnixConnector.java:258) Level: INFO Message: Exit status = -1
This is the JSch Log:
INFO: Connecting to 192.168.1.62 port 22 INFO: Connection established INFO: Remote version string: SSH-2.0-OpenSSH_5.3 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-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1 INFO: kex: server: ssh-rsa,ssh-dss INFO: kex: server: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se INFO: kex: server: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se INFO: kex: server: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 INFO: kex: server: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 INFO: kex: server: none,zlib@openssh.com INFO: kex: server: none,zlib@openssh.com INFO: kex: server: INFO: kex: server: INFO: kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,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.62' (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: gssapi-with-mic,publickey,keyboard-interactive,password INFO: Next authentication method: gssapi-with-mic INFO: Authentications that can continue: publickey,keyboard-interactive,password INFO: Next authentication method: publickey INFO: Authentications that can continue: password INFO: Next authentication method: password INFO: Authentication succeeded (password). INFO: Disconnecting from 192.168.1.62 port 22 INFO: Caught an exception, leaving main loop due to Socket closed
Advertisement
Answer
I assume the problem is that you close the connection before the command is even started.
All the examples your pointed to read a command output, until the end (hence until the command finishes). You do not read the output so you fail to wait for the command to finish.
Either consume the command output as the other examples do. Or (if you are not interested in the output) wait until channel.isClosed()
is true before exiting.