cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ashaki...@apache.org
Subject svn commit: r1493072 [2/3] - in /cxf/trunk/services/xkms: xkms-client/src/main/resources/OSGI-INF/blueprint/ xkms-common/src/main/java/org/apache/cxf/xkms/handlers/ xkms-features/ xkms-features/src/main/resources/ xkms-itests/ xkms-itests/src/test/java...
Date Fri, 14 Jun 2013 13:50:32 GMT
Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509RegisterHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509RegisterHandler.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509RegisterHandler.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509RegisterHandler.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,141 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.handlers;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.cxf.xkms.handlers.KeyRegisterHandler;
+import org.apache.cxf.xkms.model.xkms.KeyBindingEnum;
+import org.apache.cxf.xkms.model.xkms.KeyBindingType;
+import org.apache.cxf.xkms.model.xkms.PrototypeKeyBindingType;
+import org.apache.cxf.xkms.model.xkms.RegisterRequestType;
+import org.apache.cxf.xkms.model.xkms.RegisterResultType;
+import org.apache.cxf.xkms.model.xkms.ReissueRequestType;
+import org.apache.cxf.xkms.model.xkms.ReissueResultType;
+import org.apache.cxf.xkms.model.xkms.RequestAbstractType;
+import org.apache.cxf.xkms.model.xkms.RespondWithEnum;
+import org.apache.cxf.xkms.model.xkms.RevokeRequestType;
+import org.apache.cxf.xkms.model.xkms.RevokeResultType;
+import org.apache.cxf.xkms.model.xkms.StatusType;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.model.xmldsig.KeyInfoType;
+import org.apache.cxf.xkms.model.xmldsig.X509DataType;
+import org.apache.cxf.xkms.x509.repo.CertificateRepo;
+import org.apache.cxf.xkms.x509.utils.X509Utils;
+
+public class X509RegisterHandler implements KeyRegisterHandler {
+
+    protected final CertificateFactory certFactory;
+    private CertificateRepo certRepo;
+
+    public X509RegisterHandler(CertificateRepo certRepo) throws CertificateException {
+        this.certRepo = certRepo;
+        certFactory = CertificateFactory.getInstance("X.509");
+    }
+
+    @Override
+    public boolean canProcess(RequestAbstractType request) {
+        List<String> respondWithList = request.getRespondWith();
+        if ((respondWithList != null) && !(respondWithList.isEmpty())) {
+            return respondWithList.contains(RespondWithEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_X_509_CERT);
+        } else {
+            // Default handler
+            return true;
+        }
+    }
+
+    @Override
+    public RegisterResultType register(RegisterRequestType request, RegisterResultType response) {
+        try {
+            PrototypeKeyBindingType binding = request.getPrototypeKeyBinding();
+            X509Utils.assertElementNotNull(binding, PrototypeKeyBindingType.class);
+            KeyInfoType keyInfo = binding.getKeyInfo();
+            X509Utils.assertElementNotNull(binding, KeyInfoType.class);
+            List<UseKeyWithType> useKeyWithList = binding.getUseKeyWith();
+            if (useKeyWithList == null || useKeyWithList.size() != 1) {
+                throw new IllegalArgumentException("Exactly one useKeyWith element needed");
+                //TODO standard requires support for multiple useKeyWith attributes
+            }
+            UseKeyWithType useKeyWith = useKeyWithList.get(0);
+            List<X509Certificate> certList = getCertsFromKeyInfo(keyInfo);
+            if (certList.size() != 1) {
+                throw new IllegalArgumentException("Must provide one X509Certificate");
+            }
+            X509Certificate cert = certList.get(0);
+            certRepo.saveCertificate(cert, useKeyWith);
+
+            KeyBindingType responseBinding = prepareResponseBinding(binding);
+            response.getKeyBinding().add(responseBinding);
+            return response;
+        } catch (CertificateException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    private KeyBindingType prepareResponseBinding(PrototypeKeyBindingType binding) {
+        KeyBindingType responseBinding = new KeyBindingType();
+        responseBinding.setKeyInfo(binding.getKeyInfo());
+        StatusType status = new StatusType();
+        status.setStatusValue(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_VALID);
+        responseBinding.setStatus(status);
+        return responseBinding;
+    }
+
+    @Override
+    public ReissueResultType reissue(ReissueRequestType request, ReissueResultType response) {
+        throw new UnsupportedOperationException("This service does not support reissue");
+    }
+
+    @Override
+    public RevokeResultType revoke(RevokeRequestType request, RevokeResultType response) {
+        throw new UnsupportedOperationException("This service does not support revoke");
+    }
+
+    private List<X509Certificate> getCertsFromKeyInfo(KeyInfoType keyInfo) throws CertificateException {
+        List<X509Certificate> certList = new ArrayList<X509Certificate>();
+        for (Object key : keyInfo.getContent()) {
+            if (key instanceof JAXBElement) {
+                Object value = ((JAXBElement<?>) key).getValue();
+                if (value instanceof X509DataType) {
+                    X509DataType x509Data = (X509DataType) value;
+                    List<Object> data = x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName();
+                    for (Object certO : data) {
+                        JAXBElement<?> certO2 = (JAXBElement<?>) certO;
+                        if (certO2.getDeclaredType() == byte[].class) {
+                            byte[] certContent = (byte[]) certO2.getValue();
+                            X509Certificate cert = (X509Certificate) certFactory
+                                    .generateCertificate(new ByteArrayInputStream(certContent));
+                            certList.add(cert);
+                        }
+                    }
+                }
+            }
+
+        }
+        return certList;
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,33 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo;
+
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+
+public interface CertificateRepo {
+    List<X509Certificate> getTrustedCaCerts();
+    List<X509Certificate> getCaCerts();
+    void saveCertificate(X509Certificate cert, UseKeyWithType key);
+    X509Certificate findBySubjectDn(String dn);
+    X509Certificate findByServiceName(String serviceName);
+    X509Certificate findByIssuerSerial(String issuer, String serial);
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo;
+
+import java.security.cert.CertificateException;
+
+import org.apache.cxf.xkms.x509.repo.file.FileCertificateRepo;
+import org.apache.cxf.xkms.x509.repo.ldap.LdapCertificateRepo;
+import org.apache.cxf.xkms.x509.repo.ldap.LdapSchemaConfig;
+import org.apache.cxf.xkms.x509.repo.ldap.LdapSearch;
+
+public final class CertificateRepoFactory {
+
+    private CertificateRepoFactory() {
+    }
+
+    public static CertificateRepo createRepository(String type, LdapSearch ldapSearch,
+                                                   LdapSchemaConfig ldapSchemaConfig, String rootDN,
+                                                   String storageDir) throws CertificateException {
+        CertificateRepo certificateRepo = null;
+
+        if ("ldap".equals(type)) {
+            certificateRepo = new LdapCertificateRepo(ldapSearch, ldapSchemaConfig, rootDN);
+        }
+
+        if ("file".equals(type)) {
+            certificateRepo = new FileCertificateRepo(storageDir);
+        }
+
+        return certificateRepo;
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,238 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.file;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.cxf.xkms.exception.XKMSConfigurationException;
+import org.apache.cxf.xkms.model.xkms.ResultMajorEnum;
+import org.apache.cxf.xkms.model.xkms.ResultMinorEnum;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.repo.CertificateRepo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class FileCertificateRepo implements CertificateRepo {
+    private static final Logger LOG = LoggerFactory.getLogger(FileCertificateRepo.class);
+    private static final String CN_PREFIX = "cn=";
+    private static final String TRUSTED_CAS_PATH = "trusted_cas";
+    private static final String CAS_PATH = "cas";
+    private final File storageDir;
+    private final CertificateFactory certFactory;
+
+    public FileCertificateRepo(String path) throws CertificateException {
+        storageDir = new File(path);
+        this.certFactory = CertificateFactory.getInstance("X.509");
+    }
+
+    public void saveCertificate(X509Certificate cert, UseKeyWithType id) {
+        saveCategorizedCertificate(cert, id, false, false);
+    }
+
+    public void saveTrustedCACertificate(X509Certificate cert, UseKeyWithType id) {
+        saveCategorizedCertificate(cert, id, true, false);
+    }
+
+    public void saveCACertificate(X509Certificate cert, UseKeyWithType id) {
+        saveCategorizedCertificate(cert, id, false, true);
+    }
+
+    private boolean saveCategorizedCertificate(X509Certificate cert, UseKeyWithType id, boolean isTrustedCA,
+                                               boolean isCA) {
+        String name = cert.getSubjectX500Principal().getName();
+        String category = "";
+        if (isTrustedCA) {
+            category = TRUSTED_CAS_PATH;
+        }
+        if (isCA) {
+            category = CAS_PATH;
+        }
+        try {
+            File certFile = new File(storageDir + "/" + category,
+                                     getRelativePathForSubjectDn(id.getIdentifier(), cert));
+            certFile.getParentFile().mkdirs();
+            FileOutputStream fos = new FileOutputStream(certFile);
+            BufferedOutputStream bos = new BufferedOutputStream(fos);
+            bos.write(cert.getEncoded());
+            bos.close();
+            fos.close();
+        } catch (Exception e) {
+            throw new RuntimeException("Error saving certificate " + name + ": " + e.getMessage(), e);
+        }
+        return true;
+    }
+
+    public String convertDnForFileSystem(String dn) {
+        String result = dn.replace("=", "-");
+        result = result.replace(", ", "_");
+        result = result.replace(",", "_");
+        result = result.replace("/", "_");
+        result = result.replace("\\", "_");
+        result = result.replace("{", "_");
+        result = result.replace("}", "_");
+        result = result.replace(":", "_");
+        return result;
+    }
+
+    public String getRelativePathForSubjectDn(String subjectDn, X509Certificate cert)
+        throws URISyntaxException {
+        BigInteger serialNumber = cert.getSerialNumber();
+        String issuer = cert.getIssuerX500Principal().getName();
+        String path = convertDnForFileSystem(subjectDn) + "-" + serialNumber.toString() + "-"
+                      + convertDnForFileSystem(issuer) + ".cer";
+        Pattern p = Pattern.compile("[a-zA-Z_0-9-_]");
+        if (p.matcher(path).find()) {
+            return path;
+        } else {
+            throw new URISyntaxException(path, "Input did not match [a-zA-Z_0-9-_].");
+        }
+    }
+
+    private File[] getX509Files() {
+        List<File> certificateFiles = new ArrayList<File>();
+        try {
+            certificateFiles.addAll(Arrays.asList(storageDir.listFiles()));
+            certificateFiles.addAll(Arrays.asList(new File(storageDir + "/" + TRUSTED_CAS_PATH).listFiles()));
+            certificateFiles.addAll(Arrays.asList(new File(storageDir + "/" + CAS_PATH).listFiles()));
+        } catch (NullPointerException e) {
+            //
+        }
+        if (certificateFiles.isEmpty()) {
+            throw new XKMSConfigurationException(ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_RECEIVER,
+                                                 ResultMinorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_FAILURE,
+                                                 "File base persistence storage is not found: "
+                                                     + storageDir.getPath());
+        }
+        return certificateFiles.toArray(new File[certificateFiles.size()]);
+    }
+
+    public X509Certificate readCertificate(File certFile) throws CertificateException, FileNotFoundException {
+        FileInputStream fis = new FileInputStream(certFile);
+        return (X509Certificate)certFactory.generateCertificate(fis);
+    }
+
+    @Override
+    public List<X509Certificate> getTrustedCaCerts() {
+        List<X509Certificate> results = new ArrayList<X509Certificate>();
+        File[] list = getX509Files();
+        for (File certFile : list) {
+            try {
+                if (certFile.isDirectory()) {
+                    continue;
+                }
+                if (certFile.getParent().endsWith(TRUSTED_CAS_PATH)) {
+                    X509Certificate cert = readCertificate(certFile);
+                    results.add(cert);
+                }
+            } catch (Exception e) {
+                LOG.warn(String.format("Cannot load certificate from file: %s. Error: %s", certFile,
+                                       e.getMessage()));
+            }
+
+        }
+        return results;
+    }
+
+    @Override
+    public List<X509Certificate> getCaCerts() {
+        List<X509Certificate> results = new ArrayList<X509Certificate>();
+        File[] list = getX509Files();
+        for (File certFile : list) {
+            try {
+                if (certFile.isDirectory()) {
+                    continue;
+                }
+                if (certFile.getParent().endsWith(CAS_PATH)) {
+                    X509Certificate cert = readCertificate(certFile);
+                    results.add(cert);
+                }
+            } catch (Exception e) {
+                LOG.warn(String.format("Cannot load certificate from file: %s. Error: %s", certFile,
+                                       e.getMessage()));
+            }
+
+        }
+        return results;
+    }
+
+    @Override
+    public X509Certificate findByServiceName(String serviceName) {
+        return findBySubjectDn(CN_PREFIX + serviceName);
+    }
+
+    @Override
+    public X509Certificate findBySubjectDn(String subjectDn) {
+        List<X509Certificate> result = new ArrayList<X509Certificate>();
+        File[] list = getX509Files();
+        for (File certFile : list) {
+            try {
+                if (certFile.isDirectory()) {
+                    continue;
+                }
+                X509Certificate cert = readCertificate(certFile);
+                if (subjectDn.equalsIgnoreCase(cert.getSubjectDN().getName())
+                    || subjectDn.equalsIgnoreCase(cert.getSubjectX500Principal().getName())) {
+                    result.add(cert);
+                }
+            } catch (Exception e) {
+                LOG.warn(String.format("Cannot load certificate from file: %s. Error: %s", certFile,
+                                       e.getMessage()));
+            }
+
+        }
+        return result.get(0);
+    }
+
+    @Override
+    public X509Certificate findByIssuerSerial(String issuer, String serial) {
+        List<X509Certificate> result = new ArrayList<X509Certificate>();
+        File[] list = getX509Files();
+        for (File certFile : list) {
+            try {
+                if (certFile.isDirectory()) {
+                    continue;
+                }
+                X509Certificate cert = readCertificate(certFile);
+                BigInteger cs = cert.getSerialNumber();
+                BigInteger ss = new BigInteger(serial, 16);
+                if (issuer.equalsIgnoreCase(cert.getIssuerX500Principal().getName()) && cs.equals(ss)) {
+                    result.add(cert);
+                }
+            } catch (Exception e) {
+                LOG.warn(String.format("Cannot load certificate from file: %s. Error: %s", certFile,
+                                       e.getMessage()));
+            }
+
+        }
+        return result.get(0);
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,242 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.ldap;
+
+import java.io.ByteArrayInputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.SearchResult;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.repo.CertificateRepo;
+
+public class LdapCertificateRepo implements CertificateRepo {
+    private static final Logger LOG = LogUtils.getL7dLogger(LdapCertificateRepo.class);
+    private static final String ATTR_OBJECT_CLASS = "objectClass";
+
+    private LdapSearch ldapSearch;
+    private String rootDN;
+    private CertificateFactory certificateFactory;
+    private final LdapSchemaConfig ldapConfig;
+    private final String filterUIDTemplate;
+    private final String filterIssuerSerialTemplate;
+
+    /**
+     * 
+     * @param ldapSearch
+     * @param rootDN rootDN of the LDAP tree 
+     * @param trustedAuthorityFilter 
+     * @param intermediateFilter
+     * @param attrName
+     */
+    public LdapCertificateRepo(LdapSearch ldapSearch, LdapSchemaConfig ldapConfig, String rootDN) {
+        this.ldapSearch = ldapSearch;
+        this.ldapSearch = ldapSearch;
+        this.ldapConfig = ldapConfig;
+        this.rootDN = rootDN;
+        try {
+            this.certificateFactory = CertificateFactory.getInstance("X.509");
+        } catch (CertificateException e) {
+            LOG.log(Level.SEVERE, e.getMessage(), e);
+        }
+        filterUIDTemplate = "(" + ldapConfig.getAttrUID() + "=%s)";
+        filterIssuerSerialTemplate = "(&(" + ldapConfig.getAttrIssuerID() + "=%s)(" + ldapConfig.getAttrSerialNumber()
+            + "=%s))";
+    }
+
+    @Override
+    public List<X509Certificate> getTrustedCaCerts() {
+        return getCertificatesFromLdap(rootDN, ldapConfig.getTrustedAuthorityFilter(), ldapConfig.getAttrCrtBinary());
+    }
+
+    @Override
+    public List<X509Certificate> getCaCerts() {
+        return getCertificatesFromLdap(rootDN, ldapConfig.getIntermediateFilter(), ldapConfig.getAttrCrtBinary());
+    }
+
+    private List<X509Certificate> getCertificatesFromLdap(String tmpRootDN, String tmpFilter, String tmpAttrName) {
+        try {
+            List<X509Certificate> certificates = new ArrayList<X509Certificate>();
+            NamingEnumeration<SearchResult> answer = ldapSearch.searchSubTree(tmpRootDN, tmpFilter);
+            while (answer.hasMore()) {
+                SearchResult sr = answer.next();
+                Attributes attrs = sr.getAttributes();
+                Attribute attribute = attrs.get(tmpAttrName);
+                if (attribute != null) {
+                    CertificateFactory cf = CertificateFactory.getInstance("X.509");
+                    X509Certificate certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(
+                            (byte[]) attribute.get()));
+                    certificates.add(certificate);
+                }
+            }
+            return certificates;
+        } catch (CertificateException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        } catch (NamingException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    private void saveCertificate(X509Certificate cert, String dn) {
+        Attributes attribs = new BasicAttributes();
+        attribs.put(new BasicAttribute(ATTR_OBJECT_CLASS, ldapConfig.getCertObjectClass()));
+        attribs.put(new BasicAttribute(ldapConfig.getAttrUID(), cert.getSubjectX500Principal().getName()));
+        attribs.put(new BasicAttribute(ldapConfig.getAttrIssuerID(), cert.getIssuerX500Principal().getName()));
+        attribs.put(new BasicAttribute(ldapConfig.getAttrSerialNumber(), cert.getSerialNumber().toString(16)));
+        addConstantAttributes(ldapConfig.getConstAttrNamesCSV(), ldapConfig.getConstAttrValuesCSV(), attribs);
+        try {
+            attribs.put(new BasicAttribute(ldapConfig.getAttrCrtBinary(), cert.getEncoded()));
+            ldapSearch.bind(dn, attribs);
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+    
+    private void addConstantAttributes(String names, String values, Attributes attribs) {
+        String[] arrNames = names.split(",");
+        String[] arrValues = values.split(",");
+        if (arrNames.length != arrValues.length) {
+            throw new IllegalArgumentException(
+                      String.format("Inconsintent constant attributes: %s; %s",  names, values));
+        }
+        for (int i = 0; i < arrNames.length; i++) {
+            attribs.put(new BasicAttribute(arrNames[i], arrValues[i]));
+        }
+    }
+
+    @Override
+    public X509Certificate findBySubjectDn(String id) {
+        X509Certificate cert = null;
+        try {
+            String dn = id;
+            if ((rootDN != null) && !(rootDN.isEmpty())) {
+                dn = dn + "," + rootDN;
+            }
+            cert = getCertificateForDn(dn);
+        } catch (NamingException e) {
+             // Not found
+        }
+        // Try to find certificate by search for uid attribute
+        try {
+            cert = getCertificateForUIDAttr(id);
+        } catch (NamingException e) {
+            // Not found
+        }
+        return cert;
+    }
+    
+    @Override
+    public X509Certificate findByServiceName(String serviceName) {
+        X509Certificate cert = null;
+        try {
+            String dn = getDnForServiceName(serviceName);
+            cert = getCertificateForDn(dn);
+        } catch (NamingException e) {
+            // Not found
+        }
+        // Try to find certificate by search for uid attribute
+        try {
+            String uidAttr = String.format(ldapConfig.getServiceCertUIDTemplate(), serviceName);
+            cert = getCertificateForUIDAttr(uidAttr);
+        } catch (NamingException e) {
+            // Not found
+        }
+        return cert;
+    }
+
+    private String getDnForServiceName(String serviceName) {
+        String escapedIdentifier = serviceName.replaceAll("\\/", Matcher.quoteReplacement("\\/"));
+        return String.format(ldapConfig.getServiceCertRDNTemplate(), escapedIdentifier) + "," + rootDN;
+    }
+
+    private X509Certificate getCertificateForDn(String dn) throws NamingException {
+        Attribute attr = ldapSearch.getAttribute(dn, ldapConfig.getAttrCrtBinary());
+        return getCert(attr);
+    }
+    
+    private X509Certificate getCertificateForUIDAttr(String uid) throws NamingException {
+        String filter = String.format(filterUIDTemplate, uid);
+        Attribute attr = ldapSearch.findAttribute(rootDN, filter, ldapConfig.getAttrCrtBinary());
+        return getCert(attr);
+    }
+
+    @Override
+    public X509Certificate findByIssuerSerial(String issuer, String serial) {
+        if ((issuer == null) || (serial == null)) {
+            throw new IllegalArgumentException("Issuer and serial applications are expected in request");
+        }
+        String filter = String.format(filterIssuerSerialTemplate, issuer, serial);
+        try {
+            Attribute attr = ldapSearch.findAttribute(rootDN, filter, ldapConfig.getAttrCrtBinary());
+            return getCert(attr);
+        } catch (NamingException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+    
+    private X509Certificate getCert(Attribute attr) {
+        if (attr == null) {
+            return null;
+        }
+        byte[] data;
+        try {
+            data = (byte[]) attr.get();
+        } catch (NamingException e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+        if (data == null) {
+            return null;
+        }
+        try {
+            return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(data));
+        } catch (CertificateException e) {
+            throw new RuntimeException("Error deserializing certificate: " + e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void saveCertificate(X509Certificate cert, UseKeyWithType key) {
+        Applications application = Applications.fromUri(key.getApplication());
+        String dn;
+        if (application == Applications.PKIX) {
+            dn = key.getIdentifier() + "," + rootDN;
+        } else if (application == Applications.SERVICE_SOAP) {
+            dn = getDnForServiceName(key.getIdentifier());
+        } else {
+            throw new IllegalArgumentException("Unsupported Application " + application);
+        }
+        saveCertificate(cert, dn);
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,122 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.ldap;
+
+public class LdapSchemaConfig {
+    private String certObjectClass = "inetOrgPerson";
+    private String attrUID = "uid";
+    private String attrIssuerID = "manager";
+    private String attrSerialNumber = "employeeNumber";
+    private String attrCrtBinary = "userCertificate;binary";
+    private String constAttrNamesCSV = "sn";
+    private String constAttrValuesCSV = "X509 certificate";
+    private String serviceCertRDNTemplate = "cn=%s,ou=services";
+    private String serviceCertUIDTemplate = "cn=%s";
+    private String trustedAuthorityFilter = "(&(objectClass=inetOrgPerson)(ou:dn:=CAs))";
+    private String intermediateFilter = "(objectClass=*)";
+
+    public String getCertObjectClass() {
+        return certObjectClass;
+    }
+
+    public void setCertObjectClass(String crtObjectClass) {
+        this.certObjectClass = crtObjectClass;
+    }
+
+    public String getAttrUID() {
+        return attrUID;
+    }
+
+    public void setAttrUID(String attrUID) {
+        this.attrUID = attrUID;
+    }
+
+    public String getAttrIssuerID() {
+        return attrIssuerID;
+    }
+
+    public void setAttrIssuerID(String attrIssuerID) {
+        this.attrIssuerID = attrIssuerID;
+    }
+
+    public String getAttrSerialNumber() {
+        return attrSerialNumber;
+    }
+
+    public void setAttrSerialNumber(String attrSerialNumber) {
+        this.attrSerialNumber = attrSerialNumber;
+    }
+
+    public String getAttrCrtBinary() {
+        return attrCrtBinary;
+    }
+
+    public void setAttrCrtBinary(String attrCrtBinary) {
+        this.attrCrtBinary = attrCrtBinary;
+    }
+
+    public String getConstAttrNamesCSV() {
+        return constAttrNamesCSV;
+    }
+
+    public void setConstAttrNamesCSV(String constAttrNamesCSV) {
+        this.constAttrNamesCSV = constAttrNamesCSV;
+    }
+
+    public String getConstAttrValuesCSV() {
+        return constAttrValuesCSV;
+    }
+
+    public void setConstAttrValuesCSV(String constAttrValuesCSV) {
+        this.constAttrValuesCSV = constAttrValuesCSV;
+    }
+
+    public String getServiceCertRDNTemplate() {
+        return serviceCertRDNTemplate;
+    }
+
+    public void setServiceCertRDNTemplate(String serviceCrtRDNTemplate) {
+        this.serviceCertRDNTemplate = serviceCrtRDNTemplate;
+    }
+
+    public String getServiceCertUIDTemplate() {
+        return serviceCertUIDTemplate;
+    }
+
+    public void setServiceCertUIDTemplate(String serviceCrtUIDTemplate) {
+        this.serviceCertUIDTemplate = serviceCrtUIDTemplate;
+    }
+
+    public String getTrustedAuthorityFilter() {
+        return trustedAuthorityFilter;
+    }
+
+    public void setTrustedAuthorityFilter(String trustedAuthorityFilter) {
+        this.trustedAuthorityFilter = trustedAuthorityFilter;
+    }
+
+    public String getIntermediateFilter() {
+        return intermediateFilter;
+    }
+
+    public void setIntermediateFilter(String intermediateFilter) {
+        this.intermediateFilter = intermediateFilter;
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,165 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.ldap;
+
+import java.util.Hashtable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.naming.CommunicationException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.xkms.exception.XKMSException;
+import org.apache.cxf.xkms.model.xkms.ResultMajorEnum;
+import org.apache.cxf.xkms.model.xkms.ResultMinorEnum;
+
+public class LdapSearch {
+    private static final String SECURITY_AUTHENTICATION = "simple";
+    private static final Logger LOG = LogUtils.getL7dLogger(LdapSearch.class);
+    
+    private String ldapuri;
+    private String bindDN;
+    private String bindPassword;
+    private int numRetries;
+    
+    private InitialDirContext dirContext;
+
+    public LdapSearch(String ldapuri, String bindDN, String bindPassword, int numRetries) {
+        this.ldapuri = ldapuri;
+        this.bindDN = bindDN;
+        this.bindPassword = bindPassword;
+        this.numRetries = numRetries;
+    }
+
+    //CHECKSTYLE:OFF
+    private InitialDirContext createInitialContext() throws NamingException {
+        Hashtable<String, String> env = new Hashtable<String, String>(5);
+        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+        env.put(javax.naming.Context.PROVIDER_URL, ldapuri.toString());
+        env.put(javax.naming.Context.SECURITY_AUTHENTICATION, SECURITY_AUTHENTICATION);
+        env.put(javax.naming.Context.SECURITY_PRINCIPAL, bindDN);
+        env.put(javax.naming.Context.SECURITY_CREDENTIALS, bindPassword);
+        return new InitialLdapContext(env, null);
+    }
+    //CHECKSTYLE:ON
+
+    public NamingEnumeration<SearchResult> searchSubTree(String rootEntry, String filter) throws NamingException {
+        int retry = 0;
+        while (true) {
+            try {
+                if (this.dirContext == null) {
+                    this.dirContext = createInitialContext();
+                }
+                SearchControls ctls = new SearchControls();
+                ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+                return dirContext.search(rootEntry, filter, ctls);
+            } catch (CommunicationException e) {
+                LOG.log(Level.WARNING, "Error in ldap search: " + e.getMessage(), e);
+                this.dirContext = null;
+                retry++;
+                if (retry >= numRetries) {
+                    throw new XKMSException(ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_RECEIVER,
+                                            ResultMinorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_FAILURE, "Backend failure");
+                }
+            }
+        }
+    }
+    
+    public Attributes getAttributes(String dn) throws NamingException {
+        int retry = 0;
+        while (true) {
+            try {
+                if (this.dirContext == null) {
+                    this.dirContext = createInitialContext();
+                }
+                return dirContext.getAttributes(dn);
+            } catch (CommunicationException e) {
+                LOG.log(Level.WARNING, "Error in ldap search: " + e.getMessage(), e);
+                this.dirContext = null;
+                retry++;
+                if (retry >= numRetries) {
+                    throw new XKMSException(ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_RECEIVER,
+                                            ResultMinorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_FAILURE, "Backend failure");
+                }
+            }
+        }
+    }
+    
+    public Attribute getAttribute(String dn, String attrName) throws NamingException {
+        Attribute attr = getAttributes(dn).get(attrName);
+        if (attr != null) {
+            return attr;
+        }
+        throw new RuntimeException("Did not find a matching attribute for dn: " + dn 
+                                   + " attributeName: " + attrName);
+    }
+    
+    public Attributes findAttributes(String rootDN, String filter) throws NamingException {
+        NamingEnumeration<SearchResult> answer = searchSubTree(rootDN, filter);
+        if (answer.hasMore()) {
+            SearchResult sr = answer.next();
+            return sr.getAttributes();
+        } else {
+            return null;
+        }
+    }
+
+    public Attribute findAttribute(String rootDN, String filter, String attrName) throws NamingException {
+        Attributes attrs = findAttributes(rootDN, filter);
+        if (attrs != null) {
+            Attribute attr = attrs.get(attrName);
+            if (attr == null) {
+                throw new RuntimeException("Did not find a matching attribute for root: " + rootDN 
+                                           + " filter: " + filter + " attributeName: " + attrName);
+            }
+            return attr;
+        } 
+        return null;
+    }
+
+    public void bind(String dn, Attributes attribs) throws NamingException {
+        int retry = 0;
+        while (true) {
+            try {
+                if (this.dirContext == null) {
+                    this.dirContext = createInitialContext();
+                }
+                dirContext.bind(dn, null, attribs);
+                return;
+            } catch (CommunicationException e) {
+                LOG.log(Level.WARNING, "Error in ldap search: " + e.getMessage(), e);
+                this.dirContext = null;
+                retry++;
+                if (retry >= numRetries) {
+                    throw new XKMSException(ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_RECEIVER,
+                                            ResultMinorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_FAILURE, "Backend failure");
+                }
+            }
+        }
+    }
+
+}

Modified: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java?rev=1493072&r1=1493071&r2=1493072&view=diff
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java (original)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java Fri Jun 14 13:50:30 2013
@@ -26,22 +26,16 @@ import java.security.cert.CertificateEnc
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.util.Collection;
-import java.util.Iterator;
 import java.util.List;
 import java.util.UUID;
 import java.util.logging.Logger;
-import java.util.regex.Matcher;
 
 import javax.xml.bind.JAXBElement;
 import javax.xml.namespace.QName;
 
 import org.apache.cxf.common.logging.LogUtils;
-import org.apache.cxf.xkms.handlers.Applications;
 import org.apache.cxf.xkms.model.xkms.LocateRequestType;
 import org.apache.cxf.xkms.model.xkms.LocateResultType;
-import org.apache.cxf.xkms.model.xkms.ResultMajorEnum;
-import org.apache.cxf.xkms.model.xkms.ResultMinorEnum;
 import org.apache.cxf.xkms.model.xkms.UnverifiedKeyBindingType;
 import org.apache.cxf.xkms.model.xmldsig.KeyInfoType;
 import org.apache.cxf.xkms.model.xmldsig.ObjectFactory;
@@ -113,30 +107,6 @@ public final class X509Utils {
         }
     }
 
-    void addResult(LocateResultType response, Collection<X509Certificate> certificates, List<String> reasons) {
-        String result = null;
-        if (0 != certificates.size()) {
-            result = ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_SUCCESS.value();
-        } else {
-            if ((null != reasons) && (0 != reasons.size())) {
-                // At least one of the components reported a problem, so we
-                // include the reported error code
-                Iterator<String> reason = reasons.iterator();
-                result = reason.next();
-                String minor = reason.next();
-                if (null != minor) {
-                    response.setResultMinor(minor);
-                }
-            } else {
-                // no error here, we simply did not find any matching
-                // certificates
-                result = ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_SUCCESS.value();
-                response.setResultMinor(ResultMinorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_NO_MATCH.value());
-            }
-        }
-        response.setResultMajor(result);
-    }
-
     public static UnverifiedKeyBindingType getUnverifiedKeyBinding(X509Certificate cert)
         throws CertificateEncodingException {
         UnverifiedKeyBindingType unverifiedKeyBinding = new UnverifiedKeyBindingType();
@@ -170,25 +140,4 @@ public final class X509Utils {
         }
     }
 
-    public static String getSubjectDN(String application, String id, String serviceDNTemplate) {
-        if (application.equalsIgnoreCase(Applications.SERVICE_SOAP.getUri())) {
-            return String.format(serviceDNTemplate, id);
-        } else {
-            return id;
-        }
-    }
-
-    public static String getDN(String applicationUri, String identifier, String serviceDNTemplate, String rootDN) {
-        String dn = identifier;
-        if (Applications.SERVICE_SOAP.getUri().equals(applicationUri)) {
-            String escapedIdentifier = identifier.replaceAll("\\/", Matcher.quoteReplacement("\\/"));
-            dn = String.format(serviceDNTemplate, escapedIdentifier);
-        }
-        if ((rootDN != null) && !(rootDN.isEmpty())) {
-            dn = dn + "," + rootDN;
-        }
-        return dn;
-    }
-
-
 }

Modified: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java?rev=1493072&r1=1493071&r2=1493072&view=diff
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java (original)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java Fri Jun 14 13:50:30 2013
@@ -33,7 +33,6 @@ import org.apache.cxf.xkms.model.xkms.Ke
 import org.apache.cxf.xkms.model.xkms.ReasonEnum;
 import org.apache.cxf.xkms.model.xkms.StatusType;
 import org.apache.cxf.xkms.model.xkms.ValidateRequestType;
-import org.apache.cxf.xkms.x509.parser.ValidateRequestParser;
 
 public class DateValidator implements Validator {
 

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,115 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.xkms.x509.validator;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertPathBuilder;
+import java.security.cert.CertPathBuilderException;
+import java.security.cert.CertStore;
+import java.security.cert.CertStoreParameters;
+import java.security.cert.CollectionCertStoreParameters;
+import java.security.cert.PKIXBuilderParameters;
+import java.security.cert.TrustAnchor;
+import java.security.cert.X509CertSelector;
+import java.security.cert.X509Certificate;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.xkms.handlers.Validator;
+import org.apache.cxf.xkms.model.xkms.KeyBindingEnum;
+import org.apache.cxf.xkms.model.xkms.ReasonEnum;
+import org.apache.cxf.xkms.model.xkms.StatusType;
+import org.apache.cxf.xkms.model.xkms.ValidateRequestType;
+import org.apache.cxf.xkms.x509.repo.CertificateRepo;
+
+public class TrustedAuthorityValidator implements Validator {
+
+    private static final Logger LOG = LogUtils.getL7dLogger(TrustedAuthorityValidator.class);
+
+    CertificateRepo certRepo;
+    
+    public TrustedAuthorityValidator(CertificateRepo certRepo) {
+        this.certRepo = certRepo;
+    }
+
+    /**
+     * Checks if a certificate is signed by a trusted authority.
+     * 
+     * @param x509Certificate to check
+     * @return the validity state of the certificate
+     */
+    boolean isCertificateChainValid(List<X509Certificate> certificates) {
+        X509Certificate targetCert = certificates.get(0);
+        X509CertSelector selector = new X509CertSelector();
+        selector.setCertificate(targetCert);
+        try {
+            List<X509Certificate> intermediateCerts = certRepo.getCaCerts();
+            List<X509Certificate> trustedAuthorityCerts = certRepo.getTrustedCaCerts();
+            Set<TrustAnchor> trustAnchors = asTrustAnchors(trustedAuthorityCerts);
+            CertStoreParameters intermediateParams = new CollectionCertStoreParameters(intermediateCerts);
+            CertStoreParameters certificateParams = new CollectionCertStoreParameters(certificates);
+            PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(trustAnchors, selector);
+            pkixParams.addCertStore(CertStore.getInstance("Collection", intermediateParams));
+            pkixParams.addCertStore(CertStore.getInstance("Collection", certificateParams));
+            CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
+            builder.build(pkixParams);
+        } catch (InvalidAlgorithmParameterException e) {
+            throw new RuntimeException(e);
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        } catch (CertPathBuilderException e) {
+            LOG.log(Level.INFO, e.getMessage(), e);
+            return false;
+        }
+        return true;
+    }
+
+    private Set<TrustAnchor> asTrustAnchors(List<X509Certificate> trustedAuthorityCerts) {
+        Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
+        for (X509Certificate trustedAuthorityCert : trustedAuthorityCerts) {
+            trustAnchors.add(new TrustAnchor(trustedAuthorityCert, null));
+        }
+        return trustAnchors;
+    }
+
+    @Override
+    public StatusType validate(ValidateRequestType request) {
+        StatusType status = new StatusType();
+        List<X509Certificate> certificates = ValidateRequestParser.parse(request);
+        if (certificates == null || certificates.isEmpty()) {
+            status.setStatusValue(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_INDETERMINATE);
+            status.getIndeterminateReason().add("http://www.cxf.apache.org/2002/03/xkms#RequestNotSupported");
+        }
+        if (isCertificateChainValid(certificates)) {
+            status.getValidReason().add(ReasonEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_ISSUER_TRUST.value());
+            status.setStatusValue(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_VALID);
+        } else {
+            status.getInvalidReason().add(ReasonEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_ISSUER_TRUST.value());
+            status.setStatusValue(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_INVALID);
+        }
+        return status;
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.validator;
+
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.xkms.exception.XKMSRequestException;
+import org.apache.cxf.xkms.model.xkms.ValidateRequestType;
+import org.apache.cxf.xkms.model.xmldsig.X509DataType;
+import org.apache.cxf.xkms.x509.utils.X509Utils;
+
+public final class ValidateRequestParser {
+
+    private static final Logger LOG = LogUtils.getL7dLogger(ValidateRequestParser.class);
+
+    private ValidateRequestParser() {
+    }
+
+    /**
+     * Extract the X509 certificates from ValidateRequestType and return them as list.
+     */
+    public static List<X509Certificate> parse(ValidateRequestType request) {
+        List<X509Certificate> certs = new ArrayList<X509Certificate>();
+
+        if ((request.getQueryKeyBinding()) != null && (request.getQueryKeyBinding().getKeyInfo() != null)) {
+            List<Object> keyInfoContent = request.getQueryKeyBinding().getKeyInfo().getContent();
+            for (Object keyInfoObject : keyInfoContent) {
+                if (keyInfoObject instanceof JAXBElement<?>) {
+                    JAXBElement<?> dataInstance = (JAXBElement<?>) keyInfoObject;
+                    if (X509Utils.X509_DATA.equals(dataInstance.getName())) {
+                        try {
+                            X509Utils.parseX509Data((X509DataType) dataInstance.getValue(), certs);
+                            LOG.fine("Extracted " + certs.size() + " certificates from ValidateRequest");
+                        } catch (CertificateException e) {
+                            throw new XKMSRequestException("Corrupted X509 certificate in request: " + e.getMessage(),
+                                    e);
+                        }
+                    }
+                }
+            }
+        }
+        return certs;
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,109 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.handlers;
+
+import java.security.cert.CertificateException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+
+import org.apache.cxf.xkms.client.X509AppId;
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.handlers.XKMSConstants;
+import org.apache.cxf.xkms.model.xkms.LocateRequestType;
+import org.apache.cxf.xkms.model.xkms.MessageAbstractType;
+import org.apache.cxf.xkms.model.xkms.QueryKeyBindingType;
+import org.apache.cxf.xkms.model.xkms.UnverifiedKeyBindingType;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.repo.CertificateRepo;
+import org.apache.cxf.xkms.x509.repo.ldap.LdapCertificateRepo;
+import org.apache.cxf.xkms.x509.repo.ldap.LdapSchemaConfig;
+import org.apache.cxf.xkms.x509.repo.ldap.LdapSearch;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test needs a real LDAP server.
+ */
+public class X509LocatorTest {
+
+    private static final org.apache.cxf.xkms.model.xkms.ObjectFactory XKMS_OF = 
+        new org.apache.cxf.xkms.model.xkms.ObjectFactory();
+
+    CertificateRepo certRepo;
+    X509Locator locator;
+
+    @Ignore
+    @Before
+    public void setUpLdapRepo() throws CertificateException {
+        LdapSearch ldapSearch = new LdapSearch("ldap://localhost:2389", 
+            "cn=Directory Manager,dc=example,dc=com", "test", 2);
+        LdapSchemaConfig ldapConfig = new LdapSchemaConfig();
+        ldapConfig.setAttrCrtBinary("userCertificate;binary");
+        ldapConfig.setAttrIssuerID("manager");
+        ldapConfig.setAttrSerialNumber("employeeNumber");
+        ldapConfig.setAttrUID("uid");
+        ldapConfig.setCertObjectClass("inetOrgPerson");
+        ldapConfig.setConstAttrNamesCSV("sn");
+        ldapConfig.setConstAttrValuesCSV("X509 certificate");
+        ldapConfig.setIntermediateFilter("(objectClass=*)");
+        ldapConfig.setServiceCertRDNTemplate("cn=%s,ou=services");
+        ldapConfig.setServiceCertUIDTemplate("cn=%s");
+        ldapConfig.setTrustedAuthorityFilter("(&(objectClass=inetOrgPerson)(ou:dn:=CAs))");
+        certRepo = new LdapCertificateRepo(ldapSearch, ldapConfig, "dc=example,dc=com");
+        locator = new X509Locator(certRepo);
+    }
+
+    @Ignore
+    @Test
+    public void locate() {
+        List<X509AppId> ids = new ArrayList<X509AppId>();
+        X509AppId id = new X509AppId(Applications.PKIX, "alice");
+        ids.add(id);
+        LocateRequestType request = prepareLocateXKMSRequest(ids);
+        UnverifiedKeyBindingType result = locator.locate(request);
+        Assert.assertNotNull(result.getKeyInfo());
+    }
+
+    private LocateRequestType prepareLocateXKMSRequest(List<X509AppId> ids) {
+        QueryKeyBindingType queryKeyBindingType = XKMS_OF.createQueryKeyBindingType();
+
+        for (X509AppId id : ids) {
+            UseKeyWithType useKeyWithType = XKMS_OF.createUseKeyWithType();
+            useKeyWithType.setIdentifier(id.getId());
+            useKeyWithType.setApplication(id.getApplication().getUri());
+
+            queryKeyBindingType.getUseKeyWith().add(useKeyWithType);
+        }
+
+        LocateRequestType locateRequestType = XKMS_OF.createLocateRequestType();
+        locateRequestType.setQueryKeyBinding(queryKeyBindingType);
+        setGenericRequestParams(locateRequestType);
+        return locateRequestType;
+    }
+
+    private void setGenericRequestParams(MessageAbstractType request) {
+        request.setService(XKMSConstants.XKMS_ENDPOINT_NAME);
+        request.setId(UUID.randomUUID().toString());
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.file;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FileCertificateRepoTest {
+    private static final String EXAMPLE_SUBJECT_DN = "CN=www.issuer.com, L=CGN, ST=NRW, C=DE, O=Issuer";
+    private static final String EXPECTED_CERT_FILE_NAME = "CN-www.issuer.com_L-CGN_ST-NRW_C-DE_O-Issuer-"
+                                + "11688544847478700689-CN-www.issuer.com_L-CGN_ST-NRW_C-DE_O-Issuer.cer";
+
+    @Test
+    public void testSaveAndFind() throws CertificateException, IOException {
+        File storageDir = new File("target/teststore1");
+        storageDir.mkdirs();
+        FileCertificateRepo fileRegisterHandler = new FileCertificateRepo("target/teststore1");
+        InputStream is = this.getClass().getResourceAsStream("/store1/" + EXPECTED_CERT_FILE_NAME);
+        if (is == null) {
+            throw new RuntimeException("Can not find path " + is + " in classpath");
+        }
+        X509Certificate cert = loadTestCert(is);
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXAMPLE_SUBJECT_DN);
+        fileRegisterHandler.saveCertificate(cert, key);
+
+        File certFile = new File(storageDir, EXPECTED_CERT_FILE_NAME);
+        Assert.assertTrue("Cert file " + certFile + " should exist", certFile.exists());
+        FileInputStream fis = new FileInputStream(certFile);
+        X509Certificate outCert = loadTestCert(fis);
+        Assert.assertEquals(cert, outCert);
+
+        X509Certificate resultCert = fileRegisterHandler.findBySubjectDn(EXAMPLE_SUBJECT_DN);
+        Assert.assertNotNull(resultCert);
+    }
+
+    private X509Certificate loadTestCert(InputStream is) throws IOException, CertificateException {
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+        return (X509Certificate)factory.generateCertificate(is);
+    }
+
+    private String read(InputStream is) throws java.io.IOException {
+        StringBuffer fileData = new StringBuffer(1000);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+        char[] buf = new char[1024];
+        int numRead = 0;
+        while ((numRead = reader.read(buf)) != -1) {
+            String readData = String.valueOf(buf, 0, numRead);
+            fileData.append(readData);
+            buf = new char[1024];
+        }
+        reader.close();
+        return fileData.toString();
+    }
+
+    @SuppressWarnings("unused")
+    private void convertBase64ToCer(String sourcePath, String destPath) throws IOException {
+        InputStream is = this.getClass().getResourceAsStream(sourcePath);
+        String certString = read(is);
+        is.close();
+        byte[] certData = DatatypeConverter.parseBase64Binary(certString);
+        File file = new File(destPath);
+        FileOutputStream fos = new FileOutputStream(file);
+        BufferedOutputStream bos = new BufferedOutputStream(fos);
+        bos.write(certData);
+        bos.close();
+        fos.close();
+    }
+
+    @Test
+    public void testFindBySubjectName() throws CertificateException {
+        File storageDir = new File("src/test/resources/store1");
+        Assert.assertTrue(storageDir.exists());
+        Assert.assertTrue(storageDir.isDirectory());
+        FileCertificateRepo persistenceManager = new FileCertificateRepo("src/test/resources/store1");
+        X509Certificate resCert = persistenceManager.findBySubjectDn(EXAMPLE_SUBJECT_DN);
+        Assert.assertNotNull(resCert);
+    }
+
+    @Test
+    public void testConvertDnForFileSystem() throws CertificateException {
+        String convertedName = new FileCertificateRepo("src/test/resources/store1")
+            .convertDnForFileSystem(EXAMPLE_SUBJECT_DN);
+        Assert.assertEquals("CN-www.issuer.com_L-CGN_ST-NRW_C-DE_O-Issuer", convertedName);
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,146 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.ldap;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.repo.CertificateRepo;
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Tests need a real ldap server
+ */
+public class LDAPCertificateRepoTest {
+    private static final String EXPECTED_SUBJECT_DN = "CN=www.issuer.com, L=CGN, ST=NRW, C=DE, O=Issuer";
+    private static final String ROOT_DN = "dc=example,dc=com";
+    private static final String EXPECTED_SUBJECT_DN2 = "CN=www.issuer.com,L=CGN,ST=NRW,C=DE,O=Issuer";
+    private static final String EXPECTED_SERVICE_URI = "http://myservice.apache.org/MyServiceName";
+    private static final String EXPECTED_DN_FOR_SERVICE = 
+            "cn=http:\\/\\/myservice.apache.org\\/MyServiceName,ou=services";
+    private static final LdapSchemaConfig LDAP_CERT_CONFIG = new LdapSchemaConfig();
+
+    @Test
+    @Ignore
+    public void testFindUserCert() throws URISyntaxException, NamingException, CertificateException {
+        CertificateRepo persistenceManager = createLdapCertificateRepo();
+        testFindBySubjectDnInternal(persistenceManager);
+    }
+
+    @Test
+    @Ignore
+    public void testFindUserCertForNonExistantDn() throws URISyntaxException, NamingException, CertificateException {
+        CertificateRepo persistenceManager = createLdapCertificateRepo();
+        X509Certificate cert = persistenceManager.findBySubjectDn("CN=wrong");
+        Assert.assertNull("Certifiacte should be null", cert);
+    }
+
+    @Test
+    @Ignore
+    public void testFindServiceCert() throws URISyntaxException, NamingException, CertificateException {
+        CertificateRepo persistenceManager = createLdapCertificateRepo();
+        String serviceUri = "cn=http:\\/\\/myservice.apache.org\\/MyServiceName,ou=services";
+        X509Certificate cert = persistenceManager.findByServiceName(serviceUri);
+        Assert.assertEquals(EXPECTED_SUBJECT_DN, cert.getSubjectDN().toString());
+    }
+
+    @Test
+    @Ignore
+    public void testSave() throws Exception {
+        CertificateRepo persistenceManager = createLdapCertificateRepo();
+        File certFile = new File("src/test/java/cert1.cer");
+        Assert.assertTrue(certFile.exists());
+        FileInputStream fis = new FileInputStream(certFile);
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+        X509Certificate cert = (X509Certificate) factory.generateCertificate(fis);
+
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXPECTED_SUBJECT_DN);
+        persistenceManager.saveCertificate(cert, key);
+        testFindBySubjectDnInternal(persistenceManager);
+    }
+
+    private CertificateRepo createLdapCertificateRepo() throws CertificateException {
+        LdapSearch ldapSearch = new LdapSearch("ldap://localhost:2389", 
+            "cn=Directory Manager,dc=example,dc=com", "test", 2);
+        return new LdapCertificateRepo(ldapSearch, LDAP_CERT_CONFIG, "dc=example,dc=com");
+    }
+
+    private void testFindBySubjectDnInternal(CertificateRepo persistenceManager) throws CertificateException {
+        X509Certificate cert2 = persistenceManager.findBySubjectDn(EXPECTED_SUBJECT_DN);
+        Assert.assertEquals(EXPECTED_SUBJECT_DN, cert2.getSubjectDN().toString());
+    }
+    
+    @Test
+    public void testSaveUserCert() throws Exception {
+        IMocksControl c = EasyMock.createControl();
+        LdapSearch ldapSearch = c.createMock(LdapSearch.class);
+        ldapSearch.bind(EasyMock.eq(EXPECTED_SUBJECT_DN2 + "," + ROOT_DN), EasyMock.anyObject(Attributes.class));
+        EasyMock.expectLastCall().once();
+        LdapCertificateRepo ldapCertRepo = new LdapCertificateRepo(ldapSearch, LDAP_CERT_CONFIG, ROOT_DN);
+        X509Certificate cert = getTestCert();
+
+        c.replay();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXPECTED_SUBJECT_DN2);
+        ldapCertRepo.saveCertificate(cert, key);
+        c.verify();
+    }
+
+    @Test
+    public void testSaveServiceCert() throws Exception {
+        IMocksControl c = EasyMock.createControl();
+        LdapSearch ldapSearch = c.createMock(LdapSearch.class);
+        ldapSearch.bind(EasyMock.eq(EXPECTED_DN_FOR_SERVICE + "," + ROOT_DN), EasyMock.anyObject(Attributes.class));
+        EasyMock.expectLastCall().once();
+        LdapCertificateRepo ldapCertRepo = new LdapCertificateRepo(ldapSearch, LDAP_CERT_CONFIG, ROOT_DN);
+        X509Certificate cert = getTestCert();
+
+        c.replay();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.SERVICE_SOAP.getUri());
+        key.setIdentifier(EXPECTED_SERVICE_URI);
+        ldapCertRepo.saveCertificate(cert, key);
+        c.verify();
+    }
+
+    private X509Certificate getTestCert() throws FileNotFoundException, CertificateException {
+        File certFile = new File("src/test/resources/cert1.cer");
+        Assert.assertTrue(certFile.exists());
+        FileInputStream fis = new FileInputStream(certFile);
+        CertificateFactory factory = CertificateFactory.getInstance("X.509");
+        return (X509Certificate) factory.generateCertificate(fis);
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,51 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.repo.ldap;
+
+import java.net.URISyntaxException;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchResult;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Tests need a real ldap server
+ */
+public class LDAPSearchTest {
+    @Test
+    @Ignore
+    public void testSearch() throws URISyntaxException, NamingException {
+        LdapSearch ldapSearch = new LdapSearch("ldap://localhost:2389",
+                                               "cn=Directory Manager,dc=example,dc=com", "test", 2);
+        NamingEnumeration<SearchResult> answer = ldapSearch.searchSubTree("dc=example, dc=com",
+                                                                          "(cn=Testuser)");
+        while (answer.hasMore()) {
+            SearchResult sr = answer.next();
+            Attributes attrs = sr.getAttributes();
+            Attribute cn = attrs.get("sn");
+            System.out.println(cn.get());
+        }
+    }
+
+}

Modified: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/utils/X509UtilsTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/utils/X509UtilsTest.java?rev=1493072&r1=1493071&r2=1493072&view=diff
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/utils/X509UtilsTest.java (original)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/utils/X509UtilsTest.java Fri Jun 14 13:50:30 2013
@@ -27,9 +27,8 @@ import javax.xml.bind.JAXBException;
 
 import org.apache.cxf.xkms.exception.XKMSRequestException;
 import org.apache.cxf.xkms.model.xkms.ValidateRequestType;
-import org.apache.cxf.xkms.x509.handlers.BasicValidationTest;
-import org.apache.cxf.xkms.x509.parser.ValidateRequestParser;
-
+import org.apache.cxf.xkms.x509.validator.BasicValidationTest;
+import org.apache.cxf.xkms.x509.validator.ValidateRequestParser;
 import org.junit.Assert;
 import org.junit.Test;
 

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/BasicValidationTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/BasicValidationTest.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/BasicValidationTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/BasicValidationTest.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.xkms.x509.validator;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+
+import org.junit.Before;
+
+public class BasicValidationTest {
+    protected JAXBContext jc;
+    protected Unmarshaller u;
+
+
+    @Before
+    public void setUp() throws JAXBException {
+        jc = JAXBContext.newInstance("org.apache.cxf.xkms.model.xkms");
+        u = jc.createUnmarshaller();
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/DateValidatorTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/DateValidatorTest.java?rev=1493072&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/DateValidatorTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/validator/DateValidatorTest.java Fri Jun 14 13:50:30 2013
@@ -0,0 +1,60 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.xkms.x509.validator;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+
+import org.apache.cxf.xkms.model.xkms.KeyBindingEnum;
+import org.apache.cxf.xkms.model.xkms.ReasonEnum;
+import org.apache.cxf.xkms.model.xkms.StatusType;
+import org.apache.cxf.xkms.model.xkms.ValidateRequestType;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class DateValidatorTest extends BasicValidationTest {
+
+    @Test
+    public void validateDateOK() throws JAXBException {
+        StatusType result = processRequest("/validateRequestOK.xml");
+        Assert.assertEquals(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_VALID, result.getStatusValue());
+        Assert.assertFalse(result.getValidReason().isEmpty());
+        Assert.assertEquals(ReasonEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_VALIDITY_INTERVAL.value(), result.getValidReason()
+                .get(0));
+    }
+
+    @Test
+    public void validateDateExpired() throws JAXBException {
+        StatusType result = processRequest("/validateRequestExpired.xml");
+        Assert.assertEquals(result.getStatusValue(), KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_INVALID);
+        Assert.assertFalse(result.getInvalidReason().isEmpty());
+        Assert.assertEquals(ReasonEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_VALIDITY_INTERVAL.value(), result
+                .getInvalidReason().get(0));
+    }
+
+    private StatusType processRequest(String path) throws JAXBException {
+        @SuppressWarnings("unchecked")
+        JAXBElement<ValidateRequestType> request = (JAXBElement<ValidateRequestType>) u.unmarshal(this.getClass()
+                .getResourceAsStream(path));
+        DateValidator validator = new DateValidator();
+        return validator.validate(request.getValue());
+
+    }
+
+}



Mime
View raw message