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