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