summaryrefslogtreecommitdiff
path: root/BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java
diff options
context:
space:
mode:
Diffstat (limited to 'BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java')
-rw-r--r--BKUOnline/src/main/java/at/gv/egiz/mocca/id/SAMLBindingProcessorImpl.java357
1 files changed, 357 insertions, 0 deletions
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<String, String> 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<FormParameter> 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<InfoboxReadRequestType> 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<String> identityLinkDomainIdentifier = factory
+ .createIdentityLinkDomainIdentifier(domainIdentifier);
+ AnyChildrenType anyChildrenType = factory.createAnyChildrenType();
+ anyChildrenType.getAny().add(identityLinkDomainIdentifier);
+
+ infoboxReadRequestType.setBoxSpecificParameters(anyChildrenType);
+ }
+
+ return factory.createInfoboxReadRequest(infoboxReadRequestType);
+
+ }
+
+ protected JAXBElement<CreateXMLSignatureRequestType> 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<String, String> getResponseHeaders() {
+ return Collections.emptyMap();
+ }
+
+}