import java.io.*;
import java.net.*;
import java.security.GeneralSecurityException;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Logger;
import javax.security.auth.x500.X500Principal;
import javax.sql.DataSource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.owasp.proxy.daemon.LoopAvoidingTargetedConnectionHandler;
import org.owasp.proxy.daemon.Proxy;
import org.owasp.proxy.daemon.ServerGroup;
import org.owasp.proxy.daemon.TargetedConnectionHandler;
import org.owasp.proxy.http.BufferedRequest;
import org.owasp.proxy.http.MutableBufferedRequest;
import org.owasp.proxy.http.MutableBufferedResponse;
import org.owasp.proxy.http.MessageFormatException;
import org.owasp.proxy.http.MutableRequestHeader;
import org.owasp.proxy.http.MutableResponseHeader;
import org.owasp.proxy.http.NamedValue;
import org.owasp.proxy.http.RequestHeader;
import org.owasp.proxy.http.client.HttpClient;
import org.owasp.proxy.http.dao.JdbcMessageDAO;
import org.owasp.proxy.http.server.BufferedMessageInterceptor;
import org.owasp.proxy.http.server.BufferingHttpRequestHandler;
import org.owasp.proxy.http.server.ConversationServiceHttpRequestHandler;
import org.owasp.proxy.http.server.DefaultHttpRequestHandler;
import org.owasp.proxy.http.server.HttpProxyConnectionHandler;
import org.owasp.proxy.http.server.HttpRequestHandler;
import org.owasp.proxy.http.server.LoggingHttpRequestHandler;
import org.owasp.proxy.http.server.RecordingHttpRequestHandler;
import org.owasp.proxy.socks.SocksConnectionHandler;
import org.owasp.proxy.ssl.AutoGeneratingContextSelector;
import org.owasp.proxy.ssl.SSLConnectionHandler;
import org.owasp.proxy.ssl.SSLContextSelector;
import org.owasp.proxy.util.TextFormatter;
public class Proxier {
private Proxy mainProxy;
private InetSocketAddress mainListener = null;
private boolean queryIsReplaced = false;
private String replacedQueryStr = "";
private boolean contentIsReplaced = false;
private byte[] replacedContent = null;
private boolean cookiesAreReplaced = false;
private boolean cookieLengthReplaced = false;
private String[] replacedCookieArr = null;
private boolean printRequestVar = false;
private boolean printResponseContentVar = false;
private static Logger logger = Logger.getLogger("org.owasp.proxy");
private void usage() {
System.err
.println("Usage: java -jar proxy.jar port [\"proxy instruction\"]");
System.err.println("Where \'proxy instruction\' might look like:");
System.err
.println("'DIRECT' or 'PROXY server:port' or 'SOCKS server:port'");
}
private ProxySelector getProxySelector(String proxy) {
final java.net.Proxy upstream;
if ("DIRECT".equals(proxy)) {
upstream = java.net.Proxy.NO_PROXY;
} else {
java.net.Proxy.Type type = null;
if (proxy.startsWith("PROXY ")) {
type = java.net.Proxy.Type.HTTP;
} else if (proxy.startsWith("SOCKS ")) {
type = java.net.Proxy.Type.SOCKS;
} else
throw new IllegalArgumentException("Unknown Proxy type: "
+ proxy);
proxy = proxy.substring(6); // "SOCKS " or "PROXY "
int c = proxy.indexOf(':');
if (c == -1)
throw new IllegalArgumentException("Illegal proxy address: "
+ proxy);
InetSocketAddress addr = new InetSocketAddress(proxy
.substring(0, c), Integer.parseInt(proxy.substring(c + 1)));
upstream = new java.net.Proxy(type, addr);
}
ProxySelector ps = new ProxySelector() {
@Override
public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
logger.info("Proxy connection to " + uri + " via " + sa
+ " failed! " + ioe.getLocalizedMessage());
}
@Override
public List<java.net.Proxy> select(URI uri) {
return Arrays.asList(upstream);
}
};
return ps;
}
private SSLContextSelector getSSLContextSelector()
throws GeneralSecurityException, IOException {
File ks = new File("ca.p12");
String type = "PKCS12";
char[] password = "password".toCharArray();
String alias = "CA";
if (ks.exists()) {
try {
return new AutoGeneratingContextSelector(ks, type, password,
password, alias);
} catch (GeneralSecurityException e) {
System.err.println("Error loading CA keys from keystore: "
+ e.getLocalizedMessage());
} catch (IOException e) {
System.err.println("Error loading CA keys from keystore: "
+ e.getLocalizedMessage());
}
}
System.err.println("Generating a new CA");
X500Principal ca = new X500Principal("cn=OWASP Custom CA for "
+ java.net.InetAddress.getLocalHost().getHostName()
+ ",ou=OWASP Custom CA,o=OWASP,l=OWASP,st=OWASP,c=OWASP");
AutoGeneratingContextSelector ssl = new AutoGeneratingContextSelector(
ca);
try {
ssl.save(ks, type, password, password, alias);
} catch (GeneralSecurityException e) {
System.err.println("Error saving CA keys to keystore: "
+ e.getLocalizedMessage());
} catch (IOException e) {
System.err.println("Error saving CA keys to keystore: "
+ e.getLocalizedMessage());
}
FileWriter pem = null;
try {
pem = new FileWriter("ca.pem");
pem.write(ssl.getCACert());
} catch (IOException e) {
System.err.println("Error writing CA cert : "
+ e.getLocalizedMessage());
} finally {
if (pem != null)
pem.close();
}
return ssl;
}
public void setReplaceQueryStringMode(boolean replaceQuery) {
queryIsReplaced = replaceQuery;
}
public void setQueryStringSuffix(String querySuffix) {
replacedQueryStr = querySuffix;
}
public void setReplaceContentMode(boolean replaceContent) {
contentIsReplaced = replaceContent;
}
public void setContent(byte[] content) {
replacedContent = content;
}
public void setReplaceCookies(boolean replaceCookies) {
cookiesAreReplaced = replaceCookies;
}
public void setCookies(String[] cookies) {
replacedCookieArr = cookies;
}
public void printRequestMode(boolean printRequest) {
printRequestVar = printRequest;
}
public void printResponseContentMode(boolean printContent) {
printResponseContentVar = printContent;
}
private String replaceQueryString(String queryString) {
queryString = queryString.replace(" HTTP", replacedQueryStr+" HTTP");
System.out.println(queryString);
return queryString;
}
private void replacePostContent(MutableBufferedRequest request) throws MessageFormatException {
request.setMethod("POST");
request.setHeader("Content-Type", "application/x-www-form-urlencoded");
request.setHeader("Content-Length", new Integer(replacedContent.length).toString());
request.setDecodedContent(replacedContent);
System.out.println("content:" + new String(request.getContent()));
}
private void printRequestHeaders(MutableBufferedRequest request) throws MessageFormatException {
System.out.println("Request:");
System.out.println("Warining: it's strings");
System.out.println(request.getResource());
NamedValue[] headers = request.getHeaders();
for (int i=0; i<headers.length; i++)
System.out.println(headers[i]);
}
private void printResponseContent(MutableBufferedResponse response) throws MessageFormatException {
System.out.println(new String(response.getDecodedContent()));
}
private void replaceCookies(MutableBufferedRequest request) throws MessageFormatException {
request.deleteHeader("Cookie");
for (int i=0; i<replacedCookieArr.length; i++) {
//String currCookie = "Cookie: " + replacedCookieArr[i] + "\n";
//request.setHeader(currCookie.getBytes());
request.addHeader("Cookie", replacedCookieArr[i]);
}
}
private void setProcessRequest(MutableBufferedRequest request) {
try {
if (queryIsReplaced) {
String queryString = request.getStartLine();
queryString = replaceQueryString(queryString);
request.setStartLine(queryString);
}
if (contentIsReplaced) {
replacePostContent(request);
}
if (cookiesAreReplaced) {
replaceCookies(request);
}
} catch (MessageFormatException mfe) {
mfe.printStackTrace();
}
}
private void setProcessResponse(BufferedRequest request,
MutableBufferedResponse response) {
byte[] cont = response.getContent();
String header = new String(response.getHeader());
String str = new String(cont);
//System.out.println();
//System.out.print(header);
//System.out.println(str);
}
private BufferedMessageInterceptor setInterseptor() {
BufferedMessageInterceptor bmi = new BufferedMessageInterceptor() {
@Override
public Action directResponse(RequestHeader request,
MutableResponseHeader response) {
//System.err.println(new String(request.getHeader())
//+ "+++++++++++\n" + new String(response.getHeader())
//+ "===========");
return Action.BUFFER;
}
public void processResponse(final BufferedRequest request,
final MutableBufferedResponse response) {
setProcessResponse(request, response);
try {
if (printResponseContentVar)
printResponseContent(response);
} catch (MessageFormatException e) {
e.printStackTrace();
}
}
@Override
public Action directRequest(MutableRequestHeader request) {
//System.err.println(new String(request.getHeader())
//+ "===========");
return Action.BUFFER;
}
public void processRequest(final MutableBufferedRequest request) {
setProcessRequest(request);
}
};
return bmi;
}
public void startProxy(String []args) throws GeneralSecurityException, IOException {
logger.setUseParentHandlers(false);
Handler ch = new ConsoleHandler();
ch.setFormatter(new TextFormatter());
logger.addHandler(ch);
if (args == null
|| (args.length != 1 && args.length != 2 && args.length != 5 && args.length != 6)) {
usage();
return;
}
try {
int port = Integer.parseInt(args[0]);
mainListener = new InetSocketAddress("localhost", port);
} catch (NumberFormatException nfe) {
usage();
return;
}
String proxy = "DIRECT";
if (args.length == 2 || args.length == 6) {
proxy = args[1];
}
final ProxySelector ps = getProxySelector(proxy);
DefaultHttpRequestHandler drh = new DefaultHttpRequestHandler() {
@Override
protected HttpClient createClient() {
HttpClient client = super.createClient();
client.setProxySelector(ps);
client.setSoTimeout(90000);
return client;
}
};
ServerGroup sg = new ServerGroup();
sg.addServer(mainListener);
drh.setServerGroup(sg);
HttpRequestHandler rh = drh;
rh = new LoggingHttpRequestHandler(rh);
BufferedMessageInterceptor bmi = setInterseptor();
rh = new BufferingHttpRequestHandler(rh, bmi, 10240);
HttpProxyConnectionHandler hpch = new HttpProxyConnectionHandler(rh);
SSLContextSelector cp = getSSLContextSelector();
TargetedConnectionHandler tch = new SSLConnectionHandler(cp, true, hpch);
tch = new LoopAvoidingTargetedConnectionHandler(sg, tch);
hpch.setConnectHandler(tch);
TargetedConnectionHandler socks = new SocksConnectionHandler(tch, true);
mainProxy = new Proxy(mainListener, socks, null);
mainProxy.setSocketTimeout(90000);
mainProxy.start();
System.out.println("Proxy: Listener started on " + mainListener);
}
public void stopProxy() {
mainProxy.stop();
System.out.println("Proxy: Proxy on " + mainListener + " was stopped");
}
public InetSocketAddress getListener() {
return mainListener;
}
}