From: Felix Dörre Date: Sun, 24 Aug 2014 16:41:25 +0000 (+0200) Subject: ADD: output pinglog, test DNS and email ping. X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=7d12c09641a69f141b92d9914d0915d62a436a2d ADD: output pinglog, test DNS and email ping. --- diff --git a/config/test.properties.template b/config/test.properties.template index a94f0b53..97ce26b4 100644 --- a/config/test.properties.template +++ b/config/test.properties.template @@ -20,3 +20,8 @@ sql.driver=com.mysql.jdbc.Driver sql.url=jdbc:mysql://localhost:3306/cacert sql.user=cacert sql.password= + + +domain.dnsmanage=http://you-installation-of-the/index.php +domain.dnstest=the.dns.zone +domain.dnsns=the.authorativ.ns.for.domain.dnstest diff --git a/doc/jenkinsJob/ci-tests-setup.txt b/doc/jenkinsJob/ci-tests-setup.txt new file mode 100644 index 00000000..2b75bd03 --- /dev/null +++ b/doc/jenkinsJob/ci-tests-setup.txt @@ -0,0 +1,14 @@ +-you need 4 domains resolving to the ci server (or localhost) +preferably +static.DOMAIN, secure.DOMAIN, www.DOMAIN and api.DOMAIN. +enter them in the jenkins job to write them to "keys/config" and "config/test.properties" + +-you need credentials to an acessabible mysql database. +make jenkins write them to "config/test.properties" + +-you need a dynamically managable dns zone. +Write the zone name to "domain.dnstest" in "test.properties" +and a manage script (see dyn-txt.php). Put the url with password in "domain.dnsmanage" + +Setup with bind9: +dnssec-keygen -a HMAC-SHA512 -b 512 -n HOST example.org. diff --git a/doc/jenkinsJob/dyn-txt.php b/doc/jenkinsJob/dyn-txt.php new file mode 100644 index 00000000..c7c73e4c --- /dev/null +++ b/doc/jenkinsJob/dyn-txt.php @@ -0,0 +1,27 @@ +"){ + die (); +} +$t1 = $_GET['t1']; +$t2 = $_GET['t2']; +if(!preg_match("/[a-zA-Z0-9]+/", $t1) || !preg_match("/[a-zA-Z0-9]+/", $t2)){ + die("Error"); +} + +$call = << TXT +update add cacert-{$t1}. 60 TXT {$t2} +send +quit + +EOF; +echo $call; + +$nsupdate = popen("/usr/bin/nsupdate -k .key", 'w'); +fwrite($nsupdate, $call); +$retval = pclose($nsupdate); // nsupdate doesn't return anything useful when called this way + +?> diff --git a/src/org/cacert/gigi/Domain.java b/src/org/cacert/gigi/Domain.java index bcc66beb..21fe668e 100644 --- a/src/org/cacert/gigi/Domain.java +++ b/src/org/cacert/gigi/Domain.java @@ -3,7 +3,6 @@ package org.cacert.gigi; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; - import org.cacert.gigi.database.DatabaseConnection; public class Domain { @@ -138,4 +137,24 @@ public class Domain { } return false; } + + public String[][] getPings() throws GigiApiException { + try { + PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT state, type, info, result FROM domainPinglog INNER JOIN pingconfig ON pingconfig.id=domainPinglog.configid WHERE pingconfig.domainid=? ORDER BY `when` DESC;"); + ps.setInt(1, id); + ResultSet rs = ps.executeQuery(); + rs.last(); + String[][] contents = new String[rs.getRow()][]; + rs.beforeFirst(); + for (int i = 0; i < contents.length && rs.next(); i++) { + contents[i] = new String[] { + rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4) + }; + } + return contents; + } catch (SQLException e) { + throw new GigiApiException(e); + } + + } } diff --git a/src/org/cacert/gigi/Gigi.java b/src/org/cacert/gigi/Gigi.java index 1e7ee0f9..f013468e 100644 --- a/src/org/cacert/gigi/Gigi.java +++ b/src/org/cacert/gigi/Gigi.java @@ -88,7 +88,7 @@ public class Gigi extends HttpServlet { putPage(RegisterPage.PATH, new RegisterPage(), "Join CAcert.org"); putPage(CertificateAdd.PATH, new CertificateAdd(), "Certificates"); putPage(MailOverview.DEFAULT_PATH, new MailOverview("My email addresses"), "Certificates"); - putPage(DomainOverview.PATH, new DomainOverview("Domains"), "Certificates"); + putPage(DomainOverview.PATH + "*", new DomainOverview("Domains"), "Certificates"); putPage(MyPoints.PATH, new MyPoints("My Points"), "CAcert Web of Trust"); putPage("/wot/rules", new StaticPage("CAcert Web of Trust Rules", AssurePage.class.getResourceAsStream("Rules.templ")), "CAcert Web of Trust"); baseTemplate = new Template(Gigi.class.getResource("Gigi.templ")); diff --git a/src/org/cacert/gigi/pages/account/DomainAddForm.templ b/src/org/cacert/gigi/pages/account/DomainAddForm.templ index 1f83ea13..2da1b0e3 100644 --- a/src/org/cacert/gigi/pages/account/DomainAddForm.templ +++ b/src/org/cacert/gigi/pages/account/DomainAddForm.templ @@ -35,7 +35,7 @@ Please insert the following DNS TXT entry into the SOA-file of your domain:
-        cacert-	IN	TXT	
+        cacert- IN TXT 
         
