1 package org.cacert.gigi.util;
3 import java.io.BufferedReader;
5 import java.io.FileInputStream;
6 import java.io.FileReader;
7 import java.io.IOException;
8 import java.io.InputStream;
9 import java.io.InputStreamReader;
10 import java.io.PrintWriter;
11 import java.math.BigInteger;
12 import java.security.GeneralSecurityException;
13 import java.security.cert.CertificateFactory;
14 import java.security.cert.X509Certificate;
15 import java.sql.PreparedStatement;
16 import java.sql.ResultSet;
17 import java.sql.SQLException;
18 import java.util.Arrays;
19 import java.util.Properties;
21 import org.cacert.gigi.Certificate.CSRType;
22 import org.cacert.gigi.database.DatabaseConnection;
24 public class SimpleSigner {
26 private static PreparedStatement warnMail;
28 private static PreparedStatement updateMail;
30 private static PreparedStatement readyCerts;
32 private static PreparedStatement getSANSs;
34 private static PreparedStatement revoke;
36 private static PreparedStatement revokeCompleted;
38 private static PreparedStatement finishJob;
40 private static boolean running = true;
42 private static Thread runner;
44 public static void main(String[] args) throws IOException, SQLException, InterruptedException {
45 Properties p = new Properties();
46 p.load(new FileReader("config/gigi.properties"));
47 DatabaseConnection.init(p);
52 public synchronized static void stopSigner() throws InterruptedException {
54 throw new IllegalStateException("already stopped");
62 public synchronized static void runSigner() throws SQLException, IOException, InterruptedException {
64 throw new IllegalStateException("already running");
67 readyCerts = DatabaseConnection.getInstance().prepare("SELECT emailcerts.id AS id, emailcerts.csr_name, emailcerts.subject, jobs.id AS jobid, csr_type, md, keyUsage, extendedKeyUsage FROM jobs " + //
68 "INNER JOIN emailcerts ON emailcerts.id=jobs.targetId " + //
69 "INNER JOIN profiles ON profiles.id=emailcerts.profile " + //
70 "WHERE jobs.state='open' "//
73 getSANSs = DatabaseConnection.getInstance().prepare("SELECT contents, type FROM subjectAlternativeNames " + //
76 updateMail = DatabaseConnection.getInstance().prepare("UPDATE emailcerts SET crt_name=?," + " created=NOW(), serial=? WHERE id=?");
77 warnMail = DatabaseConnection.getInstance().prepare("UPDATE jobs SET warning=warning+1, state=IF(warning<3, 'open','error') WHERE id=?");
79 revoke = DatabaseConnection.getInstance().prepare("SELECT emailcerts.id, emailcerts.csr_name,jobs.id FROM jobs INNER JOIN emailcerts ON jobs.targetId=emailcerts.id" + " WHERE jobs.state='open' AND task='revoke'");
80 revokeCompleted = DatabaseConnection.getInstance().prepare("UPDATE emailcerts SET revoked=NOW() WHERE id=?");
82 finishJob = DatabaseConnection.getInstance().prepare("UPDATE jobs SET state='done' WHERE id=?");
84 runner = new Thread() {
95 private static void work() {
98 } catch (IOException e2) {
100 } catch (InterruptedException e2) {
101 e2.printStackTrace();
106 revokeCertificates();
108 } catch (IOException e) {
110 } catch (SQLException e) {
112 } catch (InterruptedException e1) {
117 private static void revokeCertificates() throws SQLException, IOException, InterruptedException {
118 ResultSet rs = revoke.executeQuery();
119 boolean worked = false;
121 int id = rs.getInt(1);
122 File crt = KeyStorage.locateCrt(id);
123 String[] call = new String[] {
130 "../" + crt.getPath(),//
136 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys"));
137 System.out.println("revoking: " + crt.getPath());
138 if (p1.waitFor() == 0) {
140 revokeCompleted.setInt(1, id);
141 revokeCompleted.execute();
142 finishJob.setInt(1, rs.getInt(3));
145 System.out.println("Failed");
153 private static void gencrl() throws IOException, InterruptedException {
154 String[] call = new String[] {
169 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys"));
170 if (p1.waitFor() != 0) {
171 System.out.println("Error while generating crl.");
175 private static int counter = 0;
177 private static void signCertificates() throws SQLException, IOException, InterruptedException {
178 ResultSet rs = readyCerts.executeQuery();
180 String csrname = rs.getString("csr_name");
181 System.out.println("sign: " + csrname);
182 int id = rs.getInt("id");
183 String csrType = rs.getString("csr_type");
184 CSRType ct = CSRType.valueOf(csrType);
185 File crt = KeyStorage.locateCrt(id);
187 String keyUsage = rs.getString("keyUsage");
188 String ekeyUsage = rs.getString("extendedKeyUsage");
189 getSANSs.setInt(1, id);
190 ResultSet san = getSANSs.executeQuery();
192 File f = new File("keys", "SANFile" + System.currentTimeMillis() + (counter++) + ".cfg");
193 PrintWriter cfg = new PrintWriter(f);
194 boolean first = true;
199 cfg.print("subjectAltName=");
202 cfg.print(san.getString("type"));
204 cfg.print(san.getString("contents"));
207 cfg.println("keyUsage=" + keyUsage);
208 cfg.println("extendedKeyUsage=" + ekeyUsage);
211 String[] call = new String[] {
220 "../" + crt.getPath(),//
225 rs.getString("md"),//
230 rs.getString("subject"),//
235 if (ct == CSRType.SPKAC) {
238 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys"));
240 int waitFor = p1.waitFor();
243 try (InputStream is = new FileInputStream(crt)) {
244 CertificateFactory cf = CertificateFactory.getInstance("X.509");
245 X509Certificate crtp = (X509Certificate) cf.generateCertificate(is);
246 BigInteger serial = crtp.getSerialNumber();
247 updateMail.setString(1, crt.getPath());
248 updateMail.setString(2, serial.toString(16));
249 updateMail.setInt(3, id);
250 updateMail.execute();
252 finishJob.setInt(1, rs.getInt("jobid"));
254 System.out.println("signed: " + id);
256 } catch (GeneralSecurityException e) {
259 System.out.println("ERROR Afterwards: " + id);
260 warnMail.setInt(1, rs.getInt("jobid"));
263 BufferedReader br = new BufferedReader(new InputStreamReader(p1.getErrorStream()));
265 while ((s = br.readLine()) != null) {
266 System.out.println(s);
268 System.out.println(Arrays.toString(call));
269 System.out.println("ERROR: " + id);
270 warnMail.setInt(1, rs.getInt("jobid"));