bodewig     2003/03/11 05:00:31

  Modified:    src/main/org/apache/tools/ant/taskdefs/optional/ssh Scp.java
  Added:       src/main/org/apache/tools/ant/taskdefs/optional/ssh
                        SSHBase.java SSHUserInfo.java
  Log:
  Add key based authentication to scp.
  
  Submitted by: Robert Anderson <riznob at hotmail dot com>
  
  Revision  Changes    Path
  1.4       +48 -140   
ant/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java
  
  Index: Scp.java
  ===================================================================
  RCS file: 
/home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/optional/ssh/Scp.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Scp.java  10 Mar 2003 10:05:43 -0000      1.3
  +++ Scp.java  11 Mar 2003 13:00:31 -0000      1.4
  @@ -74,19 +74,11 @@
    * @author [EMAIL PROTECTED]
    * @since Ant 1.6
    */
  -public class Scp extends Task implements LogListener {
  +public class Scp extends SSHBase {
   
       private String fromUri;
       private String toUri;
  -    private String knownHosts;
  -    private boolean trust = false;
  -    private int port = 22;
       private List fileSets = null;
  -    private boolean failOnError = true;
  -
  -    public void setFailonerror( boolean failure ) {
  -        failOnError = failure;
  -    }
   
       /**
        * Sets the file to be transferred.  This can either be a remote
  @@ -114,35 +106,7 @@
           this.toUri = aToUri;
       }
   
  -    /**
  -     * Sets the path to the file that has the identities of
  -     * all known hosts.  This is used by SSH protocol to validate
  -     * the identity of the host.  The default is
  -     * <i>${user.home}/.ssh/known_hosts</i>.
  -
  -     * @param knownHosts a path to the known hosts file.
  -     */
  -    public void setKnownhosts( String knownHosts ) {
  -        this.knownHosts = knownHosts;
  -    }
   
  -    /**
  -     * Setting this to true trusts hosts whose identity is unknown.
  -     *
  -     * @param yesOrNo if true trust the identity of unknown hosts.
  -     */
  -    public void setTrust( boolean yesOrNo ) {
  -        this.trust = yesOrNo;
  -    }
  -
  -    /**
  -     * Changes the port used to connect to the remote host.
  -     *
  -     * @param port port number of remote host.
  -     */
  -    public void setPort( int port ) {
  -        this.port = port;
  -    }
   
       /**
        * Adds a FileSet tranfer to remote host.  NOTE: Either
  @@ -161,9 +125,6 @@
           super.init();
           this.toUri = null;
           this.fromUri = null;
  -        this.knownHosts = System.getProperty("user.home") + 
"/.ssh/known_hosts";
  -        this.trust = false;
  -        this.port = 22;
           this.fileSets = null;
       }
   
  @@ -174,12 +135,13 @@
   
           if ( fromUri == null && fileSets == null ) {
               throw new BuildException("Either the 'file' attribute or one " +
  -                    "FileSet is required.");
  +                                     "FileSet is required.");
           }
   
           boolean isFromRemote = false;
  -        if( fromUri != null )
  +        if( fromUri != null ) {
               isFromRemote = isRemoteUri(fromUri);
  +        }
           boolean isToRemote = isRemoteUri(toUri);
           try {
               if (isFromRemote && !isToRemote) {
  @@ -194,11 +156,11 @@
                   // not implemented yet.
               } else {
                   throw new BuildException("'todir' and 'file' attributes " +
  -                        "must have syntax like the following: " +
  -                        "user:[EMAIL PROTECTED]:/path");
  +                                         "must have syntax like the 
following: " +
  +                                         "user:[EMAIL PROTECTED]:/path");
               }
           } catch (Exception e) {
  -            if( failOnError ) {
  +            if(getFailonerror()) {
                   throw new BuildException(e);
               } else {
                   log("Caught exception: " + e.getMessage(), Project.MSG_ERR);
  @@ -207,20 +169,17 @@
       }
   
       private void download( String fromSshUri, String toPath )
  -            throws JSchException, IOException {
  -        String[] fromValues = parseUri(fromSshUri);
  +        throws JSchException, IOException {
  +        String file = parseUri(fromSshUri);
   
           Session session = null;
           try {
  -            session = openSession(fromValues[0],
  -                    fromValues[1],
  -                    fromValues[2],
  -                    port );
  +            session = openSession();
               ScpFromMessage message = new ScpFromMessage( session,
  -                    fromValues[3],
  -                    new File( toPath ),
  -                    fromSshUri.endsWith("*") );
  -            log("Receiving file: " + fromValues[3] );
  +                                                         file,
  +                                                         new File( toPath ),
  +                                                         
fromSshUri.endsWith("*") );
  +            log("Receiving file: " + file );
               message.setLogListener( this );
               message.execute();
           } finally {
  @@ -230,23 +189,20 @@
       }
   
       private void upload( List fileSet, String toSshUri )
  -            throws IOException, JSchException {
  -        String[] toValues = parseUri(toSshUri);
  +        throws IOException, JSchException {
  +        String file = parseUri(toSshUri);
   
           Session session = null;
           try {
  -            session = openSession( toValues[0],
  -                    toValues[1],
  -                    toValues[2],
  -                    port );
  +            session = openSession();
               List list = new ArrayList( fileSet.size() );
               for( Iterator i = fileSet.iterator(); i.hasNext(); ) {
                   FileSet set = (FileSet) i.next();
                   list.add( createDirectory( set ) );
               }
               ScpToMessage message = new ScpToMessage( session,
  -                    list,
  -                    toValues[3] );
  +                                                     list,
  +                                                     file);
               message.setLogListener( this );
               message.execute();
           } finally {
  @@ -256,18 +212,15 @@
       }
   
       private void upload( String fromPath, String toSshUri )
  -            throws IOException, JSchException {
  -        String[] toValues = parseUri(toSshUri);
  +        throws IOException, JSchException {
  +        String file = parseUri(toSshUri);
   
           Session session = null;
           try {
  -            session = openSession( toValues[0],
  -                    toValues[1],
  -                    toValues[2],
  -                    port );
  +            session = openSession();
               ScpToMessage message = new ScpToMessage( session,
  -                    new File( fromPath ),
  -                    toValues[3] );
  +                                                     new File( fromPath ),
  +                                                     file );
               message.setLogListener( this );
               message.execute();
           } finally {
  @@ -276,35 +229,32 @@
           }
       }
   
  -    private Session openSession( String user, String password,
  -                                 String host, int port )
  -            throws JSchException {
  -        JSch jsch = new JSch();
  -        if( knownHosts != null ) {
  -            log( "Using known hosts: " + knownHosts, Project.MSG_DEBUG );
  -            jsch.setKnownHosts( knownHosts );
  -        }
  -        Session session = jsch.getSession( user, host, port );
  -
  -        UserInfo userInfo = new DefaultUserInfo( password, trust );
  -        session.setUserInfo(userInfo);
  -        log("Connecting to " + host + ":" + port );
  -        session.connect();
  -        return session;
  -    }
  -
  -    private String[] parseUri(String uri) {
  +    private String parseUri(String uri) {
           int indexOfAt = uri.indexOf('@');
           int indexOfColon = uri.indexOf(':');
  -        int indexOfPath = uri.indexOf(':', indexOfColon + 1);
  -
  -        String[] values = new String[4];
  -        values[0] = uri.substring(0, indexOfColon);
  -        values[1] = uri.substring(indexOfColon + 1, indexOfAt);
  -        values[2] = uri.substring(indexOfAt + 1, indexOfPath);
  -        values[3] = uri.substring(indexOfPath + 1);
  -
  -        return values;
  +        if (indexOfColon > -1 && indexOfColon < indexOfAt) {
  +            // user:[EMAIL PROTECTED]:/path notation
  +            setUsername(uri.substring(0, indexOfColon));
  +            setPassword(uri.substring(indexOfColon + 1, indexOfAt));
  +        } else {
  +            // no password, will require passphrase
  +            setUsername(uri.substring(0, indexOfAt));
  +        }
  +
  +        if (getUserInfo().getPassword() == null
  +            && getUserInfo().getPassphrase() == null) {
  +            throw new BuildException("neither password nor passphrase for 
user "
  +                                     + getUserInfo().getName() + " has been "
  +                                     + "given.  Can't authenticate.");
  +        }
  +
  +        int indexOfPath = uri.indexOf(':', indexOfAt + 1);
  +        if (indexOfPath == -1) {
  +            throw new BuildException("no remote path in " + uri);
  +        }
  +        
  +        setHost(uri.substring(indexOfAt + 1, indexOfPath));
  +        return uri.substring(indexOfPath + 1);
       }
   
       private boolean isRemoteUri(String uri) {
  @@ -337,47 +287,5 @@
           }
   
           return root;
  -    }
  -
  -
  -    public class DefaultUserInfo implements UserInfo {
  -        private String password = null;
  -        private boolean firstTime = true;
  -        private boolean trustAllCertificates;
  -
  -        public DefaultUserInfo(String password, boolean 
trustAllCertificates) {
  -            this.password = password;
  -            this.trustAllCertificates = trustAllCertificates;
  -        }
  -
  -        public String getPassphrase() {
  -            return null;
  -        }
  -
  -        public String getPassword() {
  -            return password;
  -        }
  -
  -        public boolean promptPassword( String passwordPrompt ) {
  -            log( passwordPrompt, Project.MSG_DEBUG );
  -            if( firstTime ) {
  -                firstTime = false;
  -                return true;
  -            }
  -            return firstTime;
  -        }
  -
  -        public boolean promptPassphrase( String passPhrasePrompt ) {
  -            return true;
  -        }
  -
  -        public boolean promptYesNo( String prompt ) {
  -            log( prompt, Project.MSG_DEBUG );
  -            return trustAllCertificates;
  -        }
  -
  -        public void showMessage( String message ) {
  -            log( message, Project.MSG_DEBUG );
  -        }
       }
   }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHBase.java
  
  Index: SSHBase.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "Ant" and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.ssh;
  
  import com.jcraft.jsch.*;
  
  import java.io.*;
  import java.util.List;
  import java.util.LinkedList;
  import java.util.Iterator;
  import java.util.ArrayList;
  
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.DirectoryScanner;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.FileSet;
  
  /**
   * Base class for Ant tasks using jsch.
   *
   * @author [EMAIL PROTECTED]
   * @author [EMAIL PROTECTED]
   * @since Ant 1.6
   */
  public abstract class SSHBase extends Task implements LogListener {
          
      private String host;
      private String keyfile;
      private String knownHosts;
      private boolean trust = false;
      private int port = 22;
      private boolean failOnError = true;
      private SSHUserInfo userInfo;
      
      /**
       * Constructor for SSHBase.
       */
      public SSHBase() {
          super();
          userInfo = new SSHUserInfo();
      }
          
      /**
       * Remote host, either DNS name or IP.
       *
       * @param host  The new host value
       */
      public void setHost(String host) {
          this.host = host;
      }
  
      
      public void setFailonerror( boolean failure ) {
          failOnError = failure;
      }
  
      public boolean getFailonerror() {
          return failOnError;
      }
  
      /**
       * Username known to remote host.
       *
       * @param username  The new username value
       */
      public void setUsername(String username) {
          userInfo.setName(username);
      }
  
  
      /**
       * Sets the password for the user.
       *
       * @param password  The new password value
       */
      public void setPassword(String password) {
          userInfo.setPassword(password);
      }
  
      /**
       * Sets the keyfile for the user.
       * 
       * @param keyfile  The new keyfile value
       */
      public void setKeyfile(String keyfile) {
          userInfo.setKeyfile(keyfile);
      }
      
      /**
       * Sets the passphrase for the users key.
       * 
       * @param passphrase  The new passphrase value
       */
      public void setPassphrase(String passphrase) {
          userInfo.setPassphrase(passphrase);
      }
      
      /**
       * Sets the path to the file that has the identities of
       * all known hosts.  This is used by SSH protocol to validate
       * the identity of the host.  The default is
       * <i>${user.home}/.ssh/known_hosts</i>.
       *
       * @param knownHosts a path to the known hosts file.
       */
      public void setKnownhosts( String knownHosts ) {
          this.knownHosts = knownHosts;
      }
  
      /**
       * Setting this to true trusts hosts whose identity is unknown.
       *
       * @param yesOrNo if true trust the identity of unknown hosts.
       */
      public void setTrust( boolean yesOrNo ) {
          userInfo.setTrust(yesOrNo);
      }
  
      /**
       * Changes the port used to connect to the remote host.
       *
       * @param port port number of remote host.
       */
      public void setPort( int port ) {
          this.port = port;
      }
      
      public int getPort() {
          return port;
      }
      
      public void init() throws BuildException{
          super.init();
          this.knownHosts = System.getProperty("user.home") + 
"/.ssh/known_hosts";
          this.trust = false;
          this.port = 22;
      }
      
      protected Session openSession() throws JSchException {
          JSch jsch = new JSch();
          if (null != userInfo.getKeyfile()) {
              jsch.addIdentity(userInfo.getKeyfile(), "passphrase");
          }
  
          if( knownHosts != null ) {
              log( "Using known hosts: " + knownHosts, Project.MSG_DEBUG );
              jsch.setKnownHosts( knownHosts );
          }
  
          Session session = jsch.getSession( userInfo.getName(), host, port );
          session.setUserInfo(userInfo);
          log("Connecting to " + host + ":" + port );
          session.connect();
          return session;
      }
  
      protected SSHUserInfo getUserInfo() {
          return userInfo;
      }
  }
  
  
  
  1.1                  
ant/src/main/org/apache/tools/ant/taskdefs/optional/ssh/SSHUserInfo.java
  
  Index: SSHUserInfo.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "Ant" and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.ssh;
  
  import com.jcraft.jsch.UserInfo;
  import org.apache.tools.ant.Project;
  
  /**
   * @author rhanderson
   */
  public class SSHUserInfo implements UserInfo {
        
      private String name;
      private String password = null;
      private String keyfile;
      private String passphrase = null;
      private boolean firstTime = true;
      private boolean trustAllCertificates;
      
      public SSHUserInfo() {
        super();
        this.trustAllCertificates = true;
      }
      
      public SSHUserInfo(String password, boolean trustAllCertificates) {
          super();
          this.password = password;
          this.trustAllCertificates = trustAllCertificates;
      }
  
      /**
       * @see com.jcraft.jsch.UserInfo#getName()
       */
      public String getName() {
          return name;
      }
      
      /**
       * @see com.jcraft.jsch.UserInfo#getPassphrase(String)
       */
      public String getPassphrase(String message) {
          return passphrase;
      }
      
      /**
       * @see com.jcraft.jsch.UserInfo#getPassword()
       */
      public String getPassword() {
          return password;
      }
      
      /**
       * @see com.jcraft.jsch.UserInfo#prompt(String)
       */
      public boolean prompt(String str) {
          return false;
      }
  
      /**
       * @see com.jcraft.jsch.UserInfo#retry()
       */
      public boolean retry() {
          return false;
      }
  
      /**
       * Sets the name.
       * @param name The name to set
       */
      public void setName(String name) {
          this.name = name;
      }
  
      /**
       * Sets the passphrase.
       * @param passphrase The passphrase to set
       */
      public void setPassphrase(String passphrase) {
          this.passphrase = passphrase;
      }
  
      /**
       * Sets the password.
       * @param password The password to set
       */
      public void setPassword(String password) {
          this.password = password;
      }
  
      /**
       * Sets the trust.
       * @param boolean
       */
      public void setTrust(boolean trust) {
          this.trustAllCertificates = trust;
      }
  
      /**
       * Returns the passphrase.
       * @return String
       */
      public String getPassphrase() {
          return passphrase;
      }
  
      /**
       * Returns the keyfile.
       * @return String
       */
      public String getKeyfile() {
          return keyfile;
      }
  
      /**
       * Sets the keyfile.
       * @param keyfile The keyfile to set
       */
      public void setKeyfile(String keyfile) {
          this.keyfile = keyfile;
      }
  
      /**
       * @see com.jcraft.jsch.UserInfo#promptPassphrase(String)
       */
      public boolean promptPassphrase(String message) {
          return true;
      }
  
      /**
       * @see com.jcraft.jsch.UserInfo#promptPassword(String)
       */
      public boolean promptPassword( String passwordPrompt ) {
          //log( passwordPrompt, Project.MSG_DEBUG );
          if( firstTime ) {
              firstTime = false;
              return true;
          }
          return firstTime;
      }
  
      /**
       * @see com.jcraft.jsch.UserInfo#promptYesNo(String)
       */
      public boolean promptYesNo(String message) {
          //log( prompt, Project.MSG_DEBUG );
          return trustAllCertificates;
      }
  
      /**
       * @see com.jcraft.jsch.UserInfo#showMessage(String)
       */
      public void showMessage(String message) {
          //log( message, Project.MSG_DEBUG );
      }
  
  }
  
  
  

Reply via email to