1 package org.cacert.gigi.dbObjects;
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;
11 import java.util.Properties;
13 import org.cacert.gigi.database.DatabaseConnection;
14 import org.cacert.gigi.database.GigiPreparedStatement;
15 import org.cacert.gigi.database.GigiResultSet;
17 public class CertificateProfile implements IdCachable {
21 private final String keyName;
23 private final String visibleName;
25 private static final Map<String, CertificateProfile> byName;
27 private static final Map<Integer, CertificateProfile> byId;
29 private final Map<String, PropertyTemplate> pt;
31 private final List<String> req;
33 private CertificateProfile(int id, String keyName, String visibleName, String requires, String include) {
35 this.keyName = keyName;
36 this.visibleName = visibleName;
37 req = parseConditions(requires);
38 pt = parsePropertyTemplates(include);
41 public static class PropertyTemplate implements Comparable<PropertyTemplate> {
43 private boolean required = true;
45 private boolean multiple = false;
49 public PropertyTemplate(String inc) {
50 if (inc.endsWith("?") || inc.endsWith("*") || inc.endsWith("+")) {
51 char sfx = inc.charAt(inc.length() - 1);
54 } else if (sfx == '*') {
60 inc = inc.substring(0, inc.length() - 1);
65 public String getBase() {
69 public boolean isMultiple() {
73 public boolean isRequired() {
78 public int hashCode() {
81 result = prime * result + ((base == null) ? 0 : base.hashCode());
82 result = prime * result + (multiple ? 1231 : 1237);
83 result = prime * result + (required ? 1231 : 1237);
88 public boolean equals(Object obj) {
95 if (getClass() != obj.getClass()) {
98 PropertyTemplate other = (PropertyTemplate) obj;
100 if (other.base != null) {
103 } else if ( !base.equals(other.base)) {
106 if (multiple != other.multiple) {
109 if (required != other.required) {
116 public String toString() {
117 return base + (multiple ? (required ? "+" : "*") : (required ? "" : "?"));
121 public int compareTo(PropertyTemplate o) {
122 return toString().compareTo(o.toString());
127 private CertificateProfile(File f) throws IOException {
128 Properties p = new Properties();
129 try (FileInputStream inStream = new FileInputStream(f)) {
132 String[] parts = f.getName().split("\\.")[0].split("-", 2);
133 id = Integer.parseInt(parts[0]);
136 pt = parsePropertyTemplates(p.getProperty("include"));
137 req = parseConditions(p.getProperty("requires", ""));
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];
145 return Collections.unmodifiableList(Arrays.asList(split2));
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++) {
153 PropertyTemplate value = new PropertyTemplate(split[i]);
155 map.put(value.getBase(), value);
157 return Collections.unmodifiableMap(map);
164 public String getKeyName() {
168 public String getVisibleName() {
172 public Map<String, PropertyTemplate> getTemplates() {
176 public List<String> getReqireds() {
181 final HashMap<String, CertificateProfile> myName = new HashMap<String, CertificateProfile>();
182 final HashMap<Integer, CertificateProfile> myId = new HashMap<Integer, CertificateProfile>();
184 for (File f : new File("config/profiles").listFiles()) {
185 Properties p = new Properties();
186 try (FileInputStream inStream = new FileInputStream(f)) {
188 } catch (IOException e) {
189 throw new Error("Unable to load profile from " + f.getName(), e);
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();
198 if ( !rs.getString("keyname").equals(parts[1])) {
199 throw new Error("Config error. Certificate Profile mismatch");
201 if ( !rs.getString("include").equals(p.getProperty("include"))) {
202 throw new Error("Config error. Certificate Profile mismatch");
204 if ( !rs.getString("requires").equals(p.getProperty("requires", ""))) {
205 throw new Error("Config error. Certificate Profile mismatch");
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]));
218 GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT `id`, `keyname`, `name`, `requires`, `include` FROM `profiles`");
219 GigiResultSet rs = ps.executeQuery();
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);
226 byName = Collections.unmodifiableMap(myName);
227 byId = Collections.unmodifiableMap(myId);
230 public static CertificateProfile getById(int id) {
234 public static CertificateProfile getByName(String name) {
235 return byName.get(name);
238 public static CertificateProfile[] getAll() {
239 return byId.values().toArray(new CertificateProfile[byId.size()]);
242 public boolean canBeIssuedBy(CertificateOwner owner, User actor) {
243 if (pt.containsKey("orga")) {
244 if ( !(owner instanceof Organisation)) {
248 if (owner instanceof Organisation) {
252 for (String s : req) {
253 if (s.equals("points>=50")) {
254 if (actor.getAssurancePoints() < 50) {
257 } else if (s.equals("points>=100")) {
258 if (actor.getAssurancePoints() < 100) {
261 } else if (s.equals("codesign")) {
262 if (actor.isInGroup(Group.CODESIGNING)) {