]> WPIA git - gigi.git/blob - src/org/cacert/gigi/Certificate.java
Show the generated certificate better.
[gigi.git] / src / org / cacert / gigi / Certificate.java
1 package org.cacert.gigi;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.security.GeneralSecurityException;
9 import java.security.cert.CertificateFactory;
10 import java.security.cert.X509Certificate;
11 import java.sql.PreparedStatement;
12 import java.sql.ResultSet;
13 import java.sql.SQLException;
14
15 import org.cacert.gigi.database.DatabaseConnection;
16 import org.cacert.gigi.util.KeyStorage;
17
18 public class Certificate {
19         private int id;
20         private int serial;
21         private String dn;
22         private String md;
23         private String csrName;
24         private String crtName;
25         private String csr = null;
26         public Certificate(String dn, String md, String csr) {
27                 this.dn = dn;
28                 this.md = md;
29                 this.csr = csr;
30         }
31
32         public Certificate(int id) {
33                 try {
34                         PreparedStatement ps = DatabaseConnection
35                                         .getInstance()
36                                         .prepare(
37                                                         "SELECT subject, md, csr_name, crt_name FROM `emailcerts` WHERE id=?");
38                         ps.setInt(1, id);
39                         ResultSet rs = ps.executeQuery();
40                         if (!rs.next()) {
41                                 throw new IllegalArgumentException("Invalid mid " + id);
42                         }
43                         this.id = id;
44                         dn = rs.getString(1);
45                         md = rs.getString(2);
46                         csrName = rs.getString(3);
47                         crtName = rs.getString(4);
48                         rs.close();
49                 } catch (SQLException e) {
50                         e.printStackTrace();
51                 }
52         }
53
54         public enum CertificateStatus {
55                 /**
56                  * This certificate is not in the database, has no id and only exists as
57                  * this java object.
58                  */
59                 DRAFT(false),
60                 /**
61                  * The certificate has been written to the database and is waiting for
62                  * the signer to sign it.
63                  */
64                 SIGNING(true),
65                 /**
66                  * The certificate has been signed. It is stored in the database.
67                  * {@link Certificate#cert()} is valid.
68                  */
69                 ISSUED(false),
70                 /**
71                  * The cetrificate is about to be revoked by the signer bot.
72                  */
73                 BEING_REVOKED(true),
74
75                 /**
76                  * The certificate has been revoked.
77                  */
78                 REVOKED(false),
79
80                 /**
81                  * If this certificate cannot be updated because an error happened in
82                  * the signer.
83                  */
84                 ERROR(false);
85
86                 private boolean unstable;
87
88                 private CertificateStatus(boolean unstable) {
89                         this.unstable = unstable;
90                 }
91                 /**
92                  * Checks, iff this certificate stage will be left by signer actions.
93                  * 
94                  * @return True, iff this certificate stage will be left by signer
95                  *         actions.
96                  */
97                 public boolean isUnstable() {
98                         return unstable;
99                 }
100
101         }
102         public CertificateStatus getStatus() throws SQLException {
103                 if (id == 0) {
104                         return CertificateStatus.DRAFT;
105                 }
106                 PreparedStatement searcher = DatabaseConnection
107                                 .getInstance()
108                                 .prepare(
109                                                 "SELECT crt_name, created, revoked, warning FROM emailcerts WHERE id=?");
110                 searcher.setInt(1, id);
111                 ResultSet rs = searcher.executeQuery();
112                 if (!rs.next()) {
113                         throw new IllegalStateException("Certificate not in Database");
114                 }
115                 if (rs.getInt(4) >= 3) {
116                         return CertificateStatus.ERROR;
117                 }
118
119                 if (rs.getString(2) == null) {
120                         return CertificateStatus.SIGNING;
121                 }
122                 crtName = rs.getString(1);
123                 System.out.println(crtName);
124                 if (rs.getTime(2) != null && rs.getTime(3) == null) {
125                         return CertificateStatus.ISSUED;
126                 }
127                 if (rs.getTime(2) != null
128                                 && rs.getString(3).equals("1970-01-01 00:00:00.0")) {
129                         return CertificateStatus.BEING_REVOKED;
130                 }
131                 return CertificateStatus.REVOKED;
132         }
133
134         public void issue() throws IOException {
135                 try {
136                         if (getStatus() != CertificateStatus.DRAFT) {
137                                 throw new IllegalStateException();
138                         }
139                         PreparedStatement inserter = DatabaseConnection
140                                         .getInstance()
141                                         .prepare(
142                                                         "INSERT INTO emailcerts SET md=?, subject=?, coll_found=0, crt_name=''");
143                         inserter.setString(1, md);
144                         inserter.setString(2, dn);
145                         inserter.execute();
146                         id = DatabaseConnection.lastInsertId(inserter);
147                         File csrFile = KeyStorage.locateCsr(id);
148                         csrName = csrFile.getPath();
149                         FileOutputStream fos = new FileOutputStream(csrFile);
150                         fos.write(csr.getBytes());
151                         fos.close();
152
153                         PreparedStatement updater = DatabaseConnection.getInstance()
154                                         .prepare("UPDATE emailcerts SET csr_name=? WHERE id=?");
155                         updater.setString(1, csrName);
156                         updater.setInt(2, id);
157                         updater.execute();
158                 } catch (SQLException e) {
159                         e.printStackTrace();
160                 }
161
162         }
163         public boolean waitFor(int max) throws SQLException, InterruptedException {
164                 long start = System.currentTimeMillis();
165                 while (getStatus().isUnstable()) {
166                         if (max != 0 && System.currentTimeMillis() - start > max) {
167                                 return false;
168                         }
169                         Thread.sleep((long) (2000 + Math.random() * 2000));
170                 }
171                 return true;
172         }
173         public void revoke() {
174                 try {
175                         if (getStatus() != CertificateStatus.ISSUED) {
176                                 throw new IllegalStateException();
177                         }
178                         PreparedStatement inserter = DatabaseConnection
179                                         .getInstance()
180                                         .prepare(
181                                                         "UPDATE emailcerts SET revoked = '1970-01-01' WHERE id=?");
182                         inserter.setInt(1, id);
183                         inserter.execute();
184                 } catch (SQLException e) {
185                         e.printStackTrace();
186                 }
187
188         }
189
190         public X509Certificate cert() throws IOException, GeneralSecurityException,
191                         SQLException {
192                 CertificateStatus status = getStatus();
193                 if (status != CertificateStatus.ISSUED) {
194                         throw new IllegalStateException(status + " is not wanted here.");
195                 }
196                 InputStream is = null;
197                 X509Certificate crt = null;
198                 try {
199                         is = new FileInputStream(crtName);
200                         CertificateFactory cf = CertificateFactory.getInstance("X.509");
201                         crt = (X509Certificate) cf.generateCertificate(is);
202                 } finally {
203                         if (is != null) {
204                                 is.close();
205                         }
206                 }
207                 return crt;
208         }
209         public Certificate renew() {
210                 return null;
211         }
212         public int getId() {
213                 return id;
214         }
215         public int getSerial() {
216                 return serial;
217         }
218         public String getDistinguishedName() {
219                 return dn;
220         }
221         public String getMessageDigest() {
222                 return md;
223         }
224
225 }