]> WPIA git - gigi.git/blob - tests/org/cacert/gigi/pages/account/TestCertificateAdd.java
Add tests for certificate data pre-fillin:
[gigi.git] / tests / org / cacert / gigi / pages / account / TestCertificateAdd.java
1 package org.cacert.gigi.pages.account;
2
3 import static org.junit.Assert.*;
4
5 import java.io.IOException;
6 import java.net.HttpURLConnection;
7 import java.net.URL;
8 import java.net.URLEncoder;
9 import java.security.GeneralSecurityException;
10 import java.security.KeyPair;
11 import java.security.Signature;
12 import java.util.Arrays;
13 import java.util.Base64;
14 import java.util.Vector;
15 import java.util.regex.Matcher;
16 import java.util.regex.Pattern;
17
18 import org.cacert.gigi.Digest;
19 import org.cacert.gigi.User;
20 import org.cacert.gigi.crypto.SPKAC;
21 import org.cacert.gigi.testUtils.IOUtils;
22 import org.cacert.gigi.testUtils.ManagedTest;
23 import org.junit.Test;
24
25 import sun.security.pkcs.PKCS9Attribute;
26 import sun.security.pkcs10.PKCS10Attribute;
27 import sun.security.pkcs10.PKCS10Attributes;
28 import sun.security.util.ObjectIdentifier;
29 import sun.security.x509.CertificateExtensions;
30 import sun.security.x509.DNSName;
31 import sun.security.x509.ExtendedKeyUsageExtension;
32 import sun.security.x509.GeneralName;
33 import sun.security.x509.GeneralNameInterface;
34 import sun.security.x509.GeneralNames;
35 import sun.security.x509.RFC822Name;
36 import sun.security.x509.SubjectAlternativeNameExtension;
37 import sun.security.x509.X509Key;
38
39 public class TestCertificateAdd extends ManagedTest {
40
41     KeyPair kp = generateKeypair();
42
43     User u = User.getById(createVerifiedUser("testuser", "testname", uniq + "@testdom.com", TEST_PASSWORD));
44
45     String session = login(uniq + "@testdom.com", TEST_PASSWORD);
46
47     public TestCertificateAdd() throws GeneralSecurityException, IOException {
48         TestDomain.addDomain(session, uniq + ".tld");
49
50     }
51
52     @Test
53     public void testSimpleServer() throws IOException, GeneralSecurityException {
54         PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] {
55             CertificateIssueForm.OID_KEY_USAGE_SSL_SERVER
56         }, new DNSName(uniq + ".tld"));
57
58         String pem = generatePEMCSR(kp, "CN=a." + uniq + ".tld", atts);
59
60         String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8"));
61         assertArrayEquals(new String[] {
62                 "server", "CAcert WoT User", "dns:a." + uniq + ".tld\ndns:" + uniq + ".tld\n", Digest.SHA256.toString()
63         }, res);
64     }
65
66     @Test
67     public void testSimpleMail() throws IOException, GeneralSecurityException {
68         PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] {
69             CertificateIssueForm.OID_KEY_USAGE_EMAIL_PROTECTION
70         }, new DNSName("a." + uniq + ".tld"), new DNSName("b." + uniq + ".tld"), new RFC822Name(uniq + "@testdom.com"));
71
72         String pem = generatePEMCSR(kp, "CN=testuser testname", atts, "SHA384WithRSA");
73
74         String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8"));
75         assertArrayEquals(new String[] {
76                 "mail", "testuser testname", "dns:a." + uniq + ".tld\ndns:b." + uniq + ".tld\nemail:" + uniq + "@testdom.com\n", Digest.SHA384.toString()
77         }, res);
78     }
79
80     @Test
81     public void testSimpleClient() throws IOException, GeneralSecurityException {
82         PKCS10Attributes atts = buildAtts(new ObjectIdentifier[] {
83             CertificateIssueForm.OID_KEY_USAGE_SSL_CLIENT
84         }, new RFC822Name(uniq + "@testdom.com"));
85
86         String pem = generatePEMCSR(kp, "CN=testuser testname,email=" + uniq + "@testdom.com", atts, "SHA512WithRSA");
87
88         String[] res = fillOutForm("CSR=" + URLEncoder.encode(pem, "UTF-8"));
89         assertArrayEquals(new String[] {
90                 "client", "testuser testname", "email:" + uniq + "@testdom.com\n", Digest.SHA512.toString()
91         }, res);
92     }
93
94     @Test
95     public void testSPKAC() throws GeneralSecurityException, IOException {
96         testSPKAC(false);
97         testSPKAC(true);
98     }
99
100     protected void testSPKAC(boolean correctChallange) throws GeneralSecurityException, IOException {
101         HttpURLConnection uc = (HttpURLConnection) ncert.openConnection();
102         uc.setRequestProperty("Cookie", session);
103         String s = IOUtils.readURL(uc);
104
105         String csrf = extractPattern(s, Pattern.compile("<input [^>]*name='csrf' [^>]*value='([^']*)'>"));
106         String challenge = extractPattern(s, Pattern.compile("<keygen [^>]*name=\"SPKAC\" [^>]*challenge=\"([^\"]*)\"/>"));
107
108         SPKAC spk = new SPKAC((X509Key) kp.getPublic(), challenge + (correctChallange ? "" : "b"));
109         Signature sign = Signature.getInstance("SHA512WithRSA");
110         sign.initSign(kp.getPrivate());
111         try {
112             String[] res = fillOutForm(csrf, "SPKAC=" + URLEncoder.encode(Base64.getEncoder().encodeToString(spk.getEncoded(sign)), "UTF-8"));
113             if ( !correctChallange) {
114                 fail("Should not succeed with wrong challange.");
115             }
116             assertArrayEquals(new String[] {
117                     "client", CertificateIssueForm.DEFAULT_CN, "", Digest.SHA512.toString()
118             }, res);
119         } catch (Error e) {
120             assertTrue(e.getMessage().startsWith("<div>Challenge mismatch"));
121         }
122     }
123
124     private PKCS10Attributes buildAtts(ObjectIdentifier[] ekuOIDs, GeneralNameInterface... SANs) throws IOException {
125         CertificateExtensions attributeValue = new CertificateExtensions();
126         GeneralNames names = new GeneralNames();
127
128         for (GeneralNameInterface name : SANs) {
129             names.add(new GeneralName(name));
130         }
131         attributeValue.set("SANs", new SubjectAlternativeNameExtension(names));
132         PKCS10Attributes atts = new PKCS10Attributes(new PKCS10Attribute[] {
133             new PKCS10Attribute(PKCS9Attribute.EXTENSION_REQUEST_OID, attributeValue)
134         });
135         ExtendedKeyUsageExtension eku = new ExtendedKeyUsageExtension(//
136                 new Vector<>(Arrays.<ObjectIdentifier>asList(ekuOIDs)));
137         attributeValue.set("eku", eku);
138         return atts;
139     }
140
141     private final URL ncert = new URL("https://" + getServerName() + CertificateAdd.PATH);
142
143     private String[] fillOutForm(String pem) throws IOException {
144         HttpURLConnection uc = (HttpURLConnection) ncert.openConnection();
145         uc.setRequestProperty("Cookie", session);
146         String csrf = getCSRF(uc);
147         return fillOutForm(csrf, pem);
148
149     }
150
151     private String[] fillOutForm(String csrf, String pem) throws IOException {
152
153         HttpURLConnection uc = (HttpURLConnection) ncert.openConnection();
154         uc.setRequestProperty("Cookie", session);
155         uc.setDoOutput(true);
156         uc.getOutputStream().write(("csrf=" + URLEncoder.encode(csrf, "UTF-8") + "&" + pem).getBytes());
157         uc.getOutputStream().flush();
158
159         String result = IOUtils.readURL(uc);
160         if (result.contains("<div class='formError'>")) {
161             String s = fetchStartErrorMessage(result);
162             throw new Error(s);
163         }
164
165         String profileKey = extractPattern(result, Pattern.compile("<option value=\"([^\"]*)\" selected>"));
166         String resultingCN = extractPattern(result, Pattern.compile("<input [^>]*name='CN' [^>]*value='([^']*)'>"));
167         String txt = extractPattern(result, Pattern.compile("<textarea [^>]*name='SANs' [^>]*>([^<]*)</textarea>"));
168         String md = extractPattern(result, Pattern.compile("<input type=\"radio\" [^>]*name=\"hash_alg\" value=\"([^\"]*)\" checked='checked'/>"));
169         return new String[] {
170                 profileKey, resultingCN, txt, md
171         };
172     }
173
174     private String extractPattern(String result, Pattern p) {
175         Matcher m = p.matcher(result);
176         assertTrue(m.find());
177         String resultingCN = m.group(1);
178         return resultingCN;
179     }
180 }