diff --git a/src/org/cacert/gigi/pages/account/DomainDetails.templ b/src/org/cacert/gigi/pages/account/DomainDetails.templ new file mode 100644 index 00000000..650f87ad --- /dev/null +++ b/src/org/cacert/gigi/pages/account/DomainDetails.templ @@ -0,0 +1,15 @@ +

''

+ + + + + + + + + + + + + +
\ No newline at end of file diff --git a/src/org/cacert/gigi/pages/account/DomainManagementForm.java b/src/org/cacert/gigi/pages/account/DomainManagementForm.java index 5df57114..b6d957b0 100644 --- a/src/org/cacert/gigi/pages/account/DomainManagementForm.java +++ b/src/org/cacert/gigi/pages/account/DomainManagementForm.java @@ -13,6 +13,7 @@ import org.cacert.gigi.output.Form; import org.cacert.gigi.output.template.IterableDataset; import org.cacert.gigi.output.template.Template; import org.cacert.gigi.pages.Page; +import org.cacert.gigi.util.ServerConstants; public class DomainManagementForm extends Form { @@ -60,6 +61,7 @@ public class DomainManagementForm extends Form { } Domain domain = doms[point]; vars.put("id", domain.getId()); + vars.put("domainhref", "https://" + ServerConstants.getWwwHostNamePort() + DomainOverview.PATH + domain.getId()); vars.put("domain", domain.getSuffix()); vars.put("status", l.getTranslation(domain.isVerified() ? "verified" : "not verified")); point++; @@ -69,5 +71,4 @@ public class DomainManagementForm extends Form { vars.put("domains", dts); t.output(out, l, vars); } - } diff --git a/src/org/cacert/gigi/pages/account/DomainManagementForm.templ b/src/org/cacert/gigi/pages/account/DomainManagementForm.templ index 58b8fe5f..0bdc9d37 100644 --- a/src/org/cacert/gigi/pages/account/DomainManagementForm.templ +++ b/src/org/cacert/gigi/pages/account/DomainManagementForm.templ @@ -12,7 +12,7 @@ - + diff --git a/src/org/cacert/gigi/pages/account/DomainOverview.java b/src/org/cacert/gigi/pages/account/DomainOverview.java index 4b298f87..d8868f93 100644 --- a/src/org/cacert/gigi/pages/account/DomainOverview.java +++ b/src/org/cacert/gigi/pages/account/DomainOverview.java @@ -2,17 +2,25 @@ package org.cacert.gigi.pages.account; import java.io.IOException; import java.util.HashMap; +import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.cacert.gigi.Domain; +import org.cacert.gigi.GigiApiException; import org.cacert.gigi.User; +import org.cacert.gigi.localisation.Language; import org.cacert.gigi.output.Form; +import org.cacert.gigi.output.template.IterableDataset; +import org.cacert.gigi.output.template.Template; import org.cacert.gigi.pages.Page; public class DomainOverview extends Page { - public static final String PATH = "/account/domains"; + public static final String PATH = "/account/domains/"; + + private Template domainDetails = new Template(DomainOverview.class.getResource("DomainDetails.templ")); public DomainOverview(String title) { super(title); @@ -21,6 +29,48 @@ public class DomainOverview extends Page { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { User u = getUser(req); + String pi = req.getPathInfo(); + if (pi.length() - PATH.length() > 0) { + int i = Integer.parseInt(pi.substring(PATH.length())); + Domain d = Domain.getById(i); + if (u.getId() != d.getOwner().getId()) { + System.out.println(u.getId()); + System.out.println(d.getOwner().getId()); + return; + } + try { + final String[][] pings = d.getPings(); + HashMap vars = new HashMap<>(); + vars.put("domainname", d.getSuffix()); + vars.put("pings", new IterableDataset() { + + int counter = 0; + + @Override + public boolean next(Language l, Map vars) { + if (counter >= pings.length) { + return false; + } + vars.put("state", pings[counter][0]); + vars.put("type", pings[counter][1]); + vars.put("config", pings[counter][2]); + String ping3 = pings[counter][3]; + if (ping3 == null) { + vars.put("result", ""); + } else { + vars.put("result", ping3); + } + counter++; + return true; + } + }); + domainDetails.output(resp.getWriter(), getLanguage(req), vars); + return; + } catch (GigiApiException e) { + e.format(resp.getWriter(), getLanguage(req)); + } + + } DomainManagementForm domMan = new DomainManagementForm(req, u); DomainAddForm domAdd = new DomainAddForm(req, u); HashMap vars = new HashMap<>(); diff --git a/src/org/cacert/gigi/ping/DNSPinger.java b/src/org/cacert/gigi/ping/DNSPinger.java index 35e17148..a611a239 100644 --- a/src/org/cacert/gigi/ping/DNSPinger.java +++ b/src/org/cacert/gigi/ping/DNSPinger.java @@ -3,6 +3,7 @@ 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; @@ -31,8 +32,9 @@ public class DNSPinger extends DomainPinger { nameservers: for (String NS : nameservers) { String[] call = new String[] { - "dig", "@" + NS, "+short", "TXT", "cacert-" + tokenParts[0] + "." + domain + "dig", "@" + NS, "+short", "TXT", "cacert-" + tokenParts[0] + "." + domain.getSuffix() }; + System.out.println(Arrays.toString(call)); p = Runtime.getRuntime().exec(call); br = new BufferedReader(new InputStreamReader(p.getInputStream())); String token = null; diff --git a/tests/org/cacert/gigi/ping/TestDNS.java b/tests/org/cacert/gigi/ping/TestDNS.java new file mode 100644 index 00000000..0a284911 --- /dev/null +++ b/tests/org/cacert/gigi/ping/TestDNS.java @@ -0,0 +1,112 @@ +package org.cacert.gigi.ping; + +import static org.junit.Assert.*; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLEncoder; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.cacert.gigi.database.DatabaseConnection; +import org.cacert.gigi.pages.account.DomainOverview; +import org.cacert.gigi.testUtils.IOUtils; +import org.cacert.gigi.testUtils.ManagedTest; +import org.cacert.gigi.testUtils.TestEmailReciever.TestMail; +import org.cacert.gigi.util.RandomToken; +import org.junit.Test; + +public class TestDNS extends ManagedTest { + + @Test + public void testDNSSanity() throws IOException { + + String token = RandomToken.generateToken(16); + String value = RandomToken.generateToken(16); + + Process p = updateDNS(token, value); + String reRead = new String(IOUtils.readURL(p.getInputStream())); + reRead = reRead.trim(); + reRead = reRead.substring(1, reRead.length() - 1); + assertEquals(value, reRead); + + } + + @Test + public void testEmailAndDNS() throws IOException, InterruptedException, SQLException { + String email = createUniqueName() + "@example.org"; + int uid = createVerifiedUser("a", "b", email, TEST_PASSWORD); + String cookie = login(email, TEST_PASSWORD); + + String test = getTestProps().getProperty("domain.dnstest"); + URL u = new URL("https://" + getServerName() + DomainOverview.PATH); + URLConnection openConnection = u.openConnection(); + openConnection.setRequestProperty("Cookie", cookie); + String content1 = IOUtils.readURL(openConnection); + String csrf = getCSRF(1, content1); + + Pattern p = Pattern.compile("cacert-([A-Za-z0-9]+) IN TXT ([A-Za-z0-9]+)"); + Matcher m = p.matcher(content1); + m.find(); + updateDNS(m.group(1), m.group(2)); + + String content = "newdomain=" + URLEncoder.encode(test, "UTF-8") + // + "&emailType=y&email=2&DNSType=y" + // + "&ssl-type-0=direct&ssl-port-0=" + // + "&ssl-type-1=direct&ssl-port-1=" + // + "&ssl-type-2=direct&ssl-port-2=" + // + "&ssl-type-3=direct&ssl-port-3=" + // + "&adddomain&csrf=" + csrf; + openConnection = u.openConnection(); + openConnection.setRequestProperty("Cookie", cookie); + openConnection.setDoOutput(true); + openConnection.getOutputStream().write(content.getBytes()); + openConnection.getHeaderField("Location"); + + String newcontent = IOUtils.readURL(cookie(u.openConnection(), cookie)); + Pattern dlink = Pattern.compile(DomainOverview.PATH + "([0-9]+)'>"); + Matcher m1 = dlink.matcher(newcontent); + m1.find(); + URL u2 = new URL(u.toString() + m1.group(1)); + + TestMail mail = getMailReciever().recieve(); + String link = mail.extractLink(); + new URL(link).openConnection().getHeaderField(""); + + PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT COUNT(*) FROM domainPinglog"); + while (true) { + ResultSet rs = ps.executeQuery(); + rs.next(); + if (rs.getInt(1) >= 2) { + break; + } + Thread.sleep(200); + } + + newcontent = IOUtils.readURL(cookie(u2.openConnection(), cookie)); + Pattern pat = Pattern.compile("dns\\s*success"); + assertTrue(newcontent, pat.matcher(newcontent).find()); + pat = Pattern.compile("email\\s*success"); + assertTrue(newcontent, pat.matcher(newcontent).find()); + } + + private Process updateDNS(String token, String value) throws IOException, MalformedURLException { + String test = getTestProps().getProperty("domain.dnstest"); + String targetDomain = "cacert-" + token + "." + test; + String manage = getTestProps().getProperty("domain.dnsmanage"); + String url = manage + "t1=" + token + "&t2=" + value; + assertEquals(200, ((HttpURLConnection) new URL(url).openConnection()).getResponseCode()); + + Process p = Runtime.getRuntime().exec(new String[] { + "dig", "@" + getTestProps().getProperty("domain.testns"), "+short", "TXT", targetDomain + }); + return p; + } + +} diff --git a/tests/org/cacert/gigi/testUtils/ManagedTest.java b/tests/org/cacert/gigi/testUtils/ManagedTest.java index a9dd4201..b0f3670a 100644 --- a/tests/org/cacert/gigi/testUtils/ManagedTest.java +++ b/tests/org/cacert/gigi/testUtils/ManagedTest.java @@ -78,6 +78,11 @@ public class ManagedTest { } static Properties testProps = new Properties(); + + public static Properties getTestProps() { + return testProps; + } + static { InitTruststore.run(); HttpURLConnection.setFollowRedirects(false); @@ -395,6 +400,10 @@ public class ManagedTest { public static String getCSRF(URLConnection u, int formIndex) throws IOException { String content = IOUtils.readURL(u); + return getCSRF(formIndex, content); + } + + public static String getCSRF(int formIndex, String content) throws Error { Pattern p = Pattern.compile(""); Matcher m = p.matcher(content); for (int i = 0; i < formIndex + 1; i++) { @@ -459,4 +468,9 @@ public class ManagedTest { return adrr; } + public static URLConnection cookie(URLConnection openConnection, String cookie) { + openConnection.setRequestProperty("Cookie", cookie); + return openConnection; + } + }