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