From c0985f466120427b0f1c8484a86785b3ca347036 Mon Sep 17 00:00:00 2001
From: Felix Sidokhine <felix.sidokhine@randstad.ca>
Date: Sun, 31 May 2020 13:52:22 +0300
Subject: [PATCH] added persisting of CRL to file

---
 jams-ca/crl.pem                               | Bin 0 -> 681 bytes
 .../jams/ca/workers/crl/CRLFileStorage.java   |  21 +++++++++
 .../jami/jams/ca/workers/crl/CRLWorker.java   |  40 ++++++++++++++---
 .../builders/SystemAccountBuilderTest.java    |   9 ++--
 .../common/serialization/fs/FileStorage.java  |  42 ++++++++++++++++++
 5 files changed, 99 insertions(+), 13 deletions(-)
 create mode 100644 jams-ca/crl.pem
 create mode 100644 jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java
 create mode 100644 jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java

diff --git a/jams-ca/crl.pem b/jams-ca/crl.pem
new file mode 100644
index 0000000000000000000000000000000000000000..f7d7e1ca04c1b47c7d6b46cdd1820dbb5de5757a
GIT binary patch
literal 681
zcmXqLVp?j@*vG`kXu!+HsnzDu_MMlJk(ZUhK;BTmfRBwil!cjxJtVcbM8Vn7klTP0
zB*G@l<Q62(Yh++xYHVm|U}|V;5oO?Ipv=U=$ev+~F2Q5K1=J)f%EHXW$O%%!T4^*1
zMUh#Q0jeTYr!Y4$F)}niO#8c#Pf?2J?2`W_+^4suUpw)dtF%;DX#3tJ%u9DIcfZ~&
zJNf9950)Q2Zf~fsw3spLZT+b?{WrDrg!rRxb6VuN>88~#+a)}y{gq%}P<Xbn;Zmi#
zpx9jPNp?KDuUcljJLh<nTQ<Mo+XmJ%@(0Y<|M;ryrEuiT&h_Qn8lKMIDfg2(e6D}*
zrXBL;UjM~28Z)b79;q(BU>dX_SM!FHiji;Yf%81+(yHGcR%<4+{!mR5dR6$RI^o;V
zUz4`){x!G$ecbxx!aPgw>4ZPBPkMF3M^(cpuIu)n4QsaD(yf0Qe=}qGw`E*5YI}dU
zwUlnxQ7yUf)4-pz_r~!GABDpcW1k%|zdPr1)GV1xh81Vzr1{0FrkB_?+SjF<WyF73
z9GvBA@LlDpMSYr>*|MU}DSRi-cfE=+KV2^`=h5@E?#R9^+^^sNPY(GyuS4<wp(Qqs
zQolSe=1WvOzo@^rZB?P&x0k2+5@(%Cd9srA<kX6%HqZadI$V}MnV8*ScWQb8yBp`G
z*TqH4C1$;@k<-r<%56O)$1wez*4~eoUvJj1V3;ggEz2FA?O3jOclvS#m79lOpWUYE
zlDDg5=J5jVMF)};Kh3??v2eff7V!guc`1J-uO;a0`{%UkkIjZ_6O)d)_57Fm<h}N!
mm3XDGTTn-TS;FZ#ey0^)uIcb?Sn8N&>U6Sgr-tN5mI?r!3mZoO

literal 0
HcmV?d00001

diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java
new file mode 100644
index 00000000..ab191b0c
--- /dev/null
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLFileStorage.java
@@ -0,0 +1,21 @@
+package net.jami.jams.ca.workers.crl;
+
+import net.jami.jams.common.serialization.fs.FileStorage;
+import org.bouncycastle.cert.X509CRLHolder;
+
+public class CRLFileStorage extends FileStorage<X509CRLHolder> {
+
+    public CRLFileStorage(String file) {
+        super(file);
+    }
+
+    @Override
+    public X509CRLHolder getObject(byte[] bytes) throws Exception{
+        return new X509CRLHolder(bytes);
+    }
+
+    @Override
+    public byte[] getBytesFromObject(X509CRLHolder object) throws Exception {
+        return object.getEncoded();
+    }
+}
diff --git a/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java
index 7cbafa56..cfd80cd0 100644
--- a/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java
+++ b/jams-ca/src/main/java/net/jami/jams/ca/workers/crl/CRLWorker.java
@@ -28,12 +28,15 @@ import lombok.extern.slf4j.Slf4j;
 import net.jami.jams.ca.JamsCA;
 import net.jami.jams.ca.workers.X509Worker;
 import net.jami.jams.common.objects.requests.RevocationRequest;
+import net.jami.jams.common.serialization.fs.FileStorage;
 import org.bouncycastle.asn1.x500.X500Name;
 import org.bouncycastle.asn1.x509.CRLReason;
 import org.bouncycastle.cert.X509CRLHolder;
 import org.bouncycastle.cert.X509v2CRLBuilder;
 import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 
+import java.io.File;
+import java.io.SyncFailedException;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
 import java.util.Date;
