Coverage report

  %line %branch
org.apache.commons.net.bsd.RExecClient
0% 
0% 

 1  
 /*
 2  
  * Copyright 2001-2005 The Apache Software Foundation
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.apache.commons.net.bsd;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.InputStream;
 20  
 import java.net.ServerSocket;
 21  
 import java.net.Socket;
 22  
 import org.apache.commons.net.io.SocketInputStream;
 23  
 import org.apache.commons.net.SocketClient;
 24  
 import java.io.OutputStream;
 25  
 
 26  
 /***
 27  
  * RExecClient implements the rexec() facility that first appeared in
 28  
  * 4.2BSD Unix.  This class will probably only be of use for connecting
 29  
  * to Unix systems and only when the rexecd daemon is configured to run,
 30  
  * which is a rarity these days because of the security risks involved.
 31  
  * However, rexec() can be very useful for performing administrative tasks
 32  
  * on a network behind a firewall.
 33  
  * <p>
 34  
  * As with virtually all of the client classes in org.apache.commons.net, this
 35  
  * class derives from SocketClient, inheriting its connection methods.
 36  
  * The way to use RExecClient is to first connect
 37  
  * to the server, call the {@link #rexec  rexec() } method, and then
 38  
  * fetch the connection's input, output, and optionally error streams.
 39  
  * Interaction with the remote command is controlled entirely through the
 40  
  * I/O streams.  Once you have finished processing the streams, you should
 41  
  * invoke {@link #disconnect  disconnect() } to clean up properly.
 42  
  * <p>
 43  
  * By default the standard output and standard error streams of the
 44  
  * remote process are transmitted over the same connection, readable
 45  
  * from the input stream returned by
 46  
  * {@link #getInputStream  getInputStream() }.  However, it is
 47  
  * possible to tell the rexecd daemon to return the standard error
 48  
  * stream over a separate connection, readable from the input stream
 49  
  * returned by {@link #getErrorStream  getErrorStream() }.  You
 50  
  * can specify that a separate connection should be created for standard
 51  
  * error by setting the boolean <code> separateErrorStream </code>
 52  
  * parameter of {@link #rexec  rexec() } to <code> true </code>.
 53  
  * The standard input of the remote process can be written to through
 54  
  * the output stream returned by
 55  
  * {@link #getOutputStream  getOutputSream() }.
 56  
  * <p>
 57  
  * <p>
 58  
  * @author Daniel F. Savarese
 59  
  * @see SocketClient
 60  
  * @see RCommandClient
 61  
  * @see RLoginClient
 62  
  ***/
 63  
 
 64  
 public class RExecClient extends SocketClient
 65  
 {
 66  
     /***
 67  
      * The default rexec port.  Set to 512 in BSD Unix.
 68  
      ***/
 69  
     public static final int DEFAULT_PORT = 512;
 70  
 
 71  
     private boolean __remoteVerificationEnabled;
 72  
 
 73  
     /***
 74  
      * If a separate error stream is requested, <code>_errorStream_</code>
 75  
      * will point to an InputStream from which the standard error of the
 76  
      * remote process can be read (after a call to rexec()).  Otherwise,
 77  
      * <code> _errorStream_ </code> will be null.
 78  
      ***/
 79  
     protected InputStream _errorStream_;
 80  
 
 81  
     // This can be overridden in local package to implement port range
 82  
     // limitations of rcmd and rlogin
 83  
     InputStream _createErrorStream() throws IOException
 84  
     {
 85  
         ServerSocket server;
 86  
         Socket socket;
 87  
 
 88  0
         server = _socketFactory_.createServerSocket(0, 1, getLocalAddress());
 89  
 
 90  0
         _output_.write(Integer.toString(server.getLocalPort()).getBytes());
 91  0
         _output_.write('\0');
 92  0
         _output_.flush();
 93  
 
 94  0
         socket = server.accept();
 95  0
         server.close();
 96  
 
 97  0
         if (__remoteVerclass="keyword">ificationEnabled && !verclass="keyword">ifyRemote(socket))
 98  
         {
 99  0
             socket.close();
 100  0
             throw new IOException(
 101  
                 "Security violation: unexpected connection attempt by " +
 102  
                 socket.getInetAddress().getHostAddress());
 103  
         }
 104  
 
 105  0
         return (new SocketInputStream(socket, socket.getInputStream()));
 106  
     }
 107  
 
 108  
 
 109  
     /***
 110  
      * The default RExecClient constructor.  Initializes the
 111  
      * default port to <code> DEFAULT_PORT </code>.
 112  
      ***/
 113  
     public RExecClient()
 114  0
     {
 115  0
         _errorStream_ = null;
 116  0
         setDefaultPort(DEFAULT_PORT);
 117  0
     }
 118  
 
 119  
 
 120  
     /***
 121  
      * Returns the InputStream from which the standard outputof the remote
 122  
      * process can be read.  The input stream will only be set after a
 123  
      * successful rexec() invocation.
 124  
      * <p>
 125  
      * @return The InputStream from which the standard output of the remote
 126  
      * process can be read.
 127  
      ***/
 128  
     public InputStream getInputStream()
 129  
     {
 130  0
         return _input_;
 131  
     }
 132  
 
 133  
 
 134  
     /***
 135  
      * Returns the OutputStream through which the standard input of the remote
 136  
      * process can be written.  The output stream will only be set after a
 137  
      * successful rexec() invocation.
 138  
      * <p>
 139  
      * @return The OutputStream through which the standard input of the remote
 140  
      * process can be written.
 141  
      ***/
 142  
     public OutputStream getOutputStream()
 143  
     {
 144  0
         return _output_;
 145  
     }
 146  
 
 147  
 
 148  
     /***
 149  
      * Returns the InputStream from which the standard error of the remote
 150  
      * process can be read if a separate error stream is requested from
 151  
      * the server.  Otherwise, null will be returned.  The error stream
 152  
      * will only be set after a successful rexec() invocation.
 153  
      * <p>
 154  
      * @return The InputStream from which the standard error of the remote
 155  
      * process can be read if a separate error stream is requested from
 156  
      * the server.  Otherwise, null will be returned.
 157  
      ***/
 158  
     public InputStream getErrorStream()
 159  
     {
 160  0
         return _errorStream_;
 161  
     }
 162  
 
 163  
 
 164  
     /***
 165  
      * Remotely executes a command through the rexecd daemon on the server
 166  
      * to which the RExecClient is connected.  After calling this method,
 167  
      * you may interact with the remote process through its standard input,
 168  
      * output, and error streams.  You will typically be able to detect
 169  
      * the termination of the remote process after reaching end of file
 170  
      * on its standard output (accessible through
 171  
      * {@link #getInputStream  getInputStream() }.    Disconnecting
 172  
      * from the server or closing the process streams before reaching
 173  
      * end of file will not necessarily terminate the remote process.
 174  
      * <p>
 175  
      * If a separate error stream is requested, the remote server will
 176  
      * connect to a local socket opened by RExecClient, providing an
 177  
      * independent stream through which standard error will be transmitted.
 178  
      * RExecClient will do a simple security check when it accepts a
 179  
      * connection for this error stream.  If the connection does not originate
 180  
      * from the remote server, an IOException will be thrown.  This serves as
 181  
      * a simple protection against possible hijacking of the error stream by
 182  
      * an attacker monitoring the rexec() negotiation.  You may disable this
 183  
      * behavior with {@link #setRemoteVerificationEnabled setRemoteVerificationEnabled()}
 184  
      * .
 185  
      * <p>
 186  
      * @param username  The account name on the server through which to execute
 187  
      *                  the command.
 188  
      * @param password  The plain text password of the user account.
 189  
      * @param command   The command, including any arguments, to execute.
 190  
      * @param separateErrorStream True if you would like the standard error
 191  
      *        to be transmitted through a different stream than standard output.
 192  
      *        False if not.
 193  
      * @exception IOException If the rexec() attempt fails.  The exception
 194  
      *            will contain a message indicating the nature of the failure.
 195  
      ***/
 196  
     public void rexec(String username, String password,
 197  
                       String command, boolean separateErrorStream)
 198  
     throws IOException
 199  
     {
 200  
         int ch;
 201  
 
 202  0
         if (separateErrorStream)
 203  
         {
 204  0
             _errorStream_ = _createErrorStream();
 205  
         }
 206  
         else
 207  
         {
 208  0
             _output_.write('\0');
 209  
         }
 210  
 
 211  0
         _output_.write(username.getBytes());
 212  0
         _output_.write('\0');
 213  0
         _output_.write(password.getBytes());
 214  0
         _output_.write('\0');
 215  0
         _output_.write(command.getBytes());
 216  0
         _output_.write('\0');
 217  0
         _output_.flush();
 218  
 
 219  0
         ch = _input_.read();
 220  0
         if (ch > 0)
 221  
         {
 222  0
             StringBuffer buffer = new StringBuffer();
 223  
 
 224  0
             while ((ch = _input_.read()) != -1 && ch != '\n')
 225  0
                 buffer.append((char)ch);
 226  
 
 227  0
             throw new IOException(buffer.toString());
 228  
         }
 229  0
         else if (ch < 0)
 230  
         {
 231  0
             throw new IOException("Server closed connection.");
 232  
         }
 233  0
     }
 234  
 
 235  
 
 236  
     /***
 237  
      * Same as <code> rexec(username, password, command, false); </code>
 238  
      ***/
 239  
     public void rexec(String username, String password,
 240  
                       String command)
 241  
     throws IOException
 242  
     {
 243  0
         rexec(username, password, command, false);
 244  0
     }
 245  
 
 246  
     /***
 247  
      * Disconnects from the server, closing all associated open sockets and
 248  
      * streams.
 249  
      * <p>
 250  
      * @exception IOException If there an error occurs while disconnecting.
 251  
      ***/
 252  
     public void disconnect() throws IOException
 253  
     {
 254  0
         if (_errorStream_ != null)
 255  0
             _errorStream_.close();
 256  0
         _errorStream_ = null;
 257  0
         super.disconnect();
 258  0
     }
 259  
 
 260  
 
 261  
     /***
 262  
      * Enable or disable verification that the remote host connecting to
 263  
      * create a separate error stream is the same as the host to which
 264  
      * the standard out stream is connected.  The default is for verification
 265  
      * to be enabled.  You may set this value at any time, whether the
 266  
      * client is currently connected or not.
 267  
      * <p>
 268  
      * @param enable True to enable verification, false to disable verification.
 269  
      ***/
 270  
     public final void setRemoteVerificationEnabled(boolean enable)
 271  
     {
 272  0
         __remoteVerificationEnabled = enable;
 273  0
     }
 274  
 
 275  
     /***
 276  
      * Return whether or not verification of the remote host providing a
 277  
      * separate error stream is enabled.  The default behavior is for
 278  
      * verification to be enabled.
 279  
      * <p>
 280  
      * @return True if verification is enabled, false if not.
 281  
      ***/
 282  
     public final boolean isRemoteVerificationEnabled()
 283  
     {
 284  0
         return __remoteVerificationEnabled;
 285  
     }
 286  
 
 287  
 }
 288  
 

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.