cxf-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ashaki...@apache.org
Subject svn commit: r1484133 [5/6] - in /cxf/trunk/services: ./ xkms/ xkms/xkms-client/ xkms/xkms-client/src/ xkms/xkms-client/src/main/ xkms/xkms-client/src/main/java/ xkms/xkms-client/src/main/java/org/ xkms/xkms-client/src/main/java/org/apache/ xkms/xkms-cl...
Date Sat, 18 May 2013 16:04:40 GMT
Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LDAPSearch.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LDAPSearch.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LDAPSearch.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LDAPSearch.java Sat May 18 16:04:37 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.handlers;
+
+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/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LdapRegisterHandler.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LdapRegisterHandler.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LdapRegisterHandler.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/handlers/LdapRegisterHandler.java Sat May 18 16:04:37 2013
@@ -0,0 +1,81 @@
+/**
+ * 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.security.cert.X509Certificate;
+import java.util.regex.Matcher;
+
+import javax.naming.directory.Attributes;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+
+import org.apache.cxf.xkms.exception.XKMSArgumentNotMatchException;
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+
+public class LdapRegisterHandler extends AbstractX509RegisterHandler {
+
+    private static final String OU_SERVICES = "ou=services";
+    private static final String CN_PREFIX = "cn=";
+    private static final String INET_ORG_PERSON = "inetOrgPerson";
+    private static final String ATTR_OBJECT_CLASS = "objectClass";
+    private static final String ATTR_SN = "sn";
+    private static final String ATTR_UID_NAME = "uid";
+    private static final String ATTR_ISSUER_IDENTIFIER = "manager";
+    private static final String ATTR_SERIAL_NUMBER = "employeeNumber";
+    private static final String ATTR_USER_CERTIFICATE_BINARY = "userCertificate;binary";
+
+    private final LDAPSearch ldapSearch;
+    private final String rootDN;
+
+    public LdapRegisterHandler(LDAPSearch ldapSearch, String rootDN) throws CertificateException {
+        super();
+        this.ldapSearch = ldapSearch;
+        this.rootDN = rootDN;
+    }
+
+    @Override
+    public void saveCertificate(X509Certificate cert, UseKeyWithType id) {
+        Attributes attribs = new BasicAttributes();
+        attribs.put(new BasicAttribute(ATTR_OBJECT_CLASS, INET_ORG_PERSON));
+        attribs.put(new BasicAttribute(ATTR_SN, "X509 certificate"));
+        attribs.put(new BasicAttribute(ATTR_UID_NAME, cert.getSubjectX500Principal().getName()));
+        attribs.put(new BasicAttribute(ATTR_SERIAL_NUMBER, cert.getSerialNumber().toString(16)));
+        attribs.put(new BasicAttribute(ATTR_ISSUER_IDENTIFIER, cert.getIssuerX500Principal().getName()));
+        try {
+            attribs.put(new BasicAttribute(ATTR_USER_CERTIFICATE_BINARY, cert.getEncoded()));
+            String dn = getDN(id.getApplication(), id.getIdentifier());
+            ldapSearch.bind(dn, attribs);
+        } catch (Exception e) {
+            throw new RuntimeException(e.getMessage(), e);
+        }
+    }
+
+    private String getDN(String applicationUri, String identifier) {
+        if (Applications.PKIX.getUri().equals(applicationUri)) {
+            return identifier + "," + rootDN;
+        } else if (Applications.SERVICE_SOAP.getUri().equals(applicationUri)) {
+            String escapedIdentifier = identifier.replaceAll("\\/", Matcher.quoteReplacement("\\/"));
+            return CN_PREFIX + escapedIdentifier + "," + OU_SERVICES + "," + rootDN;
+        } else {
+            throw new XKMSArgumentNotMatchException("Unsupported application uri: " + applicationUri);
+        }
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/FileLocator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/FileLocator.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/FileLocator.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/FileLocator.java Sat May 18 16:04:37 2013
@@ -0,0 +1,216 @@
+/**
+ * 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.locator;
+
+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.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.cxf.xkms.exception.XKMSArgumentNotMatchException;
+import org.apache.cxf.xkms.exception.XKMSCertificateException;
+import org.apache.cxf.xkms.exception.XKMSConfigurationException;
+import org.apache.cxf.xkms.exception.XKMSTooManyResponsesException;
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.handlers.Locator;
+import org.apache.cxf.xkms.model.xkms.LocateRequestType;
+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.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.parser.LocateRequestParser;
+import org.apache.cxf.xkms.x509.utils.X509Utils;
+
+public class FileLocator implements Locator {
+
+    private static final String CN_PREFIX = "cn=";
+    //private static final Logger LOG = LoggerFactory.getLogger(FilePersistenceManager.class);
+    private final File storageDir;
+    private final CertificateFactory certFactory;
+
+    public FileLocator(File storageDir) throws CertificateException {
+        if (storageDir == null) {
+            throw new IllegalStateException("File Persistence: root certificate directory is not initialized");
+        }
+        this.storageDir = storageDir;
+        this.certFactory = CertificateFactory.getInstance("X.509");
+    }
+
+    @Override
+    public UnverifiedKeyBindingType locate(LocateRequestType request) {
+
+        List<UseKeyWithType> keyIDs = LocateRequestParser.parse(request);
+
+        X509Certificate cert = findCertificate(keyIDs);
+
+        if (cert == null) {
+            return null;
+        }
+
+        try {
+            UnverifiedKeyBindingType result = new UnverifiedKeyBindingType();
+            result.setKeyInfo(X509Utils.getKeyInfo(cert));
+            return result;
+        } catch (CertificateEncodingException e) {
+            throw new XKMSCertificateException("Cannot encode certificate: " + e.getMessage(), e);
+        }
+    }
+
+    public X509Certificate findCertificate(List<UseKeyWithType> ids) {
+        List<X509Certificate> certs = Collections.emptyList();
+        if ((ids.size() == 1) && (getIdForApplication(Applications.PKIX, ids) != null)
+                || (getIdForApplication(Applications.SERVICE_SOAP, ids) != null)) {
+            String subjectDN = getSubjectDN(ids.get(0).getApplication(), ids.get(0).getIdentifier());
+            certs = findCertificateBySubjectDn(subjectDN);
+        }
+        String issuer = getIdForApplication(Applications.ISSUER, ids);
+        String serial = getIdForApplication(Applications.SERIAL, ids);
+        if ((issuer != null) && (serial != null)) {
+            certs = findCertificateByIssuerSerial(issuer, serial);
+        }
+        if (certs.size() > 1) {
+            throw new XKMSTooManyResponsesException("More than one matching key was found for: " + ids);
+        }
+        if (certs.size() == 0) {
+            return null;
+        }
+        return certs.get(0);
+    }
+
+    private String getSubjectDN(String applicationUri, String identifier) {
+        if (Applications.PKIX.getUri().equals(applicationUri)) {
+            return identifier;
+        } else if (Applications.SERVICE_SOAP.getUri().equals(applicationUri)) {
+            return CN_PREFIX + identifier;
+        } else {
+            throw new XKMSArgumentNotMatchException("Unsupported application uri: " + applicationUri);
+        }
+    }
+
+    private List<X509Certificate> findCertificateBySubjectDn(String subjectDN) {
+        List<X509Certificate> result = new ArrayList<X509Certificate>();
+        File[] list = getX509Files();
+        //        String searchId = DnUtils.extractMostSignificantAttribute(subjectDN);
+        for (File certFile : list) {
+            try {
+                X509Certificate cert = readCertificate(certFile);
+                //                String id = DnUtils.extractMostSignificantAttribute(cert.getSubjectDN().getName());
+                //                if (searchId.equalsIgnoreCase(id)) {
+                if (subjectDN.equalsIgnoreCase(cert.getSubjectDN().getName())
+                        || subjectDN.equalsIgnoreCase(cert.getSubjectX500Principal().getName())) {
+                    result.add(cert);
+                }
+            } catch (Exception e) {
+                throw new RuntimeException("Error reading certificate for " + subjectDN + ": " + e.getMessage(), e);
+            }
+
+        }
+        return result;
+    }
+
+    private List<X509Certificate> findCertificateByIssuerSerial(String issuer, String serial) {
+        List<X509Certificate> result = new ArrayList<X509Certificate>();
+        File[] list = getX509Files();
+        for (File certFile : list) {
+            try {
+                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) {
+                throw new RuntimeException("Error reading certificate for issuer " + issuer + ": " + e.getMessage(), e);
+            }
+
+        }
+        return result;
+    }
+
+    private File[] getX509Files() {
+        File[] list = storageDir.listFiles();
+        if (list == null) {
+            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 list;
+    }
+
+    private X509Certificate readCertificate(File certFile) throws CertificateException, FileNotFoundException {
+        FileInputStream fis = new FileInputStream(certFile);
+        return (X509Certificate) certFactory.generateCertificate(fis);
+    }
+
+    public void saveCertificate(X509Certificate cert, UseKeyWithType id) {
+        String name = cert.getSubjectX500Principal().getName();
+        try {
+            File certFile = new File(storageDir, 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);
+        }
+    }
+
+    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) {
+        BigInteger serialNumber = cert.getSerialNumber();
+        String issuer = cert.getIssuerX500Principal().getName();
+        String path = convertDnForFileSystem(subjectDn) + "-" + serialNumber.toString() + "-"
+                + convertDnForFileSystem(issuer) + ".cer";
+        // TODO Filter for only valid and safe characters
+        return path;
+    }
+
+    private String getIdForApplication(Applications application, List<UseKeyWithType> ids) {
+        for (UseKeyWithType id : ids) {
+            if (application.getUri().equalsIgnoreCase(id.getApplication())) {
+                return id.getIdentifier();
+            }
+        }
+        return null;
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/LdapLocator.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/LdapLocator.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/LdapLocator.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/locator/LdapLocator.java Sat May 18 16:04:37 2013
@@ -0,0 +1,191 @@
+/**
+ * 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.locator;
+
+import java.io.ByteArrayInputStream;
+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.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Matcher;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+
+import org.apache.cxf.common.logging.LogUtils;
+import org.apache.cxf.xkms.exception.XKMSArgumentNotMatchException;
+import org.apache.cxf.xkms.exception.XKMSCertificateException;
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.handlers.Locator;
+import org.apache.cxf.xkms.model.xkms.LocateRequestType;
+import org.apache.cxf.xkms.model.xkms.UnverifiedKeyBindingType;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.handlers.LDAPSearch;
+import org.apache.cxf.xkms.x509.parser.LocateRequestParser;
+import org.apache.cxf.xkms.x509.utils.X509Utils;
+
+public class LdapLocator implements Locator {
+
+    private static final String OU_SERVICES = "ou=services";
+    private static final String CN_PREFIX = "cn=";
+    private static final String ATTR_UID_NAME = "uid";
+    private static final String ATTR_ISSUER_IDENTIFIER = "manager";
+    private static final String ATTR_SERIAL_NUMBER = "employeeNumber";
+    private static final String ATTR_USER_CERTIFICATE_BINARY = "userCertificate;binary";
+    private static final String FILTER_UID = "(" + ATTR_UID_NAME + "=%s)";
+    private static final String FILTER_ISSUER_SERIAL = "(&(" + ATTR_ISSUER_IDENTIFIER + "=%s)(" + ATTR_SERIAL_NUMBER
+            + "=%s))";
+    private static final Logger LOG = LogUtils.getL7dLogger(LdapLocator.class);
+    private final LDAPSearch ldapSearch;
+    private CertificateFactory certificateFactory;
+    private final String rootDN;
+
+    public LdapLocator(LDAPSearch ldapSearch, String rootDN) {
+        this.ldapSearch = ldapSearch;
+        this.rootDN = rootDN;
+        try {
+            this.certificateFactory = CertificateFactory.getInstance("X.509");
+        } catch (CertificateException e) {
+            LOG.log(Level.SEVERE, e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public UnverifiedKeyBindingType locate(LocateRequestType request) {
+
+        List<UseKeyWithType> keyIDs = LocateRequestParser.parse(request);
+
+        X509Certificate cert = findCertificate(keyIDs);
+
+        if (cert == null) {
+            return null;
+        }
+
+        try {
+            UnverifiedKeyBindingType result = new UnverifiedKeyBindingType();
+            result.setKeyInfo(X509Utils.getKeyInfo(cert));
+            return result;
+        } catch (CertificateEncodingException e) {
+            throw new XKMSCertificateException("Cannot encode certificate: " + e.getMessage(), e);
+        }
+    }
+
+    public X509Certificate findCertificate(List<UseKeyWithType> ids) {
+        try {
+            String issuer = null;
+            String serial = null;
+
+            for (UseKeyWithType key : ids) {
+                if (Applications.PKIX.getUri().equals(key.getApplication())) {
+                    return findByDn(key.getApplication(), key.getIdentifier());
+                } else if (Applications.SERVICE_SOAP.getUri().equals(key.getApplication())) {
+                    return findByDn(key.getApplication(), key.getIdentifier());
+                } else if (Applications.ISSUER.getUri().equals(key.getApplication())) {
+                    issuer = key.getIdentifier();
+                } else if (Applications.SERIAL.getUri().equals(key.getApplication())) {
+                    serial = key.getIdentifier();
+                }
+            }
+
+            if (issuer != null && serial != null) {
+                return findByIssuerSerial(issuer, serial);
+            }
+
+            throw new IllegalArgumentException("Application identifier not supported");
+
+        } catch (Exception e) {
+            throw new RuntimeException("Search certificates failure: " + e.getMessage(), e);
+        }
+    }
+
+    private X509Certificate findByDn(String application, String id) throws CertificateException {
+        byte[] content = null;
+        try {
+            String dn = getDN(application, id);
+            content = getCertificateForDn(dn);
+        } catch (NamingException e) {
+            // Not found
+        }
+        // Try to find certificate by search for distinguishedName attribute
+        try {
+            if (content == null) {
+                content = getCertificateForDnAttr(getSubjectDN(application, id));
+            }
+        } catch (NamingException e) {
+            // Not found
+        }
+        return (content != null)
+                ? (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream(content))
+                : null;
+    }
+
+    private byte[] getCertificateForDn(String dn) throws NamingException {
+        Attribute attr = ldapSearch.getAttribute(dn, ATTR_USER_CERTIFICATE_BINARY);
+        return (attr != null)
+                ? (byte[]) attr.get()
+                : null;
+    }
+
+    private X509Certificate findByIssuerSerial(String issuer, String serial) throws CertificateException,
+            NamingException {
+
+        if ((issuer == null) || (serial == null)) {
+            throw new IllegalArgumentException("Issuer and serial applications are expected in request");
+        }
+        String filter = String.format(FILTER_ISSUER_SERIAL, issuer, serial);
+        Attribute attr = ldapSearch.findAttribute(rootDN, filter, ATTR_USER_CERTIFICATE_BINARY);
+        if ((attr != null) && (attr.get() != null)) {
+            return (X509Certificate) certificateFactory.generateCertificate(new ByteArrayInputStream((byte[]) attr
+                    .get()));
+        } else {
+            return null;
+        }
+    }
+
+    private String getDN(String applicationUri, String identifier) {
+        if (Applications.PKIX.getUri().equals(applicationUri)) {
+            return identifier + "," + rootDN;
+        } else if (Applications.SERVICE_SOAP.getUri().equals(applicationUri)) {
+            String escapedIdentifier = identifier.replaceAll("\\/", Matcher.quoteReplacement("\\/"));
+            return CN_PREFIX + escapedIdentifier + "," + OU_SERVICES + "," + rootDN;
+        } else {
+            throw new XKMSArgumentNotMatchException("Unsupported application uri: " + applicationUri);
+        }
+    }
+
+    private String getSubjectDN(String application, String id) {
+        if (application.equalsIgnoreCase(Applications.SERVICE_SOAP.getUri())) {
+            return CN_PREFIX + id;
+        } else {
+            return id;
+        }
+    }
+
+    private byte[] getCertificateForDnAttr(String dn) throws NamingException {
+        String filter = String.format(FILTER_UID, dn);
+        Attribute attr = ldapSearch.findAttribute(rootDN, filter, ATTR_USER_CERTIFICATE_BINARY);
+        return (attr != null)
+                ? (byte[]) attr.get()
+                : null;
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/LocateRequestParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/LocateRequestParser.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/LocateRequestParser.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/LocateRequestParser.java Sat May 18 16:04:37 2013
@@ -0,0 +1,119 @@
+/**
+ * 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.parser;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.cxf.xkms.exception.XKMSException;
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.LocateRequestType;
+import org.apache.cxf.xkms.model.xkms.QueryKeyBindingType;
+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.model.xmldsig.KeyInfoType;
+import org.apache.cxf.xkms.model.xmldsig.X509DataType;
+import org.apache.cxf.xkms.model.xmldsig.X509IssuerSerialType;
+import org.apache.cxf.xkms.x509.utils.X509Utils;
+
+public final class LocateRequestParser {
+
+    private LocateRequestParser() {
+    }
+
+    public static List<UseKeyWithType> parse(LocateRequestType request) {
+        List<UseKeyWithType> keyIDs = new ArrayList<UseKeyWithType>();
+        if (request == null) {
+            return keyIDs;
+        }
+
+        QueryKeyBindingType query = request.getQueryKeyBinding();
+        if (query == null) {
+            return keyIDs;
+        }
+
+        // http://www.w3.org/TR/xkms2/ [213]
+        if (query.getTimeInstant() != null) {
+            throw new XKMSException(ResultMajorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_RECEIVER,
+                    ResultMinorEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_TIME_INSTANT_NOT_SUPPORTED);
+        }
+
+        keyIDs.addAll(parse(query.getKeyInfo()));
+
+        List<UseKeyWithType> useKeyList = query.getUseKeyWith();
+        keyIDs.addAll(useKeyList);
+
+        return keyIDs;
+    }
+
+    protected static List<UseKeyWithType> parse(KeyInfoType keyInfo) {
+        List<UseKeyWithType> keyIDs = new ArrayList<UseKeyWithType>();
+
+        if (keyInfo == null) {
+            return keyIDs;
+        }
+
+        List<Object> content = keyInfo.getContent();
+        for (Object obj1 : content) {
+            if (obj1 instanceof JAXBElement) {
+                JAXBElement<?> keyInfoChild = (JAXBElement<?>) obj1;
+                if (X509Utils.X509_KEY_NAME.equals(keyInfoChild.getName())) {
+                    UseKeyWithType keyDN = new UseKeyWithType();
+                    keyDN.setApplication(Applications.PKIX.getUri());
+                    keyDN.setIdentifier((String) keyInfoChild.getValue());
+                    keyIDs.add(keyDN);
+
+                } else if (X509Utils.X509_DATA.equals(keyInfoChild.getName())) {
+                    X509DataType x509Data = (X509DataType) keyInfoChild.getValue();
+                    List<Object> x509DataContent = x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName();
+
+                    for (Object obj2 : x509DataContent) {
+                        if (obj2 instanceof JAXBElement) {
+                            JAXBElement<?> x509DataChild = (JAXBElement<?>) obj2;
+
+                            if (X509Utils.X509_ISSUER_SERIAL.equals(x509DataChild.getName())) {
+                                X509IssuerSerialType x509IssuerSerial = (X509IssuerSerialType) x509DataChild.getValue();
+
+                                UseKeyWithType issuer = new UseKeyWithType();
+                                issuer.setApplication(Applications.ISSUER.getUri());
+                                issuer.setIdentifier(x509IssuerSerial.getX509IssuerName());
+                                keyIDs.add(issuer);
+
+                                UseKeyWithType serial = new UseKeyWithType();
+                                serial.setApplication(Applications.SERIAL.getUri());
+                                serial.setIdentifier(x509IssuerSerial.getX509SerialNumber().toString());
+                                keyIDs.add(serial);
+
+                            } else if (X509Utils.X509_SUBJECT_NAME.equals(x509DataChild.getName())) {
+                                UseKeyWithType keyDN = new UseKeyWithType();
+                                keyDN.setApplication(Applications.PKIX.getUri());
+                                keyDN.setIdentifier((String) x509DataChild.getValue());
+                                keyIDs.add(keyDN);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return keyIDs;
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/ValidateRequestParser.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/ValidateRequestParser.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/ValidateRequestParser.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/parser/ValidateRequestParser.java Sat May 18 16:04:37 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.parser;
+
+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/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=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/utils/X509Utils.java Sat May 18 16:04:37 2013
@@ -0,0 +1,171 @@
+/**
+ * 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.Collection;
+import java.util.Iterator;
+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.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;
+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());
+        }
+    }
+
+    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();
+        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/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=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/main/java/org/apache/cxf/xkms/x509/validator/DateValidator.java Sat May 18 16:04:37 2013
@@ -0,0 +1,99 @@
+/**
+ * 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;
+import org.apache.cxf.xkms.x509.parser.ValidateRequestParser;
+
+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/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/file/persistence/FilePersistenceManagerTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/file/persistence/FilePersistenceManagerTest.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/file/persistence/FilePersistenceManagerTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/file/persistence/FilePersistenceManagerTest.java Sat May 18 16:04:37 2013
@@ -0,0 +1,135 @@
+/**
+ * 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.file.persistence;
+
+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 java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.handlers.FileRegisterHandler;
+import org.apache.cxf.xkms.x509.locator.FileLocator;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class FilePersistenceManagerTest {
+    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();
+        FileRegisterHandler fileRegisterHandler = new FileRegisterHandler(storageDir);
+        FileLocator fileLocator = new FileLocator(storageDir);
+        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);
+
+        List<UseKeyWithType> ids = new ArrayList<UseKeyWithType>();
+        key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXAMPLE_SUBJECT_DN);
+        ids.add(key);
+        X509Certificate resultCert = fileLocator.findCertificate(ids);
+        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());
+        FileLocator persistenceManager = new FileLocator(storageDir);
+        List<UseKeyWithType> ids = new ArrayList<UseKeyWithType>();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXAMPLE_SUBJECT_DN);
+        ids.add(key);
+        X509Certificate resCert = persistenceManager.findCertificate(ids);
+        Assert.assertNotNull(resCert);
+    }
+
+    @Test
+    public void testConvertDnForFileSystem() throws CertificateException {
+        File storageDir = new File("src/test/resources/store1");
+        String convertedName = new FileRegisterHandler(storageDir).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/ldap/persistence/LDAPPersistenceManagerITest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerITest.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerITest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerITest.java Sat May 18 16:04:37 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.ldap.persistence;
+
+import java.io.File;
+import java.io.FileInputStream;
+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.List;
+
+import javax.naming.NamingException;
+
+import org.apache.cxf.xkms.handlers.Applications;
+import org.apache.cxf.xkms.model.xkms.UseKeyWithType;
+import org.apache.cxf.xkms.x509.handlers.LDAPSearch;
+import org.apache.cxf.xkms.x509.handlers.LdapRegisterHandler;
+import org.apache.cxf.xkms.x509.locator.LdapLocator;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Tests need a real ldap server
+ */
+public class LDAPPersistenceManagerITest {
+    private static final String EXPECTED_SUBJECT_DN = "CN=www.issuer.com, L=CGN, ST=NRW, C=DE, O=Issuer";
+
+    @Test
+    @Ignore
+    public void testFindUserCert() throws URISyntaxException, NamingException, CertificateException {
+        LdapLocator persistenceManager = createLdapLocator();
+        testFindBySubjectDnInternal(persistenceManager);
+    }
+
+    @Test
+    @Ignore
+    public void testFindUserCertForNonExistantDn() throws URISyntaxException, NamingException, CertificateException {
+        LdapLocator persistenceManager = createLdapLocator();
+        List<UseKeyWithType> ids = new ArrayList<UseKeyWithType>();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier("CN=wrong");
+        ids.add(key);
+        X509Certificate cert = persistenceManager.findCertificate(ids);
+        Assert.assertNull("Certifiacte should be null", cert);
+    }
+
+    @Test
+    @Ignore
+    public void testFindServiceCert() throws URISyntaxException, NamingException, CertificateException {
+        LdapLocator persistenceManager = createLdapLocator();
+        String serviceUri = "cn=http:\\/\\/myservice.apache.org\\/MyServiceName,ou=services";
+        List<UseKeyWithType> ids = new ArrayList<UseKeyWithType>();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.SERVICE_SOAP.getUri());
+        key.setIdentifier(serviceUri);
+        ids.add(key);
+        X509Certificate cert = persistenceManager.findCertificate(ids);
+        Assert.assertEquals(EXPECTED_SUBJECT_DN, cert.getSubjectDN().toString());
+    }
+
+    @Test
+    @Ignore
+    public void testSave() throws Exception {
+        LDAPSearch ldapSearch = new LDAPSearch("ldap://localhost:2389", "cn=Directory Manager", "test", 2);
+        LdapLocator locator = createLdapLocator();
+        LdapRegisterHandler persistenceManager = new LdapRegisterHandler(ldapSearch, "dc=example,dc=com");
+        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(locator);
+    }
+
+    private LdapLocator createLdapLocator() throws CertificateException {
+        LDAPSearch ldapSearch = new LDAPSearch("ldap://localhost:2389", "cn=Directory Manager", "test", 2);
+        return new LdapLocator(ldapSearch, "dc=example,dc=com");
+    }
+
+    private void testFindBySubjectDnInternal(LdapLocator persistenceManager) {
+        List<UseKeyWithType> ids = new ArrayList<UseKeyWithType>();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXPECTED_SUBJECT_DN);
+        ids.add(key);
+        X509Certificate cert2 = persistenceManager.findCertificate(ids);
+        Assert.assertEquals(EXPECTED_SUBJECT_DN, cert2.getSubjectDN().toString());
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerTest.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPPersistenceManagerTest.java Sat May 18 16:04:37 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.ldap.persistence;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+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.handlers.LDAPSearch;
+import org.apache.cxf.xkms.x509.handlers.LdapRegisterHandler;
+import org.easymock.EasyMock;
+import org.easymock.IMocksControl;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LDAPPersistenceManagerTest {
+    private static final String ROOT_DN = "dc=example,dc=com";
+    private static final String EXPECTED_SUBJECT_DN = "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";
+
+    @Test
+    public void testSaveUserCert() throws Exception {
+        IMocksControl c = EasyMock.createControl();
+        LDAPSearch ldapSearch = c.createMock(LDAPSearch.class);
+        ldapSearch.bind(EasyMock.eq(EXPECTED_SUBJECT_DN + "," + ROOT_DN), EasyMock.anyObject(Attributes.class));
+        EasyMock.expectLastCall().once();
+        LdapRegisterHandler persistenceManager = new LdapRegisterHandler(ldapSearch, ROOT_DN);
+        X509Certificate cert = getTestCert();
+
+        c.replay();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.PKIX.getUri());
+        key.setIdentifier(EXPECTED_SUBJECT_DN);
+        persistenceManager.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();
+        LdapRegisterHandler persistenceManager = new LdapRegisterHandler(ldapSearch, ROOT_DN);
+        X509Certificate cert = getTestCert();
+
+        c.replay();
+        UseKeyWithType key = new UseKeyWithType();
+        key.setApplication(Applications.SERVICE_SOAP.getUri());
+        key.setIdentifier(EXPECTED_SERVICE_URI);
+        persistenceManager.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/ldap/persistence/LDAPSearchTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPSearchTest.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPSearchTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/ldap/persistence/LDAPSearchTest.java Sat May 18 16:04:37 2013
@@ -0,0 +1,50 @@
+/**
+ * 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.ldap.persistence;
+
+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.apache.cxf.xkms.x509.handlers.LDAPSearch;
+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", "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());
+        }
+    }
+
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/BasicValidationTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/BasicValidationTest.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/BasicValidationTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/BasicValidationTest.java Sat May 18 16:04:37 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.handlers;
+
+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/handlers/ValidateDateHandlerTest.java
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/ValidateDateHandlerTest.java?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/ValidateDateHandlerTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/handlers/ValidateDateHandlerTest.java Sat May 18 16:04:37 2013
@@ -0,0 +1,62 @@
+/**
+ * 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 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.apache.cxf.xkms.x509.validator.DateValidator;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ValidateDateHandlerTest 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());
+
+    }
+
+}

Added: 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=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/utils/X509UtilsTest.java (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/java/org/apache/cxf/xkms/x509/utils/X509UtilsTest.java Sat May 18 16:04:37 2013
@@ -0,0 +1,55 @@
+/**
+ * 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.security.cert.X509Certificate;
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+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.junit.Assert;
+import org.junit.Test;
+
+public class X509UtilsTest extends BasicValidationTest {
+    private static final String CERT_DN = "CN=www.anothersts.com, L=CGN, ST=NRW, C=DE, O=AnotherSTS";
+
+    public void extractValidatingCertsOK() throws JAXBException {
+        @SuppressWarnings("unchecked")
+        JAXBElement<ValidateRequestType> request = (JAXBElement<ValidateRequestType>)u.unmarshal(this.getClass()
+            .getResourceAsStream("/validateRequestOK.xml"));
+        List<X509Certificate> certs = ValidateRequestParser.parse(request.getValue());
+        Assert.assertEquals("Exactly one certificate should be found", 1, certs.size());
+        Assert.assertEquals("Unexcpected certificate DN", CERT_DN, certs.get(0).getSubjectDN().getName());
+    }
+
+    @Test(expected = XKMSRequestException.class)
+    public void extractValidatingCertsCorrupted() throws JAXBException {
+        @SuppressWarnings("unchecked")
+        JAXBElement<ValidateRequestType> request = (JAXBElement<ValidateRequestType>)u.unmarshal(this.getClass()
+            .getResourceAsStream("/validateRequestCorrupted.xml"));
+        ValidateRequestParser.parse(request.getValue());
+    }
+}

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.bas64
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.bas64?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.bas64 (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.bas64 Sat May 18 16:04:37 2013
@@ -0,0 +1,2 @@
+MIIF4DCCA8igAwIBAgIJAKI2DZw3MLqRMA0GCSqGSIb3DQEBBQUAMFMxDzANBgNVBAoTBklzc3VlcjELMAkGA1UEBhMCREUxDDAKBgNVBAgTA05SVzEMMAoGA1UEBxMDQ0dOMRcwFQYDVQQDEw53d3cuaXNzdWVyLmNvbTAeFw0xMjAyMjkxMDIzMDFaFw0xMzAyMjgxMDIzMDFaMFMxDzANBgNVBAoTBklzc3VlcjELMAkGA1UEBhMCREUxDDAKBgNVBAgTA05SVzEMMAoGA1UEBxMDQ0dOMRcwFQYDVQQDEw53d3cuaXNzdWVyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMSCbQd/92wAJnfaFZTRmEP0afGGS0lGJghLg3uoMpewcQj4A2RZVJl2sfFbk/OppUqtJYxLKv0LRkx9MsZ2rQOq1YfmHShxpb6PeyRx8dEgSCtgWivVzKk/w+UudilQVC3cTNWtCayjajHcc0UAG4Kaaypl5CNEWH0M4JapcjFCwU3t7INI/DcAZK2J0aZI0pevw977nEzHyHOeea3O0RFrTTQomt/fv4gtP08F4x13cK0ssD93YZwhzFQ/63E/P0UM6daKJG8Ysg9owjwuSGR6bDR/FNuDeH4hqq0QGuvFHANpVTakvE5d+WWw1BDIZ8RK2vf3yFs+/jazTUhUJvoiniqtTf6VnMUmI7n5mDFQbutiIOeFzK4bQ+KKYch/aO2Pc6dXoEYmCfgA/SdcoOhEfGJKqU8mvPU/bXJEDVj1VgFzRssnaZcmReXfrcFuxW9fkVMEQ4jXlUF6v63uwqpdMWqgBGlti5hHjOuE/MOYpmBv6mUNX0MxqtgRU7/8fUoR6HwgAlRBOoWGCHIzv/0V6fSm804OiUf+DY65dbpZRhZmd7yANYYoewSwrNokDXGlz6e5cPaXMUnakIgcj2crr+dqQpxkrpTgP5ihq8Jrw8GHY
 Zwm0SE4dqhA/DcyL6UlJarZSk7U3XEGvs60p0YThEgbpHCkgyruxocyQ4z3AgMBAAGjgbYwgbMwHQYDVR0OBBYEFCN8oLmMeAxU7v5mcE6U2bDmP63cMIGDBgNVHSMEfDB6gBQjfKC5jHgMVO7+ZnBOlNmw5j+t3KFXpFUwUzEPMA0GA1UEChMGSXNzdWVyMQswCQYDVQQGEwJERTEMMAoGA1UECBMDTlJXMQwwCgYDVQQHEwNDR04xFzAVBgNVBAMTDnd3dy5pc3N1ZXIuY29tggkAojYNnDcwupEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEAPDAcr3TdfLlczzkBR6iiN63ERK/FnIcB8vIJdxJeYsq/w49CgxMjOugGsZ7rKTmT89zPQzVe/GJITRHNS1q81cf8hd4SWZ/i3z7k8tqhMRq0b31aQqkLzjPWD6PAwzDWUAY8HMMq9Gbxx52u4yXxx1PabTxq/0EDtX7+JfZ462BGtWCcUrrXq6Wck4acvAw2NmMfUR+RYLVKLINen82KD1YAl+mOKFfc3r9i1mLi/ylE2LuKN6Z3LnYAcaUgq22mRKR6hGXyw4zU2HzFNlgBnoJottYdZWxa5Chcr6wMgZS/rg3gQ8z6ALOFG/UTBxcXRmI0CCBhTPjn4Dq8gd+BWixBzFVF8DoYEyVEX7fGNOAwb3OZCQMVsaM6PuqIfiz0s5oiqdohYSzwXc6ajmQB7JJkfHE8B43dnL+G1+d2mqvhXhTeJNlwC0Hcqtc7MY2rRDY0Kj0LrGqjhN6kKiXHXA0YqVpn1W7qsu+GS51jxpxZ2DUELNuIhXU/xbP3IS/BKMgiwNM2kZBtP0qkfKlsO9IemiQTNGZzxm+DJvE5U4wC0cVxsvqRTqdfKumaIMoUHsIrC5OWibTZ658KFuZZGHtxolH1sZnSPjs9D9RC9xDv5OyIHcHcMhN6c7wk2Tf3GpY91r6Sp6
 TxIkB2cZQDT8eTSS/PTHC+muh5/365lRE=
+						

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.cer
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.cer?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.cer (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/cert1.cer Sat May 18 16:04:37 2013
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIIF4DCCA8igAwIBAgIJAKI2DZw3MLqRMA0GCSqGSIb3DQEBBQUAMFMxDzANBgNVBAoTBklzc3Vl
+cjELMAkGA1UEBhMCREUxDDAKBgNVBAgTA05SVzEMMAoGA1UEBxMDQ0dOMRcwFQYDVQQDEw53d3cu
+aXNzdWVyLmNvbTAeFw0xMjAyMjkxMDIzMDFaFw0xMzAyMjgxMDIzMDFaMFMxDzANBgNVBAoTBklz
+c3VlcjELMAkGA1UEBhMCREUxDDAKBgNVBAgTA05SVzEMMAoGA1UEBxMDQ0dOMRcwFQYDVQQDEw53
+d3cuaXNzdWVyLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMSCbQd/92wAJnfa
+FZTRmEP0afGGS0lGJghLg3uoMpewcQj4A2RZVJl2sfFbk/OppUqtJYxLKv0LRkx9MsZ2rQOq1Yfm
+HShxpb6PeyRx8dEgSCtgWivVzKk/w+UudilQVC3cTNWtCayjajHcc0UAG4Kaaypl5CNEWH0M4Jap
+cjFCwU3t7INI/DcAZK2J0aZI0pevw977nEzHyHOeea3O0RFrTTQomt/fv4gtP08F4x13cK0ssD93
+YZwhzFQ/63E/P0UM6daKJG8Ysg9owjwuSGR6bDR/FNuDeH4hqq0QGuvFHANpVTakvE5d+WWw1BDI
+Z8RK2vf3yFs+/jazTUhUJvoiniqtTf6VnMUmI7n5mDFQbutiIOeFzK4bQ+KKYch/aO2Pc6dXoEYm
+CfgA/SdcoOhEfGJKqU8mvPU/bXJEDVj1VgFzRssnaZcmReXfrcFuxW9fkVMEQ4jXlUF6v63uwqpd
+MWqgBGlti5hHjOuE/MOYpmBv6mUNX0MxqtgRU7/8fUoR6HwgAlRBOoWGCHIzv/0V6fSm804OiUf+
+DY65dbpZRhZmd7yANYYoewSwrNokDXGlz6e5cPaXMUnakIgcj2crr+dqQpxkrpTgP5ihq8Jrw8GH
+YZwm0SE4dqhA/DcyL6UlJarZSk7U3XEGvs60p0YThEgbpHCkgyruxocyQ4z3AgMBAAGjgbYwgbMw
+HQYDVR0OBBYEFCN8oLmMeAxU7v5mcE6U2bDmP63cMIGDBgNVHSMEfDB6gBQjfKC5jHgMVO7+ZnBO
+lNmw5j+t3KFXpFUwUzEPMA0GA1UEChMGSXNzdWVyMQswCQYDVQQGEwJERTEMMAoGA1UECBMDTlJX
+MQwwCgYDVQQHEwNDR04xFzAVBgNVBAMTDnd3dy5pc3N1ZXIuY29tggkAojYNnDcwupEwDAYDVR0T
+BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAgEAPDAcr3TdfLlczzkBR6iiN63ERK/FnIcB8vIJdxJe
+Ysq/w49CgxMjOugGsZ7rKTmT89zPQzVe/GJITRHNS1q81cf8hd4SWZ/i3z7k8tqhMRq0b31aQqkL
+zjPWD6PAwzDWUAY8HMMq9Gbxx52u4yXxx1PabTxq/0EDtX7+JfZ462BGtWCcUrrXq6Wck4acvAw2
+NmMfUR+RYLVKLINen82KD1YAl+mOKFfc3r9i1mLi/ylE2LuKN6Z3LnYAcaUgq22mRKR6hGXyw4zU
+2HzFNlgBnoJottYdZWxa5Chcr6wMgZS/rg3gQ8z6ALOFG/UTBxcXRmI0CCBhTPjn4Dq8gd+BWixB
+zFVF8DoYEyVEX7fGNOAwb3OZCQMVsaM6PuqIfiz0s5oiqdohYSzwXc6ajmQB7JJkfHE8B43dnL+G
+1+d2mqvhXhTeJNlwC0Hcqtc7MY2rRDY0Kj0LrGqjhN6kKiXHXA0YqVpn1W7qsu+GS51jxpxZ2DUE
+LNuIhXU/xbP3IS/BKMgiwNM2kZBtP0qkfKlsO9IemiQTNGZzxm+DJvE5U4wC0cVxsvqRTqdfKuma
+IMoUHsIrC5OWibTZ658KFuZZGHtxolH1sZnSPjs9D9RC9xDv5OyIHcHcMhN6c7wk2Tf3GpY91r6S
+p6TxIkB2cZQDT8eTSS/PTHC+muh5/365lRE=
+-----END CERTIFICATE-----

Added: cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/registerRequest.xml
URL: http://svn.apache.org/viewvc/cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/registerRequest.xml?rev=1484133&view=auto
==============================================================================
--- cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/registerRequest.xml (added)
+++ cxf/trunk/services/xkms/xkms-x509-handlers/src/test/resources/registerRequest.xml Sat May 18 16:04:37 2013
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RegisterRequest xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+   xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
+   Id="I1494ac4351b7de5c174d455b7000e18f"
+   Service="http://www.example.org/XKMS"
+   xmlns="http://www.w3.org/2002/03/xkms#">
+  <RespondWith>http://www.w3.org/2002/03/xkms#X509Cert</RespondWith>
+  <RespondWith>http://www.w3.org/2002/03/xkms#X509Chain</RespondWith>
+  <PrototypeKeyBinding Id="I269e655567dbae568591c0a06957529e">
+    <ds:KeyInfo>
+      <ds:KeyValue>
+        <ds:RSAKeyValue>
+          <ds:Modulus>
+            0nIsmR+aVW2egl5MIfOKy4HuMKkk9AZ/IQuDLVPlhzOfgngjVQCjr8uvmnqtNu8
+            HBupui8LgGthO6U9D0CNT5mbmhIAErRADUMIAFsi7LzBarUvNWTqYNEJmcHsAUZ
+            drdcDrkNnG7SzbuJx+GDNiHKVDQggPBLc1XagW20RMvok=
+          </ds:Modulus>
+          <ds:Exponent>AQAB</ds:Exponent>
+        </ds:RSAKeyValue>
+      </ds:KeyValue>
+    </ds:KeyInfo>
+    <KeyUsage>http://www.w3.org/2002/03/xkms#Signature</KeyUsage>
+    <KeyUsage>http://www.w3.org/2002/03/xkms#Encryption</KeyUsage>
+    <KeyUsage>http://www.w3.org/2002/03/xkms#Exchange</KeyUsage>
+    <UseKeyWith Application="urn:ietf:rfc:2459"
+         Identifier='C="US" O="Alice Corp" CN="Alice Aardvark"' />
+    <UseKeyWith Application="urn:ietf:rfc:2633"
+         Identifier="alice@example.com" />
+    <UseKeyWith Application="http://ca.example.com/cps/20030401/class3"
+         Identifier="alice@example.com" />
+    <RevocationCodeIdentifier>
+      5AEAai06hFJEkuqyDyqNh8k/u3M=
+    </RevocationCodeIdentifier>
+  </PrototypeKeyBinding>
+  <Authentication>
+    <KeyBindingAuthentication>
+      <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+        <SignedInfo>
+          <CanonicalizationMethod 
+                  Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+          <SignatureMethod 
+                  Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1" />
+          <Reference URI="#I269e655567dbae568591c0a06957529e">
+            <Transforms>
+              <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+            </Transforms>
+            <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+            <DigestValue>WCbpkifxJ1zIJ+V6/knZgxRhR34=</DigestValue>
+          </Reference>
+        </SignedInfo>
+        <SignatureValue>iJSKM+98hj5ae+btC2WjwBYP+/k=</SignatureValue>
+      </Signature>
+    </KeyBindingAuthentication>
+  </Authentication>
+  <ProofOfPossession>
+    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
+      <SignedInfo>
+        <CanonicalizationMethod 
+                Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+        <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
+        <Reference URI="#I269e655567dbae568591c0a06957529e">
+          <Transforms>
+            <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
+          </Transforms>
+          <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
+          <DigestValue>WCbpkifxJ1zIJ+V6/knZgxRhR34=</DigestValue>
+        </Reference>
+      </SignedInfo>
+      <SignatureValue>
+        DcPw742vN120QNrCjCKw0jiCX3pUvbMeRkYjktZkn4nbgo1b7leXU0sJgXM2CY/
+        oQugaRsgz18+qUzM0UX+jr1t1wtCMci5fjzVKZB63oZyKZ9+CJLcBCbirsgJAId
+        +Pq9w4WiwKDf2AytsdXHlN5V1byQIkpfR1CypvBzQa1b4=
+      </SignatureValue>
+    </Signature>
+  </ProofOfPossession>
+</RegisterRequest> 



Mime
View raw message