1 package org.cacert.gigi.dbObjects;
4 import java.io.FileInputStream;
5 import java.io.FileNotFoundException;
6 import java.security.GeneralSecurityException;
7 import java.security.cert.CertificateException;
8 import java.security.cert.CertificateFactory;
9 import java.security.cert.X509Certificate;
10 import java.util.ArrayDeque;
11 import java.util.Deque;
12 import java.util.HashMap;
14 import javax.security.auth.x500.X500Principal;
16 import org.cacert.gigi.database.DatabaseConnection;
17 import org.cacert.gigi.database.GigiPreparedStatement;
18 import org.cacert.gigi.database.GigiResultSet;
20 public class CACertificate implements IdCachable {
26 CACertificate parent = null;
28 final X509Certificate cert;
32 private CACertificate(int id) {
34 GigiPreparedStatement conn = DatabaseConnection.getInstance().prepare("SELECT keyname, parentRoot, link FROM cacerts WHERE id = ?");
36 GigiResultSet res = conn.executeQuery();
38 throw new IllegalArgumentException();
40 keyname = res.getString("keyname");
41 link = res.getString("link");
42 int parentRoot = res.getInt("parentRoot");
44 throw new RuntimeException("DB is broken");
46 if (parentRoot == id) {
49 parent = getById(parentRoot);
52 FileInputStream fis = new FileInputStream("config/ca/" + keyname + ".crt");
53 CertificateFactory cf = CertificateFactory.getInstance("X509");
54 cert = (X509Certificate) cf.generateCertificate(fis);
55 } catch (FileNotFoundException e) {
57 } catch (GeneralSecurityException e) {
62 public CACertificate getParent() {
66 public X509Certificate getCertificate() {
71 public String toString() {
72 return "CACertificate: " + keyname;
78 } catch (CertificateException e) {
80 } catch (FileNotFoundException e) {
85 private static void update() throws CertificateException, FileNotFoundException {
86 File scandir = new File("config/ca");
87 CertificateFactory xf = CertificateFactory.getInstance("X509");
88 HashMap<X500Principal, X509Certificate> map = new HashMap<>();
89 HashMap<X500Principal, String> names = new HashMap<>();
90 for (File f : scandir.listFiles()) {
91 X509Certificate cert = (X509Certificate) xf.generateCertificate(new FileInputStream(f));
92 X500Principal princip = cert.getSubjectX500Principal();
93 map.put(princip, cert);
94 String name = f.getName();
95 names.put(princip, name.substring(0, name.length() - 4));
97 HashMap<X500Principal, Integer> inserted = new HashMap<>();
98 for (X509Certificate i : map.values()) {
99 if (inserted.containsKey(i.getSubjectX500Principal())) {
102 Deque<X509Certificate> toInserts = new ArrayDeque<>();
104 while ( !inserted.containsKey(i.getIssuerX500Principal()) && !i.getIssuerX500Principal().equals(i.getSubjectX500Principal())) {
105 i = map.get(i.getIssuerX500Principal());
106 toInserts.addFirst(i);
108 for (X509Certificate toInsert : toInserts) {
110 X500Principal subj = toInsert.getSubjectX500Principal();
111 boolean self = toInsert.getIssuerX500Principal().equals(subj);
112 GigiPreparedStatement q = DatabaseConnection.getInstance().prepare("SELECT id, parentRoot FROM cacerts WHERE keyname=?");
113 q.setString(1, names.get(subj));
114 GigiResultSet res = q.executeQuery();
117 id = res.getInt("id");
118 if (res.getInt("parentRoot") != (self ? id : inserted.get(toInsert.getIssuerX500Principal()))) {
119 throw new Error("Invalid DB structure: " + subj + "->" + inserted.get(toInsert.getIssuerX500Principal()) + " vs " + res.getInt("parentRoot"));
123 String keyname = names.get(subj);
124 if ( !keyname.contains("_")) {
125 link = "http://g2.crt.cacert.org/g2/" + keyname + ".crt";
127 String[] parts = keyname.split("_");
128 link = "http://g2.crt.cacert.org/g2/" + parts[1] + "/" + parts[0] + "-" + parts[2] + ".crt";
131 GigiPreparedStatement q2 = DatabaseConnection.getInstance().prepare("INSERT INTO cacerts SET parentRoot=?, keyname=?, link=?");
132 q2.setInt(1, self ? 0 : inserted.get(toInsert.getIssuerX500Principal()));
133 q2.setString(2, keyname);
134 q2.setString(3, link);
136 id = q2.lastInsertId();
138 GigiPreparedStatement q3 = DatabaseConnection.getInstance().prepare("UPDATE cacerts SET parentRoot=?, id=?");
144 inserted.put(subj, id);
154 private static ObjectCache<CACertificate> myCache = new ObjectCache<>();
156 public String getKeyname() {
160 public String getLink() {
164 public static synchronized CACertificate getById(int id) throws IllegalArgumentException {
165 CACertificate em = myCache.get(id);
167 myCache.put(em = new CACertificate(id));
172 public boolean isSelfsigned() {
173 return this == getParent();