You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by br...@apache.org on 2002/04/03 06:38:06 UTC

cvs commit: jakarta-commons-sandbox/net/src/java/org/apache/commons/net/bsd RCommandClient.java RExecClient.java RLoginClient.java

brekke      02/04/02 20:38:06

  Added:       net/src/java/org/apache/commons/net/bsd RCommandClient.java
                        RExecClient.java RLoginClient.java
  Log:
  Moving com.oroinc.net.bsd to org.apache.commons.net.bsd
  
  Revision  Changes    Path
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/bsd/RCommandClient.java
  
  Index: RCommandClient.java
  ===================================================================
  package org.apache.commons.net.bsd;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * 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/>.
   */
  
  import java.io.*;
  import java.net.*;
  
  import org.apache.commons.io.SocketInputStream;
  import org.apache.commons.net.SocketClient;
  
  
  /***
   * RCommandClient is very similar to
   * <a href="org.apache.commons.net.bsd.RExecClient.html"> RExecClient </a>,
   * from which it is derived, and implements the rcmd() facility that
   * first appeared in 4.2BSD Unix.  rcmd() is the facility used by the rsh
   * (rshell) and other commands to execute a command on another machine
   * from a trusted host without issuing a password.  The trust relationship
   * between two machines is established by the contents of a machine's
   * /etc/hosts.equiv file and a user's .rhosts file.  These files specify
   * from which hosts and accounts on those hosts rcmd() requests will be
   * accepted.  The only additional measure for establishing trust is that
   * all client connections must originate from a port between 512 and 1023.
   * Consequently, there is an upper limit to the number of rcmd connections
   * that can be running simultaneously.   The required ports are reserved
   * ports on Unix systems, and can only be bound by a
   * process running with root permissions (to accomplish this rsh, rlogin,
   * and related commands usualy have the suid bit set).  Therefore, on a
   * Unix system, you will only be able to successfully use the RCommandClient 
   * class if the process runs as root.  However, there is no such restriction
   * on Windows95 and some other systems.  The security risks are obvious.
   * However, when carefully used, rcmd() can be very useful when used behind
   * a firewall.
   * <p>
   * As with virtually all of the client classes in org.apache.commons.net, this
   * class derives from SocketClient.  But it overrides most of its connection
   * methods so that the local Socket will originate from an acceptable
   * rshell port.  The way to use RCommandClient is to first connect
   * to the server, call the <a href="#rcommand"> rcommand() </a> method,
   * and then
   * fetch the connection's input, output, and optionally error streams.
   * Interaction with the remote command is controlled entirely through the
   * I/O streams.  Once you have finished processing the streams, you should
   * invoke <a href="org.apache.commons.net.bsd.RExecClient.html#disconnect"> 
   * disconnect() </a> to clean up properly.
   * <p>
   * By default the standard output and standard error streams of the
   * remote process are transmitted over the same connection, readable
   * from the input stream returned by
   * <a href="org.apache.commons.net.bsd.RExecClient.html#getInputStream">
   * getInputStream() </a>.  However, it is
   * possible to tell the rshd daemon to return the standard error
   * stream over a separate connection, readable from the input stream
   * returned by <a href="org.apache.commons.net.bsd.RExecClient.html#getErrorStream">
   * getErrorStream() </a>.  You
   * can specify that a separate connection should be created for standard
   * error by setting the boolean <code> separateErrorStream </code> 
   * parameter of <a href="#rcommand"> rcommand() </a> to <code> true </code>.
   * The standard input of the remote process can be written to through
   * the output stream returned by 
   * <a href="org.apache.commons.net.bsd.RExecClient.html#getOutputStream"> 
   * getOutputSream() </a>.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see SocketClient
   * @see RExecClient
   * @see RLoginClient
   ***/
  
  public class RCommandClient extends RExecClient {
    /***
     * The default rshell port.  Set to 514 in BSD Unix.
     ***/
    public static final int DEFAULT_PORT    = 514;
  
    /***
     * The smallest port number an rcmd client may use.  By BSD convention
     * this number is 512.
     ***/
    public static final int MIN_CLIENT_PORT =  512;
  
    /***
     * The largest port number an rcmd client may use.  By BSD convention
     * this number is 1023.
     ***/
    public static final int MAX_CLIENT_PORT = 1023;
  
    // Overrides method in RExecClient in order to implement proper
    // port number limitations.
    InputStream _createErrorStream() throws IOException {
      int localPort;
      ServerSocket server;
      Socket socket;
  
      localPort = MAX_CLIENT_PORT;
      server    = null; // Keep compiler from barfing
  
      for(localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
      {
        try {
  	server = _socketFactory_.createServerSocket(localPort, 1, 
  						    getLocalAddress());
        } catch(SocketException e) {
  	continue;
        }
        break;
      }
  
      if(localPort < MIN_CLIENT_PORT)
        throw new BindException("All ports in use.");
  
      _output_.write(Integer.toString(server.getLocalPort()).getBytes());
      _output_.write('\0');
      _output_.flush();
  
      socket = server.accept();
      server.close();
  
      if(isRemoteVerificationEnabled() && !verifyRemote(socket)) {
        socket.close();
        throw new IOException(
  		    "Security violation: unexpected connection attempt by " +
  		    socket.getInetAddress().getHostAddress());
      }
  
      return (new SocketInputStream(socket, socket.getInputStream()));
    }
  
    /***
     * The default RCommandClient constructor.  Initializes the
     * default port to <code> DEFAULT_PORT </code>.
     ***/
    public RCommandClient() {
      setDefaultPort(DEFAULT_PORT);
    }
  
  
    /***
     * Opens a Socket connected to a remote host at the specified port and
     * originating from the specified local address using a port in a range
     * acceptable to the BSD rshell daemon.
     * Before returning, <a href="org.apache.commons.net.SocketClient.html#_connectAction_"> _connectAction_() </a>
     * is called to perform connection initialization actions.
     * <p>
     * @param host  The remote host.
     * @param port  The port to connect to on the remote host.
     * @param localAddr  The local address to use.
     * @exception SocketException If the socket timeout could not be set.
     * @exception BindException If all acceptable rshell ports are in use.
     * @exception IOException If the socket could not be opened.  In most
     *  cases you will only want to catch IOException since SocketException is
     *  derived from it.
     ***/
    public void connect(InetAddress host, int port, InetAddress localAddr)
         throws SocketException, BindException, IOException
    {
      int localPort;
  
      localPort = MAX_CLIENT_PORT;
  
      for(localPort = MAX_CLIENT_PORT; localPort >= MIN_CLIENT_PORT; --localPort)
      {
        try {
  	_socket_ = 
  	  _socketFactory_.createSocket(host, port, localAddr, localPort);
        } catch(SocketException e) {
  	continue;
        }
        break;
      }
  
      if(localPort < MIN_CLIENT_PORT)
        throw new BindException("All ports in use or insufficient permssion.");
  
      _connectAction_();
    }
  
  
  
    /***
     * Opens a Socket connected to a remote host at the specified port and
     * originating from the current host at a port in a range acceptable
     * to the BSD rshell daemon.
     * Before returning, <a href="org.apache.commons.net.SocketClient.html#_connectAction_"> _connectAction_() </a>
     * is called to perform connection initialization actions.
     * <p>
     * @param host  The remote host.
     * @param port  The port to connect to on the remote host.
     * @exception SocketException If the socket timeout could not be set.
     * @exception BindException If all acceptable rshell ports are in use.
     * @exception IOException If the socket could not be opened.  In most
     *  cases you will only want to catch IOException since SocketException is
     *  derived from it.
     ***/
    public void connect(InetAddress host, int port)
         throws SocketException, IOException
    {
      connect(host, port, InetAddress.getLocalHost());
    }
  
  
    /***
     * Opens a Socket connected to a remote host at the specified port and
     * originating from the current host at a port in a range acceptable
     * to the BSD rshell daemon.
     * Before returning, <a href="org.apache.commons.net.SocketClient.html#_connectAction_"> _connectAction_() </a>
     * is called to perform connection initialization actions.
     * <p>
     * @param hostname  The name of the remote host.
     * @param port  The port to connect to on the remote host.
     * @exception SocketException If the socket timeout could not be set.
     * @exception BindException If all acceptable rshell ports are in use.
     * @exception IOException If the socket could not be opened.  In most
     *  cases you will only want to catch IOException since SocketException is
     *  derived from it.
     * @exception UnknownHostException If the hostname cannot be resolved.
     ***/
    public void connect(String hostname, int port)
         throws SocketException, IOException
    {
      connect(InetAddress.getByName(hostname), port, InetAddress.getLocalHost());
    }
  
  
    /***
     * Opens a Socket connected to a remote host at the specified port and
     * originating from the specified local address using a port in a range
     * acceptable to the BSD rshell daemon.
     * Before returning, <a href="org.apache.commons.net.SocketClient.html#_connectAction_"> _connectAction_() </a>
     * is called to perform connection initialization actions.
     * <p>
     * @param host  The remote host.
     * @param port  The port to connect to on the remote host.
     * @param localAddr  The local address to use.
     * @exception SocketException If the socket timeout could not be set.
     * @exception BindException If all acceptable rshell ports are in use.
     * @exception IOException If the socket could not be opened.  In most
     *  cases you will only want to catch IOException since SocketException is
     *  derived from it.
     ***/
    public void connect(String hostname, int port, InetAddress localAddr)
         throws SocketException, IOException
    {
      connect(InetAddress.getByName(hostname), port, localAddr);
    }
  
  
    /***
     * Opens a Socket connected to a remote host at the specified port and
     * originating from the specified local address and port. The
     * local port must lie between <code> MIN_CLIENT_PORT </code> and
     * <code> MAX_CLIENT_PORT </code> or an IllegalArgumentException will
     * be thrown.
     * Before returning, <a href="org.apache.commons.net.SocketClient.html#_connectAction_"> _connectAction_() </a>
     * is called to perform connection initialization actions.
     * <p>
     * @param host  The remote host.
     * @param port  The port to connect to on the remote host.
     * @param localAddr  The local address to use.
     * @param localPort  The local port to use.
     * @exception SocketException If the socket timeout could not be set.
     * @exception IOException If the socket could not be opened.  In most
     *  cases you will only want to catch IOException since SocketException is
     *  derived from it.
     * @exception IllegalArgumentException If an invalid local port number
     *            is specified.
     ***/
    public void connect(InetAddress host, int port,
  		      InetAddress localAddr, int localPort)
         throws SocketException, IOException, IllegalArgumentException
    {
      if(localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT)
        throw new IllegalArgumentException("Invalid port number " + localPort);
      super.connect(host, port, localAddr, localPort);
    }
  
  
    /***
     * Opens a Socket connected to a remote host at the specified port and
     * originating from the specified local address and port. The
     * local port must lie between <code> MIN_CLIENT_PORT </code> and
     * <code> MAX_CLIENT_PORT </code> or an IllegalArgumentException will
     * be thrown.
     * Before returning, <a href="org.apache.commons.net.SocketClient.html#_connectAction_"> _connectAction_() </a>
     * is called to perform connection initialization actions.
     * <p>
     * @param hostname  The name of the remote host.
     * @param port  The port to connect to on the remote host.
     * @param localAddr  The local address to use.
     * @param localPort  The local port to use.
     * @exception SocketException If the socket timeout could not be set.
     * @exception IOException If the socket could not be opened.  In most
     *  cases you will only want to catch IOException since SocketException is
     *  derived from it.
     * @exception UnknownHostException If the hostname cannot be resolved.
     * @exception IllegalArgumentException If an invalid local port number
     *            is specified.
     ***/
    public void connect(String hostname, int port,
  		      InetAddress localAddr, int localPort)
         throws SocketException, IOException, IllegalArgumentException
    {
      if(localPort < MIN_CLIENT_PORT || localPort > MAX_CLIENT_PORT)
        throw new IllegalArgumentException("Invalid port number " + localPort);
      super.connect(hostname, port, localAddr, localPort);
    }
  
  
    /***
     * Remotely executes a command through the rshd daemon on the server
     * to which the RCommandClient is connected.  After calling this method,
     * you may interact with the remote process through its standard input,
     * output, and error streams.  You will typically be able to detect
     * the termination of the remote process after reaching end of file
     * on its standard output (accessible through
     * <a href="#getInputStream"> getInputStream() </a>.  Disconnecting
     * from the server or closing the process streams before reaching
     * end of file will not necessarily terminate the remote process.
     * <p>
     * If a separate error stream is requested, the remote server will
     * connect to a local socket opened by RCommandClient, providing an
     * independent stream through which standard error will be transmitted.
     * The local socket must originate from a secure port (512 - 1023),
     * and rcommand() ensures that this will be so.
     * RCommandClient will also do a simple security check when it accepts a
     * connection for this error stream.  If the connection does not originate
     * from the remote server, an IOException will be thrown.  This serves as
     * a simple protection against possible hijacking of the error stream by
     * an attacker monitoring the rexec() negotiation.  You may disable this 
     * behavior with
     * <a href="org.apache.commons.net.bsd.RExecClient.html#setRemoteVerificationEnabled">
     * setRemoteVerificationEnabled()</a>.
     * <p>
     * @param localUsername  The user account on the local machine that is
     *        requesting the command execution.
     * @param remoteUsername  The account name on the server through which to
     *        execute the command.
     * @param command   The command, including any arguments, to execute.
     * @param separateErrorStream True if you would like the standard error
     *        to be transmitted through a different stream than standard output.
     *        False if not.
     * @exception IOException If the rcommand() attempt fails.  The exception
     *            will contain a message indicating the nature of the failure.
     ***/
    public void rcommand(String localUsername, String remoteUsername,
  		       String command, boolean separateErrorStream)
         throws IOException
    {
      rexec(localUsername, remoteUsername, command, separateErrorStream);
    }
  
  
    /***
     * Same as
     * <code> rcommand(localUsername, remoteUsername, command, false); </code>
     ***/
    public void rcommand(String localUsername, String remoteUsername,
  		       String command)
         throws IOException
    {
      rcommand(localUsername, remoteUsername, command, false);
    }
  
  }
  
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/bsd/RExecClient.java
  
  Index: RExecClient.java
  ===================================================================
  package org.apache.commons.net.bsd;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * 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/>.
   */
  
  import java.io.*;
  import java.net.*;
  
  import org.apache.commons.io.SocketInputStream;
  import org.apache.commons.net.SocketClient;
  
  /***
   * RExecClient implements the rexec() facility that first appeared in
   * 4.2BSD Unix.  This class will probably only be of use for connecting
   * to Unix systems and only when the rexecd daemon is configured to run,
   * which is a rarity these days because of the security risks involved.
   * However, rexec() can be very useful for performing administrative tasks
   * on a network behind a firewall.
   * <p>
   * As with virtually all of the client classes in org.apache.commons.net, this
   * class derives from SocketClient, inheriting its connection methods.
   * The way to use RExecClient is to first connect
   * to the server, call the <a href="#rexec"> rexec() </a> method, and then
   * fetch the connection's input, output, and optionally error streams.
   * Interaction with the remote command is controlled entirely through the
   * I/O streams.  Once you have finished processing the streams, you should
   * invoke <a href="#disconnect"> disconnect() </a> to clean up properly.
   * <p>
   * By default the standard output and standard error streams of the
   * remote process are transmitted over the same connection, readable
   * from the input stream returned by
   * <a href="#getInputStream"> getInputStream() </a>.  However, it is
   * possible to tell the rexecd daemon to return the standard error
   * stream over a separate connection, readable from the input stream
   * returned by <a href="#getErrorStream"> getErrorStream() </a>.  You
   * can specify that a separate connection should be created for standard
   * error by setting the boolean <code> separateErrorStream </code> 
   * parameter of <a href="#rexec"> rexec() </a> to <code> true </code>.
   * The standard input of the remote process can be written to through
   * the output stream returned by 
   * <a href="#getOutputStream"> getOutputSream() </a>.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see SocketClient
   * @see RCommandClient
   * @see RLoginClient
   ***/
  
  public class RExecClient extends SocketClient {
    /***
     * The default rexec port.  Set to 512 in BSD Unix.
     ***/
    public static final int DEFAULT_PORT    = 512;
  
    private boolean __remoteVerificationEnabled;
  
    /***
     * If a separate error stream is requested, <code>_errorStream_</code>
     * will point to an InputStream from which the standard error of the
     * remote process can be read (after a call to rexec()).  Otherwise,
     * <code> _errorStream_ </code> will be null.
     ***/
    protected InputStream _errorStream_;
  
    // This can be overridden in local package to implement port range
    // limitations of rcmd and rlogin
    InputStream _createErrorStream() throws IOException {
      ServerSocket server;
      Socket socket;
  
      server = _socketFactory_.createServerSocket(0, 1, getLocalAddress());
  
      _output_.write(Integer.toString(server.getLocalPort()).getBytes());
      _output_.write('\0');
      _output_.flush();
  
      socket = server.accept();
      server.close();
  
      if(__remoteVerificationEnabled && !verifyRemote(socket)) {
        socket.close();
        throw new IOException(
  		    "Security violation: unexpected connection attempt by " +
  		    socket.getInetAddress().getHostAddress());
      }
  
      return (new SocketInputStream(socket, socket.getInputStream()));
    }
  
  
    /***
     * The default RExecClient constructor.  Initializes the
     * default port to <code> DEFAULT_PORT </code>.
     ***/
    public RExecClient() {
      _errorStream_ = null;
      setDefaultPort(DEFAULT_PORT);
    }
  
  
    /***
     * Returns the InputStream from which the standard outputof the remote
     * process can be read.  The input stream will only be set after a
     * successful rexec() invocation.
     * <p>
     * @return The InputStream from which the standard output of the remote
     * process can be read.
     ***/
    public InputStream getInputStream() { return _input_; }
  
  
    /***
     * Returns the OutputStream through which the standard input of the remote
     * process can be written.  The output stream will only be set after a
     * successful rexec() invocation.
     * <p>
     * @return The OutputStream through which the standard input of the remote
     * process can be written.
     ***/
    public OutputStream getOutputStream(){ return _output_; }
  
  
    /***
     * Returns the InputStream from which the standard error of the remote
     * process can be read if a separate error stream is requested from
     * the server.  Otherwise, null will be returned.  The error stream
     * will only be set after a successful rexec() invocation.
     * <p>
     * @return The InputStream from which the standard error of the remote
     * process can be read if a separate error stream is requested from
     * the server.  Otherwise, null will be returned.
     ***/
    public InputStream getErrorStream() { return _errorStream_; }
  
  
    /***
     * Remotely executes a command through the rexecd daemon on the server
     * to which the RExecClient is connected.  After calling this method,
     * you may interact with the remote process through its standard input,
     * output, and error streams.  You will typically be able to detect
     * the termination of the remote process after reaching end of file
     * on its standard output (accessible through
     * <a href="#getInputStream"> getInputStream() </a>.    Disconnecting
     * from the server or closing the process streams before reaching
     * end of file will not necessarily terminate the remote process.
     * <p>
     * If a separate error stream is requested, the remote server will
     * connect to a local socket opened by RExecClient, providing an
     * independent stream through which standard error will be transmitted.
     * RExecClient will do a simple security check when it accepts a
     * connection for this error stream.  If the connection does not originate
     * from the remote server, an IOException will be thrown.  This serves as
     * a simple protection against possible hijacking of the error stream by
     * an attacker monitoring the rexec() negotiation.  You may disable this 
     * behavior with <a href="#setRemoteVerificationEnabled">
     * setRemoteVerificationEnabled()</a>.
     * <p>
     * @param username  The account name on the server through which to execute
     *                  the command.
     * @param password  The plain text password of the user account.
     * @param command   The command, including any arguments, to execute.
     * @param separateErrorStream True if you would like the standard error
     *        to be transmitted through a different stream than standard output.
     *        False if not.
     * @exception IOException If the rexec() attempt fails.  The exception
     *            will contain a message indicating the nature of the failure.
     ***/
    public void rexec(String username, String password,
  		    String command, boolean separateErrorStream)
         throws IOException
    {
      int ch;
  
      if(separateErrorStream) {
        _errorStream_ = _createErrorStream();
      } else {
        _output_.write('\0');
      }
  
      _output_.write(username.getBytes());
      _output_.write('\0');
      _output_.write(password.getBytes());
      _output_.write('\0');
      _output_.write(command.getBytes());
      _output_.write('\0');
      _output_.flush();
  
      ch = _input_.read();
      if(ch > 0) {
        StringBuffer buffer = new StringBuffer();
  
        while((ch = _input_.read()) != -1 && ch != '\n')
  	buffer.append((char)ch);
  
        throw new IOException(buffer.toString());
      } else if(ch < 0) {
        throw new IOException("Server closed connection.");
      }
    }
  
  
    /***
     * Same as <code> rexec(username, password, command, false); </code>
     ***/
    public void rexec(String username, String password,
  		    String command)
         throws IOException
    {
      rexec(username, password, command, false);
    }
  
    /***
     * Disconnects from the server, closing all associated open sockets and
     * streams.
     * <p>
     * @exception IOException If there an error occurs while disconnecting.
     ***/
    public void disconnect() throws IOException {
      if(_errorStream_ != null)
        _errorStream_.close();
      _errorStream_ = null;
      super.disconnect();
    }
  
  
    /***
     * Enable or disable verification that the remote host connecting to
     * create a separate error stream is the same as the host to which
     * the standard out stream is connected.  The default is for verification 
     * to be enabled.  You may set this value at any time, whether the
     * client is currently connected or not.
     * <p>
     * @param enable True to enable verification, false to disable verification.
     ***/
    public final void setRemoteVerificationEnabled(boolean enable) {
      __remoteVerificationEnabled = enable;
    }
  
    /***
     * Return whether or not verification of the remote host providing a
     * separate error stream is enabled.  The default behavior is for
     * verification to be enabled.
     * <p>
     * @return True if verification is enabled, false if not.
     ***/
    public final boolean isRemoteVerificationEnabled() {
      return __remoteVerificationEnabled;
    }
  
  }
  
  
  
  
  1.1                  jakarta-commons-sandbox/net/src/java/org/apache/commons/net/bsd/RLoginClient.java
  
  Index: RLoginClient.java
  ===================================================================
  package org.apache.commons.net.bsd;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Commons" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * 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/>.
   */
  
  import java.io.*;
  
  /***
   * RLoginClient is very similar to
   * <a href="org.apache.commons.net.bsd.RCommandClient.html"> RCommandClient </a>,
   * from which it is derived, and uses the rcmd() facility implemented
   * in RCommandClient to implement the functionality of the rlogin command that
   * first appeared in 4.2BSD Unix.  rlogin is a command used to login to
   * a remote machine from a trusted host, sometimes without issuing a
   * password.  The trust relationship is the same as described in
   * the documentation for
   * <a href="org.apache.commons.net.bsd.RCommandClient.html"> RCommandClient </a>.
   * <p>
   * As with virtually all of the client classes in org.apache.commons.net, this
   * class derives from SocketClient.  But it relies on the connection
   * methods defined  in RcommandClient which ensure that the local Socket
   * will originate from an acceptable rshell port.  The way to use 
   * RLoginClient is to first connect
   * to the server, call the <a href="#rlogin"> rlogin() </a> method,
   * and then
   * fetch the connection's input and output streams.
   * Interaction with the remote command is controlled entirely through the
   * I/O streams.  Once you have finished processing the streams, you should
   * invoke <a href="org.apache.commons.net.bsd.RExecClient.html#disconnect"> 
   * disconnect() </a> to clean up properly.
   * <p>
   * The standard output and standard error streams of the
   * remote process are transmitted over the same connection, readable
   * from the input stream returned by
   * <a href="org.apache.commons.net.bsd.RExecClient.html#getInputStream">
   * getInputStream() </a>.  Unlike RExecClient and RCommandClient, it is
   * not possible to tell the rlogind daemon to return the standard error
   * stream over a separate connection.
   * <a href="org.apache.commons.net.bsd.RExecClient.html#getErrorStream">
   * getErrorStream() </a> will always return null.
   * The standard input of the remote process can be written to through
   * the output stream returned by 
   * <a href="org.apache.commons.net.bsd.RExecClient.html#getOutputStream"> 
   * getOutputSream() </a>.
   * <p>
   * <p>
   * @author Daniel F. Savarese
   * @see org.apache.commons.net.SocketClient
   * @see RExecClient
   * @see RCommandClient
   ***/
  
  public class RLoginClient extends RCommandClient {
    /***
     * The default rlogin port.  Set to 513 in BSD Unix and according 
     * to RFC 1282.
     ***/
    public static final int DEFAULT_PORT    = 513;
  
    /***
     * The default RLoginClient constructor.  Initializes the
     * default port to <code> DEFAULT_PORT </code>.
     ***/
    public RLoginClient() {
      setDefaultPort(DEFAULT_PORT);
    }
  
  
    /***
     * Logins into a remote machine through the rlogind daemon on the server
     * to which the RLoginClient is connected.  After calling this method,
     * you may interact with the remote login shell through its standard input
     * and output streams.  Standard error is sent over the same stream as
     * standard output.  You will typically be able to detect
     * the termination of the remote login shell after reaching end of file
     * on its standard output (accessible through
     * <a href="#getInputStream"> getInputStream() </a>.  Disconnecting
     * from the server or closing the process streams before reaching
     * end of file will terminate the remote login shell in most cases.
     * <p>
     * If user authentication fails, the rlogind daemon will request that
     * a password be entered interactively.  You will be able to read the
     * prompt from the output stream of the RLoginClient and write the
     * password to the input stream of the RLoginClient.
     * <p>
     * @param localUsername  The user account on the local machine that is
     *        trying to login to the remote host.
     * @param remoteUsername  The account name on the server that is
     *        being logged in to.
     * @param terminalType   The name of the user's terminal (e.g., "vt100",
     *        "network", etc.)
     * @param terminalSpeed  The speed of the user's terminal, expressed
     *        as a baud rate or bps (e.g., 9600 or 38400)
     * @exception IOException If the rlogin() attempt fails.  The exception
     *            will contain a message indicating the nature of the failure.
     ***/
    public void rlogin(String localUsername, String remoteUsername,
  		     String terminalType, int terminalSpeed)
         throws IOException
    {
      rexec(localUsername, remoteUsername, terminalType + "/" + terminalSpeed,
  	  false);
    }
  
    /***
     * Same as the other rlogin method, but no terminal speed is defined.
     ***/
    public void rlogin(String localUsername, String remoteUsername,
  		     String terminalType)
         throws IOException
    {
      rexec(localUsername, remoteUsername, terminalType, false);
    }
  
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>