diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java')
-rw-r--r-- | id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java | 492 |
1 files changed, 492 insertions, 0 deletions
diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java new file mode 100644 index 000000000..3256e1812 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java @@ -0,0 +1,492 @@ +package at.gv.egovernment.moa.id.protocols.stork2.attributeproviders; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.activation.DataSource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.stream.StreamSource; +import javax.xml.ws.Service; +import javax.xml.ws.soap.SOAPBinding; +import javax.xml.ws.BindingProvider; + +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang.NotImplementedException; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; + +import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.stork2.ExternalAttributeRequestRequiredException; +import at.gv.egovernment.moa.id.protocols.stork2.UnsupportedAttributeException; +import at.gv.egovernment.moa.id.util.VelocityProvider; +import at.gv.egovernment.moa.logging.Logger; +import eu.stork.oasisdss.api.ApiUtils; +import eu.stork.oasisdss.api.LightweightSourceResolver; +import eu.stork.oasisdss.api.exceptions.ApiUtilsException; +import eu.stork.oasisdss.api.exceptions.UtilsException; +import eu.stork.oasisdss.profile.Base64Data; +import eu.stork.oasisdss.profile.DocumentType; +import eu.stork.oasisdss.profile.IncludeObject; +import eu.stork.oasisdss.profile.SignRequest; +import eu.stork.oasisdss.profile.SignResponse; +import eu.stork.peps.auth.commons.IPersonalAttributeList; +import eu.stork.peps.auth.commons.PEPSUtil; +import eu.stork.peps.auth.commons.PersonalAttribute; +import eu.stork.peps.auth.commons.PersonalAttributeList; +import eu.stork.peps.auth.commons.STORKAttrQueryRequest; +import eu.stork.peps.auth.engine.STORKSAMLEngine; +import eu.stork.peps.exceptions.STORKSAMLEngineException; +import eu.stork.documentservice.DocumentService; +/** + * Forwards a signedDoc attribute request to the oasis-dss service instance + */ +public class SignedDocAttributeRequestProvider extends AttributeProvider { + + private String dtlUrl = null; + private PersonalAttribute requestedAttribute; + + /** + * The URL of the service listening for the oasis dss webform post request + */ + private String oasisDssWebFormURL; + + /** + * Instantiates a new signed doc attribute request provider. + * + * @param oasisDssWebFormURL + * the AP location + * @param attributes + */ + public SignedDocAttributeRequestProvider(String oasisDssWebFormURL, String attributes) { + super(attributes); + this.oasisDssWebFormURL = oasisDssWebFormURL; + //TODO load dtlUrl from config + dtlUrl = "http://mopsos.iaik.tugraz.at:8080/DocumentService/DocumentService"; + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#acquire(java + * .lang.String) + */ + @Override + protected IPersonalAttributeList acquire(PersonalAttribute attribute, String spCountyCode, IAuthData authData) throws UnsupportedAttributeException, + ExternalAttributeRequestRequiredException { + if(!attributes.contains(attribute.getName())) { + throw new UnsupportedAttributeException(); + } + + requestedAttribute = attribute; + + throw new ExternalAttributeRequestRequiredException(this); + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#parse(javax + * .servlet.http.HttpServletRequest) + */ + public IPersonalAttributeList parse(HttpServletRequest httpReq) throws MOAIDException, UnsupportedAttributeException { + Logger.debug("Beginning to extract OASIS-DSS response out of HTTP Request"); + + try { + String signResponseString = new String(Base64.decodeBase64(httpReq.getParameter("signresponse")), "UTF8"); + //TODO + //FIXME + //test123 + //create SignResponse object + Source response = new StreamSource(new java.io.StringReader(signResponseString)); + SignResponse signResponse = ApiUtils.unmarshal(response, SignResponse.class); + //extract doc from signresponse + DataSource dataSource = LightweightSourceResolver.getDataSource(signResponse); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + IOUtils.copy(dataSource.getInputStream(), baos); + byte[] data = baos.toByteArray(); + + //update doc in DTL + String docId, dssId = ""; + docId = signResponse.getDocUI(); + //For reference dssId equals docId + dssId = docId; + if (dssId != null && data!=null) + { + if(updateDocumentInDtl(data, docId, signResponseString)) + { +// SignResponse outRes = new SignResponse(); +// outRes.setDocUI(signResponse.getDocUI()); +// outRes.setProfile(signResponse.getProfile()); +// outRes.setRequestID(signResponse.getRequestID()); +// outRes.setSignatureObject(signResponse.getSignatureObject()); + //outRes; + + signResponse.getResult().setResultMinor(dtlUrl); + System.out.println("overwriting:"+signResponse.getResult().getResultMessage()+" with DTL url:"+dtlUrl); + InputStream istr = ApiUtils.marshalToInputStream(signResponse); + StringWriter writer = new StringWriter(); + IOUtils.copy(istr, writer, "UTF-8"); + signResponseString = writer.toString(); + System.out.println("SignResponse overwritten:"+signResponseString); + } + } + else + throw new Exception("No DSS id found."); + + + //alter signresponse + //done + List<String> values = new ArrayList<String>(); + values.add(signResponseString); + + Logger.debug("Assembling signedDoc attribute"); + PersonalAttribute signedDocAttribute = new PersonalAttribute("signedDoc", false, values, + "Available"); + + // pack and return the result + PersonalAttributeList result = new PersonalAttributeList(); + result.add(signedDocAttribute); + return result; + } catch (UnsupportedEncodingException e) { + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } catch (ApiUtilsException e) { + e.printStackTrace(); + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } catch (IOException e) { + e.printStackTrace(); + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } catch (Exception e) { + e.printStackTrace(); + Logger.error("Failed to assemble signedDoc attribute"); + throw new MOAIDException("stork.05", null); + } + } + + /* + * (non-Javadoc) + * + * @see + * at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#performRedirect + * (java.lang.String) + */ + public void performRedirect(String url, HttpServletRequest req, HttpServletResponse resp, OAAuthParameter oaParam) + throws MOAIDException { + + try { + Logger.trace("Initialize VelocityEngine..."); + + VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine(); + Template template = velocityEngine.getTemplate("/resources/templates/oasis_dss_webform_binding.vm"); + VelocityContext context = new VelocityContext(); + + //Parse SignRequest + String signRequestString = requestedAttribute.getValue().get(0); + Source signDoc = new StreamSource(new java.io.StringReader(signRequestString)); + SignRequest signRequest = ApiUtils.unmarshal(signDoc, SignRequest.class); + try{ + //TODO + //FIXME + //search for DTL link + String dtlURL = getDtlUrlFromRequest(signRequest); + String docId = signRequest.getDocUI(); + + String docRequest = getDocTransferRequest(docId, dtlURL);//dtlUrl + + byte[] data = getDocumentFromDtl(docRequest, dtlURL);//dtlUrl + //load doc from DTL + System.out.println("data:"+data); + String mime = getDocumentMimeFromDtl(docId, dtlURL);//dtlUrl + System.out.println("mime:"+mime); + //add doc as base64* to signrequest => post doc to oasis + try{ + List<IncludeObject> includeObjects = ApiUtils.findNamedElement( + signRequest.getOptionalInputs(), "IncludeObject", + IncludeObject.class); + signRequest.getOptionalInputs().getAny().removeAll(includeObjects); + + DocumentType document = new DocumentType(); + Base64Data b64data = new Base64Data(); + b64data.setValue(data); + b64data.setMimeType(mime); + document.setBase64Data(b64data); + signRequest.setInputDocuments(ApiUtils.createInputDocuments(document)); + //override old signRequestString + + InputStream istr = ApiUtils.marshalToInputStream(signRequest); + StringWriter writer = new StringWriter(); + IOUtils.copy(istr, writer, "UTF-8"); + signRequestString = writer.toString(); + System.out.println("Signrequest overwritten"); + } catch (Exception e) { + e.printStackTrace(); + throw new Exception("Could not marshall sign request", e); + } + + + }catch(Exception e) + { + Logger.info("No documentservice used?"); + e.printStackTrace(); + } + + context.put("signrequest", Base64.encodeBase64String(signRequestString.getBytes("UTF8"))); + context.put("clienturl", url); + context.put("action", oasisDssWebFormURL); + + StringWriter writer = new StringWriter(); + template.merge(context, writer); + + resp.getOutputStream().write(writer.toString().getBytes()); + } catch (Exception e) { + Logger.error("Error sending DSS signrequest.", e); + throw new MOAIDException("stork.11", null); + } + } + + + + /* (non-Javadoc) + * @see at.gv.egovernment.moa.id.protocols.stork2.AttributeProvider#getSupportedAttributeNames() + */ + @Override + public List<String> getSupportedAttributeNames() throws MOAIDException { + ArrayList<String> supportedAttributeNames = new ArrayList<String>(); + for (String attributeName : this.attributes.split(",")) { + supportedAttributeNames.add(attributeName); + } + return supportedAttributeNames; + } + + + //From DTLPEPSUTIL + + /** + * Get DTL uril from the oasis sign request + * @param signRequest The signature request + * @return The URL of DTL service + * @throws SimpleException + */ + private String getDtlUrlFromRequest(SignRequest signRequest) throws Exception + { + if (signRequest == null) + throw new Exception("Signature request is empty"); + else + { + try + { + Object objDoc = signRequest.getInputDocuments().getDocumentOrTransformedDataOrDocumentHash().get(0); + if (objDoc instanceof DocumentType) + { + DocumentType document = (DocumentType)objDoc; + if (document.getDocumentURL() != null) + return document.getDocumentURL(); + else + throw new Exception("No document url found"); + } + else + throw new Exception("No input document found"); + } + catch (Exception ex) + { + throw new Exception("Unable to parse xml.", ex); + } + } + } + + /** + * Get document from DTL + * @param transferRequest The transfer request (attribute query) + * @param eDtlUrl The DTL url of external DTL + * @return the document data + * @throws SimpleException + */ + private byte[] getDocumentFromDtl(String transferRequest, String eDtlUrl) throws Exception + { + URL url = null; + try + { + url = new URL(dtlUrl); + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + if (eDtlUrl.equalsIgnoreCase(dtlUrl)) + return docservice.getDocument(transferRequest, ""); + else + return docservice.getDocument(transferRequest, eDtlUrl); + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Error in getDocumentFromDtl", e); + } + } + + /** + * Get a document transfer request (attribute query) + * @param docId + * @return + * @throws SimpleException + */ + private String getDocTransferRequest(String docId, String destinationUrl) throws Exception + { + final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP");//getInstance(samlDTLInstance); + STORKAttrQueryRequest req = new STORKAttrQueryRequest(); + req.setAssertionConsumerServiceURL(dtlUrl); + req.setDestination(destinationUrl); + req.setSpCountry("IS");//FIXME + req.setQaa(3);//TODO + PersonalAttributeList pal = new PersonalAttributeList(); + PersonalAttribute attr = new PersonalAttribute(); + attr.setName("docRequest"); + attr.setIsRequired(true); + attr.setValue(Arrays.asList(docId)); + pal.add(attr); + req.setPersonalAttributeList(pal); + + STORKAttrQueryRequest req1; + try { + req1 = engine.generateSTORKAttrQueryRequest(req); + return PEPSUtil.encodeSAMLTokenUrlSafe(req1.getTokenSaml()); + } catch (STORKSAMLEngineException e) { + e.printStackTrace(); + throw new Exception("Error in doc request attribute query generation", e); + } + } + + /** + * Get mime type of document from DTL + * @param docId The document id + * @param dtlUrl The url of dtl + * @return The mime type + */ + private String getDocumentMimeFromDtl(String docId, String eDtlUrl) throws Exception + { + URL url = null; + try + { + url = new URL(dtlUrl); + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + if (eDtlUrl.equalsIgnoreCase(dtlUrl)) + return docservice.getDocumentMime(docId, ""); + else + return docservice.getDocumentMime(docId, eDtlUrl); + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Error in getDocumentFromDtl", e); + } + } + + /** + * Add document to DTL service + * @param docData the document data + * @param mime the mime type of data + * @param signRequest the sign request + * @return the document id + * @throws SimpleException + */ + private String addDocumentToDtl(byte[] docData, String mime, String signRequest, String destCountry, String spId) throws Exception + { + throw new NotImplementedException(); +// URL url = null; +// String docID = null; +// try +// { +// url = new URL(dtlUrl); +// QName qname = new QName("http://stork.eu", +// "DocumentService"); +// +// Service service = Service.create(url, qname); +// DocumentService docservice = service.getPort(DocumentService.class); +// +// BindingProvider bp = (BindingProvider) docservice; +// SOAPBinding binding = (SOAPBinding) bp.getBinding(); +// binding.setMTOMEnabled(true); +// +// docID = docservice.addDocument(docData, signRequest, destCountry, spId, mime, ""); +// } +// catch (Exception e) +// { +// e.printStackTrace(); +// throw new Exception("Error in addDocumentToDtl", e); +// } +// +// return docID; + } + + /** + * Update document in DTL + * @param docData The docment data + * @param docId The document ID + * @param signResponse The signature response + * @return True if successful + * @throws SimpleException + */ + private boolean updateDocumentInDtl(byte[] docData, String docId, String signResponse) throws Exception + { + boolean success = false; + URL url = null; + try + { + url = new URL(dtlUrl); + QName qname = new QName("http://stork.eu", + "DocumentService"); + + Service service = Service.create(url, qname); + DocumentService docservice = service.getPort(DocumentService.class); + + BindingProvider bp = (BindingProvider) docservice; + SOAPBinding binding = (SOAPBinding) bp.getBinding(); + binding.setMTOMEnabled(true); + + success = docservice.updateDocument(docId, signResponse, docData); + } + catch (Exception e) + { + e.printStackTrace(); + throw new Exception("Error in addDocumentToDtl", e); + } + + return success; + } +} |