/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2010 psiinon@gmail.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zaproxy.zap; import java.io.File; import java.io.IOException; import java.util.Enumeration; import java.util.Locale; import org.apache.commons.httpclient.protocol.Protocol; import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import org.apache.log4j.Appender; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.parosproxy.paros.CommandLine; import org.parosproxy.paros.Constant; import org.parosproxy.paros.network.SSLConnector; import org.zaproxy.zap.eventBus.EventBus; import org.zaproxy.zap.eventBus.SimpleEventBus; import org.zaproxy.zap.utils.ClassLoaderUtil; public class ZAP { /** * ZAP can be run in 4 different ways: * cmdline: an inline process that exits when it completes the tasks specified by the parameters * daemon: a single process with no Swing UI, typically run as a background process * desktop: a Swing based desktop tool (which is how is originated, as a fork of Paros Proxy) * zaas: a highly scalable distributed system with a web based UI, aka 'ZAP as a Service' (this is 'work in progress') */ public enum ProcessType {cmdline, daemon, desktop, zaas} private static ProcessType processType; private static final EventBus eventBus = new SimpleEventBus(); private static final Logger logger = Logger.getLogger(ZAP.class); static { Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionLogger()); // set SSLConnector as socketfactory in HttpClient. ProtocolSocketFactory sslFactory = null; try { final Protocol protocol = Protocol.getProtocol("https"); sslFactory = protocol.getSocketFactory(); } catch (final IllegalStateException e) { // Print the exception - log not yet initialised e.printStackTrace(); } if (sslFactory == null || !(sslFactory instanceof SSLConnector)) { Protocol.registerProtocol("https", new Protocol("https", (ProtocolSocketFactory) new SSLConnector(), 443)); } } /** * Main method * * @param args * the arguments passed to the command line version * @throws Exception * if something wrong happens */ public static void main(String[] args) throws Exception { CommandLine cmdLine = null; try { cmdLine = new CommandLine(args); } catch (final Exception e) { // Cant use the CommandLine help here as the // i18n messages wont have been loaded System.out.println("Failed due to invalid parameters. Use '-h' for more details."); System.exit(1); } initClassLoader(); ZapBootstrap bootstrap = createZapBootstrap(cmdLine); try { int rc = bootstrap.start(); if (rc != 0) { System.exit(rc); } } catch (final Exception e) { logger.fatal(e.getMessage(), e); System.exit(1); } } private static void initClassLoader() { try { // lang directory includes all of the language files final File langDir = new File(Constant.getZapInstall(), "lang"); if (langDir.exists() && langDir.isDirectory()) { ClassLoaderUtil.addFile(langDir.getAbsolutePath()); } else { System.out .println("Warning: failed to load language files from " + langDir.getAbsolutePath()); } // Load all of the jars in the lib directory final File libDir = new File(Constant.getZapInstall(), "lib"); if (libDir.exists() && libDir.isDirectory()) { final File[] files = libDir.listFiles(); for (final File file : files) { if (file.getName().toLowerCase(Locale.ENGLISH) .endsWith("jar")) { ClassLoaderUtil.addFile(file); } } } else { System.out.println("Warning: failed to load jar files from " + libDir.getAbsolutePath()); } } catch (final IOException e) { System.out.println("Failed loading jars: " + e); } } private static ZapBootstrap createZapBootstrap(CommandLine cmdLineArgs) { ZapBootstrap bootstrap; if (cmdLineArgs.isGUI()) { ZAP.processType = ProcessType.desktop; bootstrap = new GuiBootstrap(cmdLineArgs); } else if (cmdLineArgs.isDaemon()) { ZAP.processType = ProcessType.daemon; bootstrap = new DaemonBootstrap(cmdLineArgs); } else { ZAP.processType = ProcessType.cmdline; bootstrap = new CommandLineBootstrap(cmdLineArgs); } return bootstrap; } public static ProcessType getProcessType() { return processType; } public static EventBus getEventBus() { return eventBus; } private static final class UncaughtExceptionLogger implements Thread.UncaughtExceptionHandler { private static final Logger logger = Logger .getLogger(UncaughtExceptionLogger.class); private static boolean loggerConfigured = false; @Override public void uncaughtException(Thread t, Throwable e) { if (!(e instanceof ThreadDeath)) { if (loggerConfigured || isLoggerConfigured()) { logger.error("Exception in thread \"" + t.getName() + "\"", e); } else { System.err.println("Exception in thread \"" + t.getName() + "\""); e.printStackTrace(); } } } private static boolean isLoggerConfigured() { if (loggerConfigured) { return true; } @SuppressWarnings("unchecked") Enumeration<Appender> appenders = LogManager.getRootLogger() .getAllAppenders(); if (appenders.hasMoreElements()) { loggerConfigured = true; } else { @SuppressWarnings("unchecked") Enumeration<Logger> loggers = LogManager.getCurrentLoggers(); while (loggers.hasMoreElements()) { Logger c = loggers.nextElement(); if (c.getAllAppenders().hasMoreElements()) { loggerConfigured = true; break; } } } return loggerConfigured; } } }