]> WPIA git - gigi.git/blobdiff - src/club/wpia/gigi/dbObjects/Certificate.java
fix: resource leaks in OCSPIssuerManager
[gigi.git] / src / club / wpia / gigi / dbObjects / Certificate.java
index 825b33928729804cd5cf112a92837ad5669df98b..28c32088fd1f09e302f0327f2168f534215c9650 100644 (file)
@@ -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;
@@ -164,6 +166,10 @@ public class Certificate implements IdCachable {
 
     private String description = "";
 
+    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}
@@ -407,12 +413,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`, `certs`.`description` FROM `certs` LEFT JOIN `certAvas` ON `certAvas`.`certId`=`certs`.`id` WHERE `serial`=? GROUP BY `certs`.`id`")) {
-            ps.setString(1, serial);
+            ps.setString(1, serial.toString(16));
             GigiResultSet rs = ps.executeQuery();
             if ( !rs.next()) {
                 return null;
@@ -582,4 +588,56 @@ public class Certificate implements IdCachable {
     public String getDescription() {
         return description;
     }
+
+    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);
+    }
 }