]> WPIA git - gigi.git/blob - util/org/cacert/gigi/util/SimpleSigner.java
Merge branch 'issuePeriod'
[gigi.git] / util / org / cacert / gigi / util / SimpleSigner.java
1 package org.cacert.gigi.util;
2
3 import java.io.BufferedReader;
4 import java.io.File;
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;
24
25 import org.cacert.gigi.Certificate.CSRType;
26 import org.cacert.gigi.database.DatabaseConnection;
27 import org.cacert.gigi.output.CertificateValiditySelector;
28
29 public class SimpleSigner {
30
31     private static PreparedStatement warnMail;
32
33     private static PreparedStatement updateMail;
34
35     private static PreparedStatement readyCerts;
36
37     private static PreparedStatement getSANSs;
38
39     private static PreparedStatement revoke;
40
41     private static PreparedStatement revokeCompleted;
42
43     private static PreparedStatement finishJob;
44
45     private static boolean running = true;
46
47     private static Thread runner;
48
49     private static SimpleDateFormat sdf = new SimpleDateFormat("YYMMddHHmmss'Z'");
50
51     static {
52         sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
53     }
54
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);
59
60         runSigner();
61     }
62
63     public synchronized static void stopSigner() throws InterruptedException {
64         if (runner == null) {
65             throw new IllegalStateException("already stopped");
66         }
67         running = false;
68         runner.interrupt();
69         runner.join();
70         runner = null;
71     }
72
73     public synchronized static void runSigner() throws SQLException, IOException, InterruptedException {
74         if (runner != null) {
75             throw new IllegalStateException("already running");
76         }
77         running = true;
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' "//
82                 + "AND task='sign'");
83
84         getSANSs = DatabaseConnection.getInstance().prepare("SELECT contents, type FROM subjectAlternativeNames " + //
85                 "WHERE certId=?");
86
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=?");
89
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=?");
92
93         finishJob = DatabaseConnection.getInstance().prepare("UPDATE jobs SET state='done' WHERE id=?");
94
95         runner = new Thread() {
96
97             @Override
98             public void run() {
99                 work();
100             }
101
102         };
103         runner.start();
104     }
105
106     private static void work() {
107         try {
108             gencrl();
109         } catch (IOException e2) {
110             e2.printStackTrace();
111         } catch (InterruptedException e2) {
112             e2.printStackTrace();
113         }
114         while (running) {
115             try {
116                 signCertificates();
117                 revokeCertificates();
118                 Thread.sleep(5000);
119             } catch (IOException e) {
120                 e.printStackTrace();
121             } catch (SQLException e) {
122                 e.printStackTrace();
123             } catch (InterruptedException e1) {
124             }
125         }
126     }
127
128     private static void revokeCertificates() throws SQLException, IOException, InterruptedException {
129         ResultSet rs = revoke.executeQuery();
130         boolean worked = false;
131         while (rs.next()) {
132             int id = rs.getInt(1);
133             File crt = KeyStorage.locateCrt(id);
134             String[] call = new String[] {
135                     "openssl", "ca",//
136                     "-cert",
137                     "../unassured.crt",//
138                     "-keyfile",
139                     "../unassured.key",//
140                     "-revoke",
141                     "../../" + crt.getPath(),//
142                     "-batch",//
143                     "-config",
144                     "../selfsign.config"
145
146             };
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) {
150                 worked = true;
151                 revokeCompleted.setInt(1, id);
152                 revokeCompleted.execute();
153                 finishJob.setInt(1, rs.getInt(3));
154                 finishJob.execute();
155             } else {
156                 System.out.println("Failed");
157             }
158         }
159         if (worked) {
160             gencrl();
161         }
162     }
163
164     private static void gencrl() throws IOException, InterruptedException {
165         String[] call = new String[] {
166                 "openssl", "ca",//
167                 "-cert",
168                 "../unassured.crt",//
169                 "-keyfile",
170                 "../unassured.key",//
171                 "-gencrl",//
172                 "-crlhours",//
173                 "12",//
174                 "-out",
175                 "../unassured.crl",//
176                 "-config",
177                 "../selfsign.config"
178
179         };
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.");
183         }
184     }
185
186     private static int counter = 0;
187
188     private static void signCertificates() throws SQLException {
189         ResultSet rs = readyCerts.executeQuery();
190         while (rs.next()) {
191             String csrname = rs.getString("csr_name");
192             int id = rs.getInt("id");
193             System.out.println("sign: " + csrname);
194             try {
195                 String csrType = rs.getString("csr_type");
196                 CSRType ct = CSRType.valueOf(csrType);
197                 File crt = KeyStorage.locateCrt(id);
198
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");
203                 Date fromDate;
204                 Date toDate;
205                 if (from == null) {
206                     fromDate = new Date(System.currentTimeMillis());
207                 } else {
208                     fromDate = new Date(from.getTime());
209                 }
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"));
215                     c.setTime(fromDate);
216                     if (length.endsWith("m")) {
217                         c.add(Calendar.MONTH, inter);
218                     } else {
219                         c.add(Calendar.YEAR, inter);
220                     }
221                     toDate = c.getTime();
222                 } else {
223                     toDate = CertificateValiditySelector.getDateFormat().parse(length);
224                 }
225                 System.out.println(from);
226                 System.out.println(sdf.format(fromDate));
227
228                 getSANSs.setInt(1, id);
229                 ResultSet san = getSANSs.executeQuery();
230
231                 File f = new File("keys", "SANFile" + System.currentTimeMillis() + (counter++) + ".cfg");
232                 PrintWriter cfg = new PrintWriter(f);
233                 boolean first = true;
234                 while (san.next()) {
235                     if ( !first) {
236                         cfg.print(", ");
237                     } else {
238                         cfg.print("subjectAltName=");
239                     }
240                     first = false;
241                     cfg.print(san.getString("type"));
242                     cfg.print(":");
243                     cfg.print(san.getString("contents"));
244                 }
245                 cfg.println();
246                 cfg.println("keyUsage=" + keyUsage);
247                 cfg.println("extendedKeyUsage=" + ekeyUsage);
248                 cfg.close();
249
250                 int rootcert = rs.getInt("rootcert");
251                 String ca = "unassured";
252                 if (rootcert == 0) {
253                     ca = "unassured";
254                 } else if (rootcert == 1) {
255                     ca = "assured";
256                 }
257
258                 String[] call = new String[] {
259                         "openssl", "ca",//
260                         "-in",
261                         "../../" + csrname,//
262                         "-cert",
263                         "../" + ca + ".crt",//
264                         "-keyfile",
265                         "../" + ca + ".key",//
266                         "-out",
267                         "../../" + crt.getPath(),//
268                         "-utf8",
269                         "-startdate",
270                         sdf.format(fromDate),//
271                         "-enddate",
272                         sdf.format(toDate),//
273                         "-batch",//
274                         "-md",
275                         rs.getString("md"),//
276                         "-extfile",
277                         "../" + f.getName(),//
278
279                         "-subj",
280                         rs.getString("subject"),//
281                         "-config",
282                         "../selfsign.config"//
283
284                 };
285                 if (ct == CSRType.SPKAC) {
286                     call[2] = "-spkac";
287                 }
288                 Process p1 = Runtime.getRuntime().exec(call, null, new File("keys/unassured.ca"));
289
290                 int waitFor = p1.waitFor();
291                 f.delete();
292                 if (waitFor == 0) {
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();
301
302                         finishJob.setInt(1, rs.getInt("jobid"));
303                         finishJob.execute();
304                         System.out.println("signed: " + id);
305                         continue;
306                     }
307                 } else {
308                     BufferedReader br = new BufferedReader(new InputStreamReader(p1.getErrorStream()));
309                     String s;
310                     while ((s = br.readLine()) != null) {
311                         System.out.println(s);
312                     }
313                 }
314             } catch (GeneralSecurityException e) {
315                 e.printStackTrace();
316             } catch (IOException e) {
317                 e.printStackTrace();
318             } catch (SQLException e) {
319                 e.printStackTrace();
320             } catch (ParseException e) {
321                 e.printStackTrace();
322             } catch (InterruptedException e1) {
323                 e1.printStackTrace();
324             }
325             System.out.println("Error with: " + id);
326             warnMail.setInt(1, rs.getInt("jobid"));
327             warnMail.execute();
328
329         }
330         rs.close();
331     }
332 }