]> WPIA git - gigi.git/blob - src/org/cacert/gigi/dbObjects/CACertificate.java
Search for cert-servers at configured domains.
[gigi.git] / src / org / cacert / gigi / dbObjects / CACertificate.java
1 package org.cacert.gigi.dbObjects;
2
3 import java.io.File;
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;
13
14 import javax.security.auth.x500.X500Principal;
15
16 import org.cacert.gigi.database.DatabaseConnection;
17 import org.cacert.gigi.database.GigiPreparedStatement;
18 import org.cacert.gigi.database.GigiResultSet;
19 import org.cacert.gigi.util.ServerConstants;
20
21 public class CACertificate implements IdCachable {
22
23     private final String keyname;
24
25     private final int id;
26
27     private CACertificate parent = null;
28
29     private final X509Certificate cert;
30
31     private final String link;
32
33     private CACertificate(int id) {
34         this.id = id;
35         GigiPreparedStatement conn = DatabaseConnection.getInstance().prepare("SELECT `keyname`, `parentRoot`, `link` FROM `cacerts` WHERE `id`=?");
36         conn.setInt(1, id);
37         GigiResultSet res = conn.executeQuery();
38         if ( !res.next()) {
39             throw new IllegalArgumentException();
40         }
41         keyname = res.getString("keyname");
42         link = res.getString("link");
43         int parentRoot = res.getInt("parentRoot");
44         if (res.next()) {
45             throw new RuntimeException("DB is broken");
46         }
47         if (parentRoot == id) {
48             parent = this;
49         } else {
50             parent = getById(parentRoot);
51         }
52         try {
53             FileInputStream fis = new FileInputStream("config/ca/" + keyname + ".crt");
54             CertificateFactory cf = CertificateFactory.getInstance("X509");
55             cert = (X509Certificate) cf.generateCertificate(fis);
56         } catch (FileNotFoundException e) {
57             throw new Error(e);
58         } catch (GeneralSecurityException e) {
59             throw new Error(e);
60         }
61     }
62
63     public CACertificate getParent() {
64         return parent;
65     }
66
67     public X509Certificate getCertificate() {
68         return cert;
69     }
70
71     @Override
72     public String toString() {
73         return "CACertificate: " + keyname;
74     }
75
76     static {
77         try {
78             update();
79         } catch (CertificateException e) {
80             throw new Error(e);
81         } catch (FileNotFoundException e) {
82             throw new Error(e);
83         }
84     }
85
86     private static void update() throws CertificateException, FileNotFoundException {
87         File scandir = new File("config/ca");
88         CertificateFactory xf = CertificateFactory.getInstance("X509");
89         HashMap<X500Principal, X509Certificate> map = new HashMap<>();
90         HashMap<X500Principal, String> names = new HashMap<>();
91         for (File f : scandir.listFiles()) {
92             X509Certificate cert = (X509Certificate) xf.generateCertificate(new FileInputStream(f));
93             X500Principal princip = cert.getSubjectX500Principal();
94             map.put(princip, cert);
95             String name = f.getName();
96             names.put(princip, name.substring(0, name.length() - 4));
97         }
98         HashMap<X500Principal, Integer> inserted = new HashMap<>();
99         for (X509Certificate i : map.values()) {
100             if (inserted.containsKey(i.getSubjectX500Principal())) {
101                 continue;
102             }
103             Deque<X509Certificate> toInserts = new ArrayDeque<>();
104             toInserts.add(i);
105             while ( !inserted.containsKey(i.getIssuerX500Principal()) && !i.getIssuerX500Principal().equals(i.getSubjectX500Principal())) {
106                 i = map.get(i.getIssuerX500Principal());
107                 toInserts.addFirst(i);
108             }
109             for (X509Certificate toInsert : toInserts) {
110
111                 X500Principal subj = toInsert.getSubjectX500Principal();
112                 boolean self = toInsert.getIssuerX500Principal().equals(subj);
113                 GigiPreparedStatement q = DatabaseConnection.getInstance().prepare("SELECT `id`, `parentRoot` FROM `cacerts` WHERE `keyname`=?");
114                 q.setString(1, names.get(subj));
115                 GigiResultSet res = q.executeQuery();
116                 int id;
117                 if (res.next()) {
118                     id = res.getInt("id");
119                     if (res.getInt("parentRoot") != (self ? id : inserted.get(toInsert.getIssuerX500Principal()))) {
120                         throw new Error("Invalid DB structure: " + subj + "->" + inserted.get(toInsert.getIssuerX500Principal()) + " vs " + res.getInt("parentRoot"));
121                     }
122                 } else {
123                     String link;
124                     String keyname = names.get(subj);
125                     if ( !keyname.contains("_")) {
126                         link = "http://g2.crt." + ServerConstants.getSuffix() + "/g2/" + keyname + ".crt";
127                     } else {
128                         String[] parts = keyname.split("_");
129                         link = "http://g2.crt." + ServerConstants.getSuffix() + "/g2/" + parts[1] + "/" + parts[0] + "-" + parts[2] + ".crt";
130
131                     }
132                     GigiPreparedStatement q2 = DatabaseConnection.getInstance().prepare("INSERT INTO `cacerts` SET `parentRoot`=?, `keyname`=?, `link`=?");
133                     q2.setInt(1, self ? 0 : inserted.get(toInsert.getIssuerX500Principal()));
134                     q2.setString(2, keyname);
135                     q2.setString(3, link);
136                     q2.execute();
137                     id = q2.lastInsertId();
138                     if (self) {
139                         GigiPreparedStatement q3 = DatabaseConnection.getInstance().prepare("UPDATE `cacerts` SET `parentRoot`=?, `id`=?");
140                         q3.setInt(1, id);
141                         q3.setInt(2, id);
142                         q3.execute();
143                     }
144                 }
145                 inserted.put(subj, id);
146             }
147         }
148     }
149
150     @Override
151     public int getId() {
152         return id;
153     }
154
155     private static ObjectCache<CACertificate> myCache = new ObjectCache<>();
156
157     public String getKeyname() {
158         return keyname;
159     }
160
161     public String getLink() {
162         return link;
163     }
164
165     public static synchronized CACertificate getById(int id) throws IllegalArgumentException {
166         CACertificate em = myCache.get(id);
167         if (em == null) {
168             myCache.put(em = new CACertificate(id));
169         }
170         return em;
171     }
172
173     public boolean isSelfsigned() {
174         return this == getParent();
175     }
176
177 }