From 299c1b3679abecdae88d71002acb626661616b0d Mon Sep 17 00:00:00 2001 From: Thomas Lenz Date: Thu, 19 Feb 2015 12:25:55 +0100 Subject: manuell merge: PEPSConnecterServlet --> PepsConnectorTask --- .../modules/stork/tasks/PepsConnectorTask.java | 269 +++++++++++++++++---- .../resources/xmldata/fakeIdL_IdL_template.xml | 51 ++++ 2 files changed, 268 insertions(+), 52 deletions(-) create mode 100644 id/server/modules/module-stork/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml (limited to 'id/server/modules') diff --git a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java index 94017e9f6..1a18f8198 100644 --- a/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java +++ b/id/server/modules/module-stork/src/main/java/at/gv/egovernment/moa/id/auth/modules/stork/tasks/PepsConnectorTask.java @@ -28,6 +28,8 @@ import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.opensaml.saml2.core.StatusCode; +import org.w3c.dom.Element; +import org.w3c.dom.Node; import at.gv.egovernment.moa.id.auth.AuthenticationServer; import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; @@ -36,6 +38,8 @@ import at.gv.egovernment.moa.id.auth.data.IdentityLink; import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; import at.gv.egovernment.moa.id.auth.exception.MOAIDException; import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; +import at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorServlet; import at.gv.egovernment.moa.id.auth.stork.STORKException; import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor; import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; @@ -46,9 +50,12 @@ import at.gv.egovernment.moa.id.process.api.ExecutionContext; import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; import at.gv.egovernment.moa.id.util.HTTPUtils; +import at.gv.egovernment.moa.id.util.IdentityLinkReSigner; import at.gv.egovernment.moa.id.util.VelocityProvider; import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.DOMUtils; import at.gv.egovernment.moa.util.StringUtils; +import at.gv.egovernment.moa.util.XPathUtils; import at.gv.util.xsd.xmldsig.SignatureType; import at.gv.util.xsd.xmldsig.X509DataType; import eu.stork.documentservice.DocumentService; @@ -111,19 +118,9 @@ import eu.stork.peps.exceptions.STORKSAMLEngineException; */ public class PepsConnectorTask extends AbstractAuthServletTask { - private String dtlUrl = null; - public PepsConnectorTask() { super(); - Properties props = new Properties(); - try { - props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties")); - dtlUrl = props.getProperty("docservice.url"); - } catch (IOException e) { - dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService"; - Logger.error("Loading DTL config failed, using default value:" + dtlUrl); - e.printStackTrace(); - } + } @Override @@ -235,6 +232,57 @@ public class PepsConnectorTask extends AbstractAuthServletTask { throw new MOAIDException("stork.07", null); } + OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(moaSession.getPublicOAURLPrefix()); + if (oaParam == null) + throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() }); + + //================== Check QAA level start ==================== + int reqQaa = -1; + int authQaa = -1; + String authQaaStr = null; + try { + reqQaa = storkAuthnRequest.getQaa(); + + //TODO: found better solution, but QAA Level in response could be not supported yet + try { + + authQaaStr = authnResponse.getAssertions().get(0). + getAuthnStatements().get(0).getAuthnContext(). + getAuthnContextClassRef().getAuthnContextClassRef(); + moaSession.setQAALevel(authQaaStr); + + } catch (Throwable e) { + Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level"); + moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel()); + authQaaStr = PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel(); + } + if(authQaaStr != null)//Check value only if set + { + authQaa = Integer.valueOf(authQaaStr.substring(PVPConstants.STORK_QAA_PREFIX.length())); +// authQaa = Integer.valueOf(authQaaStr); + if (reqQaa > authQaa) { + Logger.warn("Requested QAA level does not match to authenticated QAA level"); + throw new MOAIDException("stork.21", new Object[]{reqQaa, authQaa}); + + } + } + } catch (MOAIDException e) { + throw e; + + } catch (Exception e) { + if (Logger.isDebugEnabled()) + Logger.warn("STORK QAA Level evaluation error", e); + + else + Logger.warn("STORK QAA Level evaluation error (ErrorMessage=" + + e.getMessage() + ")"); + + throw new MOAIDException("stork.21", new Object[]{reqQaa, authQaa}); + + } + //================== Check QAA level end ==================== + + Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID); // //////////// incorporate gender from parameters if not in stork response @@ -279,27 +327,42 @@ public class PepsConnectorTask extends AbstractAuthServletTask { new java.io.StringReader(signatureInfo))); // fetch signed doc - DataSource ds = LightweightSourceResolver.getDataSource(dssSignResponse); - if (ds == null) { - throw new ApiUtilsException("No datasource found in response"); + DataSource ds = null; + try{ + ds = LightweightSourceResolver.getDataSource(dssSignResponse); + }catch(Exception e) + { + e.printStackTrace(); } - - InputStream incoming = ds.getInputStream(); - citizenSignature = IOUtils.toString(incoming); - incoming.close(); - - Logger.debug("citizenSignature:" + citizenSignature); - if (isDocumentServiceUsed(citizenSignature) == true) { - Logger.debug("Loading document from DocumentService."); - String url = getDtlUrlFromResponse(dssSignResponse); - // get Transferrequest - String transferRequest = getDocTransferRequest(dssSignResponse.getDocUI(), url); - // Load document from DocujmentService - byte[] data = getDocumentFromDtl(transferRequest, url); - citizenSignature = new String(data, "UTF-8"); - Logger.debug("Overridung citizenSignature with:" + citizenSignature); + if(ds == null){ + //Normal DocumentServices return a http-page, but the SI DocumentService returns HTTP error 500 + //which results in an exception and ds==null + + //try to load document from documentservice + citizenSignature = loadDocumentFromDocumentService(dssSignResponse); + //throw new ApiUtilsException("No datasource found in response"); + } + else + { + InputStream incoming = ds.getInputStream(); + citizenSignature = IOUtils.toString(incoming); + incoming.close(); + + Logger.debug("citizenSignature:"+citizenSignature); + if(isDocumentServiceUsed(citizenSignature)==true) + { + citizenSignature = loadDocumentFromDocumentService(dssSignResponse); + // Logger.debug("Loading document from DocumentService."); + // String url = getDtlUrlFromResponse(dssSignResponse); + // //get Transferrequest + // String transferRequest = getDocTransferRequest(dssSignResponse.getDocUI(), url); + // //Load document from DocumentService + // byte[] data = getDocumentFromDtl(transferRequest, url); + // citizenSignature = new String(data, "UTF-8"); + // Logger.debug("Overridung citizenSignature with:"+citizenSignature); + } } - + JAXBContext ctx = JAXBContext.newInstance(SignatureType.class.getPackage().getName()); SignatureType root = ((JAXBElement) ctx.createUnmarshaller().unmarshal( IOUtils.toInputStream(citizenSignature))).getValue(); @@ -338,11 +401,7 @@ public class PepsConnectorTask extends AbstractAuthServletTask { // Logger.error("could not retrieve moa session"); // throw new AuthenticationException("auth.01", null); // } - OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter( - moaSession.getPublicOAURLPrefix()); - if (oaParam == null) - throw new AuthenticationException("auth.00", new Object[] { moaSession.getPublicOAURLPrefix() }); - + // retrieve target // TODO: check in case of SSO!!! String targetType = null; @@ -361,8 +420,66 @@ public class PepsConnectorTask extends AbstractAuthServletTask { IdentityLink identityLink = null; executionContext.put("identityLinkAvailable", false); try { - identityLink = STORKResponseProcessor.connectToSZRGateway(authnResponse.getPersonalAttributeList(), - oaParam.getFriendlyName(), targetType, null, oaParam.getMandateProfiles(), citizenSignature); + AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); + if(config.isStorkFakeIdLActive() && config.getStorkFakeIdLCountries().contains(storkAuthnRequest.getCitizenCountryCode())) { + // create fake IdL + // - fetch IdL template from resources + InputStream s = PepsConnectorTask.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml"); + Element idlTemplate = DOMUtils.parseXmlValidating(s); + + identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink(); + + // replace data + Element idlassertion = identityLink.getSamlAssertion(); + // - set bpk/wpbk; + Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH); + if(!STORKResponseProcessor.hasAttribute("eIdentifier", attributeList)) + throw new STORKException("eIdentifier is missing"); + String eIdentifier = STORKResponseProcessor.getAttributeValue("eIdentifier", attributeList, false); + prIdentification.getFirstChild().setNodeValue(eIdentifier); + + // - set last name + Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH); + if(!STORKResponseProcessor.hasAttribute("surname", attributeList)) + throw new STORKException("surname is missing"); + String familyName = STORKResponseProcessor.getAttributeValue("surname", attributeList, false); + prFamilyName.getFirstChild().setNodeValue(familyName); + + // - set first name + Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH); + if(!STORKResponseProcessor.hasAttribute("givenName", attributeList)) + throw new STORKException("givenName is missing"); + String givenName = STORKResponseProcessor.getAttributeValue("givenName", attributeList, false); + prGivenName.getFirstChild().setNodeValue(givenName); + + // - set date of birth + Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH); + if(!STORKResponseProcessor.hasAttribute("dateOfBirth", attributeList)) + throw new STORKException("dateOfBirth is missing"); + String dateOfBirth = STORKResponseProcessor.getAttributeValue("dateOfBirth", attributeList, false); + prDateOfBirth.getFirstChild().setNodeValue(dateOfBirth); + + identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink(); + + //resign IDL + IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance(); + Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), config.getStorkFakeIdLResigningKey()); + identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink(); + + } else { + //contact SZR Gateway + Logger.debug("Starting connecting SZR Gateway"); + + identityLink = STORKResponseProcessor.connectToSZRGateway( + authnResponse.getPersonalAttributeList(), + oaParam.getFriendlyName(), + targetType, + null, + oaParam.getMandateProfiles(), + citizenSignature); + + } + } catch (STORKException e) { // this is really nasty but we work against the system here. We are supposed to get the gender attribute // from @@ -422,17 +539,17 @@ public class PepsConnectorTask extends AbstractAuthServletTask { // stork did the authentication step moaSession.setAuthenticated(true); - // TODO: found better solution, but QAA Level in response could be not supported yet - try { - - moaSession.setQAALevel(authnResponse.getAssertions().get(0).getAuthnStatements().get(0) - .getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef()); - - } catch (Throwable e) { - Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level"); - moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel()); - - } + // TODO: found better solution, but QAA Level in STORK response is not be supported yet +// try { +// +// moaSession.setQAALevel(authnResponse.getAssertions().get(0).getAuthnStatements().get(0) +// .getAuthnContext().getAuthnContextClassRef().getAuthnContextClassRef()); +// +// } catch (Throwable e) { +// Logger.warn("STORK QAA-Level is not found in AuthnResponse. Set QAA Level to requested level"); +// moaSession.setQAALevel(PVPConstants.STORK_QAA_PREFIX + oaParam.getQaaLevel()); +// +// } // session is implicit stored in changeSessionID!!!! String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(moaSession); @@ -471,8 +588,12 @@ public class PepsConnectorTask extends AbstractAuthServletTask { private boolean isDocumentServiceUsed(String citizenSignature) // TODo add better check { if (citizenSignature - .contains("
Service Name:{http://stork.eu}DocumentService
Port Name:{http://stork.eu}DocumentServicePort
")) + .contains("
Service Name:{http://stork.eu}DocumentService
Port Name:{http://stork.eu}DocumentServicePort
")) { + Logger.trace("isDocumentServiceUsed => true"); return true; + } + + Logger.trace("isDocumentServiceUsed => false"); return false; } @@ -510,7 +631,9 @@ public class PepsConnectorTask extends AbstractAuthServletTask { private byte[] getDocumentFromDtl(String transferRequest, String eDtlUrl) throws Exception { URL url = null; try { - url = new URL(dtlUrl); + + Logger.trace("getDocumentFromDtl, dtlUrl:'"+getdtlUrl()+"' eDtlUrl:'"+eDtlUrl+"'"); + url = new URL(getdtlUrl()); QName qname = new QName("http://stork.eu", "DocumentService"); Service service = Service.create(url, qname); @@ -520,7 +643,7 @@ public class PepsConnectorTask extends AbstractAuthServletTask { SOAPBinding binding = (SOAPBinding) bp.getBinding(); binding.setMTOMEnabled(true); - if (eDtlUrl.equalsIgnoreCase(dtlUrl)) + if (eDtlUrl.equalsIgnoreCase(getdtlUrl())) return docservice.getDocument(transferRequest, ""); else return docservice.getDocument(transferRequest, eDtlUrl); @@ -541,7 +664,7 @@ public class PepsConnectorTask extends AbstractAuthServletTask { String spCountry = docId.substring(0, docId.indexOf("/")); final STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); STORKAttrQueryRequest req = new STORKAttrQueryRequest(); - req.setAssertionConsumerServiceURL(dtlUrl); + req.setAssertionConsumerServiceURL(getdtlUrl()); req.setDestination(destinationUrl); req.setSpCountry(spCountry); req.setQaa(3);// TODO @@ -562,5 +685,47 @@ public class PepsConnectorTask extends AbstractAuthServletTask { throw new Exception("Error in doc request attribute query generation", e); } } + + private String getdtlUrl() { + String dtlUrl; + try { + AuthConfigurationProvider authConfigurationProvider = AuthConfigurationProvider.getInstance(); + dtlUrl = authConfigurationProvider.getDocumentServiceUrl(); + Logger.info ("PEPSConnectorServlet, using dtlUrl:"+dtlUrl); + + } catch (Exception e) { + dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService"; + Logger.error("Loading documentservice url failed, using default value:"+dtlUrl, e); + + } + + +// Properties props = new Properties(); +// try { +// props.load(DatabaseConnectorMySQLImpl.class.getResourceAsStream("docservice.properties")); +// dtlUrl = props.getProperty("docservice.url"); +// } catch (IOException e) { +// dtlUrl = "http://testvidp.buergerkarte.at/DocumentService/DocumentService"; +// Logger.error("Loading DTL config failed, using default value:" + dtlUrl); +// e.printStackTrace(); +// } + + return dtlUrl; + + } + + private String loadDocumentFromDocumentService(SignResponse dssSignResponse) throws Exception + { + Logger.debug("Loading document from DocumentService."); + String url = getDtlUrlFromResponse(dssSignResponse); + Logger.debug("Loading document from DocumentService, url:"+url); + //get Transferrequest + String transferRequest = getDocTransferRequest(dssSignResponse.getDocUI(), url); + //Load document from DocumentService + byte[] data = getDocumentFromDtl(transferRequest, url); + String citizenSignature = new String(data, "UTF-8"); + Logger.debug("Overridung citizenSignature with:"+citizenSignature); + return citizenSignature; + } } diff --git a/id/server/modules/module-stork/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml b/id/server/modules/module-stork/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml new file mode 100644 index 000000000..09084a34f --- /dev/null +++ b/id/server/modules/module-stork/src/main/resources/resources/xmldata/fakeIdL_IdL_template.xml @@ -0,0 +1,51 @@ + + + + + urn:oasis:names:tc:SAML:1.0:cm:sender-vouches + + wJO/bvDJjUysG0yARn7I6w==urn:publicid:gv.at:baseidXXXRúùdXXXVàn Nisteĺrooy1969-02-13 + + + + 4Y4FL09VhczsfYQgFPuycP8quJNZBAAu1R1rFXNodI2711B6BTMjAGQn6xuFWfd3/nyFav/MLTr/ +t2VazvANS4TRFxJAcWyIx7xbxCdzZr6gJ+FCmq4g5JPrQvt50v3JX+wKSYft1gHBOWlDn90Ia4Gm +P8MVuze21T+VVKM6ZklmS6d5PT1er/uYQFydGErmJ17xlSQG6Fi5xuftopBDyJxG1tL1KIebpLFg +gaM2EyuB1HxH8/+Mfqa4UgeqIH65AQAB + + + + + + + + not(ancestor-or-self::pr:Identification) + + + + + KEQEPY2O3Z3IRaISSSoRZVPzsHE= + + + + gzGhjH1kdmPcPbgen0xojNIoJLk= + + + + 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 + + + + + + not(ancestor-or-self::dsig:Signature) + + + + 8e7RjLnA4Mgltq5ruIJzheKGxu0= + + + + + \ No newline at end of file -- cgit v1.2.3