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.util.Date;
16 import java.sql.PreparedStatement;
17 import java.sql.ResultSet;
18 import java.sql.SQLException;
19 import java.text.ParseException;
20 import java.text.SimpleDateFormat;
21 import java.util.Calendar;
22 import java.util.Properties;
23 import java.util.TimeZone;
25 import org.cacert.gigi.Certificate.CSRType;
26 import org.cacert.gigi.database.DatabaseConnection;
27 import org.cacert.gigi.output.CertificateValiditySelector;
29 public class SimpleSigner {
31 private static PreparedStatement warnMail;
33 private static PreparedStatement updateMail;
35 private static PreparedStatement readyCerts;
37 private static PreparedStatement getSANSs;
39 private static PreparedStatement revoke;
41 private static PreparedStatement revokeCompleted;
43 private static PreparedStatement finishJob;
45 private static boolean running = true;
47 private static Thread runner;
49 private static SimpleDateFormat sdf = new SimpleDateFormat("YYMMddHHmmss'Z'");
51 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
54 public static void main(String[] args) throws IOException, SQLException, InterruptedException {
55 Properties p = new Properties();
56 p.load(new FileReader("config/gigi.properties"));
57 DatabaseConnection.init(p);
62 public synchronized static void stopSigner() throws InterruptedException {
64 throw new IllegalStateException("already stopped");
72 public synchronized static void runSigner() throws SQLException, IOException, InterruptedException {
74 throw new IllegalStateException("already running");
77 readyCerts = DatabaseConnection.getInstance().prepare("SELECT certs.id AS id, certs.csr_name, certs.subject, jobs.id AS jobid, csr_type, md, keyUsage, extendedKeyUsage, executeFrom, executeTo FROM jobs " + //
78 "INNER JOIN certs ON certs.id=jobs.targetId " + //
79 "INNER JOIN profiles ON profiles.id=certs.profile " + //
80 "WHERE jobs.state='open' "//
83 getSANSs = DatabaseConnection.getInstance().prepare("SELECT contents, type FROM subjectAlternativeNames " + //
86 updateMail = DatabaseConnection.getInstance().prepare("UPDATE certs SET crt_name=?," + " created=NOW(), serial=? WHERE id=?");
87 warnMail = DatabaseConnection.getInstance().prepare("UPDATE jobs SET warning=warning+1, state=IF(warning<3, 'open','error') WHERE id=?");
89 revoke = DatabaseConnection.getInstance().prepare("SELECT certs.id, certs.csr_name,jobs.id FROM jobs INNER JOIN certs ON jobs.targetId=certs.id" + " WHERE jobs.state='open' AND task='revoke'");
90 revokeCompleted = DatabaseConnection.getInstance().prepare("UPDATE certs SET revoked=NOW() WHERE id=?");
92 finishJob = DatabaseConnection.getInstance().prepare("UPDATE jobs SET state='done' WHERE id=?");
94 runner = new Thread() {
105 private static void work() {
108 } catch (IOException e2) {
109 e2.printStackTrace();
110 } catch (InterruptedException e2) {
111 e2.printStackTrace();
116 revokeCertificates();
118 } catch (IOException e) {
120 } catch (SQLException e) {
122 } catch (InterruptedException e1) {
127 private static void revokeCertificates() throws SQLException, IOException, InterruptedException {
128 ResultSet rs = revoke.executeQuery();
129 boolean worked = false;
131 int id = rs.getInt(1);
132 File crt = KeyStorage.locateCrt(id);
133 String[] call = new String[] {
136 "../unassured.crt",//
138 "../unassured.key",//
140 "../../" + crt.getPath(),//
146 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
147 System.out.println("revoking: " + crt.getPath());
148 if (p1.waitFor() == 0) {
150 revokeCompleted.setInt(1, id);
151 revokeCompleted.execute();
152 finishJob.setInt(1, rs.getInt(3));
155 System.out.println("Failed");
163 private static void gencrl() throws IOException, InterruptedException {
164 String[] call = new String[] {
167 "../unassured.crt",//
169 "../unassured.key",//
174 "../unassured.crl",//
179 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
180 if (p1.waitFor() != 0) {
181 System.out.println("Error while generating crl.");
185 private static int counter = 0;
187 private static void signCertificates() throws SQLException {
188 ResultSet rs = readyCerts.executeQuery();
190 String csrname = rs.getString("csr_name");
191 int id = rs.getInt("id");
192 System.out.println("sign: " + csrname);
194 String csrType = rs.getString("csr_type");
195 CSRType ct = CSRType.valueOf(csrType);
196 File crt = KeyStorage.locateCrt(id);
198 String keyUsage = rs.getString("keyUsage");
199 String ekeyUsage = rs.getString("extendedKeyUsage");
200 java.sql.Date from = rs.getDate("executeFrom");
201 String length = rs.getString("executeTo");
205 fromDate = new Date(System.currentTimeMillis());
207 fromDate = new Date(from.getTime());
209 if (length.endsWith("m") || length.endsWith("y")) {
210 String num = length.substring(0, length.length() - 1);
211 int inter = Integer.parseInt(num);
212 Calendar c = Calendar.getInstance();
213 c.setTimeZone(TimeZone.getTimeZone("UTC"));
215 if (length.endsWith("m")) {
216 c.add(Calendar.MONTH, inter);
218 c.add(Calendar.YEAR, inter);
220 toDate = c.getTime();
222 toDate = CertificateValiditySelector.getDateFormat().parse(length);
224 System.out.println(from);
225 System.out.println(sdf.format(fromDate));
227 getSANSs.setInt(1, id);
228 ResultSet san = getSANSs.executeQuery();
230 File f = new File("keys", "SANFile" + System.currentTimeMillis() + (counter++) + ".cfg");
231 PrintWriter cfg = new PrintWriter(f);
232 boolean first = true;
237 cfg.print("subjectAltName=");
240 cfg.print(san.getString("type"));
242 cfg.print(san.getString("contents"));
245 cfg.println("keyUsage=" + keyUsage);
246 cfg.println("extendedKeyUsage=" + ekeyUsage);
249 String[] call = new String[] {
252 "../../" + csrname,//
254 "../unassured.crt",//
256 "../unassured.key",//
258 "../../" + crt.getPath(),//
261 sdf.format(fromDate),//
263 sdf.format(toDate),//
266 rs.getString("md"),//
268 "../" + f.getName(),//
271 rs.getString("subject"),//
273 "../selfsign.config"//
276 if (ct == CSRType.SPKAC) {
279 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
281 int waitFor = p1.waitFor();
284 try (InputStream is = new FileInputStream(crt)) {
285 CertificateFactory cf = CertificateFactory.getInstance("X.509");
286 X509Certificate crtp = (X509Certificate) cf.generateCertificate(is);
287 BigInteger serial = crtp.getSerialNumber();
288 updateMail.setString(1, crt.getPath());
289 updateMail.setString(2, serial.toString(16));
290 updateMail.setInt(3, id);
291 updateMail.execute();
293 finishJob.setInt(1, rs.getInt("jobid"));
295 System.out.println("signed: " + id);
299 BufferedReader br = new BufferedReader(new InputStreamReader(p1.getErrorStream()));
301 while ((s = br.readLine()) != null) {
302 System.out.println(s);
305 } catch (GeneralSecurityException e) {
307 } catch (IOException e) {
309 } catch (SQLException e) {
311 } catch (ParseException e) {
313 } catch (InterruptedException e1) {
314 e1.printStackTrace();
316 System.out.println("Error with: " + id);
317 warnMail.setInt(1, rs.getInt("jobid"));