X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=src%2Fclub%2Fwpia%2Fgigi%2FdbObjects%2FCertificate.java;h=61fd7d341a11d0a07c4329a532d93a2eeb6c062f;hp=51bf41be136687041cdca9b3e511958a9dc01682;hb=443b1f0954;hpb=0d53a31181ded3b9897179d3099ccb74a159d2cc diff --git a/src/club/wpia/gigi/dbObjects/Certificate.java b/src/club/wpia/gigi/dbObjects/Certificate.java index 51bf41be..61fd7d34 100644 --- a/src/club/wpia/gigi/dbObjects/Certificate.java +++ b/src/club/wpia/gigi/dbObjects/Certificate.java @@ -2,7 +2,9 @@ package club.wpia.gigi.dbObjects; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.math.BigInteger; import java.security.GeneralSecurityException; +import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.sql.Date; @@ -162,6 +164,14 @@ public class Certificate implements IdCachable { private CACertificate ca; + private String description = ""; + + private User actor; + + public static final TranslateCommand NOT_LOADED = new TranslateCommand("Certificate could not be loaded"); + + public static final TranslateCommand NOT_PARSED = new TranslateCommand("Certificate could not be parsed"); + /** * Creates a new Certificate. WARNING: this is an internal API. Creating * certificates for users must be done using the {@link CertificateRequest} @@ -204,13 +214,15 @@ public class Certificate implements IdCachable { this.csrType = csrType; this.profile = profile; this.sans = Arrays.asList(sans); + this.actor = actor; synchronized (Certificate.class) { - try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, memid=?, profile=?")) { + try (GigiPreparedStatement inserter = new GigiPreparedStatement("INSERT INTO certs SET md=?::`mdType`, csr_type=?::`csrType`, memid=?, profile=?, actorid=?")) { inserter.setString(1, md.toString().toLowerCase()); inserter.setString(2, this.csrType.toString()); inserter.setInt(3, owner.getId()); inserter.setInt(4, profile.getId()); + inserter.setInt(5, this.actor.getId()); inserter.execute(); id = inserter.lastInsertId(); } @@ -244,6 +256,8 @@ public class Certificate implements IdCachable { owner = CertificateOwner.getById(rs.getInt("memid")); profile = CertificateProfile.getById(rs.getInt("profile")); this.serial = rs.getString("serial"); + this.description = rs.getString("description"); + this.actor = User.getById(rs.getInt("actorid")); try (GigiPreparedStatement ps2 = new GigiPreparedStatement("SELECT `contents`, `type` FROM `subjectAlternativeNames` WHERE `certId`=?")) { ps2.setInt(1, id); @@ -404,12 +418,12 @@ public class Certificate implements IdCachable { private static final String CONCAT = "string_agg(concat('/', `name`, '=', REPLACE(REPLACE(value, '\\\\', '\\\\\\\\'), '/', '\\\\/')), '')"; - public synchronized static Certificate getBySerial(String serial) { - if (serial == null || "".equals(serial)) { + public synchronized static Certificate getBySerial(BigInteger serial) { + if (serial == null) { return null; } - try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as `subject`, `md`,`memid`, `profile`, `certs`.`serial` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) { - ps.setString(1, serial); + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as `subject`, `md`,`memid`, `profile`, `certs`.`serial`, `certs`.`description`, `certs`.`actorid` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) { + ps.setString(1, serial.toString(16)); GigiResultSet rs = ps.executeQuery(); if ( !rs.next()) { return null; @@ -434,7 +448,7 @@ public class Certificate implements IdCachable { } try { - try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, memid, profile, certs.serial FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=certs.id WHERE certs.id=? GROUP BY certs.id")) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("SELECT certs.id, " + CONCAT + " as subject, md, memid, profile, certs.serial, description, actorid 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(); if ( !rs.next()) { @@ -486,6 +500,19 @@ public class Certificate implements IdCachable { return null; } + public java.util.Date getExpiryDate() { + if (getStatus() == CertificateStatus.ISSUED) { + try (GigiPreparedStatement prep = new GigiPreparedStatement("SELECT expire FROM certs WHERE id=?")) { + prep.setInt(1, getId()); + GigiResultSet res = prep.executeQuery(); + if (res.next()) { + return res.getTimestamp("expire"); + } + } + } + return null; + } + public void setLoginEnabled(boolean activate) { if (activate) { if ( !isLoginEnabled()) { @@ -566,4 +593,73 @@ public class Certificate implements IdCachable { return s; } } + + public void setDescription(String description) { + try (GigiPreparedStatement ps = new GigiPreparedStatement("UPDATE `certs` SET `description`=? WHERE `id`=?")) { + ps.setString(1, description); + ps.setInt(2, id); + ps.execute(); + } + this.description = description; + } + + public String getDescription() { + return description; + } + + public User getActor() { + return actor; + } + + public static Certificate locateCertificate(String serial, String certData) throws GigiApiException { + if (serial != null && !serial.isEmpty()) { + return getBySerial(normalizeSerial(serial)); + } + + if (certData != null && !certData.isEmpty()) { + final byte[] supplied; + final X509Certificate c0; + try { + supplied = PEM.decode("CERTIFICATE", certData); + c0 = (X509Certificate) CertificateFactory.getInstance("X509").generateCertificate(new ByteArrayInputStream(supplied)); + } catch (IllegalArgumentException e1) { + throw new GigiApiException(NOT_PARSED); + } catch (CertificateException e1) { + throw new GigiApiException(NOT_PARSED); + } + try { + Certificate c = getBySerial(c0.getSerialNumber()); + if (c == null) { + return null; + } + X509Certificate cert = c.cert(); + if ( !Arrays.equals(supplied, cert.getEncoded())) { + return null; + } + return c; + } catch (IOException e) { + throw new GigiApiException(NOT_LOADED); + } catch (GeneralSecurityException e) { + throw new GigiApiException(NOT_LOADED); + } + } + throw new GigiApiException("No information to identify the correct certificate was provided."); + } + + public static BigInteger normalizeSerial(String serial) throws GigiApiException { + serial = serial.replace(" ", ""); + serial = serial.toLowerCase(); + if (serial.matches("[0-9a-f]{2}(:[0-9a-f]{2})*")) { + serial = serial.replace(":", ""); + } + int idx = 0; + while (idx < serial.length() && serial.charAt(idx) == '0') { + idx++; + } + serial = serial.substring(idx); + if ( !serial.matches("[0-9a-f]+")) { + throw new GigiApiException("Malformed serial"); + } + return new BigInteger(serial, 16); + } }