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'");
52 sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
55 public static void main(String[] args) throws IOException, SQLException, InterruptedException {
56 Properties p = new Properties();
57 p.load(new FileReader("config/gigi.properties"));
58 DatabaseConnection.init(p);
63 public synchronized static void stopSigner() throws InterruptedException {
65 throw new IllegalStateException("already stopped");
73 public synchronized static void runSigner() throws SQLException, IOException, InterruptedException {
75 throw new IllegalStateException("already running");
78 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, rootcert FROM jobs " + //
79 "INNER JOIN certs ON certs.id=jobs.targetId " + //
80 "INNER JOIN profiles ON profiles.id=certs.profile " + //
81 "WHERE jobs.state='open' "//
84 getSANSs = DatabaseConnection.getInstance().prepare("SELECT contents, type FROM subjectAlternativeNames " + //
87 updateMail = DatabaseConnection.getInstance().prepare("UPDATE certs SET crt_name=?," + " created=NOW(), serial=? WHERE id=?");
88 warnMail = DatabaseConnection.getInstance().prepare("UPDATE jobs SET warning=warning+1, state=IF(warning<3, 'open','error') WHERE id=?");
90 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'");
91 revokeCompleted = DatabaseConnection.getInstance().prepare("UPDATE certs SET revoked=NOW() WHERE id=?");
93 finishJob = DatabaseConnection.getInstance().prepare("UPDATE jobs SET state='done' WHERE id=?");
95 runner = new Thread() {
106 private static void work() {
109 } catch (IOException e2) {
110 e2.printStackTrace();
111 } catch (InterruptedException e2) {
112 e2.printStackTrace();
117 revokeCertificates();
119 } catch (IOException e) {
121 } catch (SQLException e) {
123 } catch (InterruptedException e1) {
128 private static void revokeCertificates() throws SQLException, IOException, InterruptedException {
129 ResultSet rs = revoke.executeQuery();
130 boolean worked = false;
132 int id = rs.getInt(1);
133 File crt = KeyStorage.locateCrt(id);
134 String[] call = new String[] {
137 "../unassured.crt",//
139 "../unassured.key",//
141 "../../" + crt.getPath(),//
147 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
148 System.out.println("revoking: " + crt.getPath());
149 if (p1.waitFor() == 0) {
151 revokeCompleted.setInt(1, id);
152 revokeCompleted.execute();
153 finishJob.setInt(1, rs.getInt(3));
156 System.out.println("Failed");
164 private static void gencrl() throws IOException, InterruptedException {
165 String[] call = new String[] {
168 "../unassured.crt",//
170 "../unassured.key",//
175 "../unassured.crl",//
180 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
181 if (p1.waitFor() != 0) {
182 System.out.println("Error while generating crl.");
186 private static int counter = 0;
188 private static void signCertificates() throws SQLException {
189 ResultSet rs = readyCerts.executeQuery();
191 String csrname = rs.getString("csr_name");
192 int id = rs.getInt("id");
193 System.out.println("sign: " + csrname);
195 String csrType = rs.getString("csr_type");
196 CSRType ct = CSRType.valueOf(csrType);
197 File crt = KeyStorage.locateCrt(id);
199 String keyUsage = rs.getString("keyUsage");
200 String ekeyUsage = rs.getString("extendedKeyUsage");
201 java.sql.Date from = rs.getDate("executeFrom");
202 String length = rs.getString("executeTo");
206 fromDate = new Date(System.currentTimeMillis());
208 fromDate = new Date(from.getTime());
210 if (length.endsWith("m") || length.endsWith("y")) {
211 String num = length.substring(0, length.length() - 1);
212 int inter = Integer.parseInt(num);
213 Calendar c = Calendar.getInstance();
214 c.setTimeZone(TimeZone.getTimeZone("UTC"));
216 if (length.endsWith("m")) {
217 c.add(Calendar.MONTH, inter);
219 c.add(Calendar.YEAR, inter);
221 toDate = c.getTime();
223 toDate = CertificateValiditySelector.getDateFormat().parse(length);
225 System.out.println(from);
226 System.out.println(sdf.format(fromDate));
228 getSANSs.setInt(1, id);
229 ResultSet san = getSANSs.executeQuery();
231 File f = new File("keys", "SANFile" + System.currentTimeMillis() + (counter++) + ".cfg");
232 PrintWriter cfg = new PrintWriter(f);
233 boolean first = true;
238 cfg.print("subjectAltName=");
241 cfg.print(san.getString("type"));
243 cfg.print(san.getString("contents"));
246 cfg.println("keyUsage=" + keyUsage);
247 cfg.println("extendedKeyUsage=" + ekeyUsage);
250 int rootcert = rs.getInt("rootcert");
251 String ca = "unassured";
254 } else if (rootcert == 1) {
258 String[] call = new String[] {
261 "../../" + csrname,//
263 "../" + ca + ".crt",//
265 "../" + ca + ".key",//
267 "../../" + crt.getPath(),//
270 sdf.format(fromDate),//
272 sdf.format(toDate),//
275 rs.getString("md"),//
277 "../" + f.getName(),//
280 rs.getString("subject"),//
282 "../selfsign.config"//
285 if (ct == CSRType.SPKAC) {
288 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
290 int waitFor = p1.waitFor();
293 try (InputStream is = new FileInputStream(crt)) {
294 CertificateFactory cf = CertificateFactory.getInstance("X.509");
295 X509Certificate crtp = (X509Certificate) cf.generateCertificate(is);
296 BigInteger serial = crtp.getSerialNumber();
297 updateMail.setString(1, crt.getPath());
298 updateMail.setString(2, serial.toString(16));
299 updateMail.setInt(3, id);
300 updateMail.execute();
302 finishJob.setInt(1, rs.getInt("jobid"));
304 System.out.println("signed: " + id);
308 BufferedReader br = new BufferedReader(new InputStreamReader(p1.getErrorStream()));
310 while ((s = br.readLine()) != null) {
311 System.out.println(s);
314 } catch (GeneralSecurityException e) {
316 } catch (IOException e) {
318 } catch (SQLException e) {
320 } catch (ParseException e) {
322 } catch (InterruptedException e1) {
323 e1.printStackTrace();
325 System.out.println("Error with: " + id);
326 warnMail.setInt(1, rs.getInt("jobid"));