@@ -44,15 +47,31 @@ import java.util.concurrent.atomic.AtomicReference;
 public class CRLWorker extends X509Worker<RevocationRequest> {
 
     @Getter
-    private AtomicReference<X509CRLHolder> existingCRL = null;
+    private final AtomicReference<X509CRLHolder> existingCRL = new AtomicReference<>();
+
+    @Getter
+    private final CRLFileStorage crlFileStorage = new CRLFileStorage(System.getProperty("user.dir") + File.separator + "crl.pem");
 
     @Getter @Setter
     private AtomicBoolean stop = new AtomicBoolean(false);
 
     public CRLWorker(PrivateKey privateKey, X509Certificate certificate) {
         super(privateKey, certificate);
-        //TODO: The CRL needs to be loaded from somewhere.
-
+        try{
+            existingCRL.set(crlFileStorage.getData());
+        }
+        catch (Exception e){
+            log.warn("Could not find existing CRL file, if this is the first" +
+                " time you are starting the server or no CRL existed, this is fine");
+            X509v2CRLBuilder crlBuilder = new X509v2CRLBuilder(new X500Name((getCertificate()).getSubjectDN().getName()), new Date());
+            try {
+                existingCRL.set(crlBuilder.build(new JcaContentSignerBuilder("SHA512WITHRSA").setProvider("BC").build(getSigningKey())));
+                crlFileStorage.storeData(existingCRL.get());
+            }
+            catch (Exception e1){
+                log.error("Could not create blank CRL!");
+            }
+        }
         this.setDaemon(true);
         this.start();
         log.info("Instantiated & started a CRL Worker...");
@@ -65,11 +84,18 @@ public class CRLWorker extends X509Worker<RevocationRequest> {
             if(revocationRequest != null) {
                 crlBuilder.addCRLEntry(revocationRequest.getIdentifier(), new Date(), CRLReason.privilegeWithdrawn);
             }
-            if (existingCRL != null){
-                crlBuilder.addCRL(existingCRL.get());
-            }
-            else existingCRL = new AtomicReference<>();
+            crlBuilder.addCRL(existingCRL.get());
             existingCRL.set(crlBuilder.build(new JcaContentSignerBuilder("SHA512WITHRSA").setProvider("BC").build(getSigningKey())));
+            boolean failedWrite = true;
+            while(failedWrite){
+                try{
+                    crlFileStorage.storeData(existingCRL.get());
+                    failedWrite = false;
+                }
+                catch (Exception e){
+                    log.warn("Failed to write file, trying again!");
+                }
+            }
             log.info("Successfully ran revocation routine");
         }
         catch (Exception e){
diff --git a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java
index 6c8e6fa8..2a3f77f1 100644
--- a/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java
+++ b/jams-ca/src/test/java/net/jami/jams/ca/workers/csr/builders/SystemAccountBuilderTest.java
@@ -110,7 +110,7 @@ class SystemAccountBuilderTest {
 
 
         JamsCA jamsCA = new JamsCA();
-        jamsCA.init(JsonStream.serialize(config),caAccount,null);
+        jamsCA.init(JsonStream.serialize(config),caAccount,caAccount);
         RevocationRequest revocationRequest = new RevocationRequest();
         revocationRequest.setIdentifier(new BigInteger("91828882"));
         revocationRequest.setRevocationType(RevocationType.USER);
@@ -119,7 +119,7 @@ class SystemAccountBuilderTest {
             this.wait(2_000);
         }
         Assertions.assertNotNull(jamsCA.getLatestCRL());
-        Assertions.assertEquals(jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,1,"Expected only 1 certificate!");
+        Assertions.assertEquals(1,jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,"Expected only 1 certificate!");
 
         revocationRequest = new RevocationRequest();
         revocationRequest.setIdentifier(new BigInteger("17262653"));
@@ -129,9 +129,6 @@ class SystemAccountBuilderTest {
             this.wait(2_000);
         }
         Assertions.assertNotNull(jamsCA.getLatestCRL());
-        Assertions.assertEquals(jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,2,"Expected only 2 certificates!");
-
-
-
+        Assertions.assertEquals(2,jamsCA.getLatestCRL().get().getRevokedCertificates().toArray().length,"Expected only 2 certificates!");
     }
 }
\ No newline at end of file
diff --git a/jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java b/jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java
new file mode 100644
index 00000000..6f3a6b40
--- /dev/null
+++ b/jams-common/src/main/java/net/jami/jams/common/serialization/fs/FileStorage.java
@@ -0,0 +1,42 @@
+package net.jami.jams.common.serialization.fs;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+
+@Getter
+@Setter
+public abstract class FileStorage<T> {
+
+    private File file;
+    private FileInputStream fileInputStream;
+    private FileOutputStream fileOutputStream;
+    private FileDescriptor fileDescriptor;
+
+    public FileStorage(String file) {
+        this.file = new File(file);
+    }
+
+    public abstract T getObject(byte[] bytes) throws Exception;
+    public abstract byte[] getBytesFromObject(T object) throws Exception;
+
+    public T getData() throws Exception{
+        fileInputStream = new FileInputStream(file);
+        return getObject(fileInputStream.readAllBytes());
+    }
+
+    public void storeData(T data) throws Exception{
+        fileOutputStream = new FileOutputStream(file);
+        fileDescriptor = fileOutputStream.getFD();
+        fileOutputStream.write(getBytesFromObject(data));
+        fileOutputStream.flush();
+        fileDescriptor.sync();
+    }
+
+
+
+}
-- 
GitLab