diff options
| author | Thomas Lenz <tlenz@iaik.tugraz.at> | 2018-05-30 14:36:39 +0200 | 
|---|---|---|
| committer | Thomas Lenz <tlenz@iaik.tugraz.at> | 2018-05-30 14:36:39 +0200 | 
| commit | ecf9de84e76dde785ced8c1632c7909d1d57f94a (patch) | |
| tree | ef32ed58461f520a790f53f1a049e566458482a0 /id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv | |
| parent | 52ad604e54cb91073503d708cd0c50ff0121174a (diff) | |
| download | moa-id-spss-ecf9de84e76dde785ced8c1632c7909d1d57f94a.tar.gz moa-id-spss-ecf9de84e76dde785ced8c1632c7909d1d57f94a.tar.bz2 moa-id-spss-ecf9de84e76dde785ced8c1632c7909d1d57f94a.zip | |
add error handling and some more validation to SL2.0 module
Diffstat (limited to 'id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv')
10 files changed, 529 insertions, 198 deletions
| diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java index 920187bfb..a3648220d 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/Constants.java @@ -3,6 +3,7 @@ package at.gv.egovernment.moa.id.auth.modules.sl20_auth;  public class Constants {  	public static final String HTTP_ENDPOINT_DATAURL = "/sl20/dataUrl"; +	public static final String HTTP_ENDPOINT_RESUME = "/sl20/resume";  	public static final String CONFIG_PROP_PREFIX = "modules.sl20";  	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT = CONFIG_PROP_PREFIX + ".vda.urls.qualeID.endpoint"; @@ -17,6 +18,9 @@ public class Constants {  	public static final String CONFIG_PROP_VDA_ENDPOINT_QUALeID_LIST = CONFIG_PROP_VDA_ENDPOINT_QUALeID_DEFAULT + ".";  	public static final String CONFIG_PROP_SP_LIST = CONFIG_PROP_PREFIX + ".sp.entityIds."; +	public static final String CONFIG_PROP_DISABLE_EID_VALIDATION = CONFIG_PROP_PREFIX + ".security.eID.validation.disable"; +	public static final String CONFIG_PROP_DISABLE_EID_ENCRYPTION = CONFIG_PROP_PREFIX + ".security.eID.encryption.enabled"; +	  	public static final String PENDING_REQ_STORAGE_PREFIX = "SL20_AUTH_";  	/** diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java index 87d306822..4f8ef0a76 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/SL20SignalServlet.java @@ -44,11 +44,14 @@ public class SL20SignalServlet extends AbstractProcessEngineSignalController {  	public SL20SignalServlet() {  		super();  		Logger.debug("Registering servlet " + getClass().getName() +  -				" with mappings '"+ Constants.HTTP_ENDPOINT_DATAURL + "'."); +				" with mappings '"+ Constants.HTTP_ENDPOINT_DATAURL +  +				" and " + Constants.HTTP_ENDPOINT_RESUME +  +				"'.");  	} -	@RequestMapping(value = { Constants.HTTP_ENDPOINT_DATAURL 							   +	@RequestMapping(value = { Constants.HTTP_ENDPOINT_DATAURL, +							  Constants.HTTP_ENDPOINT_RESUME  							},   					method = {RequestMethod.POST, RequestMethod.GET})  	public void performCitizenCardAuthentication(HttpServletRequest req, HttpServletResponse resp) throws IOException { diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java new file mode 100644 index 000000000..957ace0fb --- /dev/null +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/exceptions/SL20eIDDataValidationException.java @@ -0,0 +1,16 @@ +package at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions; + +public class SL20eIDDataValidationException extends SL20Exception { +	private static final long serialVersionUID = 1L; + +	public SL20eIDDataValidationException(Object[] parameters) { +		super("sl20.07", parameters); +		 +	} +	 +	public SL20eIDDataValidationException(Object[] parameters, Throwable e) { +		super("sl20.07", parameters, e); +		 +	} + +} diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java index d00ef8a04..2563c7f7d 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/JsonSecurityUtils.java @@ -105,7 +105,7 @@ public class JsonSecurityUtils implements IJOSETools{  				}  			} -			 +  			//some short validation  			if (signPrivKey == null || !(signPrivKey instanceof PrivateKey)) {  				Logger.info("Can NOT open privateKey for SL2.0 signing. KeyStore=" + getKeyStoreFilePath()); diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java index b855c3cac..33bb4fe36 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20Constants.java @@ -12,6 +12,8 @@ public class SL20Constants {  	//http binding parameters  	public static final String PARAM_SL20_REQ_COMMAND_PARAM = "slcommand"; +	public static final String PARAM_SL20_REQ_COMMAND_PARAM_OLD = "sl2command"; +	  	public static final String PARAM_SL20_REQ_ICP_RETURN_URL_PARAM = "slIPCReturnUrl";  	public static final String PARAM_SL20_REQ_TRANSACTIONID = "slTransactionID"; diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java index e01945df0..6949b7a18 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/SL20JSONExtractorUtils.java @@ -9,6 +9,7 @@ import java.util.Map;  import java.util.Map.Entry;  import org.apache.http.Header; +import org.apache.http.HttpEntity;  import org.apache.http.HttpResponse;  import org.apache.http.client.utils.URIBuilder;  import org.apache.log4j.Logger; @@ -163,19 +164,23 @@ public class SL20JSONExtractorUtils {  			return result;  		else if (encryptedResult != null && encryptedResult.isJsonPrimitive()) { -			/*TODO: -			 *  -			 * Remove dummy code and test real decryption!!!!! -			 *  -			 */			 - -			//return decrypter.decryptPayload(encryptedResult.getAsString()); +			try { +				return decrypter.decryptPayload(encryptedResult.getAsString()); +				 +			} catch (Exception e) { +				log.info("Can NOT decrypt SL20 result. Reason:" + e.getMessage()); +				if (!mustBeEncrypted) { +					log.warn("Decrypted results are disabled by configuration. Parse result in plain if it is possible"); -			//dummy code -			String[] signedPayload = encryptedResult.toString().split("\\."); -			JsonElement payLoad = new JsonParser().parse(new String(Base64.getUrlDecoder().decode(signedPayload[1]))); -			return payLoad; -			 +					//dummy code +					String[] signedPayload = encryptedResult.toString().split("\\."); +					JsonElement payLoad = new JsonParser().parse(new String(Base64.getUrlDecoder().decode(signedPayload[1]))); +					return payLoad; +					 +				} else +					throw e;	 +				 +			}  		} else  			throw new SLCommandoParserException("Internal build error"); @@ -241,13 +246,21 @@ public class SL20JSONExtractorUtils {  			} else if (httpResp.getStatusLine().getStatusCode() == 200) {  				if (!httpResp.getEntity().getContentType().getValue().equals("application/json;charset=UTF-8")) -					throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue()); -					 -				sl20Resp = new JsonParser().parse(new InputStreamReader(httpResp.getEntity().getContent())).getAsJsonObject(); +					throw new SLCommandoParserException("SL20 response with a wrong ContentType: " + httpResp.getEntity().getContentType().getValue());					 +				sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); +			} else if ( (httpResp.getStatusLine().getStatusCode() == 500) ||  +					(httpResp.getStatusLine().getStatusCode() == 401) ||  +					(httpResp.getStatusLine().getStatusCode() == 400) ) { +				log.info("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()  +						+ ". Search for error message");				 +				sl20Resp = parseSL20ResultFromResponse(httpResp.getEntity()); +				 +				  			} else  				throw new SLCommandoParserException("SL20 response with http-code: " + httpResp.getStatusLine().getStatusCode()); -				 + +			log.info("Find JSON object in http response");  			return sl20Resp;  		} catch (Exception e) { @@ -256,6 +269,22 @@ public class SL20JSONExtractorUtils {  		}		  	} +	private static JsonObject parseSL20ResultFromResponse(HttpEntity resp) throws Exception { +		if (resp != null && resp.getContent() != null) {			 +			JsonElement sl20Resp = new JsonParser().parse(new InputStreamReader(resp.getContent())); +			if (sl20Resp != null && sl20Resp.isJsonObject()) { +				return sl20Resp.getAsJsonObject(); +				 +			} else +				throw new SLCommandoParserException("SL2.0 can NOT parse to a JSON object"); +			 +			 +		} else +			throw new SLCommandoParserException("Can NOT find content in http response"); + 					 +	} +	 +	  	private static JsonElement getAndCheck(JsonObject input, String keyID, boolean isRequired) throws SLCommandoParserException {  		JsonElement internal = input.get(keyID); diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java index 7d03a43ac..d07d7a78a 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/sl20/verifier/QualifiedeIDVerifier.java @@ -1,24 +1,17 @@  package at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.verifier;  import java.io.IOException; -import java.util.Calendar;  import java.util.Date; -import java.util.GregorianCalendar;  import java.util.List; -import javax.xml.bind.DatatypeConverter; -import javax.xml.transform.TransformerException; -  import org.jaxen.SimpleNamespaceContext;  import org.w3c.dom.Element;  import at.gv.egovernment.moa.id.auth.builder.SignatureVerificationUtils; -import at.gv.egovernment.moa.id.auth.data.CreateXMLSignatureResponse; -import at.gv.egovernment.moa.id.auth.exception.BuildException; -import at.gv.egovernment.moa.id.auth.exception.ParseException; -import at.gv.egovernment.moa.id.auth.exception.ServiceException;  import at.gv.egovernment.moa.id.auth.exception.ValidateException;  import at.gv.egovernment.moa.id.auth.invoke.SignatureVerificationInvoker; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20eIDDataValidationException; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;  import at.gv.egovernment.moa.id.auth.parser.VerifyXMLSignatureResponseParser;  import at.gv.egovernment.moa.id.auth.validator.IdentityLinkValidator;  import at.gv.egovernment.moa.id.auth.validator.VerifyXMLSignatureRequestBuilder; @@ -27,13 +20,12 @@ import at.gv.egovernment.moa.id.commons.api.AuthConfiguration;  import at.gv.egovernment.moa.id.commons.api.IOAAuthParameters;  import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;  import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse; -import at.gv.egovernment.moa.id.commons.api.exceptions.ConfigurationException;  import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;  import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.spss.api.impl.VerifyXMLSignatureRequestImpl; +import at.gv.egovernment.moa.sig.tsl.utils.MiscUtil; +import at.gv.egovernment.moa.util.Base64Utils;  import at.gv.egovernment.moa.util.Constants; -import at.gv.egovernment.moa.util.DOMUtils; -import at.gv.egovernment.moa.util.XPathUtils;  public class QualifiedeIDVerifier { @@ -57,7 +49,7 @@ public class QualifiedeIDVerifier {  	    NS_CONTEXT.addNamespace(Constants.XADES_1_4_1_NS_PREFIX, Constants.XADES_1_4_1_NS_URI);  	  } -	public static boolean verifyIdentityLink(IIdentityLink idl, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException {		 +	public static void verifyIdentityLink(IIdentityLink idl, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException {		  		// validates the identity link  		IdentityLinkValidator.getInstance().validate(idl); @@ -79,17 +71,15 @@ public class QualifiedeIDVerifier {  			VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK,  			oaParam); -		 -		return false; -		 +				  	} -	public static IVerifiyXMLSignatureResponse verifyAuthBlock(byte[] authblock, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException { +	public static IVerifiyXMLSignatureResponse verifyAuthBlock(String authBlockB64, IOAAuthParameters oaParam, AuthConfiguration authConfig) throws MOAIDException, IOException {  		String trustProfileId = authConfig.getMoaSpAuthBlockTrustProfileID(oaParam.isUseAuthBlockTestTestStore());  		List<String> verifyTransformsInfoProfileID = null;  		SignatureVerificationUtils sigVerify = new SignatureVerificationUtils(); -		IVerifiyXMLSignatureResponse sigVerifyResult = sigVerify.verify(authblock, trustProfileId , verifyTransformsInfoProfileID); +		IVerifiyXMLSignatureResponse sigVerifyResult = sigVerify.verify(Base64Utils.decode(authBlockB64, false), trustProfileId , verifyTransformsInfoProfileID);  		// validates the <VerifyXMLSignatureResponse>  		VerifyXMLSignatureResponseValidator.getInstance().validate(sigVerifyResult, @@ -99,20 +89,43 @@ public class QualifiedeIDVerifier {  	} -	public static boolean checkIDLAgainstAuthblock(IVerifiyXMLSignatureResponse sigVerifyResult, IIdentityLink idl, byte[] authBlock) throws ValidateException { +	public static boolean checkConsistencyOfeIDData(String sl20ReqId, IIdentityLink idl, AssertionAttributeExtractor authBlockExtractor, IVerifiyXMLSignatureResponse sigVerifyResult) throws SL20eIDDataValidationException {  		try {          			// compares the public keys from the identityLink with the AuthBlock  			VerifyXMLSignatureResponseValidator.getInstance().validateCertificate(sigVerifyResult, idl); +			//compare requestId from SL20 qualifiedeID command to ID from SAML2 assertion +			String authBlockId = authBlockExtractor.getAssertionID(); +			if (MiscUtil.isEmpty(authBlockId)) { +				Logger.info("AuthBlock containts no ID, but ID MUST be included"); +				throw new SL20eIDDataValidationException(new Object[] { +						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +						"AuthBlock containts no ID, but ID MUST be included" +				}); +			} +			if (!authBlockId.equals(sl20ReqId)) { +				Logger.info("SL20 'requestId' does NOT match to AuthBlock Id." +						+ " Expected : " + sl20ReqId +						+ " Authblock: " + authBlockId); +				throw new SL20eIDDataValidationException(new Object[] { +						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +						"SL20 'requestId' does NOT match to AuthBlock Id." +				}); +			} +			 +						  			// Compare AuthBlock Data with information stored in session, especially  			// date and time -			validateSigningDateTime(sigVerifyResult); +			validateSigningDateTime(sigVerifyResult, authBlockExtractor);  		} catch ( ValidateException e) { -			Logger.error("Signature verification error. ", e); -			throw e;  +			Logger.warn("Validation of eID information FAILED. ", e); +			throw new SL20eIDDataValidationException(new Object[] { +					SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, +					e.getMessage() +			});  		} @@ -121,12 +134,46 @@ public class QualifiedeIDVerifier {  	} -	private static boolean validateSigningDateTime( IVerifiyXMLSignatureResponse sigVerifyResult) throws ValidateException { +	private static void validateSigningDateTime( IVerifiyXMLSignatureResponse sigVerifyResult, AssertionAttributeExtractor authBlockExtractor) throws SL20eIDDataValidationException {  		Date signingDate = sigVerifyResult.getSigningDateTime(); +		Date notBefore = authBlockExtractor.getAssertionNotBefore(); +		Date notOrNotAfter = authBlockExtractor.getAssertionNotOnOrAfter(); +		if (signingDate == null) { +			Logger.info("AuthBlock signature contains NO signing data"); +			throw new SL20eIDDataValidationException(new Object[] { +					SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +					"AuthBlock signature contains NO signing data" +			}); +			 +		} -			   -		return false; +		Logger.debug("AuthBlock signing data: " + signingDate.toString()); + +		if (notBefore == null || notOrNotAfter == null) { +			Logger.info("AuthBlock contains NO 'notBefore' or 'notOrNotAfter' dates"); +			throw new SL20eIDDataValidationException(new Object[] { +					SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +					"AuthBlock contains NO 'notBefore' or 'notOrNotAfter' dates" +			}); +			 +		} +		 +		Logger.debug("AuthBlock valid period." +				+ " NotBefore:" + notBefore.toString()  +				+ " NotOrNotAfter:" + notOrNotAfter.toString()); +		 +		if (signingDate.after(notBefore) || signingDate.before(notOrNotAfter)) +			Logger.debug("Signing date validation successfull"); +		 +		else { +			Logger.info("AuthBlock signing date does NOT match to AuthBlock constrains"); +			throw new SL20eIDDataValidationException(new Object[] { +					SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +					"AuthBlock signing date does NOT match to AuthBlock constrains" +			}); +			 +		}		  	  }  } diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java index d9ff9d93c..763454639 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/CreateQualeIDRequestTask.java @@ -5,7 +5,6 @@ import java.util.HashMap;  import java.util.List;  import java.util.Map;  import java.util.Map.Entry; -import java.util.UUID;  import javax.net.ssl.SSLSocketFactory;  import javax.servlet.http.HttpServletRequest; @@ -30,6 +29,7 @@ import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.Constants;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.data.VerificationResult;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20Exception; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SLCommandoParserException;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.IJOSETools;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20HttpBindingUtils; @@ -41,6 +41,7 @@ import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;  import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport;  import at.gv.egovernment.moa.id.commons.utils.KeyValueUtils;  import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;  import at.gv.egovernment.moa.id.util.SSLUtils;  import at.gv.egovernment.moa.util.MiscUtil;  import at.gv.egovernment.moaspss.logging.Logger; @@ -91,7 +92,8 @@ public class CreateQualeIDRequestTask extends AbstractAuthServletTask {  						qualifiedeIDParams,   						joseTools.getEncryptionCertificate()); -				String qualeIDReqId = UUID.randomUUID().toString(); +				//String qualeIDReqId = UUID.randomUUID().toString(); +				String qualeIDReqId = SAML2Utils.getSecureIdentifier();  				String signedQualeIDCommand = SL20JSONBuilderUtils.createSignedCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID, qualeIDCommandParams, joseTools);  				JsonObject sl20Req = SL20JSONBuilderUtils.createGenericRequest(qualeIDReqId, null, null, signedQualeIDCommand); @@ -107,9 +109,16 @@ public class CreateQualeIDRequestTask extends AbstractAuthServletTask {  				HttpPost httpReq = new HttpPost(new URIBuilder(vdaQualeIDUrl).build());								  				httpReq.addHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE, SL20Constants.HTTP_HEADER_VALUE_NATIVE);  				List<NameValuePair> parameters = new ArrayList<NameValuePair>();; -				parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, sl20Req.toString())); +				 +				//correct one +				//parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM, Base64Url.encode(sl20Req.toString().getBytes()))); +				 +				//A-Trust current version +				parameters.add(new BasicNameValuePair(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM_OLD, sl20Req.toString()));  				httpReq.setEntity(new UrlEncodedFormEntity(parameters ));				 +				 +				  				//request VDA  				HttpResponse httpResp = httpClient.execute(httpReq); @@ -147,10 +156,22 @@ public class CreateQualeIDRequestTask extends AbstractAuthServletTask {  					//TODO: maybe add SL2ClientType Header from execution context  					SL20HttpBindingUtils.writeIntoResponse(request, response, sl20Forward, redirectURL); +				} else if (respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString() +						.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR)) {  +					JsonObject result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_RESULT, false); +					if (result  == null) +						result = SL20JSONExtractorUtils.getJSONObjectValue(respPayload, SL20Constants.SL20_COMMAND_CONTAINER_PARAMS, false); +					 +					String errorCode = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORCODE, true); +					String errorMsg = SL20JSONExtractorUtils.getStringValue(result, SL20Constants.SL20_COMMAND_PARAM_GENERAL_RESPONSE_ERRORMESSAGE, true); +					 +					Logger.info("Receive SL2.0 error. Code:" + errorCode + " Msg:" + errorMsg); +					throw new SL20Exception("sl20.08", new Object[]{errorCode, errorMsg}); +					  				} else {  					//TODO: update to add error handling  					Logger.warn("Received an unrecognized command: " + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()); -				 +					throw new SLCommandoParserException("Received an unrecognized command: \" + respPayload.get(SL20Constants.SL20_COMMAND_CONTAINER_NAME).getAsString()");  				} diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java index 90e19326e..b7fe579a3 100644 --- a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/ReceiveQualeIDTask.java @@ -1,9 +1,8 @@  package at.gv.egovernment.moa.id.auth.modules.sl20_auth.tasks; -import java.io.ByteArrayInputStream; +import java.io.IOException;  import java.io.StringWriter;  import java.security.cert.X509Certificate; -import java.util.Calendar;  import java.util.HashMap;  import java.util.List;  import java.util.Map; @@ -13,7 +12,6 @@ import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.http.entity.ContentType; -import org.jose4j.keys.X509Util;  import org.springframework.beans.factory.annotation.Autowired;  import org.springframework.stereotype.Component; @@ -35,18 +33,12 @@ import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.IJOSETools;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20JSONBuilderUtils;  import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20JSONExtractorUtils; -import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;  import at.gv.egovernment.moa.id.commons.MOAIDAuthConstants; -import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink;  import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException;  import at.gv.egovernment.moa.id.process.api.ExecutionContext; -import at.gv.egovernment.moa.id.protocols.AbstractAuthProtocolModulController; -import at.gv.egovernment.moa.util.Base64Utils; -import at.gv.egovernment.moa.util.DateTimeUtils;  import at.gv.egovernment.moa.util.MiscUtil;  import at.gv.egovernment.moaspss.logging.Logger; -import iaik.esi.sva.util.X509Utils; -import iaik.utils.Util; +  @Component("ReceiveQualeIDTask")  public class ReceiveQualeIDTask extends AbstractAuthServletTask { @@ -57,173 +49,210 @@ public class ReceiveQualeIDTask extends AbstractAuthServletTask {  	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response)  			throws TaskExecutionException { -		Logger.debug("Receiving SL2.0 response process .... ");  		try { -			//get SL2.0 command or result from HTTP request -			Map<String, String> reqParams = getParameters(request); -			String sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM); 			 -			if (MiscUtil.isEmpty(sl20Result)) { -				Logger.info("NO SL2.0 commando or result FOUND."); -				throw new SL20Exception("sl20.04", null); -				 -			} -			 -			 -			//parse SL2.0 command/result into JSON +			Logger.debug("Receiving SL2.0 response process .... ");  			JsonObject sl20ReqObj = null;  			try { -				JsonParser jsonParser = new JsonParser(); -				JsonElement sl20Req = jsonParser.parse(sl20Result); -				sl20ReqObj = sl20Req.getAsJsonObject(); +				//get SL2.0 command or result from HTTP request +				Map<String, String> reqParams = getParameters(request); +				String sl20Result = reqParams.get(SL20Constants.PARAM_SL20_REQ_COMMAND_PARAM); 			 +				if (MiscUtil.isEmpty(sl20Result)) { +					Logger.info("NO SL2.0 commando or result FOUND."); +					throw new SL20Exception("sl20.04", null); +					 +				} +							 +				//parse SL2.0 command/result into JSON			 +				try { +					JsonParser jsonParser = new JsonParser(); +					JsonElement sl20Req = jsonParser.parse(sl20Result); +					sl20ReqObj = sl20Req.getAsJsonObject(); +					 +				} catch (JsonSyntaxException e) { +					Logger.warn("SL2.0 command or result is NOT valid JSON.", e); +					Logger.debug("SL2.0 msg: " + sl20Result); +					throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e); +					 +				} -			} catch (JsonSyntaxException e) { -				Logger.warn("SL2.0 command or result is NOT valid JSON.", e); -				Logger.debug("SL2.0 msg: " + sl20Result); -				throw new SL20Exception("sl20.02", new Object[]{"SL2.0 command or result is NOT valid JSON."}, e); +				//validate reqId with inResponseTo  +				String sl20ReqId = pendingReq.getGenericData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); +				String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); +				if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { +					Logger.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); +					throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); +				} -			} -			 -			//validate reqId with inResponseTo  -			String sl20ReqId = pendingReq.getGenericData(Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID, String.class); -			String inRespTo = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_INRESPTO, true); -			if (sl20ReqId == null || !sl20ReqId.equals(inRespTo)) { -				Logger.info("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); -				throw new SL20SecurityException("SL20 'reqId': " + sl20ReqId + " does NOT match to 'inResponseTo':" + inRespTo); -			} -			 -			 -			//validate signature -			VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, true); -			if (payLoadContainer.isValidSigned() == null ||  -					!payLoadContainer.isValidSigned()) { -				Logger.info("SL20 result from VDA was not valid signed"); -				throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."}); -			} -			 -			//TODO validate certificate -			List<X509Certificate> sigCertChain = payLoadContainer.getCertChain(); -			 -			 -			//extract payloaf -			JsonObject payLoad = payLoadContainer.getPayload(); -			 -			//check response type -			if (SL20JSONExtractorUtils.getStringValue( -					payLoad, SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) -						.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID)) { -				Logger.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result .... "); -								 -				//TODO: activate decryption in 'SL20JSONExtractorUtils.extractSL20Result' -				JsonElement qualeIDResult = SL20JSONExtractorUtils.extractSL20Result(payLoad, joseTools, false); -								 -				//extract attributes from result -				String idlB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  -										SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, true); -				String authBlockB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  -						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, true); -				String ccsURL = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  -						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, true); -				String LoA = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  -						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, true); +				//validate signature +				VerificationResult payLoadContainer = SL20JSONExtractorUtils.extractSL20PayLoad(sl20ReqObj, joseTools, true); +				if (payLoadContainer.isValidSigned() == null ||  +						!payLoadContainer.isValidSigned()) { +					Logger.info("SL20 result from VDA was not valid signed"); +					throw new SL20SecurityException(new Object[]{"Signature on SL20 result NOT valid."}); +					 +				} +				/*TODO validate certificate by using MOA-SPSS +				* currently, the certificate is validated in IJOSETools by using a pkcs12 or jks keystore +				*/ +				List<X509Certificate> sigCertChain = payLoadContainer.getCertChain(); -				//TODO: validate results -				IIdentityLink idl = new IdentityLinkAssertionParser(new ByteArrayInputStream(Base64Utils.decode(idlB64, false))).parseIdentityLink(); +				//extract payloaf +				JsonObject payLoad = payLoadContainer.getPayload(); +				//check response type +				if (SL20JSONExtractorUtils.getStringValue( +						payLoad, SL20Constants.SL20_COMMAND_CONTAINER_NAME, true) +							.equals(SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID)) { +					Logger.debug("Find " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result .... "); +									 +					JsonElement qualeIDResult = SL20JSONExtractorUtils.extractSL20Result( +							payLoad, joseTools,  +							authConfig.getBasicMOAIDConfigurationBoolean(Constants.CONFIG_PROP_DISABLE_EID_ENCRYPTION, true)); +					 +					//extract attributes from result +					String idlB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  +											SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, true); +					String authBlockB64 = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  +							SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, true); +					String ccsURL = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  +							SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL, true); +					String LoA = SL20JSONExtractorUtils.getStringValue(qualeIDResult.getAsJsonObject(),  +							SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA, true); +					 +					//cache qualified eID data into pending request +					pendingReq.setGenericDataToSession( +							Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL,  +							idlB64); +					pendingReq.setGenericDataToSession( +							Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,  +							authBlockB64); +					pendingReq.setGenericDataToSession( +							Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,  +							ccsURL); +					pendingReq.setGenericDataToSession( +							Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA,  +							LoA); +																										 +				} else { +					Logger.info("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result"); +					throw new SLCommandoParserException("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result"); +				} -				//add into session -				defaultTaskInitialization(request, executionContext); -				moasession.setIdentityLink(idl); -				moasession.setBkuURL(ccsURL); -				//TODO: from AuthBlock -				moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(Calendar.getInstance())); -				moasession.setQAALevel(LoA); -				//mark as authenticated -				moasession.setAuthenticated(true); -				pendingReq.setAuthenticated(true); -								 -				//store pending request -				requestStoreage.storePendingRequest(pendingReq); -								 -				//create response  -				Map<String, String> reqParameters = new HashMap<String, String>(); -				reqParameters.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); -				JsonObject callReqParams = SL20JSONBuilderUtils.createCallCommandParameters( -						new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, null),  -						SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,  -						false,  -						reqParameters); -				JsonObject callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); +			} catch (MOAIDException  e) { +				Logger.warn("SL2.0 processing error:", e); +				pendingReq.setGenericDataToSession( +						Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,  +						new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e)); -				//build first redirect command for app -				JsonObject redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters("", callCommand, null, true); -				JsonObject redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); -								 -				//build second redirect command for IDP -				JsonObject redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters( -						new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), AbstractAuthProtocolModulController.FINALIZEPROTOCOL_ENDPOINT, null),  -						redirectOneCommand, null, true); -				JsonObject redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); +			} catch (Exception e) { +				Logger.warn("ERROR:", e); +				Logger.warn("SL2.0 Authentication FAILED with a generic error.", e); +				pendingReq.setGenericDataToSession( +						Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR,  +						new TaskExecutionException(pendingReq, e.getMessage(), e)); -				//build generic SL2.0 response container								 -				String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); -				JsonObject respContainer = SL20JSONBuilderUtils.createGenericRequest( -						UUID.randomUUID().toString(),  -						transactionId,  -						redirectTwoCommand,  -						null);  +			} finally { +					//store pending request +					requestStoreage.storePendingRequest(pendingReq); -				if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  -						request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {					 -					Logger.debug("Client request containts 'native client' header ... ");												 -					StringWriter writer = new StringWriter(); -					writer.write(respContainer.toString());						 -					final byte[] content = writer.toString().getBytes("UTF-8"); -					response.setStatus(HttpServletResponse.SC_OK); -					response.setContentLength(content.length); -					response.setContentType(ContentType.APPLICATION_JSON.toString());						 -					response.getOutputStream().write(content); +					//write SL2.0 response +					if (sl20ReqObj != null)				 +						buildResponse(request, response, sl20ReqObj); +					else  +						buildErrorResponse(request, response, "2000", "General transport Binding error");					 -					 -				} else { -					Logger.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); -					throw new SL20Exception("sl20.06",  -							new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); -					 -				} -												 -			} else { -				Logger.info("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result"); -				throw new SLCommandoParserException("SL20 response is NOT a " + SL20Constants.SL20_COMMAND_IDENTIFIER_QUALIFIEDEID + " result");  			} -			 -			 -		} catch (MOAIDException  e) { -			Logger.warn("ERROR:", e); -			throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); -			 +		  		} catch (Exception e) { -			Logger.warn("ERROR:", e); -			Logger.warn("SL2.0 Authentication FAILED with a generic error.", e); -			throw new TaskExecutionException(pendingReq, e.getMessage(), e); +			//write internal server errror 500 according to SL2.0 specification, chapter https transport binding +			Logger.warn("Can NOT build SL2.0 response. Reason: " + e.getMessage(), e); +			try { +				response.sendError(500, "Internal Server Error."); +				 +			} catch (IOException e1) { +				Logger.error("Can NOT send error message. SOMETHING IS REALY WRONG!", e); +				 +			}	 -		} finally {				 +		} finally {  			TransactionIDUtils.removeTransactionId();  			TransactionIDUtils.removeSessionId();  		}  	} -	 -	private JsonObject createRedirectCommand() { -		 +	private void buildErrorResponse(HttpServletRequest request, HttpServletResponse response, String errorCode, String errorMsg) throws Exception {				 +		JsonObject error = SL20JSONBuilderUtils.createErrorCommandResult(errorCode, errorMsg); +		JsonObject respContainer = SL20JSONBuilderUtils.createGenericRequest( +				UUID.randomUUID().toString(),  +				null,  +				error ,  +				null); +			 +		Logger.debug("Client request containts 'native client' header ... ");												 +		StringWriter writer = new StringWriter(); +		writer.write(respContainer.toString());						 +		final byte[] content = writer.toString().getBytes("UTF-8"); +		response.setStatus(HttpServletResponse.SC_OK); +		response.setContentLength(content.length); +		response.setContentType(ContentType.APPLICATION_JSON.toString());						 +		response.getOutputStream().write(content); +				 +	} + +	private void buildResponse(HttpServletRequest request, HttpServletResponse response, JsonObject sl20ReqObj) throws IOException, SL20Exception {		 +		//create response  +		Map<String, String> reqParameters = new HashMap<String, String>(); +		reqParameters.put(MOAIDAuthConstants.PARAM_TARGET_PENDINGREQUESTID, pendingReq.getRequestID()); +		JsonObject callReqParams = SL20JSONBuilderUtils.createCallCommandParameters( +				new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), Constants.HTTP_ENDPOINT_RESUME, null),  +				SL20Constants.SL20_COMMAND_PARAM_GENERAL_CALL_METHOD_GET,  +				false,  +				reqParameters); +		JsonObject callCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_CALL, callReqParams); -		return null; +		//build first redirect command for app +		JsonObject redirectOneParams = SL20JSONBuilderUtils.createRedirectCommandParameters("", callCommand, null, true); +		JsonObject redirectOneCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectOneParams); +						 +		//build second redirect command for IDP +		JsonObject redirectTwoParams = SL20JSONBuilderUtils.createRedirectCommandParameters( +				new DataURLBuilder().buildDataURL(pendingReq.getAuthURL(), Constants.HTTP_ENDPOINT_RESUME, null),  +				redirectOneCommand, null, true); +		JsonObject redirectTwoCommand = SL20JSONBuilderUtils.createCommand(SL20Constants.SL20_COMMAND_IDENTIFIER_REDIRECT, redirectTwoParams); +		//build generic SL2.0 response container								 +		String transactionId = SL20JSONExtractorUtils.getStringValue(sl20ReqObj, SL20Constants.SL20_TRANSACTIONID, false); +		JsonObject respContainer = SL20JSONBuilderUtils.createGenericRequest( +				UUID.randomUUID().toString(),  +				transactionId,  +				redirectTwoCommand,  +				null);  +		if (request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE) != null &&  +				request.getHeader(SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE).equals(SL20Constants.HTTP_HEADER_VALUE_NATIVE)) {					 +			Logger.debug("Client request containts 'native client' header ... ");												 +			StringWriter writer = new StringWriter(); +			writer.write(respContainer.toString());						 +			final byte[] content = writer.toString().getBytes("UTF-8"); +			response.setStatus(HttpServletResponse.SC_OK); +			response.setContentLength(content.length); +			response.setContentType(ContentType.APPLICATION_JSON.toString());						 +			response.getOutputStream().write(content); +			 +			 +		} else { +			Logger.info("SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"); +			throw new SL20Exception("sl20.06",  +					new Object[] {"SL2.0 DataURL communication needs http header: '" + SL20Constants.HTTP_HEADER_SL20_CLIENT_TYPE + "'"}); +			 +		}  	} + +	  } diff --git a/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java new file mode 100644 index 000000000..b5c84d315 --- /dev/null +++ b/id/server/modules/moa-id-module-sl20_authentication/src/main/java/at/gv/egovernment/moa/id/auth/modules/sl20_auth/tasks/VerifyQualifiedeIDTask.java @@ -0,0 +1,180 @@ +package at.gv.egovernment.moa.id.auth.modules.sl20_auth.tasks; + +import java.io.ByteArrayInputStream; +import java.util.Calendar; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.opensaml.Configuration; +import org.opensaml.saml2.core.Assertion; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.io.Unmarshaller; +import org.opensaml.xml.io.UnmarshallerFactory; +import org.springframework.stereotype.Component; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.Constants; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.exceptions.SL20eIDDataValidationException; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.SL20Constants; +import at.gv.egovernment.moa.id.auth.modules.sl20_auth.sl20.verifier.QualifiedeIDVerifier; +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser; +import at.gv.egovernment.moa.id.commons.api.data.IIdentityLink; +import at.gv.egovernment.moa.id.commons.api.data.IVerifiyXMLSignatureResponse; +import at.gv.egovernment.moa.id.commons.api.exceptions.MOAIDException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor; +import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.util.Base64Utils; +import at.gv.egovernment.moa.util.DOMUtils; +import at.gv.egovernment.moa.util.DateTimeUtils; +import at.gv.egovernment.moaspss.logging.Logger; + + +@Component("VerifyQualifiedeIDTask") +public class VerifyQualifiedeIDTask extends AbstractAuthServletTask { +	 +	@Override +	public void execute(ExecutionContext executionContext, HttpServletRequest request, HttpServletResponse response) +			throws TaskExecutionException { +		 +		Logger.debug("Verify qualified eID data from SL20 response .... "); +		try { +			//check if there was an error  +			TaskExecutionException sl20Error = pendingReq.getGenericData( +					Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_IDENTIFIER_ERROR, +					TaskExecutionException.class);			 +			if (sl20Error != null) { +				Logger.info("Found SL2.0 error after redirect ... "); +				throw sl20Error; +				 +			} +			 +			//get data from pending request +			String sl20ReqId = pendingReq.getGenericData( +					Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_REQID,  +					String.class); +			String idlB64 =  pendingReq.getGenericData( +					Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_IDL, +					String.class); +			String authBlockB64 = pendingReq.getGenericData( +					Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK,  +					String.class); +			String ccsURL = pendingReq.getGenericData( +					Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_CCSURL,  +					String.class); +			String LoA = pendingReq.getGenericData( +					Constants.PENDING_REQ_STORAGE_PREFIX + SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_LOA,  +					String.class); +							 +			//parse eID data +			IIdentityLink idl = new IdentityLinkAssertionParser(new ByteArrayInputStream(Base64Utils.decode(idlB64, false))).parseIdentityLink(); +			IVerifiyXMLSignatureResponse authBlockVerificationResult = null; +			try {				 +				Assertion authBlock = parseAuthBlockToSaml2Assertion(authBlockB64); +				AssertionAttributeExtractor authBlockExtractor = new AssertionAttributeExtractor(authBlock); + +			 +				//validate eID data			 +				QualifiedeIDVerifier.verifyIdentityLink(idl, pendingReq.getOnlineApplicationConfiguration(), authConfig); +				authBlockVerificationResult = QualifiedeIDVerifier.verifyAuthBlock( +							authBlockB64, pendingReq.getOnlineApplicationConfiguration(), authConfig); +				QualifiedeIDVerifier.checkConsistencyOfeIDData(sl20ReqId, idl, authBlockExtractor, authBlockVerificationResult); +			 +				//TODO: add LoA verification +				 +			} catch (SL20eIDDataValidationException e) { +				if (authConfig.getBasicMOAIDConfigurationBoolean(Constants.CONFIG_PROP_DISABLE_EID_VALIDATION, false)) { +					Logger.warn("SL20 eID data validation IS DISABLED!!"); +					Logger.warn("SL20 eID data IS NOT VALID!!! Reason: " + e.getMessage(), e); +					 +				} else +					throw e; +				 +			} +							 +			//add into session +			defaultTaskInitialization(request, executionContext); +			moasession.setIdentityLink(idl); +			moasession.setBkuURL(ccsURL); +			//TODO: from AuthBlock +			if (authBlockVerificationResult != null) +				moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(authBlockVerificationResult.getSigningDateTime())); +			else +				moasession.setIssueInstant(DateTimeUtils.buildDateTimeUTC(Calendar.getInstance())); +			 +			moasession.setQAALevel(LoA); + +			//store pending request +			requestStoreage.storePendingRequest(pendingReq); +						 +		} catch (MOAIDException  e) { +			Logger.warn("ERROR:", e); +			throw new TaskExecutionException(pendingReq, "SL2.0 Authentication FAILED. Msg: " + e.getMessage(), e); +			 +		} catch (Exception e) { +			Logger.warn("ERROR:", e); +			Logger.warn("SL2.0 Authentication FAILED with a generic error.", e); +			throw new TaskExecutionException(pendingReq, e.getMessage(), e); +			 +		} finally {				 +			TransactionIDUtils.removeTransactionId(); +			TransactionIDUtils.removeSessionId(); +			 +		} +	} + +	private Assertion parseAuthBlockToSaml2Assertion(String authblockB64) throws SL20eIDDataValidationException { +		try { +			//parse authBlock into SAML2 Assertion +			byte[] authBlockBytes = Base64Utils.decode(authblockB64, false);			 +			Element authBlockDOM = DOMUtils.parseXmlValidating(new ByteArrayInputStream(authBlockBytes)); +			UnmarshallerFactory unmarshallerFactory = Configuration.getUnmarshallerFactory(); +			Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(authBlockDOM);			  +			XMLObject samlAssertion = unmarshaller.unmarshall(authBlockDOM); +			 +			//validate SAML2 Assertion +			SAML2Utils.schemeValidation(samlAssertion); +			 +			if (samlAssertion instanceof Assertion)			 +				return (Assertion) samlAssertion;			 +			else  +				throw new SL20eIDDataValidationException( +						new Object[] { +							SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +							"AuthBlock is NOT of type SAML2 Assertion" +						}); +				 +		} catch (SL20eIDDataValidationException e) { +			throw e; +				 +		} catch (SAXException e) { +			Logger.info("Scheme validation of SAML2 AuthBlock FAILED. Reason: " + e.getMessage()); +			throw new SL20eIDDataValidationException( +					new Object[] { +						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +						e.getMessage() +					},  +					e); +			 +		} catch (Exception e) { +			Logger.info("Can not parse AuthBlock. Reason: " + e.getMessage()); +			Logger.trace("FullAuthBlock: " + authblockB64); +			throw new SL20eIDDataValidationException( +					new Object[] { +						SL20Constants.SL20_COMMAND_PARAM_EID_RESULT_AUTHBLOCK, +						e.getMessage() +					},  +					e); +		 +		} +						 +	} + +	 +	 +} | 
