]> WPIA git - gigi.git/blob - util-testing/org/cacert/gigi/pages/Manager.java
add: Allow multiple names, name-schemes, multi-name-assurance, etc.
[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             User byEmail = User.getByEmail(mail);
269             if (byEmail == null) {
270                 resp.getWriter().println("User not found.");
271                 return;
272             }
273             try {
274                 for (int i = 0; i < 10; i++) {
275                     Notary.assure(getAssurer(i), byEmail, byEmail.getPreferredName(), byEmail.getDoB(), 10, "Testmanager Assure up code", "2014-11-06", AssuranceType.FACE_TO_FACE);
276                 }
277             } catch (GigiApiException e) {
278                 throw new Error(e);
279             }
280             resp.getWriter().println("User has been assured.");
281         } else if (req.getParameter("letassure") != null) {
282             String mail = req.getParameter("letassureEmail");
283             User byEmail = User.getByEmail(mail);
284             try {
285                 for (int i = 0; i < 25; i++) {
286                     User a = getAssurer(i);
287                     Notary.assure(byEmail, a, a.getNames()[0], a.getDoB(), 10, "Testmanager exp up code", "2014-11-06", AssuranceType.FACE_TO_FACE);
288                 }
289             } catch (GigiApiException e) {
290                 throw new Error(e);
291             }
292         } else if (req.getParameter("addEmail") != null) {
293             User u = User.getByEmail(req.getParameter("addEmailEmail"));
294             try {
295                 EmailAddress ea = new EmailAddress(u, req.getParameter("addEmailNew"), Locale.ENGLISH);
296                 verify(ea.getAddress(), ea);
297             } catch (IllegalArgumentException e) {
298                 e.printStackTrace();
299                 resp.getWriter().println("An internal error occured.");
300             } catch (GigiApiException e) {
301                 e.format(resp.getWriter(), Language.getInstance(Locale.ENGLISH));
302             }
303         } else if (req.getParameter("addCert") != null) {
304             User u = User.getByEmail(req.getParameter("addCertEmail"));
305             try {
306                 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
307                 kpg.initialize(4096);
308                 KeyPair kp = kpg.generateKeyPair();
309                 SPKAC s = new SPKAC((X509Key) kp.getPublic(), "challange");
310                 Signature sign = Signature.getInstance("SHA512withRSA");
311                 sign.initSign(kp.getPrivate());
312
313                 byte[] res = s.getEncoded(sign);
314
315                 CertificateRequest cr = new CertificateRequest(new AuthorizationContext(u, u), Base64.getEncoder().encodeToString(res), "challange");
316                 cr.update(CertificateRequest.DEFAULT_CN, Digest.SHA512.toString(), "client", null, "", "email:" + u.getEmail());
317                 Certificate draft = cr.draft();
318                 draft.issue(null, "2y", u).waitFor(10000);
319                 if (draft.getStatus() == CertificateStatus.ISSUED) {
320                     resp.getWriter().println("added certificate");
321                 } else {
322                     resp.getWriter().println("signer failed");
323                 }
324             } catch (GeneralSecurityException e1) {
325                 e1.printStackTrace();
326                 resp.getWriter().println("error");
327             } catch (GigiApiException e) {
328                 e.format(resp.getWriter(), Language.getInstance(Locale.ENGLISH));
329             } catch (InterruptedException e) {
330                 e.printStackTrace();
331                 resp.getWriter().println("interrupted");
332             }
333
334         } else if (req.getParameter("addExDom") != null) {
335             String dom = req.getParameter("exemtDom");
336             pingExempt.add(dom);
337             resp.getWriter().println("Updated domains exempt from pings. Current set: <br/>");
338             resp.getWriter().println(pingExempt);
339         } else if (req.getParameter("delExDom") != null) {
340             String dom = req.getParameter("exemtDom");
341             pingExempt.remove(dom);
342             resp.getWriter().println("Updated domains exempt from pings. Current set: <br/>");
343             resp.getWriter().println(pingExempt);
344         }
345     }
346
347     private void fetchMails(HttpServletRequest req, HttpServletResponse resp, String mail) throws IOException {
348         final LinkedList<String> mails = emails.get(mail);
349         HashMap<String, Object> vars = new HashMap<>();
350         vars.put("mail", mail);
351         if (mails != null) {
352             vars.put("mails", new IterableDataset() {
353
354                 Iterator<String> s = mails.iterator();
355
356                 @Override
357                 public boolean next(Language l, Map<String, Object> vars) {
358                     if ( !s.hasNext()) {
359                         return false;
360                     }
361                     vars.put("body", s.next().replaceAll("(https?://\\S+)", "<a href=\"$1\">$1</a>"));
362                     return true;
363                 }
364             });
365         }
366         t.output(resp.getWriter(), getLanguage(req), vars);
367         if (mails == null) {
368             resp.getWriter().println("No mails");
369
370         }
371     }
372
373     private static final Template form = new Template(Manager.class.getResource("Manager.templ"));
374
375     @Override
376     public boolean needsLogin() {
377         return false;
378     }
379
380     @Override
381     public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
382         String pi = req.getPathInfo().substring(PATH.length());
383         if (pi.length() > 1 && pi.startsWith("/fetch-")) {
384             String mail = pi.substring(pi.indexOf('-', 2) + 1);
385             fetchMails(req, resp, mail);
386             return;
387         }
388         HashMap<String, Object> vars = new HashMap<>();
389         vars.put("cats_types", new IterableDataset() {
390
391             CATSType[] type = CATSType.values();
392
393             int i = 0;
394
395             @Override
396             public boolean next(Language l, Map<String, Object> vars) {
397                 if (i >= type.length) {
398                     return false;
399                 }
400                 CATSType t = type[i++];
401                 vars.put("id", i - 1);
402                 vars.put("name", t.getDisplayName());
403                 return true;
404             }
405         });
406         form.output(resp.getWriter(), getLanguage(req), vars);
407     }
408 }