]> WPIA git - gigi.git/blob - src/org/cacert/gigi/pages/account/IssueCertificateForm.java
UPD: moved getUser up
[gigi.git] / src / org / cacert / gigi / pages / account / IssueCertificateForm.java
1 package org.cacert.gigi.pages.account;
2
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.security.GeneralSecurityException;
6 import java.security.PublicKey;
7 import java.security.interfaces.DSAPublicKey;
8 import java.security.interfaces.ECPublicKey;
9 import java.security.interfaces.RSAPublicKey;
10 import java.sql.SQLException;
11 import java.util.Base64;
12 import java.util.HashMap;
13 import java.util.Map;
14
15 import javax.servlet.http.HttpServletRequest;
16
17 import org.cacert.gigi.Certificate;
18 import org.cacert.gigi.Certificate.CSRType;
19 import org.cacert.gigi.Digest;
20 import org.cacert.gigi.EmailAddress;
21 import org.cacert.gigi.GigiApiException;
22 import org.cacert.gigi.Language;
23 import org.cacert.gigi.User;
24 import org.cacert.gigi.crypto.SPKAC;
25 import org.cacert.gigi.output.Form;
26 import org.cacert.gigi.output.template.HashAlgorithms;
27 import org.cacert.gigi.output.template.IterableDataset;
28 import org.cacert.gigi.output.template.Template;
29 import org.cacert.gigi.pages.LoginPage;
30 import org.cacert.gigi.pages.Page;
31 import org.cacert.gigi.util.PEM;
32 import org.cacert.gigi.util.RandomToken;
33
34 import sun.security.pkcs10.PKCS10;
35 import sun.security.util.DerInputStream;
36 import sun.security.util.DerValue;
37 import sun.security.x509.AlgorithmId;
38
39 /**
40  * This class represents a form that is used for issuing certificates. This
41  * class uses "sun.security" and therefore needs "-XDignore.symbol.file"
42  */
43 public class IssueCertificateForm extends Form {
44
45     User u;
46
47     Digest selectedDigest = Digest.getDefault();
48
49     boolean login;
50
51     String csr;
52
53     private final static Template t = new Template(IssueCertificateForm.class.getResource("IssueCertificateForm.templ"));
54
55     private final static Template tIni = new Template(MailCertificateAdd.class.getResource("RequestCertificate.templ"));
56
57     String spkacChallange;
58
59     public IssueCertificateForm(HttpServletRequest hsr) {
60         super(hsr);
61         u = Page.getUser(hsr);
62         spkacChallange = RandomToken.generateToken(16);
63     }
64
65     Certificate result;
66
67     private CSRType csrType;
68
69     public Certificate getResult() {
70         return result;
71     }
72
73     @Override
74     public boolean submit(PrintWriter out, HttpServletRequest req) {
75         String csr = req.getParameter("CSR");
76         String spkac = req.getParameter("SPKAC");
77         try {
78             try {
79                 if (csr != null) {
80                     byte[] data = PEM.decode("(NEW )?CERTIFICATE REQUEST", csr);
81                     PKCS10 parsed = new PKCS10(data);
82
83                     out.println(parsed.getSubjectName().getCommonName());
84                     out.println(parsed.getSubjectName().getCountry());
85                     out.println("CSR DN: " + parsed.getSubjectName() + "<br/>");
86                     PublicKey pk = parsed.getSubjectPublicKeyInfo();
87                     checkKeyStrength(pk, out);
88                     String sign = getSignatureAlgorithm(data);
89                     out.println("<br/>digest: " + sign + "<br/>");
90
91                     this.csr = csr;
92                     this.csrType = CSRType.CSR;
93                 } else if (spkac != null) {
94                     String cleanedSPKAC = spkac.replaceAll("[\r\n]", "");
95                     byte[] data = Base64.getDecoder().decode(cleanedSPKAC);
96                     SPKAC parsed = new SPKAC(data);
97                     if ( !parsed.getChallenge().equals(spkacChallange)) {
98                         throw new GigiApiException("Challange mismatch");
99                     }
100                     checkKeyStrength(parsed.getPubkey(), out);
101                     String sign = getSignatureAlgorithm(data);
102                     out.println("<br/>digest: " + sign + "<br/>");
103
104                     // spkacChallange
105                     this.csr = "SPKAC=" + cleanedSPKAC;
106                     this.csrType = CSRType.SPKAC;
107
108                 } else {
109                     login = "1".equals(req.getParameter("login"));
110                     String hashAlg = req.getParameter("hash_alg");
111                     if (hashAlg != null) {
112                         selectedDigest = Digest.valueOf(hashAlg);
113                     }
114                     if (req.getParameter("CCA") == null) {
115                         outputError(out, req, "You need to accept the CCA.");
116                         return false;
117                     }
118                     System.out.println("issuing " + selectedDigest);
119                     result = new Certificate(LoginPage.getUser(req).getId(), "/commonName=CAcert WoT User", selectedDigest.toString(), this.csr, this.csrType);
120                     result.issue().waitFor(60000);
121                     return true;
122                 }
123             } catch (IOException e) {
124                 e.printStackTrace();
125             } catch (IllegalArgumentException e) {
126                 throw new GigiApiException("Certificate Request format is invalid.");
127             } catch (GeneralSecurityException e) {
128                 throw new GigiApiException("Certificate Request format is invalid.");
129             } catch (InterruptedException e) {
130                 e.printStackTrace();
131             } catch (SQLException e) {
132                 throw new GigiApiException(e);
133             }
134         } catch (GigiApiException e) {
135             e.format(out, Page.getLanguage(req));
136         }
137         return false;
138     }
139
140     private void checkKeyStrength(PublicKey pk, PrintWriter out) {
141         out.println("Type: " + pk.getAlgorithm() + "<br/>");
142         if (pk instanceof RSAPublicKey) {
143             out.println("Exponent: " + ((RSAPublicKey) pk).getPublicExponent() + "<br/>");
144             out.println("Length: " + ((RSAPublicKey) pk).getModulus().bitLength());
145         } else if (pk instanceof DSAPublicKey) {
146             DSAPublicKey dpk = (DSAPublicKey) pk;
147             out.println("Length: " + dpk.getY().bitLength() + "<br/>");
148             out.println(dpk.getParams());
149         } else if (pk instanceof ECPublicKey) {
150             ECPublicKey epk = (ECPublicKey) pk;
151             out.println("Length-x: " + epk.getW().getAffineX().bitLength() + "<br/>");
152             out.println("Length-y: " + epk.getW().getAffineY().bitLength() + "<br/>");
153             out.println(epk.getParams().getCurve());
154         }
155     }
156
157     private static PKCS10 parseCSR(String csr) throws IOException, GeneralSecurityException {
158         return new PKCS10(PEM.decode("(NEW )?CERTIFICATE REQUEST", csr));
159     }
160
161     private static String getSignatureAlgorithm(byte[] data) throws IOException {
162         DerInputStream in = new DerInputStream(data);
163         DerValue[] seq = in.getSequence(3);
164         return AlgorithmId.parse(seq[1]).getName();
165     }
166
167     @Override
168     public void output(PrintWriter out, Language l, Map<String, Object> vars) {
169         if (csr == null) {
170             HashMap<String, Object> vars2 = new HashMap<String, Object>(vars);
171             vars2.put("csrf", getCSRFToken());
172             vars2.put("csrf_name", getCsrfFieldName());
173             vars2.put("spkacChallange", spkacChallange);
174             tIni.output(out, l, vars2);
175             return;
176         } else {
177             super.output(out, l, vars);
178         }
179     }
180
181     @Override
182     protected void outputContent(PrintWriter out, Language l, Map<String, Object> vars) {
183         HashMap<String, Object> vars2 = new HashMap<String, Object>(vars);
184         vars2.put("CCA", "<a href='/policy/CAcertCommunityAgreement.html'>CCA</a>");
185
186         final EmailAddress[] ea = u.getEmails();
187         vars2.put("emails", new IterableDataset() {
188
189             int count;
190
191             @Override
192             public boolean next(Language l, Map<String, Object> vars) {
193                 if (count >= ea.length) {
194                     return false;
195                 }
196                 vars.put("id", ea[count].getId());
197                 vars.put("value", ea[count].getAddress());
198                 count++;
199                 return true;
200             }
201         });
202         vars2.put("hashs", new HashAlgorithms(selectedDigest));
203         t.output(out, l, vars2);
204     }
205 }