]> WPIA git - gigi.git/blobdiff - src/org/cacert/gigi/ping/SSLPinger.java
Merge "Suggestions to enhance the SQL call pattern."
[gigi.git] / src / org / cacert / gigi / ping / SSLPinger.java
index 32434079a3e477c7a7d8f8e138c01a8088f67156..505a6b349767a3856aec5504413016e554aa16ba 100644 (file)
@@ -3,42 +3,65 @@ package org.cacert.gigi.ping;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.math.BigInteger;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.nio.ByteBuffer;
 import java.nio.channels.SocketChannel;
-import java.security.NoSuchAlgorithmException;
+import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.SecureRandom;
 import java.util.Arrays;
 
 import javax.net.ssl.SNIHostName;
 import javax.net.ssl.SNIServerName;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLEngineResult.Status;
 import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLEngineResult.HandshakeStatus;
 import javax.net.ssl.SSLParameters;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import javax.security.cert.CertificateException;
 import javax.security.cert.X509Certificate;
 
+import org.cacert.gigi.dbObjects.CACertificate;
+import org.cacert.gigi.dbObjects.Certificate;
+import org.cacert.gigi.dbObjects.CertificateOwner;
+import org.cacert.gigi.dbObjects.Domain;
+
+import sun.security.x509.AVA;
+import sun.security.x509.X500Name;
+
 public class SSLPinger extends DomainPinger {
 
     public static final String[] TYPES = new String[] {
             "xmpp", "server-xmpp", "smtp", "imap"
     };
 
+    private KeyStore truststore;
+
+    public SSLPinger(KeyStore truststore) {
+        this.truststore = truststore;
+    }
+
     @Override
-    public void ping(String domain, String configuration, String expToken) {
-        try {
-            SocketChannel sch = SocketChannel.open();
-            String[] parts = configuration.split(":", 2);
-            sch.connect(new InetSocketAddress(domain, Integer.parseInt(parts[0])));
-            if (parts.length == 2) {
-                switch (parts[1]) {
+    public void ping(Domain domain, String configuration, CertificateOwner u, int confId) {
+        try (SocketChannel sch = SocketChannel.open()) {
+            sch.socket().setSoTimeout(5000);
+            String[] parts = configuration.split(":", 4);
+            sch.socket().connect(new InetSocketAddress(domain.getSuffix(), Integer.parseInt(parts[2])), 5000);
+            if (parts.length == 4) {
+                switch (parts[3]) {
                 case "xmpp":
-                    startXMPP(sch, false, domain);
+                    startXMPP(sch, false, domain.getSuffix());
                     break;
                 case "server-xmpp":
-                    startXMPP(sch, true, domain);
+                    startXMPP(sch, true, domain.getSuffix());
                     break;
                 case "smtp":
                     startSMTP(sch);
@@ -49,9 +72,14 @@ public class SSLPinger extends DomainPinger {
 
                 }
             }
-            test(sch, domain);
+            String key = parts[0];
+            String value = parts[1];
+            String res = test(sch, domain.getSuffix(), u, value);
+            enterPingResult(confId, res, res, null);
+            return;
         } catch (IOException e) {
-            e.printStackTrace();
+            enterPingResult(confId, "error", "connection Failed", null);
+            return;
         }
 
     }
@@ -61,7 +89,7 @@ public class SSLPinger extends DomainPinger {
         InputStream is = s.getInputStream();
         OutputStream os = s.getOutputStream();
         scanFor(is, "\n");
-        os.write("ENABLE STARTTLS\r\n".getBytes());
+        os.write("ENABLE STARTTLS\r\n".getBytes("UTF-8"));
         os.flush();
         scanFor(is, "\n");
     }
@@ -70,9 +98,9 @@ public class SSLPinger extends DomainPinger {
         Socket s = sch.socket();
         InputStream is = s.getInputStream();
         OutputStream os = s.getOutputStream();
-        os.write(("<stream:stream to=\"" + domain + "\" xmlns=\"jabber:" + (server ? "server" : "client") + "\"" + " xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">").getBytes());
+        os.write(("<stream:stream to=\"" + domain + "\" xmlns=\"jabber:" + (server ? "server" : "client") + "\"" + " xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">").getBytes("UTF-8"));
         os.flush();
-        os.write("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>".getBytes());
+        os.write("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>".getBytes("UTF-8"));
         os.flush();
         scanFor(is, "<proceed");
         scanFor(is, ">");
@@ -94,13 +122,13 @@ public class SSLPinger extends DomainPinger {
         Socket s = sch.socket();
         InputStream is = s.getInputStream();
         readSMTP(is);
-        s.getOutputStream().write("EHLO ssl.pinger\r\n".getBytes());
+        s.getOutputStream().write("EHLO ssl.pinger\r\n".getBytes("UTF-8"));
         s.getOutputStream().flush();
         readSMTP(is);
-        s.getOutputStream().write("HELP\r\n".getBytes());
+        s.getOutputStream().write("HELP\r\n".getBytes("UTF-8"));
         s.getOutputStream().flush();
         readSMTP(is);
-        s.getOutputStream().write("STARTTLS\r\n".getBytes());
+        s.getOutputStream().write("STARTTLS\r\n".getBytes("UTF-8"));
         s.getOutputStream().flush();
         readSMTP(is);
     }
@@ -130,9 +158,40 @@ public class SSLPinger extends DomainPinger {
         }
     }
 
-    private void test(SocketChannel sch, String domain) {
+    private String test(SocketChannel sch, String domain, CertificateOwner subject, String tok) {
+        System.out.println("SSL- connecting");
+
         try {
-            SSLContext sc = SSLContext.getDefault();
+            sch.socket().setSoTimeout(5000);
+            SSLContext sc = SSLContext.getInstance("SSL");
+            try {
+                TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
+                tmf.init(truststore);
+                sc.init(null, new TrustManager[] {
+                    new X509TrustManager() {
+
+                        @Override
+                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+                            return null;
+                        }
+
+                        @Override
+                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
+                            java.security.cert.X509Certificate c = chain[0];
+                            if ( !c.getExtendedKeyUsage().contains("1.3.6.1.5.5.7.3.1")) {
+                                throw new java.security.cert.CertificateException("Illegal EKU");
+                            }
+                        }
+
+                        @Override
+                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {}
+                    }
+                }, new SecureRandom());
+            } catch (KeyManagementException e) {
+                e.printStackTrace();
+            } catch (KeyStoreException e) {
+                e.printStackTrace();
+            }
             SSLEngine se = sc.createSSLEngine();
             ByteBuffer enc_in = ByteBuffer.allocate(se.getSession().getPacketBufferSize());
             ByteBuffer enc_out = ByteBuffer.allocate(se.getSession().getPacketBufferSize());
@@ -179,18 +238,51 @@ public class SSLPinger extends DomainPinger {
                 }
 
             }
-            System.out.println("completed");
-            System.out.println(se.getSession().getCipherSuite());
+            System.out.println("SSL- connected");
             X509Certificate[] peerCertificateChain = se.getSession().getPeerCertificateChain();
-            for (X509Certificate x509Certificate : peerCertificateChain) {
-                System.out.println(x509Certificate.getSubjectDN().getName());
+            X509Certificate first = peerCertificateChain[0];
+            if (first.getIssuerDN().equals(first.getSubjectDN())) {
+                first.verify(first.getPublicKey());
+                X500Name p = (X500Name) first.getSubjectDN();
+                X500Name n = new X500Name(p.getEncoded());
+                for (AVA i : n.allAvas()) {
+                    if (i.getObjectIdentifier().equals((Object) X500Name.orgUnitName_oid)) {
+                        String toke = i.getDerValue().getAsString();
+                        if (tok.equals(toke)) {
+                            return PING_SUCCEDED;
+                        } else {
+                            return "Self-signed certificate is wrong";
+                        }
+                    }
+                }
+            }
+
+            BigInteger serial = first.getSerialNumber();
+            Certificate c = Certificate.getBySerial(serial.toString(16));
+            if (c == null) {
+                return "Certificate not found: Serial " + serial.toString(16) + " missing.";
+            }
+            CACertificate p = c.getParent();
+            if ( !first.getIssuerDN().equals(p.getCertificate().getSubjectDN())) {
+                return "Broken certificate supplied";
+            }
+            first.verify(p.getCertificate().getPublicKey());
+            if (c.getOwner().getId() != subject.getId()) {
+                return "Owner mismatch";
             }
-        } catch (NoSuchAlgorithmException e) {
-            e.printStackTrace();
+            return PING_SUCCEDED;
+        } catch (GeneralSecurityException e) {
+            // e.printStackTrace();
+            return "Security failed";
         } catch (SSLException e) {
-            e.printStackTrace();
+            // e.printStackTrace(); TODO log for user debugging?
+            return "Security failed";
         } catch (IOException e) {
-            e.printStackTrace();
+            // e.printStackTrace(); TODO log for user debugging?
+            return "Connection closed";
+        } catch (CertificateException e) {
+            // e.printStackTrace();
+            return "Security failed";
         }
     }
 }