package org.cacert.gigi.dbObjects;
import org.cacert.gigi.database.GigiResultSet;
+import org.cacert.gigi.dbObjects.wrappers.DataContainer;
+@DataContainer
public class Assurance {
public enum AssuranceType {
import org.cacert.gigi.util.KeyStorage;
import org.cacert.gigi.util.Notary;
-public class Certificate {
+public class Certificate implements IdCachable {
public enum SANType {
EMAIL("email"), DNS("DNS");
private CACertificate ca;
- public Certificate(User owner, HashMap<String, String> dn, String md, String csr, CSRType csrType, CertificateProfile profile, SubjectAlternateName... sans) throws GigiApiException {
+ public Certificate(User owner, HashMap<String, String> dn, String md, String csr, CSRType csrType, CertificateProfile profile, SubjectAlternateName... sans) throws GigiApiException, IOException {
if ( !profile.canBeIssuedBy(owner)) {
throw new GigiApiException("You are not allowed to issue these certificates.");
}
this.csrType = csrType;
this.profile = profile;
this.sans = Arrays.asList(sans);
+ synchronized (Certificate.class) {
+
+ GigiPreparedStatement inserter = DatabaseConnection.getInstance().prepare("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, crt_name='', memid=?, profile=?");
+ inserter.setString(1, md.toLowerCase());
+ inserter.setString(2, csrType.toString());
+ inserter.setInt(3, owner.getId());
+ inserter.setInt(4, profile.getId());
+ inserter.execute();
+ id = inserter.lastInsertId();
+
+ GigiPreparedStatement san = DatabaseConnection.getInstance().prepare("INSERT INTO `subjectAlternativeNames` SET `certId`=?, contents=?, type=?::`SANType`");
+ for (SubjectAlternateName subjectAlternateName : sans) {
+ san.setInt(1, id);
+ san.setString(2, subjectAlternateName.getName());
+ san.setString(3, subjectAlternateName.getType().getOpensslName());
+ san.execute();
+ }
+
+ GigiPreparedStatement insertAVA = DatabaseConnection.getInstance().prepare("INSERT INTO `certAvas` SET `certId`=?, name=?, value=?");
+ insertAVA.setInt(1, id);
+ for (Entry<String, String> e : dn.entrySet()) {
+ insertAVA.setString(2, e.getKey());
+ insertAVA.setString(3, e.getValue());
+ insertAVA.execute();
+ }
+ File csrFile = KeyStorage.locateCsr(id);
+ csrName = csrFile.getPath();
+ try (FileOutputStream fos = new FileOutputStream(csrFile)) {
+ fos.write(csr.getBytes("UTF-8"));
+ }
+
+ GigiPreparedStatement updater = DatabaseConnection.getInstance().prepare("UPDATE `certs` SET `csr_name`=? WHERE id=?");
+ updater.setString(1, csrName);
+ updater.setInt(2, id);
+ updater.execute();
+
+ cache.put(this);
+ }
}
private Certificate(GigiResultSet rs) {
}
Notary.writeUserAgreement(owner, "CCA", "issue certificate", "", true, 0);
- GigiPreparedStatement inserter = DatabaseConnection.getInstance().prepare("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, crt_name='', memid=?, profile=?");
- inserter.setString(1, md.toLowerCase());
- inserter.setString(2, csrType.toString());
- inserter.setInt(3, owner.getId());
- inserter.setInt(4, profile.getId());
- inserter.execute();
- id = inserter.lastInsertId();
-
- GigiPreparedStatement san = DatabaseConnection.getInstance().prepare("INSERT INTO `subjectAlternativeNames` SET `certId`=?, contents=?, type=?::`SANType`");
- for (SubjectAlternateName subjectAlternateName : sans) {
- san.setInt(1, id);
- san.setString(2, subjectAlternateName.getName());
- san.setString(3, subjectAlternateName.getType().getOpensslName());
- san.execute();
- }
-
- GigiPreparedStatement insertAVA = DatabaseConnection.getInstance().prepare("INSERT INTO `certAvas` SET `certId`=?, name=?, value=?");
- insertAVA.setInt(1, id);
- for (Entry<String, String> e : dn.entrySet()) {
- insertAVA.setString(2, e.getKey());
- insertAVA.setString(3, e.getValue());
- insertAVA.execute();
- }
- File csrFile = KeyStorage.locateCsr(id);
- csrName = csrFile.getPath();
- try (FileOutputStream fos = new FileOutputStream(csrFile)) {
- fos.write(csr.getBytes("UTF-8"));
- }
-
- GigiPreparedStatement updater = DatabaseConnection.getInstance().prepare("UPDATE `certs` SET `csr_name`=? WHERE id=?");
- updater.setString(1, csrName);
- updater.setInt(2, id);
- updater.execute();
return Job.sign(this, start, period);
}
return profile;
}
- public static Certificate getBySerial(String serial) {
+ public synchronized static Certificate getBySerial(String serial) {
if (serial == null || "".equals(serial)) {
return null;
}
- // TODO caching?
try {
String concat = "string_agg(concat('/', `name`, '=', REPLACE(REPLACE(value, '\\\\', '\\\\\\\\'), '/', '\\\\/')), '')";
GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT certs.id, " + concat + " as `subject`, `md`, `csr_name`, `crt_name`,`memid`, `profile`, `certs`.`serial` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`");
ps.setString(1, serial);
GigiResultSet rs = ps.executeQuery();
- return new Certificate(rs);
+ int id = rs.getInt(1);
+ Certificate c1 = cache.get(id);
+ if (c1 != null) {
+ return c1;
+ }
+ Certificate certificate = new Certificate(rs);
+ cache.put(certificate);
+ return certificate;
} catch (IllegalArgumentException e) {
}
return null;
}
- public static Certificate getById(int id) {
+ private static ObjectCache<Certificate> cache = new ObjectCache<>();
+
+ public synchronized static Certificate getById(int id) {
+ Certificate cacheRes = cache.get(id);
+ if (cacheRes != null) {
+ return cacheRes;
+ }
- // TODO caching?
try {
String concat = "string_agg(concat('/', `name`, '=', REPLACE(REPLACE(value, '\\\\', '\\\\\\\\'), '/', '\\\\/')), '')";
GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT certs.id, " + concat + " as subject, md, csr_name, crt_name,memid, profile, certs.serial FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=certs.id WHERE certs.id=? GROUP BY certs.id");
ps.setInt(1, id);
GigiResultSet rs = ps.executeQuery();
- return new Certificate(rs);
+ Certificate c = new Certificate(rs);
+ cache.put(c);
+ return c;
} catch (IllegalArgumentException e) {
}
}
public Domain(User owner, String suffix) throws GigiApiException {
- checkCertifyableDomain(suffix, owner.isInGroup(Group.CODESIGNING));
- this.owner = owner;
- this.suffix = suffix;
-
+ synchronized (Domain.class) {
+ checkCertifyableDomain(suffix, owner.isInGroup(Group.CODESIGNING));
+ this.owner = owner;
+ this.suffix = suffix;
+ insert();
+ }
}
public static void checkCertifyableDomain(String s, boolean hasPunycodeRight) throws GigiApiException {
}
}
- public void insert() throws GigiApiException {
- synchronized (Domain.class) {
- if (id != 0) {
- throw new GigiApiException("already inserted.");
- }
- checkInsert(suffix);
- GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO `domains` SET memid=?, domain=?");
- ps.setInt(1, owner.getId());
- ps.setString(2, suffix);
- ps.execute();
- id = ps.lastInsertId();
- myCache.put(this);
+ private void insert() throws GigiApiException {
+ if (id != 0) {
+ throw new GigiApiException("already inserted.");
}
+ checkInsert(suffix);
+ GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO `domains` SET memid=?, domain=?");
+ ps.setInt(1, owner.getId());
+ ps.setString(2, suffix);
+ ps.execute();
+ id = ps.lastInsertId();
+ myCache.put(this);
}
public void delete() throws GigiApiException {
import org.cacert.gigi.database.GigiResultSet;
import org.cacert.gigi.output.CertificateValiditySelector;
-public class Job {
+public class Job implements IdCachable {
private int id;
ps.setDate(3, start);
ps.setString(4, period);
ps.execute();
- return new Job(ps.lastInsertId());
+ return cache.put(new Job(ps.lastInsertId()));
}
- public static Job revoke(Certificate targetId) {
+ public synchronized static Job revoke(Certificate targetId) {
GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO `jobs` SET targetId=?, task=?::`jobType`");
ps.setInt(1, targetId.getId());
ps.setString(2, JobType.REVOKE.getName());
ps.execute();
- return new Job(ps.lastInsertId());
+ return cache.put(new Job(ps.lastInsertId()));
}
- public boolean waitFor(int max) throws InterruptedException {
+ public synchronized boolean waitFor(int max) throws InterruptedException {
long start = System.currentTimeMillis();
GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT 1 FROM `jobs` WHERE id=? AND state='open'");
ps.setInt(1, id);
rs.close();
return true;
}
+
+ @Override
+ public int getId() {
+ return id;
+ }
+
+ static ObjectCache<Job> cache = new ObjectCache<>();
+
+ public synchronized static Job getById(int id) {
+ Job i = cache.get(id);
+ if (i != null) {
+ return i;
+ }
+ GigiPreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT 1 FROM `jobs` WHERE id=?'");
+ ps.setInt(1, id);
+ GigiResultSet rs = ps.executeQuery();
+ if (rs.next()) {
+ Job j = new Job(id);
+ cache.put(j);
+ return j;
+ }
+ return null;
+
+ }
}
import java.io.PrintWriter;
import java.util.Map;
+import org.cacert.gigi.dbObjects.wrappers.DataContainer;
import org.cacert.gigi.localisation.Language;
import org.cacert.gigi.output.template.Outputable;
import org.cacert.gigi.util.HTMLEncoder;
+@DataContainer
public class Name implements Outputable {
private final String fname;
caches.add(this);
}
- public void put(T c) {
+ public T put(T c) {
hashmap.put(c.getId(), new WeakReference<T>(c));
+ return c;
}
public T get(int id) {
--- /dev/null
+package org.cacert.gigi.dbObjects.wrappers;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+public @interface DataContainer {
+
+}
if ( !error.isEmpty()) {
throw error;
}
- return new Certificate(u, subject, selectedDigest.toString(), //
- this.csr, this.csrType, profile, SANs.toArray(new SubjectAlternateName[SANs.size()]));
+ try {
+ return new Certificate(u, subject, selectedDigest.toString(), //
+ this.csr, this.csrType, profile, SANs.toArray(new SubjectAlternateName[SANs.size()]));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
}
private String verifyName(GigiApiException error, PropertyTemplate nameTemp, PropertyTemplate wotUserTemp, String verifiedCN) {
throw new GigiApiException("No domain inserted.");
}
Domain d = new Domain(target, parameter);
- d.insert();
pcf.setTarget(d);
pcf.submit(out, req);
return true;
assertEquals(0, us.getDomains().length);
Domain d = new Domain(us, "v1example.org");
assertEquals(0, d.getId());
- d.insert();
Domain[] domains = us.getDomains();
assertEquals(1, domains.length);
assertEquals("v1example.org", domains[0].getSuffix());
Domain d2 = new Domain(us, "v2-example.org");
assertEquals(0, d2.getId());
- d2.insert();
domains = us.getDomains();
assertEquals(2, domains.length);
@Test
public void testDoubleDomain() throws InterruptedException, GigiApiException {
Domain d = new Domain(us, "dub-example.org");
- d.insert();
try {
Domain d2 = new Domain(us, "dub-example.org");
- d2.insert();
fail("expected exception");
} catch (GigiApiException e) {
// expected
@Test
public void testDoubleDomainDelete() throws InterruptedException, GigiApiException {
Domain d = new Domain(us, "delexample.org");
- d.insert();
d.delete();
Domain d2 = new Domain(us, "delexample.org");
- d2.insert();
- }
-
- @Test
- public void testDoubleInsertDomain() throws InterruptedException, GigiApiException {
- Domain d = new Domain(us, "dins-example.org");
- d.insert();
- try {
- d.insert();
- fail("expected exception");
- } catch (GigiApiException e) {
- // expected
- }
}
}
@Test
public void testDomainCache() throws GigiApiException {
Domain d = new Domain(User.getById(uid), "example.org");
- d.insert();
assertThat(d, is(sameInstance(Domain.getById(d.getId()))));
assertThat(Domain.getById(d.getId()), is(sameInstance(Domain.getById(d.getId()))));
User u = User.getById(id);
new EmailAddress(u, uq + "b@email.org", Locale.ENGLISH);
new EmailAddress(u, uq + "c@email.org", Locale.ENGLISH);
- new Domain(u, uq + "a-testdomain.org").insert();
- new Domain(u, uq + "b-testdomain.org").insert();
- new Domain(u, uq + "c-testdomain.org").insert();
+ new Domain(u, uq + "a-testdomain.org");
+ new Domain(u, uq + "b-testdomain.org");
+ new Domain(u, uq + "c-testdomain.org");
assertEquals(3, u.getEmails().length);
assertEquals(3, u.getDomains().length);
assertTrue(u.isValidDomain(uq + "a-testdomain.org"));
int id = createVerifiedUser("Först", "Secönd", mail, TEST_PASSWORD);
User user = User.getById(id);
String domainName = createUniqueName() + ".org";
- Domain d = new Domain(user, domainName);
- d.insert();
+ new Domain(user, domainName);
URLConnection uc = new URL("https://" + getServerName() + FindDomainPage.PATH).openConnection();
uc.addRequestProperty("Cookie", cookie);
String csrf = getCSRF(uc, 0);
User user = User.getById(id);
String domainName = createUniqueName() + ".org";
Domain d = new Domain(user, domainName);
- d.insert();
URLConnection uc = new URL("https://" + getServerName() + FindDomainPage.PATH).openConnection();
uc.addRequestProperty("Cookie", cookie);
String csrf = getCSRF(uc, 0);
f = EmailAddress.class.getDeclaredField("hash");
f.setAccessible(true);
} catch (ReflectiveOperationException e) {
- throw new Error(e);
+ // TODO
+ System.out.println("I don't have 'hash', we are working probably in layered mode. Test Manager may not work.");
+ // throw new Error(e);
}
}
gc.set(1990, 0, 1);
User u = new User(email, "xvXV12°§", new Name("Först", "Läst", "Müddle", "Süffix"), new Date(gc.getTime().getTime()), Locale.ENGLISH);
EmailAddress ea = u.getEmails()[0];
+ if (f == null) {
+ System.out.println("verification failed");
+ return;
+ }
String hash = (String) f.get(ea);
ea.verify(hash);
User u = User.getByEmail(req.getParameter("addEmailEmail"));
try {
EmailAddress ea = new EmailAddress(u, req.getParameter("addEmailNew"), Locale.ENGLISH);
- String hash = (String) f.get(ea);
- ea.verify(hash);
- resp.getWriter().println("Email added and verified");
+ if (f != null) {
+ String hash = (String) f.get(ea);
+ ea.verify(hash);
+ resp.getWriter().println("Email added and verified");
+ } else {
+ resp.getWriter().println("Email added but verificatio failed.");
+ }
} catch (IllegalArgumentException e) {
e.printStackTrace();
resp.getWriter().println("An internal error occured.");