diff options
Diffstat (limited to 'id/server/idserverlib/src/main')
31 files changed, 3057 insertions, 280 deletions
| diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java index a58f5fce2..a57ab5262 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationServer.java @@ -29,8 +29,12 @@ import iaik.x509.X509Certificate;  import java.io.ByteArrayInputStream;  import java.io.File;  import java.io.IOException; +import java.io.InputStream;  import java.security.GeneralSecurityException;  import java.security.Principal; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.util.ArrayList;  import java.util.Calendar;  import java.util.Date;  import java.util.HashMap; @@ -41,18 +45,24 @@ import java.util.Map;  import java.util.Set;  import java.util.Vector; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession;  import javax.xml.parsers.ParserConfigurationException;  import javax.xml.transform.TransformerException;  import org.apache.xpath.XPathAPI; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.xml.util.Base64; +import org.opensaml.xml.util.XMLHelper;  import org.w3c.dom.Document;  import org.w3c.dom.Element; -import org.w3c.dom.Node;  import org.w3c.dom.NodeList;  import org.xml.sax.SAXException;  import at.gv.egovernment.moa.id.AuthenticationException;  import at.gv.egovernment.moa.id.BuildException; +import at.gv.egovernment.moa.id.MOAIDException;  import at.gv.egovernment.moa.id.ParseException;  import at.gv.egovernment.moa.id.ServiceException;  import at.gv.egovernment.moa.id.auth.builder.AuthenticationBlockAssertionBuilder; @@ -83,6 +93,9 @@ import at.gv.egovernment.moa.id.auth.parser.InfoboxReadResponseParser;  import at.gv.egovernment.moa.id.auth.parser.SAMLArtifactParser;  import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser;  import at.gv.egovernment.moa.id.auth.servlet.AuthServlet; +import at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorServlet; +import at.gv.egovernment.moa.id.auth.stork.STORKAuthnRequestProcessor; +import at.gv.egovernment.moa.id.auth.stork.STORKException;  import at.gv.egovernment.moa.id.auth.validator.CreateXMLSignatureResponseValidator;  import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator;  import at.gv.egovernment.moa.id.auth.validator.InfoboxValidator; @@ -90,6 +103,9 @@ import at.gv.egovernment.moa.id.auth.validator.ValidateException;  import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureResponseValidator;  import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils;  import at.gv.egovernment.moa.id.auth.validator.parep.ParepValidator; +import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.CreateIdentityLinkResponse; +import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWClient; +import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWClientException;  import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWConstants;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.config.ConfigurationProvider; @@ -98,6 +114,8 @@ import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.config.auth.VerifyInfoboxParameter;  import at.gv.egovernment.moa.id.config.auth.VerifyInfoboxParameters; +import at.gv.egovernment.moa.id.config.stork.CPEPS; +import at.gv.egovernment.moa.id.config.stork.STORKConfig;  import at.gv.egovernment.moa.id.data.AuthenticationData;  import at.gv.egovernment.moa.id.util.HTTPUtils;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; @@ -113,6 +131,15 @@ import at.gv.egovernment.moa.util.DOMUtils;  import at.gv.egovernment.moa.util.DateTimeUtils;  import at.gv.egovernment.moa.util.FileUtils;  import at.gv.egovernment.moa.util.StringUtils; +import eu.stork.mw.messages.saml.STORKAuthnRequest; +import eu.stork.vidp.messages.builder.STORKMessagesBuilder; +import eu.stork.vidp.messages.common.STORKConstants; +import eu.stork.vidp.messages.exception.SAMLException; +import eu.stork.vidp.messages.exception.SAMLValidationException; +import eu.stork.vidp.messages.stork.QualityAuthenticationAssuranceLevel; +import eu.stork.vidp.messages.stork.RequestedAttributes; +import eu.stork.vidp.messages.util.SAMLUtil; +import eu.stork.vidp.messages.util.XMLUtil;  /**   * API for MOA ID Authentication Service.<br> {@link AuthenticationSession} is @@ -543,16 +570,16 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		int b = xmlInfoboxReadResponse.indexOf(se);  		if (b != -1) { // no identity link found  			Logger -					.info("Es konnte keine Personenbindung auf der Karte gefunden werden. Versuche Anmeldung als ausländische eID."); +					.info("Es konnte keine Personenbindung auf der Karte gefunden werden. Versuche Anmeldung als ausl�ndische eID.");  			return null;  		} -		// spezifikationsgemäßer (SL1.2) Errorcode +		// spezifikationsgem��er (SL1.2) Errorcode  		se = "ErrorCode>4002";  		// b = xmlInfoboxReadResponse.contains(se);  		b = xmlInfoboxReadResponse.indexOf(se);  		if (b != -1) { // Unbekannter Infoboxbezeichner  			Logger -					.info("Unbekannter Infoboxbezeichner. Versuche Anmeldung als ausländische eID."); +					.info("Unbekannter Infoboxbezeichner. Versuche Anmeldung als ausl�ndische eID.");  			return null;  		} @@ -1732,7 +1759,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		// builds authentication data and stores it together with a SAML  		// artifact  		AuthenticationData authData = buildAuthenticationData(session, vsresp, -				useUTC); +				useUTC, false);  		if (session.getUseMandate()) {  			// mandate mode @@ -2037,17 +2064,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		AuthenticationSession session = getSession(sessionID);  		// AuthConfigurationProvider authConf =  		// AuthConfigurationProvider.getInstance(); -		try { -			String serializedAssertion = DOMUtils.serializeNode(session -					.getIdentityLink().getSamlAssertion()); -			session.setAuthBlock(serializedAssertion); -		} catch (TransformerException e) { -			throw new ParseException("parser.04", new Object[] { -					REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE }); -		} catch (IOException e) { -			throw new ParseException("parser.04", new Object[] { -					REQ_VERIFY_AUTH_BLOCK, PARAM_XMLRESPONSE }); -		} +		  		// post processing of the infoboxes  		Iterator iter = session.getInfoboxValidatorIterator();  		boolean formpending = false; @@ -2097,7 +2114,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		boolean useCondition = oaParam.getUseCondition();  		int conditionLength = oaParam.getConditionLength();  		AuthenticationData authData = buildAuthenticationData(session, vsresp, -				useUTC); +				useUTC, true);  		String samlAssertion = new AuthenticationDataAssertionBuilder().build(  				authData, session.getAssertionPrPerson(), session @@ -2141,6 +2158,9 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 *            authentication session  	 * @param verifyXMLSigResp  	 *            VerifyXMLSignatureResponse from MOA-SP +	 * @param useUTC uses correct UTC time format +	 * @param useUTC indicates that authenticated citizen is a foreigner +	 * @param isForeigner indicates whether Austrian (false) or foreigner (true) authenticates  	 * @return AuthenticationData object  	 * @throws ConfigurationException  	 *             while accessing configuration data @@ -2149,7 +2169,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 */  	private AuthenticationData buildAuthenticationData(  			AuthenticationSession session, -			VerifyXMLSignatureResponse verifyXMLSigResp, boolean useUTC) +			VerifyXMLSignatureResponse verifyXMLSigResp, boolean useUTC, boolean isForeigner)  			throws ConfigurationException, BuildException {  		IdentityLink identityLink = session.getIdentityLink(); @@ -2196,21 +2216,44 @@ public class AuthenticationServer implements MOAIDAuthConstants {  				}  			}  			authData.setSignerCertificate(signerCertificateBase64); -			if (businessService) { -				authData.setWBPK(identityLink.getIdentificationValue()); +			if(!isForeigner) { +				//we have Austrian citizen +				if (businessService) { +					authData.setWBPK(identityLink.getIdentificationValue()); +				} else { +					authData.setBPK(identityLink.getIdentificationValue()); +	 +					// BZ.., calculation of bPK already before sending AUTHBlock +					/* +					 * if(identityLink.getIdentificationType().equals(Constants. +					 * URN_PREFIX_BASEID)) { // only compute bPK if online +					 * application is a public service and we have the Stammzahl +					 * String bpkBase64 = new BPKBuilder().buildBPK( +					 * identityLink.getIdentificationValue(), session.getTarget()); +					 * authData.setBPK(bpkBase64); } +					 */ +	 +				}  			} else { -				authData.setBPK(identityLink.getIdentificationValue()); - -				// BZ.., calculation of bPK already before sending AUTHBlock -				/* -				 * if(identityLink.getIdentificationType().equals(Constants. -				 * URN_PREFIX_BASEID)) { // only compute bPK if online -				 * application is a public service and we have the Stammzahl -				 * String bpkBase64 = new BPKBuilder().buildBPK( -				 * identityLink.getIdentificationValue(), session.getTarget()); -				 * authData.setBPK(bpkBase64); } -				 */ - +				//we have foreigner, thus we have to calculate bPK and wbPK now (after receiving identity link from SZR-GW +				if (businessService) { +					//since we have foreigner, wbPK is not calculated in BKU +					if(identityLink.getIdentificationType().equals(Constants.URN_PREFIX_BASEID)) { 						  +						 String wbpkBase64 = new BPKBuilder().buildWBPK(identityLink.getIdentificationValue(), session.getDomainIdentifier()); +						 authData.setWBPK(wbpkBase64);  +					 }										 +					 +				} else { +					 +					 if(identityLink.getIdentificationType().equals(Constants.URN_PREFIX_BASEID)) {  +						 // only compute bPK if online application is a public service and we have the Stammzahl +						 String bpkBase64 = new BPKBuilder().buildBPK(identityLink.getIdentificationValue(), session.getTarget()); +						 authData.setBPK(bpkBase64);  +					 } +					 +	 +				} +				  			}  			String ilAssertion = oaParam.getProvideIdentityLink() ? identityLink  					.getSerializedSamlAssertion() @@ -2227,8 +2270,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			session.setAssertionBusinessService(businessService);  			session.setAssertionIlAssertion(ilAssertion);  			session.setAssertionPrPerson(prPerson); -			session -					.setAssertionSignerCertificateBase64(signerCertificateBase64); +			session.setAssertionSignerCertificateBase64(signerCertificateBase64);  			return authData; @@ -2482,4 +2524,288 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		return value;  	} +	 +	/** +	   * Does the request to the SZR-GW +	   * @param signature XMLDSIG signature +	   * @return Identity link assertion +	 * @throws SZRGWClientException  +	   */ +	     public CreateIdentityLinkResponse getIdentityLink(String PEPSIdentifier, String PEPSFirstname, String PEPSFamilyname, String PEPSDateOfBirth, Element signature) throws SZRGWClientException { + +		    SZRGWClient client = new SZRGWClient(); +		  +		    try { +		    	AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance(); +		    	ConnectionParameter connectionParameters = authConf.getForeignIDConnectionParameter(); + +		    	client.setAddress(connectionParameters.getUrl()); +		    	if (connectionParameters.getUrl().toLowerCase().startsWith("https:")) { +		    		Logger.debug("Initialisiere SSL Verbindung"); +		    		try { +		    			client.setSSLSocketFactory(SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters)); +		    		} catch (IOException e) { +		    			Logger.error("Could not initialize SSL Factory", e); +		    			throw new SZRGWClientException("Could not initialize SSL Factory"); +		    		} catch (GeneralSecurityException e) { +		    			Logger.error("Could not initialize SSL Factory", e); +		    			throw new SZRGWClientException("Could not initialize SSL Factory"); +		    		} catch (PKIException e) { +		    			Logger.error("Could not initialize SSL Factory", e); +		    			throw new SZRGWClientException("Could not initialize SSL Factory"); +		    		}  +		    	} +		    	Logger.info("Starte Kommunikation mit dem Stammzahlenregister Gateway(" + connectionParameters.getUrl() + ")..."); +		    } +		    catch (ConfigurationException e) { +		    	Logger.warn(e); +		    	Logger.warn(MOAIDMessageProvider.getInstance().getMessage("config.12", null )); +		    } +		     +		    // create request +		    CreateIdentityLinkResponse response = null; +		    Element request = null; +		    try { +		    	Document doc = client.buildGetIdentityLinkRequest(PEPSIdentifier, PEPSFirstname, PEPSFamilyname, PEPSDateOfBirth, signature); +		    	request = doc.getDocumentElement(); +		    	 +		    	// send request +		    	response = client.createIdentityLinkResponse(request); +		    } catch (SZRGWClientException e) { +		    	// 	give him a second try - Nach dem Starten des Tomcat wird beim ersten Mal das Client-Zertifikat offenbar vom HTTPClient nicht mitgeschickt. +		    	try { +		    		response = client.createIdentityLinkResponse(request); +		    	}  +		    	catch (SZRGWClientException e1) { +		    		throw new SZRGWClientException(e1); +		    	} +		    } +	         +		     +		    return response; +		 +	  } +	 +	/** +	 * Starts a MOA-ID authentication process using STORK +	 * @param req HttpServletRequest +	 * @param resp HttpServletResponse +	 * @param ccc Citizen country code +	 * @param oaURL URL of the online application  +	 * @param target Target parameter +	 * @param targetFriendlyName Friendly Name of Target +	 * @param authURL Authentication URL +	 * @param sourceID SourceID parameter +	 * @throws MOAIDException +	 * @throws AuthenticationException +	 * @throws WrongParametersException +	 * @throws ConfigurationException +	 */ +	public static void startSTORKAuthentication( +			HttpServletRequest req, +			HttpServletResponse resp,  +			String ccc, +			String oaURL, +			String target, +			String targetFriendlyName, +			String authURL, +			String sourceID) throws MOAIDException, AuthenticationException, WrongParametersException, ConfigurationException { +		 +		//read configuration paramters of OA +		OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL); +		if (oaParam == null) +				throw new AuthenticationException("auth.00", new Object[] { oaURL }); +		 +		if (!oaParam.getBusinessService()) { +			if (StringUtils.isEmpty(target)) +				throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.05"); +		} else {		 +			target = null;			 +		} +		 +		//create MOA session +		AuthenticationSession moaSession = newSession(); +		Logger.info("MOASession " + moaSession.getSessionID() + " angelegt"); +		moaSession.setTarget(target); +		moaSession.setTargetFriendlyName(targetFriendlyName); +		moaSession.setOAURLRequested(oaURL); +		moaSession.setPublicOAURLPrefix(oaParam.getPublicURLPrefix()); +		moaSession.setAuthURL(authURL);		 +		moaSession.setBusinessService(oaParam.getBusinessService()); +		moaSession.setDomainIdentifier(oaParam.getIdentityLinkDomainIdentifier()); +		if (sourceID != null) +			moaSession.setSourceID(sourceID); +		 +		//Start of STORK Processing		 +		STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig(); +		 +		CPEPS cpeps = storkConfig.getCPEPS(ccc); +    	 +		Logger.debug("Preparing to assemble STORK AuthnRequest witht the following values:");		 +    	String destination = cpeps.getPepsURL().toExternalForm();    	 +    	Logger.debug("C-PEPS URL: " + destination); +    	 +    	String acsURL = HTTPUtils.getBaseURL(req) + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; +    	Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL); +    	 +    	String providerName= oaParam.getFriendlyName(); +    	String issuerValue = HTTPUtils.getBaseURL(req); +    	Logger.debug("Issuer value: " + issuerValue); +    	 +    	QualityAuthenticationAssuranceLevel qaaLevel = STORKMessagesBuilder.buildQualityAuthenticationAssuranceLevel(oaParam.getQaaLevel().getValue()); +    	Logger.debug("QAALevel: " + qaaLevel.getValue()); +    	 +    	RequestedAttributes requestedAttributes; +    	 +    	requestedAttributes = oaParam.getRequestedAttributes(); +		requestedAttributes.detach(); +    	List<RequestedAttribute> reqAttributeList = new ArrayList<RequestedAttribute>(); +    	List<RequestedAttribute> oaReqAttributeList = new ArrayList<RequestedAttribute>(oaParam.getRequestedAttributes().getRequestedAttributes()); +    	//check if country specific attributes must be additionally requested +    	if (!cpeps.getCountrySpecificRequestedAttributes().isEmpty()) { +    		//add country specific attributes to be requested (Hierarchy: default oa attributes > country specific attributes > oa specific attributes +    		Logger.debug("We have addtional country specific attributes to be requested from the C-PEPS of country: " + ccc); +    		Logger.debug("The following attributes are requested for this specific country:"); +    		List<RequestedAttribute> countrySpecificReqAttributeList = new ArrayList<RequestedAttribute>(cpeps.getCountrySpecificRequestedAttributes()); +    		for (RequestedAttribute csReqAttr : countrySpecificReqAttributeList) { +    			csReqAttr.detach(); +    			if (!STORKConstants.DEFAULT_STORK_REQUESTED_ATTRIBUTE_SET.contains(csReqAttr.getName())) { +    				//this country specific attribute does not override default attribute +	    			if (SAMLUtil.containsAttribute(oaReqAttributeList, csReqAttr.getName())) { +	    				//the same attribute is requested for OA, applying hierachy        			 +	        			//remove oa attribute +	        			oaReqAttributeList.remove(SAMLUtil.getAttribute(oaReqAttributeList, csReqAttr.getName())); +	        			//add country specific attribute instead        		 +	        			Logger.debug("Requested Attribute (" + csReqAttr.getName() + ") is also requested by OA but we use Country Specific value instead");	        			 +	        		} +	    			oaReqAttributeList.add(csReqAttr); +	    			Logger.debug("Country specific requested attribute: " + csReqAttr.getName() + ", isRequired: " + csReqAttr.isRequired()); +    			} else { +    				Logger.debug("Country specific requested attribute: " + csReqAttr.getName() + ", isRequired: " + csReqAttr.isRequired() + " tries to overwrite default requested and required attributes, hence we skip it."); +    			}    			   +    			 +    		}    		    		 +    		reqAttributeList.addAll(oaReqAttributeList);    		 +    	} else { +    		//no country specific requested attributes +    		reqAttributeList.addAll(oaReqAttributeList); +    	} +    	 +    	reqAttributeList = (List<RequestedAttribute>) SAMLUtil.releaseDOM(reqAttributeList); +		requestedAttributes = STORKMessagesBuilder.buildRequestedAttributes(reqAttributeList); +		 +		if (Logger.isDebugEnabled()) { +			Logger.debug("The following attributes are requested for this OA:"); +			for (RequestedAttribute logReqAttr : reqAttributeList) { +				Logger.debug("OA specific requested attribute: " + logReqAttr.getName() + ", isRequired: " + logReqAttr.isRequired()); +				 +			} +		} +    	 +    	String spSector = StringUtils.isEmpty(target) ? "Business" : target; +    	String spInstitution = StringUtils.isEmpty(oaParam.getFriendlyName()) ? "UNKNOWN" : oaParam.getFriendlyName(); +    	String spApplication = spInstitution; +    	String spCountry = "AT"; +    	 +    	String textToBeSigned =  +    		CreateXMLSignatureRequestBuilder.buildForeignIDTextToBeSigned("wie im  Signaturzertifikat (as in my signature certificate)", oaParam, moaSession); +    	 +    	//generate AuthnRquest    	 +    	STORKAuthnRequest storkAuthnRequest = STORKAuthnRequestProcessor.generateSTORKAuthnRequest( +    			destination,  +    			acsURL,  +    			providerName,  +    			issuerValue,  +    			qaaLevel,  +    			requestedAttributes,  +    			spSector,  +    			spInstitution,  +    			spApplication,  +    			spCountry, +    			textToBeSigned, +    			"application/xhtml+xml"); +    			    	 +    	Logger.debug("STORK AuthnRequest succesfully assembled."); +    	 +    	//sign AuthnRequest +    	String keyStorePath = storkConfig.getSignatureCreationParameter().getKeyStorePath(); +    	String keyStorePassword = storkConfig.getSignatureCreationParameter().getKeyStorePassword(); +    	String keyName = storkConfig.getSignatureCreationParameter().getKeyName(); +    	String keyPassword = storkConfig.getSignatureCreationParameter().getKeyPassword(); +    	 +    	Logger.debug("Starting signing process of STORK AuthnRequest."); +    	Logger.trace("Using the following Keystore and Key for that:"); +    	Logger.trace("KeyStore: " + keyStorePath); +    	Logger.trace("KeyName: " + keyName); +    	 +    	try { +			storkAuthnRequest = STORKAuthnRequestProcessor.signSTORKAuthnRequest(storkAuthnRequest, keyStorePath, keyStorePassword, keyName, keyPassword); +		} catch (SAMLException e) { +			Logger.error("Could not sign STORK SAML AuthnRequest.", e); +			throw new MOAIDException("stork.00", null); +		} +    	 +		Logger.info("STORK AuthnRequest successfully signed!"); +		 +    	//validate AuthnRequest +		try { +			STORKAuthnRequestProcessor.validateSTORKAuthnRequest(storkAuthnRequest); +		} catch (SAMLValidationException e) { +			Logger.error("STORK SAML AuthnRequest not valid.", e); +			throw new MOAIDException("stork.01", null); +		}	 +		 +		Logger.debug("STORK AuthnRequest successfully internally validated."); +		 +		//send +		moaSession.setStorkAuthnRequest(storkAuthnRequest); +		HttpSession httpSession = req.getSession(); +		httpSession.setAttribute("MOA-Session-ID", moaSession.getSessionID()); +		 +		Logger.debug("Preparing to send STORK AuthnRequest."); +		 +		try { +			STORKAuthnRequestProcessor.sendSTORKAuthnRequest(req, resp, storkAuthnRequest); +		} catch (Exception e) { +			Logger.error("Error sending STORK SAML AuthnRequest.", e); +			httpSession.invalidate(); +			throw new MOAIDException("stork.02", new Object[] { destination }); +		} +		 +		Logger.info("STORK AuthnRequest successfully sent to: " + storkAuthnRequest.getDestination()); +		Logger.debug("STORKAuthnRequest sent (pretty print): "); +		Logger.debug(XMLHelper.prettyPrintXML(storkAuthnRequest.getDOM())); +		Logger.trace("STORKAuthnRequest sent (original): "); +		Logger.trace(XMLUtil.printXML(storkAuthnRequest.getDOM())); +		 +	} +	 +	/** +	 * Extracts an X509 Certificate out of an XML signagture element +	 * @param signedXML XML signature element +	 * @return X509Certificate +	 * @throws CertificateException +	 */ +	public static X509Certificate getCertificateFromXML(Element signedXML) throws CertificateException { +		 +		NodeList nList = signedXML.getElementsByTagNameNS(Constants.DSIG_NS_URI, "X509Certificate"); +		 +		String base64CertString = XMLUtil.getFirstTextValueFromNodeList(nList); +		 +		if (StringUtils.isEmpty(base64CertString)) {					 +			String msg = "XML does not contain a X509Certificate element."; +			Logger.error(msg); +			throw new CertificateException(msg); +		} +		 +		InputStream is = new ByteArrayInputStream(Base64.decode(base64CertString)); +		 +		CertificateFactory cf; +		X509Certificate cert = null; +		cf = CertificateFactory.getInstance("X.509"); +		cert = (X509Certificate)cf.generateCertificate(is); +	 +		return cert; +	} +	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java index f3be98ef0..7d5835f20 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthConstants.java @@ -47,6 +47,8 @@ public interface MOAIDAuthConstants {    public static final String PARAM_SOURCEID = "sourceID";      /** servlet parameter "BKUSelectionTemplate" */    public static final String PARAM_BKUTEMPLATE = "BKUSelectionTemplate"; +  /** servlet parameter "CCC (Citizen Country Code)" */ +  public static final String PARAM_CCC = "CCC";      /** servlet parameter "BKUSelectionTemplate" */    public static final String PARAM_INPUT_PROCESSOR_SIGN_TEMPLATE = "InputProcessorSignTemplate";    /** default BKU URL */ diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java index b6ba5871d..fa9789530 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/BPKBuilder.java @@ -56,7 +56,7 @@ public class BPKBuilder {           target.length() == 0))       {        throw new BuildException("builder.00",  -      		                     new Object[] {"BPK", "Unvollständige Parameterangaben: identificationValue=" +  +      		                     new Object[] {"BPK", "Unvollständige Parameterangaben: identificationValue=" +                                                identificationValue + ",target=" + target});      }      String basisbegriff = identificationValue + "+" + Constants.URN_PREFIX_CDID + "+" + target; @@ -86,7 +86,7 @@ public class BPKBuilder {           registerAndOrdNr.length() == 0))       {        throw new BuildException("builder.00",  -          new Object[] {"wbPK", "Unvollständige Parameterangaben: identificationValue=" +  +          new Object[] {"wbPK", "Unvollständige Parameterangaben: identificationValue=" +                           identificationValue + ",Register+Registernummer=" + registerAndOrdNr});      }      String basisbegriff = identificationValue + "+" + Constants.URN_PREFIX_WBPK + "+" + registerAndOrdNr; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java index 9c696f245..2da7db2b2 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/CreateXMLSignatureRequestBuilder.java @@ -129,7 +129,31 @@ public class CreateXMLSignatureRequestBuilder implements Constants {  	 * @return String representation of <code><CreateXMLSignatureRequest></code>  	 */  	public String buildForeignID(String subject, OAAuthParameter oaParam, AuthenticationSession session) { +			 +		String request = ""; +		request += "<sl:CreateXMLSignatureRequest xmlns:sl=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\">";  +		request += "<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>"; +		request += "<sl:DataObjectInfo Structure=\"enveloping\">";  +		request += "<sl:DataObject>"; +		request += "<sl:XMLContent>"; +		 +		request += buildForeignIDTextToBeSigned(subject, oaParam, session); +		request += "</sl:XMLContent>";		 +		request += "</sl:DataObject>"; +		request += "<sl:TransformsInfo>"; +		request += "<sl:FinalDataMetaInfo>"; +		request += "<sl:MimeType>application/xhtml+xml</sl:MimeType>"; +		request += "</sl:FinalDataMetaInfo>"; +		request += "</sl:TransformsInfo>"; +		request += "</sl:DataObjectInfo>"; +		request += "</sl:CreateXMLSignatureRequest>"; +				 +		return request; +	} +	 +	public static String buildForeignIDTextToBeSigned(String subject, OAAuthParameter oaParam, AuthenticationSession session) { +		  		String target = session.getTarget();		  		String sectorName = TargetToSectorNameMapper.getSectorNameViaTarget(target); @@ -137,14 +161,9 @@ public class CreateXMLSignatureRequestBuilder implements Constants {  		String date = DateTimeUtils.buildDate(cal);  		String time = DateTimeUtils.buildTime(cal); -		String request = ""; -		request += "<sl:CreateXMLSignatureRequest xmlns:sl=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\">";  -		request += "<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>"; -		request += "<sl:DataObjectInfo Structure=\"enveloping\">";  -		request += "<sl:DataObject>"; -		request += "<sl:XMLContent>"; -		 -		request += "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; +		String request = "";		 +		request += "<html xmlns=\"http://www.w3.org/1999/xhtml\">"; //application/xhtml+xml text/html +		//request += "<meta http-equiv=\"content-type\" content=\"application/xhtml+xml; charset=UTF-8\">";  		request += "<head>";  		request += "<title>Signatur der Anmeldedaten</title>";  		request += "<style type=\"text/css\" media=\"screen\">"; @@ -263,17 +282,9 @@ public class CreateXMLSignatureRequestBuilder implements Constants {  		request += "</body>";  		request += "</html>"; - -		request += "</sl:XMLContent>";		 -		request += "</sl:DataObject>"; -		request += "<sl:TransformsInfo>"; -		request += "<sl:FinalDataMetaInfo>"; -		request += "<sl:MimeType>application/xhtml+xml</sl:MimeType>"; -		request += "</sl:FinalDataMetaInfo>"; -		request += "</sl:TransformsInfo>"; -		request += "</sl:DataObjectInfo>"; -		request += "</sl:CreateXMLSignatureRequest>"; -				 +		  		return request; +	  	} +	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java index 5a18b720b..e861c62fa 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/data/AuthenticationSession.java @@ -24,6 +24,8 @@  package at.gv.egovernment.moa.id.auth.data; + +  import iaik.x509.X509Certificate;  import java.util.ArrayList; @@ -37,6 +39,7 @@ import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils;  import at.gv.egovernment.moa.id.data.AuthenticationData;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.Constants; +import eu.stork.mw.messages.saml.STORKAuthnRequest;  /**   * Session data to be stored between <code>AuthenticationServer</code> API calls. @@ -204,7 +207,10 @@ public class AuthenticationSession {     */    private String pushInfobox; -     +  /** +   * The STORK AuthRequest to be sent to the C-PEPS +   */ +  private STORKAuthnRequest storkAuthnRequest;    /**     * Constructor for AuthenticationSession. @@ -814,6 +820,23 @@ public class AuthenticationSession {    public void setMandateReferenceValue(String mandateReferenceValue) {  	  this.mandateReferenceValue = mandateReferenceValue;    } + +  /** +   * Gets the STORK SAML AuthnRequest +   * @return STORK SAML AuthnRequest +   */ +  public STORKAuthnRequest getStorkAuthnRequest() { +		return storkAuthnRequest; +	} +	 +  /** +   * Sets the STORK SAML AuthnRequest +   * @param storkAuthnRequest STORK SAML AuthnRequest +   */ +	public void setStorkAuthnRequest(STORKAuthnRequest storkAuthnRequest) { +		this.storkAuthnRequest = storkAuthnRequest; +	} +    } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java index a19618dc2..16041f8cb 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/AuthServlet.java @@ -46,10 +46,18 @@ import org.apache.commons.fileupload.FileUploadException;  import org.apache.commons.fileupload.disk.DiskFileItemFactory;  import org.apache.commons.fileupload.servlet.ServletFileUpload; +import at.gv.egovernment.moa.id.AuthenticationException; +import at.gv.egovernment.moa.id.auth.AuthenticationServer;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.WrongParametersException; +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder; +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.BoolUtils;  import at.gv.egovernment.moa.util.URLDecoder; +import at.gv.egovernment.moa.util.URLEncoder;  /**   * Base class for MOA-ID Auth Servlets, providing standard error handling @@ -65,7 +73,16 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	 *   	 */  	private static final long serialVersionUID = -6929905344382283738L; +	 +	 +	@Override +	protected void doGet(HttpServletRequest req, HttpServletResponse resp) +		throws ServletException, IOException { +		Logger.debug("GET " +  this.getServletName()); + +		this.setNoCachingHeadersInHttpRespone(req, resp); +}  /**     * Handles an error. <br>>     * <ul> @@ -260,4 +277,51 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	public void init(ServletConfig servletConfig) throws ServletException {  		super.init(servletConfig);  	} +	 +	/** +	 * Set response headers to avoid caching +	 * @param request HttpServletRequest +	 * @param response HttpServletResponse +	 */ +	protected void setNoCachingHeadersInHttpRespone(HttpServletRequest request, HttpServletResponse response) { +		response.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES); +		response.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA); +		response.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL); +		response.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE); +		 +	} +	 +	/** +	   * Adds a parameter to a URL. +	   * @param url the URL +	   * @param paramname parameter name +	   * @param paramvalue parameter value +	   * @return the URL with parameter added +	   */ +	  protected static String addURLParameter(String url, String paramname, String paramvalue) { +			String param = paramname + "=" + paramvalue; +	  	if (url.indexOf("?") < 0) +		  	return url + "?" + param; +	  	else +	  		return url + "&" + param; +	  } + +	  /** +	   * Checks if HTTP requests are allowed +	   * @param authURL requestURL +	   * @throws AuthenticationException if HTTP requests are not allowed +	   * @throws ConfigurationException +	   */ +	  protected void checkIfHTTPisAllowed(String authURL) throws AuthenticationException, ConfigurationException { +		// check if HTTP Connection may be allowed (through +			// FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY) +			String boolStr = AuthConfigurationProvider.getInstance().getGenericConfigurationParameter( +							AuthConfigurationProvider.FRONTEND_SERVLETS_ENABLE_HTTP_CONNECTION_PROPERTY); +			if ((!authURL.startsWith("https:")) +					&& (false == BoolUtils.valueOf(boolStr))) +				throw new AuthenticationException("auth.07", +						new Object[] { authURL + "*" }); +			 +	  } +  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java index 246a47699..bf7a0f714 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetForeignIDServlet.java @@ -24,19 +24,17 @@  package at.gv.egovernment.moa.id.auth.servlet;
 -import iaik.pki.PKIException; -  import java.io.IOException; -import java.security.GeneralSecurityException; +import java.security.cert.CertificateException;  import java.util.Map;  import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.transform.TransformerException;  import org.apache.commons.fileupload.FileUploadException;  import org.apache.commons.lang.StringEscapeUtils; -import org.w3c.dom.Document;  import org.w3c.dom.Element;  import at.gv.egovernment.moa.id.MOAIDException; @@ -50,15 +48,10 @@ import at.gv.egovernment.moa.id.auth.data.IdentityLink;  import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;  import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;  import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.CreateIdentityLinkResponse; -import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWClient;  import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWClientException; -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.ConnectionParameter; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;  import at.gv.egovernment.moa.id.util.ParamValidatorUtils; -import at.gv.egovernment.moa.id.util.SSLUtils;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.DOMUtils;  import at.gv.egovernment.moa.util.URLEncoder;  /**
 @@ -89,14 +82,7 @@ public class GetForeignIDServlet extends AuthServlet {    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException { 
 -		Logger.debug("GET GetForeignIDServlet");
 -
 -		resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,MOAIDAuthConstants.HEADER_VALUE_EXPIRES);
 -		resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA,MOAIDAuthConstants.HEADER_VALUE_PRAGMA);
 -		resp.setHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL);
 -		resp.addHeader(MOAIDAuthConstants.HEADER_CACHE_CONTROL,MOAIDAuthConstants.HEADER_VALUE_CACHE_CONTROL_IE);
 -
 -		
 +		super.doGet(req, resp);		
    }
    /**
 @@ -160,10 +146,17 @@ public class GetForeignIDServlet extends AuthServlet {  	    	CreateXMLSignatureResponse csresp =
  	    	      new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureResponse).parseResponseDsig();
 -	    	Element signature = csresp.getDsigSignature();
 +	    	Element signature = csresp.getDsigSignature(); +	    	 +	    	try { +				session.setSignerCertificate(AuthenticationServer.getCertificateFromXML(signature)); +			} catch (CertificateException e) { +				Logger.error("Could not extract certificate from CreateXMLSignatureResponse"); +				throw new MOAIDException("auth.14", null); +			}
  	    	// make SZR request to the identity link
 -	    	CreateIdentityLinkResponse response = getIdentityLink(signature);
 +	    	CreateIdentityLinkResponse response = AuthenticationServer.getInstance().getIdentityLink(null, null, null, null, signature);
  	    	if (response.isError()) {	    		
 @@ -173,28 +166,30 @@ public class GetForeignIDServlet extends AuthServlet {  	    		Element samlAssertion = response.getAssertion();
 -//	    		try {
 -//					System.out.println(DOMUtils.serializeNode(samlAssertion));
 -//				} catch (TransformerException e) {
 -//					e.printStackTrace();
 -//				}
 +	    		try {
 +					System.out.println("PB: " + DOMUtils.serializeNode(samlAssertion));
 +				} catch (TransformerException e) {
 +					e.printStackTrace();
 +				}
  		    	IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(samlAssertion);
  		    	IdentityLink identitylink = ilParser.parseIdentityLink();
  		    	session.setIdentityLink(identitylink);
  		    	String samlArtifactBase64 = 
 -		    		AuthenticationServer.getInstance().getForeignAuthenticationData(sessionID);
 -		    	if (!samlArtifactBase64.equals("Redirect to Input Processor")) {
 -		    		redirectURL = session.getOAURLRequested();
 -		    		if (!session.getBusinessService()) {
 -		    			redirectURL = addURLParameter(redirectURL, PARAM_TARGET, URLEncoder.encode(session.getTarget(), "UTF-8"));
 -		    		}
 -		    		redirectURL = addURLParameter(redirectURL, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8"));
 -		    		redirectURL = resp.encodeRedirectURL(redirectURL);
 -		    	} else {
 -		    		redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(), AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, session.getSessionID());
 +		    		AuthenticationServer.getInstance().getForeignAuthenticationData(sessionID); +		    	if (!samlArtifactBase64.equals("Redirect to Input Processor")) { +		    		redirectURL = session.getOAURLRequested(); +		    		if (!session.getBusinessService()) { +		    			redirectURL = addURLParameter(redirectURL, PARAM_TARGET, URLEncoder.encode(session.getTarget(), "UTF-8")); +		    		} +		    		redirectURL = addURLParameter(redirectURL, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8")); +		    		redirectURL = resp.encodeRedirectURL(redirectURL); +		    		 +		    	} else { +		    		redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(), AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, session.getSessionID());  		    	}
 +		    	
  		    	resp.setContentType("text/html");
  		    	resp.setStatus(302);
  		    	resp.addHeader("Location", redirectURL);
 @@ -210,84 +205,12 @@ public class GetForeignIDServlet extends AuthServlet {  		}
    }
 -  /**
 -   * Adds a parameter to a URL.
 -   * @param url the URL
 -   * @param paramname parameter name
 -   * @param paramvalue parameter value
 -   * @return the URL with parameter added
 -   */
 -  private static String addURLParameter(String url, String paramname, String paramvalue) {
 -		String param = paramname + "=" + paramvalue;
 -  	if (url.indexOf("?") < 0)
 -	  	return url + "?" + param;
 -  	else
 -  		return url + "&" + param;
 -  }
 -  /**
 -   * Does the request to the SZR-GW
 -   * @param signature XMLDSIG signature
 -   * @return Identity link assertion
 - * @throws SZRGWClientException 
 -   */
 -     private CreateIdentityLinkResponse getIdentityLink(Element signature) throws SZRGWClientException {
 -
 -	    SZRGWClient client = new SZRGWClient();
 -	 
 -	    try {
 -	    	AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
 -	    	ConnectionParameter connectionParameters = authConf.getForeignIDConnectionParameter();
 -
 -	    	client.setAddress(connectionParameters.getUrl());
 -	    	if (connectionParameters.getUrl().toLowerCase().startsWith("https:")) {
 -	    		Logger.debug("Initialisiere SSL Verbindung");
 -	    		try {
 -	    			client.setSSLSocketFactory(SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters));
 -	    		} catch (IOException e) {
 -	    			Logger.error("Could not initialize SSL Factory", e);
 -	    			throw new SZRGWClientException("Could not initialize SSL Factory");
 -	    		} catch (GeneralSecurityException e) {
 -	    			Logger.error("Could not initialize SSL Factory", e);
 -	    			throw new SZRGWClientException("Could not initialize SSL Factory");
 -	    		} catch (PKIException e) {
 -	    			Logger.error("Could not initialize SSL Factory", e);
 -	    			throw new SZRGWClientException("Could not initialize SSL Factory");
 -	    		} 
 -	    	}
 -	    	Logger.info("Starte Kommunikation mit dem Stammzahlenregister Gateway(" + connectionParameters.getUrl() + ")...");
 -	    }
 -	    catch (ConfigurationException e) {
 -	    	Logger.warn(e);
 -	    	Logger.warn(MOAIDMessageProvider.getInstance().getMessage("config.12", null ));
 -	    }
 -	    
 -	    // create request
 -	    CreateIdentityLinkResponse response = null;
 -	    Element request = null;
 -	    try {
 -	    	Document doc = client.buildGetIdentityLinkRequest(null, null, null, null, signature);
 -	    	request = doc.getDocumentElement();
 -	    	
 -	    	// send request
 -	    	response = client.createIdentityLinkResponse(request);
 -	    } catch (SZRGWClientException e) {
 -	    	// 	give him a second try - Nach dem Starten des Tomcat wird beim ersten Mal das Client-Zertifikat offenbar vom HTTPClient nicht mitgeschickt.
 -	    	try {
 -	    		response = client.createIdentityLinkResponse(request);
 -	    	} 
 -	    	catch (SZRGWClientException e1) {
 -	    		throw new SZRGWClientException(e1);
 -	    	}
 -	    }
 -        
 -	    
 -	    return response;
 -	
 -  }
 +  
 +  
    /**
 -   * Builds the szrgw:GetIdentityLinkRequest für the SZR-GW
 +   * Builds the szrgw:GetIdentityLinkRequest f�r the SZR-GW
     * @param givenname
     * @param familyname
     * @param birthday
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java index 9d26ded8a..74b2f80b9 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GetMISSessionIDServlet.java @@ -206,20 +206,6 @@ public class GetMISSessionIDServlet extends AuthServlet {  		} 
    } -  /** -   * Adds a parameter to a URL. -   * @param url the URL -   * @param paramname parameter name -   * @param paramvalue parameter value -   * @return the URL with parameter added -   */ -  private static String addURLParameter(String url, String paramname, String paramvalue) { -		String param = paramname + "=" + paramvalue; -  	if (url.indexOf("?") < 0) -	  	return url + "?" + param; -  	else -  		return url + "&" + param; -  }
 -  
 +   
   }
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java new file mode 100644 index 000000000..4ec894d47 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorServlet.java @@ -0,0 +1,227 @@ +package at.gv.egovernment.moa.id.auth.servlet;
 +
 +import java.io.IOException;
 +import java.util.List;
 +
 +import javax.servlet.ServletException;
 +import javax.servlet.http.HttpServlet;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.servlet.http.HttpSession;
 +
 +import org.opensaml.saml2.core.Assertion;
 +import org.opensaml.saml2.core.StatusCode;
 +import org.opensaml.xml.util.XMLHelper;
 +import org.w3c.dom.Element;
 +
 +import at.gv.egovernment.moa.id.AuthenticationException;
 +import at.gv.egovernment.moa.id.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute;
 +import at.gv.egovernment.moa.id.auth.data.IdentityLink;
 +import at.gv.egovernment.moa.id.auth.stork.STORKException;
 +import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
 +import at.gv.egovernment.moa.id.util.HTTPUtils;
 +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.URLEncoder;
 +import eu.stork.mw.messages.saml.STORKAuthnRequest;
 +import eu.stork.mw.messages.saml.STORKResponse;
 +import eu.stork.vidp.messages.util.XMLUtil;
 +
 +/**
 + * Endpoint for receiving STORK response messages
 + */
 +public class PEPSConnectorServlet extends AuthServlet {
 +	private static final long serialVersionUID = 1L;
 +	
 +	public static final String PEPSCONNECTOR_SERVLET_URL_PATTERN = "/PEPSConnector";
 +
 +    
 +	/**
 +	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
 +	 */
 +	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 +		super.doGet(request, response);
 +	}
 +
 +	/**
 +	 * Handles the reception of a STORK response message
 +	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
 +	 */
 +	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 +		
 +		try {
 +			
 +			Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
 +			Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
 +						
 +			super.setNoCachingHeadersInHttpRespone(request, response);
 +			Logger.trace("No Caching headers set for HTTP response");
 +			
 +			//check if https or only http
 +			super.checkIfHTTPisAllowed(request.getRequestURL().toString());
 +			
 +			Logger.debug("Trying to find MOA Session-ID");			
 +			HttpSession httpSession = request.getSession();
 +			String moaSessionID = (String) httpSession.getAttribute("MOA-Session-ID");
 +			
 +			if (StringUtils.isEmpty(moaSessionID)) {
 +				//No authentication session has been started before
 +				Logger.error("MOA-SessionID was not found, no previous AuthnRequest had been started");
 +				throw new AuthenticationException("auth.02", new Object[] { moaSessionID });
 +			} else {
 +				//We know user and MOA takes over session handling, invalidate HttpSession
 +				httpSession.invalidate();
 +			}
 +			
 +			Logger.info("Found MOA sessionID: " + moaSessionID);
 +			
 +			Logger.debug("Beginning to extract SAMLResponse out of HTTP Request");
 +			
 +			//extract STORK Response from HTTP Request
 +			STORKResponse storkResponse = null;
 +			try {
 +				storkResponse = STORKResponseProcessor.receiveSTORKRepsonse(request, response);
 +			} catch (STORKException e) {
 +				Logger.error("Unable to retrieve STORK Response", e);
 +				throw new MOAIDException("stork.04", null);
 +			}
 +			
 +			Logger.info("STORK SAML Response message succesfully extracted");
 +			Logger.debug("STORK response (pretty print): ");
 +			Logger.debug(XMLHelper.prettyPrintXML(storkResponse.getDOM()));
 +			Logger.trace("STORK response (original): ");
 +			Logger.trace(XMLUtil.printXML(storkResponse.getDOM()));
 +			
 +			Logger.debug("Starting validation of SAML response");
 +			//verify SAML response
 +			try {
 +				STORKResponseProcessor.verifySTORKResponse(storkResponse);
 +			} catch (STORKException e) {
 +				Logger.error("Failed to verify STORK SAML Response", e);
 +				throw new MOAIDException("stork.05", null);
 +			}
 +			
 +			Logger.info("SAML response succesfully verified!");
 +			
 +			String statusCodeValue = storkResponse.getStatus().getStatusCode().getValue();
 +			
 +			if (!statusCodeValue.equals(StatusCode.SUCCESS_URI)) {
 +				Logger.error("Received ErrorResponse from PEPS: " + statusCodeValue);
 +				throw new MOAIDException("stork.06", new Object[] { statusCodeValue });
 +			}
 +			
 +			Logger.info("Got SAML response with authentication success message.");
 +			
 +			//check if authentication request was created before
 +			AuthenticationSession moaSession = AuthenticationServer.getSession(moaSessionID);
 +			
 +			Logger.debug("MOA session is still valid");
 +			
 +			STORKAuthnRequest storkAuthnRequest = moaSession.getStorkAuthnRequest();
 +			
 +			if (storkAuthnRequest == null) {
 +				Logger.error("Could not find any preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
 +				throw new MOAIDException("stork.07", null);
 +			}
 +						
 +			Logger.debug("Found a preceeding STORK AuthnRequest to this MOA session: " + moaSessionID);
 +			
 +			Logger.debug("Starting validation of SAML assertion");
 +			//verify SAML assertion
 +			Assertion storkAssertion = storkResponse.getAssertions().get(0);
 +			try {
 +				STORKResponseProcessor.verifySTORKAssertion(
 +						storkAssertion, //assertion 
 +						request.getRemoteAddr(), //IP address of user 
 +						storkAuthnRequest.getID(), //ID of STORK AuthnRequest 
 +						request.getRequestURL().toString(), //destination
 +						HTTPUtils.getBaseURL(request), //audience
 +						storkAuthnRequest.getRequestedAttributes()); //Requested Attributes
 +			} catch (STORKException e) {
 +				Logger.error("Failed to verify STORK SAML Assertion", e);
 +				throw new MOAIDException("stork.08", null);
 +			}
 +			
 +			Logger.info("SAML assertion succesfully verified!");
 +			
 +			Logger.debug("Starting extraction of signedDoc attribute");			
 +			//extract signed doc element and citizen signature
 +			Element citizenSignature = null;
 +			try {
 +			
 +				citizenSignature = STORKResponseProcessor.extractCitizenSignature(storkAssertion);				
 +				moaSession.setAuthBlock(DOMUtils.serializeNode(citizenSignature));
 +				moaSession.setSignerCertificate(AuthenticationServer.getCertificateFromXML(citizenSignature));
 +				
 +			} catch (Exception e) {
 +				Logger.error("Could not extract citizen signature from C-PEPS", e);
 +				throw new MOAIDException("stork.09", null);
 +			}
 +			Logger.debug("Foregin Citizen signature successfully extracted from STORK Assertion (signedDoc)");
 +			Logger.debug("Citizen signature will be verified by SZR Gateway!");
 +			
 +			Logger.debug("Starting connecting SZR Gateway");
 +			//contact SZR Gateway
 +			IdentityLink identityLink = null;
 +			try {
 +				identityLink = STORKResponseProcessor.connectToSZRGateway(citizenSignature, storkAssertion.getAttributeStatements().get(0).getAttributes());
 +			} catch (STORKException e) {
 +				Logger.error("Error connecting SZR Gateway", e);
 +				throw new MOAIDException("stork.10", null);
 +			}
 +			Logger.debug("SZR communication was successfull");
 +			
 +			if (identityLink == null) {
 +				Logger.error("SZR Gateway did not return an identity link.");
 +				throw new MOAIDException("stork.10", null);	
 +			}
 +			Logger.info("Received Identity Link from SZR Gateway");
 +			moaSession.setIdentityLink(identityLink);
 +			
 +			Logger.debug("Adding addtional STORK attributes to MOA assertion");
 +			//add other stork attributes to MOA assertion
 +			List<ExtendedSAMLAttribute> moaExtendedSAMLAttibutes = STORKResponseProcessor.addAdditionalSTORKAttributes(storkAssertion.getAttributeStatements().get(0).getAttributes());
 +			moaSession.setExtendedSAMLAttributesOA(moaExtendedSAMLAttibutes);
 +			
 +			//We don't have BKUURL, setting from null to "Not applicable"
 +			moaSession.setBkuURL("Not applicable (STORK Authentication)");
 +						
 +			Logger.debug("Starting to assemble MOA assertion");
 +			//produce MOA-Assertion and artifact			
 +			String samlArtifactBase64 = 
 +	    		AuthenticationServer.getInstance().getForeignAuthenticationData(moaSessionID);
 +			Logger.info("MOA assertion assembled and SAML Artifact generated.");
 +			
 +			//redirect
 +			String redirectURL = null;
 +	    	if (!samlArtifactBase64.equals("Redirect to Input Processor")) {
 +	    		redirectURL = moaSession.getOAURLRequested();
 +	    		if (!moaSession.getBusinessService()) {
 +	    			redirectURL = addURLParameter(redirectURL, PARAM_TARGET, URLEncoder.encode(moaSession.getTarget(), "UTF-8"));
 +	    		}
 +	    		redirectURL = addURLParameter(redirectURL, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8"));
 +	    		redirectURL = response.encodeRedirectURL(redirectURL);
 +	    	} else {
 +	    		redirectURL = new DataURLBuilder().buildDataURL(moaSession.getAuthURL(), AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, moaSession.getSessionID());
 +	    	}
 +	    	response.setContentType("text/html");
 +	    	response.setStatus(302);
 +	    	response.addHeader("Location", redirectURL);
 +	    	Logger.info("REDIRECT TO: " + redirectURL);
 +			
 +			
 +			
 +		} catch (AuthenticationException e) {
 +			handleError(null, e, request, response);
 +		} catch (MOAIDException e) {
 +			handleError(null, e, request, response);
 +		}
 +		
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java index 355e85ce5..012ed4c14 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/StartAuthenticationServlet.java @@ -26,6 +26,7 @@ package at.gv.egovernment.moa.id.auth.servlet;  import java.io.IOException;  import java.io.PrintWriter; +import java.util.List;  import javax.servlet.ServletConfig;  import javax.servlet.ServletException; @@ -33,18 +34,29 @@ import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang.StringEscapeUtils; +import org.opensaml.saml2.metadata.RequestedAttribute;  import at.gv.egovernment.moa.id.AuthenticationException;  import at.gv.egovernment.moa.id.MOAIDException;  import at.gv.egovernment.moa.id.auth.AuthenticationServer;  import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer;  import at.gv.egovernment.moa.id.auth.WrongParametersException; +import at.gv.egovernment.moa.id.auth.stork.STORKAuthnRequestProcessor;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; +import at.gv.egovernment.moa.id.config.stork.CPEPS; +import at.gv.egovernment.moa.id.config.stork.STORKConfig; +import at.gv.egovernment.moa.id.util.HTTPUtils;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;  import at.gv.egovernment.moa.id.util.ParamValidatorUtils;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.StringUtils; +import eu.stork.mw.messages.saml.STORKAuthnRequest; +import eu.stork.vidp.messages.builder.STORKMessagesBuilder; +import eu.stork.vidp.messages.exception.SAMLException; +import eu.stork.vidp.messages.exception.SAMLValidationException; +import eu.stork.vidp.messages.stork.QualityAuthenticationAssuranceLevel; +import eu.stork.vidp.messages.stork.RequestedAttributes;  /**   * Servlet requested for starting a MOA ID authentication session. @@ -77,7 +89,7 @@ public class StartAuthenticationServlet extends AuthServlet {    protected void doGet(HttpServletRequest req, HttpServletResponse resp)      throws ServletException, IOException { -		Logger.debug("GET StartAuthentication"); +	Logger.debug("GET StartAuthentication");      String authURL = req.getScheme() + "://" + req.getServerName();      if ((req.getScheme().equalsIgnoreCase("https") && req.getServerPort()!=443) || (req.getScheme().equalsIgnoreCase("http") && req.getServerPort()!=80)) {         authURL = authURL.concat(":" + req.getServerPort()); @@ -91,6 +103,7 @@ public class StartAuthenticationServlet extends AuthServlet {      String templateURL = req.getParameter(PARAM_TEMPLATE);      String sessionID = req.getParameter(PARAM_SESSIONID);      String useMandate = req.getParameter(PARAM_USEMANDATE); +    String ccc = req.getParameter(PARAM_CCC);      // escape parameter strings      target = StringEscapeUtils.escapeHtml(target); @@ -100,11 +113,9 @@ public class StartAuthenticationServlet extends AuthServlet {      templateURL = StringEscapeUtils.escapeHtml(templateURL);      sessionID = StringEscapeUtils.escapeHtml(sessionID);      useMandate = StringEscapeUtils.escapeHtml(useMandate); +    ccc = StringEscapeUtils.escapeHtml(ccc); -    resp.setHeader(HEADER_EXPIRES,HEADER_VALUE_EXPIRES); -    resp.setHeader(HEADER_PRAGMA,HEADER_VALUE_PRAGMA); -    resp.setHeader(HEADER_CACHE_CONTROL,HEADER_VALUE_CACHE_CONTROL); -    resp.addHeader(HEADER_CACHE_CONTROL,HEADER_VALUE_CACHE_CONTROL_IE); +    setNoCachingHeadersInHttpRespone(req, resp);      	try { @@ -121,35 +132,56 @@ public class StartAuthenticationServlet extends AuthServlet {  	             throw new WrongParametersException("StartAuthentication", PARAM_USEMANDATE, "auth.12");		      		    if (!ParamValidatorUtils.isValidSourceID(sourceID))  	             throw new WrongParametersException("StartAuthentication", PARAM_SOURCEID, "auth.12"); +		    if (!ParamValidatorUtils.isValidCCC(ccc)) +	             throw new WrongParametersException("StartAuthentication", PARAM_CCC, "auth.12"); +		    		     +		          		    OAAuthParameter oaParam =  		          AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(oaURL);  		        if (oaParam == null)  		          throw new AuthenticationException("auth.00", new Object[] { oaURL }); - +		      		    // get target and target friendly name from config  		    String targetConfig = oaParam.getTarget(); -		    String targetFriendlyNameConfig = oaParam.getTargetFriendlyName(); +			String targetFriendlyNameConfig = oaParam.getTargetFriendlyName(); +			 +			String targetFriendlyName = null; +			    			 +			if (StringUtils.isEmpty(targetConfig)) { +			    	// no target attribut is given in OA config +			    	// target is used from request +			    	// check parameter +			 	if (!ParamValidatorUtils.isValidTarget(target)) +			   		throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.12");			    			    +			} else { +			    	// use target from config			    	 +			    	target = targetConfig; +			    	targetFriendlyName = targetFriendlyNameConfig; +			}		     + +		    STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig(); -		    String getIdentityLinkForm = null; -		    if (StringUtils.isEmpty(targetConfig)) { -		    	// no target attribut is given in OA config -		    	// target is used from request -		    	// check parameter -		    	if (!ParamValidatorUtils.isValidTarget(target)) -		    		throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.12"); +		    Logger.info("Starting authentication for a citizen of country: " + (StringUtils.isEmpty(ccc) ? "AT" : ccc));     +		    // STORK or normal authentication +		    if (storkConfig.isSTORKAuthentication(ccc)) { +		    	//STORK authentication +		    	Logger.trace("Found C-PEPS configuration for citizen of country: " + ccc); +		    	Logger.debug("Starting STORK authentication"); -		    	getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(authURL, target, null, oaURL, templateURL, bkuURL, useMandate, sessionID, req.getScheme(), sourceID); -		    } -		    else { -		    	// use target from config			    	 -		    	getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(authURL, targetConfig, targetFriendlyNameConfig, oaURL, templateURL, bkuURL, useMandate, sessionID, req.getScheme(), sourceID); +		    	AuthenticationServer.startSTORKAuthentication(req, resp, ccc, oaURL, target, targetFriendlyName, authURL, sourceID);							 +		    	 +		    } else { +		    	//normal MOA-ID authentication +		    	Logger.debug("Starting normal MOA-ID authentication"); +			    			    	    	 +		    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(authURL, target, targetFriendlyName, oaURL, templateURL, bkuURL, useMandate, sessionID, req.getScheme(), sourceID);	    +	 +				resp.setContentType("text/html;charset=UTF-8"); +				PrintWriter out = new PrintWriter(resp.getOutputStream()); +				out.print(getIdentityLinkForm); +				out.flush();  		    } - -			resp.setContentType("text/html;charset=UTF-8"); -			PrintWriter out = new PrintWriter(resp.getOutputStream()); -			out.print(getIdentityLinkForm); -			out.flush();  			Logger.debug("Finished GET StartAuthentication");  		} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java index f15f839d7..fbf700365 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyAuthenticationBlockServlet.java @@ -326,19 +326,6 @@ public class VerifyAuthenticationBlockServlet extends AuthServlet {  //			handleError(null, e, req, resp);  //		}   //  } -  /** -   * Adds a parameter to a URL. -   * @param url the URL -   * @param paramname parameter name -   * @param paramvalue parameter value -   * @return the URL with parameter added -   */ -  private static String addURLParameter(String url, String paramname, String paramvalue) { -		String param = paramname + "=" + paramvalue; -  	if (url.indexOf("?") < 0) -	  	return url + "?" + param; -  	else -  		return url + "&" + param; -  } +    } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/AssertionVerifier.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/AssertionVerifier.java new file mode 100644 index 000000000..7ffe59fd9 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/AssertionVerifier.java @@ -0,0 +1,56 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import java.util.List; + +import org.opensaml.saml2.core.Assertion; +import org.opensaml.saml2.metadata.RequestedAttribute; +
 +/**
 + * Interface to be implemented for verifying SAML assertions + *  + * @author bzwattendorfer
 + *
 + */
 +public interface AssertionVerifier {
 +	 +	/** +	 * Verifies a given assertion +	 * @param assertion SAML assertion +	 * @param reqIPAddress IP address of the client +	 * @param authnRequestID ID of the corresponding authentication request for verification +	 * @param recipient recipient for verification  +	 * @param audience audience for verification +	 * @param reqAttrList RequestedAttribute list for verification +	 * @throws SecurityException +	 */
 +	public void verify(Assertion assertion, String reqIPAddress, String authnRequestID, String recipient, String audience, List<RequestedAttribute> reqAttrList) throws SecurityException;
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/CredentialProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/CredentialProvider.java new file mode 100644 index 000000000..b95ab6218 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/CredentialProvider.java @@ -0,0 +1,50 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import org.opensaml.xml.security.credential.Credential;
 +
 +import eu.stork.vidp.messages.exception.SAMLException;
 +
 +/**
 + * Interface supporting different kinds of Credentials + *  + * @author bzwattendorfer
 + *
 + */
 +public interface CredentialProvider {
 +	 +	/** +	 * Gets appropriate credentials +	 * @return Credential object +	 * @throws SAMLException +	 */
 +	public Credential getCredential() throws SAMLException;
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/KeyStoreCredentialProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/KeyStoreCredentialProvider.java new file mode 100644 index 000000000..467210b4d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/KeyStoreCredentialProvider.java @@ -0,0 +1,126 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +import org.opensaml.xml.security.credential.Credential; +import org.opensaml.xml.security.x509.BasicX509Credential; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.util.KeyStoreUtils; +import at.gv.egovernment.moa.util.StringUtils; +import eu.stork.vidp.messages.exception.SAMLException; +
 +/** + * Provides credentials from a KeyStore + * @author bzwattendorfer + * + */
 +public class KeyStoreCredentialProvider implements CredentialProvider {
 +	
 +	private final static Logger log = LoggerFactory.getLogger(KeyStoreCredentialProvider.class);
 +	 +	/** KeyStore Path */
 +	private String keyStorePath;
 +	 +	/** KeyStore Password */
 +	private String keyStorePassword;
 +	 +	/** Specific Key Name as Credential */
 +	private String keyName;
 +	 +	/** Key password */
 +	private String keyPassword;
 +	
 +	/** +	 * Creates a KeyStoreCredentialProvider object +	 * @param keyStorePath KeyStore Path +	 * @param keyStorePassword KeyStore Password +	 * @param keyName KeyName of the key to be retrieved +	 * @param keyPassword Password for the Key +	 */
 +	public KeyStoreCredentialProvider(String keyStorePath,
 +			String keyStorePassword, String keyName, String keyPassword) {
 +		super();
 +		this.keyStorePath = keyStorePath;
 +		this.keyStorePassword = keyStorePassword;
 +		this.keyName = keyName;
 +		this.keyPassword = keyPassword;
 +	}
 +
 + +	/** +	 * Gets the credential object from the KeyStore +	 */
 +	public Credential getCredential() throws SAMLException {
 +		log.trace("Retrieving credentials for signing SAML Response.");
 +		
 +		if (StringUtils.isEmpty(this.keyStorePath))
 +			throw new SAMLException("No keyStorePath specified");
 +		 +		//KeyStorePassword optional
 +		//if (StringUtils.isEmpty(this.keyStorePassword))
 +		//	throw new SAMLException("No keyStorePassword specified");
 +		
 +		if (StringUtils.isEmpty(this.keyName))
 +			throw new SAMLException("No keyName specified");
 +		 +		//KeyStorePassword optional
 +		//if (StringUtils.isEmpty(this.keyPassword))
 +		//	throw new SAMLException("No keyPassword specified");
 +		
 +		KeyStore ks;
 +		try {
 +			ks = KeyStoreUtils.loadKeyStore(this.keyStorePath, this.keyStorePassword);					
 +		} catch (Exception e) {
 +			log.error("Failed to load keystore information", e);
 +			throw new SAMLException(e);
 +		}
 +		
 +		//return new KeyStoreX509CredentialAdapter(ks, keyName, keyPwd.toCharArray());
 +		BasicX509Credential credential = null;
 +		try {
 +			java.security.cert.X509Certificate certificate = (X509Certificate) ks.getCertificate(this.keyName);
 +			PrivateKey privateKey = (PrivateKey) ks.getKey(this.keyName, this.keyPassword.toCharArray());
 +			credential = new BasicX509Credential();
 +			credential.setEntityCertificate(certificate);			
 +			credential.setPrivateKey(privateKey);
 +						
 +		} catch (Exception e) {
 +			log.error("Error retrieving signing credentials.", e);
 +			throw new SAMLException(e);
 +		}
 +						
 +		return credential;
 +		
 +	} +	 +		 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/PEPSConnectorAssertionVerifier.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/PEPSConnectorAssertionVerifier.java new file mode 100644 index 000000000..3048ccbee --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/PEPSConnectorAssertionVerifier.java @@ -0,0 +1,241 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import java.util.List; + +import org.joda.time.DateTime; +import org.opensaml.saml2.core.Assertion; +import org.opensaml.saml2.core.Attribute; +import org.opensaml.saml2.core.Audience; +import org.opensaml.saml2.core.AudienceRestriction; +import org.opensaml.saml2.core.Conditions; +import org.opensaml.saml2.core.SubjectConfirmation; +import org.opensaml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml2.metadata.RequestedAttribute; + +import at.gv.egovernment.moa.logging.Logger; +import eu.stork.vidp.messages.saml.STORKAttribute; +import eu.stork.vidp.messages.util.SAMLUtil; +
 +/**
 + * Verifies the SAML assertion according to the STORK specification + * @author bzwattendorfer
 + *
 + */
 +public class PEPSConnectorAssertionVerifier implements AssertionVerifier {
 +			
 +	private static final int CLOCK_SKEW_MINUTES = 5; +	 +	private static final boolean IS_USERS_CLIENT_IP_ADDRESS_TO_VERIFY = false;
 +
 +	/* (non-Javadoc)
 +	 * @see eu.stork.mw.peps.connector.validation.AssertionVerifier#verifyAssertion(org.opensaml.saml2.core.Assertion, java.lang.String, java.lang.String, java.lang.String)
 +	 */
 +	public void verify(Assertion assertion, String reqIPAddress,
 +			String authnRequestID, String recipient, String audience, List<RequestedAttribute> reqAttrList) throws SecurityException {
 +
 +		//SAML assertion need not to be signed, skipping signature validation
 +		
 +		verifySubjectConfirmation(assertion, reqIPAddress, authnRequestID, recipient); +		 +		Logger.debug("SubjectConfirmationData successfully verified"); +		
 +		verifyConditions(assertion, audience);
 +		 +		Logger.debug("Conditions successfully verified"); +	}
 +	
 +	
 +	private void verifySubjectConfirmation(Assertion assertion, String reqAddress, String requestID, String recipient) throws SecurityException {		
 +		for (SubjectConfirmation sc : assertion.getSubject().getSubjectConfirmations()) {
 +			verifySubjectConfirmationData(sc.getSubjectConfirmationData(), reqAddress, requestID, recipient);
 +		}
 +				
 +	}
 +	
 +	private void verifySubjectConfirmationData(SubjectConfirmationData scData, String reqAddress, String requestID, String recipient) throws SecurityException {				
 +		//NotBefore not allowed in SSO profile
 +		verifyNotOnOrAfter(scData.getNotOnOrAfter()); +		 +		Logger.trace("NotOnOrAfter successfully verified");
 +		
 +		if(IS_USERS_CLIENT_IP_ADDRESS_TO_VERIFY) {
 +			verifyClientAddress(scData, reqAddress); +			Logger.trace("User's client IP address successfully verified.");
 +		} else {
 +			Logger.warn("User's client IP address will not be verified.");
 +		}
 +		
 +		verifyRecipient(scData, recipient); +		Logger.trace("Recipient successfully verified"); +		
 +		verifyInResponseTo(scData, requestID); +		Logger.trace("InResponseTo successfully verified");
 +				 
 +	}
 +	
 +	private void verifyNotBefore(DateTime notBefore) throws SecurityException {
 +		if (notBefore.minusMinutes(CLOCK_SKEW_MINUTES).isAfterNow()) {
 +			String msg = "Subject/Assertion not yet valid, Timestamp: ";
 +			Logger.error(msg + notBefore);
 +			throw new SecurityException(msg);
 +		}
 +		
 +		Logger.trace("Subject/Assertion already valid, notBefore: " + notBefore);
 +		
 +	}
 +	
 +	private void verifyNotOnOrAfter(DateTime notOnOrAfter) throws SecurityException {
 +		if (notOnOrAfter.plusMinutes(CLOCK_SKEW_MINUTES).isBeforeNow()) {
 +			String msg = "Subject/Assertion no longer valid.";
 +			Logger.error(msg);
 +			throw new SecurityException(msg);
 +		}
 +		
 +		Logger.trace("Subject/Assertion still valid, notOnOrAfter: " + notOnOrAfter);
 +	}
 +
 +	private void verifyClientAddress(SubjectConfirmationData scData, String reqAddress) throws SecurityException {
 +		if (!reqAddress.equals(scData.getAddress())) {
 +			String msg = "Response coming from wrong Client-Address";
 +			Logger.error("Response coming from wrong Client-Address " +  reqAddress + ", expected " + scData.getAddress());
 +			throw new SecurityException(msg);
 +		}
 +		
 +	}
 +	
 +	private void verifyInResponseTo(SubjectConfirmationData scData, String requestID) throws SecurityException {
 +		if (!scData.getInResponseTo().equals(requestID)) {
 +			String msg = "Assertion issued for wrong request";
 +			Logger.error(msg);
 +			throw new SecurityException(msg);
 +		}
 +	}
 +	
 +	private void verifyRecipient(SubjectConfirmationData scData, String reqRecipient) throws SecurityException {
 +		if (!scData.getRecipient().equals(reqRecipient)) {
 +			String msg = "Assertion intended for another recipient";
 +			Logger.error("Assertion intended for recipient " + scData.getRecipient() + "but expected " + reqRecipient);
 +			throw new SecurityException(msg);
 +		}
 +		
 +	}
 +	
 +	private void verifyAudience(AudienceRestriction audienceRestriction, String reqAudience) throws SecurityException {
 +		for (Audience audience : audienceRestriction.getAudiences()) {
 +			if (audience.getAudienceURI().equals(reqAudience))
 +				return;
 +		}
 +		String msg = "Assertion sent to wrong audience";
 +		Logger.error("Assertion intended for wrong audience, expected " + reqAudience);
 +		throw new SecurityException(msg);
 +	}
 +	
 +	private void verifyOneTimeUse(String assertionID) {
 +		//not necessarily required to check since notBefore and notOnOrAfter are verified   
 +		//check response Store for already existing assertion
 +		
 +	}
 +	
 +	private void verifyConditions(Assertion assertion, String reqAudience) throws SecurityException {		
 +		Conditions conditions = assertion.getConditions();
 +		
 +		verifyNotBefore(conditions.getNotBefore()); +		Logger.trace("NotBefore successfully verified"); +		
 +		verifyNotOnOrAfter(conditions.getNotOnOrAfter()); +		Logger.trace("NotOnOrAfter successfully verified");
 +		
 +		verifyAudience(conditions.getAudienceRestrictions().get(0), reqAudience); +		 +		Logger.trace("Audience successfully verified");
 +		
 +	} +	 +	public static void validateRequiredAttributes( +			List<RequestedAttribute> reqAttrList, +			List<Attribute> attrList) +			throws STORKException { +		 +		Logger.debug("Starting required attribute validation"); +		 +		if (reqAttrList == null || reqAttrList.isEmpty()) { +			Logger.error("Requested Attributes list is empty."); +			throw new STORKException("No attributes have been requested"); +		} +		 +		if (attrList == null || attrList.isEmpty()) { +			Logger.error("STORK AttributeStatement is empty."); +			throw new STORKException("No attributes have been received"); +		} +		 +		Logger.trace("These attributes have been requested and received: "); +		int count = 0; +		for (RequestedAttribute reqAttr : reqAttrList) { +			Logger.trace("Requested attribute: " + reqAttr.getName() + " isRequired: " + reqAttr.isRequired()); +			for(Attribute attr : attrList) { +				if (verifyRequestedAttribute(reqAttr, attr)) +					count++; +			} +		} +		 +		int numRequiredReqAttr = getNumberOfRequiredAttributes(reqAttrList); +		Logger.trace("Number of requested required attributes: " + numRequiredReqAttr); +		Logger.trace("Number of received required attributes: " + count); +		 +		if (count != numRequiredReqAttr) { +			Logger.error("Not all required attributes have been received"); +			throw new STORKException("Not all required attributes have been received"); +		} +		Logger.debug("Received all required attributes!");			 +		 +	} +	 +	private static boolean verifyRequestedAttribute(RequestedAttribute reqAttr, Attribute attr) { +		 +		if ((reqAttr.getName()).equals(attr.getName())) { +			if (reqAttr.isRequired() && SAMLUtil.getStatusFromAttribute(attr).equals(STORKAttribute.ALLOWED_ATTRIBUTE_STATUS_AVAIL)) { +				Logger.trace("Received required attribute " + attr.getName() + " status: " + SAMLUtil.getStatusFromAttribute(attr)); +				return true; +			}			 +		} +		return false; +	} +	 +	private static int getNumberOfRequiredAttributes(List<RequestedAttribute> reqAttrList) { +		int count = 0; +		for (RequestedAttribute reqAttr : reqAttrList) +			if (reqAttr.isRequired()) count++; +		 +		return count; +	} +	
 +	
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/PEPSConnectorResponseVerifier.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/PEPSConnectorResponseVerifier.java new file mode 100644 index 000000000..2deeb2aae --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/PEPSConnectorResponseVerifier.java @@ -0,0 +1,153 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 + +import org.w3c.dom.Element; + +import at.gv.egovernment.moa.id.BuildException; +import at.gv.egovernment.moa.id.ParseException; +import at.gv.egovernment.moa.id.ServiceException; +import at.gv.egovernment.moa.id.auth.AuthenticationServer; +import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder; +import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; +import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; +import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser; +import at.gv.egovernment.moa.id.config.ConfigurationException; +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Constants; +import eu.stork.mw.messages.saml.STORKResponse; +import eu.stork.vidp.messages.exception.SAMLValidationException; +import eu.stork.vidp.messages.util.SAMLUtil; +import eu.stork.vidp.messages.util.XMLUtil; +
 +/**
 + * Verifies the SMAL response according to the STORK specification + * @author bzwattendorfer
 + *
 + */
 +public class PEPSConnectorResponseVerifier implements ResponseVerifier {
 +		
 +		
 +	/* (non-Javadoc)
 +	 * @see eu.stork.mw.peps.connector.validation.ResponseVerifier#verify(org.opensaml.saml2.core.Response)
 +	 */
 +	public void verify(STORKResponse response) throws SecurityException {
 +		
 +		verifySignature(response);
 +		Logger.debug("Signature of SAML response valid.");
 +		
 +		verifyStandardValidation(response);
 +		
 +		Logger.debug("SAML response format valid.");
 +		
 +	}
 +	
 +	
 +	private void verifySignature(STORKResponse response) throws SecurityException {
 +		//validate Signature
 +		try {
 +			if (response.isSigned()) {		 +				 +				String trustProfileID = AuthConfigurationProvider.getInstance().getStorkConfig().getSignatureVerificationParameter().getTrustProfileID(); +				 +				Logger.debug("Invoking MOA-SP with TrustProfileID: " + trustProfileID); +				
 +				// builds a <VerifyXMLSignatureRequest> for a call of MOA-SP +				Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder() +						.build(XMLUtil.printXML(response.getDOM()).getBytes(), trustProfileID); + +				Logger.trace("VerifyXMLSignatureRequest for MOA-SP succesfully built"); +				 +				Logger.trace("Calling MOA-SP"); +				// invokes the call +				Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker() +						.verifyXMLSignature(domVerifyXMLSignatureRequest);								 +				 +				// parses the <VerifyXMLSignatureResponse> +				VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser( +						domVerifyXMLSignatureResponse).parseData(); +				 +				Logger.trace("Received VerifyXMLSignatureResponse from MOA-SP"); + +				if (verifyXMLSignatureResponse.getSignatureCheckCode() != 0) { +					String msg = "Signature of SAMLResponse not valid"; +					Logger.error(msg);					 +					throw new SecurityException(msg); +				} +				 +				Logger.debug("Signature of SAML response successfully verified"); +				 +				if (verifyXMLSignatureResponse.getCertificateCheckCode() != 0) { +					String msg = "Certificate of SAMLResponse not valid"; +					Logger.error(msg);					 +					throw new SecurityException(msg); +				} +				 +				Logger.debug("Signing certificate of SAML response succesfully verified"); +				
 +			} else {
 +				String msg = "SAML Response is not signed.";
 +				throw new SecurityException(msg);
 +			}
 +			
 +		} catch (ConfigurationException e) {
 +			String msg = "Unable to load STORK configuration for STORK SAML Response signature verification.";
 +			Logger.error(msg, e);
 +			throw new SecurityException(msg, e);
 +		} catch (ParseException e) { +			String msg = "Unable to parse VerifyXMLSignature Request or Response."; +			Logger.error(msg, e); +			throw new SecurityException(msg, e); +		} catch (BuildException e) { +			String msg = "Unable to parse VerifyXMLSignature Request or Response."; +			Logger.error(msg, e); +			throw new SecurityException(msg, e); +		} catch (ServiceException e) { +			String msg = "Unable to invoke MOA-SP."; +			Logger.error(msg, e); +			throw new SecurityException(msg, e); +		} 			
 +		
 +	}
 +	
 +	private void verifyStandardValidation(STORKResponse response) throws SecurityException {
 +		try {
 +			SAMLUtil.verifySAMLObjectStandardValidation(response, "saml2-core-schema-and-stork-validator");
 +		} catch (SAMLValidationException e) {
 +			String msg ="SAML Response received not valid.";
 +			throw new SecurityException(msg, e);
 +		}
 +		
 +	}
 +	
 +	
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/ResponseVerifier.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/ResponseVerifier.java new file mode 100644 index 000000000..848937824 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/ResponseVerifier.java @@ -0,0 +1,44 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import eu.stork.mw.messages.saml.STORKResponse; + +/** + * Interface to be implemented for SAML response verification + * @author bzwattendorfer + * + */
 +public interface ResponseVerifier {
 +	 +	/** +	 * Verifies a STORK response +	 * @param response STORK response +	 * @throws SecurityException +	 */
 +	public void verify(STORKResponse response) throws SecurityException;
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKAuthnRequestProcessor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKAuthnRequestProcessor.java new file mode 100644 index 000000000..ff30919bc --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKAuthnRequestProcessor.java @@ -0,0 +1,170 @@ +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.lang.StringUtils;
 +import org.apache.velocity.app.VelocityEngine;
 +import org.opensaml.common.binding.BasicSAMLMessageContext;
 +import org.opensaml.saml2.binding.encoding.HTTPPostEncoder;
 +import org.opensaml.saml2.metadata.AssertionConsumerService;
 +import org.opensaml.saml2.metadata.Endpoint;
 +import org.opensaml.saml2.metadata.RequestedAttribute;
 +import org.opensaml.ws.transport.http.HTTPOutTransport;
 +import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
 +import org.opensaml.xml.security.credential.Credential;
 +
 +import at.gv.egovernment.moa.id.auth.servlet.PEPSConnectorServlet;
 +import at.gv.egovernment.moa.id.util.HTTPUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import eu.stork.mw.messages.saml.STORKAuthnRequest;
 +import eu.stork.vidp.messages.builder.STORKMessagesBuilder;
 +import eu.stork.vidp.messages.exception.SAMLException;
 +import eu.stork.vidp.messages.exception.SAMLValidationException;
 +import eu.stork.vidp.messages.stork.QualityAuthenticationAssuranceLevel;
 +import eu.stork.vidp.messages.stork.RequestedAttributes;
 +import eu.stork.vidp.messages.util.SAMLUtil;
 +
 +/**
 + * Class handling all necessary functionality for STORK AuthnRequest processing
 + * 
 + * @author bzwattendorfer
 + *
 + */
 +public class STORKAuthnRequestProcessor {
 +	
 +	/**
 +	 * Creates a STORK AuthnRequest
 +	 * @param destination Destination URL
 +	 * @param acsURL Assertion Consumer Service URL
 +	 * @param providerName SP Provider Name
 +	 * @param issuerValue Issuer Name
 +	 * @param qaaLevel STORK QAALevel to be requested
 +	 * @param requestedAttributes Requested Attributes to be requested
 +	 * @param spSector Sp Sector
 +	 * @param spInstitution SP Institution
 +	 * @param spApplication SP Application
 +	 * @param spCountry SP Country
 +	 * @param textToBeSigned text to be included in signedDoc element
 +	 * @param mimeType mimeType for the text to be signed in signedDoc
 +	 * @return STORK AuthnRequest
 +	 */
 +	public static STORKAuthnRequest generateSTORKAuthnRequest(
 +			String destination, 
 +			String acsURL, 
 +			String providerName, 
 +			String issuerValue, 
 +			QualityAuthenticationAssuranceLevel qaaLevel, 
 +			RequestedAttributes requestedAttributes, 
 +			String spSector, 
 +			String spInstitution, 
 +			String spApplication, 
 +			String spCountry,
 +			String textToBeSigned,
 +			String mimeType) {
 +		
 +			
 +		STORKAuthnRequest storkAuthnRequest =  
 +			STORKMessagesBuilder.buildSTORKAuthnRequest(
 +					destination, 
 +					acsURL, 
 +					providerName, 
 +					issuerValue, 
 +					qaaLevel, 
 +					requestedAttributes, 
 +					spSector, 
 +					spInstitution, 
 +					spApplication, 
 +					spCountry);				
 +		
 +		STORKMessagesBuilder.buildAndAddSignatureRequestToAuthnRequest(storkAuthnRequest, textToBeSigned, mimeType, true);
 +		
 +		Logger.debug("Added signedDoc attribute to STORK AuthnRequest");
 +		
 +		return storkAuthnRequest;
 +		
 +	}
 +	
 +	/**
 +	 * Signs a STORK AuthnRequest
 +	 * @param storkAuthnRequest STORK AuthRequest to sign
 +	 * @param keyStorePath KeyStorePath to the signing key
 +	 * @param keyStorePassword KeyStore Password
 +	 * @param keyName Signing key name
 +	 * @param keyPassword Signing key password
 +	 * @return Signed STORK AuthnRequest
 +	 * @throws SAMLException
 +	 */
 +	public static STORKAuthnRequest signSTORKAuthnRequest(
 +			STORKAuthnRequest storkAuthnRequest,
 +			String keyStorePath,
 +			String keyStorePassword,
 +			String keyName,
 +			String keyPassword) throws SAMLException {
 +		
 +		Logger.trace("Building Credential Provider for signing process");
 +		
 +		CredentialProvider credentialProvider = new KeyStoreCredentialProvider(keyStorePath, keyStorePassword, keyName, keyPassword);
 +		
 +		Credential credential = credentialProvider.getCredential();
 +		
 +		Logger.trace("Credentials found");
 +		
 +		SAMLUtil.signSAMLObject(storkAuthnRequest, credential);
 +		
 +		return storkAuthnRequest;
 +	}
 +	
 +	/**
 +	 * Validates a STORK AuthnRequest
 +	 * @param storkAuthnRequest STORK AuthnRequest to validate
 +	 * @throws SAMLValidationException
 +	 */
 +	public static void validateSTORKAuthnRequest(STORKAuthnRequest storkAuthnRequest) throws SAMLValidationException {
 +				
 +		SAMLUtil.verifySAMLObjectStandardValidation(storkAuthnRequest, "saml2-core-schema-and-stork-validator");
 +		
 +	}
 +	
 +	/**
 +	 * Sends a STORK AuthnRequest (Endpoint taken out of AuthnRequest)
 +	 * @param request HttpServletRequest
 +	 * @param response HttpServletResponse
 +	 * @param storkAuthnRequest STORK AuthnRequest to send
 +	 * @throws Exception
 +	 */
 +	public static void sendSTORKAuthnRequest(HttpServletRequest request, HttpServletResponse response, STORKAuthnRequest storkAuthnRequest) throws Exception {
 +		
 +		Logger.trace("Create endpoint...");
 +		Endpoint endpoint = STORKMessagesBuilder.buildSAMLObject(AssertionConsumerService.DEFAULT_ELEMENT_NAME);
 +		endpoint.setBinding("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST");
 +		endpoint.setLocation(storkAuthnRequest.getDestination());
 +
 +		
 +		Logger.trace("Prepare SAMLMessageContext...");
 +		HTTPOutTransport outTransport = new HttpServletResponseAdapter(response, request.isSecure());		
 +		BasicSAMLMessageContext<?, STORKAuthnRequest, ?> samlMessageContext = new BasicSAMLMessageContext();
 +		samlMessageContext.setOutboundMessageTransport(outTransport);
 +		samlMessageContext.setPeerEntityEndpoint(endpoint);
 +
 +		Logger.trace("Set STORK SAML AuthnRequest to SAMLMessageContext...");
 +		samlMessageContext.setOutboundSAMLMessage(storkAuthnRequest);
 +				
 +		Logger.trace("Initialize VelocityEngine...");
 +
 +		VelocityEngine velocityEngine = VelocityProvider.getClassPathVelocityEngine();
 +		
 +//		HTTPPostEncoder encoder = new HTTPPostEncoder(velocityEngine, "/templates/saml2-post-binding.vm");
 +		HTTPPostEncoder encoder = new HTTPPostEncoder(velocityEngine, "/saml2-post-binding-moa.vm");
 +
 +		Logger.trace("HTTP-Post encode SAMLMessageContext...");
 +		encoder.encode(samlMessageContext);
 +	}
 +		
 +	
 +	
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKException.java new file mode 100644 index 000000000..5b737603b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKException.java @@ -0,0 +1,42 @@ +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +
 +/**
 + * Exception thrown if error occurs in STORK processing
 + * @author bzwattendorfer
 + *
 + */
 +public class STORKException extends Exception{
 +
 +	/**
 +	 * 
 +	 */
 +	private static final long serialVersionUID = 1L;
 +
 +	public STORKException() {
 +		super();
 +		
 +	}
 +
 +	public STORKException(String message, Throwable cause) {
 +		super(message, cause);
 +		
 +	}
 +
 +	public STORKException(String message) {
 +		super(message);
 +		
 +	}
 +
 +	public STORKException(Throwable cause) {
 +		super(cause);
 +		
 +	}
 +	
 +	
 +
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java new file mode 100644 index 000000000..c98ca87b9 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/STORKResponseProcessor.java @@ -0,0 +1,405 @@ +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import iaik.x509.X509Certificate;
 +
 +import java.io.ByteArrayInputStream;
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.security.cert.CertificateException;
 +import java.security.cert.CertificateFactory;
 +import java.util.List;
 +import java.util.Vector;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.namespace.QName;
 +import javax.xml.transform.TransformerException;
 +
 +import org.opensaml.common.binding.BasicSAMLMessageContext;
 +import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;
 +import org.opensaml.saml2.core.Assertion;
 +import org.opensaml.saml2.core.Attribute;
 +import org.opensaml.saml2.metadata.RequestedAttribute;
 +import org.opensaml.saml2.metadata.SurName;
 +import org.opensaml.ws.transport.http.HTTPInTransport;
 +import org.opensaml.ws.transport.http.HTTPOutTransport;
 +import org.opensaml.ws.transport.http.HttpServletRequestAdapter;
 +import org.opensaml.ws.transport.http.HttpServletResponseAdapter;
 +import org.opensaml.xml.XMLObject;
 +import org.opensaml.xml.schema.XSAny;
 +import org.opensaml.xml.schema.XSString;
 +import org.opensaml.xml.util.Base64;
 +import org.opensaml.xml.util.XMLHelper;
 +import org.w3c.dom.Element;
 +import org.w3c.dom.NodeList;
 +
 +import at.gv.egovernment.moa.id.ParseException;
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute;
 +import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttributeImpl;
 +import at.gv.egovernment.moa.id.auth.data.IdentityLink;
 +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
 +import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.CreateIdentityLinkResponse;
 +import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWClientException;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.Constants;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +import at.gv.egovernment.moa.util.DateTimeUtils;
 +import at.gv.egovernment.moa.util.StringUtils;
 +import eu.stork.mw.messages.saml.STORKResponse;
 +import eu.stork.vidp.messages.common.STORKConstants;
 +import eu.stork.vidp.messages.util.SAMLUtil;
 +import eu.stork.vidp.messages.util.XMLUtil;
 +
 +/**
 + * 
 + * Handles all functionality for the processing of a STORK response
 + * @author bzwattendorfer
 + *
 + */
 +public class STORKResponseProcessor {
 +	
 +	/** OASIS DSS Namespace */
 +	public static final String OASIS_DSS_NS = "urn:oasis:names:tc:dss:1.0:core:schema";
 +	
 +	/** OASIS DSS Success Message */
 +	public static final String OASIS_DSS_SUCCESS_MSG = "urn:oasis:names:tc:dss:1.0:resultmajor:Success";
 +	
 +	/**
 +	 * Extracts a STORK response from a HTTP message
 +	 * @param request HttpServletRequest
 +	 * @param response HttpServletResponse
 +	 * @return STORK Response
 +	 * @throws STORKException
 +	 */
 +	public static STORKResponse receiveSTORKRepsonse(HttpServletRequest request, HttpServletResponse response) throws STORKException {
 +		
 +		HTTPInTransport httpInTransport = new HttpServletRequestAdapter(request);
 +		HTTPOutTransport httpOutTransport = new HttpServletResponseAdapter(response, request.isSecure());
 +		
 +		httpInTransport.getPeerAddress();
 +		
 +		String samlResponseString = request.getParameter("SAMLResponse");
 +		
 +		if (StringUtils.isEmpty(samlResponseString)) {
 +			Logger.error("SAMLResponse not found in request.");
 +			throw new STORKException("SAMLResponse not found in request.");
 +		}
 +		
 +		BasicSAMLMessageContext samlMessageContext = new BasicSAMLMessageContext();
 +		
 +		samlMessageContext.setInboundMessageTransport(httpInTransport);
 +		samlMessageContext.setOutboundMessageTransport(httpOutTransport);
 +		
 +		HTTPPostDecoder postDecoder = new HTTPPostDecoder();
 +		
 +		try {
 +			postDecoder.decode(samlMessageContext);
 +		} catch (Exception e) {
 +			Logger.error("Error decoding SAMLResponse message", e);
 +			throw new STORKException("Error decoding SAMLResponse message", e);
 +		}
 +		
 +		if (!(samlMessageContext.getInboundSAMLMessage() instanceof STORKResponse)) {
 +			Logger.error("Message received is not a SAMLResponse message");
 +			throw new STORKException("Message received is not a SAMLResponse message");
 +		}
 +			
 +		STORKResponse samlResponse = (STORKResponse) samlMessageContext.getInboundSAMLMessage();
 +		
 +		return samlResponse;
 +	}
 +	
 +	/**
 +	 * Verifies a STORK response according STORK specification
 +	 * @param storkResponse STORK Response to verify
 +	 * @throws STORKException if validation fails
 +	 */
 +	public static void verifySTORKResponse(STORKResponse storkResponse) throws STORKException {
 +		
 +		ResponseVerifier responseVerifier = new PEPSConnectorResponseVerifier();
 +		try {
 +			responseVerifier.verify(storkResponse);
 +		} catch (SecurityException e) {
 +			Logger.error("Error validating response message from PEPS.", e);
 +			throw new STORKException("Error validating response message from PEPS.");
 +		}
 +		
 +	}
 +	
 +	/**
 +	 * Verifies a STORK assertion
 +	 * @param assertion STORK assertion
 +	 * @param ipAddress Client IP address
 +	 * @param authnRequestID ID of the AuthnRequest
 +	 * @param recipient recipient for verification
 +	 * @param audience audience for verification
 +	 * @param reqAttributeList RequestedAttribute list for verification
 +	 * @throws STORKException
 +	 */
 +	public static void verifySTORKAssertion(
 +			Assertion assertion, 
 +			String ipAddress, 
 +			String authnRequestID, 
 +			String recipient, 
 +			String audience,
 +			List<RequestedAttribute> reqAttributeList) throws STORKException {
 +		
 +		//validate Assertion			
 +		AssertionVerifier assertionVerifier = new PEPSConnectorAssertionVerifier();
 +		try {
 +			assertionVerifier.verify(assertion, ipAddress, authnRequestID, recipient, audience, reqAttributeList);
 +			
 +			//verify if all required attributes are present
 +			PEPSConnectorAssertionVerifier.validateRequiredAttributes(reqAttributeList, assertion.getAttributeStatements().get(0).getAttributes());
 +			
 +		} catch (SecurityException e) {
 +			Logger.error("Error verifying assertion from PEPS", e);
 +			throw new STORKException("Error validating assertion received from PEPS.");
 +		}						
 +			
 +	}
 +	
 +	/**
 +	 * Extracts the citizen signature from the signedDoc element present in the STORK assertion
 +	 * @param storkAssertion STORK assertion
 +	 * @return citizen signature as XML
 +	 * @throws STORKException
 +	 */
 +	public static Element extractCitizenSignature(Assertion storkAssertion) throws STORKException {
 +		
 +		Logger.debug("Processing DSS signature response from PEPS");
 +		
 +		Element signatureResponse = getSignedDocAttributeValue(storkAssertion);
 +					
 +		if (signatureResponse == null) {
 +			String msg = "Could not find DSS signature response in SAML assertion";
 +			Logger.error(msg);
 +			throw new STORKException(msg);
 +		}
 +		
 +		Logger.debug("Found DSS signature in SAML assertion");
 +		
 +		Logger.debug("DSS Signature creation response received from PEPS (pretty print):");
 +		Logger.debug(XMLHelper.prettyPrintXML(signatureResponse));
 +		Logger.trace("DSS Signature creation response received from PEPS (original):");
 +		Logger.trace(XMLUtil.printXML(signatureResponse));
 +		
 +		Element signature = getSignature(signatureResponse);
 +		
 +		if (signature == null) {
 +			String msg = "Could not find citizen signature in SAML assertion";
 +			Logger.error(msg);
 +			throw new STORKException(msg);
 +		} 		
 +				
 +		Logger.debug("Found foreign citizen signature in SAML assertion (pretty print):");
 +		Logger.debug(XMLHelper.prettyPrintXML(signature));
 +		Logger.trace("Found foreign citizen signature in SAML assertion (original):");
 +		Logger.trace(XMLUtil.printXML(signature));		
 +		
 +		return signature;
 +	}
 +	
 +	/**
 +	 * Extracts the signedDoc attribute from a STORK assertion as XML
 +	 * @param storkAssertion STORK assertion
 +	 * @return Value of signedDoc attribute
 +	 * @throws STORKException
 +	 */
 +	private static Element getSignedDocAttributeValue(Assertion storkAssertion) throws STORKException {	
 +		
 +		XMLObject xmlObj = SAMLUtil.getAttributeValue(storkAssertion.getAttributeStatements().get(0).getAttributes(), STORKConstants.STORK_ATTRIBUTE_SIGNEDDOC);
 +		
 +		
 +		if (xmlObj instanceof XSAny)
 +			return getSignedDocAttributeValueFromAny((XSAny) xmlObj);
 +		else if (xmlObj instanceof XSString)
 +			return getSignedDocAttributValueFromString((XSString) xmlObj);
 +		else 
 +			return null;
 +		
 +	}
 +	
 +	/**
 +	 * Get signedDoc as XML if provided as anyType
 +	 * @param any AttributeValue as anyType
 +	 * @return signedDoc as XML
 +	 */
 +	private static Element getSignedDocAttributeValueFromAny(XSAny any) {
 +		if (!any.getUnknownXMLObjects(new QName(OASIS_DSS_NS, "SignResponse")).isEmpty()) {
 +			XMLObject xmlObj = any.getUnknownXMLObjects(new QName(OASIS_DSS_NS, "SignResponse")).get(0);
 +			return xmlObj.getDOM();
 +		} else {
 +			return null;
 +		}
 +	}
 +	
 +	/**
 +	 * Get signedDoc as XML if provided as String
 +	 * @param string AttributeValue as String
 +	 * @return signedDoc as XML
 +	 * @throws STORKException
 +	 */
 +	private static Element getSignedDocAttributValueFromString(XSString string) throws STORKException {
 +		try {
 +			return XMLUtil.stringToDOM(string.getValue());
 +		} catch (Exception e) {
 +			Logger.error("Error building DOM", e);
 +			throw new STORKException(e);
 +			
 +		} 
 +	}
 +	
 +	/**
 +	 * Extracts the signature value out of a DSS response
 +	 * @param signatureResponse DSS signature response
 +	 * @return signature 
 +	 * @throws STORKException
 +	 */
 +	private static Element getSignature(Element signatureResponse) throws STORKException {
 +		
 +		NodeList nList = signatureResponse.getElementsByTagNameNS(OASIS_DSS_NS, "ResultMajor");
 +				
 +		String resultMajor = XMLUtil.getFirstTextValueFromNodeList(nList);
 +		
 +		if (StringUtils.isEmpty(resultMajor)) {					
 +			String msg = "DSS response not correct, ResultMajor element missing.";
 +			Logger.error(msg);
 +			throw new STORKException(msg);
 +		}
 +		
 +		Logger.trace("ResultMajor of DSS response: " + resultMajor);
 +		
 +		if (!OASIS_DSS_SUCCESS_MSG.equals(resultMajor)) {
 +			String msg = "DSS response not correct, ResultMajor is " + resultMajor;
 +			Logger.error(msg);
 +			throw new STORKException(msg);
 +		}
 +				
 +		NodeList nList2 = signatureResponse.getElementsByTagNameNS(OASIS_DSS_NS, "Base64Signature");; 
 +		
 +		String base64SigString = XMLUtil.getFirstTextValueFromNodeList(nList2);
 +		
 +		if (StringUtils.isEmpty(base64SigString)) {					
 +			String msg = "DSS response not correct, Base64Signature element missing.";
 +			Logger.error(msg);
 +			throw new STORKException(msg);
 +		}
 +		
 +		Logger.trace("Base64Signature element of DSS response: " + base64SigString);
 +		
 +		String sigString = new String(Base64.decode(base64SigString));
 +		
 +		try {
 +			return XMLUtil.stringToDOM(sigString);
 +		} catch (Exception e) {
 +			String msg = "Unable to extract signature from DSS response";
 +			Logger.error(msg);
 +			throw new STORKException(msg);
 +		} 
 +		
 +		
 +	}
 +	
 +	/**
 +	 * Handels connection to SZR-GW and returns Identity Link on success
 +	 * @param citizenSignature Citizen signature
 +	 * @param attributeList Received attribute List in assertion
 +	 * @return Identity Link
 +	 * @throws STORKException
 +	 */
 +	public static IdentityLink connectToSZRGateway(Element citizenSignature, List<Attribute> attributeList) throws STORKException {				
 +		Logger.trace("Calling SZR Gateway with the following attributes:");
 +
 +		String fiscalNumber = SAMLUtil.getAttributeStringValue(attributeList, STORKConstants.STORK_ATTRIBUTE_FISCALNUMBER);
 +		Logger.trace(STORKConstants.STORK_ATTRIBUTE_FISCALNUMBER + " : " + fiscalNumber);
 +				
 +		String givenName = SAMLUtil.getAttributeStringValue(attributeList, STORKConstants.STORK_ATTRIBUTE_GIVENNAME);
 +		Logger.trace(STORKConstants.STORK_ATTRIBUTE_GIVENNAME+ " : " + givenName);
 +		
 +		String lastName = SAMLUtil.getAttributeStringValue(attributeList, STORKConstants.STORK_ATTRIBUTE_SURNAME);
 +		Logger.trace(STORKConstants.STORK_ATTRIBUTE_SURNAME+ " : " + lastName);
 +		
 +		String dateOfBirth = SAMLUtil.getAttributeStringValue(attributeList, STORKConstants.STORK_ATTRIBUTE_DATEOFBIRTH);
 +		Logger.trace(STORKConstants.STORK_ATTRIBUTE_DATEOFBIRTH + " : " + dateOfBirth);
 +		
 +		if (!StringUtils.isEmpty(dateOfBirth)) {
 +			dateOfBirth = DateTimeUtils.formatPEPSDateToMOADate(dateOfBirth);
 +		} 
 +		
 +		CreateIdentityLinkResponse response;
 +		IdentityLink identityLink = null;
 +		try {
 +			Logger.trace("Starting call...");
 +			response = AuthenticationServer.getInstance().getIdentityLink(fiscalNumber, givenName, lastName, dateOfBirth, citizenSignature);
 +			if (response.isError()) {	    
 +				Logger.error("Receveid ErrorResponse from SZR Gateway.");
 +	    		throw new SZRGWClientException(response.getError());
 +	    	}
 +	    	else {
 +	    		Logger.trace("Receveid Success Response from SZR Gateway.");
 +	    		Element samlAssertion = response.getAssertion();
 +	    		    	
 +		    	IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(samlAssertion);
 +		    	identityLink = ilParser.parseIdentityLink();
 +		    	
 +		    	
 +		    	Logger.debug("Received Identity Link from SZR Gateway");
 +		    	//TODO: is this ok?
 +//		    	if (StringUtils.isEmpty(identityLink.getDateOfBirth())) {
 +//		    		identityLink.setDateOfBirth("9999-12-31");
 +//				}
 +
 +	    	}
 +		} catch (SZRGWClientException e) {
 +			Logger.error("Error connecting SZR-Gateway: ", e);
 +			throw new STORKException("Error connecting SZR-Gateway: ", e);
 +		} catch (ParseException e) {
 +			Logger.error("Error parsing IdentityLink received from SZR-Gateway: ", e);
 +			throw new STORKException("Error parsing IdentityLink received from SZR-Gateway: ", e);
 +		}
 +    		    	
 +    	return identityLink;
 +		
 +	}
 +	
 +	
 +	/**
 +	 * Transforms additional STORK attributes to MOA Extended attributes
 +	 * @param storkAttributeList STORK attribute list
 +	 * @return
 +	 */
 +	public static List<ExtendedSAMLAttribute> addAdditionalSTORKAttributes(List<Attribute> storkAttributeList) {
 +		List<ExtendedSAMLAttribute> moaExtendedSAMLAttributeList = new Vector<ExtendedSAMLAttribute>();
 +		
 +		Logger.trace("Adding the following attributes to MOA assertion: ");
 +		int count = 0;
 +		//only add attributes different than eIdentifier, given name, surname, dateOfBirth, signedDoc
 +		for (Attribute attribute : storkAttributeList) {
 +			//attribute is not in default returned attribute set
 +			if (!STORKConstants.DEFAULT_STORK_RETURNED_ATTRIBUTE_SET.contains(attribute.getName())) {
 +				
 +				String attributeValue = null;
 +				if (!attribute.getAttributeValues().isEmpty()) {
 +					//we have attribute value
 +					attributeValue = SAMLUtil.getStringValueFromXMLObject(attribute.getAttributeValues().get(0));
 +				}
 +				ExtendedSAMLAttribute extendedSAMLAttribute = 
 +					new ExtendedSAMLAttributeImpl(attribute.getName(), attributeValue, Constants.STORK_NS_URI, 0);
 +				moaExtendedSAMLAttributeList.add(extendedSAMLAttribute);
 +				count++;
 +				Logger.trace("Additional attribute: " + attribute.getName());
 +			}				
 +		}
 +		
 +		
 +		Logger.debug("Added " + count + " STORK attribute(s) to the MOA assertion.");		
 +		
 +		return moaExtendedSAMLAttributeList;
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/VelocityProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/VelocityProvider.java new file mode 100644 index 000000000..29478718f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/stork/VelocityProvider.java @@ -0,0 +1,88 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * The Austrian STORK Modules have been developed by the E-Government + * Innovation Center EGIZ, a joint initiative of the Federal Chancellery + * Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.auth.stork;
 +
 +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +
 +/**
 + * Gets a Velocity Engine + *  + * @author bzwattendorfer
 + *
 + */
 +public class VelocityProvider {
 + +	/** +	 * Gets velocityEngine from Classpath +	 * @return VelocityEngine +	 * @throws Exception +	 */
 +	public static VelocityEngine getClassPathVelocityEngine() throws Exception {
 +		VelocityEngine velocityEngine = getBaseVelocityEngine();
 +        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
 +        velocityEngine.setProperty("classpath.resource.loader.class",
 +                "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
 +        
 +		velocityEngine.init();
 +		
 +		return velocityEngine;
 +	}
 +	 +	/** +	 * Gets VelocityEngine from File +	 * @param rootPath File Path to template file +	 * @return VelocityEngine +	 * @throws Exception +	 */
 +	public static VelocityEngine getFileVelocityEngine(String rootPath) throws Exception {
 +		VelocityEngine velocityEngine = getBaseVelocityEngine();
 +        velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
 +        velocityEngine.setProperty("file.resource.loader.class",
 +                "org.apache.velocity.runtime.resource.loader.FileResourceLoader");
 +        velocityEngine.setProperty("file.resource.loader.path", rootPath);
 +        
 +		velocityEngine.init();
 +		
 +		return velocityEngine;
 +	}
 +	 +	/** +	 * Gets a basic VelocityEngine +	 * @return VelocityEngine +	 */
 +	private static VelocityEngine getBaseVelocityEngine() {
 +		VelocityEngine velocityEngine = new VelocityEngine();
 +        velocityEngine.setProperty(RuntimeConstants.ENCODING_DEFAULT, "UTF-8");
 +        velocityEngine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
 +        
 +        return velocityEngine;
 +	}
 +	
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java index c719484fa..13e7cb0f1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationBuilder.java @@ -24,12 +24,13 @@  package at.gv.egovernment.moa.id.config; -import iaik.ixsil.util.Utils;  import iaik.pki.pathvalidation.ChainingModes;  import iaik.utils.RFC2253NameParser;  import iaik.utils.RFC2253NameParserException;  import java.math.BigInteger; +import java.net.MalformedURLException; +import java.net.URL;  import java.security.Principal;  import java.util.ArrayList;  import java.util.HashMap; @@ -39,20 +40,23 @@ import java.util.List;  import java.util.Map;  import java.util.Vector; +import org.opensaml.saml2.metadata.RequestedAttribute; +import org.opensaml.ws.message.encoder.MessageEncodingException;  import org.w3c.dom.Attr;  import org.w3c.dom.Element;  import org.w3c.dom.Node;  import org.w3c.dom.NodeList;  import org.w3c.dom.traversal.NodeIterator; -import com.sun.xml.internal.fastinfoset.stax.events.Util; -  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.data.Schema;  import at.gv.egovernment.moa.id.auth.data.SchemaImpl;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.config.auth.VerifyInfoboxParameter;  import at.gv.egovernment.moa.id.config.auth.VerifyInfoboxParameters; +import at.gv.egovernment.moa.id.config.stork.CPEPS; +import at.gv.egovernment.moa.id.config.stork.SignatureCreationParameter; +import at.gv.egovernment.moa.id.config.stork.SignatureVerificationParameter;  import at.gv.egovernment.moa.id.data.IssuerAndSerial;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;  import at.gv.egovernment.moa.logging.Logger; @@ -63,6 +67,12 @@ import at.gv.egovernment.moa.util.FileUtils;  import at.gv.egovernment.moa.util.StringUtils;  import at.gv.egovernment.moa.util.XPathException;  import at.gv.egovernment.moa.util.XPathUtils; +import eu.stork.vidp.messages.builder.STORKMessagesBuilder; +import eu.stork.vidp.messages.common.STORKConstants; +import eu.stork.vidp.messages.stork.QualityAuthenticationAssuranceLevel; +import eu.stork.vidp.messages.stork.RequestedAttributes; +import eu.stork.vidp.messages.util.SAMLUtil; +import eu.stork.vidp.messages.util.XMLUtil;  /**   * A class that builds configuration data from a DOM based representation. @@ -80,6 +90,12 @@ public class ConfigurationBuilder {    protected static final String CONF = Constants.MOA_ID_CONFIG_PREFIX + ":";    /** an XPATH-Expression */     protected static final String DSIG = Constants.DSIG_PREFIX + ":"; +   +  /** an XPATH-Expression */  +  protected static final String STORK = Constants.STORK_PREFIX + ":"; +   +  /** an XPATH-Expression */  +  protected static final String STORKP= Constants.STORKP_PREFIX + ":";    //    // chaining mode constants appearing in the configuration file @@ -220,8 +236,58 @@ public class ConfigurationBuilder {    protected static final String VERIFY_INFOBOXES_INFOBOX_XPATH = CONF + "Infobox"; +  /** STORK Config XPATH-Expression */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_CPEPS = +    ROOT + CONF + "AuthComponent/" + CONF + "ForeignIdentities/" + CONF + "STORK/" + CONF + "C-PEPS"; +   +  /** STORK Config AttributeName */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_COUNTRY_CODE = "countryCode"; +   +  /** STORK Config AttributeName */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_URL = "URL"; +   +  /** STORK Config XPATH-Expression */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_SIGNATURE_CREATION_PARAMETER = +    ROOT + CONF + "AuthComponent/" + CONF + "ForeignIdentities/" + CONF + "STORK/" + CONF + "SAMLSigningParameter/" + +    CONF + "SignatureCreationParameter" ; +   +  /** STORK Config XPATH-Expression */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_REQUESTED_ATTRIBUTES = +    STORK + "RequestedAttribute"; +   +  /** STORK Config XPATH-Expression */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_SIGNATURE_VERIFICATION_PARAMETER = +    ROOT + CONF + "AuthComponent/" + CONF + "ForeignIdentities/" + CONF + "STORK/" + CONF + "SAMLSigningParameter/" + +    CONF + "SignatureVerificationParameter"; +   +  /** STORK Config XPATH-Expression */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_KEYSTORE =     +	CONF + "KeyStore"; +   +  /** STORK Config XPATH-Expression */   +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_KEYNAME =     +	  CONF + "KeyName"; +   +  /** STORK Config XPATH-Expression */   +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_KEYSTORE_PASSWORD =     +    	CONF + "KeyStore/@password"; +   +  /** STORK Config XPATH-Expression */   +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_KEYNAME_PASSWORD =     +    	CONF + "KeyName/@password"; +   +  /** STORK Config XPATH-Expression */  +  public static final String AUTH_FOREIGN_IDENTITIES_STORK_TRUSTPROFILE_ID = +    	CONF + "TrustProfileID"; +  /** STORK Config XPATH-Expression */  +  public static final String OA_AUTH_COMPONENT_STORK_QAA = +    CONF + "STORK/" + STORK + "QualityAuthenticationAssuranceLevel"; +  /** STORK Config XPATH-Expression */  +  public static final String OA_AUTH_COMPONENT_STORK_REQUESTED_ATTRIBUTE = +    CONF + "STORK/" + STORKP + "RequestedAttributes/" + STORK + "RequestedAttribute"; +         /**      * main configuration file directory name used to configure MOA-ID       */ @@ -615,6 +681,32 @@ public class ConfigurationBuilder {          		oap.setMandateProfiles(profiles);          	}        	          }         +         +        //add STORK Configuration specific to OA (RequestedAttributes, QAALevel) +        QualityAuthenticationAssuranceLevel qaaLevel = buildOaSTORKQAALevel(authComponent); +        if (qaaLevel != null) {        	 +        	oap.setQaaLevel(qaaLevel); +        	Logger.debug("Using non-MOA-default STORK QAALevel for this OA " + "(" + oap.getPublicURLPrefix() + "): " + qaaLevel.getValue()); +        } +         +        RequestedAttributes additionalRequestedAttributes = buildOaSTORKRequestedAttributes(authComponent);  +         +        if(!additionalRequestedAttributes.getRequestedAttributes().isEmpty()) { +        	//we have additional STORK attributes to request for this OA         	 +        	Logger.debug("Using non-MOA-default STORK RequestedAttributes for this OA " + "(" + oap.getPublicURLPrefix() + "): "); +        	for (RequestedAttribute addReqAttr : additionalRequestedAttributes.getRequestedAttributes()) { +        		if (!SAMLUtil.containsAttribute(oap.getRequestedAttributes().getRequestedAttributes(),addReqAttr.getName())) { +        			addReqAttr.detach(); +        			oap.getRequestedAttributes().getRequestedAttributes().add(addReqAttr); +        			Logger.debug("Requesting additional attribute: " + addReqAttr.getName() + ", isRequired: " + addReqAttr.isRequired()); +        		} +        	} +        	 +        } else { +        	//do nothing, only request default attributes +        } + +                }         OA_set.add(oap);      } @@ -633,7 +725,7 @@ public class ConfigurationBuilder {     */    private int buildConditionLength(String length) { -      if (Util.isEmptyString(length)) +      if (StringUtils.isEmpty(length))      	  return -1;        else       	  return new Integer(length).intValue(); @@ -1035,6 +1127,228 @@ public class ConfigurationBuilder {        return new VerifyInfoboxParameters(defaultIdentifiers, infoboxParameters);      }           } +   +  /** +   * Creates a SignatureCreationParameter object from the MOA-ID configuration +   * This configuration object contains KeyStore and Key data for signature creation (STORK SAML Signature Creation). +   *  +   * @return KeyStore and Key data for signature creation (STORK SAML Signature Creation) +   */ +  public SignatureCreationParameter buildSTORKSignatureCreationParameter() { +	   +	  Logger.debug("Loading STORK signature creation parameters."); +	  	  	   +	  Element signatureCreationParameterElement = (Element)XPathUtils.selectSingleNode(configElem_, AUTH_FOREIGN_IDENTITIES_STORK_SIGNATURE_CREATION_PARAMETER); +	  if (signatureCreationParameterElement == null) { +		  Logger.debug("No STORK signature parameters found, " + AUTH_FOREIGN_IDENTITIES_STORK_SIGNATURE_CREATION_PARAMETER + "is missing."); +		  return null; +	  } +	   +	  SignatureCreationParameter signatureCreationParameter = new SignatureCreationParameter(); +	   +	  Element keyStoreElement = (Element)XPathUtils.selectSingleNode(signatureCreationParameterElement, AUTH_FOREIGN_IDENTITIES_STORK_KEYSTORE); +	  if (keyStoreElement==null) { +		  Logger.error(AUTH_FOREIGN_IDENTITIES_STORK_KEYSTORE + "is missing."); +		  return null; +	  } +	      +	  Element keyNameElement = (Element)XPathUtils.selectSingleNode(signatureCreationParameterElement, AUTH_FOREIGN_IDENTITIES_STORK_KEYNAME); +	  if (keyNameElement==null) { +		  Logger.error(AUTH_FOREIGN_IDENTITIES_STORK_KEYNAME + "is missing."); +		  return null; +	  } +	      +	  String keyStorePath = DOMUtils.getText(keyStoreElement); +	  if (StringUtils.isEmpty(keyStorePath)) { +		  Logger.error("No KeyStorePath for STORK SAML Signing Certificate provided!"); +		  return null;	    +	  } +	  signatureCreationParameter.setKeyStorePath(FileUtils.makeAbsoluteURL(keyStorePath, rootConfigFileDir_)); +	  Logger.trace("Found KeyStorePath for STORK SAML Signing Certificate: " + keyStorePath); +	    +	  String keyStorePassword = XPathUtils.getAttributeValue(signatureCreationParameterElement, AUTH_FOREIGN_IDENTITIES_STORK_KEYSTORE_PASSWORD, ""); +	  signatureCreationParameter.setKeyStorePassword(keyStorePassword); +	   +	  String keyName = DOMUtils.getText(keyNameElement); +	  if (StringUtils.isEmpty(keyName)) { +		  Logger.warn(AUTH_FOREIGN_IDENTITIES_STORK_KEYSTORE_PASSWORD + "is missing."); +		  return null; +	  } +	  signatureCreationParameter.setKeyName(keyName); +	  Logger.trace("Found KeyName for STORK SAML Signing Certificate: " + keyName); +	   +	  String keyPassword = XPathUtils.getAttributeValue(signatureCreationParameterElement, AUTH_FOREIGN_IDENTITIES_STORK_KEYNAME_PASSWORD, ""); +	  signatureCreationParameter.setKeyPassword(keyPassword); +	   +	  Logger.info("STORK signature creation parameters loaded."); +	   +	  return signatureCreationParameter;	      + +  } +   +  /** +   * Creates a SignatureVerificationParameter object from the MOA-ID configuration +   * This configuration object contains the TrustProfile to be used for signature verification (STORK SAML Signature Verification) +   *  +   * @return TrustProfileID for signature verification (STORK SAML Signature Verification) +   */ +  public SignatureVerificationParameter buildSTORKSignatureVerificationParameter() { +	   +	  Logger.debug("Loading STORK signature verification parameters."); +	   +	  Element signatureVerificationParameterElement = (Element)XPathUtils.selectSingleNode(configElem_, AUTH_FOREIGN_IDENTITIES_STORK_SIGNATURE_VERIFICATION_PARAMETER); +	  if (signatureVerificationParameterElement == null) { +		  Logger.debug("No STORK verification parameters found, " +AUTH_FOREIGN_IDENTITIES_STORK_SIGNATURE_VERIFICATION_PARAMETER + "is missing."); +		  return null; +	  } +	   +	  SignatureVerificationParameter signatureVerificationParameter = new SignatureVerificationParameter(); +	   +	  String trustProfileID = XPathUtils.getElementValue(signatureVerificationParameterElement, AUTH_FOREIGN_IDENTITIES_STORK_TRUSTPROFILE_ID, null); +	  if (StringUtils.isEmpty(trustProfileID)) { +		  Logger.error(AUTH_FOREIGN_IDENTITIES_STORK_TRUSTPROFILE_ID + "is missing."); +		  return null; +	  } +	  Logger.trace("Using the following MOA-SP TrustProfile for STORK SAML signature verification: " + trustProfileID); +	  signatureVerificationParameter.setTrustProfileID(trustProfileID); +	   +	  Logger.info("STORK signature verification parameters loaded."); +	   +	  return signatureVerificationParameter; +  } +   +  /** +   * Builds a C-PEPS object from configuration +   * @param cpepsElement DOM Element of C-PEPS from configuration +   * @return C-PEPS object +   */ +  public CPEPS buildSTORKCpeps(Element cpepsElement) { +	   +	  String countryCode = cpepsElement.getAttribute(AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_COUNTRY_CODE);	 +      String cpepsURLString = cpepsElement.getAttribute(AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_URL); +      if (StringUtils.isEmpty(countryCode)) { +    	  Logger.error(AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_COUNTRY_CODE + "is missing."); +    	  return null; +      } +      if (StringUtils.isEmpty(cpepsURLString)) { +    	  Logger.error(AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_URL + "is missing."); +    	  return null; +      }  +       +      URL cpepsURL; +      try { +			cpepsURL = new URL(cpepsURLString); +      } catch (MalformedURLException e) { +			Logger.error("Provided CPEPS-URL (" + cpepsURLString + ") for country " + countryCode + " is not a URL", e); +			return null; +      } +      CPEPS cpeps = new CPEPS(countryCode, cpepsURL); +      Logger.debug("Adding C-PEPS for country: " + cpeps.getCountryCode() + ", URL: " + cpeps.getPepsURL()); +  	       +      Element reqAttributeElement; +      NodeIterator reqAttributeIterator = XPathUtils.selectNodeIterator(cpepsElement, AUTH_FOREIGN_IDENTITIES_STORK_CPEPS_REQUESTED_ATTRIBUTES);       +       +      while ((reqAttributeElement = (Element) reqAttributeIterator.nextNode()) != null) { +		    RequestedAttribute requestedAttribute; +			try { +				requestedAttribute = (RequestedAttribute) SAMLUtil.unmarshallMessage(reqAttributeElement); +			} catch (MessageEncodingException e) { +				Logger.error("Provided RequestedAttributes for CPEPS from country " + countryCode + " is malformed.", e); +				return null; +			} +			//only add if STORK attribute is correct +			if (STORKConstants.FULL_STORK_ATTRIBUTE_SET.contains(requestedAttribute.getName())) { +				cpeps.addCountrySpecificRequestedAttribute(requestedAttribute); +				Logger.debug("Adding also country specific requested attribute for C-PEPS (" + countryCode + "): " + requestedAttribute.getName() + ", isRequired: " + requestedAttribute.isRequired()); +			} else { +				Logger.warn("Skipping addition of requested STORK Attribute, attribute unknown : " + requestedAttribute.getName()); +			} +		     +	  } +       +	  return cpeps; +  } +   +  /** +   * Builds the supported C-PEPS Map from configuration +   * @return Map of C-PEPS +   */ +  public Map<String, CPEPS> buildSTORKcPEPSMap() { +	   +	  Logger.debug("Loading STORK C-PEPS information"); +	   +	  Map<String, CPEPS> cpepsMap = new HashMap<String, CPEPS>(); +	  	  	    +	  NodeIterator cpepsIterator = XPathUtils.selectNodeIterator(configElem_, AUTH_FOREIGN_IDENTITIES_STORK_CPEPS); +	  	        +	  Element cpepsElement; +	  CPEPS cpeps; + +	  while ((cpepsElement = (Element) cpepsIterator.nextNode()) != null) { +		    cpeps = buildSTORKCpeps(cpepsElement); +		    if (cpeps != null) { +		    	cpepsMap.put(cpeps.getCountryCode(), cpeps);		    	 +		    } +	  } +	   +	  if(!cpepsMap.isEmpty()) { +		  Logger.info("STORK C-PEPS information loaded"); +	  } +	       +	  return cpepsMap; +	   +  } +   +  /** +   * Builds the required STORK QAALevel for this OA +   * @param authComponentElement DOM Element of AuthComponent (from MOA configuration) +   * @return STORK QAALevel for this OA +   */ +  public QualityAuthenticationAssuranceLevel buildOaSTORKQAALevel(Element authComponentElement) { +	  Element qaaLevelElement = (Element)XPathUtils.selectSingleNode(authComponentElement, OA_AUTH_COMPONENT_STORK_QAA); +	   +	  if (qaaLevelElement == null) return null; +	   +	  try { +		QualityAuthenticationAssuranceLevel qaaLevel = (QualityAuthenticationAssuranceLevel) SAMLUtil.unmarshallMessage(qaaLevelElement); +		return qaaLevel; +	} catch (MessageEncodingException e) { +		Logger.error("Could not build STORK QAALevel, using default."); +		return null; +	} +	   +  } +   +  /** +   * Builds the Requested Attributes specific for an OA +   * @param authComponentElement DOM Element of AuthComponent (from MOA configuration) +   * @return STORK RequestedAttributes for this OA +   */ +  public RequestedAttributes buildOaSTORKRequestedAttributes(Element authComponentElement) { +	  List<RequestedAttribute> reqAttributeList = new ArrayList<RequestedAttribute>(); +	   +	   +	  Element reqAttributeElement; +      NodeIterator reqAttributeIterator = XPathUtils.selectNodeIterator(authComponentElement, OA_AUTH_COMPONENT_STORK_REQUESTED_ATTRIBUTE); +                   +      while ((reqAttributeElement = (Element) reqAttributeIterator.nextNode()) != null) { +		    RequestedAttribute requestedAttribute; +			try { +				requestedAttribute = (RequestedAttribute) SAMLUtil.unmarshallMessage(reqAttributeElement); +			} catch (MessageEncodingException e) { +				Logger.error("Provided RequestedAttributes Online Application is malformed.", e); +				return null; +			} +			//only add if STORK attribute is correct +			if (STORKConstants.FULL_STORK_ATTRIBUTE_SET.contains(requestedAttribute.getName())) { +				reqAttributeList.add(requestedAttribute); +			} else { +				Logger.warn("Skipping addition of requested STORK Attribute, attribute unknown : " + requestedAttribute.getName()); +			} +	  } +	   +	  return STORKMessagesBuilder.buildRequestedAttributes(reqAttributeList); +  }    /**     * Method warn. diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java index 04b92f209..b6ffb0c59 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigurationProvider.java @@ -35,13 +35,17 @@ import java.util.List;  import org.w3c.dom.Element;  import org.w3c.dom.Node; +import eu.stork.vidp.messages.common.STORKBootstrap; +  import at.gv.egovernment.moa.id.config.ConfigurationBuilder;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.config.ConfigurationProvider;  import at.gv.egovernment.moa.id.config.ConnectionParameter; +import at.gv.egovernment.moa.id.config.stork.STORKConfig;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.DOMUtils;  import at.gv.egovernment.moa.util.FileUtils; +import at.gv.egovernment.moa.util.StringUtils;  import at.gv.egovernment.moa.util.XPathUtils;  /** @@ -183,6 +187,11 @@ public class AuthConfigurationProvider extends ConfigurationProvider {     */    private List trustedBKUs; +  /** +   * Holds general information for STORK (e.g. C-PEPS connection parameter, SAML signing parameters, etc.) +   */ +  private STORKConfig storkConfig; +     /**     * Return the single instance of configuration data.     *  @@ -263,7 +272,12 @@ public class AuthConfigurationProvider extends ConfigurationProvider {  			} catch (MalformedURLException t) {  				throw new ConfigurationException("config.03", null, t);  		  } -		  		   + +		//Initialize OpenSAML for STORK +		Logger.trace("Starting initialization of OpenSAML..."); +		STORKBootstrap.bootstrap(); +		Logger.debug("OpenSAML successfully initialized"); +			          // build the internal datastructures      	builder = new ConfigurationBuilder(configElem, rootConfigFileDir);      	bKUConnectionParameter = builder.buildAuthBKUConnectionParameter(); @@ -293,6 +307,7 @@ public class AuthConfigurationProvider extends ConfigurationProvider {      	trustedCACertificates = builder.getTrustedCACertificates();      	trustedCACertificates = FileUtils.makeAbsoluteURL(trustedCACertificates, rootConfigFileDir);      	trustedBKUs = builder.getTrustedBKUs(); +    	storkConfig = new STORKConfig(builder.buildSTORKSignatureCreationParameter(),builder.buildSTORKSignatureVerificationParameter(), builder.buildSTORKcPEPSMap());      } catch (Throwable t) {        throw new ConfigurationException("config.02", null, t); @@ -370,6 +385,7 @@ public class AuthConfigurationProvider extends ConfigurationProvider {    	}      return null;    } +        /**     * Return a string with a url-reference to the VerifyAuthBlock trust  @@ -484,4 +500,14 @@ public class AuthConfigurationProvider extends ConfigurationProvider {      return defaultVerifyInfoboxParameters;    } +  /** +   * Retruns the STORK Configuration +   * @return STORK Configuration +   */ +  public STORKConfig getStorkConfig() { +		return storkConfig; +  } +	   +   +  }
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java index 2959d9208..091a01bf7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/OAAuthParameter.java @@ -24,7 +24,15 @@  package at.gv.egovernment.moa.id.config.auth; +import java.util.ArrayList; + +import org.opensaml.saml2.metadata.RequestedAttribute; +  import at.gv.egovernment.moa.id.config.OAParameter; +import eu.stork.vidp.messages.builder.STORKMessagesBuilder; +import eu.stork.vidp.messages.common.STORKConstants; +import eu.stork.vidp.messages.stork.QualityAuthenticationAssuranceLevel; +import eu.stork.vidp.messages.stork.RequestedAttributes;  /**   * Configuration parameters belonging to an online application, @@ -117,12 +125,28 @@ public class OAAuthParameter extends OAParameter {    private String mandateProfiles;    /** -   * BZ +   *      * Type for authentication number (e.g. Firmenbuchnummer)     */    private String identityLinkDomainIdentifierType;    /** +   * STORK QAA Level, Default = 4 +   */ +  private QualityAuthenticationAssuranceLevel qaaLevel = STORKMessagesBuilder.buildQualityAuthenticationAssuranceLevel(4); +   +  /** +   * STORK RequestedAttributes for Online Application +   * Default RequestedAttributes are: eIdentifier, givenName, surname, dateOfBirth  +   */ +  private RequestedAttributes requestedAttributes = STORKMessagesBuilder.buildRequestedAttributes( +		  STORKMessagesBuilder.buildRequestedAttribute(STORKConstants.STORK_ATTRIBUTE_EIDENTIFIER, true, null),  +		  STORKMessagesBuilder.buildRequestedAttribute(STORKConstants.STORK_ATTRIBUTE_GIVENNAME, true, null),  +		  STORKMessagesBuilder.buildRequestedAttribute(STORKConstants.STORK_ATTRIBUTE_SURNAME, true, null),  +		  STORKMessagesBuilder.buildRequestedAttribute(STORKConstants.STORK_ATTRIBUTE_DATEOFBIRTH, false, null)); +   +     +/**     * Returns <code>true</code> if the Security Layer version is version 1.2,     * otherwise <code>false</code>.     * @return <code>true</code> if the Security Layer version is version 1.2, @@ -441,4 +465,38 @@ public class OAAuthParameter extends OAParameter {  	  return this.mandateProfiles;    } +  	/** +  	 * Returns the defined STORK QAALevel +  	 * @return STORK QAALevel +  	 */ +	public QualityAuthenticationAssuranceLevel getQaaLevel() { +		return qaaLevel; +	} +	 +	/** +	 * Sets the STORK QAALevel +	 * @param qaaLevel +	 */ +	public void setQaaLevel(QualityAuthenticationAssuranceLevel qaaLevel) { +		this.qaaLevel = qaaLevel; +	} +	 +	/** +	 * Returns the desired STORK Requested Attributes +	 * @return STORK Requested Attributes +	 */ +	public RequestedAttributes getRequestedAttributes() { +		return requestedAttributes; +	} +	 +	/** +	 * Sets the desired STORK Requested Attributes +	 * @param requestedAttributes +	 */ +	public void setRequestedAttributes(RequestedAttributes requestedAttributes) { +		this.requestedAttributes = requestedAttributes; +	} +   +   +  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/CPEPS.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/CPEPS.java new file mode 100644 index 000000000..a5b160454 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/CPEPS.java @@ -0,0 +1,98 @@ +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.config.stork;
 +
 +import java.net.URL;
 +import java.util.ArrayList;
 +import java.util.List;
 +
 +import org.opensaml.saml2.metadata.RequestedAttribute;
 +
 +/**
 + * Encpasulates C-PEPS information according MOA configuration
 + * 
 + * @author bzwattendorfer
 + *
 + */
 +public class CPEPS {
 +	
 +	/**  Country Code of C-PEPS */
 +	private String countryCode;
 +	
 +	/**  URL of C-PEPS */
 +	private URL pepsURL;
 +	
 +	/** Specific attributes to be requested for this C-PEPS */
 +	private List<RequestedAttribute> countrySpecificRequestedAttributes = new ArrayList<RequestedAttribute>();
 +	
 +	/**
 +	 * Constructs a C-PEPS
 +	 * @param countryCode ISO Country Code of C-PEPS
 +	 * @param pepsURL URL of C-PEPS
 +	 */
 +	public CPEPS(String countryCode, URL pepsURL) {
 +		super();
 +		this.countryCode = countryCode;
 +		this.pepsURL = pepsURL;
 +	}
 +
 +	/**
 +	 * Gets the country code of this C-PEPS
 +	 * @return ISO country code
 +	 */
 +	public String getCountryCode() {
 +		return countryCode;
 +	}
 +
 +	/**
 +	 * Sets the country code of this C-PEPS
 +	 * @param countryCode ISO country code
 +	 */
 +	public void setCountryCode(String countryCode) {
 +		this.countryCode = countryCode;
 +	}
 +
 +	/**
 +	 * Gets the URL of this C-PEPS
 +	 * @return C-PEPS URL
 +	 */
 +	public URL getPepsURL() {
 +		return pepsURL;
 +	}
 +
 +	/**
 +	 * Sets the C-PEPS URL
 +	 * @param pepsURL C-PEPS URL
 +	 */
 +	public void setPepsURL(URL pepsURL) {
 +		this.pepsURL = pepsURL;
 +	}
 +
 +	/**
 +	 * Gets the country specific attributes of this C-PEPS
 +	 * @return List of country specific attributes
 +	 */
 +	public List<RequestedAttribute> getCountrySpecificRequestedAttributes() {
 +		return countrySpecificRequestedAttributes;
 +	}
 +
 +	/**
 +	 * Sets the country specific attributes
 +	 * @param countrySpecificRequestedAttributes List of country specific requested attributes
 +	 */
 +	public void setCountrySpecificRequestedAttributes(
 +			List<RequestedAttribute> countrySpecificRequestedAttributes) {
 +		this.countrySpecificRequestedAttributes = countrySpecificRequestedAttributes;
 +	}
 +	
 +	/**
 +	 * Adds a Requested attribute to the country specific attribute List
 +	 * @param countrySpecificRequestedAttribute Additional country specific requested attribute to add 
 +	 */
 +	public void addCountrySpecificRequestedAttribute(RequestedAttribute countrySpecificRequestedAttribute) {
 +		this.countrySpecificRequestedAttributes.add(countrySpecificRequestedAttribute);
 +	}
 +	
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java new file mode 100644 index 000000000..485a44421 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/STORKConfig.java @@ -0,0 +1,90 @@ +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.config.stork;
 +
 +import java.util.HashMap;
 +import java.util.Map;
 +
 +import at.gv.egovernment.moa.util.StringUtils;
 +
 +/**
 + * Encapsulates several STORK configuration parameters according MOA configuration
 + * 
 + * @author bzwattendorfer
 + *
 + */
 +public class STORKConfig {
 +	
 +	/** STORK SAML signature creation parameters */
 +	private SignatureCreationParameter signatureCreationParameter;
 +	
 +	/** STORK SAML signature verification parameters */
 +	private SignatureVerificationParameter signatureVerificationParameter;
 +	
 +	/** Map of supported C-PEPSs */
 +	private Map<String, CPEPS> cpepsMap = new HashMap<String, CPEPS>();
 +	
 +	
 +	/**
 +	 * Constructs a STORK Config object
 +	 * @param signatureCreationParameter STORK SAML Signature creation parameters
 +	 * @param signatureVerificationParameter STORK SAML Signature verification parameters
 +	 * @param cpepsMap Map of supported C-PEPS
 +	 */
 +	public STORKConfig(SignatureCreationParameter signatureCreationParameter,
 +			SignatureVerificationParameter signatureVerificationParameter,
 +			Map<String, CPEPS> cpepsMap) {
 +		super();
 +		this.signatureCreationParameter = signatureCreationParameter;
 +		this.signatureVerificationParameter = signatureVerificationParameter;
 +		this.cpepsMap = cpepsMap;
 +	}
 +
 +	public SignatureCreationParameter getSignatureCreationParameter() {
 +		return signatureCreationParameter;
 +	}
 +
 +	public void setSignatureCreationParameter(
 +			SignatureCreationParameter signatureCreationParameter) {
 +		this.signatureCreationParameter = signatureCreationParameter;
 +	}
 +
 +	public SignatureVerificationParameter getSignatureVerificationParameter() {
 +		return signatureVerificationParameter;
 +	}
 +
 +	public void setSignatureVerificationParameter(
 +			SignatureVerificationParameter signatureVerificationParameter) {
 +		this.signatureVerificationParameter = signatureVerificationParameter;
 +	}
 +
 +	public Map<String, CPEPS> getCpepsMap() {
 +		return cpepsMap;
 +	}
 +
 +	public void setCpepsMap(Map<String, CPEPS> cpepsMap) {
 +		this.cpepsMap = cpepsMap;
 +	}
 +	
 +	public boolean isSTORKAuthentication(String ccc) {
 +		  
 +		  if (StringUtils.isEmpty(ccc) || this.cpepsMap.isEmpty())
 +			  return false;
 +		   		 
 +		  if (this.cpepsMap.containsKey(ccc.toUpperCase()))
 +			  return true;
 +		  else
 +			  return false;
 +			  
 +	}
 +	
 +	public CPEPS getCPEPS(String ccc) {
 +		if (isSTORKAuthentication(ccc))
 +			return this.cpepsMap.get(ccc);
 +		else
 +			return null;
 +	}
 +	
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/SignatureCreationParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/SignatureCreationParameter.java new file mode 100644 index 000000000..1f66b7752 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/SignatureCreationParameter.java @@ -0,0 +1,112 @@ +/*
 + * Copyright 2003 Federal Chancellery Austria
 + * MOA-ID has been developed in a cooperation between BRZ, the Federal
 + * Chancellery Austria - ICT staff unit, and Graz University of Technology.
 + *
 + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
 + * the European Commission - subsequent versions of the EUPL (the "Licence");
 + * You may not use this work except in compliance with the Licence.
 + * You may obtain a copy of the Licence at:
 + * http://www.osor.eu/eupl/
 + *
 + * Unless required by applicable law or agreed to in writing, software
 + * distributed under the Licence is distributed on an "AS IS" basis,
 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 + * See the Licence for the specific language governing permissions and
 + * limitations under the Licence.
 + *
 + * This product combines work with different licenses. See the "NOTICE" text
 + * file for details on the various modules and licenses.
 + * The "NOTICE" text file is part of the distribution. Any derivative works
 + * that you distribute must include a readable copy of the "NOTICE" text file.
 + */
 +
 +package at.gv.egovernment.moa.id.config.stork;
 +
 +/**
 + * Encapsulates signature creation parameters according MOA configuration
 + * 
 + * @author bzwattendorfer
 + *
 + */
 +public class SignatureCreationParameter {
 +	
 +	/** KeyStore Path */
 +	private String keyStorePath;
 +	
 +	/** KeyStore Password */
 +	private String keyStorePassword;
 +	
 +	/** Signing Key Name */
 +	private String keyName;
 +	
 +	/** Signing Key Password */
 +	private String keyPassword;
 +
 +	/**
 +	 * Gets the KeyStore Path
 +	 * @return File Path to KeyStore
 +	 */
 +	public String getKeyStorePath() {
 +		return keyStorePath;
 +	}
 +
 +	/**
 +	 * Sets the KeyStore Path
 +	 * @param keyStorePath Path to KeyStore
 +	 */
 +	public void setKeyStorePath(String keyStorePath) {
 +		this.keyStorePath = keyStorePath;
 +	}
 +
 +	/**
 +	 * Gets the KeyStore Password
 +	 * @return Password to KeyStore
 +	 */
 +	public String getKeyStorePassword() {
 +		return keyStorePassword;
 +	}
 +
 +	/**
 +	 * Sets the KeyStore Password
 +	 * @param keyStorePassword Password to KeyStore
 +	 */
 +	public void setKeyStorePassword(String keyStorePassword) {
 +		this.keyStorePassword = keyStorePassword;
 +	}
 +
 +	/**
 +	 * Gets the Signing Key Name
 +	 * @return Siging Key Name
 +	 */
 +	public String getKeyName() {
 +		return keyName;
 +	}
 +
 +	/**
 +	 * Sets the Signing Key Name
 +	 * @param keyName Signing Key Name
 +	 */
 +	public void setKeyName(String keyName) {
 +		this.keyName = keyName;
 +	}
 +
 +	/**
 +	 * Gets the Signing Key Password
 +	 * @return Signing Key Password
 +	 */
 +	public String getKeyPassword() {
 +		return keyPassword;
 +	}
 +
 +	/**
 +	 * Sets the Signing Key Password
 +	 * @param keyPassword Signing Key Password
 +	 */
 +	public void setKeyPassword(String keyPassword) {
 +		this.keyPassword = keyPassword;
 +	}
 +	
 +	
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/SignatureVerificationParameter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/SignatureVerificationParameter.java new file mode 100644 index 000000000..2d8402e4d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/stork/SignatureVerificationParameter.java @@ -0,0 +1,35 @@ +/**
 + * 
 + */
 +package at.gv.egovernment.moa.id.config.stork;
 +
 +/**
 + * Encapsulates Signature Verification data for STORK according MOA configuration
 + * 
 + * @author bzwattendorfer
 + *
 + */
 +public class SignatureVerificationParameter {
 +	
 +	/** ID of the MOA-SP TrustProfile to be used for STORK SAML signature verification */
 +	private String trustProfileID;
 +
 +	/**
 +	 * Gets the MOA-SP TrustProfileID
 +	 * @return TrustProfileID of MOA-SP for STORK signature verification
 +	 */
 +	public String getTrustProfileID() {
 +		return trustProfileID;
 +	}
 +
 +	/**
 +	 * Sets the MOA-SP TrustProfileID
 +	 * @param trustProfileID TrustProfileID of MOA-SP for STORK signature verification
 +	 */
 +	public void setTrustProfileID(String trustProfileID) {
 +		this.trustProfileID = trustProfileID;
 +	}
 +	
 +	
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java index 7b29051f3..a148aa690 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/HTTPUtils.java @@ -40,9 +40,13 @@ import java.io.Reader;  import java.net.HttpURLConnection;  import java.net.URL; +import javax.servlet.http.HttpServletRequest; +  import org.apache.regexp.RE;  import org.apache.regexp.RESyntaxException; +import at.gv.egovernment.moa.util.StringUtils; +  /**   *    * @author Rudolf Schamberger @@ -88,5 +92,47 @@ public class HTTPUtils {      conn.disconnect();      return buffer.toString();    } +   +  	/** +  	 * Helper method to retrieve server URL including context path +  	 * @param request HttpServletRequest +  	 * @return Server URL including context path (e.g. http://localhost:8443/moa-id-auth +  	 */ +  	public static String getBaseURL(HttpServletRequest request) { +		StringBuffer buffer = new StringBuffer(getServerURL(request)); +		 +	    // add context path if available +	    String contextPath = request.getContextPath(); +	    if (!StringUtils.isEmpty(contextPath)) { +	    	buffer.append(contextPath); +	    } +		 +		return buffer.toString();  +	} +	 +  	/** +  	 * Helper method to retrieve server URL +  	 * @param request HttpServletRequest +  	 * @return Server URL (e.g. http://localhost:8443) +  	 */ +	public static String getServerURL(HttpServletRequest request) { +		StringBuffer buffer = new StringBuffer(); +		 +		// get protocol +		String protocol = request.getScheme(); +		buffer.append(protocol).append("://"); +		 +		// server name +		buffer.append(request.getServerName()); +		 +		// add port if necessary +		int port = request.getServerPort(); +	    if ((protocol.equals("http") && port != 80) || (protocol.equals("https") && port != 443)) { +	    	buffer.append(':'); +	    	buffer.append(port); +	    } +	 +	    return buffer.toString();  +	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java index 790651adf..0862371dd 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ParamValidatorUtils.java @@ -43,6 +43,7 @@ import org.xml.sax.SAXException;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.StringUtils;  public class ParamValidatorUtils {
 @@ -54,10 +55,10 @@ public class ParamValidatorUtils {      */
     public static boolean isValidTarget(String target) {
 -	   Logger.debug("Überprüfe Parameter Target");
 +	   Logger.debug("�berpr�fe Parameter Target");
        // if non parameter is given return true
 -      if (target == null) {
 +      if (StringUtils.isEmpty(target)) {
      	  Logger.debug("Parameter Target ist null");
      	  return true;
        }
 @@ -67,27 +68,57 @@ public class ParamValidatorUtils {        Matcher matcher = pattern.matcher(target);
        boolean b = matcher.matches();
        if (b) {
 -    	Logger.debug("Parameter Target erfolgreich überprüft");
 +    	Logger.debug("Parameter Target erfolgreich �berpr�ft");
      	return true;
        }
        else {
 -    	  Logger.error("Fehler Überprüfung Parameter Target. Target entspricht nicht den Kriterien (nur Zeichen a-z, A-Z und -, sowie 1-5 Zeichen lang)");
 +    	  Logger.error("Fehler �berpr�fung Parameter Target. Target entspricht nicht den Kriterien (nur Zeichen a-z, A-Z und -, sowie 1-5 Zeichen lang)");
      	  return false;  
        }
     }     /** +    * Checks if the given ccc parameter is valid +    * @param ccc HTTP parameter from request +    * @return true if ccc is valid +    */ +   public static boolean isValidCCC(String ccc) { +    +	   Logger.debug("�berpr�fe Parameter CCC"); +	    +      // if non parameter is given return true +      if (StringUtils.isEmpty(ccc)) { +    	  Logger.debug("Parameter CCC ist null"); +    	  return true; +      } +          +       +      Pattern pattern = Pattern.compile("[a-zA-Z]{2}"); +      Matcher matcher = pattern.matcher(ccc); +      boolean b = matcher.matches(); +      if (b) { +    	Logger.debug("Parameter CCC erfolgreich �berpr�ft"); +    	return true; +      } +      else { +    	  Logger.error("Fehler �berpr�fung Parameter CCC. CCC entspricht nicht den Kriterien (nur Zeichen a-z, A-Z, sowie 2 Zeichen lang)"); +    	  return false;   +      } +             +   } +    +   /**      * Checks if the given target is valid      * @param sourceID HTTP parameter from request      * @return       */     public static boolean isValidSourceID(String sourceID) { -	   Logger.debug("Überprüfe Parameter sourceID"); +	   Logger.debug("�berpr�fe Parameter sourceID");        // if non parameter is given return true -      if (sourceID == null) { +      if (StringUtils.isEmpty(sourceID)) {      	  Logger.debug("Parameter Target ist null");      	  return true;        } @@ -97,11 +128,11 @@ public class ParamValidatorUtils {        Matcher matcher = pattern.matcher(sourceID);        boolean b = matcher.matches();        if (b) { -    	Logger.debug("Parameter sourceID erfolgreich überprüft"); +    	Logger.debug("Parameter sourceID erfolgreich �berpr�ft");      	return true;        }        else { -    	  Logger.error("Fehler Überprüfung Parameter sourceID. SourceID entspricht nicht den Kriterien (nur Zeichen a-z, A-Z, - und _, sowie 1-20 Zeichen lang)"); +    	  Logger.error("Fehler �berpr�fung Parameter sourceID. SourceID entspricht nicht den Kriterien (nur Zeichen a-z, A-Z, - und _, sowie 1-20 Zeichen lang)");      	  return false;          } @@ -114,21 +145,21 @@ public class ParamValidatorUtils {      */
     public static boolean isValidUseMandate(String usemandate) {
 -	   Logger.debug("Überprüfe Parameter useMandate");
 +	   Logger.debug("�berpr�fe Parameter useMandate");
        // if non parameter is given return true
 -      if (usemandate== null) {
 +      if (StringUtils.isEmpty(usemandate)) {
      	  Logger.debug("Parameter useMandate ist null");
      	  return true;
        }
        if (usemandate.compareToIgnoreCase("true") == 0 || usemandate.compareToIgnoreCase("false") == 0) {
 -    	  Logger.debug("Parameter useMandate erfolgreich überprüft");
 +    	  Logger.debug("Parameter useMandate erfolgreich �berpr�ft");
      	  return true;
        }
        else {
 -    	  Logger.error("Fehler Überprüfung Parameter useMandate. useMandate ist weder 'true' noch 'false')");
 +    	  Logger.error("Fehler �berpr�fung Parameter useMandate. useMandate ist weder 'true' noch 'false')");
      	  return false;
        }
 @@ -144,10 +175,10 @@ public class ParamValidatorUtils {      * @return 
      */
     public static boolean isValidBKUURI(String bkuURI) {
 -	   Logger.debug("Überprüfe Parameter bkuURI"); +	   Logger.debug("�berpr�fe Parameter bkuURI");  	   // if non parameter is given return true
 -	      if (bkuURI == null) {
 +	      if (StringUtils.isEmpty(bkuURI)) {
  	    	 Logger.debug("Parameter bkuURI ist null");
  	         return true;
  	      }
 @@ -163,20 +194,20 @@ public class ParamValidatorUtils {  	    			  bkuURI.compareToIgnoreCase("http://localhost:3495/http-security-layer-request") == 0 ||  	    			  bkuURI.compareToIgnoreCase("http://127.0.0.1:3495/http-security-layer-request") == 0 ||  	    			  bkuURI.compareToIgnoreCase("https://127.0.0.1:3496/https-security-layer-request") == 0) {
 -	    			  Logger.debug("Parameter bkuURI erfolgreich überprüft");
 +	    			  Logger.debug("Parameter bkuURI erfolgreich �berpr�ft");
  	    			  return true;
  	    		  }
  	    		  else {
 -	    			  Logger.debug("Parameter bkuURI ist keine lokale BKU. Überprüfe Liste der vertrauenswürdigen BKUs.");
 +	    			  Logger.debug("Parameter bkuURI ist keine lokale BKU. �berpr�fe Liste der vertrauensw�rdigen BKUs.");
  	    			  AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
  		    		  List trustedBKUs = authConf.getTrustedBKUs();
  		    		  boolean b = trustedBKUs.contains(bkuURI);
  		    		  if (b) {
 -		    			  Logger.debug("Parameter bkuURI erfolgreich überprüft");
 +		    			  Logger.debug("Parameter bkuURI erfolgreich �berpr�ft");
  		    			  return true;
  		    		  }
  		    		  else {
 -		    			  Logger.error("Fehler Überprüfung Parameter bkuURI. bkuURI ist nicht auf Liste der vertrauenswürdigen BKUs (Konfigurationselement: MOA-IDConfiguration/TrustedBKUs)");  
 +		    			  Logger.error("Fehler �berpr�fung Parameter bkuURI. bkuURI ist nicht auf Liste der vertrauensw�rdigen BKUs (Konfigurationselement: MOA-IDConfiguration/TrustedBKUs)");  
  		    			  return false;
  		    		  }  
  	    		  }
 @@ -184,16 +215,16 @@ public class ParamValidatorUtils {  	    	  }
  	    	  else {
 -	    		  Logger.error("Fehler Überprüfung Parameter bkuURI. bkuURI beginnt nicht mit http or https");
 +	    		  Logger.error("Fehler �berpr�fung Parameter bkuURI. bkuURI beginnt nicht mit http or https");
  	    		  return false;
  	    	  }
  	      } catch (MalformedURLException e) {
 -	    	  Logger.error("Fehler Überprüfung Parameter bkuURI", e);
 +	    	  Logger.error("Fehler �berpr�fung Parameter bkuURI", e);
  	         return false;
  	      } catch (ConfigurationException e) {
 -	    	  Logger.error("Fehler Überprüfung Parameter bkuURI", e);
 +	    	  Logger.error("Fehler �berpr�fung Parameter bkuURI", e);
  	    	  return false;
  		}
     }
 @@ -243,7 +274,7 @@ public class ParamValidatorUtils {  //			    	
  //			    	System.out.println("ret: " + ret);
  //			    	
 -//			    	Logger.error("Fehler Überprüfung Parameter bkuURI. Antwortcode von BKU ist nicht 200.");
 +//			    	Logger.error("Fehler �berpr�fung Parameter bkuURI. Antwortcode von BKU ist nicht 200.");
  //			    	return false;
  //			    }
  //		      
 @@ -257,26 +288,26 @@ public class ParamValidatorUtils {  //			    
  ////			    NodeList l = doc.getElementsByTagNameNS(Constants.SL12_NS_URI, "ErrorResponse");		    	
  ////		    	if (l.getLength() != 0) {
 -////		    		Logger.error("Fehler Überprüfung Parameter bkuURI. ErrorResponse von BKU empfangen.");
 +////		    		Logger.error("Fehler �berpr�fung Parameter bkuURI. ErrorResponse von BKU empfangen.");
  ////		    		return false;			    	
  ////		    	}
  //		    	
 -//		    	Logger.debug("Parameter Template bkuURI erfolgreich überprüft");
 +//		    	Logger.debug("Parameter Template bkuURI erfolgreich �berpr�ft");
  //			    return true;
  //			    
  ////		   } catch (SAXException e) {
 -////				Logger.error("Fehler Überprüfung Parameter bkuURI.", e);
 +////				Logger.error("Fehler �berpr�fung Parameter bkuURI.", e);
  ////				return false;
  //			} catch (IOException e) {
 -//				Logger.error("Fehler Überprüfung Parameter bkuURI.", e);
 +//				Logger.error("Fehler �berpr�fung Parameter bkuURI.", e);
  //				return false;
  //			} catch (ParserConfigurationException e) {
 -//				Logger.error("Fehler Überprüfung Parameter bkuURI.", e);
 +//				Logger.error("Fehler �berpr�fung Parameter bkuURI.", e);
  //				return false;
  //			}
  //		}
  //	   else {
 -//		   Logger.error("Fehler Überprüfung Parameter bkuURI. bkuURI ist null.");
 +//		   Logger.error("Fehler �berpr�fung Parameter bkuURI. bkuURI ist null.");
  //		   return false;
  //	   }
  //		    
 @@ -313,10 +344,10 @@ public class ParamValidatorUtils {      */
     public static boolean isValidTemplate(HttpServletRequest req, String template) {
 -	   Logger.debug("Überprüfe Parameter Template bzw. bkuSelectionTemplateURL");
 +	   Logger.debug("�berpr�fe Parameter Template bzw. bkuSelectionTemplateURL");
        // if non parameter is given return true
 -      if (template == null) {
 +      if (StringUtils.isEmpty(template)) {
      	  Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL ist null");
      	  return true;
        }
 @@ -334,37 +365,37 @@ public class ParamValidatorUtils {      		  if (template.startsWith(httpName) || template.startsWith(httpsName)) {
      			 new URL(template);
 -    			 Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL erfolgreich überprüft");
 +    			 Logger.debug("Parameter Template bzw. bkuSelectionTemplateURL erfolgreich �berpr�ft");
       	         return true;
      		  }
      		  else {
 -    			  Logger.error("Fehler Überprüfung Parameter Template bzw. bkuSelectionTemplateURL. Parameter liegt nicht am gleichen Server wie die MOA-Instanz (" + req.getServerName() + ")");
 +    			  Logger.error("Fehler �berpr�fung Parameter Template bzw. bkuSelectionTemplateURL. Parameter liegt nicht am gleichen Server wie die MOA-Instanz (" + req.getServerName() + ")");
      			  return false;
      		  }
      	  }
      	  else {
 -    		  Logger.error("Fehler Überprüfung Parameter Template bzw. bkuSelectionTemplateURL. Paramter beginnt nicht mit http oder https.");
 +    		  Logger.error("Fehler �berpr�fung Parameter Template bzw. bkuSelectionTemplateURL. Paramter beginnt nicht mit http oder https.");
      		  return false;
      	  }
        } catch (MalformedURLException e) {
 -    	 Logger.error("Fehler Überprüfung Parameter Template bzw. bkuSelectionTemplateURL.", e);
 +    	 Logger.error("Fehler �berpr�fung Parameter Template bzw. bkuSelectionTemplateURL.", e);
           return false;
        }
     }
     /**
 -    * Checks if the given template is valid
 +    * Checks if the given sessionID is valid
      * @param target HTTP parameter from request
      * @return 
      */
     public static boolean isValidSessionID(String sessionID) {
 -	   Logger.debug("Überprüfe Parameter MOASessionId");
 +	   Logger.debug("�berpr�fe Parameter MOASessionId");
        // if non parameter is given return true
 -      if (sessionID == null) {
 +      if (StringUtils.isEmpty(sessionID)) {
      	  Logger.debug("Parameter MOASessionId ist null");
      	  return true; 
        }
 @@ -374,11 +405,11 @@ public class ParamValidatorUtils {        Matcher matcher = pattern.matcher(sessionID);
        boolean b = matcher.matches();
        if (b) {
 -    	  Logger.debug("Parameter MOASessionId erfolgreich überprüft");
 +    	  Logger.debug("Parameter MOASessionId erfolgreich �berpr�ft");
      	  return true;
        }
        else {
 -    	  Logger.error("Fehler Überprüfung Parameter MOASessionId. MOASessionId entspricht nicht den Kriterien (nur Zeichen 0-9 und -)");
 +    	  Logger.error("Fehler �berpr�fung Parameter MOASessionId. MOASessionId entspricht nicht den Kriterien (nur Zeichen 0-9 und -)");
      	  return false;
        }
 @@ -394,9 +425,9 @@ public class ParamValidatorUtils {      * @return 
      */
     public static boolean isValidOA(String oa) {
 -	   Logger.debug("Überprüfe Parameter oa");
 +	   Logger.debug("�berpr�fe Parameter oa");
  	   // if non parameter is given return true
 -	   if (oa == null) {
 +	   if (StringUtils.isEmpty(oa)) {
  		   Logger.debug("Parameter oa ist null");
  		   return true;
  	   }
 @@ -407,16 +438,16 @@ public class ParamValidatorUtils {  		   // check if template url starts with http or https 
  		   if (oa.startsWith("http") || oa.startsWith("https")) {
  			   new URL(oa);
 -			   Logger.debug("Parameter oa erfolgreich überprüft");
 +			   Logger.debug("Parameter oa erfolgreich �berpr�ft");
  			   return true;	    		  
  	    	  }
  	    	  else  {
 -	    		  Logger.error("Fehler Überprüfung Parameter oa. oa beginnt nicht mit http or https");
 +	    		  Logger.error("Fehler �berpr�fung Parameter oa. oa beginnt nicht mit http or https");
  	    		  return false;    	  
  	    	  }
  	      } catch (MalformedURLException e) {
 -	    	  Logger.error("Fehler Überprüfung Parameter oa", e);
 +	    	  Logger.error("Fehler �berpr�fung Parameter oa", e);
  	         return false;
  	      }
 @@ -429,10 +460,10 @@ public class ParamValidatorUtils {      */
     public static boolean isValidSignUrl(String signurl) {
 -	   Logger.debug("Überprüfe Parameter signurl");
 +	   Logger.debug("�berpr�fe Parameter signurl");
  	   // if non parameter is given return true
 -	   if (signurl == null) {
 +	   if (StringUtils.isEmpty(signurl)) {
  		   Logger.debug("Parameter signurl ist null");
  		   return true;
  	   }
 @@ -443,16 +474,16 @@ public class ParamValidatorUtils {  		   // check if signurl starts with http or https 
  		   if (signurl.startsWith("http") || signurl.startsWith("https")) {
  			   new URL(signurl);
 -			   Logger.debug("Parameter signurl erfolgreich überprüft");
 +			   Logger.debug("Parameter signurl erfolgreich �berpr�ft");
  			   return true;	    		  
  	    	  }
  	    	  else {
 -	    		  Logger.error("Fehler Überprüfung Parameter signurl. signurl beginnt nicht mit http or https");
 +	    		  Logger.error("Fehler �berpr�fung Parameter signurl. signurl beginnt nicht mit http or https");
  	    		  return false;
  	    	  }	    	  
  	      } catch (MalformedURLException e) {
 -	    	  Logger.error("Fehler Überprüfung Parameter signurl", e);
 +	    	  Logger.error("Fehler �berpr�fung Parameter signurl", e);
  	         return false;
  	      }
 @@ -508,27 +539,27 @@ public class ParamValidatorUtils {     public static boolean isValidXMLDocument(String document) {
 -	   if (document == null)
 +	   if (StringUtils.isEmpty(document))
  		   return false;
 -	   Logger.debug("Überprüfe Parameter XMLDocument");
 +	   Logger.debug("Überprüfe Parameter XMLDocument");
  	   try {   
  		   DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
  		   DocumentBuilder builder = factory.newDocumentBuilder();
  		   InputSource is = new InputSource(new StringReader(document));
  		   builder.parse(is);
 -		   Logger.debug("Parameter XMLDocument erfolgreich überprüft");
 +		   Logger.debug("Parameter XMLDocument erfolgreich überprüft");
  		   return true;
  	   } catch (ParserConfigurationException e) {
 -		   Logger.error("Fehler Überprüfung Parameter XMLDocument", e);
 +		   Logger.error("Fehler Überprüfung Parameter XMLDocument", e);
  		   return false;
  	   } catch (SAXException e) {
 -		   Logger.error("Fehler Überprüfung Parameter XMLDocument", e);
 +		   Logger.error("Fehler Überprüfung Parameter XMLDocument", e);
  		   return false;
  	   } catch (IOException e) {
 -		   Logger.error("Fehler Überprüfung Parameter XMLDocument", e);
 +		   Logger.error("Fehler Überprüfung Parameter XMLDocument", e);
  		   return false;
  	   }	
 diff --git a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties index db6fbe990..8089b851c 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/id_messages_de.properties @@ -173,3 +173,14 @@ validator.65=Es ist ein Fehler bei der Formulargenerierung für berufliche Partei  validator.66=Überprüfung der {0}-Infobox fehlgeschlagen: berufliche Parteienvetretung ist nicht konfiguriert.
  ssl.01=Validierung des SSL-Server-Endzertifikates hat fehlgeschlagen
 +
 +stork.00=STORK SAML AuthnRequest konnte nicht signiert werden
 +stork.01=STORK SAML AuthnRequest nicht gültig
 +stork.02=STORK SAML AuthnRequest kann nicht an folgende URL geschickt werden: {0}
 +stork.04=STORK SAML Response konnte nicht decodiert werden
 +stork.05=STORK SAML Response Validierung fehlgeschlagen
 +stork.06=STORK SAML Response enthält eine Fehlermeldung: {0}
 +stork.07=Es existiert kein STORK AuthnRequest für diese STORK Response
 +stork.08=STORK SAML Assertion Validierung fehlgeschlagen
 +stork.09=Fehler beim Überprüfen der STORK BürgerInnen Signatur
 +stork.10=Fehler in der Verbindung zum SZR-Gateway
 | 
