]> WPIA git - gigi.git/blob - tests/org/cacert/gigi/testUtils/ManagedTest.java
ADD: cretaeVerifiedEmail fo testcases
[gigi.git] / tests / org / cacert / gigi / testUtils / ManagedTest.java
1 package org.cacert.gigi.testUtils;
2
3 import static org.junit.Assert.*;
4
5 import java.io.BufferedReader;
6 import java.io.DataOutputStream;
7 import java.io.FileInputStream;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.io.OutputStream;
11 import java.io.UnsupportedEncodingException;
12 import java.net.HttpURLConnection;
13 import java.net.InetSocketAddress;
14 import java.net.MalformedURLException;
15 import java.net.Socket;
16 import java.net.URL;
17 import java.net.URLConnection;
18 import java.net.URLEncoder;
19 import java.nio.file.Files;
20 import java.nio.file.Paths;
21 import java.security.KeyManagementException;
22 import java.security.NoSuchAlgorithmException;
23 import java.security.Principal;
24 import java.security.PrivateKey;
25 import java.security.cert.X509Certificate;
26 import java.sql.PreparedStatement;
27 import java.sql.ResultSet;
28 import java.sql.SQLException;
29 import java.util.Properties;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32
33 import javax.net.ssl.HttpsURLConnection;
34 import javax.net.ssl.KeyManager;
35 import javax.net.ssl.SSLContext;
36 import javax.net.ssl.X509KeyManager;
37
38 import org.cacert.gigi.DevelLauncher;
39 import org.cacert.gigi.EmailAddress;
40 import org.cacert.gigi.GigiApiException;
41 import org.cacert.gigi.Language;
42 import org.cacert.gigi.User;
43 import org.cacert.gigi.database.DatabaseConnection;
44 import org.cacert.gigi.testUtils.TestEmailReciever.TestMail;
45 import org.cacert.gigi.util.DatabaseManager;
46 import org.cacert.gigi.util.ServerConstants;
47 import org.cacert.gigi.util.SimpleSigner;
48 import org.junit.After;
49 import org.junit.AfterClass;
50 import org.junit.BeforeClass;
51
52 public class ManagedTest {
53         /**
54          * Some password that fullfills the password criteria.
55          */
56         protected static final String TEST_PASSWORD = "xvXV12°§";
57
58         private final String registerService = "/register";
59
60         private static TestEmailReciever ter;
61         private static Process gigi;
62         private static String url = "localhost:4443";
63
64         public static String getServerName() {
65                 return url;
66         }
67
68         static Properties testProps = new Properties();
69         static {
70                 InitTruststore.run();
71                 HttpURLConnection.setFollowRedirects(false);
72         }
73
74         @BeforeClass
75         public static void connectToServer() {
76                 try {
77                         testProps.load(new FileInputStream("config/test.properties"));
78                         if (!DatabaseConnection.isInited()) {
79                                 DatabaseConnection.init(testProps);
80                         }
81                         System.out.println("... purging Database");
82                         DatabaseManager.run(new String[] { testProps.getProperty("sql.driver"), testProps.getProperty("sql.url"),
83                                         testProps.getProperty("sql.user"), testProps.getProperty("sql.password") });
84                         String type = testProps.getProperty("type");
85                         Properties mainProps = generateMainProps();
86                         ServerConstants.init(mainProps);
87                         if (type.equals("local")) {
88                                 url = testProps.getProperty("name.www") + ":" + testProps.getProperty("serverPort");
89                                 String[] parts = testProps.getProperty("mail").split(":", 2);
90                                 ter = new TestEmailReciever(new InetSocketAddress(parts[0], Integer.parseInt(parts[1])));
91                                 return;
92                         }
93                         url = testProps.getProperty("name.www") + ":" + testProps.getProperty("serverPort");
94                         gigi = Runtime.getRuntime().exec(testProps.getProperty("java"));
95                         DataOutputStream toGigi = new DataOutputStream(gigi.getOutputStream());
96                         System.out.println("... starting server");
97
98                         byte[] cacerts = Files.readAllBytes(Paths.get("config/cacerts.jks"));
99                         byte[] keystore = Files.readAllBytes(Paths.get("config/keystore.pkcs12"));
100
101                         DevelLauncher.writeGigiConfig(toGigi, "changeit".getBytes(), "changeit".getBytes(), mainProps, cacerts,
102                                 keystore);
103                         toGigi.flush();
104
105                         final BufferedReader br = new BufferedReader(new InputStreamReader(gigi.getErrorStream()));
106                         String line;
107                         while ((line = br.readLine()) != null && !line.contains("Server:main: Started")) {
108                         }
109                         new Thread() {
110                                 @Override
111                                 public void run() {
112                                         String line;
113                                         try {
114                                                 while ((line = br.readLine()) != null) {
115                                                         System.err.println(line);
116                                                 }
117                                         } catch (IOException e) {
118                                                 e.printStackTrace();
119                                         }
120                                 }
121                         }.start();
122                         if (line == null) {
123                                 throw new Error("Server startup failed");
124                         }
125                         ter = new TestEmailReciever(new InetSocketAddress("localhost", 8473));
126                         SimpleSigner.runSigner();
127                 } catch (IOException e) {
128                         throw new Error(e);
129                 } catch (ClassNotFoundException e1) {
130                         e1.printStackTrace();
131                 } catch (SQLException e1) {
132                         e1.printStackTrace();
133                 } catch (InterruptedException e) {
134                         e.printStackTrace();
135                 }
136
137         }
138
139         private static Properties generateMainProps() {
140                 Properties mainProps = new Properties();
141                 mainProps.setProperty("host", "127.0.0.1");
142                 mainProps.setProperty("name.secure", testProps.getProperty("name.secure"));
143                 mainProps.setProperty("name.www", testProps.getProperty("name.www"));
144                 mainProps.setProperty("name.static", testProps.getProperty("name.static"));
145
146                 mainProps.setProperty("port", testProps.getProperty("serverPort"));
147                 mainProps.setProperty("emailProvider", "org.cacert.gigi.email.TestEmailProvider");
148                 mainProps.setProperty("emailProvider.port", "8473");
149                 mainProps.setProperty("sql.driver", testProps.getProperty("sql.driver"));
150                 mainProps.setProperty("sql.url", testProps.getProperty("sql.url"));
151                 mainProps.setProperty("sql.user", testProps.getProperty("sql.user"));
152                 mainProps.setProperty("sql.password", testProps.getProperty("sql.password"));
153                 return mainProps;
154         }
155
156         @AfterClass
157         public static void tearDownServer() {
158                 String type = testProps.getProperty("type");
159                 ter.destroy();
160                 if (type.equals("local")) {
161                         return;
162                 }
163                 gigi.destroy();
164                 try {
165                         SimpleSigner.stopSigner();
166                 } catch (InterruptedException e) {
167                         e.printStackTrace();
168                 }
169         }
170
171         @After
172         public void removeMails() {
173                 ter.reset();
174         }
175
176         public TestMail waitForMail() {
177                 try {
178                         return ter.recieve();
179                 } catch (InterruptedException e) {
180                         throw new Error(e);
181                 }
182         }
183
184         public static TestEmailReciever getMailReciever() {
185                 return ter;
186         }
187
188         public String runRegister(String param) throws IOException {
189                 URL regist = new URL("https://" + getServerName() + registerService);
190                 HttpURLConnection uc = (HttpURLConnection) regist.openConnection();
191                 HttpURLConnection csrfConn = (HttpURLConnection) regist.openConnection();
192
193                 String headerField = csrfConn.getHeaderField("Set-Cookie");
194                 headerField = stripCookie(headerField);
195
196                 String csrf = getCSRF(csrfConn);
197                 uc.addRequestProperty("Cookie", headerField);
198                 uc.setDoOutput(true);
199                 uc.getOutputStream().write((param + "&csrf=" + csrf).getBytes());
200                 String d = IOUtils.readURL(uc);
201                 return d;
202         }
203
204         public String fetchStartErrorMessage(String d) throws IOException {
205                 String formFail = "<div class='formError'>";
206                 int idx = d.indexOf(formFail);
207                 if (idx == -1) {
208                         return null;
209                 }
210                 String startError = d.substring(idx + formFail.length(), idx + 100).trim();
211                 return startError;
212         }
213
214         public void registerUser(String firstName, String lastName, String email, String password) {
215                 try {
216                         String query = "fname=" + URLEncoder.encode(firstName, "UTF-8") + "&lname="
217                                 + URLEncoder.encode(lastName, "UTF-8") + "&email=" + URLEncoder.encode(email, "UTF-8") + "&pword1="
218                                 + URLEncoder.encode(password, "UTF-8") + "&pword2=" + URLEncoder.encode(password, "UTF-8")
219                                 + "&day=1&month=1&year=1910&cca_agree=1";
220                         String data = fetchStartErrorMessage(runRegister(query));
221                         assertTrue(data, data.startsWith("</div>"));
222                 } catch (UnsupportedEncodingException e) {
223                         throw new Error(e);
224                 } catch (IOException e) {
225                         throw new Error(e);
226                 }
227         }
228
229         public int createVerifiedUser(String firstName, String lastName, String email, String password) {
230                 registerUser(firstName, lastName, email, password);
231                 try {
232                         TestMail tm = ter.recieve();
233                         String verifyLink = tm.extractLink();
234                         String[] parts = verifyLink.split("\\?");
235                         URL u = new URL("https://" + getServerName() + "/verify?" + parts[1]);
236                         u.openStream().close();
237                         ;
238                         PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM users where email=?");
239                         ps.setString(1, email);
240                         ResultSet rs = ps.executeQuery();
241                         if (rs.next()) {
242                                 return rs.getInt(1);
243                         }
244                         throw new Error();
245                 } catch (InterruptedException e) {
246                         throw new Error(e);
247                 } catch (IOException e) {
248                         throw new Error(e);
249                 } catch (SQLException e) {
250                         throw new Error(e);
251                 }
252         }
253
254         /**
255          * Creates a new user with 100 Assurance points given by an (invalid)
256          * assurance.
257          * 
258          * @param firstName
259          *            the first name
260          * @param lastName
261          *            the last name
262          * @param email
263          *            the email
264          * @param password
265          *            the password
266          * @return a new userid.
267          */
268         public int createAssuranceUser(String firstName, String lastName, String email, String password) {
269                 int uid = createVerifiedUser(firstName, lastName, email, password);
270                 try {
271                         PreparedStatement ps = DatabaseConnection.getInstance().prepare(
272                                 "INSERT INTO `cats_passed` SET `user_id`=?, `variant_id`=?");
273                         ps.setInt(1, uid);
274                         ps.setInt(2, 0);
275                         ps.execute();
276                         ps = DatabaseConnection.getInstance().prepare("INSERT INTO `notary` SET `from`=?, `to`=?, points='100'");
277                         ps.setInt(1, uid);
278                         ps.setInt(2, uid);
279                         ps.execute();
280
281                 } catch (SQLException e) {
282                         throw new Error(e);
283                 }
284                 return uid;
285         }
286
287         static int count = 0;
288
289         public String createUniqueName() {
290                 return "test" + System.currentTimeMillis() + "a" + (count++);
291         }
292
293         private String stripCookie(String headerField) {
294                 return headerField.substring(0, headerField.indexOf(';'));
295         }
296
297         public static final String SECURE_REFERENCE = "/account/certs/email";
298
299         public boolean isLoggedin(String cookie) throws IOException {
300                 URL u = new URL("https://" + getServerName() + SECURE_REFERENCE);
301                 HttpURLConnection huc = (HttpURLConnection) u.openConnection();
302                 huc.addRequestProperty("Cookie", cookie);
303                 return huc.getResponseCode() == 200;
304         }
305
306         public String login(String email, String pw) throws IOException {
307                 URL u = new URL("https://" + getServerName() + "/login");
308                 HttpURLConnection huc = (HttpURLConnection) u.openConnection();
309                 huc.setDoOutput(true);
310                 OutputStream os = huc.getOutputStream();
311                 String data = "username=" + URLEncoder.encode(email, "UTF-8") + "&password=" + URLEncoder.encode(pw, "UTF-8");
312                 os.write(data.getBytes());
313                 os.flush();
314                 String headerField = huc.getHeaderField("Set-Cookie");
315                 return stripCookie(headerField);
316         }
317
318         public String login(final PrivateKey pk, final X509Certificate ce) throws NoSuchAlgorithmException,
319                 KeyManagementException, IOException, MalformedURLException {
320
321                 HttpURLConnection connection = (HttpURLConnection) new URL("https://"
322                         + getServerName().replaceFirst("^www.", "secure.") + "/login").openConnection();
323                 authenticateClientCert(pk, ce, connection);
324                 if (connection.getResponseCode() == 302) {
325                         assertEquals("https://" + getServerName().replaceFirst("^www.", "secure.").replaceFirst(":443$", "") + "/",
326                                 connection.getHeaderField("Location").replaceFirst(":443$", ""));
327                         return stripCookie(connection.getHeaderField("Set-Cookie"));
328                 } else {
329                         return null;
330                 }
331         }
332
333         public void authenticateClientCert(final PrivateKey pk, final X509Certificate ce, HttpURLConnection connection)
334                 throws NoSuchAlgorithmException, KeyManagementException {
335                 KeyManager km = new X509KeyManager() {
336
337                         @Override
338                         public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
339                                 return "client";
340                         }
341
342                         @Override
343                         public String chooseServerAlias(String arg0, Principal[] arg1, Socket arg2) {
344                                 return null;
345                         }
346
347                         @Override
348                         public X509Certificate[] getCertificateChain(String arg0) {
349                                 return new X509Certificate[] { ce };
350                         }
351
352                         @Override
353                         public String[] getClientAliases(String arg0, Principal[] arg1) {
354                                 return new String[] { "client" };
355                         }
356
357                         @Override
358                         public PrivateKey getPrivateKey(String arg0) {
359                                 if (arg0.equals("client")) {
360                                         return pk;
361                                 }
362                                 return null;
363                         }
364
365                         @Override
366                         public String[] getServerAliases(String arg0, Principal[] arg1) {
367                                 return new String[] { "client" };
368                         }
369                 };
370                 SSLContext sc = SSLContext.getInstance("TLS");
371                 sc.init(new KeyManager[] { km }, null, null);
372                 if (connection instanceof HttpsURLConnection) {
373                         ((HttpsURLConnection) connection).setSSLSocketFactory(sc.getSocketFactory());
374                 }
375         }
376
377         public String getCSRF(URLConnection u) throws IOException {
378                 return getCSRF(u, 0);
379         }
380
381         public String getCSRF(URLConnection u, int formIndex) throws IOException {
382                 String content = IOUtils.readURL(u);
383                 Pattern p = Pattern.compile("<input type='hidden' name='csrf' value='([^']+)'>");
384                 Matcher m = p.matcher(content);
385                 for (int i = 0; i < formIndex + 1; i++) {
386                         if (!m.find()) {
387                                 throw new Error("No CSRF Token");
388                         }
389                 }
390                 return m.group(1);
391         }
392
393         public static String[] generateCSR(String dn) throws IOException {
394                 Process p = Runtime.getRuntime().exec(
395                         new String[] { "openssl", "req", "-newkey", "rsa:1024", "-nodes", "-subj", dn, "-config",
396                                         "keys/selfsign.config" });
397                 String csr = IOUtils.readURL(new InputStreamReader(p.getInputStream()));
398
399                 String[] parts = csr.split("(?<=-----)\n(?=-----)");
400                 if (parts.length != 2) {
401                         System.err.println(IOUtils.readURL(new InputStreamReader(p.getErrorStream())));
402                         throw new Error();
403                 }
404                 return parts;
405         }
406
407         public String executeBasicWebInteraction(String cookie, String path, String query) throws MalformedURLException,
408                 UnsupportedEncodingException, IOException {
409                 return executeBasicWebInteraction(cookie, path, query, 0);
410         }
411
412         public String executeBasicWebInteraction(String cookie, String path, String query, int formIndex)
413                 throws IOException, MalformedURLException, UnsupportedEncodingException {
414                 URLConnection uc = new URL("https://" + getServerName() + path).openConnection();
415                 uc.addRequestProperty("Cookie", cookie);
416                 String csrf = getCSRF(uc, formIndex);
417
418                 uc = new URL("https://" + getServerName() + path).openConnection();
419                 uc.addRequestProperty("Cookie", cookie);
420                 uc.setDoOutput(true);
421                 OutputStream os = uc.getOutputStream();
422                 os.write(("csrf=" + URLEncoder.encode(csrf, "UTF-8") + "&" //
423                 + query//
424                 ).getBytes());
425                 os.flush();
426                 String error = fetchStartErrorMessage(IOUtils.readURL(uc));
427                 return error;
428         }
429
430         public EmailAddress createVerifiedEmail(User u) throws InterruptedException, GigiApiException {
431                 EmailAddress adrr = new EmailAddress(createUniqueName() + "test@test.tld", u);
432                 adrr.insert(Language.getInstance("en"));
433                 TestMail testMail = getMailReciever().recieve();
434                 assertTrue(adrr.getAddress().equals(testMail.getTo()));
435                 String hash = testMail.extractLink().substring(testMail.extractLink().lastIndexOf('=') + 1);
436                 adrr.verify(hash);
437                 getMailReciever().clearMails();
438                 return adrr;
439         }
440
441 }