|
From: <ha...@us...> - 2007-11-23 21:24:50
|
Revision: 1840
http://cogkit.svn.sourceforge.net/cogkit/?rev=1840&view=rev
Author: hategan
Date: 2007-11-23 13:24:48 -0800 (Fri, 23 Nov 2007)
Log Message:
-----------
new ssh stuff
Added Paths:
-----------
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/ConnectionID.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/CredentialsDialog.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/InteractiveSSHSecurityContextImpl.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannel.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannelManager.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHConnectionBundle.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHRunner.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHSecurityContextImpl.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTask.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTaskStatusListener.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/Ssh.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/DelegatedTaskHandlerFactory.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/Exec.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/FileTransferTaskHandler.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/JobSubmissionTaskHandler.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/OutputListener.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/Sftp.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/TaskHandlerImpl.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/file/
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/file/FileResourceImpl.java
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/file/TaskHandlerImpl.java
Removed Paths:
-------------
trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/execution/
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/ConnectionID.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/ConnectionID.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/ConnectionID.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,51 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Nov 20, 2007
+ */
+package org.globus.cog.abstraction.impl.ssh;
+
+public class ConnectionID {
+ public String host;
+ public int port;
+ public Object credentials;
+
+ public ConnectionID(String host, int port, Object credentials) {
+ this.host = host;
+ this.port = port;
+ this.credentials = credentials;
+ }
+
+ public boolean equals(Object obj) {
+ if (obj instanceof ConnectionID) {
+ ConnectionID other = (ConnectionID) obj;
+ return eq(host, other.host) && port == other.port
+ && eq(credentials, other.credentials);
+ }
+ else {
+ return false;
+ }
+ }
+
+ private boolean eq(Object o1, Object o2) {
+ if (o1 == null) {
+ return o2 == null;
+ }
+ else {
+ return o1.equals(o2);
+ }
+ }
+
+ public int hashCode() {
+ return (host == null ? 0 : host.hashCode()) + port
+ + (credentials == null ? 0 : credentials.hashCode());
+ }
+
+ public String toString() {
+ return credentials + "@" + host + ":" + port;
+ }
+}
\ No newline at end of file
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/CredentialsDialog.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/CredentialsDialog.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/CredentialsDialog.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,347 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.GraphicsEnvironment;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.PasswordAuthentication;
+import java.util.Arrays;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+
+import org.globus.cog.abstraction.impl.common.PublicKeyAuthentication;
+
+public abstract class CredentialsDialog {
+ private static final String NOTHING = "";
+ private static final String SSH_HOME = System.getProperty("user.home") + File.separator
+ + ".ssh";
+
+ protected String userName, privateKey;
+
+ public String getPrivateKey() {
+ return privateKey;
+ }
+
+ public void setPrivateKey(String privatekey) {
+ this.privateKey = privatekey;
+ }
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String username) {
+ this.userName = username;
+ }
+
+ public abstract Object getResult();
+
+ public static Object showCredentialsDialog() {
+ return showCredentialsDialog(null, null);
+ }
+
+ public static Object showCredentialsDialog(String userName, String privateKey) {
+ return showCredentialsDialog(userName, privateKey, false);
+ }
+
+ public static Object showCredentialsDialog(String userName, String privateKey,
+ boolean forceTextMode) {
+ CredentialsDialog cd;
+ try {
+ if (GraphicsEnvironment.isHeadless() || forceTextMode) {
+ cd = new ConsoleCredentialsDialog();
+ }
+ else {
+ cd = new SwingCredentialsDialog();
+ }
+ }
+ catch (Exception e) {
+ cd = new ConsoleCredentialsDialog();
+ }
+ if (userName != null) {
+ cd.setUserName(userName);
+ }
+ if (privateKey != null) {
+ cd.setPrivateKey(privateKey);
+ }
+ return cd.getResult();
+ }
+
+ public static class SwingCredentialsDialog extends CredentialsDialog {
+ private JOptionPane optionPane = new JOptionPane();
+ private JDialog dialog;
+
+ private JLabel passwordLabel;
+ private JTextField usernameField = new JTextField();
+ private JPasswordField passwordField = new JPasswordField();
+ private JTextField privateKeyField = new JTextField();
+
+ private JButton choosePathButton = new JButton("Browse");
+
+ public SwingCredentialsDialog() {
+ // init sizes
+ usernameField.setPreferredSize(new Dimension(125, 20));
+ passwordField.setPreferredSize(new Dimension(125, 20));
+ privateKeyField.setPreferredSize(new Dimension(150, 20));
+
+ // the main panel
+ JPanel main = new JPanel(new BorderLayout());
+
+ // Labels
+ JPanel labels = new JPanel(new GridLayout(0, 1));
+ labels.add(new JLabel("Username: "));
+ labels.add(passwordLabel = new JLabel("Password: "));
+ JLabel pkLabel = new JLabel("Private Key: ");
+ pkLabel.setToolTipText("Your private key if needed, else leave blank");
+ labels.add(pkLabel);
+
+ // username and password labels/fields
+ JPanel fields = new JPanel(new GridLayout(0, 1));
+ fields.add(usernameField);
+ fields.add(passwordField);
+
+ // path to the private key field/button
+ JPanel pKeyPanel = new JPanel(new BorderLayout());
+ privateKeyField.setToolTipText("Your private key if needed, else leave blank");
+ pKeyPanel.add(privateKeyField, BorderLayout.CENTER);
+ pKeyPanel.add(choosePathButton, BorderLayout.EAST);
+
+ // add an action listener
+ choosePathButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent aEvent) {
+ choosePathToPrivateKey();
+ }
+ });
+
+ fields.add(pKeyPanel);
+
+ main.add(labels, BorderLayout.WEST);
+ main.add(fields, BorderLayout.CENTER);
+
+ optionPane.setMessage(main);
+ optionPane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
+ dialog = optionPane.createDialog(null, "Enter Your SSH Credentials");
+ }
+
+ protected void choosePathToPrivateKey() {
+ JFileChooser fileChooser = new JFileChooser(SSH_HOME);
+ fileChooser.setFileHidingEnabled(false);
+ int returnVal = fileChooser.showOpenDialog(optionPane);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ setPrivateKeyFieldText(fileChooser.getSelectedFile().getAbsolutePath());
+ }
+ }
+
+ protected synchronized Object okButtonPushed() {
+ String uname = usernameField.getText();
+ char[] passwd = passwordField.getPassword();
+ String pKeyPath = privateKeyField.getText();
+
+ if (NOTHING.equals(uname) && NOTHING.equals(passwd) && NOTHING.equals(pKeyPath)) {
+ return null;
+ }
+ else if (passwd == null) { // prevent null pointers
+ return null;
+ }
+ else if (NOTHING.equals(pKeyPath)) {
+ return new PasswordAuthentication(uname, passwd);
+ }
+ else {
+ return new PublicKeyAuthentication(uname, pKeyPath, passwd);
+ }
+ }
+
+ public Object getResult() {
+ dialog.setVisible(true);
+ if (optionPane.getValue() != null
+ && ((Integer) optionPane.getValue()).equals(new Integer(JOptionPane.OK_OPTION))) {
+ return okButtonPushed();
+ }
+ else {
+ return null;
+ }
+ }
+
+ public void setPrivateKey(String privatekey) {
+ super.setPrivateKey(privatekey);
+ setPrivateKeyFieldText(privatekey);
+ }
+
+ private void setPrivateKeyFieldText(String privateKey) {
+ privateKeyField.setText(privateKey);
+ if (privateKey == null || privateKey.equals("")) {
+ passwordLabel.setText("Password: ");
+ }
+ else {
+ passwordLabel.setText("Passphrase: ");
+ }
+ }
+
+ public void setUserName(String username) {
+ super.setUserName(username);
+ usernameField.setText(username);
+ if (username != null) {
+ passwordField.requestFocus();
+ }
+ }
+
+ }
+
+ public static class ConsoleCredentialsDialog extends CredentialsDialog {
+ public String TAB = "\t";
+ public static final int MAX_MASKED_CHARS = 80;
+
+ public Object getResult() {
+ if (userName == null) {
+ System.out.print("Username: ");
+ userName = input();
+ }
+ else {
+ System.out.println("Username: " + userName);
+ }
+ if (privateKey == null) {
+ System.out.println("Empty password for public key authentication.");
+ System.out.print("Password: ");
+ char[] tmp = inputMasked();
+ if (tmp.length == 0) {
+ for (int i = 0; i < 80; i++) {
+ System.out.print('\b');
+ }
+ String defaultPK = getDefaultPrivateKey();
+ System.out.println("Private key file ["+defaultPK+"]: ");
+ privateKey = input();
+ if (privateKey == null || privateKey.equals("")) {
+ privateKey = defaultPK;
+ }
+ System.out.print("Passphrase: ");
+ return new PublicKeyAuthentication(userName, privateKey, inputMasked());
+ }
+ else {
+ return new PasswordAuthentication(userName, tmp);
+ }
+ }
+ else {
+ System.out.println("Private key: " + privateKey);
+ System.out.print("Passphrase: ");
+ return new PublicKeyAuthentication(userName, privateKey, inputMasked());
+ }
+ }
+
+ protected String getDefaultPrivateKey() {
+ File pk;
+ pk = new File(SSH_HOME, "identity");
+ if (pk.exists()) {
+ return pk.getAbsolutePath();
+ }
+ pk = new File(SSH_HOME);
+ if (pk.exists()) {
+ return pk.getAbsolutePath();
+ }
+ return "";
+ }
+
+ protected String input() {
+ BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
+ try {
+ return br.readLine();
+ }
+ catch (IOException e) {
+ return "";
+ }
+ }
+
+ protected synchronized char[] inputMasked() {
+ char[] buf = new char[MAX_MASKED_CHARS];
+ int crt = 0;
+ char c;
+ ConsoleMasker.startMasking();
+ while (crt < MAX_MASKED_CHARS) {
+ try {
+ c = (char) System.in.read();
+ if (c == '\n') {
+ break;
+ }
+ else {
+ buf[crt++] = c;
+ }
+ }
+ catch (IOException e) {
+ break;
+ }
+ }
+ ConsoleMasker.stopMasking();
+ char[] in = new char[crt];
+ System.arraycopy(buf, 0, in, 0, crt);
+ Arrays.fill(buf, '\0');
+ return in;
+ }
+ }
+
+ public static class ConsoleMasker extends Thread {
+ private static ConsoleMasker masker;
+ private volatile boolean done;
+
+ public synchronized static void startMasking() {
+ if (masker != null) {
+ throw new IllegalStateException("Another maskeing thread");
+ }
+ masker = new ConsoleMasker();
+ masker.start();
+ }
+
+ public synchronized static void stopMasking() {
+ if (masker == null) {
+ throw new IllegalStateException("No masking thread is active");
+ }
+ masker.done();
+ masker = null;
+ }
+
+ public ConsoleMasker() {
+ this.setPriority(Thread.MAX_PRIORITY);
+ this.setName("Console Masking");
+ }
+
+ public void run() {
+ System.out.print(' ');
+ char crt = ' ';
+ while (!done) {
+ System.out.print('\b');
+ System.out.print(crt++);
+ System.out.flush();
+ if (crt == 127) {
+ crt = ' ';
+ }
+ try {
+ Thread.sleep(1);
+ }
+ catch (InterruptedException e) {
+ return;
+ }
+ }
+ }
+
+ private void done() {
+ done = true;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/InteractiveSSHSecurityContextImpl.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/InteractiveSSHSecurityContextImpl.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/InteractiveSSHSecurityContextImpl.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,72 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.net.PasswordAuthentication;
+import java.util.Hashtable;
+
+import org.apache.log4j.Logger;
+import org.globus.cog.abstraction.interfaces.SecurityContext;
+
+public class InteractiveSSHSecurityContextImpl implements SecurityContext {
+
+ private static Logger logger = Logger.getLogger(InteractiveSSHSecurityContextImpl.class.getName());
+ private Object credentials;
+
+ private Hashtable attributes = new Hashtable();
+
+ public InteractiveSSHSecurityContextImpl() {
+ // this.credentials = new PasswordAuthentication(null, null);
+ }
+
+ public InteractiveSSHSecurityContextImpl(Object credentials) {
+ setCredentials(credentials);
+ }
+
+ public void setCredentials(Object credentials, String alias) {
+ setCredentials(credentials);
+ }
+
+ public void setCredentials(Object credentials) {
+ this.credentials = credentials;
+ }
+
+ public synchronized Object getCredentials() {
+ if (credentials == null) {
+ boolean forceText = false;
+ Object text = getAttribute("nogui");
+ if (text != null
+ && (Boolean.TRUE.equals(text) || (text instanceof String && Boolean.valueOf(
+ (String) text).booleanValue()))) {
+ forceText = true;
+ }
+ credentials = CredentialsDialog.showCredentialsDialog(
+ (String) getAttribute("username"), (String) getAttribute("privatekey"), forceText);
+ if (credentials == null) {
+ // Cancel was pressed, so we set it to mock credentials to
+ // avoid being asked again
+ credentials = new PasswordAuthentication("", new char[0]);
+ }
+ }
+ return this.credentials;
+ }
+
+ public void setAttribute(String name, Object value) {
+ this.attributes.put(name, value);
+ }
+
+ public Object getAttribute(String name) {
+ return this.attributes.get(name);
+ }
+
+ public void setAlias(String alias) {
+ }
+
+ public String getAlias() {
+ return null;
+ }
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannel.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannel.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannel.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,38 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Nov 20, 2007
+ */
+package org.globus.cog.abstraction.impl.ssh;
+
+import com.sshtools.j2ssh.session.SessionChannelClient;
+
+public class SSHChannel {
+ private Ssh connection;
+ private SessionChannelClient session;
+ private SSHConnectionBundle bundle;
+
+ public SSHChannel(SSHConnectionBundle bundle, Ssh connection, SessionChannelClient session) {
+ this.connection = connection;
+ this.session = session;
+ this.bundle = bundle;
+ }
+
+ public Ssh getSsh() {
+ return connection;
+ }
+
+ public SessionChannelClient getSession() {
+ return session;
+ }
+
+ public SSHConnectionBundle getBundle() {
+ return bundle;
+ }
+
+
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannelManager.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannelManager.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHChannelManager.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,204 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Nov 19, 2007
+ */
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.PasswordAuthentication;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Map.Entry;
+
+import org.apache.log4j.Logger;
+import org.globus.cog.abstraction.impl.common.PublicKeyAuthentication;
+import org.globus.cog.abstraction.impl.common.task.IllegalSpecException;
+import org.globus.cog.abstraction.impl.common.task.InvalidSecurityContextException;
+import org.globus.cog.abstraction.impl.common.task.InvalidServiceContactException;
+import org.globus.cog.abstraction.impl.common.task.TaskSubmissionException;
+
+public class SSHChannelManager {
+ public static final Logger logger = Logger
+ .getLogger(SSHChannelManager.class);
+
+ public static final long REAP_INTERVAL = 10 * 1000;
+
+ private static SSHChannelManager defaultManager;
+
+ static {
+ defaultManager = new SSHChannelManager();
+ }
+
+ public static SSHChannelManager getDefault() {
+ return defaultManager;
+ }
+
+ private Map bundles;
+ private Reaper reaper;
+
+ public SSHChannelManager() {
+ bundles = new HashMap();
+ reaper = new Reaper();
+ reaper.start();
+ }
+
+ public SSHChannel getChannel(String host, int port, Object credentials)
+ throws InvalidSecurityContextException, IllegalSpecException,
+ InvalidServiceContactException, TaskSubmissionException {
+ if (port == -1) {
+ port = 22;
+ }
+ ConnectionID i = new ConnectionID(host, port, getCredentials(credentials, host));
+ SSHConnectionBundle bundle = null;
+ synchronized (bundles) {
+ bundle = (SSHConnectionBundle) bundles.get(i);
+ if (bundle == null) {
+ bundle = new SSHConnectionBundle(i);
+ bundles.put(i, bundle);
+ }
+ }
+ return bundle.allocateChannel();
+ }
+
+ private static final char[] NO_PASSPHRASE = new char[0];
+
+ public static Object getCredentials(Object credentials, String host)
+ throws InvalidSecurityContextException {
+ if (credentials == null) {
+ credentials = getDefaultCredentials(host);
+ }
+ if (credentials instanceof PasswordAuthentication) {
+ return credentials;
+ }
+ else if (credentials instanceof PublicKeyAuthentication) {
+ return credentials;
+ }
+ else if (credentials == null) {
+ throw new InvalidSecurityContextException(
+ "No credentials specified and no entry found in "
+ + getAuthFilePath() + " for " + host);
+ }
+ else {
+ throw new InvalidSecurityContextException(
+ "Unsupported credentials: " + credentials);
+ }
+ }
+
+ public void releaseChannel(SSHChannel s) {
+ s.getBundle().releaseChannel(s);
+ }
+
+ private static Map credentials;
+ private static long lastLoad;
+ public static final String CREDENTIALS_FILE = "auth.defaults";
+
+ static {
+ credentials = new HashMap();
+ }
+
+ private static String getAuthFilePath() {
+ return System.getProperty("user.home") + File.separator + ".ssh"
+ + File.separator + CREDENTIALS_FILE;
+ }
+
+ public static Object getDefaultCredentials(String host) {
+ File f = new File(getAuthFilePath());
+ if (f.exists()) {
+ if (lastLoad < f.lastModified()) {
+ try {
+ loadDefaultCredentials(f);
+ }
+ catch (IOException e) {
+ logger.warn("Failed to load default credentials file", e);
+ }
+ }
+ synchronized (credentials) {
+ return credentials.get(host);
+ }
+ }
+ else {
+ return null;
+ }
+ }
+
+ public static void loadDefaultCredentials(File f) throws IOException {
+ synchronized (credentials) {
+ credentials.clear();
+ Properties p = new Properties();
+ p.load(new FileInputStream(f));
+ Iterator i = p.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
+ String key = (String) e.getKey();
+ String val = (String) e.getValue();
+ if (key.endsWith(".type")) {
+ String host = key.substring(0, key.length() - 5);
+ String username = p.getProperty(host + ".username");
+ if (username == null) {
+ username = System.getProperty("user.name");
+ }
+ Object auth = null;
+ if ("password".equals(val)) {
+ String password = p.getProperty(host + ".password");
+ auth = new PasswordAuthentication(username, password
+ .toCharArray());
+ }
+ else if ("key".equals(val)) {
+ String pkey = p.getProperty(host + ".key");
+ String passphrase = p.getProperty(host + ".passphrase");
+ auth = new PublicKeyAuthentication(username, pkey,
+ passphrase.toCharArray());
+ }
+ else {
+ logger.warn("Unknown authentication type for \"" + host
+ + "\": " + val);
+ }
+ credentials.put(host, auth);
+ }
+ }
+ lastLoad = System.currentTimeMillis();
+ }
+ }
+
+ private class Reaper extends Thread {
+ public Reaper() {
+ super("SSH Channel Reaper");
+ setDaemon(true);
+ }
+
+ public void run() {
+ try {
+ List shutdown = new ArrayList();
+ while (true) {
+ shutdown.clear();
+ Thread.sleep(REAP_INTERVAL);
+ synchronized (bundles) {
+ Iterator i = bundles.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Entry) i.next();
+ ConnectionID ix = (ConnectionID) e.getKey();
+ SSHConnectionBundle bundle = (SSHConnectionBundle) e.getValue();
+ if (!bundle.shutdownIdleConnections()) {
+ i.remove();
+ }
+ }
+ }
+ }
+ }
+ catch (InterruptedException e) {
+
+ }
+ }
+ }
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHConnectionBundle.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHConnectionBundle.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHConnectionBundle.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,254 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Nov 20, 2007
+ */
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.io.IOException;
+import java.net.PasswordAuthentication;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.globus.cog.abstraction.impl.common.PublicKeyAuthentication;
+import org.globus.cog.abstraction.impl.common.task.InvalidSecurityContextException;
+import org.globus.cog.abstraction.impl.common.task.InvalidServiceContactException;
+import org.globus.cog.abstraction.impl.common.task.TaskSubmissionException;
+
+public class SSHConnectionBundle {
+ public static final Logger logger = Logger
+ .getLogger(SSHConnectionBundle.class);
+
+ public static final long MAX_IDLE_TIME = 60 * 1000;
+ public static final int MAX_SESSIONS_PER_CONNECTION = 10;
+ public static final int MAX_CONCURRENT_CONNECTIONS = 10;
+
+ private List connections;
+ private ConnectionID id;
+ private Object credentials;
+ private int connecting;
+
+ public SSHConnectionBundle(ConnectionID id) {
+ this.id = id;
+ connections = new ArrayList();
+ if (logger.isDebugEnabled()) {
+ logger.debug("New SSH connection bundle: " + id);
+ }
+ }
+
+ public ConnectionID getId() {
+ return id;
+ }
+
+ public Object getCredentials() {
+ return credentials;
+ }
+
+ public void setCredentials(Object credentials) {
+ this.credentials = credentials;
+ }
+
+ public SSHChannel allocateChannel() throws InvalidSecurityContextException,
+ InvalidServiceContactException, TaskSubmissionException {
+ Connection connection = null;
+ synchronized (connections) {
+ Iterator i = connections.iterator();
+ while (i.hasNext()) {
+ Connection c = (Connection) i.next();
+ if (c.sessionCount < MAX_SESSIONS_PER_CONNECTION) {
+ connection = c;
+ break;
+ }
+ }
+ if (connection == null) {
+ connection = newConnection();
+ connections.add(connection);
+ }
+ connection.sessionCount++;
+ }
+ try {
+ connection.ensureConnected();
+ }
+ catch (Exception e) {
+ badSsh(connection.ssh);
+ rethrow(e);
+ }
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Creating new SSH session to " + id);
+ }
+ return new SSHChannel(this, connection.ssh, connection.ssh
+ .openSessionChannel());
+ }
+ catch (IOException e) {
+ throw new TaskSubmissionException("Failed to create SSH session", e);
+ }
+ }
+
+ private Connection newConnection() {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Creating new SSH connection to " + id);
+ }
+ Ssh ssh = new Ssh();
+ ssh.setHost(id.host);
+ ssh.setPort(id.port);
+ if (id.credentials instanceof PasswordAuthentication) {
+ PasswordAuthentication auth = (PasswordAuthentication) id.credentials;
+ ssh.setUsername(auth.getUserName());
+ ssh.setPassword(String.valueOf(auth.getPassword()));
+ }
+ else if (id.credentials instanceof PublicKeyAuthentication) {
+ PublicKeyAuthentication auth = (PublicKeyAuthentication) id.credentials;
+ ssh.setUsername(auth.getUsername());
+ ssh.setKeyfile(auth.getPrivateKeyFile().getAbsolutePath());
+ if (auth.getPassPhrase() != null) {
+ ssh.setPassphrase(String.valueOf(auth.getPassPhrase()));
+ }
+ }
+ Connection c = new Connection(ssh);
+ return c;
+ }
+
+ public void releaseChannel(SSHChannel s) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Releasing ssh channel for " + id);
+ }
+ try {
+ s.getSession().close();
+ }
+ catch (IOException e) {
+ badSsh(s.getSsh());
+ }
+ synchronized (connections) {
+ Ssh ssh = s.getSsh();
+ Iterator i = connections.iterator();
+ while (i.hasNext()) {
+ Connection c = (Connection) i.next();
+ if (c.ssh == ssh) {
+ c.sessionCount--;
+ if (c.sessionCount == 0) {
+ c.idleTime = System.currentTimeMillis();
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void badSsh(Ssh ssh) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Bad connection for " + id + ". Removing.");
+ }
+ synchronized (connections) {
+ Iterator i = connections.iterator();
+ while (i.hasNext()) {
+ Connection c = (Connection) i.next();
+ if (c.ssh == ssh) {
+ i.remove();
+ break;
+ }
+ }
+ }
+ }
+
+ public boolean shutdownIdleConnections() {
+ long crt = System.currentTimeMillis();
+ boolean anyActive = false;
+ synchronized (connections) {
+ Iterator i = connections.iterator();
+ while (i.hasNext()) {
+ Connection c = (Connection) i.next();
+ if (c.sessionCount == 0 && crt - c.idleTime > MAX_IDLE_TIME) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Shutting down idle connection for " + id);
+ }
+ c.ssh.disconnect();
+ }
+ else {
+ anyActive = true;
+ }
+ }
+ }
+ return anyActive;
+ }
+
+ private void rethrow(Exception e) throws InvalidSecurityContextException,
+ InvalidServiceContactException, TaskSubmissionException {
+ if (e instanceof InvalidSecurityContextException) {
+ throw (InvalidSecurityContextException) e;
+ }
+ if (e instanceof InvalidServiceContactException) {
+ throw (InvalidServiceContactException) e;
+ }
+ if (e instanceof TaskSubmissionException) {
+ throw (TaskSubmissionException) e;
+ }
+ if (e != null) {
+ throw new TaskSubmissionException(e);
+ }
+ }
+
+ private class Connection {
+ private Ssh ssh;
+ public int sessionCount;
+ public long idleTime;
+ private boolean fconnecting, fconnected;
+ private Exception connectionException;
+
+ public Connection(Ssh connection) {
+ this.ssh = connection;
+ }
+
+ public void ensureConnected() throws InvalidSecurityContextException,
+ InvalidServiceContactException, TaskSubmissionException {
+ try {
+ synchronized (this) {
+ while (fconnecting) {
+ wait();
+ }
+ if (fconnected) {
+ rethrow(connectionException);
+ return;
+ }
+ else {
+ fconnecting = true;
+ }
+ }
+ synchronized (id) {
+ connecting++;
+ while (connecting > MAX_CONCURRENT_CONNECTIONS) {
+ id.wait();
+ }
+ }
+ try {
+ ssh.connect();
+ }
+ catch (Exception e) {
+ synchronized (id) {
+ connectionException = e;
+ }
+ }
+ synchronized (id) {
+ connecting--;
+ id.notify();
+ }
+ synchronized (this) {
+ fconnecting = false;
+ fconnected = true;
+ notifyAll();
+ }
+ rethrow(connectionException);
+ }
+ catch (InterruptedException e) {
+ throw new TaskSubmissionException(
+ "Thread got interrupted while connecting", e);
+ }
+ }
+ }
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHRunner.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHRunner.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHRunner.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,87 @@
+// ----------------------------------------------------------------------
+// This code is developed as part of the Java CoG Kit project
+// The terms of the license can be found at http://www.cogkit.org/license
+// This message may not be removed or altered.
+// ----------------------------------------------------------------------
+
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.globus.cog.abstraction.impl.common.execution.JobException;
+import org.globus.cog.abstraction.impl.common.task.IllegalSpecException;
+import org.globus.cog.abstraction.impl.common.task.InvalidSecurityContextException;
+import org.globus.cog.abstraction.impl.common.task.InvalidServiceContactException;
+import org.globus.cog.abstraction.impl.common.task.TaskSubmissionException;
+
+public class SSHRunner implements Runnable {
+ private SSHTask crt;
+ private SSHChannel s;
+ private List listeners;
+ private boolean shutdownFlag;
+ private static int id;
+
+ public SSHRunner(SSHChannel s, SSHTask task) {
+ this.crt = task;
+ this.s = s;
+ }
+
+ public Thread wrapInThread() {
+ Thread t = new Thread(this);
+ synchronized (SSHRunner.class) {
+ t.setName("SSH Thread " + (id++));
+ }
+ t.setDaemon(true);
+ return t;
+ }
+
+ public void run() {
+ try {
+ runTask(crt);
+ notifyListeners(SSHTaskStatusListener.COMPLETED, null);
+ }
+ catch (Exception e) {
+ notifyListeners(SSHTaskStatusListener.FAILED, e);
+ }
+ }
+
+ public void runTask(SSHTask t) throws IllegalSpecException,
+ InvalidSecurityContextException, InvalidServiceContactException,
+ TaskSubmissionException, JobException {
+ t.execute(s.getSession());
+ }
+
+ public void startRun(SSHTask run) {
+ this.crt = run;
+ Thread t = wrapInThread();
+ t.start();
+ }
+
+ public void addListener(SSHTaskStatusListener l) {
+ if (listeners == null) {
+ listeners = new LinkedList();
+ }
+ if (!listeners.contains(l)) {
+ listeners.add(l);
+ }
+ }
+
+ public void removeListener(SSHTaskStatusListener l) {
+ if (listeners != null) {
+ listeners.remove(l);
+ }
+ }
+
+ public void clearListeners() {
+ listeners.clear();
+ }
+
+ public void notifyListeners(int event, Exception e) {
+ Iterator i = listeners.iterator();
+ while (i.hasNext()) {
+ ((SSHTaskStatusListener) i.next()).SSHTaskStatusChanged(event, e);
+ }
+ }
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHSecurityContextImpl.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHSecurityContextImpl.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHSecurityContextImpl.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,59 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.util.Hashtable;
+
+import org.apache.log4j.Logger;
+import org.globus.cog.abstraction.impl.common.task.InvalidSecurityContextException;
+import org.globus.cog.abstraction.interfaces.SecurityContext;
+
+public class SSHSecurityContextImpl implements SecurityContext {
+
+ private static Logger logger = Logger
+ .getLogger(SSHSecurityContextImpl.class.getName());
+ private Object credentials;
+
+ private Hashtable attributes = new Hashtable();
+
+ public SSHSecurityContextImpl() {
+ // this.credentials = new PasswordAuthentication(null, null);
+ }
+
+ public SSHSecurityContextImpl(Object credentials) {
+ setCredentials(credentials);
+ }
+
+ public void setCredentials(Object credentials, String alias) {
+ setCredentials(credentials);
+ }
+
+ public void setCredentials(Object credentials) {
+ this.credentials = credentials;
+ }
+
+ public Object getCredentials() throws InvalidSecurityContextException {
+ return this.credentials;
+ }
+
+ public void setAttribute(String name, Object value) {
+ this.attributes.put(name, value);
+ }
+
+ public Object getAttribute(String name) {
+
+ return this.attributes.get(name);
+ }
+
+ public void setAlias(String alias) {
+ }
+
+ public String getAlias() {
+
+ return null;
+ }
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTask.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTask.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTask.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,25 @@
+//----------------------------------------------------------------------
+//This code is developed as part of the Java CoG Kit project
+//The terms of the license can be found at http://www.cogkit.org/license
+//This message may not be removed or altered.
+//----------------------------------------------------------------------
+
+/*
+ * Created on Nov 19, 2007
+ */
+package org.globus.cog.abstraction.impl.ssh;
+
+import org.globus.cog.abstraction.impl.common.execution.JobException;
+import org.globus.cog.abstraction.impl.common.task.IllegalSpecException;
+import org.globus.cog.abstraction.impl.common.task.InvalidSecurityContextException;
+import org.globus.cog.abstraction.impl.common.task.InvalidServiceContactException;
+import org.globus.cog.abstraction.impl.common.task.TaskSubmissionException;
+
+import com.sshtools.j2ssh.session.SessionChannelClient;
+
+public interface SSHTask {
+ public void execute(SessionChannelClient session)
+ throws IllegalSpecException, InvalidSecurityContextException,
+ InvalidServiceContactException, TaskSubmissionException,
+ JobException;
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTaskStatusListener.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTaskStatusListener.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/SSHTaskStatusListener.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,13 @@
+// ----------------------------------------------------------------------
+// This code is developed as part of the Java CoG Kit project
+// The terms of the license can be found at http://www.cogkit.org/license
+// This message may not be removed or altered.
+// ----------------------------------------------------------------------
+
+package org.globus.cog.abstraction.impl.ssh;
+
+public interface SSHTaskStatusListener {
+ public static final int FAILED = 1;
+ public static final int COMPLETED = 0;
+ public void SSHTaskStatusChanged(int status, Exception e);
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/Ssh.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/Ssh.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/Ssh.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,373 @@
+// ----------------------------------------------------------------------
+// This code is developed as part of the Java CoG Kit project
+// The terms of the license can be found at http://www.cogkit.org/license
+// This message may not be removed or altered.
+// ----------------------------------------------------------------------
+
+/*
+ * Sshtools - Java SSH2 API
+ *
+ * Copyright (C) 2002 Lee David Painter.
+ *
+ * Written by: 2002 Lee David Painter <le...@ss...>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public License
+ * as published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package org.globus.cog.abstraction.impl.ssh;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+import org.globus.cog.abstraction.impl.common.task.InvalidSecurityContextException;
+import org.globus.cog.abstraction.impl.common.task.InvalidServiceContactException;
+import org.globus.cog.abstraction.impl.common.task.TaskSubmissionException;
+
+import com.sshtools.common.hosts.AbstractHostKeyVerification;
+import com.sshtools.j2ssh.SshClient;
+import com.sshtools.j2ssh.authentication.AuthenticationProtocolState;
+import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient;
+import com.sshtools.j2ssh.authentication.PublicKeyAuthenticationClient;
+import com.sshtools.j2ssh.configuration.ConfigurationLoader;
+import com.sshtools.j2ssh.configuration.SshConnectionProperties;
+import com.sshtools.j2ssh.session.SessionChannelClient;
+import com.sshtools.j2ssh.transport.InvalidHostFileException;
+import com.sshtools.j2ssh.transport.cipher.SshCipherFactory;
+import com.sshtools.j2ssh.transport.hmac.SshHmacFactory;
+import com.sshtools.j2ssh.transport.publickey.SshPrivateKey;
+import com.sshtools.j2ssh.transport.publickey.SshPrivateKeyFile;
+
+public class Ssh {
+ static Logger logger = Logger.getLogger(Ssh.class.getName());
+ protected String host;
+ protected int port = 22;
+ protected String username;
+ protected String password;
+ protected String keyfile;
+ protected String passphrase;
+ protected String cipher;
+ protected String mac;
+ protected String fingerprint;
+ protected String logfile = "ssh.log";
+ protected boolean verifyhost = true;
+ protected boolean always = false;
+ protected SshClient client;
+ protected String sshtoolsHome;
+ protected SessionChannelClient session = null;
+ private boolean connected, connecting;
+
+ static {
+ if (System.getProperty("sshtools.home") == null) {
+ System.setProperty("sshtools.home", System.getProperty("user.home")
+ + File.separator + ".globus");
+ }
+ File dir = new File(System.getProperty("sshtools.home"), "conf");
+ if (!dir.exists()) {
+ if (!dir.mkdirs()) {
+ throw new RuntimeException("Cannot create "
+ + dir.getAbsolutePath()
+ + ". Please check if you have a .globus directory"
+ + "in your home directory, and that it is writable");
+ }
+ }
+ else if (!dir.isDirectory()) {
+ throw new RuntimeException("Cannot create directory: "
+ + dir.getAbsolutePath()
+ + ". A file with that name already exists");
+ }
+ File hosts = new File(dir, "hosts.xml");
+ if (!hosts.exists()) {
+ try {
+ FileWriter w = new FileWriter(hosts);
+ w.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+ w.write("<HostAuthorizations>\n");
+ w
+ .write("<!-- please consult the j2ssh documentation for details on this file -->\n");
+ w.write("</HostAuthorizations>\n");
+ w.close();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(
+ "Cannot create hosts.xml file. Please check if you have a .globus directory"
+ + "in your home directory, and that it is writable",
+ e);
+ }
+ }
+ }
+
+ public Ssh() {
+ setVerifyhost(false);
+ }
+
+ public SessionChannelClient openSessionChannel() throws IOException {
+ return client.openSessionChannel();
+ }
+
+ public void connect() throws InvalidSecurityContextException,
+ InvalidServiceContactException, TaskSubmissionException {
+ try {
+ if (host == null) {
+ throw new InvalidServiceContactException(
+ "You must provide a host to connect to.");
+ }
+
+ if (username == null) {
+ throw new InvalidSecurityContextException(
+ "You must supply a username for authentication.");
+ }
+
+ if ((password == null) && (keyfile == null)) {
+ throw new InvalidSecurityContextException(
+ "You must supply either a password or keyfile/passphrase to authenticate!");
+ }
+
+ if (verifyhost && (fingerprint == null)) {
+ throw new InvalidSecurityContextException(
+ "Public key fingerprint required to verify the host");
+ }
+
+ if (sshtoolsHome != null) {
+ System.setProperty("sshtools.home", sshtoolsHome);
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Initializing J2SSH");
+ }
+
+ if (logfile != null) {
+ System.setProperty("sshtools.logfile", logfile);
+ }
+
+ ConfigurationLoader.initialize(false);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Creating connection to " + host + ":"
+ + String.valueOf(port));
+ }
+
+ if (client == null) {
+ client = new SshClient();
+
+ SshConnectionProperties properties = new SshConnectionProperties();
+ properties.setHost(host);
+ properties.setPort(port);
+ properties.setUsername(username);
+
+ if (cipher != null) {
+ if (SshCipherFactory.getSupportedCiphers().contains(cipher)) {
+ properties.setPrefSCEncryption(cipher);
+ properties.setPrefCSEncryption(cipher);
+ }
+ else {
+ if (logger.isDebugEnabled()) {
+ logger
+ .debug(cipher
+ + " is not a supported cipher, using default "
+ + SshCipherFactory
+ .getDefaultCipher());
+ }
+ }
+ }
+
+ if (mac != null) {
+ if (SshHmacFactory.getSupportedMacs().contains(mac)) {
+ properties.setPrefCSMac(mac);
+ properties.setPrefSCMac(mac);
+ }
+ else {
+ if (logger.isDebugEnabled()) {
+ logger.debug(mac
+ + " is not a supported mac, using default "
+ + SshHmacFactory.getDefaultHmac());
+ }
+ }
+ }
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Connecting....");
+ }
+
+ client.connect(properties, new AbstractHostKeyVerification() {
+ public void onUnknownHost(String hostname,
+ String fingerprint) throws InvalidHostFileException {
+ if (Ssh.this.verifyhost) {
+ if (fingerprint
+ .equalsIgnoreCase(Ssh.this.fingerprint)) {
+ allowHost(hostname, fingerprint, always);
+ }
+ }
+ else {
+ allowHost(hostname, fingerprint, always);
+ }
+ }
+
+ public void onHostKeyMismatch(String hostname,
+ String allowed, String supplied)
+ throws InvalidHostFileException {
+ if (Ssh.this.verifyhost) {
+ if (supplied.equalsIgnoreCase(Ssh.this.fingerprint)) {
+ allowHost(hostname, supplied, always);
+ }
+ }
+ else {
+ allowHost(hostname, supplied, always);
+ }
+ }
+
+ public void onDeniedHost(String host) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("The server host key is denied!");
+ }
+ }
+ });
+
+ int result;
+ boolean authenticated = false;
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authenticating " + username);
+ }
+
+ if (keyfile != null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Performing public key authentication");
+ }
+
+ PublicKeyAuthenticationClient pk = new PublicKeyAuthenticationClient();
+
+ // Open up the private key file
+ SshPrivateKeyFile file = SshPrivateKeyFile.parse(new File(
+ keyfile));
+
+ // If the private key is passphrase protected then ask for
+ // the passphrase
+ if (file.isPassphraseProtected() && (passphrase == null)) {
+ throw new InvalidSecurityContextException(
+ "Private key file is passphrase protected, please supply a valid passphrase");
+ }
+
+ // Get the key
+ SshPrivateKey key = file.toPrivateKey(passphrase);
+ pk.setUsername(username);
+ pk.setKey(key);
+
+ // Try the authentication
+ result = client.authenticate(pk);
+
+ if (result == AuthenticationProtocolState.COMPLETE) {
+ authenticated = true;
+ }
+ else if (result == AuthenticationProtocolState.PARTIAL) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Public key authentication "
+ + "completed, attempting password authentication");
+ }
+ }
+ else {
+ throw new InvalidSecurityContextException(
+ "Public Key Authentication failed");
+ }
+ }
+
+ if ((password != null) && (authenticated == false)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Performing password authentication");
+ }
+
+ PasswordAuthenticationClient pwd = new PasswordAuthenticationClient();
+ pwd.setUsername(username);
+ pwd.setPassword(password);
+
+ result = client.authenticate(pwd);
+
+ if (result == AuthenticationProtocolState.COMPLETE) {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Authentication complete");
+ }
+ }
+ else if (result == AuthenticationProtocolState.PARTIAL) {
+ if (logger.isDebugEnabled()) {
+ logger.error("Password Authentication succeeded "
+ + "but further authentication required!");
+ }
+ }
+ else {
+ throw new InvalidSecurityContextException(
+ "Password Authentication failed");
+ }
+ }
+ }
+
+ }
+ catch (IOException sshe) {
+ logger.debug(sshe);
+ throw new TaskSubmissionException("SSH Connection failed: "
+ + sshe.getMessage());
+ }
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public void setKeyfile(String keyfile) {
+ this.keyfile = keyfile;
+ }
+
+ public void setPassphrase(String passphrase) {
+ this.passphrase = passphrase;
+ }
+
+ public void setCipher(String cipher) {
+ this.cipher = cipher;
+ }
+
+ public void setMac(String mac) {
+ this.mac = mac;
+ }
+
+ public void setLogfile(String logfile) {
+ this.logfile = logfile;
+ }
+
+ public void setVerifyhost(boolean verifyhost) {
+ this.verifyhost = verifyhost;
+ }
+
+ public void setAlways(boolean always) {
+ this.always = always;
+ }
+
+ public void setSshtoolshome(String sshtoolsHome) {
+ this.sshtoolsHome = sshtoolsHome;
+ }
+
+ public void disconnect() {
+ client.disconnect();
+ }
+
+}
Added: trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/DelegatedTaskHandlerFactory.java
===================================================================
--- trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/DelegatedTaskHandlerFactory.java (rev 0)
+++ trunk/current/src/cog/modules/provider-ssh/src/org/globus/cog/abstraction/impl/ssh/execution/DelegatedTaskHandlerFactory.java 2007-11-23 21:24:48 UTC (rev 1840)
@@ -0,0 +1,27 @@
+// ----------------------------------------------------------------------
+// This code is developed as part of the Java CoG Kit project
+// The terms of the license can be found at http://www.cogkit.org/license
+// This message may not be removed or altered.
+// ----------------------------------------------------------------------
+
+
+
+package org.globus.cog.abstraction.impl.ssh.execution;
+
+import org.globus.cog.abstraction.interfaces.DelegatedTaskHandler;
+import org.globus.cog.abstraction.interfaces.Task;
+
+publ...
[truncated message content] |