//password is must for key distribution
if (passwd == null) {
throw new IOException("SSH password is required for distributing the public key. You can specify the SSH password in a password file and pass it through --passwordfile option.");
}
connection = new Connection(node, port);
connection.connect();
connected = connection.authenticateWithPassword(userName, passwd);
if(!connected) {
throw new IOException("SSH password authentication failed for user " + userName + " on host " + node);
}
//We open up a second connection for scp and exec. For some reason, a hang
//is seen in MKS if we try to do everything using the same connection.
Connection conn = new Connection(node, port);
conn.connect();
boolean ret = conn.authenticateWithPassword(userName, passwd);
if (!ret) {
throw new IOException("SSH password authentication failed for user " + userName + " on host " + node);
}
//initiate scp client
SCPClient scp = new SCPClient(conn);
SFTPClient sftp = new SFTPClient(connection);
if (key.exists()) {
//fixes .ssh file mode
setupSSHDir();
if (pubKeyFile == null) {
pubKeyFile = keyFile + ".pub";
}
File pubKey = new File(pubKeyFile);
if(!pubKey.exists()) {
throw new IOException("Public key file " + pubKeyFile + " does not exist.");
}
try {
if(!sftp.exists(SSH_DIR)) {
if(logger.isLoggable(Level.FINER)) {
logger.fine(SSH_DIR + " does not exist");
}
sftp.mkdirs(".ssh", 0700);
}
} catch (Exception e) {
if(logger.isLoggable(Level.FINER)) {
e.printStackTrace();
}
throw new IOException("Error while creating .ssh directory on remote host:" + e.getMessage());
}
//copy over the public key to remote host
scp.put(pubKey.getAbsolutePath(), "key.tmp", ".ssh", "0600");
//append the public key file contents to authorized_keys file on remote host
String mergeCommand = "cd .ssh; cat key.tmp >> " + AUTH_KEY_FILE;
if(logger.isLoggable(Level.FINER)) {
logger.finer("mergeCommand = " + mergeCommand);
}
if(conn.exec(mergeCommand, new ByteArrayOutputStream())!=0) {
throw new IOException("Failed to propogate the public key " + pubKeyFile + " to " + host);
}
logger.info("Copied keyfile " + pubKeyFile + " to " + userName + "@" + host);
//remove the public key file on remote host
if(conn.exec("rm .ssh/key.tmp", new ByteArrayOutputStream())!=0) {
logger.warning("WARNING: Failed to remove the public key file key.tmp on remote host " + host);
}
if(logger.isLoggable(Level.FINER)) {
logger.finer("Removed the temporary key file on remote host");
}
//Lets fix all the permissions
//On MKS, chmod doesn't work as expected. StrictMode needs to be disabled
//for connection to go through
logger.info("Fixing file permissions for home(755), .ssh(700) and authorized_keys file(644)");
sftp.chmod(".", 0755);
sftp.chmod(SSH_DIR, 0700);
sftp.chmod(SSH_DIR + AUTH_KEY_FILE, 0644);
connection.close();
conn.close();
}
}