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