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.