]> WPIA git - gigi.git/blob - util-testing/org/cacert/gigi/pages/Manager.java
da506a6ae08d1d717689e2947a32ddfdaea7503f
[gigi.git] / util-testing / org / cacert / gigi / pages / Manager.java
1 package org.cacert.gigi.pages;
2
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.lang.reflect.Field;
6 import java.security.GeneralSecurityException;
7 import java.security.KeyPair;
8 import java.security.KeyPairGenerator;
9 import java.security.Signature;
10 import java.sql.Date;
11 import java.util.Base64;
12 import java.util.Calendar;
13 import java.util.GregorianCalendar;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.LinkedList;
17 import java.util.Locale;
18 import java.util.Map;
19 import java.util.Properties;
20 import java.util.TreeSet;
21
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24
25 import org.cacert.gigi.Gigi;
26 import org.cacert.gigi.GigiApiException;
27 import org.cacert.gigi.crypto.SPKAC;
28 import org.cacert.gigi.database.DatabaseConnection;
29 import org.cacert.gigi.database.GigiPreparedStatement;
30 import org.cacert.gigi.dbObjects.Certificate;
31 import org.cacert.gigi.dbObjects.Certificate.CertificateStatus;
32 import org.cacert.gigi.dbObjects.CertificateOwner;
33 import org.cacert.gigi.dbObjects.Digest;
34 import org.cacert.gigi.dbObjects.Domain;
35 import org.cacert.gigi.dbObjects.DomainPingType;
36 import org.cacert.gigi.dbObjects.EmailAddress;
37 import org.cacert.gigi.dbObjects.Group;
38 import org.cacert.gigi.dbObjects.Name;
39 import org.cacert.gigi.dbObjects.User;
40 import org.cacert.gigi.email.EmailProvider;
41 import org.cacert.gigi.localisation.Language;
42 import org.cacert.gigi.output.template.IterableDataset;
43 import org.cacert.gigi.output.template.Template;
44 import org.cacert.gigi.pages.account.certs.CertificateRequest;
45 import org.cacert.gigi.ping.DomainPinger;
46 import org.cacert.gigi.ping.PingerDaemon;
47 import org.cacert.gigi.util.AuthorizationContext;
48 import org.cacert.gigi.util.Notary;
49
50 import sun.security.x509.X509Key;
51
52 public class Manager extends Page {
53
54     public static final String PATH = "/manager";
55
56     Field f;
57
58     private static HashMap<DomainPingType, DomainPinger> dps;
59
60     private Manager() {
61         super("Test Manager");
62         try {
63             f = EmailAddress.class.getDeclaredField("hash");
64             f.setAccessible(true);
65         } catch (ReflectiveOperationException e) {
66             // TODO
67             System.out.println("I don't have 'hash', we are working probably in layered mode. Test Manager may not work.");
68             // throw new Error(e);
69         }
70
71         try {
72             Field gigiInstance = Gigi.class.getDeclaredField("instance");
73             gigiInstance.setAccessible(true);
74             Gigi g = (Gigi) gigiInstance.get(null);
75
76             Field gigiPinger = Gigi.class.getDeclaredField("pinger");
77             gigiPinger.setAccessible(true);
78             PingerDaemon pd = (PingerDaemon) gigiPinger.get(g);
79
80             Field f = PingerDaemon.class.getDeclaredField("pingers");
81             f.setAccessible(true);
82             dps = (HashMap<DomainPingType, DomainPinger>) f.get(pd);
83             HashMap<DomainPingType, DomainPinger> pingers = new HashMap<>();
84             for (DomainPingType dpt : DomainPingType.values()) {
85                 pingers.put(dpt, new PingerFetcher(dpt));
86             }
87             f.set(pd, pingers);
88         } catch (ReflectiveOperationException e) {
89             e.printStackTrace();
90         }
91     }
92
93     public User[] getAssurers() {
94         if (assurers != null) {
95             return assurers;
96         }
97         assurers = new User[10];
98         try {
99             GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO `notary` SET `from`=?, `to`=?, `points`=?, `location`=?, `date`=?");
100             for (int i = 0; i < assurers.length; i++) {
101                 String mail = "test-assurer" + i + "@example.com";
102                 User u = User.getByEmail(mail);
103                 if (u == null) {
104                     System.out.println("Creating assurer");
105                     createUser(mail);
106                     u = User.getByEmail(mail);
107                     passCATS(u);
108                     ps.setInt(1, u.getId());
109                     ps.setInt(2, u.getId());
110                     ps.setInt(3, 100);
111                     ps.setString(4, "Manager init code");
112                     ps.setString(5, "1990-01-01");
113                     ps.execute();
114                 }
115                 assurers[i] = u;
116
117             }
118         } catch (ReflectiveOperationException | GigiApiException e) {
119             e.printStackTrace();
120         }
121         return assurers;
122     }
123
124     private void passCATS(User u) {
125         GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO cats_passed SET user_id=?, variant_id=1");
126         ps.setInt(1, u.getId());
127         ps.execute();
128     }
129
130     private static Manager instance;
131
132     Template t = new Template(Manager.class.getResource("ManagerMails.templ"));
133
134     HashMap<String, LinkedList<String>> emails = new HashMap<>();
135
136     private static TreeSet<String> pingExempt = new TreeSet<>();
137
138     public static Manager getInstance() {
139         if (instance == null) {
140             instance = new Manager();
141         }
142         return instance;
143     }
144
145     public static class MailFetcher extends EmailProvider {
146
147         public MailFetcher(Properties p) {}
148
149         @Override
150         public String checkEmailServer(int forUid, String address) throws IOException {
151             return OK;
152         }
153
154         @Override
155         public synchronized void sendmail(String to, String subject, String message, String from, String replyto, String toname, String fromname, String errorsto, boolean extra) throws IOException {
156             HashMap<String, LinkedList<String>> mails = Manager.getInstance().emails;
157             LinkedList<String> hismails = mails.get(to);
158             if (hismails == null) {
159                 mails.put(to, hismails = new LinkedList<>());
160             }
161             hismails.addFirst(subject + "\n" + message);
162         }
163
164     }
165
166     public class PingerFetcher extends DomainPinger {
167
168         private DomainPingType dpt;
169
170         public PingerFetcher(DomainPingType dpt) {
171             this.dpt = dpt;
172         }
173
174         @Override
175         public void ping(Domain domain, String configuration, CertificateOwner target, int confId) {
176             System.out.println("Test: " + domain);
177             if (pingExempt.contains(domain.getSuffix())) {
178                 enterPingResult(confId, DomainPinger.PING_SUCCEDED, "Succeeded by TestManager pass-by", null);
179             } else {
180                 dps.get(dpt).ping(domain, configuration, target, confId);
181             }
182         }
183
184     }
185
186     public void batchCreateUsers(String mailPrefix, String domain, int amount, PrintWriter out) {
187
188         try {
189             if (amount > 100) {
190                 out.print("100 at most, please.");
191                 return;
192             }
193             for (int i = 0; i < amount; i++) {
194                 String email = mailPrefix + i + "@" + domain;
195                 createUser(email);
196             }
197         } catch (ReflectiveOperationException e) {
198             out.println("failed");
199             e.printStackTrace();
200         } catch (GigiApiException e) {
201             out.println("failed: " + e.getMessage());
202             e.printStackTrace();
203         }
204     }
205
206     private void createUser(String email) throws GigiApiException, IllegalAccessException {
207         Calendar gc = GregorianCalendar.getInstance();
208         gc.set(1990, 0, 1);
209         User u = new User(email, "xvXV12°§", new Name("Först", "Läst", "Müddle", "Süffix"), new Date(gc.getTime().getTime()), Locale.ENGLISH);
210         EmailAddress ea = u.getEmails()[0];
211         if (f == null) {
212             System.out.println("verification failed");
213             return;
214         }
215         String hash = (String) f.get(ea);
216
217         ea.verify(hash);
218     }
219
220     User[] assurers;
221
222     @Override
223     public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
224         if (req.getParameter("create") != null) {
225             batchCreateUsers(req.getParameter("prefix"), req.getParameter("suffix"), Integer.parseInt(req.getParameter("amount")), resp.getWriter());
226             resp.getWriter().println("User batch created.");
227         } else if (req.getParameter("addpriv") != null || req.getParameter("delpriv") != null) {
228             User u = User.getByEmail(req.getParameter("email"));
229             if (u == null) {
230                 resp.getWriter().println("User not found.");
231                 return;
232             }
233             if (req.getParameter("addpriv") != null) {
234                 u.grantGroup(u, Group.getByString(req.getParameter("priv")));
235                 resp.getWriter().println("Privilege granted");
236             } else {
237                 u.revokeGroup(u, Group.getByString(req.getParameter("priv")));
238                 resp.getWriter().println("Privilege revoked");
239             }
240         } else if (req.getParameter("fetch") != null) {
241             String mail = req.getParameter("femail");
242             fetchMails(req, resp, mail);
243         } else if (req.getParameter("cats") != null) {
244             String mail = req.getParameter("catsEmail");
245             User byEmail = User.getByEmail(mail);
246             if (byEmail == null) {
247                 resp.getWriter().println("User not found.");
248                 return;
249             }
250             passCATS(byEmail);
251             resp.getWriter().println("User has been passed CATS");
252         } else if (req.getParameter("assure") != null) {
253             String mail = req.getParameter("assureEmail");
254             User byEmail = User.getByEmail(mail);
255             if (byEmail == null) {
256                 resp.getWriter().println("User not found.");
257                 return;
258             }
259             try {
260                 for (int i = 0; i < getAssurers().length; i++) {
261                     Notary.assure(getAssurers()[i], byEmail, byEmail.getName(), byEmail.getDoB(), 10, "Testmanager Assure up code", "2014-11-06");
262                 }
263             } catch (GigiApiException e) {
264                 throw new Error(e);
265             }
266             resp.getWriter().println("User has been assured.");
267         } else if (req.getParameter("addEmail") != null) {
268             User u = User.getByEmail(req.getParameter("addEmailEmail"));
269             try {
270                 EmailAddress ea = new EmailAddress(u, req.getParameter("addEmailNew"), Locale.ENGLISH);
271                 if (f != null) {
272                     String hash = (String) f.get(ea);
273                     ea.verify(hash);
274                     resp.getWriter().println("Email added and verified");
275                 } else {
276                     resp.getWriter().println("Email added but verificatio failed.");
277                 }
278             } catch (IllegalArgumentException e) {
279                 e.printStackTrace();
280                 resp.getWriter().println("An internal error occured.");
281             } catch (IllegalAccessException e) {
282                 e.printStackTrace();
283                 resp.getWriter().println("An internal error occured.");
284             } catch (GigiApiException e) {
285                 e.format(resp.getWriter(), Language.getInstance(Locale.ENGLISH));
286             }
287         } else if (req.getParameter("addCert") != null) {
288             User u = User.getByEmail(req.getParameter("addCertEmail"));
289             try {
290                 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
291                 kpg.initialize(4096);
292                 KeyPair kp = kpg.generateKeyPair();
293                 SPKAC s = new SPKAC((X509Key) kp.getPublic(), "challange");
294                 Signature sign = Signature.getInstance("SHA512withRSA");
295                 sign.initSign(kp.getPrivate());
296
297                 byte[] res = s.getEncoded(sign);
298
299                 CertificateRequest cr = new CertificateRequest(new AuthorizationContext(u, u), Base64.getEncoder().encodeToString(res), "challange");
300                 cr.update(CertificateRequest.DEFAULT_CN, Digest.SHA512.toString(), "client", null, "", "email:" + u.getEmail(), resp.getWriter(), req);
301                 Certificate draft = cr.draft();
302                 draft.issue(null, "2y", u).waitFor(10000);
303                 if (draft.getStatus() == CertificateStatus.ISSUED) {
304                     resp.getWriter().println("added certificate");
305                 } else {
306                     resp.getWriter().println("signer failed");
307                 }
308             } catch (GeneralSecurityException e1) {
309                 e1.printStackTrace();
310                 resp.getWriter().println("error");
311             } catch (GigiApiException e) {
312                 e.format(resp.getWriter(), Language.getInstance(Locale.ENGLISH));
313             } catch (InterruptedException e) {
314                 e.printStackTrace();
315                 resp.getWriter().println("interrupted");
316             }
317
318         } else if (req.getParameter("addExDom") != null) {
319             String dom = req.getParameter("exemtDom");
320             pingExempt.add(dom);
321             resp.getWriter().println("Updated domains exempt from pings. Current set: <br/>");
322             resp.getWriter().println(pingExempt);
323         } else if (req.getParameter("delExDom") != null) {
324             String dom = req.getParameter("exemtDom");
325             pingExempt.remove(dom);
326             resp.getWriter().println("Updated domains exempt from pings. Current set: <br/>");
327             resp.getWriter().println(pingExempt);
328         }
329     }
330
331     private void fetchMails(HttpServletRequest req, HttpServletResponse resp, String mail) throws IOException {
332         final LinkedList<String> mails = emails.get(mail);
333         HashMap<String, Object> vars = new HashMap<>();
334         vars.put("mail", mail);
335         if (mails != null) {
336             vars.put("mails", new IterableDataset() {
337
338                 Iterator<String> s = mails.iterator();
339
340                 @Override
341                 public boolean next(Language l, Map<String, Object> vars) {
342                     if ( !s.hasNext()) {
343                         return false;
344                     }
345                     vars.put("body", s.next().replaceAll("(https?://\\S+)", "<a href=\"$1\">$1</a>"));
346                     return true;
347                 }
348             });
349         }
350         t.output(resp.getWriter(), getLanguage(req), vars);
351         if (mails == null) {
352             resp.getWriter().println("No mails");
353
354         }
355     }
356
357     private Template form = new Template(Manager.class.getResource("Manager.templ"));
358
359     @Override
360     public boolean needsLogin() {
361         return false;
362     }
363
364     @Override
365     public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
366         getAssurers();
367         String pi = req.getPathInfo().substring(PATH.length());
368         if (pi.length() > 1 && pi.startsWith("/fetch-")) {
369             String mail = pi.substring(pi.indexOf('-', 2) + 1);
370             fetchMails(req, resp, mail);
371             return;
372         }
373
374         form.output(resp.getWriter(), getLanguage(req), new HashMap<String, Object>());
375     }
376 }