]> WPIA git - gigi.git/blob - src/org/cacert/gigi/dbObjects/CertificateProfile.java
add: cert-profile loading from config
[gigi.git] / src / org / cacert / gigi / dbObjects / CertificateProfile.java
1 package org.cacert.gigi.dbObjects;
2
3 import java.awt.Desktop;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.PrintWriter;
8 import java.util.Arrays;
9 import java.util.HashMap;
10 import java.util.LinkedList;
11 import java.util.Properties;
12 import java.util.TreeSet;
13
14 import org.cacert.gigi.database.DatabaseConnection;
15 import org.cacert.gigi.database.GigiPreparedStatement;
16 import org.cacert.gigi.database.GigiResultSet;
17
18 public class CertificateProfile {
19
20     private final int id;
21
22     private final String keyName;
23
24     private final String visibleName;
25
26     private static HashMap<String, CertificateProfile> byName = new HashMap<>();
27
28     private static HashMap<Integer, CertificateProfile> byId = new HashMap<>();
29
30     private final PropertyTemplate[] pt;
31
32     private final String[] req;
33
34     private CertificateProfile(int id, String keyName, String visibleName, String requires, String include) {
35         this.id = id;
36         this.keyName = keyName;
37         this.visibleName = visibleName;
38         req = parseConditions(requires);
39         pt = parsePropertyTemplates(include);
40     }
41
42     private static class PropertyTemplate implements Comparable<PropertyTemplate> {
43
44         boolean required = true;
45
46         boolean multiple = false;
47
48         private String inc;
49
50         public PropertyTemplate(String inc) {
51             if (inc.endsWith("?") || inc.endsWith("*") || inc.endsWith("+")) {
52                 char sfx = inc.charAt(inc.length() - 1);
53                 if (sfx == '?') {
54                     required = false;
55                 } else if (sfx == '*') {
56                     multiple = true;
57                     required = false;
58                 } else {
59                     multiple = true;
60                 }
61                 inc = inc.substring(0, inc.length() - 1);
62             }
63             this.inc = inc;
64         }
65
66         @Override
67         public int hashCode() {
68             final int prime = 31;
69             int result = 1;
70             result = prime * result + ((inc == null) ? 0 : inc.hashCode());
71             result = prime * result + (multiple ? 1231 : 1237);
72             result = prime * result + (required ? 1231 : 1237);
73             return result;
74         }
75
76         @Override
77         public boolean equals(Object obj) {
78             if (this == obj) {
79                 return true;
80             }
81             if (obj == null) {
82                 return false;
83             }
84             if (getClass() != obj.getClass()) {
85                 return false;
86             }
87             PropertyTemplate other = (PropertyTemplate) obj;
88             if (inc == null) {
89                 if (other.inc != null) {
90                     return false;
91                 }
92             } else if ( !inc.equals(other.inc)) {
93                 return false;
94             }
95             if (multiple != other.multiple) {
96                 return false;
97             }
98             if (required != other.required) {
99                 return false;
100             }
101             return true;
102         }
103
104         @Override
105         public String toString() {
106             return inc + (multiple ? (required ? "+" : "*") : (required ? "" : "?"));
107         }
108
109         @Override
110         public int compareTo(PropertyTemplate o) {
111             return toString().compareTo(o.toString());
112         }
113
114     }
115
116     private CertificateProfile(File f) throws IOException {
117         Properties p = new Properties();
118         p.load(new FileInputStream(f));
119         String[] parts = f.getName().split("\\.")[0].split("-", 2);
120         id = Integer.parseInt(parts[0]);
121         keyName = parts[1];
122         visibleName = "";
123         pt = parsePropertyTemplates(p.getProperty("include"));
124         req = parseConditions(p.getProperty("requires", ""));
125     }
126
127     private String[] parseConditions(String property) {
128         String[] split2 = property.split(",");
129         if (split2.length == 1 && split2[0].equals("")) {
130             split2 = new String[0];
131         }
132         return split2;
133     }
134
135     private PropertyTemplate[] parsePropertyTemplates(String property) {
136         String[] split = property.split(",");
137         PropertyTemplate[] pt = new PropertyTemplate[split.length];
138         for (int i = 0; i < split.length; i++) {
139             pt[i] = new PropertyTemplate(split[i]);
140         }
141         return pt;
142     }
143
144     public int getId() {
145         return id;
146     }
147
148     public String getKeyName() {
149         return keyName;
150     }
151
152     public String getVisibleName() {
153         return visibleName;
154     }
155
156     static {
157         for (File f : new File("config/profiles").listFiles()) {
158             Properties p = new Properties();
159             try {
160                 p.load(new FileInputStream(f));
161             } catch (IOException e) {
162                 e.printStackTrace();
163             }
164             String[] parts = f.getName().split("\\.")[0].split("-", 2);
165             GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT keyname, include, requires, name FROM `profiles` WHERE id=?");
166             ps.setInt(1, Integer.parseInt(parts[0]));
167             GigiResultSet rs = ps.executeQuery();
168
169             if (rs.next()) {
170                 if ( !rs.getString("keyname").equals(parts[1])) {
171                     throw new Error("Config error. Certificate Profile mismatch");
172                 }
173                 if ( !rs.getString("include").equals(p.getProperty("include"))) {
174                     throw new Error("Config error. Certificate Profile mismatch");
175                 }
176                 if ( !rs.getString("requires").equals(p.getProperty("requires", ""))) {
177                     throw new Error("Config error. Certificate Profile mismatch");
178                 }
179             } else {
180                 GigiPreparedStatement insert = DatabaseConnection.getInstance().prepare("INSERT INTO `profiles` SET keyname=?, include=?, requires=?, name=?, id=?");
181                 insert.setString(1, parts[1]);
182                 insert.setString(2, p.getProperty("include"));
183                 insert.setString(3, p.getProperty("requires", ""));
184                 insert.setString(4, p.getProperty("name"));
185                 insert.setInt(5, Integer.parseInt(parts[0]));
186                 insert.execute();
187             }
188
189         }
190         GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id, keyname, name, requires, include FROM `profiles`");
191         GigiResultSet rs = ps.executeQuery();
192         while (rs.next()) {
193             CertificateProfile cp = new CertificateProfile(rs.getInt("id"), rs.getString("keyName"), rs.getString("name"), rs.getString("requires"), rs.getString("include"));
194             byId.put(cp.getId(), cp);
195             byName.put(cp.getKeyName(), cp);
196         }
197
198     }
199
200     public static CertificateProfile getById(int id) {
201         return byId.get(id);
202     }
203
204     public static CertificateProfile getByName(String name) {
205         return byName.get(name);
206     }
207
208     public static CertificateProfile[] getAll() {
209         return byId.values().toArray(new CertificateProfile[byId.size()]);
210     }
211
212     public static void main(String[] args) throws IOException {
213         TreeSet<String> pt = new TreeSet<>();
214         TreeSet<String> req = new TreeSet<>();
215         LinkedList<CertificateProfile> cps = new LinkedList<>();
216         for (CertificateProfile cp : byId.values()) {
217             cps.add(cp);
218             for (PropertyTemplate p : cp.pt) {
219                 pt.add(p.inc);
220             }
221             req.addAll(Arrays.asList(cp.req));
222         }
223         PrintWriter pw = new PrintWriter("profiles.html");
224         pw.println("<!DOCTYPE html><html><head><title>Profiles</title>");
225         pw.println("<style>.split{background-color:#000;margin:0;cell-spacing:0}td{text-align:center}</style>");
226         pw.println("</head>");
227         pw.println("<body><table border='1'>");
228         pw.println("<tr><td>id</td><td> </td>");
229         for (String p : pt) {
230             pw.println("<th>" + p + "</th>");
231         }
232         pw.println("<th class='split'></th>");
233         for (String p : req) {
234             pw.println("<th class='req'>" + p + "</th>");
235         }
236         pw.println("</tr>");
237         for (CertificateProfile certificateProfile : cps) {
238             pw.println("<tr>");
239             pw.println("<td>" + certificateProfile.id + "</td>");
240             pw.println("<td>" + certificateProfile.keyName + "</td>");
241             outer:
242             for (String p : pt) {
243                 for (PropertyTemplate t : certificateProfile.pt) {
244                     if (t.inc.equals(p)) {
245                         pw.println("<td>" + (t.required ? (t.multiple ? "+" : "y") : (t.multiple ? "*" : "?")) + "</td>");
246                         continue outer;
247                     }
248                 }
249                 pw.println("<td></td>");
250             }
251             pw.println("<td class='split'></td>");
252             outer:
253             for (String p : req) {
254                 for (String t : certificateProfile.req) {
255                     if (t.equals(p)) {
256                         pw.println("<td class='req'>y</td>");
257                         continue outer;
258                     }
259                 }
260                 pw.println("<td></td>");
261             }
262             pw.println("</tr>");
263         }
264         pw.println("</table></body></html>");
265         Desktop.getDesktop().browse(new File("profiles.html").toURI());
266         pw.close();
267     }
268
269     public boolean canBeIssuedBy(User u) {
270         for (String s : req) {
271             if (s.equals("points>=50")) {
272                 if (u.getAssurancePoints() < 50) {
273                     return false;
274                 }
275             } else if (s.equals("points>=100")) {
276                 if (u.getAssurancePoints() < 100) {
277                     return false;
278                 }
279             } else if (s.equals("codesign")) {
280                 if (u.isInGroup(Group.CODESIGNING)) {
281                     return false;
282                 }
283             } else {
284                 return false;
285             }
286
287         }
288         return true;
289     }
290 }