From d5cc9c8c26ebe835229bfcbf5667f5693ba0661a Mon Sep 17 00:00:00 2001
From: Joze RIHTARSIC <joze.rihtarsic@ext.ec.europa.eu>
Date: Wed, 4 Mar 2020 11:31:21 +0100
Subject: [PATCH] - add support for multivalue RDN certifcates

---
 smp-parent-pom/pom.xml                        |   2 +-
 .../ec/edelivery/smp/config/FileProperty.java |   2 +-
 .../smp/data/dao/ConfigurationDao.java        |   2 +-
 .../ec/edelivery/smp/data/dao/DomainDao.java  |   8 +--
 .../smp/data/ui/enums/SMPPropertyEnum.java    |   2 +-
 .../smp/services/ui/UITruststoreService.java  |  48 +++++++++++++++---
 ...rtificateToCertificateROConverterTest.java |   7 ++-
 .../services/ui/UITruststoreServiceTest.java  |  45 +++++++++++++++-
 .../resources/certificates/test-mvRdn.crt     | Bin 0 -> 622 bytes
 9 files changed, 97 insertions(+), 19 deletions(-)
 create mode 100644 smp-server-library/src/test/resources/certificates/test-mvRdn.crt

diff --git a/smp-parent-pom/pom.xml b/smp-parent-pom/pom.xml
index 6378e9546..84dbbc316 100644
--- a/smp-parent-pom/pom.xml
+++ b/smp-parent-pom/pom.xml
@@ -46,7 +46,7 @@
     <properties>
         <!-- Only selected modules are deployed -->
         <maven.deploy.skip>true</maven.deploy.skip>
-        <edelivery.ssl-auth.version>1.6</edelivery.ssl-auth.version>
+        <edelivery.ssl-auth.version>1.8</edelivery.ssl-auth.version>
 
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <slf4j.version>1.7.26</slf4j.version>
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java
index e1108be9f..50c0db98b 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java
@@ -3,7 +3,7 @@ package eu.europa.ec.edelivery.smp.config;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
 import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.PropertyConfigurator;
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java
index d3742e4c9..ae5c0d2b3 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java
@@ -23,8 +23,8 @@ import eu.europa.ec.edelivery.smp.logging.SMPLogger;
 import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
 import eu.europa.ec.edelivery.smp.utils.PropertyUtils;
 import eu.europa.ec.edelivery.smp.utils.SecurityUtils;
-import org.apache.commons.lang.exception.ExceptionUtils;
 import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.springframework.stereotype.Repository;
 import org.springframework.transaction.annotation.Transactional;
 
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
index 56b120bff..985baa2dc 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java
@@ -15,10 +15,9 @@ package eu.europa.ec.edelivery.smp.data.dao;
 
 import eu.europa.ec.edelivery.smp.data.model.DBDomain;
 import eu.europa.ec.edelivery.smp.data.model.DBDomainDeleteValidation;
-import eu.europa.ec.edelivery.smp.data.model.DBUserDeleteValidation;
 import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
 import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.NoResultException;
