]> WPIA git - gigi.git/blob - src/org/cacert/gigi/Certificate.java
New Signer Job Table.
[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.Job;
17 import org.cacert.gigi.util.Job.JobType;
18 import org.cacert.gigi.util.KeyStorage;
19 import org.cacert.gigi.util.Notary;
20
21 public class Certificate {
22         private int id;
23         private int ownerId;
24         private String serial;
25         private String dn;
26         private String md;
27         private String csrName;
28         private String crtName;
29         private String csr = null;
30
31         public Certificate(int ownerId, String dn, String md, String csr) {
32                 this.ownerId = ownerId;
33                 this.dn = dn;
34                 this.md = md;
35                 this.csr = csr;
36         }
37
38         private Certificate(String serial) {
39                 try {
40                         PreparedStatement ps = DatabaseConnection.getInstance().prepare(
41                                 "SELECT id,subject, md, csr_name, crt_name,memid FROM `emailcerts` WHERE serial=?");
42                         ps.setString(1, serial);
43                         ResultSet rs = ps.executeQuery();
44                         if (!rs.next()) {
45                                 throw new IllegalArgumentException("Invalid mid " + serial);
46                         }
47                         this.id = rs.getInt(1);
48                         dn = rs.getString(2);
49                         md = rs.getString(3);
50                         csrName = rs.getString(4);
51                         crtName = rs.getString(5);
52                         ownerId = rs.getInt(6);
53                         this.serial = serial;
54                         rs.close();
55                 } catch (SQLException e) {
56                         e.printStackTrace();
57                 }
58         }
59
60         public enum CertificateStatus {
61                 /**
62                  * This certificate is not in the database, has no id and only exists as
63                  * this java object.
64                  */
65                 DRAFT(),
66                 /**
67                  * The certificate has been signed. It is stored in the database.
68                  * {@link Certificate#cert()} is valid.
69                  */
70                 ISSUED(),
71
72                 /**
73                  * The certificate has been revoked.
74                  */
75                 REVOKED(),
76
77                 /**
78                  * If this certificate cannot be updated because an error happened in
79                  * the signer.
80                  */
81                 ERROR();
82
83                 private CertificateStatus() {
84                 }
85
86         }
87
88         public CertificateStatus getStatus() throws SQLException {
89                 if (id == 0) {
90                         return CertificateStatus.DRAFT;
91                 }
92                 PreparedStatement searcher = DatabaseConnection.getInstance().prepare(
93                         "SELECT crt_name, created, revoked, serial FROM emailcerts WHERE id=?");
94                 searcher.setInt(1, id);
95                 ResultSet rs = searcher.executeQuery();
96                 if (!rs.next()) {
97                         throw new IllegalStateException("Certificate not in Database");
98                 }
99
100                 crtName = rs.getString(1);
101                 serial = rs.getString(4);
102                 if (rs.getTime(2) == null) {
103                         return CertificateStatus.DRAFT;
104                 }
105                 if (rs.getTime(2) != null && rs.getTime(3) == null) {
106                         return CertificateStatus.ISSUED;
107                 }
108                 return CertificateStatus.REVOKED;
109         }
110
111         public Job issue() throws IOException, SQLException {
112                 if (getStatus() != CertificateStatus.DRAFT) {
113                         throw new IllegalStateException();
114                 }
115                 Notary.writeUserAgreement(ownerId, "CCA", "issue certificate", "", true, 0);
116
117                 PreparedStatement inserter = DatabaseConnection.getInstance().prepare(
118                         "INSERT INTO emailcerts SET md=?, subject=?, crt_name='', memid=?");
119                 inserter.setString(1, md);
120                 inserter.setString(2, dn);
121                 inserter.setInt(3, ownerId);
122                 inserter.execute();
123                 id = DatabaseConnection.lastInsertId(inserter);
124                 File csrFile = KeyStorage.locateCsr(id);
125                 csrName = csrFile.getPath();
126                 FileOutputStream fos = new FileOutputStream(csrFile);
127                 fos.write(csr.getBytes());
128                 fos.close();
129
130                 PreparedStatement updater = DatabaseConnection.getInstance().prepare(
131                         "UPDATE emailcerts SET csr_name=? WHERE id=?");
132                 updater.setString(1, csrName);
133                 updater.setInt(2, id);
134                 updater.execute();
135                 return Job.submit(this, JobType.SIGN);
136
137         }
138
139         public Job revoke() throws SQLException {
140                 if (getStatus() != CertificateStatus.ISSUED) {
141                         throw new IllegalStateException();
142                 }
143                 return Job.submit(this, JobType.REVOKE);
144
145         }
146
147         public X509Certificate cert() throws IOException, GeneralSecurityException, SQLException {
148                 CertificateStatus status = getStatus();
149                 if (status != CertificateStatus.ISSUED) {
150                         throw new IllegalStateException(status + " is not wanted here.");
151                 }
152                 InputStream is = null;
153                 X509Certificate crt = null;
154                 try {
155                         is = new FileInputStream(crtName);
156                         CertificateFactory cf = CertificateFactory.getInstance("X.509");
157                         crt = (X509Certificate) cf.generateCertificate(is);
158                 } finally {
159                         if (is != null) {
160                                 is.close();
161                         }
162                 }
163                 return crt;
164         }
165
166         public Certificate renew() {
167                 return null;
168         }
169
170         public int getId() {
171                 return id;
172         }
173
174         public String getSerial() {
175                 return serial;
176         }
177
178         public String getDistinguishedName() {
179                 return dn;
180         }
181
182         public String getMessageDigest() {
183                 return md;
184         }
185
186         public int getOwnerId() {
187                 return ownerId;
188         }
189
190         public static Certificate getBySerial(String serial) {
191                 // TODO caching?
192                 try {
193                         return new Certificate(serial);
194                 } catch (IllegalArgumentException e) {
195
196                 }
197                 return null;
198         }
199
200 }