/** * 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.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBElement; import org.apache.cxf.xkms.exception.XKMSCertificateException; import org.apache.cxf.xkms.exception.XKMSException; 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.QueryKeyBindingType; 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.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.repo.CertificateRepo; import org.apache.cxf.xkms.x509.utils.X509Utils; public class X509Locator implements Locator { private CertificateRepo certRepo; public X509Locator(CertificateRepo certRepo) throws CertificateException { this.certRepo = certRepo; } @Override public UnverifiedKeyBindingType locate(LocateRequestType request) { List<UseKeyWithType> keyIDs = parse(request); X509Certificate cert; try { cert = findCertificate(keyIDs); if (cert == null) { return null; } UnverifiedKeyBindingType result = new UnverifiedKeyBindingType(); result.setKeyInfo(X509Utils.getKeyInfo(cert)); return result; } catch (CertificateEncodingException e) { throw new XKMSCertificateException("Cannot encode certificate: " + e.getMessage(), e); } catch (CertificateException e1) { throw new XKMSCertificateException(e1.getMessage(), e1); } } public X509Certificate findCertificate(List<UseKeyWithType> ids) throws CertificateException { X509Certificate cert = null; if (ids.size() == 0) { throw new IllegalArgumentException("No UseKeyWithType elements found"); } if (ids.size() == 1) { Applications application = Applications.fromUri(ids.get(0).getApplication()); String id = ids.get(0).getIdentifier(); if (application == Applications.PKIX) { cert = certRepo.findBySubjectDn(id); } else if (application == Applications.SERVICE_NAME) { cert = certRepo.findByServiceName(id); } else if (application == Applications.SERVICE_ENDPOINT) { cert = certRepo.findByEndpoint(id); } } String issuer = getIdForApplication(Applications.ISSUER, ids); String serial = getIdForApplication(Applications.SERIAL, ids); if ((issuer != null) && (serial != null)) { cert = certRepo.findByIssuerSerial(issuer, serial); } return cert; } private String getIdForApplication(Applications application, List<UseKeyWithType> ids) { for (UseKeyWithType id : ids) { if (application.getUri().equalsIgnoreCase(id.getApplication())) { return id.getIdentifier(); } } return null; } private List<UseKeyWithType> parse(LocateRequestType request) { List<UseKeyWithType> keyIDs = new ArrayList<>(); 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; } private List<UseKeyWithType> parse(KeyInfoType keyInfo) { List<UseKeyWithType> keyIDs = new ArrayList<>(); 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; } }