X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=tests%2Forg%2Fcacert%2Fgigi%2Fpages%2Faccount%2FTestCertificateAdd.java;h=38130bc455656ba54868a0e6d32afcec2fb9d25e;hp=9888b6a057f0c0517295d9022c3cb268eaa92aa3;hb=72328c64659f06441c35dbd4f8cdcfd41376e7a3;hpb=f9674a8330dcdbf4384a3ef60ac6917d41b327c5 diff --git a/tests/org/cacert/gigi/pages/account/TestCertificateAdd.java b/tests/org/cacert/gigi/pages/account/TestCertificateAdd.java index 9888b6a0..38130bc4 100644 --- a/tests/org/cacert/gigi/pages/account/TestCertificateAdd.java +++ b/tests/org/cacert/gigi/pages/account/TestCertificateAdd.java @@ -1,27 +1,44 @@ package org.cacert.gigi.pages.account; +import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; +import java.net.MalformedURLException; import java.net.URL; +import java.net.URLConnection; import java.net.URLEncoder; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.Signature; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Base64; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.cacert.gigi.Digest; -import org.cacert.gigi.User; import org.cacert.gigi.crypto.SPKAC; +import org.cacert.gigi.dbObjects.Digest; +import org.cacert.gigi.pages.account.certs.CertificateAdd; +import org.cacert.gigi.pages.account.certs.CertificateRequest; +import org.cacert.gigi.testUtils.ClientTest; import org.cacert.gigi.testUtils.IOUtils; -import org.cacert.gigi.testUtils.ManagedTest; +import org.cacert.gigi.util.PEM; import org.junit.Test; +import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS9Attribute; import sun.security.pkcs10.PKCS10Attribute; import sun.security.pkcs10.PKCS10Attributes; @@ -36,23 +53,21 @@ import sun.security.x509.RFC822Name; import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.X509Key; -public class TestCertificateAdd extends ManagedTest { +public class TestCertificateAdd extends ClientTest { KeyPair kp = generateKeypair(); - User u = User.getById(createVerifiedUser("testuser", "testname", uniq + "@testdom.com", TEST_PASSWORD)); - - String session = login(uniq + "@testdom.com", TEST_PASSWORD); + String csrf; public TestCertificateAdd() throws GeneralSecurityException, IOException { - TestDomain.addDomain(session, uniq + ".tld"); + TestDomain.addDomain(cookie, uniq + ".tld"); } @Test public void testSimpleServer() throws IOException, GeneralSecurityException { PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { - CertificateIssueForm.OID_KEY_USAGE_SSL_SERVER + CertificateRequest.OID_KEY_USAGE_SSL_SERVER }, new DNSName(uniq + ".tld")); String pem = generatePEMCSR(kp, "CN=a." + uniq + ".tld", atts); @@ -66,28 +81,28 @@ public class TestCertificateAdd extends ManagedTest { @Test public void testSimpleMail() throws IOException, GeneralSecurityException { PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { - CertificateIssueForm.OID_KEY_USAGE_EMAIL_PROTECTION - }, new DNSName("a." + uniq + ".tld"), new DNSName("b." + uniq + ".tld"), new RFC822Name(uniq + "@testdom.com")); + CertificateRequest.OID_KEY_USAGE_EMAIL_PROTECTION + }, new DNSName("a." + uniq + ".tld"), new DNSName("b." + uniq + ".tld"), new RFC822Name(email)); - String pem = generatePEMCSR(kp, "CN=testuser testname", atts, "SHA384WithRSA"); + String pem = generatePEMCSR(kp, "CN=a b", atts, "SHA384WithRSA"); String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); assertArrayEquals(new String[] { - "mail", "testuser testname", "dns:a." + uniq + ".tld\ndns:b." + uniq + ".tld\nemail:" + uniq + "@testdom.com\n", Digest.SHA384.toString() + "mail", "a b", "email:" + email + "\ndns:a." + uniq + ".tld\ndns:b." + uniq + ".tld\n", Digest.SHA384.toString() }, res); } @Test public void testSimpleClient() throws IOException, GeneralSecurityException { PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { - CertificateIssueForm.OID_KEY_USAGE_SSL_CLIENT - }, new RFC822Name(uniq + "@testdom.com")); + CertificateRequest.OID_KEY_USAGE_SSL_CLIENT + }, new RFC822Name(email)); - String pem = generatePEMCSR(kp, "CN=testuser testname,email=" + uniq + "@testdom.com", atts, "SHA512WithRSA"); + String pem = generatePEMCSR(kp, "CN=a b,email=" + email, atts, "SHA512WithRSA"); String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); assertArrayEquals(new String[] { - "client", "testuser testname", "email:" + uniq + "@testdom.com\n", Digest.SHA512.toString() + "client", "a b", "email:" + email + "\n", Digest.SHA512.toString() }, res); } @@ -97,28 +112,184 @@ public class TestCertificateAdd extends ManagedTest { testSPKAC(true); } - protected void testSPKAC(boolean correctChallange) throws GeneralSecurityException, IOException { + @Test + public void testIssue() throws IOException, GeneralSecurityException { + PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { + CertificateRequest.OID_KEY_USAGE_SSL_CLIENT + }, new RFC822Name(email)); + + String pem = generatePEMCSR(kp, "CN=a b,email=" + email, atts, "SHA512WithRSA"); + + String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); + assertArrayEquals(new String[] { + "client", "a b", "email:" + email + "\n", Digest.SHA512.toString() + }, res); + + HttpURLConnection huc = (HttpURLConnection) ncert.openConnection(); + huc.setRequestProperty("Cookie", cookie); + huc.setDoOutput(true); + OutputStream out = huc.getOutputStream(); + out.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8")).getBytes("UTF-8")); + out.write(("&CN=CAcert+WoT+User&profile=client&SANs=" + URLEncoder.encode("email:" + email + "\n", "UTF-8")).getBytes("UTF-8")); + out.write(("&hash_alg=SHA512&CCA=y").getBytes("UTF-8")); + URLConnection uc = authenticate(new URL(huc.getHeaderField("Location") + ".crt")); + String crt = IOUtils.readURL(new InputStreamReader(uc.getInputStream(), "UTF-8")); + + uc = authenticate(new URL(huc.getHeaderField("Location") + ".cer")); + byte[] cer = IOUtils.readURL(uc.getInputStream()); + assertArrayEquals(cer, PEM.decode("CERTIFICATE", crt)); + + uc = authenticate(new URL(huc.getHeaderField("Location") + ".cer?install&chain")); + byte[] pkcs7 = IOUtils.readURL(uc.getInputStream()); + PKCS7 p7 = new PKCS7(pkcs7); + byte[] sub = verifyChain(p7.getCertificates()); + assertArrayEquals(cer, sub); + assertEquals("application/x-x509-user-cert", uc.getHeaderField("Content-type")); + + uc = authenticate(new URL(huc.getHeaderField("Location"))); + String gui = IOUtils.readURL(uc); + assertThat(gui, containsString("clientAuth")); + assertThat(gui, containsString("CN=CAcert WoT User")); + assertThat(gui, containsString("SHA512withRSA")); + assertThat(gui, containsString("RFC822Name: " + email)); + + } + + private byte[] verifyChain(X509Certificate[] x509Certificates) throws GeneralSecurityException { + X509Certificate current = null; + nextCert: + while (true) { + for (int i = 0; i < x509Certificates.length; i++) { + X509Certificate cert = x509Certificates[i]; + if (current == null) { + if (cert.getSubjectX500Principal().equals(cert.getIssuerX500Principal())) { + current = cert; + continue nextCert; + } + } else { + if (cert.getSubjectX500Principal().equals(cert.getIssuerX500Principal())) { + continue; + } + if (current.getSubjectX500Principal().equals(cert.getIssuerX500Principal())) { + Signature s = Signature.getInstance(cert.getSigAlgName()); + s.initVerify(current.getPublicKey()); + s.update(cert.getTBSCertificate()); + assertTrue(s.verify(cert.getSignature())); + current = cert; + continue nextCert; + } + } + } + return current.getEncoded(); + } + } + + @Test + public void testValidityPeriodCalendar() throws IOException, GeneralSecurityException { + testCertificateValidityRelative(Calendar.YEAR, 2, "2y", true); + testCertificateValidityRelative(Calendar.YEAR, 1, "1y", true); + testCertificateValidityRelative(Calendar.MONTH, 3, "3m", true); + testCertificateValidityRelative(Calendar.MONTH, 7, "7m", true); + testCertificateValidityRelative(Calendar.MONTH, 13, "13m", true); + + testCertificateValidityRelative(Calendar.MONTH, 13, "-1m", false); + } + + @Test + public void testValidityPeriodWhishStart() throws IOException, GeneralSecurityException { + long now = System.currentTimeMillis(); + final long MS_PER_DAY = 24 * 60 * 60 * 1000; + now -= now % MS_PER_DAY; + now += MS_PER_DAY; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); + + Date start = new Date(now); + Date end = new Date(now + MS_PER_DAY * 10); + X509Certificate res = createCertWithValidity("&validFrom=" + sdf.format(start) + "&validity=" + sdf.format(end)); + assertNotNull(res); + assertEquals(start, res.getNotBefore()); + assertEquals(end, res.getNotAfter()); + } + + private void testCertificateValidityRelative(int field, int amount, String length, boolean shouldsucceed) throws IOException, GeneralSecurityException, UnsupportedEncodingException, MalformedURLException, CertificateException { + X509Certificate parsed = createCertWithValidity("&validFrom=now&validity=" + length); + if (parsed == null) { + assertTrue( !shouldsucceed); + return; + } else { + assertTrue(shouldsucceed); + } + + long now = System.currentTimeMillis(); + Date start = parsed.getNotBefore(); + Date end = parsed.getNotAfter(); + Calendar c = Calendar.getInstance(); + c.setTimeZone(TimeZone.getTimeZone("UTC")); + c.setTime(start); + c.add(field, amount); + assertTrue(Math.abs(start.getTime() - now) < 10000); + assertEquals(c.getTime(), end); + } + + private X509Certificate createCertWithValidity(String validity) throws IOException, GeneralSecurityException, UnsupportedEncodingException, MalformedURLException, CertificateException { + PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] { + CertificateRequest.OID_KEY_USAGE_SSL_CLIENT + }, new RFC822Name(email)); + + String pem = generatePEMCSR(kp, "CN=a b", atts, "SHA512WithRSA"); + fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8")); + + HttpURLConnection huc = (HttpURLConnection) ncert.openConnection(); + huc.setRequestProperty("Cookie", cookie); + huc.setDoOutput(true); + OutputStream out = huc.getOutputStream(); + out.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8")).getBytes("UTF-8")); + out.write(("&profile=client&CN=" + CertificateRequest.DEFAULT_CN + "&SANs=" + URLEncoder.encode("email:" + email + "\n", "UTF-8")).getBytes("UTF-8")); + out.write(("&hash_alg=SHA512&CCA=y&").getBytes("UTF-8")); + out.write(validity.getBytes("UTF-8")); + + String certurl = huc.getHeaderField("Location"); + if (certurl == null) { + return null; + } + URLConnection uc = authenticate(new URL(certurl + ".crt")); + String crt = IOUtils.readURL(new InputStreamReader(uc.getInputStream(), "UTF-8")); + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate parsed = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(crt.getBytes("UTF-8"))); + return parsed; + } + + private URLConnection authenticate(URL url) throws IOException { + URLConnection uc = url.openConnection(); + uc.setRequestProperty("Cookie", cookie); + return uc; + } + + protected String testSPKAC(boolean correctChallange) throws GeneralSecurityException, IOException { HttpURLConnection uc = (HttpURLConnection) ncert.openConnection(); - uc.setRequestProperty("Cookie", session); + uc.setRequestProperty("Cookie", cookie); String s = IOUtils.readURL(uc); - String csrf = extractPattern(s, Pattern.compile("]*name='csrf' [^>]*value='([^']*)'>")); + csrf = extractPattern(s, Pattern.compile("]*name='csrf' [^>]*value='([^']*)'>")); String challenge = extractPattern(s, Pattern.compile("]*name=\"SPKAC\" [^>]*challenge=\"([^\"]*)\"/>")); SPKAC spk = new SPKAC((X509Key) kp.getPublic(), challenge + (correctChallange ? "" : "b")); Signature sign = Signature.getInstance("SHA512WithRSA"); sign.initSign(kp.getPrivate()); try { - String[] res = fillOutForm(csrf, "SPKAC=" + URLEncoder.encode(Base64.getEncoder().encodeToString(spk.getEncoded(sign)), "UTF-8")); + String[] res = fillOutFormDirect("SPKAC=" + URLEncoder.encode(Base64.getEncoder().encodeToString(spk.getEncoded(sign)), "UTF-8")); if ( !correctChallange) { fail("Should not succeed with wrong challange."); } assertArrayEquals(new String[] { - "client", CertificateIssueForm.DEFAULT_CN, "", Digest.SHA512.toString() + "client", CertificateRequest.DEFAULT_CN, "", Digest.SHA512.toString() }, res); } catch (Error e) { assertTrue(e.getMessage().startsWith("
Challenge mismatch")); } + return csrf; } private PKCS10Attributes buildAtts(ObjectIdentifier[] ekuOIDs, GeneralNameInterface... SANs) throws IOException { @@ -142,20 +313,24 @@ public class TestCertificateAdd extends ManagedTest { private String[] fillOutForm(String pem) throws IOException { HttpURLConnection uc = (HttpURLConnection) ncert.openConnection(); - uc.setRequestProperty("Cookie", session); - String csrf = getCSRF(uc); - return fillOutForm(csrf, pem); + uc.setRequestProperty("Cookie", cookie); + csrf = getCSRF(uc); + return fillOutFormDirect(pem); } - private String[] fillOutForm(String csrf, String pem) throws IOException { + private String[] fillOutFormDirect(String pem) throws IOException { HttpURLConnection uc = (HttpURLConnection) ncert.openConnection(); - uc.setRequestProperty("Cookie", session); + uc.setRequestProperty("Cookie", cookie); uc.setDoOutput(true); - uc.getOutputStream().write(("csrf=" + URLEncoder.encode(csrf, "UTF-8") + "&" + pem).getBytes()); + uc.getOutputStream().write(("csrf=" + URLEncoder.encode(csrf, "UTF-8") + "&" + pem).getBytes("UTF-8")); uc.getOutputStream().flush(); + return extractFormData(uc); + } + + private String[] extractFormData(HttpURLConnection uc) throws IOException, Error { String result = IOUtils.readURL(uc); if (result.contains("
")) { String s = fetchStartErrorMessage(result); @@ -163,7 +338,7 @@ public class TestCertificateAdd extends ManagedTest { } String profileKey = extractPattern(result, Pattern.compile("