528 lines
14 KiB
Java

package org.owasp.webgoat.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.BitSet;
/***************************************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
* please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2007 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at code.google.com, a repository for free software
* projects.
*
* For details, please see http://code.google.com/p/webgoat/
*
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
* @created October 28, 2003
*/
public class Exec
{
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @param input
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execInput(String command, String input)
{
return (execOptions(command, input, 0, 0, false));
}
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execLazy(String command)
{
return (execOptions(command, "", 0, 0, true));
}
/*
* Execute an OS command and capture the output in an ExecResults. All exceptions are caught and
* stored in the ExecResults. @param String command is the OS command to execute @param String
* input is piped into the OS command @param int successCode is the expected return code if the
* command completes successfully @param int timeout is the number of milliseconds to wait
* before interrupting the command @param boolean quit tells the method to exit when there is no
* more output waiting
*/
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @param input
* Description of the Parameter
* @param successCode
* Description of the Parameter
* @param timeout
* Description of the Parameter
* @param lazy
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execOptions(String[] command, String input, int successCode, int timeout, boolean lazy)
{
Process child = null;
ByteArrayOutputStream output = new ByteArrayOutputStream();
ByteArrayOutputStream errors = new ByteArrayOutputStream();
ExecResults results = new ExecResults(Arrays.asList(command).toString(), input, successCode, timeout);
BitSet interrupted = new BitSet(1);
boolean lazyQuit = false;
ThreadWatcher watcher;
try
{
// start the command
child = Runtime.getRuntime().exec(command);
// get the streams in and out of the command
InputStream processIn = child.getInputStream();
InputStream processError = child.getErrorStream();
OutputStream processOut = child.getOutputStream();
// start the clock running
if (timeout > 0)
{
watcher = new ThreadWatcher(child, interrupted, timeout);
new Thread(watcher).start();
}
// Write to the child process' input stream
if ((input != null) && !input.equals(""))
{
try
{
processOut.write(input.getBytes());
processOut.flush();
processOut.close();
} catch (IOException e1)
{
results.setThrowable(e1);
}
}
// Read from the child process' output stream
// The process may get killed by the watcher at any time
int c = 0;
try
{
while (true)
{
if (interrupted.get(0) || lazyQuit)
{
break;
}
// interrupted
c = processIn.read();
if (c == -1)
{
break;
}
// end of stream
output.write(c);
if (lazy && (processIn.available() < 1))
{
lazyQuit = true;
}
// if lazy and nothing then quit (after at least one read)
}
processIn.close();
} catch (IOException e2)
{
results.setThrowable(e2);
} finally
{
if (interrupted.get(0))
{
results.setInterrupted();
}
results.setOutput(output.toString());
}
// Read from the child process' error stream
// The process may get killed by the watcher at any time
try
{
while (true)
{
if (interrupted.get(0) || lazyQuit)
{
break;
}
// interrupted
c = processError.read();
if (c == -1)
{
break;
}
// end of stream
output.write(c);
if (lazy && (processError.available() < 1))
{
lazyQuit = true;
}
// if lazy and nothing then quit (after at least one read)
}
processError.close();
} catch (IOException e3)
{
results.setThrowable(e3);
} finally
{
if (interrupted.get(0))
{
results.setInterrupted();
}
results.setErrors(errors.toString());
}
// wait for the return value of the child process.
if (!interrupted.get(0) && !lazyQuit)
{
int returnCode = child.waitFor();
results.setReturnCode(returnCode);
if (returnCode != successCode)
{
results.setError(ExecResults.BADRETURNCODE);
}
}
} catch (InterruptedException i)
{
results.setInterrupted();
} catch (Throwable t)
{
results.setThrowable(t);
} finally
{
if (child != null)
{
child.destroy();
}
}
return (results);
}
/*
* Execute an OS command and capture the output in an ExecResults. All exceptions are caught and
* stored in the ExecResults. @param String command is the OS command to execute @param String
* input is piped into the OS command @param int successCode is the expected return code if the
* command completes successfully @param int timeout is the number of milliseconds to wait
* before interrupting the command @param boolean quit tells the method to exit when there is no
* more output waiting
*/
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @param input
* Description of the Parameter
* @param successCode
* Description of the Parameter
* @param timeout
* Description of the Parameter
* @param lazy
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execOptions(String command, String input, int successCode, int timeout, boolean lazy)
{
Process child = null;
ByteArrayOutputStream output = new ByteArrayOutputStream();
ByteArrayOutputStream errors = new ByteArrayOutputStream();
ExecResults results = new ExecResults(command, input, successCode, timeout);
BitSet interrupted = new BitSet(1);
boolean lazyQuit = false;
ThreadWatcher watcher;
try
{
// start the command
child = Runtime.getRuntime().exec(command);
// get the streams in and out of the command
InputStream processIn = child.getInputStream();
InputStream processError = child.getErrorStream();
OutputStream processOut = child.getOutputStream();
// start the clock running
if (timeout > 0)
{
watcher = new ThreadWatcher(child, interrupted, timeout);
new Thread(watcher).start();
}
// Write to the child process' input stream
if ((input != null) && !input.equals(""))
{
try
{
processOut.write(input.getBytes());
processOut.flush();
processOut.close();
} catch (IOException e1)
{
results.setThrowable(e1);
}
}
// Read from the child process' output stream
// The process may get killed by the watcher at any time
int c = 0;
try
{
while (true)
{
if (interrupted.get(0) || lazyQuit)
{
break;
}
// interrupted
c = processIn.read();
if (c == -1)
{
break;
}
// end of stream
output.write(c);
if (lazy && (processIn.available() < 1))
{
lazyQuit = true;
}
// if lazy and nothing then quit (after at least one read)
}
processIn.close();
} catch (IOException e2)
{
results.setThrowable(e2);
} finally
{
if (interrupted.get(0))
{
results.setInterrupted();
}
results.setOutput(output.toString());
}
// Read from the child process' error stream
// The process may get killed by the watcher at any time
try
{
while (true)
{
if (interrupted.get(0) || lazyQuit)
{
break;
}
// interrupted
c = processError.read();
if (c == -1)
{
break;
}
// end of stream
output.write(c);
if (lazy && (processError.available() < 1))
{
lazyQuit = true;
}
// if lazy and nothing then quit (after at least one read)
}
processError.close();
} catch (IOException e3)
{
results.setThrowable(e3);
} finally
{
if (interrupted.get(0))
{
results.setInterrupted();
}
results.setErrors(errors.toString());
}
// wait for the return value of the child process.
if (!interrupted.get(0) && !lazyQuit)
{
int returnCode = child.waitFor();
results.setReturnCode(returnCode);
if (returnCode != successCode)
{
results.setError(ExecResults.BADRETURNCODE);
}
}
} catch (InterruptedException i)
{
results.setInterrupted();
} catch (Throwable t)
{
results.setThrowable(t);
} finally
{
if (child != null)
{
child.destroy();
}
}
return (results);
}
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execSimple(String[] command)
{
return (execOptions(command, "", 0, 0, false));
}
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execSimple(String command)
{
return (execOptions(command, "", 0, 0, false));
}
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @param args
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execSimple(String command, String args)
{
return (execOptions(command, args, 0, 0, false));
}
/**
* Description of the Method
*
* @param command
* Description of the Parameter
* @param timeout
* Description of the Parameter
* @return Description of the Return Value
*/
public static ExecResults execTimeout(String command, int timeout)
{
return (execOptions(command, "", 0, timeout, false));
}
/**
* The main program for the Exec class
*
* @param args
* The command line arguments
*/
public static void main(String[] args)
{
ExecResults results;
String sep = System.getProperty("line.separator");
System.out.println("-------------------------------------------" + sep + "TEST 1: execSimple");
results = Exec.execSimple("c:/swarm-2.1.1/bin/whoami.exe");
System.out.println(results);
System.out.println("-------------------------------------------" + sep + "TEST 2: execSimple (with search)");
results = Exec.execSimple("netstat -r");
System.out.println(results);
if (results.outputContains("localhost:1031"))
{
System.out.println("ERROR: listening on 1031");
}
System.out.println("-------------------------------------------" + sep + "TEST 3: execInput");
results = Exec.execInput("find \"cde\"", "abcdefg1\nhijklmnop\nqrstuv\nabcdefg2");
System.out.println(results);
System.out.println("-------------------------------------------" + sep + "TEST 4:execTimeout");
results = Exec.execTimeout("ping -t 127.0.0.1", 5 * 1000);
System.out.println(results);
System.out.println("-------------------------------------------" + sep + "TEST 5:execLazy");
results = Exec.execLazy("ping -t 127.0.0.1");
System.out.println(results);
System.out.println("-------------------------------------------" + sep
+ "TEST 6:ExecTimeout process never outputs");
results = Exec.execTimeout("c:/swarm-2.1.1/bin/sleep.exe 20", 5 * 1000);
System.out.println(results);
System.out.println("-------------------------------------------" + sep
+ "TEST 7:ExecTimeout process waits for input");
results = Exec.execTimeout("c:/swarm-2.1.1/bin/cat", 5 * 1000);
System.out.println(results);
}
}