X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Forg%2Fcacert%2Fgigi%2FLauncher.java;h=7bf5bd119554387739d8b07a2647342cde3f82df;hp=7448151a3bbc3bbef960438d943ad4ae5d100c2e;hb=d23d7a6fa9dc38c6193fea70017e0bff11257be5;hpb=d945bd512a5d2036d23acec82977106efc8d7f74 diff --git a/src/org/cacert/gigi/Launcher.java b/src/org/cacert/gigi/Launcher.java index 7448151a..7bf5bd11 100644 --- a/src/org/cacert/gigi/Launcher.java +++ b/src/org/cacert/gigi/Launcher.java @@ -1,6 +1,8 @@ package org.cacert.gigi; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.net.InetSocketAddress; import java.security.GeneralSecurityException; import java.security.Key; import java.security.KeyStore; @@ -8,6 +10,9 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.util.List; import java.util.Locale; import java.util.Properties; @@ -19,17 +24,23 @@ import javax.net.ssl.SNIServerName; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLParameters; import javax.net.ssl.SSLSession; +import javax.servlet.http.HttpServletResponse; import org.cacert.gigi.api.GigiAPI; import org.cacert.gigi.email.EmailProvider; import org.cacert.gigi.natives.SetUID; import org.cacert.gigi.util.CipherInfo; +import org.cacert.gigi.util.PEM; import org.cacert.gigi.util.ServerConstants; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConfiguration.Customizer; import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.SecureRequestCustomizer; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -43,40 +54,67 @@ import org.eclipse.jetty.servlet.ErrorPageErrorHandler; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.ssl.SslContextFactory; public class Launcher { + class ExtendedForwarded implements Customizer { + + @Override + public void customize(Connector connector, HttpConfiguration config, Request request) { + HttpFields httpFields = request.getHttpFields(); + + String ip = httpFields.getStringField("X-Real-IP"); + String proto = httpFields.getStringField("X-Real-Proto"); + String cert = httpFields.getStringField("X-Client-Cert"); + request.setSecure("https".equals(proto)); + request.setScheme(proto); + if ( !"https".equals(proto)) { + cert = null; + + } + if (cert != null) { + X509Certificate[] certs = new X509Certificate[1]; + try { + certs[0] = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(PEM.decode("CERTIFICATE", cert))); + request.setAttribute("javax.servlet.request.X509Certificate", certs); + } catch (CertificateException e) { + e.printStackTrace(); + } + } + if (ip != null) { + String[] parts = ip.split(":"); + if (parts.length == 2) { + request.setRemoteAddr(InetSocketAddress.createUnresolved(parts[0], Integer.parseInt(parts[1]))); + } + } + + } + } + public static void main(String[] args) throws Exception { System.setProperty("jdk.tls.ephemeralDHKeySize", "4096"); - boot(); + new Launcher().boot(); } - public static void boot() throws Exception { + Server s; + + GigiConfig conf; + + public synchronized void boot() throws Exception { Locale.setDefault(Locale.ENGLISH); TimeZone.setDefault(TimeZone.getTimeZone("UTC")); - GigiConfig conf = GigiConfig.parse(System.in); + conf = GigiConfig.parse(System.in); ServerConstants.init(conf.getMainProps()); initEmails(conf); - Server s = new Server(); - HttpConfiguration httpsConfig = createHttpConfiguration(); + s = new Server(); - // for client-cert auth - httpsConfig.addCustomizer(new SecureRequestCustomizer()); + initConnectors(); + initHandlers(); - HttpConfiguration httpConfig = createHttpConfiguration(); - - s.setConnectors(new Connector[] { - createConnector(conf, s, httpsConfig, true), createConnector(conf, s, httpConfig, false) - }); - - HandlerList hl = new HandlerList(); - hl.setHandlers(new Handler[] { - generateStaticContext(), generateGigiContexts(conf.getMainProps(), conf.getTrustStore()), generateAPIContext() - }); - s.setHandler(hl); s.start(); if ((ServerConstants.getSecurePort() <= 1024 || ServerConstants.getPort() <= 1024) && !System.getProperty("os.name").toLowerCase().contains("win")) { SetUID uid = new SetUID(); @@ -84,29 +122,9 @@ public class Launcher { Log.getLogger(Launcher.class).warn("Couldn't set uid!"); } } - if (conf.getMainProps().containsKey("testrunner")) { - DevelLauncher.addDevelPage(); - } - } - - private static ServerConnector createConnector(GigiConfig conf, Server s, HttpConfiguration httpConfig, boolean doHttps) throws GeneralSecurityException, IOException { - ServerConnector connector; - if (doHttps) { - connector = new ServerConnector(s, createConnectionFactory(conf), new HttpConnectionFactory(httpConfig)); - } else { - connector = new ServerConnector(s, new HttpConnectionFactory(httpConfig)); - } - connector.setHost(conf.getMainProps().getProperty("host")); - if (doHttps) { - connector.setPort(ServerConstants.getSecurePort()); - } else { - connector.setPort(ServerConstants.getPort()); - } - connector.setAcceptQueueSize(100); - return connector; } - private static HttpConfiguration createHttpConfiguration() { + private HttpConfiguration createHttpConfiguration() { // SSL HTTP Configuration HttpConfiguration httpsConfig = new HttpConfiguration(); httpsConfig.setSendServerVersion(false); @@ -114,163 +132,235 @@ public class Launcher { return httpsConfig; } - private static void initEmails(GigiConfig conf) throws GeneralSecurityException, IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { + private void initConnectors() throws GeneralSecurityException, IOException { + HttpConfiguration httpConfig = createHttpConfiguration(); + if (conf.getMainProps().getProperty("proxy", "false").equals("true")) { + httpConfig.addCustomizer(new ExtendedForwarded()); + s.setConnectors(new Connector[] { + ConnectorsLauncher.createConnector(conf, s, httpConfig, false) + }); + } else { + HttpConfiguration httpsConfig = createHttpConfiguration(); + // for client-cert auth + httpsConfig.addCustomizer(new SecureRequestCustomizer()); + s.setConnectors(new Connector[] { + ConnectorsLauncher.createConnector(conf, s, httpsConfig, true), ConnectorsLauncher.createConnector(conf, s, httpConfig, false) + }); + } + } + + private void initEmails(GigiConfig conf) throws GeneralSecurityException, IOException, KeyStoreException, NoSuchAlgorithmException, UnrecoverableKeyException { KeyStore privateStore = conf.getPrivateStore(); - Certificate mail = privateStore.getCertificate("mail"); - Key k = privateStore.getKey("mail", conf.getPrivateStorePw().toCharArray()); + Certificate mail = null; + Key k = null; + if (privateStore != null && privateStore.containsAlias("mail")) { + mail = privateStore.getCertificate("mail"); + k = privateStore.getKey("mail", conf.getPrivateStorePw().toCharArray()); + } EmailProvider.initSystem(conf.getMainProps(), mail, k); } - private static SslConnectionFactory createConnectionFactory(GigiConfig conf) throws GeneralSecurityException, IOException { - final SslContextFactory sslContextFactory = generateSSLContextFactory(conf, "www"); - final SslContextFactory secureContextFactory = generateSSLContextFactory(conf, "secure"); - secureContextFactory.setWantClientAuth(true); - secureContextFactory.setNeedClientAuth(false); - final SslContextFactory staticContextFactory = generateSSLContextFactory(conf, "static"); - final SslContextFactory apiContextFactory = generateSSLContextFactory(conf, "api"); - try { - secureContextFactory.start(); - staticContextFactory.start(); - apiContextFactory.start(); - } catch (Exception e) { - e.printStackTrace(); + private static class ConnectorsLauncher { + + private ConnectorsLauncher() {} + + protected static ServerConnector createConnector(GigiConfig conf, Server s, HttpConfiguration httpConfig, boolean doHttps) throws GeneralSecurityException, IOException { + ServerConnector connector; + if (doHttps) { + connector = new ServerConnector(s, createConnectionFactory(conf), new HttpConnectionFactory(httpConfig)); + } else { + connector = new ServerConnector(s, new HttpConnectionFactory(httpConfig)); + } + connector.setHost(conf.getMainProps().getProperty("host")); + if (doHttps) { + connector.setPort(ServerConstants.getSecurePort()); + } else { + connector.setPort(ServerConstants.getPort()); + } + connector.setAcceptQueueSize(100); + return connector; } - return new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()) { - @Override - public boolean shouldRestartSSL() { - return true; + private static SslConnectionFactory createConnectionFactory(GigiConfig conf) throws GeneralSecurityException, IOException { + final SslContextFactory sslContextFactory = generateSSLContextFactory(conf, "www"); + final SslContextFactory secureContextFactory = generateSSLContextFactory(conf, "secure"); + secureContextFactory.setWantClientAuth(true); + secureContextFactory.setNeedClientAuth(true); + final SslContextFactory staticContextFactory = generateSSLContextFactory(conf, "static"); + final SslContextFactory apiContextFactory = generateSSLContextFactory(conf, "api"); + apiContextFactory.setWantClientAuth(true); + try { + secureContextFactory.start(); + staticContextFactory.start(); + apiContextFactory.start(); + } catch (Exception e) { + e.printStackTrace(); } + return new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()) { - @Override - public SSLEngine restartSSL(SSLSession sslSession) { - SSLEngine e2 = null; - if (sslSession instanceof ExtendedSSLSession) { - ExtendedSSLSession es = (ExtendedSSLSession) sslSession; - List names = es.getRequestedServerNames(); - for (SNIServerName sniServerName : names) { - if (sniServerName instanceof SNIHostName) { - SNIHostName host = (SNIHostName) sniServerName; - String hostname = host.getAsciiName(); - if (hostname.equals(ServerConstants.getWwwHostName())) { - e2 = sslContextFactory.newSSLEngine(); - } else if (hostname.equals(ServerConstants.getStaticHostName())) { - e2 = staticContextFactory.newSSLEngine(); - } else if (hostname.equals(ServerConstants.getSecureHostName())) { - e2 = secureContextFactory.newSSLEngine(); - } else if (hostname.equals(ServerConstants.getApiHostName())) { - e2 = apiContextFactory.newSSLEngine(); + @Override + public boolean shouldRestartSSL() { + return true; + } + + @Override + public SSLEngine restartSSL(SSLSession sslSession) { + SSLEngine e2 = null; + if (sslSession instanceof ExtendedSSLSession) { + ExtendedSSLSession es = (ExtendedSSLSession) sslSession; + List names = es.getRequestedServerNames(); + for (SNIServerName sniServerName : names) { + if (sniServerName instanceof SNIHostName) { + SNIHostName host = (SNIHostName) sniServerName; + String hostname = host.getAsciiName(); + if (hostname.equals(ServerConstants.getWwwHostName())) { + e2 = sslContextFactory.newSSLEngine(); + } else if (hostname.equals(ServerConstants.getStaticHostName())) { + e2 = staticContextFactory.newSSLEngine(); + } else if (hostname.equals(ServerConstants.getSecureHostName())) { + e2 = secureContextFactory.newSSLEngine(); + } else if (hostname.equals(ServerConstants.getApiHostName())) { + e2 = apiContextFactory.newSSLEngine(); + } + break; } - break; } } + if (e2 == null) { + e2 = sslContextFactory.newSSLEngine(sslSession.getPeerHost(), sslSession.getPeerPort()); + } + e2.setUseClientMode(false); + return e2; } - if (e2 == null) { - e2 = sslContextFactory.newSSLEngine(sslSession.getPeerHost(), sslSession.getPeerPort()); - } - e2.setUseClientMode(false); - return e2; - } - }; - } + }; + } - private static Handler generateGigiContexts(Properties conf, KeyStore trust) { - ServletHolder webAppServlet = new ServletHolder(new Gigi(conf, trust)); + private static SslContextFactory generateSSLContextFactory(GigiConfig conf, String alias) throws GeneralSecurityException, IOException { + SslContextFactory scf = new SslContextFactory() { - ContextHandler ch = generateGigiServletContext(webAppServlet); - ch.setVirtualHosts(new String[] { - ServerConstants.getWwwHostName() - }); - ContextHandler chSecure = generateGigiServletContext(webAppServlet); - chSecure.setVirtualHosts(new String[] { - ServerConstants.getSecureHostName() - }); + String[] ciphers = null; - HandlerList hl = new HandlerList(); - hl.setHandlers(new Handler[] { - ch, chSecure - }); - return hl; - } + @Override + public void customize(SSLEngine sslEngine) { + super.customize(sslEngine); - private static ContextHandler generateGigiServletContext(ServletHolder webAppServlet) { - final ResourceHandler rh = new ResourceHandler(); - rh.setResourceBase("static/www"); + SSLParameters ssl = sslEngine.getSSLParameters(); + ssl.setUseCipherSuitesOrder(true); + if (ciphers == null) { + ciphers = CipherInfo.filter(sslEngine.getSupportedCipherSuites()); + } - HandlerWrapper hw = new PolicyRedirector(); - hw.setHandler(rh); + ssl.setCipherSuites(ciphers); + sslEngine.setSSLParameters(ssl); - ServletContextHandler servlet = new ServletContextHandler(ServletContextHandler.SESSIONS); - servlet.setInitParameter(SessionManager.__SessionCookieProperty, "CACert-Session"); - servlet.addServlet(webAppServlet, "/*"); - ErrorPageErrorHandler epeh = new ErrorPageErrorHandler(); - epeh.addErrorPage(404, "/error"); - epeh.addErrorPage(403, "/denied"); - servlet.setErrorHandler(epeh); + } + }; + scf.setRenegotiationAllowed(false); + + scf.setProtocol("TLS"); + scf.setIncludeProtocols("TLSv1", "TLSv1.1", "TLSv1.2"); + scf.setTrustStore(conf.getTrustStore()); + KeyStore privateStore = conf.getPrivateStore(); + scf.setKeyStorePassword(conf.getPrivateStorePw()); + scf.setKeyStore(privateStore); + scf.setCertAlias(alias); + return scf; + } + } + + private void initHandlers() throws GeneralSecurityException, IOException { HandlerList hl = new HandlerList(); hl.setHandlers(new Handler[] { - hw, servlet + ContextLauncher.generateStaticContext(), ContextLauncher.generateGigiContexts(conf.getMainProps(), conf.getTrustStore()), ContextLauncher.generateAPIContext() }); - - ContextHandler ch = new ContextHandler(); - ch.setHandler(hl); - return ch; + s.setHandler(hl); } - private static Handler generateStaticContext() { - final ResourceHandler rh = new ResourceHandler(); - rh.setResourceBase("static/static"); + private static class ContextLauncher { - ContextHandler ch = new ContextHandler(); - ch.setHandler(rh); - ch.setVirtualHosts(new String[] { - ServerConstants.getStaticHostName() - }); + private ContextLauncher() {} - return ch; - } + protected static Handler generateGigiContexts(Properties conf, KeyStore trust) { + ServletHolder webAppServlet = new ServletHolder(new Gigi(conf, trust)); - private static Handler generateAPIContext() { - ServletContextHandler sch = new ServletContextHandler(); + ContextHandler ch = generateGigiServletContext(webAppServlet); + ch.setVirtualHosts(new String[] { + ServerConstants.getWwwHostName() + }); + ContextHandler chSecure = generateGigiServletContext(webAppServlet); + chSecure.setVirtualHosts(new String[] { + ServerConstants.getSecureHostName() + }); - sch.addVirtualHosts(new String[] { - ServerConstants.getApiHostName() - }); - sch.addServlet(new ServletHolder(new GigiAPI()), "/*"); - return sch; - } + HandlerList hl = new HandlerList(); + hl.setHandlers(new Handler[] { + ch, chSecure + }); + return hl; + } + + private static ContextHandler generateGigiServletContext(ServletHolder webAppServlet) { + final ResourceHandler rh = generateResourceHandler(); + rh.setResourceBase("static/www"); + + HandlerWrapper hw = new PolicyRedirector(); + hw.setHandler(rh); + + ServletContextHandler servlet = new ServletContextHandler(ServletContextHandler.SESSIONS); + servlet.setInitParameter(SessionManager.__SessionCookieProperty, "SomeCA-Session"); + servlet.addServlet(webAppServlet, "/*"); + ErrorPageErrorHandler epeh = new ErrorPageErrorHandler(); + epeh.addErrorPage(404, "/error"); + epeh.addErrorPage(403, "/denied"); + servlet.setErrorHandler(epeh); + + HandlerList hl = new HandlerList(); + hl.setHandlers(new Handler[] { + hw, servlet + }); + + ContextHandler ch = new ContextHandler(); + ch.setHandler(hl); + return ch; + } + + protected static Handler generateStaticContext() { + final ResourceHandler rh = generateResourceHandler(); + rh.setResourceBase("static/static"); - private static SslContextFactory generateSSLContextFactory(GigiConfig conf, String alias) throws GeneralSecurityException, IOException { - SslContextFactory scf = new SslContextFactory() { + ContextHandler ch = new ContextHandler(); + ch.setHandler(rh); + ch.setVirtualHosts(new String[] { + ServerConstants.getStaticHostName() + }); - String[] ciphers = null; + return ch; + } - @Override - public void customize(SSLEngine sslEngine) { - super.customize(sslEngine); + private static ResourceHandler generateResourceHandler() { + ResourceHandler rh = new ResourceHandler() { - SSLParameters ssl = sslEngine.getSSLParameters(); - ssl.setUseCipherSuitesOrder(true); - if (ciphers == null) { - ciphers = CipherInfo.filter(sslEngine.getSupportedCipherSuites()); + @Override + protected void doResponseHeaders(HttpServletResponse response, Resource resource, String mimeType) { + super.doResponseHeaders(response, resource, mimeType); + response.setDateHeader(HttpHeader.EXPIRES.asString(), System.currentTimeMillis() + 1000L * 60 * 60 * 24 * 7); } + }; + rh.setEtags(true); + return rh; + } - ssl.setCipherSuites(ciphers); - sslEngine.setSSLParameters(ssl); + protected static Handler generateAPIContext() { + ServletContextHandler sch = new ServletContextHandler(); - } - - }; - scf.setRenegotiationAllowed(false); + sch.addVirtualHosts(new String[] { + ServerConstants.getApiHostName() + }); + sch.addServlet(new ServletHolder(new GigiAPI()), "/*"); + return sch; + } - scf.setProtocol("TLS"); - scf.setIncludeProtocols("TLSv1", "TLSv1.1", "TLSv1.2"); - scf.setTrustStore(conf.getTrustStore()); - KeyStore privateStore = conf.getPrivateStore(); - scf.setKeyStorePassword(conf.getPrivateStorePw()); - scf.setKeyStore(privateStore); - scf.setCertAlias(alias); - return scf; } + }