]> WPIA git - gigi.git/blob - src/org/cacert/gigi/Certificate.java
Merge remote-tracking branch 'origin/emailMgmt'
[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                 inserter.setString(2, dn);
127                 inserter.setString(3, csrType.toString());
128                 inserter.setInt(4, ownerId);
129                 inserter.execute();
130                 id = DatabaseConnection.lastInsertId(inserter);
131                 File csrFile = KeyStorage.locateCsr(id);
132                 csrName = csrFile.getPath();
133                 FileOutputStream fos = new FileOutputStream(csrFile);
134                 fos.write(csr.getBytes());
135                 fos.close();
136
137                 PreparedStatement updater = DatabaseConnection.getInstance().prepare(
138                         "UPDATE emailcerts SET csr_name=? WHERE id=?");
139                 updater.setString(1, csrName);
140                 updater.setInt(2, id);
141                 updater.execute();
142                 return Job.submit(this, JobType.SIGN);
143
144         }
145
146         public Job revoke() throws SQLException {
147                 if (getStatus() != CertificateStatus.ISSUED) {
148                         throw new IllegalStateException();
149                 }
150                 return Job.submit(this, JobType.REVOKE);
151
152         }
153
154         public X509Certificate cert() throws IOException, GeneralSecurityException, SQLException {
155                 CertificateStatus status = getStatus();
156                 if (status != CertificateStatus.ISSUED) {
157                         throw new IllegalStateException(status + " is not wanted here.");
158                 }
159                 InputStream is = null;
160                 X509Certificate crt = null;
161                 try {
162                         is = new FileInputStream(crtName);
163                         CertificateFactory cf = CertificateFactory.getInstance("X.509");
164                         crt = (X509Certificate) cf.generateCertificate(is);
165                 } finally {
166                         if (is != null) {
167                                 is.close();
168                         }
169                 }
170                 return crt;
171         }
172
173         public Certificate renew() {
174                 return null;
175         }
176
177         public int getId() {
178                 return id;
179         }
180
181         public String getSerial() {
182                 try {
183                         getStatus();
184                 } catch (SQLException e) {
185                         e.printStackTrace();
186                 } // poll changes
187                 return serial;
188         }
189
190         public String getDistinguishedName() {
191                 return dn;
192         }
193
194         public String getMessageDigest() {
195                 return md;
196         }
197
198         public int getOwnerId() {
199                 return ownerId;
200         }
201
202         public static Certificate getBySerial(String serial) {
203                 // TODO caching?
204                 try {
205                         return new Certificate(serial);
206                 } catch (IllegalArgumentException e) {
207
208                 }
209                 return null;
210         }
211
212 }