You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by cs...@apache.org on 2013/08/10 09:52:39 UTC
svn commit: r1512574 [5/6] - in /cxf/branches/2.7.x-fixes: parent/ services/
services/xkms/ services/xkms/xkms-client/ services/xkms/xkms-client/src/
services/xkms/xkms-client/src/main/
services/xkms/xkms-client/src/main/java/ services/xkms/xkms-client...
Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509Register.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509Register.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509Register.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/X509Register.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,151 @@
+/**
+ * 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.Register;
+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.RecoverRequestType;
+import org.apache.cxf.xkms.model.xkms.RecoverResultType;
+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 X509Register implements Register {
+
+ protected final CertificateFactory certFactory;
+ private CertificateRepo certRepo;
+
+ public X509Register(CertificateRepo certRepo) throws CertificateException {
+ this.certRepo = certRepo;
+ certFactory = CertificateFactory.getInstance("X.509");
+ }
+
+ @Override
+ public boolean canProcess(RequestAbstractType request) {
+ if (request instanceof RecoverRequestType) {
+ return false;
+ }
+ 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;
+ }
+
+ @Override
+ public RecoverResultType recover(RecoverRequestType request, RecoverResultType response) {
+ throw new UnsupportedOperationException("Recover is currently not supported");
+ }
+
+}
Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepo.java Sat Aug 10 07:52:35 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/CertificateRepoFactory.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,43 @@
+/**
+ * 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 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) {
+ if ("ldap".equals(type)) {
+ return new LdapCertificateRepo(ldapSearch, ldapSchemaConfig, rootDN);
+ } else if ("file".equals(type)) {
+ return new FileCertificateRepo(storageDir);
+ } else {
+ throw new RuntimeException("Invalid repo type " + type + ". Valid types are file, ldap");
+ }
+ }
+
+}
Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepo.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,244 @@
+/**
+ * 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) {
+ storageDir = new File(path);
+ try {
+ this.certFactory = CertificateFactory.getInstance("X.509");
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ 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);
+ LOG.debug("Searching for " + subjectDn + ". Checking cert "
+ + cert.getSubjectDN().getName() + ", " + cert.getSubjectX500Principal().getName());
+ 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapCertificateRepo.java Sat Aug 10 07:52:35 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSchemaConfig.java Sat Aug 10 07:52:35 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/repo/ldap/LdapSearch.java Sat Aug 10 07:52:35 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");
+ }
+ }
+ }
+ }
+
+}
Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,143 @@
+/**
+ * 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.utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.xkms.model.xkms.LocateRequestType;
+import org.apache.cxf.xkms.model.xkms.LocateResultType;
+import org.apache.cxf.xkms.model.xkms.UnverifiedKeyBindingType;
+import org.apache.cxf.xkms.model.xmldsig.KeyInfoType;
+import org.apache.cxf.xkms.model.xmldsig.ObjectFactory;
+import org.apache.cxf.xkms.model.xmldsig.X509DataType;
+
+public final class X509Utils {
+ public static final QName X509_DATA = new QName("http://www.w3.org/2000/09/xmldsig#", "X509Data");
+
+ public static final QName X509_KEY_NAME = new QName("http://www.w3.org/2000/09/xmldsig#", "KeyName");
+
+ public static final QName X509_ISSUER_SERIAL = new QName("http://www.w3.org/2000/09/xmldsig#", "X509IssuerSerial");
+
+ public static final QName X509_SUBJECT_NAME = new QName("http://www.w3.org/2000/09/xmldsig#", "X509SubjectName");
+
+ public static final QName X509_CERTIFICATE = new QName("http://www.w3.org/2000/09/xmldsig#", "X509Certificate");
+
+ private static final Logger LOG = LogUtils.getL7dLogger(X509Utils.class);
+
+ private static final CertificateFactory X509_FACTORY;
+
+
+ static {
+ try {
+ X509_FACTORY = CertificateFactory.getInstance("X.509");
+ } catch (CertificateException e) {
+ throw new IllegalStateException("Cannot initialize X509 CertificateFactory: " + e.getMessage(), e);
+ }
+ }
+
+ private X509Utils() {
+
+ }
+
+ public static void parseX509Data(X509DataType x509Data, List<X509Certificate> certs) throws CertificateException {
+ List<Object> dataList = x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName();
+ for (Object x509Object : dataList) {
+ if (x509Object instanceof JAXBElement<?>) {
+ JAXBElement<?> x509Item = (JAXBElement<?>) x509Object;
+ X509Certificate certificate = parseX509Item(x509Item);
+ if (null != certificate) {
+ certs.add(certificate);
+ }
+ }
+ }
+ }
+
+ private static X509Certificate parseX509Item(JAXBElement<?> x509Item) throws CertificateException {
+ QName x509ItemName = x509Item.getName();
+ if (X509_CERTIFICATE.equals(x509ItemName)) {
+ X509Certificate certificate;
+ certificate = extractCertificate(x509Item);
+ LOG.fine("Extracted " + certificate.getSubjectX500Principal().getName());
+ return certificate;
+ }
+ return null;
+ }
+
+ private static X509Certificate extractCertificate(JAXBElement<?> x509Item) throws CertificateException {
+ @SuppressWarnings("unchecked")
+ JAXBElement<byte[]> byteElement = (JAXBElement<byte[]>) x509Item;
+ byte[] bytes = byteElement.getValue();
+ InputStream stream = new ByteArrayInputStream(bytes);
+ Certificate certificate = X509_FACTORY.generateCertificate(stream);
+ if (certificate instanceof X509Certificate) {
+ return (X509Certificate) certificate;
+ } else {
+ throw new CertificateException("Unsupported certificate type encountered: "
+ + certificate.getClass().getName());
+ }
+ }
+
+ public static UnverifiedKeyBindingType getUnverifiedKeyBinding(X509Certificate cert)
+ throws CertificateEncodingException {
+ UnverifiedKeyBindingType unverifiedKeyBinding = new UnverifiedKeyBindingType();
+ unverifiedKeyBinding.setKeyInfo(getKeyInfo(cert));
+ return unverifiedKeyBinding;
+ }
+
+ public static KeyInfoType getKeyInfo(X509Certificate cert) throws CertificateEncodingException {
+ KeyInfoType keyInfo = new KeyInfoType();
+ JAXBElement<byte[]> certificate = new ObjectFactory().createX509DataTypeX509Certificate(cert.getEncoded());
+ X509DataType x509DataType = new X509DataType();
+ List<Object> x509DataContent = x509DataType.getX509IssuerSerialOrX509SKIOrX509SubjectName();
+ x509DataContent.add(certificate);
+ JAXBElement<X509DataType> x509Data = new ObjectFactory().createX509Data(x509DataType);
+ List<Object> keyInfoContent = keyInfo.getContent();
+ keyInfoContent.add(x509Data);
+ return keyInfo;
+ }
+
+ LocateResultType createResponse(LocateRequestType request) {
+ LocateResultType ret = new LocateResultType();
+ ret.setId(UUID.randomUUID().toString());
+ ret.setRequestId(request.getId());
+ ret.setService("http://services.sopera.org/xkms/v2.0");
+ return ret;
+ }
+
+ public static void assertElementNotNull(Object element, Class<?> elementClass) {
+ if (element == null) {
+ throw new IllegalArgumentException(elementClass.getName() + " must be set");
+ }
+ }
+
+}
Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,98 @@
+/**
+ * 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.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+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;
+
+public class DateValidator implements Validator {
+
+ private static final Logger LOG = LogUtils.getL7dLogger(DateValidator.class);
+
+ /**
+ * Checks if a certificate is within its validity period.
+ *
+ * @param certificate to check
+ * @return the validity state of the certificate
+ */
+ public boolean isCertificateValid(X509Certificate certificate) {
+ Date date = Calendar.getInstance().getTime();
+
+ try {
+ certificate.checkValidity(date);
+ } catch (CertificateNotYetValidException e) {
+ return false;
+ } catch (CertificateExpiredException e) {
+ return false;
+ }
+ /*
+ * TODO: clarify use of KeyUsage with customer if (null == certificate.getKeyUsage()) { return false; }
+ * boolean[] keyUsage = certificate.getKeyUsage(); if (!keyUsage[KeyUsage.digitalSignature.ordinal()] ||
+ * !keyUsage[KeyUsage.dataEncipherment.ordinal()] || keyUsage[KeyUsage.encipherOnly.ordinal()] ||
+ * keyUsage[KeyUsage.decipherOnly.ordinal()]) { return false; }
+ */
+ return true;
+ }
+
+ @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_VALIDITY_INTERVAL.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_VALIDITY_INTERVAL.value());
+ status.setStatusValue(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_INVALID);
+ }
+ return status;
+ }
+
+ public boolean isCertificateChainValid(List<X509Certificate> certificates) {
+ if (certificates == null) {
+ return false;
+ }
+
+ for (X509Certificate x509Certificate : certificates) {
+ if (!isCertificateValid(x509Certificate)) {
+ LOG.severe("Certificate is expired: " + x509Certificate.getSubjectX500Principal());
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
Added: cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/TrustedAuthorityValidator.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,116 @@
+/**
+ * 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));
+ pkixParams.setRevocationEnabled(false);
+ 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/ValidateRequestParser.java Sat Aug 10 07:52:35 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/X509LocatorTest.java Sat Aug 10 07:52:35 2013
@@ -0,0 +1,88 @@
+/**
+ * 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.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.UUID;
+
+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.easymock.EasyMock;
+import org.junit.Assert;
+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();
+
+ @Test
+ public void locate() throws CertificateException {
+ CertificateRepo certRepo = EasyMock.createMock(CertificateRepo.class);
+ EasyMock.expect(certRepo.findBySubjectDn(EasyMock.eq("alice"))).andReturn(getAliceCert());
+ EasyMock.replay(certRepo);
+ X509Locator locator = new X509Locator(certRepo);
+ LocateRequestType request = prepareLocateXKMSRequest();
+ UnverifiedKeyBindingType result = locator.locate(request);
+ Assert.assertNotNull(result.getKeyInfo());
+ }
+
+ private X509Certificate getAliceCert() {
+ try {
+ CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
+ InputStream is = this.getClass().getResourceAsStream("/cert1.cer");
+ return (X509Certificate)certFactory.generateCertificate(is);
+ } catch (CertificateException e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ private LocateRequestType prepareLocateXKMSRequest() {
+ QueryKeyBindingType queryKeyBindingType = XKMS_OF.createQueryKeyBindingType();
+
+ UseKeyWithType useKeyWithType = XKMS_OF.createUseKeyWithType();
+ useKeyWithType.setIdentifier("alice");
+ useKeyWithType.setApplication(Applications.PKIX.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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/file/FileCertificateRepoTest.java Sat Aug 10 07:52:35 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPCertificateRepoTest.java Sat Aug 10 07:52:35 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/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java
URL: http://svn.apache.org/viewvc/cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java?rev=1512574&view=auto
==============================================================================
--- cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java (added)
+++ cxf/branches/2.7.x-fixes/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/repo/ldap/LDAPSearchTest.java Sat Aug 10 07:52:35 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());
+ }
+ }
+
+}