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