/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.cxf.xkms.x509.handlers; import java.io.ByteArrayInputStream; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBElement; import org.apache.cxf.xkms.handlers.Register; import org.apache.cxf.xkms.model.xkms.KeyBindingEnum; import org.apache.cxf.xkms.model.xkms.KeyBindingType; import org.apache.cxf.xkms.model.xkms.PrototypeKeyBindingType; import org.apache.cxf.xkms.model.xkms.RecoverRequestType; import org.apache.cxf.xkms.model.xkms.RecoverResultType; import org.apache.cxf.xkms.model.xkms.RegisterRequestType; import org.apache.cxf.xkms.model.xkms.RegisterResultType; import org.apache.cxf.xkms.model.xkms.ReissueRequestType; import org.apache.cxf.xkms.model.xkms.ReissueResultType; import org.apache.cxf.xkms.model.xkms.RequestAbstractType; import org.apache.cxf.xkms.model.xkms.RespondWithEnum; import org.apache.cxf.xkms.model.xkms.RevokeRequestType; import org.apache.cxf.xkms.model.xkms.RevokeResultType; import org.apache.cxf.xkms.model.xkms.StatusType; import org.apache.cxf.xkms.model.xkms.UseKeyWithType; import org.apache.cxf.xkms.model.xmldsig.KeyInfoType; import org.apache.cxf.xkms.model.xmldsig.X509DataType; import org.apache.cxf.xkms.x509.repo.CertificateRepo; import org.apache.cxf.xkms.x509.utils.X509Utils; public class X509Register implements Register { protected final CertificateFactory certFactory; private CertificateRepo certRepo; public X509Register(CertificateRepo certRepo) throws CertificateException { this.certRepo = certRepo; certFactory = CertificateFactory.getInstance("X.509"); } @Override public boolean canProcess(RequestAbstractType request) { if (request instanceof RecoverRequestType) { return false; } List<String> respondWithList = request.getRespondWith(); if ((respondWithList != null) && !(respondWithList.isEmpty())) { return respondWithList.contains(RespondWithEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_X_509_CERT); } else { // Default handler return true; } } @Override public RegisterResultType register(RegisterRequestType request, RegisterResultType response) { try { PrototypeKeyBindingType binding = request.getPrototypeKeyBinding(); X509Utils.assertElementNotNull(binding, PrototypeKeyBindingType.class); KeyInfoType keyInfo = binding.getKeyInfo(); X509Utils.assertElementNotNull(binding, KeyInfoType.class); List<UseKeyWithType> useKeyWithList = binding.getUseKeyWith(); if (useKeyWithList == null || useKeyWithList.size() != 1) { throw new IllegalArgumentException("Exactly one useKeyWith element is supported"); //TODO standard requires support for multiple useKeyWith attributes } UseKeyWithType useKeyWith = useKeyWithList.get(0); List<X509Certificate> certList = getCertsFromKeyInfo(keyInfo); if (certList.size() != 1) { throw new IllegalArgumentException("Must provide one X509Certificate"); } X509Certificate cert = certList.get(0); certRepo.saveCertificate(cert, useKeyWith); KeyBindingType responseBinding = prepareResponseBinding(binding); response.getKeyBinding().add(responseBinding); return response; } catch (CertificateException e) { throw new RuntimeException(e.getMessage(), e); } } private KeyBindingType prepareResponseBinding(PrototypeKeyBindingType binding) { KeyBindingType responseBinding = new KeyBindingType(); responseBinding.setKeyInfo(binding.getKeyInfo()); StatusType status = new StatusType(); status.setStatusValue(KeyBindingEnum.HTTP_WWW_W_3_ORG_2002_03_XKMS_VALID); responseBinding.setStatus(status); return responseBinding; } @Override public ReissueResultType reissue(ReissueRequestType request, ReissueResultType response) { throw new UnsupportedOperationException("This service does not support reissue"); } @Override public RevokeResultType revoke(RevokeRequestType request, RevokeResultType response) { throw new UnsupportedOperationException("This service does not support revoke"); } private List<X509Certificate> getCertsFromKeyInfo(KeyInfoType keyInfo) throws CertificateException { List<X509Certificate> certList = new ArrayList<>(); for (Object key : keyInfo.getContent()) { if (key instanceof JAXBElement) { Object value = ((JAXBElement<?>) key).getValue(); if (value instanceof X509DataType) { X509DataType x509Data = (X509DataType) value; List<Object> data = x509Data.getX509IssuerSerialOrX509SKIOrX509SubjectName(); for (Object certO : data) { JAXBElement<?> certO2 = (JAXBElement<?>) certO; if (certO2.getDeclaredType() == byte[].class) { byte[] certContent = (byte[]) certO2.getValue(); X509Certificate cert = (X509Certificate) certFactory .generateCertificate(new ByteArrayInputStream(certContent)); certList.add(cert); } } } } } return certList; } @Override public RecoverResultType recover(RecoverRequestType request, RecoverResultType response) { throw new UnsupportedOperationException("Recover is currently not supported"); } }