@@ -124,10 +123,11 @@ public class DomainDao extends BaseDao<DBDomain> {
 
     /**
      * Validation report for domain which are used by  service groups from list of domain ids..
-     *  @param domainIds
+     *
+     * @param domainIds
      * @return
      */
-    public List<DBDomainDeleteValidation> validateDomainsForDelete(List<Long> domainIds){
+    public List<DBDomainDeleteValidation> validateDomainsForDelete(List<Long> domainIds) {
         TypedQuery<DBDomainDeleteValidation> query = memEManager.createNamedQuery("DBDomainDeleteValidation.validateDomainUsage",
                 DBDomainDeleteValidation.class);
         query.setParameter("domainIds", domainIds);
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
index 5aa8253c1..e827e0dd8 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java
@@ -1,6 +1,6 @@
 package eu.europa.ec.edelivery.smp.data.ui.enums;
 
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
 
 import java.util.Arrays;
 import java.util.Optional;
diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
index 2dbecae9d..880034465 100644
--- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
+++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreService.java
@@ -18,7 +18,9 @@ import org.springframework.security.authentication.AuthenticationServiceExceptio
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
-import javax.naming.InvalidNameException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.BasicAttribute;
 import javax.naming.ldap.LdapName;
 import javax.naming.ldap.Rdn;
 import javax.net.ssl.TrustManager;
@@ -359,20 +361,54 @@ public class UITruststoreService {
 
 
         String dn = x509cert.getSubjectX500Principal().getName();
+        String alias = null;
         try {
-            String alias = null;
+
             LdapName ldapDN = new LdapName(dn);
+            Rdn cn = null;
             for (Rdn rdn : ldapDN.getRdns()) {
-                if (Objects.equals("CN", rdn.getType())) {
+
+                if (rdn.size()>1) {
+                    NamingEnumeration enr = rdn.toAttributes().getAll();
+                    while(enr.hasMore()) {
+                        Object mvRDn = enr.next();
+                        if (mvRDn instanceof BasicAttribute){
+                            BasicAttribute ba = (BasicAttribute)mvRDn;
+                            if (Objects.equals("CN", ba.getID())) {
+                                cn = new Rdn(ba.getID(), ba.get());
+                                break;
+                            }
+                        }
+                    }
+
+                }else if (Objects.equals("CN", rdn.getType())) {
                     alias = rdn.getValue().toString().trim();
                     break;
                 }
+                if (cn !=null) {
+                    alias = cn.getValue().toString().trim();
+                    break;
+                }
             }
-            return alias;
-        } catch (InvalidNameException e) {
+
+        } catch (NamingException e) {
             LOG.error("Can not parse certificate subject: " + dn);
         }
-        return UUID.randomUUID().toString();
+        alias = StringUtils.isEmpty(alias)?UUID.randomUUID().toString():alias;
+
+        try {
+            if (truststore != null && truststore.containsAlias(alias)) {
+                int iVal = 1;
+                while(truststore.containsAlias(alias+"_"+iVal)){
+                    iVal++;
+                }
+                alias =alias+"_"+iVal;
+            }
+        } catch (KeyStoreException e) {
+            LOG.error("Error occured while reading truststore for validating alias: " + alias, e);
+        }
+
+        return alias;
 
     }
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/conversion/X509CertificateToCertificateROConverterTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/conversion/X509CertificateToCertificateROConverterTest.java
index 4ad6a09a6..736db31bc 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/conversion/X509CertificateToCertificateROConverterTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/conversion/X509CertificateToCertificateROConverterTest.java
@@ -25,13 +25,12 @@ import static org.junit.Assert.*;
 
 @RunWith(JUnitParamsRunner.class)
 public class X509CertificateToCertificateROConverterTest {
-
-    @Before
-    public void setup(){
+    static {
         Security.insertProviderAt(new org.bouncycastle.jce.provider.BouncyCastleProvider(), 1);
     }
 
 
+
     private static final Object[] testCases() {
         return new Object[][]{
                 // filename, subject, issuer, serial number, blueCoatHeader, certificateId
@@ -39,7 +38,7 @@ public class X509CertificateToCertificateROConverterTest {
                 {"cert-nonAscii.pem", "CN=NonAscii chars:  àøýßĉæãäħ,OU=CEF,O=DIGIT,C=BE", "CN=NonAscii chars:  àøýßĉæãäħ,OU=CEF,O=DIGIT,C=BE","5c1bb38d","sno=5c1bb38d&subject=CN%3DNonAscii+chars%3A++%C3%A0%C3%B8%C3%BD%C3%9F%C4%89%C3%A6%C3%A3%C3%A4%C4%A7%2COU%3DCEF%2CO%3DDIGIT%2CC%3DBE&validfrom=Dec+20+16%3A21%3A49+2018+GMT&validto=Dec+17+16%3A21%3A49+2028+GMT&issuer=CN%3DNonAscii+chars%3A++%C3%A0%C3%B8%C3%BD%C3%9F%C4%89%C3%A6%C3%A3%C3%A4%C4%A7%2COU%3DCEF%2CO%3DDIGIT%2CC%3DBE","CN=NonAscii chars:  aøyßcæaaħ,O=DIGIT,C=BE:000000005c1bb38d"},
                 {"cert-with-email.pem", "CN=Cert with email,OU=CEF,O=DIGIT,C=BE", "CN=Cert with email,OU=CEF,O=DIGIT,C=BE","5c1bb358","sno=5c1bb358&subject=CN%3DCert+with+email%2COU%3DCEF%2CO%3DDIGIT%2CC%3DBE&validfrom=Dec+20+16%3A20%3A56+2018+GMT&validto=Dec+17+16%3A20%3A56+2028+GMT&issuer=CN%3DCert+with+email%2COU%3DCEF%2CO%3DDIGIT%2CC%3DBE","CN=Cert with email,O=DIGIT,C=BE:000000005c1bb358"},
                 {"cert-smime.pem", "C=BE,O=European Commission,OU=PEPPOL TEST SMP,CN=edelivery_sml", "CN=PEPPOL SERVICE METADATA PUBLISHER TEST CA - G2,OU=FOR TEST ONLY,O=OpenPEPPOL AISBL,C=BE","3cfe6b37e4702512c01e71f9b9175464","sno=3cfe6b37e4702512c01e71f9b9175464&subject=C%3DBE%2CO%3DEuropean+Commission%2COU%3DPEPPOL+TEST+SMP%2CCN%3Dedelivery_sml&validfrom=Sep+21+02%3A00%3A00+2018+GMT&validto=Sep+11+01%3A59%3A59+2020+GMT&issuer=CN%3DPEPPOL+SERVICE+METADATA+PUBLISHER+TEST+CA+-+G2%2COU%3DFOR+TEST+ONLY%2CO%3DOpenPEPPOL+AISBL%2CC%3DBE","CN=edelivery_sml,O=European Commission,C=BE:3cfe6b37e4702512c01e71f9b9175464"},
-
+                {"test-mvRdn.crt", "C=BE,O=DIGIT,2.5.4.5=#130131+2.5.4.42=#0c046a6f686e+CN=SMP_receiverCN", "C=BE,O=DIGIT,2.5.4.5=#130131+2.5.4.42=#0c046a6f686e+CN=SMP_receiverCN","123456789101112","sno=123456789101112&subject=C%3DBE%2CO%3DDIGIT%2C2.5.4.5%3D%23130131%2B2.5.4.42%3D%230c046a6f686e%2BCN%3DSMP_receiverCN&validfrom=Dec+09+14%3A14%3A11+2019+GMT&validto=Feb+01+14%3A14%3A11+2021+GMT&issuer=C%3DBE%2CO%3DDIGIT%2C2.5.4.5%3D%23130131%2B2.5.4.42%3D%230c046a6f686e%2BCN%3DSMP_receiverCN","CN=SMP_receiverCN,O=DIGIT,C=BE:0123456789101112"},
         };
     }
 
diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreServiceTest.java
index 3f89ce579..2a30e0fbc 100644
--- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreServiceTest.java
+++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UITruststoreServiceTest.java
@@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
 import org.springframework.test.util.ReflectionTestUtils;
 
+import javax.security.auth.x500.X500Principal;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Path;
@@ -128,6 +129,23 @@ public class UITruststoreServiceTest extends AbstractServiceIntegrationTest {
         assertTrue(testInstance.isSubjectOnTrustedList(certSubject));
     }
 
+    @Test
+    public void testAddCertificateRDN() throws Exception {
+        // given
+        String certSubject = "GIVENNAME=John+SERIALNUMBER=1+CN=SMP Test,OU=eDelivery,O=DIGITAL,C=BE";
+        String alias = UUID.randomUUID().toString();
+        X509Certificate certificate = X509CertificateTestUtils.createX509CertificateForTest(certSubject);
+        String val = certificate.getSubjectX500Principal().getName(X500Principal.RFC2253);
+        int iSize = testInstance.getNormalizedTrustedList().size();
+        assertFalse(testInstance.isSubjectOnTrustedList(certSubject));
+        // when
+        testInstance.addCertificate(alias, certificate);
+
+        // then
+        assertEquals(iSize + 1, testInstance.getNormalizedTrustedList().size());
+        assertTrue(testInstance.isSubjectOnTrustedList(certSubject));
+    }
+
     @Test
     public void testDeleteCertificate() throws Exception {
         // given
@@ -365,7 +383,32 @@ public class UITruststoreServiceTest extends AbstractServiceIntegrationTest {
         testInstance.checkFullCertificateValidity(certificate);
 
         // then
-        //no erroros should be thrown
+        //no errors should be thrown
+    }
+
+    @Test
+    public void testCreateAliasForCert() throws Exception {
+        // given
+        String certSubject = "CN=SMP Test,OU=eDelivery,O=DIGITAL,C=BE";
+        X509Certificate certificate = X509CertificateTestUtils.createX509CertificateForTest(certSubject);
+        // when
+        String alias = testInstance.createAliasFromCert(certificate, null);
+
+        // then
+        assertEquals("SMP Test", alias);
+    }
+
+
+    @Test
+    public void testCreateAliasFoMultiValuerCert() throws Exception {
+        // given
+        String certSubject = "GIVENNAME=John+SERIALNUMBER=1+CN=SMP Test,OU=eDelivery,O=DIGITAL,C=BE";
+        X509Certificate certificate = X509CertificateTestUtils.createX509CertificateForTest(certSubject);
+        // when
+        String alias = testInstance.createAliasFromCert(certificate, null);
+
+        // then
+        assertEquals("SMP Test", alias);
     }
 
 }
\ No newline at end of file
diff --git a/smp-server-library/src/test/resources/certificates/test-mvRdn.crt b/smp-server-library/src/test/resources/certificates/test-mvRdn.crt
new file mode 100644
index 0000000000000000000000000000000000000000..97416e0da299b217ff90a11fcf7d406b5ef0d01f
GIT binary patch
literal 622
zcmXqLV#+dTV!XV7nTe5!iGxwuHN8_nP{@FnjZ>@5qwPB{BO@y-gMqK1o&g6Nb0`a|
zFr%RXH;ARh!;+Psk!K(Z;xO~@1^WiX7o{erW|pNEIr|y%8SsE4xOiAyJl#D*47m+B
zL3}o0CMQ<|IdNV?OG6_AOG9Hr6GOu&ab6=s10w@ND3{vSHO@!&4<joBb7L=qL1QOV
zV<W?{N|ys$HnM4}O{<i4`|))*U*3DkIn$RdyY%i=%5&cOZATT~K2?&ED`L{pZj<^{
zGrd*L*=C=Sm8<hID^ub5%WeHmIVn5+$nuvFxc^#qm*ko3-%(6Hrmz05-rBJ3^z1ah
zpS$lhyqvzVasCWZgYuo`$CupR%jeQky{qrFpFwxPBTFV`Mh3>k!3Kc_{=o2&m1prV
za5HdO;IzP@%`Po7C)G+nIW<i`IX@*;KPe@*I0r)NmZv5q78K~0Bo?KomgtwH7MJKI
z=Oh*vrxt@bddWpO$bJUKAv4gkT62yXukU54y!$@JpfT1eU7_OQq<v=&W*>4jzp<x$
z-7m57u;navT5Cn!Z&bBhKfhw<v;Ai`#JzVE;fs3nWADtH%g(#k`N+O4o7k_oVMD;W
zteG$0-p)$N;IlZgvztG7_lK6f*Y)hp?@us2-kLeZv`z7^O8n*pJiD4T=idr1)4lEs
E03vwQH2?qr

literal 0
HcmV?d00001

-- 
GitLab