From 446d3aa82c177eb844f6f19c8f85d4a6e631efe7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Sun, 24 Aug 2014 09:33:11 +0200 Subject: [PATCH] ADD: simple pinger daemon. --- doc/tableStructure.sql | 3 +- src/org/cacert/gigi/Domain.java | 11 +++ src/org/cacert/gigi/EmailAddress.java | 16 +---- src/org/cacert/gigi/Gigi.java | 4 ++ src/org/cacert/gigi/User.java | 5 ++ src/org/cacert/gigi/email/MailProbe.java | 28 ++++++++ src/org/cacert/gigi/email/Sendmail.java | 1 + src/org/cacert/gigi/pages/Verify.java | 12 ++++ .../gigi/pages/account/DomainAddForm.java | 3 +- src/org/cacert/gigi/ping/DNSPinger.java | 9 +-- src/org/cacert/gigi/ping/DomainPinger.java | 5 +- src/org/cacert/gigi/ping/EmailPinger.java | 23 ++++++ src/org/cacert/gigi/ping/HTTPFetch.java | 8 ++- src/org/cacert/gigi/ping/PingerDaemon.java | 72 ++++++++++++------- src/org/cacert/gigi/ping/SSLPinger.java | 13 ++-- 15 files changed, 158 insertions(+), 55 deletions(-) create mode 100644 src/org/cacert/gigi/email/MailProbe.java create mode 100644 src/org/cacert/gigi/ping/EmailPinger.java diff --git a/doc/tableStructure.sql b/doc/tableStructure.sql index 6b2806da..2d5fa6c3 100644 --- a/doc/tableStructure.sql +++ b/doc/tableStructure.sql @@ -87,7 +87,8 @@ CREATE TABLE `domainPinglog` ( `when` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `configId` int(13) NOT NULL, `state` enum('open', 'success', 'failed') NOT NULL, - `result` varchar(255) NOT NULL + `challenge` varchar(16) NOT NULL, + `result` varchar(255) ) ENGINE=InnoDB DEFAULT CHARSET=latin1; DROP TABLE IF EXISTS `baddomains`; diff --git a/src/org/cacert/gigi/Domain.java b/src/org/cacert/gigi/Domain.java index 89a3d2b6..3eb628aa 100644 --- a/src/org/cacert/gigi/Domain.java +++ b/src/org/cacert/gigi/Domain.java @@ -115,4 +115,15 @@ public class Domain { throw new GigiApiException(e); } } + + public void verify(String hash) throws GigiApiException { + try { + PreparedStatement ps = DatabaseConnection.getInstance().prepare("UPDATE domainPinglog SET state='success' WHERE challenge=? AND configId IN (SELECT id FROM pingconfig WHERE domainId=?)"); + ps.setString(1, hash); + ps.setInt(2, id); + ps.executeUpdate(); + } catch (SQLException e) { + throw new GigiApiException(e); + } + } } diff --git a/src/org/cacert/gigi/EmailAddress.java b/src/org/cacert/gigi/EmailAddress.java index 480da6f4..5259fbcd 100644 --- a/src/org/cacert/gigi/EmailAddress.java +++ b/src/org/cacert/gigi/EmailAddress.java @@ -7,9 +7,9 @@ import java.sql.SQLException; import org.cacert.gigi.database.DatabaseConnection; import org.cacert.gigi.email.EmailProvider; +import org.cacert.gigi.email.MailProbe; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.util.RandomToken; -import org.cacert.gigi.util.ServerConstants; public class EmailAddress { @@ -56,19 +56,7 @@ public class EmailAddress { ps.setString(3, address); ps.execute(); id = DatabaseConnection.lastInsertId(ps); - StringBuffer body = new StringBuffer(); - body.append(l.getTranslation("Thanks for signing up with CAcert.org, below is the link you need to open to verify your account. Once your account is verified you will be able to start issuing certificates till your hearts' content!")); - body.append("\n\nhttps://"); - body.append(ServerConstants.getWwwHostNamePort()); - body.append("/verify?type=email&id="); - body.append(id); - body.append("&hash="); - body.append(hash); - body.append("\n\n"); - body.append(l.getTranslation("Best regards")); - body.append("\n"); - body.append(l.getTranslation("CAcert.org Support!")); - EmailProvider.getInstance().sendmail(address, "[CAcert.org] " + l.getTranslation("Mail Probe"), body.toString(), "support@cacert.org", null, null, null, null, false); + MailProbe.sendMailProbe(l, "email", id, hash, address); } catch (SQLException e) { e.printStackTrace(); } catch (IOException e) { diff --git a/src/org/cacert/gigi/Gigi.java b/src/org/cacert/gigi/Gigi.java index 3d902281..1e7ee0f9 100644 --- a/src/org/cacert/gigi/Gigi.java +++ b/src/org/cacert/gigi/Gigi.java @@ -37,6 +37,7 @@ import org.cacert.gigi.pages.error.PageNotFound; import org.cacert.gigi.pages.main.RegisterPage; import org.cacert.gigi.pages.wot.AssurePage; import org.cacert.gigi.pages.wot.MyPoints; +import org.cacert.gigi.ping.PingerDaemon; import org.cacert.gigi.util.ServerConstants; public class Gigi extends HttpServlet { @@ -61,12 +62,15 @@ public class Gigi extends HttpServlet { private static Gigi instance; + private PingerDaemon pinger = new PingerDaemon(); + public Gigi(Properties conf) { if (instance != null) { new IllegalStateException("Multiple Gigi instances!"); } instance = this; DatabaseConnection.init(conf); + pinger.start(); } @Override diff --git a/src/org/cacert/gigi/User.java b/src/org/cacert/gigi/User.java index e251a987..ca1c8ff8 100644 --- a/src/org/cacert/gigi/User.java +++ b/src/org/cacert/gigi/User.java @@ -8,6 +8,7 @@ import java.util.Calendar; import org.cacert.gigi.database.DatabaseConnection; import org.cacert.gigi.util.Notary; +import org.cacert.gigi.localisation.Language; import org.cacert.gigi.util.PasswordHash; import org.cacert.gigi.util.PasswordStrengthChecker; @@ -445,4 +446,8 @@ public class User { update.executeUpdate(); } } + + public Language getPrefferedLanguage() { + return Language.getInstance("de"); + } } diff --git a/src/org/cacert/gigi/email/MailProbe.java b/src/org/cacert/gigi/email/MailProbe.java new file mode 100644 index 00000000..7bca705c --- /dev/null +++ b/src/org/cacert/gigi/email/MailProbe.java @@ -0,0 +1,28 @@ +package org.cacert.gigi.email; + +import java.io.IOException; + +import org.cacert.gigi.localisation.Language; +import org.cacert.gigi.util.ServerConstants; + +public class MailProbe { + + public static void sendMailProbe(Language l, String type, int id, String hash, String address) throws IOException { + StringBuffer body = new StringBuffer(); + body.append(l.getTranslation("Thanks for signing up with CAcert.org, below is the link you need to open to verify your account. Once your account is verified you will be able to start issuing certificates till your hearts' content!")); + body.append("\n\nhttps://"); + body.append(ServerConstants.getWwwHostNamePort()); + body.append("/verify?type="); + body.append(type); + body.append("&id="); + body.append(id); + body.append("&hash="); + body.append(hash); + body.append("\n\n"); + body.append(l.getTranslation("Best regards")); + body.append("\n"); + body.append(l.getTranslation("CAcert.org Support!")); + EmailProvider.getInstance().sendmail(address, "[CAcert.org] " + l.getTranslation("Mail Probe"), body.toString(), "support@cacert.org", null, null, null, null, false); + } + +} diff --git a/src/org/cacert/gigi/email/Sendmail.java b/src/org/cacert/gigi/email/Sendmail.java index 812de6bd..60113050 100644 --- a/src/org/cacert/gigi/email/Sendmail.java +++ b/src/org/cacert/gigi/email/Sendmail.java @@ -95,6 +95,7 @@ public class Sendmail extends EmailProvider { private static void readResponse(BufferedReader in) throws IOException { String line; while ((line = in.readLine()) != null && line.matches("\\d+-")) { + System.out.println(line); } } diff --git a/src/org/cacert/gigi/pages/Verify.java b/src/org/cacert/gigi/pages/Verify.java index fff62628..f64c2145 100644 --- a/src/org/cacert/gigi/pages/Verify.java +++ b/src/org/cacert/gigi/pages/Verify.java @@ -2,9 +2,11 @@ package org.cacert.gigi.pages; import java.io.IOException; import java.io.PrintWriter; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.cacert.gigi.Domain; import org.cacert.gigi.EmailAddress; import org.cacert.gigi.GigiApiException; @@ -37,6 +39,16 @@ public class Verify extends Page { } catch (GigiApiException e) { e.format(out, getLanguage(req)); } + } else if ("domain".equals(type)) { + try { + Domain ea = Domain.getById(Integer.parseInt(id)); + ea.verify(hash); + out.println("Domain verification completed."); + } catch (IllegalArgumentException e) { + out.println(translate(req, "The domain address is invalid.")); + } catch (GigiApiException e) { + e.format(out, getLanguage(req)); + } } } diff --git a/src/org/cacert/gigi/pages/account/DomainAddForm.java b/src/org/cacert/gigi/pages/account/DomainAddForm.java index edf729e5..e37dbaaa 100644 --- a/src/org/cacert/gigi/pages/account/DomainAddForm.java +++ b/src/org/cacert/gigi/pages/account/DomainAddForm.java @@ -47,7 +47,7 @@ public class DomainAddForm extends Form { d.insert(); if (req.getParameter("emailType") != null) { String mail = AUTHORATIVE_EMAILS[Integer.parseInt(req.getParameter("email"))]; - d.addPing("email", mail + "@" + d.getSuffix()); + d.addPing("email", mail); } if (req.getParameter("DNSType") != null) { d.addPing("dns", tokenName + ":" + tokenValue); @@ -56,7 +56,6 @@ public class DomainAddForm extends Form { d.addPing("http", tokenName + ":" + tokenValue); } if (req.getParameter("SSLType") != null) { - System.out.println("ssl"); List types = Arrays.asList(SSLPinger.TYPES); for (int i = 0; i < MAX_SSL_TESTS; i++) { String type = req.getParameter("ssl-type-" + i); diff --git a/src/org/cacert/gigi/ping/DNSPinger.java b/src/org/cacert/gigi/ping/DNSPinger.java index 3dc9ac60..35e17148 100644 --- a/src/org/cacert/gigi/ping/DNSPinger.java +++ b/src/org/cacert/gigi/ping/DNSPinger.java @@ -3,18 +3,20 @@ package org.cacert.gigi.ping; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; -import java.util.Arrays; import java.util.LinkedList; +import org.cacert.gigi.Domain; +import org.cacert.gigi.User; + public class DNSPinger extends DomainPinger { @Override - public String ping(String domain, String expToken) { + public String ping(Domain domain, String expToken, User u) { try { String[] tokenParts = expToken.split(":", 2); Process p = Runtime.getRuntime().exec(new String[] { - "dig", "+short", "NS", domain + "dig", "+short", "NS", domain.getSuffix() }); BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream())); String line; @@ -31,7 +33,6 @@ public class DNSPinger extends DomainPinger { String[] call = new String[] { "dig", "@" + NS, "+short", "TXT", "cacert-" + tokenParts[0] + "." + domain }; - System.out.println(Arrays.toString(call)); p = Runtime.getRuntime().exec(call); br = new BufferedReader(new InputStreamReader(p.getInputStream())); String token = null; diff --git a/src/org/cacert/gigi/ping/DomainPinger.java b/src/org/cacert/gigi/ping/DomainPinger.java index 3044f34d..c9b8a9bb 100644 --- a/src/org/cacert/gigi/ping/DomainPinger.java +++ b/src/org/cacert/gigi/ping/DomainPinger.java @@ -1,10 +1,13 @@ package org.cacert.gigi.ping; +import org.cacert.gigi.Domain; +import org.cacert.gigi.User; + public abstract class DomainPinger { public static final String PING_STILL_PENDING = null; public static final String PING_SUCCEDED = ""; - public abstract String ping(String domain, String configuration); + public abstract String ping(Domain domain, String configuration, User user); } diff --git a/src/org/cacert/gigi/ping/EmailPinger.java b/src/org/cacert/gigi/ping/EmailPinger.java new file mode 100644 index 00000000..ea63c0b6 --- /dev/null +++ b/src/org/cacert/gigi/ping/EmailPinger.java @@ -0,0 +1,23 @@ +package org.cacert.gigi.ping; + +import java.io.IOException; +import org.cacert.gigi.Domain; +import org.cacert.gigi.User; +import org.cacert.gigi.email.MailProbe; + +public class EmailPinger extends DomainPinger { + + @Override + public String ping(Domain domain, String configuration, User u) { + String[] parts = configuration.split(":", 2); + String mail = parts[0] + "@" + domain.getSuffix(); + try { + MailProbe.sendMailProbe(u.getPrefferedLanguage(), "domain", domain.getId(), parts[1], mail); + } catch (IOException e) { + e.printStackTrace(); + return "Mail connection interrupted"; + } + return PING_STILL_PENDING; + } + +} diff --git a/src/org/cacert/gigi/ping/HTTPFetch.java b/src/org/cacert/gigi/ping/HTTPFetch.java index 3bb2d095..5450f265 100644 --- a/src/org/cacert/gigi/ping/HTTPFetch.java +++ b/src/org/cacert/gigi/ping/HTTPFetch.java @@ -6,14 +6,16 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; +import org.cacert.gigi.Domain; +import org.cacert.gigi.User; + public class HTTPFetch extends DomainPinger { @Override - public String ping(String domain, String expToken) { + public String ping(Domain domain, String expToken, User user) { try { String[] tokenParts = expToken.split(":", 2); - URL u = new URL("http://" + domain + "/cacert_" + tokenParts[0] + ".txt"); - System.out.println(u.toString()); + URL u = new URL("http://" + domain.getSuffix() + "/cacert-" + tokenParts[0] + ".txt"); HttpURLConnection huc = (HttpURLConnection) u.openConnection(); if (huc.getResponseCode() != 200) { return "Invalid status code."; diff --git a/src/org/cacert/gigi/ping/PingerDaemon.java b/src/org/cacert/gigi/ping/PingerDaemon.java index 595b6a6f..253780cb 100644 --- a/src/org/cacert/gigi/ping/PingerDaemon.java +++ b/src/org/cacert/gigi/ping/PingerDaemon.java @@ -8,44 +8,66 @@ import java.sql.SQLException; import java.util.HashMap; import java.util.Properties; +import org.cacert.gigi.Domain; +import org.cacert.gigi.User; import org.cacert.gigi.database.DatabaseConnection; +import org.cacert.gigi.util.RandomToken; -public class PingerDaemon implements Runnable { +public class PingerDaemon extends Thread { HashMap pingers = new HashMap<>(); - public PingerDaemon() { - // pingers.put("email",); - pingers.put("ssl", new SSLPinger()); - pingers.put("http", new HTTPFetch()); - pingers.put("dns", new DNSPinger()); + private PreparedStatement searchNeededPings; - } + private PreparedStatement enterPingResult; @Override public void run() { try { - PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT pingconfig.*, domains.domain FROM pingconfig LEFT JOIN domainPinglog ON domainPinglog.configId=pingconfig.id INNER JOIN domains ON domains.id=pingconfig.domainid WHERE domainPinglog.configId IS NULL "); - PreparedStatement result = DatabaseConnection.getInstance().prepare("INSERT INTO domainPinglog SET configId=?, state=?, result=?"); - - ResultSet rs = ps.executeQuery(); - while (rs.next()) { - String type = rs.getString("type"); - String config = rs.getString("info"); - System.out.println(type); - System.out.println(config); - DomainPinger dp = pingers.get(type); - if (dp != null) { - result.setInt(1, rs.getInt("id")); - String resp = dp.ping(rs.getString("domain"), config); - result.setString(2, resp == DomainPinger.PING_STILL_PENDING ? "open" : resp == DomainPinger.PING_SUCCEDED ? "success" : "failed"); - result.setString(3, resp); - result.execute(); - } - } + searchNeededPings = DatabaseConnection.getInstance().prepare("SELECT pingconfig.*, domains.domain, domains.memid FROM pingconfig LEFT JOIN domainPinglog ON domainPinglog.configId=pingconfig.id INNER JOIN domains ON domains.id=pingconfig.domainid WHERE domainPinglog.configId IS NULL "); + enterPingResult = DatabaseConnection.getInstance().prepare("INSERT INTO domainPinglog SET configId=?, state=?, result=?, challenge=?"); + pingers.put("email", new EmailPinger()); + pingers.put("ssl", new SSLPinger()); + pingers.put("http", new HTTPFetch()); + pingers.put("dns", new DNSPinger()); } catch (SQLException e) { e.printStackTrace(); } + while (true) { + try { + execute(); + } catch (SQLException e) { + e.printStackTrace(); + } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void execute() throws SQLException { + + ResultSet rs = searchNeededPings.executeQuery(); + while (rs.next()) { + String type = rs.getString("type"); + String config = rs.getString("info"); + DomainPinger dp = pingers.get(type); + if (dp != null) { + String token = null; + if (dp instanceof EmailPinger) { + token = RandomToken.generateToken(16); + config = config + ":" + token; + } + enterPingResult.setInt(1, rs.getInt("id")); + String resp = dp.ping(Domain.getById(rs.getInt("domainid")), config, User.getById(rs.getInt("memid"))); + enterPingResult.setString(2, resp == DomainPinger.PING_STILL_PENDING ? "open" : resp == DomainPinger.PING_SUCCEDED ? "success" : "failed"); + enterPingResult.setString(3, resp); + enterPingResult.setString(4, token); + enterPingResult.execute(); + } + } } public static void main(String[] args) throws IOException { diff --git a/src/org/cacert/gigi/ping/SSLPinger.java b/src/org/cacert/gigi/ping/SSLPinger.java index ccb05b84..81c73937 100644 --- a/src/org/cacert/gigi/ping/SSLPinger.java +++ b/src/org/cacert/gigi/ping/SSLPinger.java @@ -20,6 +20,9 @@ import javax.net.ssl.SSLEngineResult.HandshakeStatus; import javax.net.ssl.SSLParameters; import javax.security.cert.X509Certificate; +import org.cacert.gigi.Domain; +import org.cacert.gigi.User; + public class SSLPinger extends DomainPinger { public static final String[] TYPES = new String[] { @@ -27,18 +30,18 @@ public class SSLPinger extends DomainPinger { }; @Override - public String ping(String domain, String configuration) { + public String ping(Domain domain, String configuration, User u) { try { SocketChannel sch = SocketChannel.open(); String[] parts = configuration.split(":", 2); - sch.connect(new InetSocketAddress(domain, Integer.parseInt(parts[0]))); + sch.connect(new InetSocketAddress(domain.getSuffix(), Integer.parseInt(parts[0]))); if (parts.length == 2) { switch (parts[1]) { 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,7 +52,7 @@ public class SSLPinger extends DomainPinger { } } - return test(sch, domain); + return test(sch, domain.getSuffix()); } catch (IOException e) { return "Connecton failed"; } -- 2.39.2