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