]> WPIA git - gigi.git/blobdiff - src/org/cacert/gigi/Launcher.java
add: implement opt-in for notification of RA Agent
[gigi.git] / src / org / cacert / gigi / Launcher.java
index 56d0d4fba2f17551add4113bb0689f921b9af437..5f767a63956a3da4ce8cb4be5256e8403b77da68 100644 (file)
@@ -1,6 +1,12 @@
 package org.cacert.gigi;
 
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
 import java.io.IOException;
+import java.net.HttpURLConnection;
+import java.net.InetSocketAddress;
 import java.security.GeneralSecurityException;
 import java.security.Key;
 import java.security.KeyStore;
@@ -8,6 +14,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;
@@ -25,13 +34,17 @@ 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;
@@ -50,20 +63,65 @@ 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");
-        new Launcher().boot();
+        InputStream in;
+        if (args.length >= 1) {
+            in = new FileInputStream(new File(args[0]));
+        } else {
+            in = System.in;
+        }
+        new Launcher().boot(in);
     }
 
     Server s;
 
     GigiConfig conf;
 
-    public synchronized void boot() throws Exception {
+    private boolean isSystemPort(int port) {
+        return 1 <= port && port <= 1024;
+    }
+
+    public synchronized void boot(InputStream in) throws Exception {
         Locale.setDefault(Locale.ENGLISH);
         TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
+        HttpURLConnection.setFollowRedirects(false);
 
-        conf = GigiConfig.parse(System.in);
+        conf = GigiConfig.parse(in);
         ServerConstants.init(conf.getMainProps());
         initEmails(conf);
 
@@ -73,7 +131,7 @@ public class Launcher {
         initHandlers();
 
         s.start();
-        if ((ServerConstants.getSecurePort() <= 1024 || ServerConstants.getPort() <= 1024) && !System.getProperty("os.name").toLowerCase().contains("win")) {
+        if ((isSystemPort(ServerConstants.getSecurePort()) || isSystemPort(ServerConstants.getPort())) && !System.getProperty("os.name").toLowerCase().contains("win")) {
             SetUID uid = new SetUID();
             if ( !uid.setUid(65536 - 2, 65536 - 2).getSuccess()) {
                 Log.getLogger(Launcher.class).warn("Couldn't set uid!");
@@ -90,19 +148,30 @@ public class Launcher {
     }
 
     private void initConnectors() throws GeneralSecurityException, IOException {
-        HttpConfiguration httpsConfig = createHttpConfiguration();
-        // for client-cert auth
-        httpsConfig.addCustomizer(new SecureRequestCustomizer());
         HttpConfiguration httpConfig = createHttpConfiguration();
-        s.setConnectors(new Connector[] {
-                ConnectorsLauncher.createConnector(conf, s, httpsConfig, true), ConnectorsLauncher.createConnector(conf, s, httpConfig, false)
-        });
+        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);
     }
 
@@ -112,16 +181,19 @@ public class Launcher {
 
         protected static ServerConnector createConnector(GigiConfig conf, Server s, HttpConfiguration httpConfig, boolean doHttps) throws GeneralSecurityException, IOException {
             ServerConnector connector;
+            int port;
             if (doHttps) {
                 connector = new ServerConnector(s, createConnectionFactory(conf), new HttpConnectionFactory(httpConfig));
+                port = ServerConstants.getSecurePort();
             } else {
                 connector = new ServerConnector(s, new HttpConnectionFactory(httpConfig));
+                port = ServerConstants.getPort();
             }
-            connector.setHost(conf.getMainProps().getProperty("host"));
-            if (doHttps) {
-                connector.setPort(ServerConstants.getSecurePort());
+            if (port == -1) {
+                connector.setInheritChannel(true);
             } else {
-                connector.setPort(ServerConstants.getPort());
+                connector.setHost(conf.getMainProps().getProperty("host"));
+                connector.setPort(port);
             }
             connector.setAcceptQueueSize(100);
             return connector;
@@ -131,7 +203,7 @@ public class Launcher {
             final SslContextFactory sslContextFactory = generateSSLContextFactory(conf, "www");
             final SslContextFactory secureContextFactory = generateSSLContextFactory(conf, "secure");
             secureContextFactory.setWantClientAuth(true);
-            secureContextFactory.setNeedClientAuth(false);
+            secureContextFactory.setNeedClientAuth(true);
             final SslContextFactory staticContextFactory = generateSSLContextFactory(conf, "static");
             final SslContextFactory apiContextFactory = generateSSLContextFactory(conf, "api");
             apiContextFactory.setWantClientAuth(true);
@@ -232,11 +304,11 @@ public class Launcher {
 
             ContextHandler ch = generateGigiServletContext(webAppServlet);
             ch.setVirtualHosts(new String[] {
-                ServerConstants.getWwwHostName()
+                    ServerConstants.getWwwHostName()
             });
             ContextHandler chSecure = generateGigiServletContext(webAppServlet);
             chSecure.setVirtualHosts(new String[] {
-                ServerConstants.getSecureHostName()
+                    ServerConstants.getSecureHostName()
             });
 
             HandlerList hl = new HandlerList();
@@ -254,7 +326,7 @@ public class Launcher {
             hw.setHandler(rh);
 
             ServletContextHandler servlet = new ServletContextHandler(ServletContextHandler.SESSIONS);
-            servlet.setInitParameter(SessionManager.__SessionCookieProperty, "CACert-Session");
+            servlet.setInitParameter(SessionManager.__SessionCookieProperty, "SomeCA-Session");
             servlet.addServlet(webAppServlet, "/*");
             ErrorPageErrorHandler epeh = new ErrorPageErrorHandler();
             epeh.addErrorPage(404, "/error");
@@ -278,7 +350,7 @@ public class Launcher {
             ContextHandler ch = new ContextHandler();
             ch.setHandler(rh);
             ch.setVirtualHosts(new String[] {
-                ServerConstants.getStaticHostName()
+                    ServerConstants.getStaticHostName()
             });
 
             return ch;
@@ -301,7 +373,7 @@ public class Launcher {
             ServletContextHandler sch = new ServletContextHandler();
 
             sch.addVirtualHosts(new String[] {
-                ServerConstants.getApiHostName()
+                    ServerConstants.getApiHostName()
             });
             sch.addServlet(new ServletHolder(new GigiAPI()), "/*");
             return sch;