From b1c8641a63a67e3c64d948f9e8dce5c01e11e2dd Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 5 May 2010 15:29:01 +0000 Subject: Merged feature branch mocca-1.2.13-id@r724 back to trunk. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@725 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/mocca/id/SAMLBindingProcessorImpl.java | 357 +++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java (limited to 'BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java') diff --git a/BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java b/BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java new file mode 100644 index 00000000..ce4ac425 --- /dev/null +++ b/BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java @@ -0,0 +1,357 @@ +/* + * Copyright 2009 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed 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 at.gv.egiz.mocca.id; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.Date; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMValidateContext; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import at.buergerkarte.namespaces.securitylayer._1.AnyChildrenType; +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefOptRefContentType; +import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureRequestType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsBinaryFileType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.buergerkarte.namespaces.securitylayer._1.MetaInfoType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.buergerkarte.namespaces.securitylayer._1.TransformsInfoType; +import at.gv.egiz.bku.binding.FormParameter; +import at.gv.egiz.bku.binding.HTTPBindingProcessor; +import at.gv.egiz.bku.binding.HttpUtil; +import at.gv.egiz.bku.binding.InputDecoder; +import at.gv.egiz.bku.binding.InputDecoderFactory; +import at.gv.egiz.bku.slcommands.CreateXMLSignatureResult; +import at.gv.egiz.bku.slcommands.ErrorResult; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLVersionException; + +public class SAMLBindingProcessorImpl extends + AbstractCommandSequenceBindingProcessor implements HTTPBindingProcessor { + + private static final Logger log = LoggerFactory + .getLogger(SAMLBindingProcessorImpl.class); + + private String requestContentType; + + private String domainIdentifier = "urn:publicid:gv.at:wbpk+FN+468924i"; + + private String keyBoxIdentifier = "SecureSignatureKeypair"; + + private String url = "www.egiz.gv.at"; + + private QESTemplates templates = new QESTemplates(); + + private IdLink idLink; + + private Element signature; + + private SLResult errorResponse; + + @Override + protected void processResult(SLResult result) { + if (result instanceof ErrorResult) { + ErrorResult errorResult = (ErrorResult) result; + log.info("Got ErrorResponse {}: {}", errorResult.getErrorCode(), + errorResult.getInfo()); + errorResponse = result; + return; + } else if (result instanceof InfoboxReadResult) { + try { + processInfoboxReadResult((InfoboxReadResult) result); + if (idLink != null) { + try { + IdLinkPersonData personData = idLink.getPersonData(); + log.info("Got idLink for {}.", personData); + } catch (MarshalException e) { + log.info("Failed to unmarshal idLink."); + } + } + } catch (JAXBException e) { + log.info("InfoboxReadResult contains unexpected data.", e); + errorResponse = result; + } catch (IdLinkException e) { + log.info("InfoboxReadResult contains invalid identity link.", e); + errorResponse = result; + } + } else if (result instanceof CreateXMLSignatureResult) { + signature = ((CreateXMLSignatureResult) result).getContent(); + log.info("Got signature."); + boolean valid = validate(signature) && validate(idLink); + log.info("Signature is valid: " + valid); + } + } + + @Override + protected SLCommand getNextCommand() { + + JAXBElement request = null; + if (errorResponse == null) { + if (idLink == null) { + request = createReadInfoboxRequest(domainIdentifier); + } else if (signature == null) { + request = createXMLSignatureRequest(); + } + } + + if (request != null) { + SLCommandFactory commandFactory = SLCommandFactory.getInstance(); + try { + return commandFactory.createSLCommand(request); + } catch (SLCommandException e) { + log.error("Failed to create SLCommand.", e); + setError(e); + } catch (SLVersionException e) { + log.error("Failed to create SLCommand.", e); + setError(e); + } + } + + return null; + } + + protected void processInfoboxReadResult(InfoboxReadResult result) + throws JAXBException, IdLinkException { + + Object object = result.getContent(); + if (object instanceof byte[]) { + log.info("InfoboxReadResult contains unexpected binary data."); + errorResponse = result; + return; + } else if (object instanceof List) { + JAXBException exception = null; + for (Object content : (List) object) { + if (content instanceof Element) { + try { + idLink = IdLinkFactory.getInstance().unmarshallIdLink( + (Element) content); + return; + } catch (JAXBException e) { + exception = e; + } + } + } + if (exception != null) { + throw exception; + } + } + + } + + @Override + public void setHTTPHeaders(Map headerMap) { + for (String header : headerMap.keySet()) { + if (HttpUtil.HTTP_HEADER_CONTENT_TYPE.equalsIgnoreCase(header)) { + requestContentType = headerMap.get(header); + } + } + } + + @Override + public void consumeRequestStream(String url, InputStream is) { + InputDecoder inputDecoder = InputDecoderFactory.getDecoder( + requestContentType, is); + Iterator fpi = inputDecoder.getFormParameterIterator(); + while (fpi.hasNext()) { + FormParameter formParameter = fpi.next(); + if ("BKUUrl".equals(formParameter.getFormParameterName())) { + setExternal(true); + } + } + } + + @Override + public String getResultContentType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void writeResultTo(OutputStream os, String encoding) + throws IOException { + // TODO Auto-generated method stub + + } + + protected JAXBElement createReadInfoboxRequest( + String domainIdentifier) { + + ObjectFactory factory = new ObjectFactory(); + + InfoboxReadRequestType infoboxReadRequestType = factory + .createInfoboxReadRequestType(); + infoboxReadRequestType.setInfoboxIdentifier("IdentityLink"); + + InfoboxReadParamsBinaryFileType infoboxReadParamsBinaryFileType = factory + .createInfoboxReadParamsBinaryFileType(); + infoboxReadParamsBinaryFileType.setContentIsXMLEntity(true); + infoboxReadRequestType + .setBinaryFileParameters(infoboxReadParamsBinaryFileType); + + if (domainIdentifier != null) { + JAXBElement identityLinkDomainIdentifier = factory + .createIdentityLinkDomainIdentifier(domainIdentifier); + AnyChildrenType anyChildrenType = factory.createAnyChildrenType(); + anyChildrenType.getAny().add(identityLinkDomainIdentifier); + + infoboxReadRequestType.setBoxSpecificParameters(anyChildrenType); + } + + return factory.createInfoboxReadRequest(infoboxReadRequestType); + + } + + protected JAXBElement createXMLSignatureRequest() { + + ObjectFactory factory = new ObjectFactory(); + + CreateXMLSignatureRequestType createXMLSignatureRequest = factory + .createCreateXMLSignatureRequestType(); + createXMLSignatureRequest.setKeyboxIdentifier(keyBoxIdentifier); + + DataObjectInfoType dataObjectInfoType = factory.createDataObjectInfoType(); + dataObjectInfoType.setStructure("enveloping"); + + TransformsInfoType transformsInfoType = factory.createTransformsInfoType(); + MetaInfoType metaInfoType = factory.createMetaInfoType(); + metaInfoType.setMimeType("application/xhtml+xml"); + transformsInfoType.setFinalDataMetaInfo(metaInfoType); + + dataObjectInfoType.getTransformsInfo().add(transformsInfoType); + + Base64XMLLocRefOptRefContentType contentType = factory + .createBase64XMLLocRefOptRefContentType(); + + PersonalIdentifier identifier; + try { + identifier = idLink.getPersonData().getIdentifier(); + } catch (MarshalException e) { + setError(e); + return null; + } + if ("urn:publicid:gv.at:baseid".equals(identifier.getType())) { + identifier = identifier.getDerivedValue(domainIdentifier); + } + String template = templates.createQESTemplate("test", locale, idLink, "", + identifier, new Date()); + + contentType.setBase64Content(template.getBytes(Charset.forName("UTF-8"))); + + dataObjectInfoType.setDataObject(contentType); + + createXMLSignatureRequest.getDataObjectInfo().add(dataObjectInfoType); + + return factory.createCreateXMLSignatureRequest(createXMLSignatureRequest); + + } + + protected boolean validate(IdLink idLink) { + try { + if (domainIdentifier != null && domainIdentifier.startsWith("urn:publicid:gv.at:ccid")) { + if (!idLink.verifyManifest()) { + log.info("Identity link manifest verification failed."); + return false; + } + } + if (idLink.verifySignature()) { + return true; + } + } catch (MarshalException e) { + log.info("Identity link signature verification failed.", e); + } catch (XMLSignatureException e) { + log.info("Identity link signature verification failed.", e); + } + log.info("Identity link signature verification failed."); + return false; + } + + + protected boolean validate(Element signature) { + + Document doc = signature.getOwnerDocument(); + if (signature != signature.getOwnerDocument().getDocumentElement()) { + doc.replaceChild(signature, doc.getDocumentElement()); + } + + XMLSignatureFactory xmlSignatureFactory = XMLSignatureFactory.getInstance(); + + try { + IdLinkKeySelector keySelector = new IdLinkKeySelector(idLink); + DOMValidateContext validateContext = new DOMValidateContext(keySelector, signature); + + XMLSignature xmlSignature = xmlSignatureFactory + .unmarshalXMLSignature(validateContext); + + return xmlSignature.validate(validateContext); + } catch (MarshalException e) { + log.info("Failed to unmarshall signature.", e); + } catch (XMLSignatureException e) { + log.info("Failed to validate signature.", e); + } + return false; + } + + @Override + public InputStream getFormData(String parameterName) { + if ("appletPage".equals(parameterName)) { + String appletPage = (isExternal()) ? "local.jsp" : "applet.jsp"; + return new ByteArrayInputStream(appletPage.getBytes()); + } + return null; + } + + @Override + public String getRedirectURL() { + return null; + } + + @Override + public int getResponseCode() { + return HttpServletResponse.SC_OK; + } + + @Override + public Map getResponseHeaders() { + return Collections.emptyMap(); + } + +} -- cgit v1.2.3