diff options
Diffstat (limited to 'id/server/idserverlib/src')
152 files changed, 7864 insertions, 1052 deletions
| diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java index b68db92a4..f45a16780 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/advancedlogging/StatisticLogger.java @@ -23,6 +23,7 @@  package at.gv.egovernment.moa.id.advancedlogging;  import java.io.ByteArrayInputStream; +import java.io.IOException;  import java.io.InputStream;  import java.util.Date; @@ -160,8 +161,9 @@ public class StatisticLogger {  						dblog.setPv(false);  					} +					InputStream is = null;  					try { -						InputStream is = new ByteArrayInputStream(mandate.getMandate()); +						is = new ByteArrayInputStream(mandate.getMandate());  						JAXBContext jc = JAXBContext.newInstance(Mandate.class);  						Unmarshaller u = jc.createUnmarshaller(); @@ -189,6 +191,17 @@ public class StatisticLogger {  					} catch (JAXBException e) {  						Logger.warn("Advancted logging can not parse mandate.", e); +						 +					} finally { +						if (is!=null) { +							try { +								is.close(); +								 +							} catch (IOException e) { +								Logger.warn("Close InputStream failed." , e); +								 +							} +						}  					}  				}		  			} 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 43384c58a..eab7c511e 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 @@ -11,9 +11,11 @@ import java.io.InputStream;  import java.io.StringWriter;  import java.io.UnsupportedEncodingException;  import java.math.BigInteger; +import java.net.URL;  import java.security.NoSuchAlgorithmException;  import java.security.Principal;  import java.security.cert.CertificateException; +import java.text.SimpleDateFormat;  import java.util.ArrayList;  //import java.security.cert.CertificateFactory;  import java.util.Calendar; @@ -29,6 +31,7 @@ import javax.xml.transform.TransformerException;  import org.apache.commons.io.IOUtils;  import org.apache.commons.lang.StringEscapeUtils; +import org.apache.commons.lang3.BooleanUtils;  import org.apache.velocity.Template;  import org.apache.velocity.VelocityContext;  import org.apache.velocity.app.VelocityEngine; @@ -311,27 +314,28 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	}  	/** -	 * Processes an <code><InfoboxReadResponse></code> sent by the -	 * security layer implementation.<br> +	 * Processes an <code><InfoboxReadResponse></code> sent by the security layer implementation.<br>  	 * <ul>  	 * <li>Validates given <code><InfoboxReadResponse></code></li> -	 * <li>Parses identity link enclosed in -	 * <code><InfoboxReadResponse></code></li> +	 * <li>Parses identity link enclosed in <code><InfoboxReadResponse></code></li>  	 * <li>Verifies identity link by calling the MOA SP component</li>  	 * <li>Checks certificate authority of identity link</li>  	 * <li>Stores identity link in the session</li>  	 * <li>Verifies all additional infoboxes returned from the BKU</li>  	 * <li>Creates an authentication block to be signed by the user</li> -	 * <li>Creates and returns a <code><CreateXMLSignatureRequest></code> -	 * containg the authentication block, meant to be returned to the security -	 * layer implementation</li> +	 * <li>Creates and returns a <code><CreateXMLSignatureRequest></code> containg the authentication block, meant +	 * to be returned to the security layer implementation</li>  	 * </ul> -	 * -	 * @param sessionID                     ID of associated authentication session data -	 * @param infoboxReadResponseParameters The parameters from the response returned from the BKU -	 *                                      including the <code><InfoboxReadResponse></code> -	 * @return String representation of the -	 * <code><CreateXMLSignatureRequest></code> +	 *  +	 * @param sessionID +	 *            ID of associated authentication session data +	 * @param infoboxReadResponseParameters +	 *            The parameters from the response returned from the BKU including the +	 *            <code><InfoboxReadResponse></code> +	 * @return String "found!" in case the identity link could be retrieved and successfully validated, {@code null} in +	 *         case the identity link could not be retrieved (indicates that the card did not contain an identity link +	 *         which might indicate a foreign identity). Note that failing to parse or failing to validate the identity +	 *         link results in an Exception being thrown.  	 * @throws BKUException  	 */  	public String verifyIdentityLink(AuthenticationSession session, @@ -1057,6 +1061,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		ByteArrayInputStream bais = new ByteArrayInputStream(mandate  				.getMandate());  		Document doc = DOMUtils.parseDocumentSimple(bais); +		bais.close();  		return doc.getDocumentElement();  	} @@ -1095,14 +1100,14 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 * <li>Stores authentication data in the authentication data store indexed  	 * by the SAML artifact</li>  	 * <li>Deletes authentication session</li> -	 * <li>Returns the SAML artifact, encoded BASE64</li> +	 * <li><strike>Returns the SAML artifact, encoded BASE64</strike><br/>New id of the authenticated MOA session or {@code null} in case of mandate mode (???)</li>  	 * </ul>  	 *  	 * @param sessionID                         session ID of the running authentication session  	 * @param xmlCreateXMLSignatureReadResponse String representation of the  	 *                                          <code><CreateXMLSignatureResponse></code> -	 * @return SAML artifact needed for retrieving authentication data, encoded -	 * BASE64 +	 * @return <strike>SAML artifact needed for retrieving authentication data, encoded +	 * BASE64</strike><br/>New id of the authenticated MOA session or {@code null} in case of mandate mode (???)  	 * @throws BKUException  	 */  	public String verifyAuthenticationBlock(AuthenticationSession session, @@ -1362,17 +1367,16 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	/**  	 * Gets the foreign authentication data.<br>  	 * <ul> -	 * <li>Creates authentication data</li> +	 * <li><strong>Creates authentication data</strong></li>  	 * <li>Creates a corresponding SAML artifact</li>  	 * <li>Stores authentication data in the authentication data store indexed  	 * by the SAML artifact</li>  	 * <li>Deletes authentication session</li> -	 * <li>Returns the SAML artifact, encoded BASE64</li> +	 * <li><strike>Returns the SAML artifact, encoded BASE64</strike></li>  	 * </ul>  	 *  	 * @param sessionID session ID of the running authentication session -	 * @return SAML artifact needed for retrieving authentication data, encoded -	 * BASE64 +	 * @return String "new Session"  	 */  	public String getForeignAuthenticationData(AuthenticationSession session)  			throws AuthenticationException, BuildException, ParseException, @@ -1381,46 +1385,6 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		if (session == null)  			throw new AuthenticationException("auth.10", new Object[]{  					REQ_VERIFY_AUTH_BLOCK, PARAM_SESSIONID}); - -		//        // post processing of the infoboxes -		//        Iterator iter = session.getInfoboxValidatorIterator(); -		//        boolean formpending = false; -		//        if (iter != null) { -		//            while (!formpending && iter.hasNext()) { -		//                Vector infoboxValidatorVector = (Vector) iter.next(); -		//                String identifier = (String) infoboxValidatorVector.get(0); -		//                String friendlyName = (String) infoboxValidatorVector.get(1); -		//                InfoboxValidator infoboxvalidator = (InfoboxValidator) infoboxValidatorVector -		//                        .get(2); -		//                InfoboxValidationResult infoboxValidationResult = null; -		//                try { -		//                    infoboxValidationResult = infoboxvalidator.validate(session -		//                            .getIdentityLink().getSamlAssertion()); -		//                } catch (ValidateException e) { -		//                    Logger.error("Error validating " + identifier + " infobox:" -		//                            + e.getMessage()); -		//                    throw new ValidateException("validator.44", -		//                            new Object[]{friendlyName}); -		//                } -		//                if (!infoboxValidationResult.isValid()) { -		//                    Logger.info("Validation of " + identifier -		//                            + " infobox failed."); -		//                    throw new ValidateException("validator.40", new Object[]{ -		//                            friendlyName, -		//                            infoboxValidationResult.getErrorMessage()}); -		//                } -		//                String form = infoboxvalidator.getForm(); -		//                if (ParepUtils.isEmpty(form)) { -		//                    AddAdditionalSAMLAttributes( -		//                            session, -		//                            infoboxValidationResult.getExtendedSamlAttributes(), -		//                            identifier, friendlyName); -		//                } else { -		//                    return "Redirect to Input Processor"; -		//                } -		//            } -		//        } -  		VerifyXMLSignatureResponse vsresp = new VerifyXMLSignatureResponse();  		X509Certificate cert = session.getSignerCertificate();  		vsresp.setX509certificate(cert); @@ -1442,8 +1406,8 @@ public class AuthenticationServer implements MOAIDAuthConstants {  	 * Retrieves a session from the session store.  	 *  	 * @param id session ID -	 * @return <code>AuthenticationSession</code> stored with given session ID, -	 * <code>null</code> if session ID unknown +	 * @return <code>AuthenticationSession</code> stored with given session ID (never {@code null}). +	 * @throws AuthenticationException in case the session id does not reflect a valic, active session.  	 */  	public static AuthenticationSession getSession(String id)  			throws AuthenticationException { @@ -1749,10 +1713,6 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		//        String acsURL = new DataURLBuilder().buildDataURL(issuerValue,   		//    			PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN, moasession.getSessionID()); -		//solve Problem with sessionIDs  -		String acsURL = issuerValue + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; - -		Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL);  		String providerName = oaParam.getFriendlyName();  		Logger.debug("Issuer value: " + issuerValue); @@ -1772,7 +1732,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			boolean globallyMandatory = false;  			for (StorkAttribute currentGlobalAttribute : storkConfig.getStorkAttributes())  				if (current.getName().equals(currentGlobalAttribute.getName())) { -					globallyMandatory = currentGlobalAttribute.isMandatory(); +					globallyMandatory = BooleanUtils.isTrue(currentGlobalAttribute.isMandatory());  					break;  				} @@ -1787,12 +1747,18 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		List<String> value = new ArrayList<String>();  		Logger.debug("PEPS supports XMLSignatures:"+cpeps.isXMLSignatureSupported()); +		String acsURL;  		if(cpeps.isXMLSignatureSupported())//Send SignRequest to PEPS  		{ +			//solve Problem with sessionIDs  +			acsURL = issuerValue + PEPSConnectorServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; +			  			value.add(generateDssSignRequest(CreateXMLSignatureRequestBuilder.buildForeignIDTextToBeSigned("wie im  Signaturzertifikat (as in my signature certificate)", oaParam, moasession),  					"application/xhtml+xml", moasession.getCcc()));  			newAttribute.setValue(value);  			attributeList.add(newAttribute); +			 +			// TODO[branch]: STORK AuthReq CPEPS acsURL "/PEPSConnector"  		}  		else//Process SignRequest locally with MOCCA  		{ @@ -1808,6 +1774,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			moasession.setSignedDoc(signedDoc);  			acsURL = issuerValue + PEPSConnectorWithLocalSigningServlet.PEPSCONNECTOR_SERVLET_URL_PATTERN; +			// TODO[branch]: STORK AuthReq acsURL "/PEPSConnectorWithLocalSigning"  			try {  				AuthenticationSessionStoreage.storeSession(moasession);  			} catch (MOADatabaseException e) { @@ -1816,6 +1783,7 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			}  		} +		Logger.debug("MOA Assertion Consumer URL (PEPSConnctor): " + acsURL);  		if (Logger.isDebugEnabled()) {  			Logger.debug("The following attributes are requested for this OA:"); @@ -1880,6 +1848,17 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		//send  		moasession.setStorkAuthnRequest(authnRequest); +		// do PEPS-conform logging for easier evaluation +		try { +			// 2015-03-12 16:44:27.144#S-PEPS receives request from SP#spurl#spepsurl#spapp#spdomain#citizen country#qaa#msghash#msg_id id1# +			Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS receives request from SP#" +  +					moasession.getPublicOAURLPrefix() + "#" + issuerValue + "#" + spApplication + "#" +  +					new URL(moasession.getPublicOAURLPrefix()).getHost() + "#" + moasession.getCcc() + "#" + oaParam.getQaaLevel() + +					"#_hash_#" + moasession.getProcessInstanceId() + "#"); +		} catch (Exception e1) { +			Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage()); +		} +  		AuthenticationSessionStoreage.changeSessionID(moasession, authnRequest.getSamlId()); @@ -1900,6 +1879,8 @@ public class AuthenticationServer implements MOAIDAuthConstants {  			StringWriter writer = new StringWriter();  			template.merge(context, writer); +			// TODO[branch]: SAML2 Form Submit to CPEPS, response to acsURL Servlet +			  			resp.setContentType("text/html;charset=UTF-8");              			resp.getOutputStream().write(writer.toString().getBytes("UTF-8")); @@ -1910,6 +1891,17 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		}  		Logger.info("STORK AuthnRequest successfully successfully prepared for client with target location: " + authnRequest.getDestination()); + +		// do PEPS-conform logging for easier evaluation +		try { +			// 2015-03-12 16:44:27.144#S-PEPS generates request to C-PEPS#spepsurl#cpepsurl#spapp#spdomain#citizen country#qaa#msghash#msg_id id1#id2# +			Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS generates request to C-PEPS#" +  +					issuerValue + "#" + destination + "#" + spApplication + "#" +  +					new URL(moasession.getPublicOAURLPrefix()).getHost() + "#" + moasession.getCcc() + "#" + oaParam.getQaaLevel() + +					"#_hash_#" + moasession.getProcessInstanceId() + "#" + authnRequest.getSamlId() + "#"); +		} catch (Exception e1) { +			Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage()); +		}  	}  	private static String generateDssSignRequest(String text, String mimeType, String citizenCountry) { @@ -1986,6 +1978,16 @@ public class AuthenticationServer implements MOAIDAuthConstants {  		} catch (Throwable e) {  			throw new CertificateException(e); +			 +		} finally { +			try { +				is.close(); +				 +			} catch (IOException e) { +				Logger.warn("Close InputStream failed." , e); +				 +			} +			  		}  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java index fe35866b1..104cd8622 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/AuthenticationSessionCleaner.java @@ -45,7 +45,7 @@ public class AuthenticationSessionCleaner implements Runnable {    public static void start() {      // start the session cleanup thread      Thread sessionCleaner = -      new Thread(new AuthenticationSessionCleaner()); +      new Thread(new AuthenticationSessionCleaner(), "AuthenticationSessionCleaner");      sessionCleaner.setName("SessionCleaner");      sessionCleaner.setDaemon(true);      sessionCleaner.setPriority(Thread.MIN_PRIORITY); 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 db8b4dd80..5223a181d 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 @@ -149,7 +149,9 @@ public interface MOAIDAuthConstants {  			Collections.unmodifiableMap(new HashMap<String, String>() {  				private static final long serialVersionUID = 1L;  				{ +					put("AT", "Other Countries");//"Workaround for PEPS Simulator"  					put("BE", "België/Belgique"); +					//put("CH", "Schweiz");  					put("EE", "Eesti");  					put("ES", "España");  					put("FI", "Suomi"); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java index db36356c0..025c4c652 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/MOAIDAuthInitializer.java @@ -147,13 +147,15 @@ public class MOAIDAuthInitializer {                          .toString() }, ex);              }          } - +           // Initializes IAIKX509TrustManager logging +        /*          String log4jConfigURL = System.getProperty("log4j.configuration");          Logger.info("Log4J Configuration: " + log4jConfigURL);          if (log4jConfigURL != null) {              IAIKX509TrustManager.initLog(new LoggerConfigImpl(log4jConfigURL));          } +         */          // Initializes the Axis secure socket factory for use in calling the          // MOA-SP web service diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java index 52488c3cb..cd751ce7f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/AuthenticationDataBuilder.java @@ -43,6 +43,7 @@ import javax.xml.bind.Marshaller;  import org.opensaml.saml2.core.Attribute;  import org.opensaml.saml2.core.AttributeQuery; +import org.opensaml.saml2.core.AuthnStatement;  import org.opensaml.saml2.core.Response;  import org.opensaml.ws.soap.common.SOAPException;  import org.opensaml.xml.XMLObject; @@ -214,7 +215,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  		} else {  			//build AuthenticationData from MOASession -			buildAuthDataFormMOASession(authdata, session, oaParam); +			buildAuthDataFormMOASession(authdata, session, oaParam, protocolRequest);  		} @@ -271,12 +272,13 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  			AssertionAttributeExtractor extractor =   					new AssertionAttributeExtractor(intfResp);			 -			if (!extractor.containsAllRequiredAttributes()) {				 +			if (!extractor.containsAllRequiredAttributes()) { +				Logger.info("Received assertion does no contain a minimum set of attributes. Starting AttributeQuery process ...");  				//collect attributes by using BackChannel communication  				String endpoint = idp.getIDPAttributQueryServiceURL();			  				if (MiscUtil.isEmpty(endpoint)) { -					Logger.error("No AttributeQueryURL for interfederationIDP " + oaParam.getPublicURLPrefix()); -					throw new ConfigurationException("No AttributeQueryURL for interfederationIDP " + oaParam.getPublicURLPrefix(), null); +					Logger.error("No AttributeQueryURL for interfederationIDP " + idp.getPublicURLPrefix()); +					throw new ConfigurationException("No AttributeQueryURL for interfederationIDP " + idp.getPublicURLPrefix(), null);  				}  				//build attributQuery request @@ -321,7 +323,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  			}  			//parse response information to authData -			buildAuthDataFormInterfederationResponse(authdata, session, extractor, oaParam);			 +			buildAuthDataFormInterfederationResponse(authdata, session, extractor, oaParam, req);			  		} catch (SOAPException e) {  			throw new BuildException("builder.06", null, e); @@ -348,7 +350,8 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  			AuthenticationData authData,   			AuthenticationSession session,   			AssertionAttributeExtractor extractor, -			IOAAuthParameters oaParam)  +			IOAAuthParameters oaParam, +			IRequest req)   					throws BuildException, AssertionAttributeExtractorExeption {  		Logger.debug("Build AuthData from assertion starts ...."); @@ -358,14 +361,35 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  		authData.setFamilyName(extractor.getSingleAttributeValue(PVPConstants.PRINCIPAL_NAME_NAME));		  		authData.setGivenName(extractor.getSingleAttributeValue(PVPConstants.GIVEN_NAME_NAME));		  		authData.setDateOfBirth(extractor.getSingleAttributeValue(PVPConstants.BIRTHDATE_NAME)); -		authData.setBPKType(extractor.getSingleAttributeValue(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME));  		authData.setCcc(extractor.getSingleAttributeValue(PVPConstants.EID_ISSUING_NATION_NAME));		  		authData.setBkuURL(extractor.getSingleAttributeValue(PVPConstants.EID_CCS_URL_NAME));  		authData.setIdentificationValue(extractor.getSingleAttributeValue(PVPConstants.EID_SOURCE_PIN_NAME));		  		authData.setIdentificationType(extractor.getSingleAttributeValue(PVPConstants.EID_SOURCE_PIN_TYPE_NAME)); +		 +		if (extractor.containsAttribute(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME)) { +			String bpkType = extractor.getSingleAttributeValue(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME); +			if (bpkType.startsWith(Constants.URN_PREFIX_CDID) &&  +					!bpkType.substring(Constants.URN_PREFIX_CDID.length(),  +							Constants.URN_PREFIX_CDID.length() + 1).equals("+")) {				 +				Logger.warn("Receive uncorrect encoded bBKType attribute " + bpkType + " Starting attribute value correction ... "); +				bpkType = Constants.URN_PREFIX_CDID + "+" + bpkType.substring(Constants.URN_PREFIX_CDID.length() + 1);  +				 +			} +									 +			authData.setBPKType(bpkType);			 +		} +				  		if (extractor.containsAttribute(PVPConstants.BPK_NAME)) {  			String pvpbPK = extractor.getSingleAttributeValue(PVPConstants.BPK_NAME); +			 +			if (pvpbPK.startsWith("bPK:")) { +				Logger.warn("Attribute " + PVPConstants.BPK_NAME  +					+ " contains a not standardize prefix! Staring attribute value correction process ..."); +				pvpbPK = pvpbPK.substring("bPK:".length()); +				 +			} +			  			String[] spitted = pvpbPK.split(":");  			authData.setBPK(spitted[1]);  			if (MiscUtil.isEmpty(authData.getBPKType())) { @@ -513,7 +537,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  			}  			//build OA specific bPK/wbPK information -			buildOAspecificbPK(oaParam, authData,  +			buildOAspecificbPK(req, oaParam, authData,   					authData.getIdentificationValue(),   					authData.getIdentificationType()); @@ -521,7 +545,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  		if (MiscUtil.isEmpty(authData.getBPK())) {  			Logger.debug("Calcutlate bPK from baseID"); -			buildOAspecificbPK(oaParam, authData,  +			buildOAspecificbPK(req, oaParam, authData,   					authData.getIdentificationValue(),   					authData.getIdentificationType()); @@ -536,7 +560,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  			} else {  				Logger.debug("Found PVP QAA level. QAA mapping process starts ... ");				 -				String mappedQAA = PVPtoSTORKMapper.getInstance().mapQAALevel(qaaLevel); +				String mappedQAA = PVPtoSTORKMapper.getInstance().mapToQAALevel(qaaLevel);  				if (MiscUtil.isNotEmpty(mappedQAA))  					authData.setQAALevel(mappedQAA); @@ -586,7 +610,8 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  		if (extractor.containsAttribute(PVPConstants.EID_IDENTITY_LINK_NAME)) {  			try {  				InputStream idlStream = Base64Utils.decodeToStream(extractor.getSingleAttributeValue(PVPConstants.EID_IDENTITY_LINK_NAME), false);				 -				IdentityLink idl = new IdentityLinkAssertionParser(idlStream).parseIdentityLink();				 +				IdentityLink idl = new IdentityLinkAssertionParser(idlStream).parseIdentityLink(); +				idlStream.close();  				buildOAspecificIdentityLink(oaParam, authData, idl);  			} catch (ParseException e) { @@ -744,6 +769,12 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  			}			  		} +		//set PVP OU attribute +		if (extractor.containsAttribute(PVPConstants.OU_NAME)) { +			authData.setPvpAttribute_OU(extractor.getSingleAttributeValue(PVPConstants.OU_NAME)); +			Logger.debug("Found PVP 'OU' attribute in response -> " + authData.getPvpAttribute_OU()); +			 +		}  		//set STORK attributes  		if (extractor.containsAttribute(PVPConstants.EID_STORK_TOKEN_NAME)) {				 @@ -761,8 +792,19 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  		authData.setSsoSession(true);  		authData.setInterfederatedSSOSession(true); -		if (extractor.getFullAssertion().getConditions() != null && extractor.getFullAssertion().getConditions().getNotOnOrAfter() != null) +		if (extractor.getFullAssertion().getAuthnStatements() != null  +				&& extractor.getFullAssertion().getAuthnStatements().size() > 0) { +			for (AuthnStatement el : extractor.getFullAssertion().getAuthnStatements()) { +				if (el.getSessionNotOnOrAfter() != null) { +					authData.setSsoSessionValidTo(el.getSessionNotOnOrAfter().toDate()); +					break; +				} +			} +			 +		} else {  			authData.setSsoSessionValidTo(extractor.getFullAssertion().getConditions().getNotOnOrAfter().toDate()); +			 +		}  		//only for SAML1  		if (PVPConstants.STORK_QAA_1_4.equals(authData.getQAALevel())) @@ -805,7 +847,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  	}  	private static void buildAuthDataFormMOASession(AuthenticationData authData, AuthenticationSession session,  -			IOAAuthParameters oaParam) throws BuildException, ConfigurationException { +			IOAAuthParameters oaParam, IRequest protocolRequest) throws BuildException, ConfigurationException {  		IdentityLink identityLink = session.getIdentityLink(); @@ -864,7 +906,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  				}  			} catch (Exception e) { -				Logger.error("Failed to extract country code from certificate", e); +				Logger.error("Failed to extract country code from certificate with message: " + e.getMessage());  			} @@ -919,7 +961,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  				Logger.trace("Authenticated User is OW: " + mandate.getOWbPK());              } else { -            	buildOAspecificbPK(oaParam, authData,  +            	buildOAspecificbPK(protocolRequest, oaParam, authData,               			identityLink.getIdentificationValue(),               			identityLink.getIdentificationType()); @@ -951,7 +993,13 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {              //resign IDL  			IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();					  			Element resignedilAssertion; -			resignedilAssertion = identitylinkresigner.resignIdentityLink(businessServiceIdl.getSamlAssertion());    				    				 + +			AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); +			if (config.isIdentityLinkResigning()) { +				resignedilAssertion = identitylinkresigner.resignIdentityLink(businessServiceIdl.getSamlAssertion(), config.getIdentityLinkResigningKey()); +			} else { +				resignedilAssertion = businessServiceIdl.getSamlAssertion(); +			}  			IdentityLinkAssertionParser resignedIDLParser = new IdentityLinkAssertionParser(resignedilAssertion);  			IdentityLink resignedIDL = resignedIDLParser.parseIdentityLink(); @@ -963,7 +1011,7 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {  	}		 -	private static void buildOAspecificbPK(IOAAuthParameters oaParam, AuthenticationData authData, String baseID, String baseIDType) throws BuildException  { +	private static void buildOAspecificbPK(IRequest protocolRequest, IOAAuthParameters oaParam, AuthenticationData authData, String baseID, String baseIDType) throws BuildException  {          if (oaParam.getBusinessService()) {              //since we have foreigner, wbPK is not calculated in BKU @@ -984,9 +1032,15 @@ public class AuthenticationDataBuilder implements MOAIDAuthConstants {              if (baseIDType.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(baseID, oaParam.getTarget()); +            	String target = null; +            	if (protocolRequest instanceof SAML1RequestImpl) +            		target = protocolRequest.getTarget(); +            	else +            		target = oaParam.getTarget(); +            	 +                String bpkBase64 = new BPKBuilder().buildBPK(baseID, target);                  authData.setBPK(bpkBase64); -                authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + oaParam.getTarget()); +                authData.setBPKType(Constants.URN_PREFIX_CDID + "+" + target);              }              Logger.trace("Authenticate user with bPK " + authData.getBPK());            diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java index 484fe1f9e..9a8372a2d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/builder/StartAuthenticationBuilder.java @@ -47,6 +47,15 @@ public class StartAuthenticationBuilder {  	} +	/** +	 * Depending on the selected citizen's country ({@code moasession.ccc}): +	 * <ul> +	 * <li><strong>Either</strong> creates an "IdentityLinkForm" with embedded {@code InfoBoxReadRequest} to be submitted to a citizen card +	 * environment for reading the subject's IdentityLink</li> +	 * </ul> +	 *  +	 * @return The IdentityLinkForm. +	 */  	public String build(AuthenticationSession moasession, HttpServletRequest req,  			HttpServletResponse resp) throws WrongParametersException, MOAIDException { @@ -54,25 +63,11 @@ public class StartAuthenticationBuilder {  			throw new AuthenticationException("auth.18", new Object[] { });  		} -	    STORKConfig storkConfig = AuthConfigurationProvider.getInstance().getStorkConfig(); -	     -	    Logger.info("Starting authentication for a citizen of country: " + (StringUtils.isEmpty(moasession.getCcc()) ? "AT" : moasession.getCcc())); -	    // STORK or normal authentication -	    if (storkConfig.isSTORKAuthentication(moasession.getCcc())) { -	    	//STORK authentication -	    	Logger.trace("Found C-PEPS configuration for citizen of country: " + moasession.getCcc()); -	    	Logger.debug("Starting STORK authentication"); -	    	 -	    	AuthenticationServer.startSTORKAuthentication(req, resp, moasession); -	    	return ""; -	    	 -	    } else { -	    	//normal MOA-ID authentication -	    	Logger.debug("Starting normal MOA-ID authentication"); -		    			    	    	 -	    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req);	    +    	//normal MOA-ID authentication +    	Logger.debug("Starting normal MOA-ID authentication"); +	    			    	    	 +    	String getIdentityLinkForm = AuthenticationServer.getInstance().startAuthentication(moasession, req);	    -	    	return getIdentityLinkForm; -	    } +    	return getIdentityLinkForm;  	}  } 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 26c22fb4a..76bf93249 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 @@ -304,6 +304,8 @@ public class AuthenticationSession implements Serializable {  	private String authnContextClassRef;  	// private String requestedProtocolURL = null; +	private String processInstanceId; +	  	public String getAuthnContextClassRef() {  		return authnContextClassRef;  	} @@ -1110,6 +1112,22 @@ public class AuthenticationSession implements Serializable {  	 */  	public Date getSessionCreated() {  		return sessionCreated; -	}	 +	} + +	/** +	 * Returns the identifier of the process instance associated with this moaid session. +	 * @return The process instance id (may be {@code null} if no process has been created yet). +	 */ +	public String getProcessInstanceId() { +		return processInstanceId; +	} + +	/** +	 * Sets the process instance identifier in order to associate a certain process instance with this moaid session.  +	 * @param processInstanceId The process instance id. +	 */ +	public void setProcessInstanceId(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java new file mode 100644 index 000000000..67ddd170a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AbstractAuthServletTask.java @@ -0,0 +1,378 @@ +package at.gv.egovernment.moa.id.auth.modules;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.ByteArrayOutputStream;
 +import java.io.IOException;
 +import java.io.InputStream;
 +import java.util.Enumeration;
 +import java.util.HashMap;
 +import java.util.Iterator;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Map.Entry;
 +
 +import javax.servlet.RequestDispatcher;
 +import javax.servlet.ServletContext;
 +import javax.servlet.ServletException;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.fileupload.FileItem;
 +import org.apache.commons.fileupload.FileItemFactory;
 +import org.apache.commons.fileupload.FileUploadException;
 +import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 +import org.apache.commons.fileupload.servlet.ServletFileUpload;
 +import org.apache.commons.lang3.ArrayUtils;
 +
 +import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;
 +import at.gv.egovernment.moa.id.config.ConfigurationException;
 +import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet;
 +import at.gv.egovernment.moa.id.process.springweb.MoaIdTask;
 +import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;
 +import at.gv.egovernment.moa.id.storage.IExceptionStore;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.MiscUtil;
 +
 +/**
 + * Task based counterpart to {@link AuthServlet}, providing the same utility methods (error handling, parameter parsing
 + * etc.).</p> The code has been taken from {@link AuthServlet}.
 + */
 +public abstract class AbstractAuthServletTask extends MoaIdTask {
 +
 +	protected static final String ERROR_CODE_PARAM = "errorid";
 +
 +	protected void handleErrorNoRedirect(String errorMessage, Throwable exceptionThrown,
 +			HttpServletRequest req, HttpServletResponse resp) {
 +
 +		if (null != errorMessage) {
 +			Logger.error(errorMessage);
 +			req.setAttribute("ErrorMessage", errorMessage);
 +		}
 +
 +		if (null != exceptionThrown) {
 +			if (null == errorMessage)
 +				errorMessage = exceptionThrown.getMessage();
 +			Logger.error(errorMessage, exceptionThrown);
 +			req.setAttribute("ExceptionThrown", exceptionThrown);
 +		}
 +
 +		if (Logger.isDebugEnabled()) {
 +			req.setAttribute("LogLevel", "debug");
 +		}
 +		
 +		
 +		StatisticLogger logger = StatisticLogger.getInstance();
 +		logger.logErrorOperation(exceptionThrown);
 +		
 +		
 +		// forward this to errorpage-auth.jsp where the HTML error page is
 +		// generated
 +		ServletContext context = req.getServletContext();
 +		RequestDispatcher dispatcher = context
 +				.getRequestDispatcher("/errorpage-auth.jsp");
 +		try {
 +
 +			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);
 +
 +			dispatcher.forward(req, resp);
 +		} catch (ServletException e) {
 +			Logger.error(e);
 +		} catch (IOException e) {
 +			Logger.error(e);
 +		}
 +	}
 +	
 +	/**
 +	 * Handles an error. <br>>
 +	 * <ul>
 +	 * <li>Logs the error</li>
 +	 * <li>Places error message and exception thrown into the request as request
 +	 * attributes (to be used by <code>"/errorpage-auth.jsp"</code>)</li>
 +	 * <li>Sets HTTP status 500 (internal server error)</li>
 +	 * </ul>
 +	 * 
 +	 * @param errorMessage
 +	 *            error message
 +	 * @param exceptionThrown
 +	 *            exception thrown
 +	 * @param req
 +	 *            servlet request
 +	 * @param resp
 +	 *            servlet response
 +	 */
 +	protected void handleError(String errorMessage, Throwable exceptionThrown,
 +			HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) {
 +
 +		if (null != errorMessage) {
 +			Logger.error(errorMessage);
 +			req.setAttribute("ErrorMessage", errorMessage);
 +		}
 +
 +		if (null != exceptionThrown) {
 +			if (null == errorMessage)
 +				errorMessage = exceptionThrown.getMessage();
 +			Logger.error(errorMessage, exceptionThrown);
 +			req.setAttribute("ExceptionThrown", exceptionThrown);
 +		}
 +
 +		if (Logger.isDebugEnabled()) {
 +			req.setAttribute("LogLevel", "debug");
 +		}
 +
 +		if (!(exceptionThrown instanceof MOAIDException)) {
 +			Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown);
 +			
 +		}
 +		
 +		IExceptionStore store = DBExceptionStoreImpl.getStore();
 +		String id = store.storeException(exceptionThrown);
 +
 +		if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) {
 +		
 +			String redirectURL = null;
 +
 +			redirectURL = ServletUtils.getBaseUrl(req);
 +			redirectURL += "/dispatcher?" + ERROR_CODE_PARAM + "=" + id 
 +					+ "&" + DispatcherServlet.PARAM_TARGET_PENDINGREQUESTID + "=" + pendingRequestID;
 +		
 +			resp.setContentType("text/html");
 +			resp.setStatus(302);
 +	
 +			resp.addHeader("Location", redirectURL);		
 +			Logger.debug("REDIRECT TO: " + redirectURL);	
 +		
 +			return;
 +			
 +		} else {
 +			
 +			//Exception can not be stored in database
 +			handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp);
 +		}
 +	}
 +
 +	/**
 +	 * Handles a <code>WrongParametersException</code>.
 +	 * 
 +	 * @param req
 +	 *            servlet request
 +	 * @param resp
 +	 *            servlet response
 +	 */
 +	protected void handleWrongParameters(WrongParametersException ex,
 +			HttpServletRequest req, HttpServletResponse resp) {
 +		Logger.error(ex.toString());
 +		req.setAttribute("WrongParameters", ex.getMessage());
 +
 +		// forward this to errorpage-auth.jsp where the HTML error page is
 +		// generated
 +		ServletContext context = req.getServletContext();
 +		RequestDispatcher dispatcher = context
 +				.getRequestDispatcher("/errorpage-auth.jsp");
 +		try {
 +			setNoCachingHeaders(resp);
 +			dispatcher.forward(req, resp);
 +		} catch (ServletException e) {
 +			Logger.error(e);
 +		} catch (IOException e) {
 +			Logger.error(e);
 +		}
 +	}
 +
 +	/**
 +	 * Logs all servlet parameters for debugging purposes.
 +	 */
 +	protected void logParameters(HttpServletRequest req) {
 +		for (Enumeration params = req.getParameterNames(); params
 +				.hasMoreElements();) {
 +			String parname = (String) params.nextElement();
 +			Logger.debug("Parameter " + parname + req.getParameter(parname));
 +		}
 +	}
 +
 +	/**
 +	 * Parses the request input stream for parameters, assuming parameters are
 +	 * encoded UTF-8 (no standard exists how browsers should encode them).
 +	 * 
 +	 * @param req
 +	 *            servlet request
 +	 * 
 +	 * @return mapping parameter name -> value
 +	 * 
 +	 * @throws IOException
 +	 *             if parsing request parameters fails.
 +	 * 
 +	 * @throws FileUploadException
 +	 *             if parsing request parameters fails.
 +	 */
 +	protected Map<String, String> getParameters(HttpServletRequest req) throws IOException,
 +			FileUploadException {
 +
 +		Map<String, String> parameters = new HashMap<String, String>();
 +
 +		if (ServletFileUpload.isMultipartContent(req)) {
 +			// request is encoded as mulitpart/form-data
 +			FileItemFactory factory = new DiskFileItemFactory();
 +			ServletFileUpload upload = null;
 +			upload = new ServletFileUpload(factory);
 +			List items = null;
 +			items = upload.parseRequest(req);
 +			for (int i = 0; i < items.size(); i++) {
 +				FileItem item = (FileItem) items.get(i);
 +				if (item.isFormField()) {
 +					// Process only form fields - no file upload items
 +					String logString = item.getString("UTF-8");
 +
 +					// TODO use RegExp
 +					String startS = "<pr:Identification><pr:Value>";
 +					String endS = "</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type>";
 +					String logWithMaskedBaseid = logString;
 +					int start = logString.indexOf(startS);
 +					if (start > -1) {
 +						int end = logString.indexOf(endS);
 +						if (end > -1) {
 +							logWithMaskedBaseid = logString.substring(0, start);
 +							logWithMaskedBaseid += startS;
 +							logWithMaskedBaseid += "xxxxxxxxxxxxxxxxxxxxxxxx";
 +							logWithMaskedBaseid += logString.substring(end,
 +									logString.length());
 +						}
 +					}
 +					parameters
 +							.put(item.getFieldName(), item.getString("UTF-8"));
 +					Logger.debug("Processed multipart/form-data request parameter: \nName: "
 +							+ item.getFieldName()
 +							+ "\nValue: "
 +							+ logWithMaskedBaseid);
 +				}
 +			}
 +		}
 +
 +		else {
 +			// request is encoded as application/x-www-urlencoded
 +			// [tknall]: we must not consume request body input stream once servlet-api request parameters have been accessed
 +			
 +			/*
 +			InputStream in = req.getInputStream();
 +
 +			String paramName;
 +			String paramValueURLEncoded;
 +			do {
 +				paramName = new String(readBytesUpTo(in, '='));
 +				if (paramName.length() > 0) {
 +					paramValueURLEncoded = readBytesUpTo(in, '&');
 +					String paramValue = URLDecoder.decode(paramValueURLEncoded,
 +							"UTF-8");
 +					parameters.put(paramName, paramValue);
 +				}
 +			} while (paramName.length() > 0);
 +			in.close();
 +			*/
 +			
 +			Iterator<Entry<String, String[]>> requestParamIt = req.getParameterMap().entrySet().iterator();
 +			while (requestParamIt.hasNext()) {
 +				Entry<String, String[]> entry = requestParamIt.next();
 +				String key = entry.getKey();
 +				String[] values = entry.getValue();
 +				// take the last value from the value array since the legacy code above also does it this way
 +				parameters.put(key, ArrayUtils.isEmpty(values) ? null : values[values.length-1]); 
 +			}
 +			
 +		}
 +
 +		return parameters;
 +	}
 +
 +	/**
 +	 * Reads bytes up to a delimiter, consuming the delimiter.
 +	 * 
 +	 * @param in
 +	 *            input stream
 +	 * @param delimiter
 +	 *            delimiter character
 +	 * @return String constructed from the read bytes
 +	 * @throws IOException
 +	 */
 +	protected String readBytesUpTo(InputStream in, char delimiter)
 +			throws IOException {
 +		ByteArrayOutputStream bout = new ByteArrayOutputStream();
 +		boolean done = false;
 +		int b;
 +		while (!done && (b = in.read()) >= 0) {
 +			if (b == delimiter)
 +				done = true;
 +			else
 +				bout.write(b);
 +		}
 +		return bout.toString();
 +	}
 +
 +	/**
 +	 * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
 +	 * 
 +	 * @param resp
 +	 *            The HttpServletResponse.
 +	 */
 +	public void setNoCachingHeaders(HttpServletResponse resp) {
 +		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);
 +	}
 +
 +	/**
 +	 * 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)
 +		
 +		//Removed from MOA-ID 2.0 config
 +//		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/modules/AuthModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java new file mode 100644 index 000000000..8983403d8 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/AuthModule.java @@ -0,0 +1,42 @@ +package at.gv.egovernment.moa.id.auth.modules; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; + +/** + * Provides metadata of a certain module. Uses for module discovery and process selection. + */ +public interface AuthModule { + +	/** +	 * Returns the priority of the module. The priority defines the order of the respective module within the chain of +	 * discovered modules. Higher priorized modules are asked before lower priorized modules for a process that they can +	 * handle. +	 * <p/> +	 * Internal default modules are priorized neutral ({@code 0}. Use a higher priority ({@code 1...Integer.MAX_VALUE}) +	 * in order to have your module(s) priorized or a lower priority ({@code Integer.MIN_VALUE...-1}) in order to put +	 * your modules behind default modules. +	 *  +	 * @return the priority of the module. +	 */ +	int getPriority(); + +	/** +	 * Selects a process (description), referenced by its unique id, which is able to perform authentication with the +	 * given {@link ExecutionContext}. Returns {@code null} if no appropriate process (description) was available within +	 * this module. +	 *  +	 * @param context +	 *            an ExecutionContext for a process. +	 * @return the process-ID of a process which is able to work with the given ExecutionContext, or {@code null}. +	 */ +	String selectProcess(ExecutionContext context); + +	/** +	 * Returns the an Array of {@link ProcessDefinition}s of the processes included in this module. +	 *  +	 * @return an array of resource uris of the processes included in this module. +	 */ +	String[] getProcessDefinitions(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java new file mode 100644 index 000000000..3e9f4cf14 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/TaskExecutionException.java @@ -0,0 +1,57 @@ +/* + * Copyright 2014 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.auth.modules; + +import at.gv.egovernment.moa.id.process.ProcessExecutionException; + +/** + * @author tlenz + * + */ +public class TaskExecutionException extends ProcessExecutionException { + +	private static final long serialVersionUID = 1L; +	Throwable originalException = null; +	 +	/** +	 * @param message +	 * @param cause +	 */ +	public TaskExecutionException(String message, Throwable cause) { +		super(message, cause); +		originalException = cause; +		 +	} + +	/** +	 * Get the original internal exception from task +	 *  +	 * @return the originalException +	 */ +	public Throwable getOriginalException() { +		return originalException; +	} +	 +	 +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java new file mode 100644 index 000000000..8ae4a9999 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthModuleImpl.java @@ -0,0 +1,28 @@ +package at.gv.egovernment.moa.id.auth.modules.internal; + +import org.apache.commons.lang3.StringUtils; + +import at.gv.egovernment.moa.id.auth.modules.AuthModule; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * Module descriptor + */ +public class DefaultAuthModuleImpl implements AuthModule { + +	@Override +	public int getPriority() { +		return 0; +	} + +	@Override +	public String selectProcess(ExecutionContext context) { +		return StringUtils.isBlank((String) context.get("ccc")) ? "DefaultAuthentication" : null; +	} + +	@Override +	public String[] getProcessDefinitions() { +		return new String[] { "classpath:at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml" }; +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java new file mode 100644 index 000000000..ed3089a41 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CertificateReadRequestTask.java @@ -0,0 +1,103 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.IOException;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.lang3.BooleanUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 +import at.gv.egovernment.moa.id.auth.builder.InfoboxReadRequestBuilderCertificate;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +/**
 + * Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Creates {@code InfoBoxReadRequest} in order to read the subject's certificates.</li>
 + * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code /VerifyCertificate}</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Responds with {@code InfoBoxReadRequest} (for CCE), {@code DataURL} is {@code /VerifyCertificate}</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class CertificateReadRequestTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +
 +		// TODO[branch]: Foreign citizen or mandate mode; respond with IRR for certificates, dataURL = "/VerifyCertificate"
 +		Logger.info("Send InfoboxReadRequest to BKU to get signer certificate.");
 +
 +		setNoCachingHeaders(resp);		
 +		try {
 +		
 +			String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("CertificateReadRequestTask", PARAM_SESSIONID, "auth.12");
 +			}
 +
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			boolean useMandate = session.getUseMandate();
 +			boolean identityLinkAvailable = BooleanUtils.isTrue((Boolean) executionContext.get("identityLinkAvailable"));
 +			
 +			if (!identityLinkAvailable && useMandate) {
 +				Logger.error("Online-Mandate Mode for foreign citizencs not supported.");
 +				throw new AuthenticationException("auth.13", null);
 +			}
 +
 +			// change MOASessionID
 +			AuthenticationSessionStoreage.changeSessionID(session);
 +			
 +			// create the InfoboxReadRequest to get the certificate
 +			String infoboxReadRequest = new InfoboxReadRequestBuilderCertificate().build(true);
 +
 +			// build dataurl (to the VerifyCertificateSerlvet)
 +			String dataurl = new DataURLBuilder().buildDataURL(session.getAuthURL(), REQ_VERIFY_CERTIFICATE,
 +					session.getSessionID());
 +
 +			ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest,
 +					AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);
 +		
 +		} catch (MOAIDException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +					
 +		} catch (IOException e) {
 +			throw new TaskExecutionException(e.getMessage(), e);
 +			
 +		} finally {
 +			ConfigurationDBUtils.closeSession();
 +		}		
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java new file mode 100644 index 000000000..ee6f0d5a4 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/CreateIdentityLinkFormTask.java @@ -0,0 +1,120 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.PrintWriter;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.apache.commons.lang3.ObjectUtils;
 +
 +import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +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.servlet.GenerateIFrameTemplateServlet;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.MiscUtil;
 +import at.gv.egovernment.moa.util.StringUtils;
 +
 +/**
 + * Creates a http form including an embedded {@code InfoBoxReadRequest} for reading the identity link.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Removes ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.</li>
 + * <li>Creates the http form mentioned above.</li>
 + * <li>Returns the http form via HttpServletResponse.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} <strong>or</strong></li>
 + * <li>ExecutionContext property {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID} (in case of legacy authentication without CCE selection, where the moa session is not provided by request parameter).</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>The identity link form via HttpServletResponse.</li>
 + * </ul>
 + * Possible branches:
 + * <ul>
 + * <li>In case of STORK authentication
 + * <ul>
 + * <li>Creates STORK auth SAML request.</li>
 + * <li>Creates and returns a form for submitting the SAML request to the CPEPS (post binding).</li>
 + * <li>Returns the form via HttpServletResponse.</li>
 + * </ul>
 + * </li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GenerateIFrameTemplateServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class CreateIdentityLinkFormTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +
 +		String moasessionid = StringEscapeUtils.escapeHtml(ObjectUtils.defaultIfNull(req.getParameter(PARAM_SESSIONID), (String) executionContext.get(PARAM_SESSIONID)));
 +		AuthenticationSession moasession = null;
 +		try {
 +			
 +			if (MiscUtil.isEmpty(moasessionid)) {
 +				Logger.warn("MOASessionID is empty.");
 +				throw new MOAIDException("auth.18", new Object[] {});
 +			}
 +			
 +			try {			
 +				moasession = AuthenticationSessionStoreage.getSession(moasessionid);
 +				AuthenticationSessionStoreage.changeSessionID(moasession);
 +				executionContext.remove(PARAM_SESSIONID);
 +			
 +			} catch (MOADatabaseException e) {
 +				Logger.info("MOASession with SessionID=" + moasessionid + " is not found in Database");
 +				throw new MOAIDException("init.04", new Object[] { moasessionid });
 +
 +			} catch (Throwable e) {
 +				Logger.info("No HTTP Session found!");
 +				throw new MOAIDException("auth.18", new Object[] {});
 +			}
 +
 +			StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();
 +			String getIdentityLinkForm = startauth.build(moasession, req, resp);
 +
 +			if (!StringUtils.isEmpty(getIdentityLinkForm)) {
 +				resp.setContentType("text/html;charset=UTF-8");
 +				PrintWriter out = new PrintWriter(resp.getOutputStream());
 +				out.print(getIdentityLinkForm);
 +				out.flush();
 +				Logger.debug("Finished GET " + GenerateIFrameTemplateServlet.class);
 +			}
 +			
 +		} catch (WrongParametersException ex) {
 +//			handleWrongParameters(ex, req, resp);
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +		}
 +
 +		catch (MOAIDException ex) {
 +//			handleError(null, ex, req, resp, pendingRequestID);
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +
 +		} catch (Exception e) {
 +			Logger.error("CreateIdentityLinkFormTask has an interal Error.", e);
 +			throw new TaskExecutionException(e.getMessage(), e);
 +
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java new file mode 100644 index 000000000..6bf68e2eb --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetForeignIDTask.java @@ -0,0 +1,185 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.ByteArrayInputStream;
 +import java.io.IOException;
 +import java.security.cert.CertificateException;
 +import java.util.Map;
 +
 +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.Element;
 +
 +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.CreateXMLSignatureResponse;
 +import at.gv.egovernment.moa.id.auth.data.IdentityLink;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.ParseException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +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.parser.CreateXMLSignatureResponseParser;
 +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
 +import at.gv.egovernment.moa.id.client.SZRGWClientException;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;
 +
 +/**
 + * Evaluates the {@code CreateXMLSignatureResponse}, extracts signature and certificate and asks the SZR Gateway for an identity link.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Parses the CreateXMLSignatureResponse retrieved from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Extracts signature and signer certificate.</li>
 + * <li>Send request to SZR Gateway in order to get an identity link.</li>
 + * <li>Updates moa session (sets identity link, QAA level 4, authentication data and foreigner flag).</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Identity link, QAA level 4 and foreigner flag put into moa session.</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetForeignIDServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class GetForeignIDTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +
 +		Logger.debug("POST GetForeignIDServlet");
 +
 +		setNoCachingHeaders(resp);
 +
 +		Map<String, String> parameters;
 +
 +		try {
 +			parameters = getParameters(req);
 +			
 +		} catch (FileUploadException | IOException e) {
 +			Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +			throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
 +		}
 +		
 +		String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +		String pendingRequestID = null;
 +		String redirectURL = null;
 +		AuthenticationSession session = null;
 +		try {
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("GetForeignID", PARAM_SESSIONID, "auth.12");
 +			}
 +			String xmlCreateXMLSignatureResponse = (String) parameters.get(PARAM_XMLRESPONSE);
 +			if (!ParamValidatorUtils.isValidXMLDocument(xmlCreateXMLSignatureResponse)) {
 +				throw new WrongParametersException("GetForeignID", PARAM_XMLRESPONSE, "auth.12");
 +			}
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +			session = AuthenticationServer.getSession(sessionID);
 +
 +			// change MOASessionID
 +			sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +
 +			Logger.debug(xmlCreateXMLSignatureResponse);
 +
 +			CreateXMLSignatureResponse csresp = new CreateXMLSignatureResponseParser(xmlCreateXMLSignatureResponse)
 +					.parseResponseDsig();
 +
 +			try {
 +				String serializedAssertion = DOMUtils.serializeNode(csresp.getDsigSignature());
 +				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 });
 +
 +			}
 +
 +			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 = AuthenticationServer.getInstance().getIdentityLink(signature);
 +
 +			if (null != response.getErrorResponse()) {
 +				// TODO fix exception parameter
 +				throw new SZRGWClientException("service.08", (String) response.getErrorResponse().getErrorCode(),
 +						(String) response.getErrorResponse().getInfo());
 +			} else {
 +				IdentityLinkAssertionParser ilParser = new IdentityLinkAssertionParser(new ByteArrayInputStream(
 +						response.getIdentityLink()));
 +				IdentityLink identitylink = ilParser.parseIdentityLink();
 +				session.setIdentityLink(identitylink);
 +
 +				// set QAA Level four in case of card authentifcation
 +				session.setQAALevel(PVPConstants.STORK_QAA_1_4);
 +
 +				AuthenticationServer.getInstance().getForeignAuthenticationData(session);
 +
 +				// session is implicit stored in changeSessionID!!!!
 +				String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +
 +				Logger.info("Changed MOASession " + sessionID + " to Session " + newMOASessionID);
 +				Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
 +
 +				redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(),
 +						ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID),
 +						newMOASessionID);
 +				redirectURL = resp.encodeRedirectURL(redirectURL);
 +
 +				// TODO[branch]: Final step back to /dispatcher
 +
 +				try {
 +					AuthenticationSessionStoreage.storeSession(session);
 +				} catch (MOADatabaseException e) {
 +					throw new MOAIDException("Session store error", null);
 +				}
 +
 +				resp.setContentType("text/html");
 +				resp.setStatus(302);
 +				resp.addHeader("Location", redirectURL);
 +				Logger.debug("REDIRECT TO: " + redirectURL);
 +			}
 +
 +		} catch (MOAIDException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +
 +		} catch (Exception e) {
 +			Logger.error("GetForeignIDServlet has an interal Error.", e);
 +			throw new TaskExecutionException(e.getMessage(), e);
 +
 +		}
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java new file mode 100644 index 000000000..4ff5672bd --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/GetMISSessionIDTask.java @@ -0,0 +1,183 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +import iaik.pki.PKIException;
 +
 +import java.security.GeneralSecurityException;
 +import java.util.List;
 +
 +import javax.net.ssl.SSLSocketFactory;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +import javax.xml.parsers.ParserConfigurationException;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +import org.xml.sax.SAXException;
 +
 +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.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.config.ConnectionParameter;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.SSLUtils;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +
 +/**
 + * Retrieves a mandate from the online mandate issuing service.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Retrieves the mandate referenced within the moa session from the online (external) mandate issuing service.</li>
 + * <li>Verifies the mandate.</li>
 + * <li>Puts mandate into moa session.</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Mandate put into moa session.</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.GetMISSessionIDServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class GetMISSessionIDTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +		
 +		Logger.debug("POST GetMISSessionIDServlet");
 +
 +		String sessionID = req.getParameter(PARAM_SESSIONID);
 +
 +		// escape parameter strings
 +		sessionID = StringEscapeUtils.escapeHtml(sessionID);
 +
 +		AuthenticationSession session = null;
 +		String pendingRequestID = null;
 +		try {
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID))
 +				throw new WrongParametersException("VerifyCertificate",
 +						PARAM_SESSIONID, "auth.12");
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +			
 +			session = AuthenticationServer.getSession(sessionID);
 +
 +			//change MOASessionID
 +		    sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +			
 +			String misSessionID = session.getMISSessionID();
 +
 +			AuthConfigurationProvider authConf = AuthConfigurationProvider
 +					.getInstance();
 +			ConnectionParameter connectionParameters = authConf
 +					.getOnlineMandatesConnectionParameter();
 +			SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(
 +					AuthConfigurationProvider.getInstance(),
 +					connectionParameters);
 +
 +			List<MISMandate> list = MISSimpleClient.sendGetMandatesRequest(
 +					connectionParameters.getUrl(), misSessionID, sslFactory);
 +
 +			if (list == null || list.size() == 0) {
 +				Logger.error("Keine Vollmacht gefunden.");
 +				throw new AuthenticationException("auth.15", null);
 +			}
 +
 +			// for now: list contains only one element
 +			MISMandate mandate = (MISMandate) list.get(0);
 +
 +			// TODO[tlenz]: UTF-8 ?
 +			String sMandate = new String(mandate.getMandate());
 +			if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {
 +				Logger.error("Mandate is empty.");
 +				throw new AuthenticationException("auth.15",
 +						new Object[] { GET_MIS_SESSIONID });
 +			}
 +						
 +			//check if it is a parsable XML
 +			byte[] byteMandate = mandate.getMandate();
 +			// TODO[tlenz]: UTF-8 ?
 +			String stringMandate = new String(byteMandate);
 +			DOMUtils.parseDocument(stringMandate, false,
 +					null, null).getDocumentElement();
 +			
 +			// extract RepresentationType
 +			AuthenticationServer.getInstance().verifyMandate(session, mandate);
 +			
 +			session.setMISMandate(mandate);
 +			session.setAuthenticatedUsed(false);
 +			session.setAuthenticated(true);
 +			
 +	    	//set QAA Level four in case of card authentifcation
 +	    	session.setQAALevel(PVPConstants.STORK_QAA_1_4);
 +			
 +			String oldsessionID = session.getSessionID();
 +			
 +			//Session is implicite stored in changeSessionID!!!
 +			String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +			
 +			Logger.info("Changed MOASession " + oldsessionID + " to Session " + newMOASessionID);
 +			Logger.info("Daten angelegt zu MOASession " + newMOASessionID);
 +						
 +			String redirectURL = new DataURLBuilder().buildDataURL(
 +					session.getAuthURL(),
 +					ModulUtils.buildAuthURL(session.getModul(),
 +							session.getAction(), pendingRequestID), newMOASessionID);
 +			redirectURL = resp.encodeRedirectURL(redirectURL);
 +			
 +			// TODO[branch]: Final step back to /dispatcher
 +			
 +			resp.setContentType("text/html");
 +			resp.setStatus(302);
 +			resp.addHeader("Location", redirectURL);
 +			Logger.debug("REDIRECT TO: " + redirectURL);
 +
 +		} catch (MOAIDException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +			
 +		} catch (GeneralSecurityException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +			
 +		} catch (PKIException e) {
 +			throw new TaskExecutionException(e.getMessage(), e);
 +			
 +		} catch (SAXException e) {
 +			throw new TaskExecutionException(e.getMessage(), e);
 +			
 +		} catch (ParserConfigurationException e) {
 +			throw new TaskExecutionException(e.getMessage(), e);
 +			
 +	    } catch (Exception e) {
 +	    	Logger.error("MISMandateValidation has an interal Error.", e);
 +	    	throw new TaskExecutionException(e.getMessage(), e);
 +	       
 +	    }
 +	    finally {
 +	    	ConfigurationDBUtils.closeSession();
 +	    }
 +		
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java new file mode 100644 index 000000000..3ae35bc24 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/PrepareAuthBlockSignatureTask.java @@ -0,0 +1,104 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +/**
 + * Creates {@code CreateXMLSignatureRequest} for auth block signature.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Creates {@code CreateXMLSignatureRequest} for auth block signature.</li>
 + * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code /VerifyAuthBlock}</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Responds with {@code CreateXMLSignatureRequest} (for CCE), {@code DataURL} is {@code /VerifyAuthBlock}</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class PrepareAuthBlockSignatureTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
 +
 +		Logger.debug("Process IdentityLink");
 +
 +		setNoCachingHeaders(resp);
 +		
 +		String pendingRequestID = null;
 +
 +		try {
 +			
 +			String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
 +			}
 +
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			// change MOASessionID
 +			sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +				
 +			Logger.info("Normal");
 +
 +			// TODO[branch]: Default behaviour; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
 +
 +			OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(
 +					session.getPublicOAURLPrefix());
 +			AuthConfigurationProvider authConf = AuthConfigurationProvider.getInstance();
 +
 +			String createXMLSignatureRequest = AuthenticationServer.getInstance()
 +					.getCreateXMLSignatureRequestAuthBlockOrRedirect(session, authConf, oaParam);
 +
 +			AuthenticationSessionStoreage.storeSession(session);
 +			
 +			ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session,
 +					createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT,
 +					"VerifyIdentityLink");
 +
 +		} catch (MOAIDException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +
 +		} catch (Exception e) {
 +			Logger.error("IdentityLinkValidation has an interal Error.", e);
 +			throw new TaskExecutionException(e.getMessage(), e);
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java new file mode 100644 index 000000000..64dcb0f41 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyAuthenticationBlockTask.java @@ -0,0 +1,250 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +import iaik.pki.PKIException;
 +
 +import java.io.IOException;
 +import java.security.GeneralSecurityException;
 +import java.util.List;
 +import java.util.Map;
 +
 +import javax.net.ssl.SSLSocketFactory;
 +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.Element;
 +
 +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.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.config.ConnectionParameter;
 +import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;
 +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;
 +import at.gv.egovernment.moa.id.moduls.ModulUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.SSLUtils;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISSessionId;
 +import at.gv.egovernment.moa.id.util.client.mis.simple.MISSimpleClient;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
 +
 +/**
 + * Verifies the signed authentication block (provided as {@code CreateXMLSignatureResponse}).<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Takes the {@code CreateXMLSignatureResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Verifies the {@code CreateXMLSignatureResponse}.</li>
 + * <li>Updates moa session.</li>
 + * <li>Redirects back to {@code /dispatcher} in order to finalize the authentication.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code CreateXMLSignatureResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Authentication data put into moa session.</li>
 + * <li>Redirect to {@code /dispatcher}.</li>
 + * </ul>
 + * Possible branches:
 + * <ul>
 + * <li>In case of mandate mode
 + * <ul>
 + * <li>Creates a mandate session at the external mandate issuing service.</li>
 + * <li>Redirects the user's browser to the online mandate issuing service GUI.</li>
 + * </ul>
 + * </li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class VerifyAuthenticationBlockTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyAuthenticationBlockServlet
 +		
 +		Logger.debug("POST VerifyAuthenticationBlock");
 +		
 +		String pendingRequestID = null;		
 +		
 +	    Map<String, String> parameters;
 +	    try 
 +	    {
 +	      parameters = getParameters(req);
 +	      
 +	    } catch (FileUploadException | IOException e) 
 +	    {
 +	      Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +	      throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
 +	    }
 +	      
 +			String sessionID = req.getParameter(PARAM_SESSIONID);
 +			String createXMLSignatureResponse = (String)parameters.get(PARAM_XMLRESPONSE);
 +
 +			// escape parameter strings
 +			sessionID = StringEscapeUtils.escapeHtml(sessionID);
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +		   		
 +			String redirectURL = null;
 +			try {
 +	         // check parameter
 +	         if (!ParamValidatorUtils.isValidSessionID(sessionID))
 +	            throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_SESSIONID, "auth.12");
 +	         if (!ParamValidatorUtils.isValidXMLDocument(createXMLSignatureResponse))
 +	            throw new WrongParametersException("VerifyAuthenticationBlock", PARAM_XMLRESPONSE, "auth.12");
 +
 +				AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +				//change MOASessionID
 +			    sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +				
 +				String authenticatedMOASessionId = AuthenticationServer.getInstance().verifyAuthenticationBlock(session, createXMLSignatureResponse);
 +				
 +				if (authenticatedMOASessionId == null) { 
 +					//mandate Mode
 +				
 +					  AuthConfigurationProvider authConf= AuthConfigurationProvider.getInstance();
 +						ConnectionParameter connectionParameters = authConf.getOnlineMandatesConnectionParameter();	
 +						SSLSocketFactory sslFactory = SSLUtils.getSSLSocketFactory(AuthConfigurationProvider.getInstance(), connectionParameters);
 +						
 +						// get identitity link as byte[]
 +						Element elem = session.getIdentityLink().getSamlAssertion();
 +						String s = DOMUtils.serializeNode(elem);
 +						
 +						//System.out.println("IDL: " + s);
 +						
 +						byte[] idl = s.getBytes("UTF-8");
 +						
 +						// redirect url
 +						// build redirect(to the GetMISSessionIdSerlvet)
 +						
 +						//change MOASessionID before MIS request
 +						String newMOASessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +						
 +				        redirectURL =
 +				              new DataURLBuilder().buildDataURL(
 +				                session.getAuthURL(),
 +				                GET_MIS_SESSIONID,
 +				                newMOASessionID);
 +						
 +				        String oaURL = session.getOAURLRequested();
 +				        OAAuthParameter oaParam = authConf.getOnlineApplicationParameter(oaURL);
 +				        List<String> profiles = oaParam.getMandateProfiles();
 +
 +				        if (profiles == null) {
 +				      	  Logger.error("No Mandate/Profile for OA configured.");
 +				      	  throw new AuthenticationException("config.21", new Object[] { GET_MIS_SESSIONID});
 +				        }
 +				        
 +				        String oaFriendlyName = oaParam.getFriendlyName();
 +				        String mandateReferenceValue = session.getMandateReferenceValue();
 +				        byte[] cert = session.getEncodedSignerCertificate();
 +				        byte[] authBlock = session.getAuthBlock().getBytes("UTF-8");
 +				        
 +				        //TODO: check in case of SSO!!!
 +				        String targetType = null;  
 +				        if(oaParam.getBusinessService()) {
 +				        	String id = oaParam.getIdentityLinkDomainIdentifier();
 +				        	if (id.startsWith(AuthenticationSession.REGISTERANDORDNR_PREFIX_))
 +				        		targetType = id;
 +				        	else
 +				        		targetType = AuthenticationSession.REGISTERANDORDNR_PREFIX_+session.getDomainIdentifier();
 +				        	
 +				        } else {
 +				        	targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
 +				        }
 +				        
 +				        MISSessionId misSessionID = MISSimpleClient.sendSessionIdRequest(
 +				        		connectionParameters.getUrl(), 
 +				        		idl, 
 +				        		cert, 
 +				        		oaFriendlyName, 
 +				        		redirectURL, 
 +				        		mandateReferenceValue, 
 +				        		profiles, 
 +				        		targetType,
 +				        		authBlock,
 +				        		sslFactory);
 +				        
 +				        if (misSessionID == null) {
 +				      	  Logger.error("Fehler bei Anfrage an Vollmachten Service. MIS Session ID ist null.");
 +				      	  throw new MISSimpleClientException("Fehler bei Anfrage an Vollmachten Service.");
 +				        }
 +				        
 +				        String redirectMISGUI = misSessionID.getRedirectURL();
 +				        session.setMISSessionID(misSessionID.getSessiondId());
 +					
 +						try {
 +							AuthenticationSessionStoreage.storeSession(session);
 +						} catch (MOADatabaseException e) {
 +							throw new MOAIDException("Session store error", null);
 +						}
 +				        
 +						// TODO[branch]: Mandate; redirect to MIS website; website redirects back to "/GetMISSessionID"
 +						
 +				        resp.setStatus(302);
 +				    	  resp.addHeader("Location", redirectMISGUI);
 +				    	  Logger.debug("REDIRECT TO: " + redirectURL);
 +				}
 +				else {
 +					// TODO[branch]: Final step back to /dispatcher
 +					redirectURL = new DataURLBuilder().buildDataURL(session.getAuthURL(), 
 +							ModulUtils.buildAuthURL(session.getModul(), session.getAction(), pendingRequestID), authenticatedMOASessionId);
 +							
 +					resp.setContentType("text/html");
 +					resp.setStatus(302);
 +				
 +					resp.addHeader("Location", redirectURL);		
 +					Logger.debug("REDIRECT TO: " + redirectURL);				
 +					
 +				}
 +				
 +			}
 +	    
 +			catch (MOAIDException ex) {
 +				throw new TaskExecutionException(ex.getMessage(), ex);
 +				
 +			} catch (GeneralSecurityException e) {
 +				throw new TaskExecutionException(e.getMessage(), e);
 +				
 +			} catch (PKIException e) {
 +				throw new TaskExecutionException(e.getMessage(), e);
 +				
 +			} catch (TransformerException e) {
 +				throw new TaskExecutionException(e.getMessage(), e);
 +				
 +		    } catch (Exception e) {
 +		    	Logger.error("AuthBlockValidation has an interal Error.", e);
 +		    	throw new TaskExecutionException(e.getMessage(), e);
 +		    	
 +		    }
 +		       
 +			
 +		    finally {
 +		    	ConfigurationDBUtils.closeSession();
 +		    }		
 +		
 +		
 +		
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java new file mode 100644 index 000000000..607641532 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyCertificateTask.java @@ -0,0 +1,163 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +import iaik.x509.X509Certificate;
 +
 +import java.io.IOException;
 +import java.util.Map;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.fileupload.FileUploadException;
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +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.exception.AuthenticationException;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.id.util.ServletUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.spss.util.CertificateUtils;
 +
 +/**
 + * Parses the certificate from {@code InfoBoxReadResponse} (via POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}), creates the auth block to be signed and returns a {@code CreateXMLSignatureRequest} for auth block signature.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Retrieves the certificate via {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Verifies the certificate.</li>
 + * <li>Creates the auth block to be signed using information from the certificate (Organwalter, foreign citizen.</li>
 + * <li>Puts it in a {@code CreateXMLSignatureRequest}.</li>
 + * <li>Updates moa session.</li>
 + * <li>Responds with {@code CreateXMLSignatureRequest}.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_SESSIONID} containing a {@code InfoBoxReadResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>{@code CreateXMLSignatureRequest} send as HttpServletResponse (for CCE).</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class VerifyCertificateTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyCertificateServlet
 +
 +		Logger.debug("POST VerifyCertificateServlet");
 +				
 +		Map<String, String> parameters;
 +	    try 
 +	    {
 +	      parameters = getParameters(req);
 +	    } catch (FileUploadException | IOException e) 
 +	    {
 +	      Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +	      throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
 +	     }
 +	    String sessionID = req.getParameter(PARAM_SESSIONID);
 +	    
 +	    // escape parameter strings
 +		sessionID = StringEscapeUtils.escapeHtml(sessionID);
 +				
 +	    AuthenticationSession session = null;
 +	    try {
 +	       // check parameter
 +	       if (!ParamValidatorUtils.isValidSessionID(sessionID))
 +	          throw new WrongParametersException("VerifyCertificate", PARAM_SESSIONID, "auth.12");
 +	       
 +	    	session = AuthenticationServer.getSession(sessionID);
 +	    	
 +	        //change MOASessionID
 +	        sessionID = AuthenticationSessionStoreage.changeSessionID(session);
 +	    	
 +    		X509Certificate cert = AuthenticationServer.getInstance().getCertificate(sessionID, parameters);
 +    		if (cert == null) {
 +    			Logger.error("Certificate could not be read.");
 +    			throw new AuthenticationException("auth.14", null);    		
 +    		}
 +    		
 +	    	boolean useMandate = session.getUseMandate();
 +	    	
 +	    	if (useMandate) {
 +
 +	    		// verify certificate for OrganWalter
 +	    		String createXMLSignatureRequestOrRedirect = AuthenticationServer.getInstance().verifyCertificate(session, cert);
 +	    		
 +		    	try {
 +					AuthenticationSessionStoreage.storeSession(session);
 +				} catch (MOADatabaseException e) {
 +					throw new MOAIDException("session store error", null);
 +				}
 +	    		
 +		    	// TODO[branch]: Mandate; respond with CXSR for authblock signature, dataURL "/VerifyAuthBlock"
 +		    	ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
 +	    		
 +	    	}
 +	    	else {
 +	    			
 +		    	
 +	    		String countrycode = CertificateUtils.getIssuerCountry(cert);
 +	    		if (countrycode != null) {
 +	    			if (countrycode.compareToIgnoreCase("AT") == 0) {
 +	    				Logger.error("Certificate issuer country code is \"AT\". Login not support in foreign identities mode.");
 +	    				throw new AuthenticationException("auth.22", null);
 +	    			}
 +	    		}
 +	    		
 +	    		// Foreign Identities Modus	
 +		    	String createXMLSignatureRequest = AuthenticationServer.getInstance().createXMLSignatureRequestForeignID(session, cert);
 +		      // build dataurl (to the GetForeignIDSerlvet)
 +		    	String dataurl =
 +	             new DataURLBuilder().buildDataURL(
 +	               session.getAuthURL(),
 +	               REQ_GET_FOREIGN_ID,
 +	               session.getSessionID());
 +	       
 +		    	try {
 +					AuthenticationSessionStoreage.storeSession(session);
 +				} catch (MOADatabaseException e) {
 +					throw new MOAIDException("session store error", null);
 +				}
 +		    	
 +	    		// TODO[branch]: Foreign citizen; respond with CXSR for authblock signature, dataURL "/GetForeignID"
 +		    	ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
 +		    	
 +		    	Logger.debug("Send CreateXMLSignatureRequest to BKU");
 +	    	}	    		    	 
 +	    }
 +	    catch (MOAIDException ex) {
 +	    	throw new TaskExecutionException(ex.getMessage(), ex);
 +	      
 +	    } catch (Exception e) {
 +	    	Logger.error("CertificateValidation has an interal Error.", e);
 +	    	throw new TaskExecutionException(e.getMessage(), e);
 +	    	
 +	    }
 +	       
 +	    
 +	    finally {
 +	    	ConfigurationDBUtils.closeSession();
 +	    }
 +
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java new file mode 100644 index 000000000..44557453a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/internal/tasks/VerifyIdentityLinkTask.java @@ -0,0 +1,102 @@ +package at.gv.egovernment.moa.id.auth.modules.internal.tasks;
 +
 +import static at.gv.egovernment.moa.id.auth.MOAIDAuthConstants.*;
 +
 +import java.io.IOException;
 +import java.util.Map;
 +
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.exception.ParseException;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.AbstractAuthServletTask;
 +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;
 +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 +import at.gv.egovernment.moa.id.process.api.ExecutionContext;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +import at.gv.egovernment.moa.logging.Logger;
 +
 +/**
 + * Verifies the identity link.<p/>
 + * In detail:
 + * <ul>
 + * <li>Renames the moa session id.</li>
 + * <li>Parses the identity link retrieved as {@code InfoBoxReadResponse} from POST parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE}.</li>
 + * <li>Verifies the identity link.</li>
 + * <li>Updates moa session.</li>
 + * <li>Puts boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
 + * </ul>
 + * Expects:
 + * <ul>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}</li>
 + * <li>HttpServletRequest parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_XMLRESPONSE PARAM_XMLRESPONSE} containing a {@code InfoBoxReadResponse}.</li>
 + * </ul>
 + * Result:
 + * <ul>
 + * <li>Identity link put into moa session.</li>
 + * <li>Boolean flag {@code identityLinkAvailable} into {@code ExecutionContext}.</li>
 + * </ul>
 + * Code taken from {@link at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet}.
 + * @see #execute(ExecutionContext, HttpServletRequest, HttpServletResponse)
 + *
 + */
 +public class VerifyIdentityLinkTask extends AbstractAuthServletTask {
 +
 +	@Override
 +	public void execute(ExecutionContext executionContext, HttpServletRequest req, HttpServletResponse resp)
 +			throws TaskExecutionException {
 +
 +		// note: code taken from at.gv.egovernment.moa.id.auth.servlet.VerifyIdentityLinkServlet
 +
 +		Logger.debug("POST VerifyIdentityLink");
 +
 +		setNoCachingHeaders(resp);
 +		
 +		Map<String, String> parameters;
 +
 +		try {
 +			parameters = getParameters(req);
 +		} catch (Exception e) {
 +			Logger.error("Parsing mulitpart/form-data request parameters failed: " + e.getMessage());
 +			throw new TaskExecutionException("Parsing mulitpart/form-data request parameters failed", new IOException(e.getMessage()));
 +		}
 +		
 +		try {
 +			
 +			String sessionID = StringEscapeUtils.escapeHtml(req.getParameter(PARAM_SESSIONID));
 +			// check parameter
 +			if (!ParamValidatorUtils.isValidSessionID(sessionID)) {
 +				throw new WrongParametersException("VerifyIdentityLink", PARAM_SESSIONID, "auth.12");
 +			}
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			boolean identityLinkAvailable = AuthenticationServer.getInstance().verifyIdentityLink(session, parameters) != null;
 +			AuthenticationSessionStoreage.storeSession(session);
 +
 +			executionContext.put("identityLinkAvailable", identityLinkAvailable);
 +
 +		} catch (ParseException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +
 +		} catch (MOAIDException ex) {
 +			throw new TaskExecutionException(ex.getMessage(), ex);
 +
 +		} catch (Exception e) {
 +			Logger.error("IdentityLinkValidation has an interal Error.", e);
 +			throw new TaskExecutionException(e.getMessage(), e);
 +			
 +		}
 +
 +		finally {
 +			ConfigurationDBUtils.closeSession();
 +		}
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java new file mode 100644 index 000000000..9c950366c --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/modules/registration/ModuleRegistration.java @@ -0,0 +1,149 @@ +package at.gv.egovernment.moa.id.auth.modules.registration; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.core.io.Resource; + +import at.gv.egovernment.moa.id.auth.modules.AuthModule; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * This class handles registering modules. The modules are detected either with + * the ServiceLoader mechanism or via Spring. All detected modules are ranked + * according to their priority. + */ +public class ModuleRegistration { + +	private static ModuleRegistration instance = new ModuleRegistration(); + +	private List<AuthModule> priorizedModules = new ArrayList<>(); + +	@Autowired +	private ApplicationContext ctx; + +	@Autowired +	private ProcessEngine processEngine; + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	public static ModuleRegistration getInstance() { +		return instance; +	} + +	private ModuleRegistration() { +	} + +	@PostConstruct +	private void init() { +		// load modules via the ServiceLoader +		initServiceLoaderModules(); + +		// load modules via Spring +		initSpringModules(); + +		// order modules according to their priority +		sortModules(); +	} +	 +	/** +	 * Discovers modules which use the ServiceLoader mechanism. +	 */ +	private void initServiceLoaderModules() { +		log.info("Looking for auth modules."); +		ServiceLoader<AuthModule> loader = ServiceLoader.load(AuthModule.class); +		Iterator<AuthModule> modules = loader.iterator(); +		while (modules.hasNext()) { +			AuthModule module = modules.next(); +			log.info("Detected module {}", module.getClass().getName()); +			registerModuleProcessDefinitions(module); +			priorizedModules.add(module); +		} +	} + +	/** +	 * Discovers modules which use Spring. +	 */ +	private void initSpringModules() { +		log.debug("Discovering Spring modules."); +		Map<String, AuthModule> modules = ctx.getBeansOfType(AuthModule.class); +		for (AuthModule module : modules.values()) { +			registerModuleProcessDefinitions(module); +			priorizedModules.add(module); +		} +	} + +	/** +	 * Registers the resource uris for the module. +	 *  +	 * @param module +	 *            the module. +	 */ +	private void registerModuleProcessDefinitions(AuthModule module) { +		for (String uri : module.getProcessDefinitions()) { +			Resource resource = ctx.getResource(uri); +			if (resource.isReadable()) { +				log.info("Registering process definition '{}'.", uri); +				try (InputStream processDefinitionInputStream = resource.getInputStream()) { +					processEngine.registerProcessDefinition(processDefinitionInputStream); +				} catch (IOException e) { +					log.error("Process definition '{}' could NOT be read.", uri, e); +				} catch (ProcessDefinitionParserException e) { +					log.error("Error while parsing process definition '{}'", uri, e); +				} +			} else { +				log.error("Process definition '{}' cannot be read.", uri); +			} +		} +	} + +	/** +	 * Order the modules in descending order according to their priority. +	 */ +	private void sortModules() { +		Collections.sort(priorizedModules, new Comparator<AuthModule>() { +			@Override +			public int compare(AuthModule thisAuthModule, AuthModule otherAuthModule) { +				int thisOrder = thisAuthModule.getPriority(); +				int otherOrder = otherAuthModule.getPriority(); +				return (thisOrder < otherOrder ? 1 : (thisOrder == otherOrder ? 0 : -1)); +			} +		}); +	} + +	/** +	 * Returns the process description id of the first process, in the highest ranked +	 * module, which is able to work with the given execution context. +	 *  +	 * @param context +	 *            the {@link ExecutionContext}. +	 * @return the process id or {@code null} +	 */ +	public String selectProcess(ExecutionContext context) { +		for (AuthModule module : priorizedModules) { +			String id = module.selectProcess(context); +			if (StringUtils.isNotEmpty(id)) { +				log.debug("Process with id '{}' selected, for context '{}'.", id, context); +				return id; +			} +		} +		log.info("No process is able to handle context '{}'.", context); +		return null; +	} +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java index e2802c1d2..a5783bfb7 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/IdentityLinkAssertionParser.java @@ -106,7 +106,7 @@ public class IdentityLinkAssertionParser {        + PDATA        + "Person";    /** Xpath expression to the PersonData GivenName element */       -  private static final String PERSON_GIVEN_NAME_XPATH = +  public static final String PERSON_GIVEN_NAME_XPATH =      PERSON_XPATH      	+ "/"        + PDATA @@ -114,7 +114,7 @@ public class IdentityLinkAssertionParser {        + PDATA        + "GivenName";    /** Xpath expression to the PersonData FamilyName element */ -  private static final String PERSON_FAMILY_NAME_XPATH = +  public static final String PERSON_FAMILY_NAME_XPATH =      PERSON_XPATH      	+ "/"        + PDATA @@ -122,7 +122,7 @@ public class IdentityLinkAssertionParser {        + PDATA        + "FamilyName";    /** Xpath expression to the PersonData DateOfBirth element */ -  private static final String PERSON_DATE_OF_BIRTH_XPATH = +  public static final String PERSON_DATE_OF_BIRTH_XPATH =      PERSON_XPATH      	+ "/"        + PDATA diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java index 1bc3702e4..f538d2d12 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/parser/StartAuthentificationParameterParser.java @@ -132,12 +132,13 @@ public class StartAuthentificationParameterParser implements MOAIDAuthConstants{  			String targetFriendlyNameConfig = oaParam.getTargetFriendlyName();  			if (StringUtils.isEmpty(targetConfig) -//					|| (module.equals(SAML1Protocol.PATH) &&  -//							!StringUtils.isEmpty(target))  +					|| (module.equals(SAML1Protocol.PATH) &&  +							!StringUtils.isEmpty(target))   				) { -			    	// no target attribut is given in OA config -			    	// target is used from request -			    	// check parameter +					//INFO: ONLY SAML1 legacy mode +			    	// if SAML1 is used and target attribute is given in request +			    	// use requested target +			    	// check target parameter  				if (!ParamValidatorUtils.isValidTarget(target)) {                      Logger.error("Selected target is invalid. Using target: " + target);  			   		throw new WrongParametersException("StartAuthentication", PARAM_TARGET, "auth.12"); @@ -211,8 +212,8 @@ public class StartAuthentificationParameterParser implements MOAIDAuthConstants{  	      authURL = authURL.concat(":" + req.getServerPort());  	    }  	    authURL = authURL.concat(req.getContextPath() + "/"); -				 -		if (!authURL.startsWith("https:")) + +		if (!authURL.startsWith("https:") && !AuthConfigurationProvider.getInstance().isHTTPAuthAllowed())  			throw new AuthenticationException("auth.07",  					new Object[] { authURL + "*" }); 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 e5b2c598c..c4c4b2691 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 @@ -66,14 +66,22 @@ import org.apache.commons.fileupload.FileItemFactory;  import org.apache.commons.fileupload.FileUploadException;  import org.apache.commons.fileupload.disk.DiskFileItemFactory;  import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils;  import at.gv.egovernment.moa.id.advancedlogging.StatisticLogger;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.entrypoints.DispatcherServlet; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessExecutionException;  import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;  import at.gv.egovernment.moa.id.storage.IExceptionStore;  import at.gv.egovernment.moa.id.util.ServletUtils; @@ -97,6 +105,11 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	protected static final String ERROR_CODE_PARAM = "errorid"; +	/** +	 * The process engine. +	 */ +	private ProcessEngine processEngine; +	  	@Override  	protected void doGet(HttpServletRequest req, HttpServletResponse resp)  			throws ServletException, IOException { @@ -174,29 +187,36 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	protected void handleError(String errorMessage, Throwable exceptionThrown,  			HttpServletRequest req, HttpServletResponse resp, String pendingRequestID) { -		if (null != errorMessage) { -			Logger.error(errorMessage); -			req.setAttribute("ErrorMessage", errorMessage); -		} - -		if (null != exceptionThrown) { -			if (null == errorMessage) -				errorMessage = exceptionThrown.getMessage(); -			Logger.error(errorMessage, exceptionThrown); -			req.setAttribute("ExceptionThrown", exceptionThrown); -		} - -		if (Logger.isDebugEnabled()) { -			req.setAttribute("LogLevel", "debug"); +		Throwable loggedException = null; +		 +		if (exceptionThrown != null  +				&& exceptionThrown instanceof ProcessExecutionException) { +			ProcessExecutionException procExc =  +					(ProcessExecutionException) exceptionThrown; +			if (procExc.getCause() != null &&  +					procExc.getCause() instanceof TaskExecutionException) { +				TaskExecutionException taskExc = (TaskExecutionException) procExc.getCause(); +				loggedException = taskExc.getOriginalException();	 +				if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) { +					Logger.error(exceptionThrown.getMessage(), exceptionThrown); +					 +				} else +					Logger.error(exceptionThrown.getMessage()); +								 +			}			  		} +		 +		if (loggedException == null) +			loggedException = exceptionThrown; +		 -		if (!(exceptionThrown instanceof MOAIDException)) { -			Logger.error("Receive an internal error: Message=" + exceptionThrown.getMessage(), exceptionThrown); +		if (!(loggedException instanceof MOAIDException)) { +			Logger.error("Receive an internal error: Message=" + loggedException.getMessage(), loggedException);  		}  		IExceptionStore store = DBExceptionStoreImpl.getStore(); -		String id = store.storeException(exceptionThrown); +		String id = store.storeException(loggedException);  		if (id != null && MiscUtil.isNotEmpty(pendingRequestID)) { @@ -217,7 +237,7 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  		} else {  			//Exception can not be stored in database -			handleErrorNoRedirect(errorMessage, exceptionThrown, req, resp); +			handleErrorNoRedirect(errorMessage, loggedException, req, resp);  		}  	} @@ -454,4 +474,31 @@ public class AuthServlet extends HttpServlet implements MOAIDAuthConstants {  	} + +	/** +	 * Returns the underlying process engine instance. +	 *  +	 * @return The process engine (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 */ +	public synchronized ProcessEngine getProcessEngine() { +		if (processEngine == null) { +			WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); +			if (ctx == null) { +				throw new IllegalStateException( +						"Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment."); +			} +			processEngine = ctx.getBean(ProcessEngine.class); +		} +		return processEngine; +	} +	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java index 2ef8ab5ec..ad4776a45 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/GenerateIFrameTemplateServlet.java @@ -23,52 +23,42 @@  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;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang.StringEscapeUtils; -import at.gv.egovernment.moa.id.auth.MOAIDAuthInitializer; -import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration;  import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.commons.db.dao.config.TemplateType;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; + +import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.moduls.RequestStorage; +import at.gv.egovernment.moa.id.protocols.saml1.SAML1Protocol; + +import at.gv.egovernment.moa.id.process.ExecutionContextImpl; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.api.ExecutionContext;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; -import at.gv.egovernment.moa.id.util.MOAIDMessageProvider;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.FileUtils;  import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.egovernment.moa.util.StringUtils;  public class GenerateIFrameTemplateServlet extends AuthServlet {  	private static final long serialVersionUID = 1L; -	public void init(ServletConfig servletConfig) throws ServletException { -//		    try { -//		      super.init(servletConfig); -//		      MOAIDAuthInitializer.initialize(); -//		      Logger.debug("default platform file.encoding: " + System.getProperty("file.encoding")); -//		      Logger.info(MOAIDMessageProvider.getInstance().getMessage("init.00", null)); -//		    } -//		    catch (Exception ex) { -//		      Logger.fatal(MOAIDMessageProvider.getInstance().getMessage("init.02", null), ex); -//		      throw new ServletException(ex); -//		    } -	} -	    	protected void doGet(HttpServletRequest req, HttpServletResponse resp)  			throws ServletException, IOException {  		Logger.info("Receive " + GenerateIFrameTemplateServlet.class + " Request"); @@ -95,7 +85,7 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  	    	    moasession = AuthenticationSessionStoreage.getSession(moasessionid); -	    	    AuthenticationSessionStoreage.changeSessionID(moasession); +//	    	    AuthenticationSessionStoreage.changeSessionID(moasession);  			} catch (MOADatabaseException e) {  				Logger.info("MOASession with SessionID="+ moasessionid + " is not found in Database"); @@ -116,11 +106,15 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  			else { -				//load Parameters from config -		    	String target = oaParam.getTarget(); - - - +				//get Target from config or from request in case of SAML 1				 +				String target = null; +				IRequest pendingReq = RequestStorage.getPendingRequest(pendingRequestID); +				if (MiscUtil.isNotEmpty(pendingReq.getTarget()) &&  +						pendingReq.requestedModule().equals(SAML1Protocol.PATH)) +					target = pendingReq.getTarget(); +				else +					target = oaParam.getTarget(); +				  		    	String bkuURL = oaParam.getBKUURL(bkuid);  		    	if (MiscUtil.isEmpty(bkuURL)) {  		    		Logger.info("No OA specific BKU defined. Use BKU from default configuration"); @@ -161,28 +155,37 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  		    											   moasession.getAction(),  		    											   req);  			} -			 -		    StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance();			 -		    String getIdentityLinkForm = startauth.build(moasession, req, resp); -			 -			//store MOASession + +			ExecutionContext ec = new ExecutionContextImpl(); +			// set execution context +			ec.put("ccc", moasession.getCcc()); +			ec.put("useMandate", moasession.getUseMandate()); +			ec.put("bkuURL", moasession.getBkuURL()); + +			// select and create process instance +			String processDefinitionId = ModuleRegistration.getInstance().selectProcess(ec); +			String processInstanceId = getProcessEngine().createProcessInstance(processDefinitionId, ec); + +			if (processDefinitionId == null) { +				Logger.warn("No suitable process found for SessionID " + moasession.getSessionID()); +				throw new MOAIDException("process.02", new Object[] { moasession.getSessionID() }); +			} + +			// keep process instance id in moa session +			moasession.setProcessInstanceId(processInstanceId); + +			// make sure moa session has been persisted before running the process  			try {  				AuthenticationSessionStoreage.storeSession(moasession); -				  			} catch (MOADatabaseException e) {  				Logger.error("Database Error! MOASession is not stored!"); -				throw new MOAIDException("init.04", new Object[] { -						moasession.getSessionID()}); +				throw new MOAIDException("init.04", new Object[] { moasession.getSessionID() });  			} -		     -		    if (!StringUtils.isEmpty(getIdentityLinkForm)) { -		    	resp.setContentType("text/html;charset=UTF-8"); -		    	PrintWriter out = new PrintWriter(resp.getOutputStream()); -		    	out.print(getIdentityLinkForm); -		    	out.flush(); -		    	Logger.debug("Finished GET "+GenerateIFrameTemplateServlet.class); -		    } -	    }  + +			// start process +			getProcessEngine().start(processInstanceId); + +		}  	    catch (WrongParametersException ex) {  	    	handleWrongParameters(ex, req, resp);  	    } @@ -199,4 +202,13 @@ public class GenerateIFrameTemplateServlet extends AuthServlet {  	    	ConfigurationDBUtils.closeSession();  	    }  	} + +	 +	 +	 +	 +	 +	 +	 +  } 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 bbc704f22..41c2a9c6a 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 @@ -69,6 +69,7 @@ import at.gv.egovernment.moa.id.auth.data.IdentityLink;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
  import at.gv.egovernment.moa.id.auth.exception.ParseException;
  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetForeignIDTask;
  import at.gv.egovernment.moa.id.auth.parser.CreateXMLSignatureResponseParser;
  import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
  import at.gv.egovernment.moa.id.client.SZRGWClientException; @@ -85,6 +86,7 @@ import at.gv.util.xsd.srzgw.CreateIdentityLinkResponse;   * Servlet requested for getting the foreign eID
   * provided by the security layer implementation.
   * Utilizes the {@link AuthenticationServer}.
 + * @deprecated Use {@link GetForeignIDTask} instead.
   *
   */
  public class GetForeignIDServlet extends AuthServlet {
 @@ -134,6 +136,8 @@ public class GetForeignIDServlet extends AuthServlet {  		Logger.debug("POST GetForeignIDServlet");
 +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
 +		
  		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);
 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 9e2e845b5..043b660c1 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 @@ -67,6 +67,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetMISSessionIDTask;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.config.ConnectionParameter;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; @@ -83,7 +84,7 @@ import at.gv.egovernment.moa.util.DOMUtils;  /**   * Servlet requested for getting the foreign eID provided by the security layer   * implementation. Utilizes the {@link AuthenticationServer}. - *  + * @deprecated Use {@link GetMISSessionIDTask} instead.   */  public class GetMISSessionIDServlet extends AuthServlet { @@ -136,6 +137,8 @@ public class GetMISSessionIDServlet extends AuthServlet {  		Logger.debug("POST GetMISSessionIDServlet"); +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more."); +		  		resp.setHeader(MOAIDAuthConstants.HEADER_EXPIRES,  				MOAIDAuthConstants.HEADER_VALUE_EXPIRES);  		resp.setHeader(MOAIDAuthConstants.HEADER_PRAGMA, @@ -197,6 +200,7 @@ public class GetMISSessionIDServlet extends AuthServlet {  			// for now: list contains only one element  			MISMandate mandate = (MISMandate) list.get(0); +			// TODO[tlenz]: UTF-8 ?  			String sMandate = new String(mandate.getMandate());  			if (sMandate == null || sMandate.compareToIgnoreCase("") == 0) {  				Logger.error("Mandate is empty."); @@ -206,6 +210,7 @@ public class GetMISSessionIDServlet extends AuthServlet {  			//check if it is a parsable XML  			byte[] byteMandate = mandate.getMandate(); +			// TODO[tlenz]: UTF-8 ?  			String stringMandate = new String(byteMandate);  			DOMUtils.parseDocument(stringMandate, false,  					null, null).getDocumentElement(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java deleted file mode 100644 index e04f97e6e..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/MonitoringServlet.java +++ /dev/null @@ -1,126 +0,0 @@ -/******************************************************************************* - * Copyright 2014 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.auth.servlet; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Arrays; -import java.util.List; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import at.gv.egovernment.moa.id.config.ConfigurationException; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.id.monitoring.TestManager; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class MonitoringServlet extends AuthServlet { - -	private static final long serialVersionUID = 1L; -	private static final String REQUEST_ATTR_MODULE = "module"; -	 -	 -	  protected void doGet(HttpServletRequest req, HttpServletResponse resp) -			    throws ServletException, IOException { -		   -		  try { -			AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -			 -			if (config.isMonitoringActive()) { -				Logger.debug("Monitoring Servlet received request"); - -				TestManager tests = TestManager.getInstance(); -				 -				String modulename = req.getParameter(REQUEST_ATTR_MODULE); -				if (MiscUtil.isEmpty(modulename)) { -				 -					List<String> error = tests.executeTests(); -					if (error != null && error.size() > 0) { -						createErrorMessage(req, resp, error); -						 -					} else { -						resp.setStatus(HttpServletResponse.SC_OK); -						resp.setContentType("text/html;charset=UTF-8"); -						resp.getWriter().write(getHtml(config.getMonitoringMessageSuccess())); -						Logger.info("Monitoring Servlet finished without errors"); -					} -					 -				} else { -					if (tests.existsModule(modulename)) { -						List<String> errors = tests.executeTest(modulename); -						if (errors != null && errors.size() > 0) { -							createErrorMessage(req, resp, errors); -							 -						} else { -							resp.setStatus(HttpServletResponse.SC_OK); -							resp.setContentType("text/html;charset=UTF-8"); -							resp.getWriter().write(getHtml(config.getMonitoringMessageSuccess())); -							Logger.info("Monitoring Servlet finished without errors"); -						} -						 -					} else { -						Logger.warn("NO Testmodule exists with modulename " + modulename); -						resp.setStatus(HttpServletResponse.SC_NOT_FOUND); -						resp.setContentType("text/html;charset=UTF-8"); -						PrintWriter out; -						try { -							out = new PrintWriter(resp.getOutputStream()); -							out.write("NO Testmodule exists with modulename " + modulename); -							out.flush(); -							     -						} catch (IOException e) { -							Logger.warn("Internal Monitoring Servlet Error. ", e); -						}  -					} -					 -				}	 -			} -			   -		} catch (ConfigurationException e) { -			createErrorMessage(req, resp, Arrays.asList(e.getMessage())); -		} -	  } -	   -	  private void createErrorMessage(HttpServletRequest req, HttpServletResponse resp, List<String> errorMessage) { -		  Logger.warn("Monitoring Servlet found some Error: " + errorMessage); -		  resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); -		  resp.setContentType("text/html;charset=UTF-8"); -		  PrintWriter out; -		  try { -			  out = new PrintWriter(resp.getOutputStream()); -			  for (String error : errorMessage) -				  out.write(error + "<br>"); -			  out.flush(); -			   -		  } catch (IOException e) { -			  Logger.warn("Internal Monitoring Servlet Error. ", e); -		  }  -	  } -	   -	private String getHtml(String text) { -		return "<html><head><title>Reponse</title></head><body>" + text +"</body></html>"; -	} -} 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 index 3dd2afd96..24daa76a3 100644 --- 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 @@ -28,8 +28,10 @@ import java.io.IOException;  import java.io.InputStream;
  import java.io.StringWriter;
  import java.net.URL;
 +import java.text.SimpleDateFormat;
  import java.util.ArrayList;
  import java.util.Arrays;
 +import java.util.Date;
  import java.util.List;
  import java.util.Properties;
 @@ -48,6 +50,8 @@ import org.apache.velocity.Template;  import org.apache.velocity.VelocityContext;
  import org.apache.velocity.app.VelocityEngine;
  import org.opensaml.saml2.core.StatusCode;
 +import org.w3c.dom.Element;
 +import org.w3c.dom.Node;
  import at.gv.egovernment.moa.id.auth.AuthenticationServer;
  import at.gv.egovernment.moa.id.auth.builder.DataURLBuilder;
 @@ -55,6 +59,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.data.IdentityLink;
  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
 +import at.gv.egovernment.moa.id.auth.parser.IdentityLinkAssertionParser;
  import at.gv.egovernment.moa.id.auth.stork.STORKException;
  import at.gv.egovernment.moa.id.auth.stork.STORKResponseProcessor;
  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
 @@ -65,9 +70,12 @@ import at.gv.egovernment.moa.id.moduls.ModulUtils;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;
  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
  import at.gv.egovernment.moa.id.util.HTTPUtils;
 +import at.gv.egovernment.moa.id.util.IdentityLinkReSigner;
  import at.gv.egovernment.moa.id.util.VelocityProvider;
  import at.gv.egovernment.moa.logging.Logger;
 +import at.gv.egovernment.moa.util.DOMUtils;
  import at.gv.egovernment.moa.util.StringUtils;
 +import at.gv.egovernment.moa.util.XPathUtils;
  import at.gv.util.xsd.xmldsig.SignatureType;
  import at.gv.util.xsd.xmldsig.X509DataType;
  import eu.stork.oasisdss.api.ApiUtils;
 @@ -98,6 +106,7 @@ import javax.xml.ws.BindingProvider;  /**
   * Endpoint for receiving STORK response messages
 + * @deprecated Use {@link at.gv.egovernment.moa.id.auth.modules.stork.tasks.PepsConnectorTask} instead.
   */
  public class PEPSConnectorServlet extends AuthServlet {
 @@ -149,6 +158,8 @@ public class PEPSConnectorServlet extends AuthServlet {  		try {
 +			Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
 +
  			Logger.info("PEPSConnector Servlet invoked, expecting C-PEPS message.");
  			Logger.debug("This ACS endpoint is: " + HTTPUtils.getBaseURL(request));
 @@ -192,6 +203,15 @@ public class PEPSConnectorServlet extends AuthServlet {  			Logger.debug("STORK response: ");
  			Logger.debug(authnResponse.toString());
 +			// do PEPS-conform logging for easier evaluation
 +			try {
 +				// 2015-03-12 16:44:27.144#S-PEPS receives response from C-PEPS#orig_msg_id id2 (in response to)#orig_msg_id id1 (in response to)#status#msghash#msg_id id3#
 +				Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS receives response from C-PEPS#" + 
 +						authnResponse.getInResponseTo() + "#NA#" + authnResponse.getMessage() + "#_hash_#" + authnResponse.getSamlId() + "#");
 +			} catch (Exception e1) {
 +				Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage());
 +			}
 +  			Logger.debug("Trying to find MOA Session-ID ...");			
  		    //String moaSessionID = request.getParameter(PARAM_SESSIONID);
  			//first use SAML2 relayState 
 @@ -434,14 +454,61 @@ public class PEPSConnectorServlet extends AuthServlet {  	        	targetType = AuthenticationSession.TARGET_PREFIX_ + oaParam.getTarget();
  	        }
 -			Logger.debug("Starting connecting SZR Gateway");
 -			//contact SZR Gateway
  			IdentityLink identityLink = null;
  			try {
 -				identityLink = STORKResponseProcessor.connectToSZRGateway(authnResponse.getPersonalAttributeList(),
 +				AuthConfigurationProvider config = AuthConfigurationProvider.getInstance();
 +				if(config.isStorkFakeIdLActive() && config.getStorkFakeIdLCountries().contains(storkAuthnRequest.getCitizenCountryCode())) {
 +					// create fake IdL
 +					// - fetch IdL template from resources
 +					InputStream s = PEPSConnectorServlet.class.getResourceAsStream("/resources/xmldata/fakeIdL_IdL_template.xml");
 +					Element idlTemplate = DOMUtils.parseXmlValidating(s);
 +
 +				    identityLink = new IdentityLinkAssertionParser(idlTemplate).parseIdentityLink();
 +
 +				    // replace data
 +		            Element idlassertion = identityLink.getSamlAssertion();
 +		            // - set bpk/wpbk;
 +			        Node prIdentification = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_IDENT_VALUE_XPATH);
 +			        if(!STORKResponseProcessor.hasAttribute("eIdentifier", attributeList))
 +			        	throw new STORKException("eIdentifier is missing");
 +			        String eIdentifier = STORKResponseProcessor.getAttributeValue("eIdentifier", attributeList, false);
 +			        prIdentification.getFirstChild().setNodeValue(eIdentifier);
 +
 +			        // - set last name
 +			        Node prFamilyName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_FAMILY_NAME_XPATH);
 +			        if(!STORKResponseProcessor.hasAttribute("surname", attributeList))
 +			        	throw new STORKException("surname is missing");
 +					String familyName = STORKResponseProcessor.getAttributeValue("surname", attributeList, false);
 +					prFamilyName.getFirstChild().setNodeValue(familyName);
 +
 +			        // - set first name
 +			        Node prGivenName = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_GIVEN_NAME_XPATH);
 +			        if(!STORKResponseProcessor.hasAttribute("givenName", attributeList))
 +			        	throw new STORKException("givenName is missing");
 +					String givenName = STORKResponseProcessor.getAttributeValue("givenName", attributeList, false);
 +					prGivenName.getFirstChild().setNodeValue(givenName);
 +
 +			        // - set date of birth
 +			        Node prDateOfBirth = XPathUtils.selectSingleNode(idlassertion, IdentityLinkAssertionParser.PERSON_DATE_OF_BIRTH_XPATH);
 +			        if(!STORKResponseProcessor.hasAttribute("dateOfBirth", attributeList))
 +			        	throw new STORKException("dateOfBirth is missing");
 +					String dateOfBirth = STORKResponseProcessor.getAttributeValue("dateOfBirth", attributeList, false);
 +					prDateOfBirth.getFirstChild().setNodeValue(dateOfBirth);
 +
 +		            identityLink = new IdentityLinkAssertionParser(idlassertion).parseIdentityLink();
 +
 +		            //resign IDL
 +					IdentityLinkReSigner identitylinkresigner = IdentityLinkReSigner.getInstance();
 +					Element resignedilAssertion = identitylinkresigner.resignIdentityLink(identityLink.getSamlAssertion(), config.getStorkFakeIdLResigningKey());
 +					identityLink = new IdentityLinkAssertionParser(resignedilAssertion).parseIdentityLink();
 +				} else {
 +					//contact SZR Gateway
 +					Logger.debug("Starting connecting SZR Gateway");
 +					identityLink = STORKResponseProcessor.connectToSZRGateway(authnResponse.getPersonalAttributeList(),
  																		  oaParam.getFriendlyName(), 
  																		  targetType, null, 
  																		  oaParam.getMandateProfiles(), citizenSignature);
 +				}
  			} catch (STORKException e) {
  				// this is really nasty but we work against the system here. We are supposed to get the gender attribute from
  				// stork. If we do not, we cannot register the person in the ERnP - we have to have the
 @@ -498,6 +565,15 @@ public class PEPSConnectorServlet extends AuthServlet {  			// stork did the authentication step
  			moaSession.setAuthenticated(true);
 +			// do PEPS-conform logging for easier evaluation
 +			try {
 +				// 2015-03-12 16:44:27.144#S-PEPS generates response to SP#orig_msg_id id1 (in response to)#status#msghash#msg_id id4#
 +				Logger.info(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()) + "#S-PEPS generates response to SP#" + 
 +						"#NA#" + authnResponse.getMessage() + "#_hash_#" + moaSession.getProcessInstanceId() + "#");
 +			} catch (Exception e1) {
 +				Logger.info("STORK PEPS conform logging failed because of: " + e1.getMessage());
 +			}
 +
  //			//TODO: found better solution, but QAA Level in response could be not supported yet
  //			try {
  //
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java index 3bc79f8bd..337a9ed31 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/PEPSConnectorWithLocalSigningServlet.java @@ -109,6 +109,7 @@ import eu.stork.peps.exceptions.STORKSAMLEngineException;  /**   * Endpoint for receiving STORK response messages + * @deprecated Use {@link at.gv.egovernment.moa.id.auth.modules.stork.tasks.PepsConnectorHandleResponseWithoutSignatureTask} instead.   */  public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  	private static final long serialVersionUID = 1L; @@ -131,6 +132,8 @@ public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  	 */  	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException   	{ +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more."); +  		String moaSessionID1 = request.getParameter("moaSessionID");	  		String signResponse = request.getParameter("signresponse");	  		Logger.info("moaSessionID1:"+moaSessionID1); @@ -473,6 +476,7 @@ public class PEPSConnectorWithLocalSigningServlet extends AuthServlet {  						Logger.info("Found AttributeProviderPlugin attribute:"+ap.getAttributes());  						if(ap.getAttributes().equalsIgnoreCase("signedDoc"))  						{ +							// FIXME[tlenz]: A servlet's class field is not thread safe.  							oasisDssWebFormURL = ap.getUrl();  							found = true;  							Logger.info("Loaded signedDoc attribute provider url from config:"+oasisDssWebFormURL); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java new file mode 100644 index 000000000..43b6c03d4 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/ProcessEngineSignalServlet.java @@ -0,0 +1,101 @@ +package at.gv.egovernment.moa.id.auth.servlet;
 +
 +import java.io.IOException;
 +
 +import javax.servlet.ServletException;
 +import javax.servlet.http.HttpServletRequest;
 +import javax.servlet.http.HttpServletResponse;
 +
 +import org.apache.commons.lang.StringEscapeUtils;
 +
 +import at.gv.egovernment.moa.id.auth.AuthenticationServer;
 +import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;
 +import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;
 +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;
 +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 +import at.gv.egovernment.moa.id.util.ParamValidatorUtils;
 +
 +/**
 + * Servlet that resumes a suspended process (in case of asynchronous tasks).
 + * 
 + * @author tknall
 + * 
 + */
 +public class ProcessEngineSignalServlet extends AuthServlet {
 +
 +	private static final long serialVersionUID = 1L;
 +	
 +	/**
 +	 * Sets response headers that prevent caching (code taken from {@link AuthServlet}).
 +	 * 
 +	 * @param resp
 +	 *            The HttpServletResponse.
 +	 */
 +	private void setNoCachingHeaders(HttpServletResponse resp) {
 +		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);
 +	}
 +
 +	/**
 +	 * Processes a GET request, delegating the call to {@link #doPost(HttpServletRequest, HttpServletResponse)}.
 +	 */
 +	@Override
 +	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 +		this.doPost(req, resp);
 +	}
 +
 +	/**
 +	 * Resumes the current process instance that has been suspended due to an asynchronous task. The process instance is
 +	 * retrieved from the MOA session referred to by the request parameter {@linkplain at.gv.egovernment.moa.id.auth.MOAIDAuthConstants#PARAM_SESSIONID PARAM_SESSIONID}.
 +	 */
 +	@Override
 +	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 +		String sessionID = StringEscapeUtils.escapeHtml(getMoaSessionId(req));
 +
 +		setNoCachingHeaders(resp);		
 +		String pendingRequestID = null;
 +		try {
 +			
 +			if (sessionID == null) {
 +				throw new IllegalStateException("Unable to determine MOA session id.");
 +			}
 +
 +			// retrieve moa session
 +			pendingRequestID = AuthenticationSessionStoreage.getPendingRequestID(sessionID);
 +			AuthenticationSession session = AuthenticationServer.getSession(sessionID);
 +
 +			// process instance is mandatory
 +			if (session.getProcessInstanceId() == null) {
 +				throw new IllegalStateException("MOA session does not provide process instance id.");
 +			}
 +
 +			// wake up next task
 +			getProcessEngine().signal(session.getProcessInstanceId());
 +
 +		} catch (Exception ex) {
 +			handleError(null, ex, req, resp, pendingRequestID);
 +		} finally {
 +			MOASessionDBUtils.closeSession();
 +		}
 +
 +	}
 +
 +	/**
 +	 * Retrieves the current MOA session id from the HttpServletRequest parameter
 +	 * {@link MOAIDAuthConstants#PARAM_SESSIONID}.
 +	 * <p/>
 +	 * Note that this class/method can be overwritten by modules providing their own strategy of retrieving the
 +	 * respective MOA session id.
 +	 * 
 +	 * @param request
 +	 *            The unterlying HttpServletRequest.
 +	 * @return The current MOA session id.
 +	 */
 +	public String getMoaSessionId(HttpServletRequest request) {
 +		return StringEscapeUtils.escapeHtml(request.getParameter(PARAM_SESSIONID));
 +	}
 +
 +}
 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 e7fa9cbd7..a8fe71485 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 @@ -71,6 +71,7 @@ import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyAuthenticationBlockTask;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.ConnectionParameter; @@ -92,6 +93,7 @@ import at.gv.egovernment.moa.util.DOMUtils;   *    * @author Paul Ivancsics   * @version $Id$ + * @deprecated Use {@link VerifyAuthenticationBlockTask} instead.   */  public class VerifyAuthenticationBlockServlet extends AuthServlet { @@ -153,6 +155,8 @@ public class VerifyAuthenticationBlockServlet extends AuthServlet {  		Logger.debug("POST VerifyAuthenticationBlock"); +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more."); +  		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); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java index a3397f561..2aa717a65 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyCertificateServlet.java @@ -65,6 +65,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;
  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;
  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException;
 +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyCertificateTask;
  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;
  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;
  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;
 @@ -77,6 +78,7 @@ import at.gv.egovernment.moa.spss.util.CertificateUtils;   * Servlet requested for getting the foreign eID
   * provided by the security layer implementation.
   * Utilizes the {@link AuthenticationServer}.
 + * @deprecated Use {@link VerifyCertificateTask} instead.
   *
   */
  public class VerifyCertificateServlet extends AuthServlet {
 @@ -126,6 +128,8 @@ public class VerifyCertificateServlet extends AuthServlet {  		Logger.debug("POST VerifyCertificateServlet");
 +		Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");
 +
  		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);
 @@ -180,7 +184,8 @@ public class VerifyCertificateServlet extends AuthServlet {  					throw new MOAIDException("session store error", null);
  				}
 -	    		ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
 +		    	ServletUtils.writeCreateXMLSignatureRequestOrRedirect(resp, session, createXMLSignatureRequestOrRedirect, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyCertificate");
 +	    		
  	    	}
  	    	else {
 @@ -208,8 +213,7 @@ public class VerifyCertificateServlet extends AuthServlet {  					throw new MOAIDException("session store error", null);
  				}
 -		    	ServletUtils.writeCreateXMLSignatureRequest(resp, session, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
 -		    	
 +		    	ServletUtils.writeCreateXMLSignatureRequest(resp, createXMLSignatureRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "GetForeignID", dataurl);
  		    	Logger.debug("Send CreateXMLSignatureRequest to BKU");
  	    	}	    		    	 
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java index 3b503f07b..b8e57ed43 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/VerifyIdentityLinkServlet.java @@ -53,7 +53,6 @@ import javax.servlet.ServletException;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; -import org.apache.commons.fileupload.FileUploadException;  import org.apache.commons.lang.StringEscapeUtils;  import at.gv.egovernment.moa.id.auth.AuthenticationServer; @@ -65,8 +64,8 @@ import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.exception.ParseException;  import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; +import at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyIdentityLinkTask;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; -import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; @@ -82,6 +81,7 @@ import at.gv.egovernment.moa.logging.Logger;   *   * @author Paul Ivancsics   * @version $Id$ + * @deprecated Use {@link VerifyIdentityLinkTask} instead.   */  public class VerifyIdentityLinkServlet extends AuthServlet { @@ -135,6 +135,8 @@ public class VerifyIdentityLinkServlet extends AuthServlet {      throws ServletException, IOException {  		Logger.debug("POST VerifyIdentityLink"); +	 +	Logger.warn(getClass().getName() + " is deprecated and should not be used any more.");      Map<String, String> parameters;      String pendingRequestID = null; @@ -201,7 +203,7 @@ public class VerifyIdentityLinkServlet extends AuthServlet {                    session.getSessionID()); -          ServletUtils.writeCreateXMLSignatureRequest(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl); +          ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);      	    } @@ -231,7 +233,7 @@ public class VerifyIdentityLinkServlet extends AuthServlet {       		  //ServletUtils.writeCreateXMLSignatureRequestURLEncoded(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);       		  Logger.debug("ContentType set to: text/xml;charset=UTF-8 (ServletUtils)"); -     		  ServletUtils.writeCreateXMLSignatureRequest(resp, session, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl); +     		  ServletUtils.writeCreateXMLSignatureRequest(resp, infoboxReadRequest, AuthenticationServer.REQ_PROCESS_VALIDATOR_INPUT, "VerifyIdentityLink", dataurl);      		}	      		else { 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 index 7113dcf70..3809ec4bc 100644 --- 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 @@ -39,6 +39,7 @@ import javax.xml.transform.TransformerFactoryConfigurationError;  import javax.xml.transform.stream.StreamSource;
  import org.apache.commons.io.IOUtils;
 +import org.apache.commons.lang3.StringEscapeUtils;
  import at.gv.egovernment.moa.id.auth.AuthenticationServer;
  import at.gv.egovernment.moa.id.auth.data.ExtendedSAMLAttribute;
 @@ -102,7 +103,7 @@ public class STORKResponseProcessor {  	private static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList) throws STORKException {
  		return getAttributeValue(attributeName, attributeList, true);
  	}
 -	private static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList, boolean throwException) throws STORKException {
 +	public static String getAttributeValue(String attributeName, IPersonalAttributeList attributeList, boolean throwException) throws STORKException {
  		try {
  			String result = attributeList.get(attributeName).getValue().get(0);
  			Logger.trace(attributeName + " : " + result);
 @@ -286,6 +287,12 @@ public class STORKResponseProcessor {  			Object attributeValue = attribute.getValue();
  			if (null == attributeValue)
  				attributeValue = attribute.getComplexValue();
 +
 +			// escape attributeValue
 +			attributeValue = StringEscapeUtils.escapeXml10(attributeValue.toString());
 +			// and remove trailing and tailing brackets. Might break something but we never saw an array with more than one entry!
 +			attributeValue = ((String) attributeValue).substring(1, ((String) attributeValue).length() - 1);
 +
  			ExtendedSAMLAttribute extendedSAMLAttribute = 
  				new ExtendedSAMLAttributeImpl(attribute.getName(), attributeValue, Constants.STORK_NS_URI, 0);
  			moaExtendedSAMLAttributeList.add(extendedSAMLAttribute);
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java index e1cd59c26..61b26b59a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/validator/parep/client/szrgw/SZRGWClient.java @@ -65,6 +65,7 @@ import org.w3c.dom.NodeList;  import org.w3c.dom.Text;
  import at.gv.egovernment.moa.id.auth.validator.parep.ParepUtils;
 +import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport;
  import at.gv.egovernment.moa.util.Constants;
  import at.gv.egovernment.moa.util.DOMUtils;
 @@ -137,7 +138,7 @@ public class SZRGWClient {        if (address == null) {
          throw new NullPointerException("Address (SZR-gateway ServiceURL) must not be null.");
        }
 -      HttpClient client = new HttpClient();
 +      HttpClient client = HttpClientWithProxySupport.getHttpClient();
        PostMethod method = new PostMethod(address);
        method.setRequestHeader("SOAPAction", "");
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java index 88ed7885f..24def1e02 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/ConfigurationProvider.java @@ -124,7 +124,7 @@ public class ConfigurationProvider {  	protected String certstoreDirectory; -	protected boolean trustmanagerrevoationchecking; +	protected boolean trustmanagerrevoationchecking = true;  	/**  		 * Returns the main configuration file directory used to configure MOA-ID diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java index b02c0946c..828bf99ca 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/AuthConfigLoader.java @@ -40,7 +40,7 @@ public class AuthConfigLoader implements Runnable {  			try {  				Thread.sleep(INTERVAL * 1000); -				Logger.info("check for new config."); +				Logger.trace("check for new config.");  				MOAIDConfiguration moaidconfig = ConfigurationDBRead.getMOAIDConfiguration();  				if (moaidconfig != null) {									 @@ -77,7 +77,7 @@ public class AuthConfigLoader implements Runnable {  	public static void start() {  		// start the session cleanup thread -		Thread configLoader = new Thread(new AuthConfigLoader()); +		Thread configLoader = new Thread(new AuthConfigLoader(), "AuthConfigLoader");  		configLoader.setName("ConfigurationLoader");  		configLoader.setDaemon(true);  		configLoader.setPriority(Thread.MIN_PRIORITY); 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 89d02c183..6a2f2db44 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 @@ -53,6 +53,7 @@ import java.io.IOException;  import java.math.BigInteger;  import java.net.MalformedURLException;  import java.util.ArrayList; +import java.util.Arrays;  import java.util.Date;  import java.util.HashMap;  import java.util.List; @@ -110,10 +111,10 @@ import at.gv.egovernment.moa.id.config.auth.data.ProtocolAllowed;  import at.gv.egovernment.moa.id.config.legacy.BuildFromLegacyConfig;  import at.gv.egovernment.moa.id.config.stork.STORKConfig;  import at.gv.egovernment.moa.id.data.IssuerAndSerial; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore;  import at.gv.egovernment.moa.id.protocols.pvp2x.config.MOADefaultBootstrap;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.util.config.EgovUtilConfiguration;  import at.gv.util.config.EgovUtilPropertiesConfiguration;  /** @@ -344,6 +345,7 @@ public class AuthConfigurationProvider extends ConfigurationProvider {  				config.addAnnotatedClass(OldSSOSessionIDStore.class);  				config.addAnnotatedClass(ExceptionStore.class);  				config.addAnnotatedClass(InterfederationSessionStore.class); +				config.addAnnotatedClass(ProcessInstanceStore.class);  				config.addProperties(moaSessionProp);  				MOASessionDBUtils.initHibernate(config, moaSessionProp); @@ -1007,6 +1009,49 @@ public class AuthConfigurationProvider extends ConfigurationProvider {  		  return null;    } +  /** +   * Checks if is fakeIdL is activated. +   * +   * @return true, if fake IdLs are available for stork +   */ +  public boolean isStorkFakeIdLActive() { +	  String prop = props.getProperty("stork.fakeIdL.active", "false"); +	  return Boolean.valueOf(prop); +  } + +  /** +   * Gets the countries which will receive a fake IdL +   * +   * @return the countries +   */ +  public List<String> getStorkFakeIdLCountries() { +	  String prop = props.getProperty("stork.fakeIdL.countries", ""); +	  return Arrays.asList(prop.replaceAll(" ", "").split(",")); +  } + +  /** +   * Gets the resigning key (group) for the stork fake IdL. +   * +   * @return the resigning key +   */ +  public String getStorkFakeIdLResigningKey() { +	  String prop = props.getProperty("stork.fakeIdL.keygroup"); +	  if (MiscUtil.isNotEmpty(prop)) +		  return prop; +	  else +		  return null; +  } + +  /** +   * Gets the countries for which it is configured to require no signature +   * +   * @return the stork no signature countries +   */ +  public List<String> getStorkNoSignatureCountries() { +	  String prop = props.getProperty("stork.fakeIdL.noSignatureCountries", ""); +	  return Arrays.asList(prop.replaceAll(" ", "").split(",")); +  } +    public boolean isMonitoringActive() {  	  String prop = props.getProperty("configuration.monitoring.active", "false");  	  return Boolean.valueOf(prop); @@ -1027,7 +1072,14 @@ public class AuthConfigurationProvider extends ConfigurationProvider {  	  else  		  return null;    } -   + +  // allow http to be used in call, used in systems proxied on the same instance +  public boolean isHTTPAuthAllowed() { +		String prop = props.getProperty("configuration.localhttpallowed.active", "false"); +		return Boolean.valueOf(prop); +  } + +    public boolean isAdvancedLoggingActive() {  	  String prop = props.getProperty("configuration.advancedlogging.active", "false");  	  return Boolean.valueOf(prop); @@ -1047,12 +1099,19 @@ public class AuthConfigurationProvider extends ConfigurationProvider {  	  return !Boolean.valueOf(prop);	      } +    //Load document service url from moa properties    public String getDocumentServiceUrl() {  	  String prop = props.getProperty("stork.documentservice.url", "false");  	  return prop;      } + +  public boolean isPVPSchemaValidationActive() { +	  String prop = props.getProperty("protocols.pvp2.schemavalidation", "true"); +	  return Boolean.valueOf(prop);	   +  } +      /**     * Returns the STORK Configuration     * @return STORK Configuration @@ -1084,10 +1143,11 @@ private void setCertStoreDirectory() throws ConfigurationException {    private void setTrustManagerRevocationChecking() throws ConfigurationException {  	  AuthComponentGeneral auth = getAuthComponentGeneral(); -	  if (auth.getGeneralConfiguration() != null)		   +	  if (auth.getGeneralConfiguration() != null && +			  auth.getGeneralConfiguration().isTrustManagerRevocationChecking() != null)		    		  trustmanagerrevoationchecking = auth.getGeneralConfiguration().isTrustManagerRevocationChecking();  	  else { -		  Logger.warn("Error in MOA-ID Configuration. No CertStoreDirectory defined."); +		  Logger.warn("No TrustMangerRevoationChecking defined. Use default value = TRUE");  		  throw new ConfigurationException("config.02", null);  	  }     } 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 90b72b72b..933dddb31 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 @@ -46,6 +46,7 @@  package at.gv.egovernment.moa.id.config.auth; +import java.io.IOException;  import java.security.PrivateKey;  import java.util.ArrayList;  import java.util.HashMap; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java index 787a480f0..b7d5ebed5 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/auth/data/BPKDecryptionParameters.java @@ -55,10 +55,12 @@ public class BPKDecryptionParameters implements Serializable{  	/**  	 * @return +	 * @throws IOException   	 */ -	public PrivateKey getPrivateKey() {		 +	public PrivateKey getPrivateKey() { +		InputStream in = null;  		try { -			InputStream in = new ByteArrayInputStream(keyStore); +			in = new ByteArrayInputStream(keyStore);  			KeyStore store = KeyStoreUtils.loadKeyStore(in , keyStorePassword);  		    char[] chPassword = " ".toCharArray(); @@ -83,6 +85,14 @@ public class BPKDecryptionParameters implements Serializable{  		} catch (NoSuchAlgorithmException e) {  			Logger.error("Can not load private key from keystore.", e); +		} finally { +			if (in != null) { +				try { +					in.close(); +				} catch (IOException e) { +					Logger.warn("Close InputStream failed." , e); +				} +			}			  		}  		return null;		 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java index 9067d8fc4..3d4b53f7c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/config/legacy/BuildFromLegacyConfig.java @@ -151,6 +151,8 @@ public class BuildFromLegacyConfig {  	    	if (genericConfiguration.containsKey(ConfigurationProvider.TRUST_MANAGER_REVOCATION_CHECKING))  	    		authGeneral.setTrustManagerRevocationChecking(  	    				Boolean.valueOf((String)genericConfiguration.get(ConfigurationProvider.TRUST_MANAGER_REVOCATION_CHECKING))); +	    	else +	    		authGeneral.setTrustManagerRevocationChecking(true);  	    	if (genericConfiguration.containsKey(ConfigurationProvider.DIRECTORY_CERTSTORE_PARAMETER_PROPERTY))  	    		authGeneral.setCertStoreDirectory( diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java index 65c413ef9..05b008515 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationData.java @@ -133,7 +133,9 @@ public class AuthenticationData  implements IAuthData, Serializable {  	  private String authBlock = null;   	  private List<String> encbPKList = null; +	  //ISA 1.18 attributes  	  private List<AuthenticationRole> roles = null; +	  private String pvpAttribute_OU = null;  	  private boolean useMandate = false;  	  private MISMandate mandate = null; @@ -707,6 +709,7 @@ public class AuthenticationData  implements IAuthData, Serializable {  		return roles;  	} +	//ISA 1.18 attributes  	/**  	 * @param roles the roles to set  	 */ @@ -716,26 +719,31 @@ public class AuthenticationData  implements IAuthData, Serializable {  		this.roles.add(role);  	} +	 +	/** +	 * @return the pvpAttribute_OU +	 */ +	public String getPvpAttribute_OU() { +		return pvpAttribute_OU; +	} + +	/** +	 * @param pvpAttribute_OU the pvpAttribute_OU to set +	 */ +	public void setPvpAttribute_OU(String pvpAttribute_OU) { +		this.pvpAttribute_OU = pvpAttribute_OU; +	}  	/* (non-Javadoc)  	 * @see at.gv.egovernment.moa.id.data.IAuthData#isBusinessService()  	 */  	@Override  	public boolean isBusinessService() { -		// TODO Auto-generated method stub  		return this.businessService;  	}  	public void setIsBusinessService(boolean flag) {  		this.businessService = flag; -	} - -	 -	 - -	 - -	 -	 +	}	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java index 8915b2442..b3b29f6c5 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/AuthenticationRoleFactory.java @@ -26,6 +26,7 @@ import java.util.Arrays;  import java.util.List;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil;  /**   * @author tlenz @@ -51,23 +52,29 @@ public class AuthenticationRoleFactory {  			List<String> param = Arrays.asList(params.split(","));  			String test = new String();  			for (String el : param) { -				test = test.concat(el); -				if (!test.endsWith("\\") ||  -						(test.endsWith("\\\\") && !test.endsWith("\\\\\\")) ) { -					String[] keyValue = test.split("="); -					if (keyValue.length < 2) { -						role.addParameter(keyValue[0].trim(), ""); -						Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim()); +				if (MiscUtil.isNotEmpty(el)) { +					test = test.concat(el); +					if (!test.endsWith("\\") ||  +							(test.endsWith("\\\\") && !test.endsWith("\\\\\\")) ) { +						String[] keyValue = test.split("="); +						if (keyValue.length < 2) { +							role.addParameter(keyValue[0].trim(), ""); +							Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim()); -					} else { -						role.addParameter(keyValue[0].trim(), keyValue[1].trim()); -						Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim()  -								+ " value=" + keyValue[1].trim()); +						} else { +							role.addParameter(keyValue[0].trim(), keyValue[1].trim()); +							Logger.debug("Add authentication roleparameter with key=" + keyValue[0].trim()  +									+ " value=" + keyValue[1].trim()); -					} +						} -					test = new String(); -				}									 +						test = new String(); +						 +					} else {  +						test = test.substring(0, test.length()-1).concat(","); +						 +					} +				}  			}			  		} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java index ebbf62ce7..ccc90a031 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/data/IAuthData.java @@ -69,7 +69,9 @@ public interface IAuthData {  	 IdentityLink getIdentityLink();  	 byte[] getSignerCertificate();  	 String getAuthBlock(); -	  + +	 //ISA 1.18 attributes +	 String getPvpAttribute_OU();  	 List<AuthenticationRole> getAuthenticationRoles();  	 boolean isPublicAuthority(); @@ -90,5 +92,6 @@ public interface IAuthData {  	 String getCcc();  	 STORKAuthnRequest getStorkAuthnRequest();  	 String getStorkAuthnResponse(); -	 IPersonalAttributeList getStorkAttributes();	 	  +	 IPersonalAttributeList getStorkAttributes(); +	 	   } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java index 03cb6c1c4..e3b7524ae 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/entrypoints/DispatcherServlet.java @@ -23,7 +23,6 @@  package at.gv.egovernment.moa.id.entrypoints;  import java.io.IOException; -  import java.util.Iterator;  import javax.servlet.ServletConfig; @@ -97,10 +96,13 @@ public class DispatcherServlet extends AuthServlet{  		boolean useSSOOA = false;  		String protocolRequestID = null; -		  		try {  			Logger.info("REQUEST: " + req.getRequestURI());  			Logger.info("QUERY  : " + req.getQueryString()); +			 + +// *** start of error handling *** +			  			String errorid = req.getParameter(ERROR_CODE_PARAM);  			if (errorid != null) { @@ -117,7 +119,7 @@ public class DispatcherServlet extends AuthServlet{  					pendingRequestID = (String) idObject;   				} -				if (throwable != null) {					 +				if (throwable != null) {  						IRequest errorRequest = null;  						if (pendingRequestID != null) { @@ -173,6 +175,11 @@ public class DispatcherServlet extends AuthServlet{  				return;  			} +// *** end of error handling *** + +			 +// *** start of protocol specific stuff *** +  			Object moduleObject = req.getParameter(PARAM_TARGET_MODULE);  			String module = null;  			if (moduleObject != null && (moduleObject instanceof String)) { @@ -272,7 +279,7 @@ public class DispatcherServlet extends AuthServlet{  							//create interfederated MOASession  							String sessionID =   									AuthenticationSessionStoreage.createInterfederatedSession(protocolRequest, true, ssoId); -							req.getParameterMap().put(PARAM_SESSIONID, sessionID); +							req.getParameterMap().put(PARAM_SESSIONID, new String[]{ sessionID });  							Logger.info("PreProcessing of SSO interfederation response complete. "); @@ -357,7 +364,11 @@ public class DispatcherServlet extends AuthServlet{  					}  				} -								 +						 +// *** end of protocol specific stuff *** +				 +// *** start handling authentication *** +				  				AuthenticationManager authmanager = AuthenticationManager.getInstance();									  				String moasessionID = null; @@ -473,7 +484,11 @@ public class DispatcherServlet extends AuthServlet{  					//build authenticationdata from session information and OA configuration  					authData = AuthenticationDataBuilder.buildAuthenticationData(protocolRequest, moasession);					  				} -										 + +// *** end handling authentication *** + +// *** start finalizing authentication (SSO, final redirects, statistic logging etc) *** +				  				SLOInformationInterface assertionID = moduleAction.processRequest(protocolRequest, req, resp, authData);  				RequestStorage.removePendingRequest(protocolRequestID); @@ -506,6 +521,8 @@ public class DispatcherServlet extends AuthServlet{  				} +// *** end finalizing authentication *** +  			} catch (Throwable e) {  				Logger.warn("An authentication error occured: ", e);;  				// Try handle module specific, if not possible rethrow diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java index a4d63b144..49f3df25c 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/moduls/AuthenticationManager.java @@ -59,17 +59,17 @@ import org.opensaml.ws.message.encoder.MessageEncodingException;  import org.opensaml.ws.soap.common.SOAPException;  import org.opensaml.xml.XMLObject;  import org.opensaml.xml.security.SecurityException; +import org.springframework.beans.factory.annotation.Autowired;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.builder.LoginFormBuilder;  import at.gv.egovernment.moa.id.auth.builder.SendAssertionFormBuilder; -import at.gv.egovernment.moa.id.auth.builder.StartAuthenticationBuilder;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.BuildException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException; +import at.gv.egovernment.moa.id.auth.modules.registration.ModuleRegistration;  import at.gv.egovernment.moa.id.auth.parser.StartAuthentificationParameterParser; -import at.gv.egovernment.moa.id.auth.servlet.AuthServlet;  import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore;  import at.gv.egovernment.moa.id.commons.db.dao.session.OASessionStore;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; @@ -77,6 +77,12 @@ import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.data.SLOInformationContainer;  import at.gv.egovernment.moa.id.data.SLOInformationImpl; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; + +import at.gv.egovernment.moa.id.process.ExecutionContextImpl; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVPTargetConfiguration;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding; @@ -87,32 +93,33 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;  import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.id.protocols.stork2.MOASTORKRequest;  import at.gv.egovernment.moa.id.storage.AssertionStorage;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; +import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper;  import at.gv.egovernment.moa.id.util.ParamValidatorUtils;  import at.gv.egovernment.moa.id.util.Random;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil; -import at.gv.egovernment.moa.util.StringUtils; -public class AuthenticationManager extends AuthServlet { +public class AuthenticationManager implements MOAIDAuthConstants { -	private static AuthenticationManager instance = null; -	 -	private static final long serialVersionUID = 1L; +	private static final AuthenticationManager INSTANCE = new AuthenticationManager();  	public static final String MOA_SESSION = "MoaAuthenticationSession";  	public static final String MOA_AUTHENTICATED = "MoaAuthenticated";  	public static final int SLOTIMEOUT = 30 * 1000; //30 sec +	@Autowired +	private ProcessEngine processEngine; +	 +	private AuthenticationManager() { +	} +	  	public static AuthenticationManager getInstance() { -		if (instance == null) { -			instance = new AuthenticationManager(); -		} -		 -		return instance; +		return INSTANCE;  	}  	/** @@ -320,7 +327,7 @@ public class AuthenticationManager extends AuthServlet {  		try {  			authSession = AuthenticationSessionStoreage  					.getSession(moaSessionID); -		 +  			if(authSession == null) {  				Logger.info("NO MOA Authentication data for ID " + moaSessionID);  				return; @@ -381,6 +388,7 @@ public class AuthenticationManager extends AuthServlet {  		//get IDP metadata  		try {  			OAAuthParameter idp = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(target.getRequestedIDP()); +			OAAuthParameter sp = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(target.getOAURL());  			if (!idp.isInderfederationIDP() || !idp.isInboundSSOInterfederationAllowed()) {  				Logger.info("Requested interfederation IDP " + target.getRequestedIDP() + " is not valid for interfederation."); @@ -389,7 +397,7 @@ public class AuthenticationManager extends AuthServlet {  				return;  			}  -						 +			  			EntityDescriptor idpEntity = MOAMetadataProvider.getInstance().  					getEntityDescriptor(target.getRequestedIDP()); @@ -409,7 +417,7 @@ public class AuthenticationManager extends AuthServlet {  							redirectEndpoint == null )  						redirectEndpoint = sss;  				} -				 +								  				if (redirectEndpoint != null) {  					AuthnRequest authReq = SAML2Utils @@ -422,16 +430,10 @@ public class AuthenticationManager extends AuthServlet {  					authReq.setAssertionConsumerServiceIndex(0);  					authReq.setIssueInstant(new DateTime()); -					Subject subject = SAML2Utils.createSAMLObject(Subject.class); -					NameID name = SAML2Utils.createSAMLObject(NameID.class); -					Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class); -					 +					Issuer issuer = SAML2Utils.createSAMLObject(Issuer.class);					  					String serviceURL = PVPConfiguration.getInstance().getIDPPublicPath(); -					name.setValue(serviceURL);  					issuer.setValue(serviceURL); -					subject.setNameID(name); -					authReq.setSubject(subject);  					issuer.setFormat(NameIDType.ENTITY);  					authReq.setIssuer(issuer);  					NameIDPolicy policy = SAML2Utils @@ -446,13 +448,55 @@ public class AuthenticationManager extends AuthServlet {  							SAML2Utils.createSAMLObject(RequestedAuthnContext.class);  					AuthnContextClassRef authnClassRef =  -							SAML2Utils.createSAMLObject(AuthnContextClassRef.class);					 -					authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); +							SAML2Utils.createSAMLObject(AuthnContextClassRef.class); +					 +					if (sp != null && sp.isSTORKPVPGateway()){ +						//use PVP SecClass instead of STORK QAA level +						String secClass = null; +						if (target instanceof MOASTORKRequest) { +							 +							try { +								MOASTORKRequest storkReq = (MOASTORKRequest) target;	 +								secClass = PVPtoSTORKMapper.getInstance().mapToSecClass( +										PVPConstants.STORK_QAA_PREFIX + storkReq.getStorkAuthnRequest().getQaa()); +							 +							} catch (Exception e) { +								Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); + +							}							 +						} +						 +						if (MiscUtil.isNotEmpty(secClass)) +							authnClassRef.setAuthnContextClassRef(secClass); +						else +							authnClassRef.setAuthnContextClassRef("http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-3"); +											 +					} else { +						if (target instanceof MOASTORKRequest) { +							//use requested QAA level from STORK request +							try { +								MOASTORKRequest storkReq = (MOASTORKRequest) target; +								authnClassRef.setAuthnContextClassRef( +										PVPConstants.STORK_QAA_PREFIX + storkReq.getStorkAuthnRequest().getQaa()); +								Logger.debug("Use STORK-QAA level " + authnClassRef.getAuthnContextClassRef()  +										+ " from STORK request"); +								 +							} catch (Exception e) { +								Logger.warn("STORK-QAA level can not read from STORK request. Use default QAA 4", e); +								 +							} +							 +						} +						 +						if (MiscUtil.isEmpty(authnClassRef.getAuthnContextClassRef()))						 +							authnClassRef.setAuthnContextClassRef("http://www.stork.gov.eu/1.0/citizenQAALevel/4"); +						 +					} +					  					reqAuthContext.setComparison(AuthnContextComparisonTypeEnumeration.MINIMUM);					  					reqAuthContext.getAuthnContextClassRefs().add(authnClassRef);					  					authReq.setRequestedAuthnContext(reqAuthContext); -					 -					 +										  					IEncoder binding = null;  					if (redirectEndpoint.getBinding().equals(  							SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { @@ -508,7 +552,10 @@ public class AuthenticationManager extends AuthServlet {  			throws ServletException, IOException, MOAIDException {  		Logger.debug("Starting authentication on this IDP ..."); -		setNoCachingHeadersInHttpRespone(request, 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);  		List<String> legacyallowed_prot = AuthConfigurationProvider.getInstance().getLegacyAllowedProtocols(); @@ -529,79 +576,95 @@ public class AuthenticationManager extends AuthServlet {  			throw new MOAIDException("init.04", new Object[] {});  		} -		 -		if (legacyallowed && legacyparamavail) { -			 -			//parse request parameter into MOASession			 -			StartAuthentificationParameterParser.parse(request, response, moasession, target); -							 -		    Logger.info("Start Authentication Module: " + moasession.getModul()  -		    		+ " Action: " + moasession.getAction()); -					     -		    StartAuthenticationBuilder startauth = StartAuthenticationBuilder.getInstance(); -			 -		    String getIdentityLinkForm = startauth.build(moasession, request, response); -			 -			//store MOASession -			try { -				AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());				 -			} catch (MOADatabaseException e) { -				Logger.error("Database Error! MOASession is not stored!"); -				throw new MOAIDException("init.04", new Object[] { -						moasession.getSessionID()}); -			} -		     -		    if (!StringUtils.isEmpty(getIdentityLinkForm)) { -		    	response.setContentType("text/html;charset=UTF-8"); -		    	PrintWriter out = new PrintWriter(response.getOutputStream()); -		    	out.print(getIdentityLinkForm); -		    	out.flush(); -		    	Logger.debug("Finished GET StartAuthentication"); -		    } -			 -		} else { -			//load Parameters from OnlineApplicationConfiguration -			OAAuthParameter oaParam = AuthConfigurationProvider.getInstance() -					.getOnlineApplicationParameter(target.getOAURL()); +		try { -			if (oaParam == null) { -				throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() }); -			} -							 -			else { +			if (legacyallowed && legacyparamavail) { -				//check if an MOASession exists and if not create an new MOASession -				//moasession = getORCreateMOASession(request); +				//parse request parameter into MOASession			 +				StartAuthentificationParameterParser.parse(request, response, moasession, target); +								 +			    Logger.info("Start Authentication Module: " + moasession.getModul()  +			    		+ " Action: " + moasession.getAction()); +	 +				// create execution context +				ExecutionContext executionContext = new ExecutionContextImpl(); +				executionContext.put("ccc", moasession.getCcc()); +				executionContext.put("useMandate", moasession.getUseMandate()); +				executionContext.put("bkuURL", moasession.getBkuURL()); +				executionContext.put(PARAM_SESSIONID, moasession.getSessionID()); -				//set OnlineApplication configuration in Session -				moasession.setOAURLRequested(target.getOAURL()); -				moasession.setAction(target.requestedAction()); -				moasession.setModul(target.requestedModule()); -			} -						 -			//Build authentication form -			 -			 -			String publicURLPreFix = AuthConfigurationProvider.getInstance().getPublicURLPrefix(); -			String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(),  -					target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); -			 -			//store MOASession -			try { -				AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());				 -			} catch (MOADatabaseException e) { -				Logger.error("Database Error! MOASession is not stored!"); -				throw new MOAIDException("init.04", new Object[] { -						moasession.getSessionID()}); +				// create process instance +				String processDefinitionId = ModuleRegistration.getInstance().selectProcess(executionContext); + +				if (processDefinitionId == null) { +					Logger.warn("No suitable process found for SessionID " + moasession.getSessionID() ); +					throw new MOAIDException("process.02",new Object[] { +							moasession.getSessionID()}); +				} + +				String processInstanceId = processEngine.createProcessInstance(processDefinitionId, executionContext); + +				// keep process instance id in moa session +				moasession.setProcessInstanceId(processInstanceId); + +				// make sure moa session has been persisted before running the process +				try { +					AuthenticationSessionStoreage.storeSession(moasession); +				} catch (MOADatabaseException e) { +					Logger.error("Database Error! MOASession is not stored!"); +					throw new MOAIDException("init.04", new Object[] { +							moasession.getSessionID()}); +				} + +		    	// start process +				processEngine.start(processInstanceId); +			     +			} else { +				//load Parameters from OnlineApplicationConfiguration +				OAAuthParameter oaParam = AuthConfigurationProvider.getInstance() +						.getOnlineApplicationParameter(target.getOAURL()); +				 +				if (oaParam == null) { +					throw new AuthenticationException("auth.00", new Object[] { target.getOAURL() }); +				} +								 +				else { +					 +					//check if an MOASession exists and if not create an new MOASession +					//moasession = getORCreateMOASession(request); +	 +					//set OnlineApplication configuration in Session +					moasession.setOAURLRequested(target.getOAURL()); +					moasession.setAction(target.requestedAction()); +					moasession.setModul(target.requestedModule()); +				} +							 +				//Build authentication form +				 +				 +				String publicURLPreFix = AuthConfigurationProvider.getInstance().getPublicURLPrefix(); +				String loginForm = LoginFormBuilder.buildLoginForm(target.requestedModule(),  +						target.requestedAction(), oaParam, publicURLPreFix, moasession.getSessionID()); +				 +				//store MOASession +				try { +					AuthenticationSessionStoreage.storeSession(moasession, target.getRequestID());				 +				} catch (MOADatabaseException e) { +					Logger.error("Database Error! MOASession is not stored!"); +					throw new MOAIDException("init.04", new Object[] { +							moasession.getSessionID()}); +				} +				 +				//set MOAIDSession +				//request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID()); +				 +				response.setContentType("text/html;charset=UTF-8"); +				PrintWriter out = new PrintWriter(response.getOutputStream());  +				out.print(loginForm); +				out.flush();   			} -			 -			//set MOAIDSession -			//request.getSession().setAttribute(MOA_SESSION, moasession.getSessionID()); -			 -			response.setContentType("text/html;charset=UTF-8"); -			PrintWriter out = new PrintWriter(response.getOutputStream());  -			out.print(loginForm); -			out.flush();  +		} catch (ProcessExecutionException e) { +			throw new MOAIDException("process.01", new Object[] { moasession.getProcessInstanceId(), moasession }, e);  		}  	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java deleted file mode 100644 index a08ef5f0c..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/DatabaseTestModule.java +++ /dev/null @@ -1,142 +0,0 @@ -/******************************************************************************* - * Copyright 2014 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.monitoring; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; - -import org.hibernate.Query; -import org.hibernate.Session; - -import at.gv.egovernment.moa.id.commons.db.ConfigurationDBRead; -import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; -import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; -import at.gv.egovernment.moa.id.commons.db.StatisticLogDBUtils; -import at.gv.egovernment.moa.id.commons.db.dao.config.MOAIDConfiguration; -import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; -import at.gv.egovernment.moa.id.commons.db.dao.statistic.StatisticLog; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class DatabaseTestModule implements TestModuleInterface{ - -	public List<String> performTests() throws Exception { -		Logger.trace("Start MOA-ID Database Test."); -		 -		List<String> errors = new ArrayList<String>(); -		 -		AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -		 -		String error = testMOAConfigurationDatabase(); -		if (MiscUtil.isNotEmpty(error)) -			errors.add(error); -		 -		error = testMOASessionDatabase(); -		if (MiscUtil.isNotEmpty(error)) -			errors.add(error); -		 -		if (config.isAdvancedLoggingActive()) { -			error = testMOAAdvancedLoggingDatabase(); -			if (MiscUtil.isNotEmpty(error)) -				errors.add(error); -		} -		 -		return errors; -	} - -	 -	private String testMOASessionDatabase() throws Exception{ -		Logger.trace("Start Test: MOASessionDatabase"); -		 -		Date expioredate = new Date(new Date().getTime() - 120); -  -		try { -			List<AssertionStore> results; -			Session session = MOASessionDBUtils.getCurrentSession(); -			 -			synchronized (session) {			 -				session.beginTransaction(); -				Query query = session.getNamedQuery("getAssertionWithTimeOut"); -				query.setTimestamp("timeout", expioredate);		 -				results = query.list(); -				session.getTransaction().commit(); -			} -			 -			Logger.trace("Finish Test: MOASessionDatabase"); -			return null; -			 -		} catch (Throwable e) { -			Logger.warn("Failed Test: MOASessionDatabase", e); -			return "MOASessionDatabase: " + e.getMessage(); -		} -	} -	 -	private String testMOAConfigurationDatabase() throws Exception{ -		 -		MOAIDConfiguration moaidconfig = ConfigurationDBRead.getMOAIDConfiguration();	 -		ConfigurationDBUtils.closeSession(); -		 -		if (moaidconfig == null) -			return ("MOA-ID 2.x configuration can not be loaded from Database."); -		 -		return null; -	} -	 -	private String testMOAAdvancedLoggingDatabase() { -		 -		Date expioredate = new Date(new Date().getTime() - 120); -		try { -			Session session = StatisticLogDBUtils.getCurrentSession(); -		 -			List<StatisticLog> results; -		 -			synchronized (session) {			 -				session.beginTransaction(); -				Query query = session.getNamedQuery("getAllEntriesNotBeforeTimeStamp"); -				query.setTimestamp("timeout", expioredate);		 -				results = query.list(); -				session.getTransaction().commit(); -			} -		 -			Logger.trace("Finish Test: AdvancedLoggingDataBase"); -			return null; -			 -		} catch (Throwable e) { -			Logger.warn("Failed Test: AdvancedLoggingDataBase", e); -			return "AdvancedLoggingDataBase: " + e.getMessage(); -		} -	} - - -	public String getName() { -		return "DatabaseTest"; -	} - - -	public void initializeTest(long delayParam, String url) throws Exception { -		// TODO Auto-generated method stub -		 -	} -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java deleted file mode 100644 index b5220914c..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/IdentityLinkTestModule.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright 2014 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.monitoring; - -import java.io.InputStream; -import java.net.URL; -import java.util.List; - -import org.w3c.dom.Element; - -import at.gv.egovernment.moa.id.auth.builder.VerifyXMLSignatureRequestBuilder; -import at.gv.egovernment.moa.id.auth.data.IdentityLink; -import at.gv.egovernment.moa.id.auth.data.VerifyXMLSignatureResponse; -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.parser.IdentityLinkAssertionParser; -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.VerifyXMLSignatureResponseValidator; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; -import at.gv.egovernment.moa.id.config.auth.data.DynamicOAAuthParameters; -import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MiscUtil; - -public class IdentityLinkTestModule implements TestModuleInterface { - -	private static IdentityLink identityLink = null; -	 -	public void initializeTest(long delayParam, String url) throws Exception{ -		 -		if (MiscUtil.isNotEmpty(url)) { -			 -		  	URL keystoreURL = new URL(url);					 -			InputStream idlstream = keystoreURL.openStream(); -			identityLink = new IdentityLinkAssertionParser(idlstream).parseIdentityLink(); -		} -		 -	} -	 -	public List<String> performTests()  throws Exception{ -		Logger.trace("Start MOA-ID IdentityLink Test"); -		 -		AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -		 -		IdentityLinkValidator.getInstance().validate(identityLink); -		// builds a <VerifyXMLSignatureRequest> for a call of MOA-SP -		Element domVerifyXMLSignatureRequest = new VerifyXMLSignatureRequestBuilder() -				.build(identityLink, config -						.getMoaSpIdentityLinkTrustProfileID()); - -		// invokes the call -		Element domVerifyXMLSignatureResponse = new SignatureVerificationInvoker() -				.verifyXMLSignature(domVerifyXMLSignatureRequest); -		// parses the <VerifyXMLSignatureResponse> -		try { -			VerifyXMLSignatureResponse verifyXMLSignatureResponse = new VerifyXMLSignatureResponseParser( -					domVerifyXMLSignatureResponse).parseData(); -		 -			DynamicOAAuthParameters oaParam = new DynamicOAAuthParameters(); -			oaParam.setBusinessService(true); -			 -			VerifyXMLSignatureResponseValidator.getInstance().validate( -					verifyXMLSignatureResponse, -					config.getIdentityLinkX509SubjectNames(), -					VerifyXMLSignatureResponseValidator.CHECK_IDENTITY_LINK, -					oaParam); -			 -		} catch (ValidateException e) { -			//check if default Monitoring IDL is used then error is ignored -			if ("validator.07".equals(e.getMessageId())  -					&& e.getMessage().contains("Das Zertifikat der Personenbindung ist")) -				return null; -			 -			else -				throw e; -			 -		} -		 -		Logger.trace("Finished MOA-ID IdentityLink Test without errors"); -		 -		return null; -	} - -	public String getName() { -		return "IdentityLinkTest"; -	} - -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java deleted file mode 100644 index 84581abe8..000000000 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestManager.java +++ /dev/null @@ -1,111 +0,0 @@ -/******************************************************************************* - * Copyright 2014 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.monitoring; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -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.FileUtils; - -public class TestManager { - -	private static TestManager instance; -	 -	private Map<String, TestModuleInterface> tests = new HashMap<String, TestModuleInterface>(); -	 -	public static TestManager getInstance() throws ConfigurationException { -		if (instance == null) -			instance = new TestManager(); -		 -		return instance; -	} -	 -	private TestManager() throws ConfigurationException { -		 -		AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -		 -		//add Database test -		DatabaseTestModule test1 = new DatabaseTestModule(); -		tests.put(test1.getName(), test1); -		 -		//add IdentityLink verification test -		IdentityLinkTestModule test2 = new IdentityLinkTestModule(); -		String idlurl = FileUtils.makeAbsoluteURL(config.getMonitoringTestIdentityLinkURL(), config.getRootConfigFileDir()); -		try { -			test2.initializeTest(0, idlurl); -			tests.put(test2.getName(), test2);; -			 -		} catch (Exception e) { -			Logger.warn("MOA-ID IdentityLink Test can not performed without IdentityLink. Insert IdentityLink file to MOA-ID configuration", e); -		} -	} -	 -	public List<String> executeTests() { -		Logger.debug("Start MOA-ID-Auth testing"); - -		 -		List<String> errors; -		 -		for (TestModuleInterface test : tests.values()) { -			try { -				errors = test.performTests(); -				if (errors != null && errors.size() > 0) -					return errors; -				 -			} catch (Exception e) { -				Logger.warn("General Testing Eception during Test " + test.getClass() + ": ", e); -				return Arrays.asList(e.getMessage()); -			} -		} -		 -		return null;	 -	} -	 -	public List<String> executeTest(String testname) { -		 -		TestModuleInterface test = tests.get(testname); -		 -		if (test != null) { -			try { -				return test.performTests(); -				 -			} catch (Exception e) { -				Logger.warn("General Testing Eception during Test " + test.getName() + ": ", e); -				return Arrays.asList(e.getMessage()); -			} -			 -		} else { -			Logger.info("TestModule with Name " + testname + " is not implemented"); -			return null; -		} -	} -	 -	public boolean existsModule(String modulename) { -		return tests.containsKey(modulename); -	} -} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java new file mode 100644 index 000000000..080990f71 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExecutionContextImpl.java @@ -0,0 +1,79 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * ExecutionContext implementation, related to a certain process instance. + *  + * @author tknall + *  + */ +public class ExecutionContextImpl implements ExecutionContext { + +	private static final long serialVersionUID = 1L; + +	private Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>()); + +	private String processInstanceId; + +	/** +	 * Creates a new instance. +	 */ +	public ExecutionContextImpl() { +	} + +	/** +	 * Creates a new instance and associated it with a certain process instance. +	 */ +	public ExecutionContextImpl(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	} + +	@Override +	public void setProcessInstanceId(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	} + +	@Override +	public String getProcessInstanceId() { +		return processInstanceId; +	} + +	@Override +	public Serializable get(String key) { +		return ctxData.get(key); +	} + +	@Override +	public Serializable remove(String key) { +		return ctxData.remove(key); +	} + +	@Override +	public void put(String key, Serializable object) { +		ctxData.put(key, object); +	} + +	@Override +	public Set<String> keySet() { +		return Collections.unmodifiableSet(ctxData.keySet()); +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("ExecutionContextImpl ["); +		builder.append("id=").append(processInstanceId); +		builder.append(", variables="); +		builder.append(ctxData.keySet()); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java new file mode 100644 index 000000000..f0d1c861d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ExpressionEvaluationContextImpl.java @@ -0,0 +1,44 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; + +/** + * Context implementation used for expression evaluation only. + *  + * @author tknall + *  + */ +public class ExpressionEvaluationContextImpl implements ExpressionEvaluationContext { + +	private static final long serialVersionUID = 1L; + +	private Map<String, Serializable> ctxData; + +	/** +	 * Creates a new instance and initializes it with data from a given process instance. +	 *  +	 * @param processInstance +	 *            The process instance. +	 */ +	ExpressionEvaluationContextImpl(ProcessInstance processInstance) { +		ExecutionContext executionContext = processInstance.getExecutionContext(); +		Set<String> keys = executionContext.keySet(); +		ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>(keys.size())); +		for (String key : keys) { +			ctxData.put(key, executionContext.get(key)); +		} +	} + +	@Override +	public Map<String, Serializable> getCtx() { +		return Collections.unmodifiableMap(ctxData); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java new file mode 100644 index 000000000..162ee624a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParser.java @@ -0,0 +1,224 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Objects; + +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.events.Attribute; +import javax.xml.stream.events.StartElement; +import javax.xml.stream.events.XMLEvent; +import javax.xml.stream.util.EventReaderDelegate; +import javax.xml.transform.stax.StAXSource; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.SAXException; + +import at.gv.egovernment.moa.id.process.model.EndEvent; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.model.ProcessNode; +import at.gv.egovernment.moa.id.process.model.StartEvent; +import at.gv.egovernment.moa.id.process.model.TaskInfo; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Parses an XML representation of a process definition as defined by the respective XML schema. + * <p/ + * The parser is thread-safe. + * @author tknall + * + */ +public class ProcessDefinitionParser { +	 +	private static final String NS = "http://reference.e-government.gv.at/namespace/moa/process/definition/v1"; +	 +	private static Logger log = LoggerFactory.getLogger(ProcessDefinitionParser.class); + +	private static class LazyProcessDefinitionSchemaHolder { +		private static final Schema PD_SCHEMA_INSTANCE; +		static { +			try (InputStream in = ProcessDefinitionParser.class.getResourceAsStream("ProcessDefinition.xsd")) { +				log.trace("Compiling process definition schema."); +				SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); +				// schema is thread-safe +				PD_SCHEMA_INSTANCE = factory.newSchema(new StreamSource(in)); +			} catch (Exception e) { +				throw new RuntimeException("Unable to compile process definition schema.", e); +			} +		} +	} + +	/** +	 * Parses an XML representation of a process definition. The representation is being validated in order to suffice +	 * the related XML schema. +	 *  +	 * @param processDefinitionInputStream +	 *            The process definition. +	 * @return A new process definition. +	 * @throws ProcessDefinitionParserException +	 *             Thrown in case of error parsing the process definition. +	 */ +	public ProcessDefinition parse(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException { +		XMLEventReader reader = null; +		final ProcessDefinition pd = new ProcessDefinition(); +		log.debug("Parsing and validating process definition."); +		try { + +			// Standard implementation of XMLInputFactory seems not to be thread-safe +			XMLInputFactory inputFactory = XMLInputFactory.newInstance(); +			reader = inputFactory.createXMLEventReader(processDefinitionInputStream); + +			final List<StartElement> transitionElements = new ArrayList<>(); +			final List<StartEvent> startEvents = new ArrayList<>(); +			 +			reader = new EventReaderDelegate(reader) { + +				@Override +				public XMLEvent nextEvent() throws XMLStreamException { +					XMLEvent event = super.nextEvent(); + +					switch (event.getEventType()) { +					case XMLStreamConstants.START_ELEMENT: +						StartElement element = event.asStartElement(); +						QName qname = element.getName(); +						 +						if (NS.equals(qname.getNamespaceURI())) { +							log.trace("Found process description element '{}'.", qname.getLocalPart()); +							Attribute id = element.getAttributeByName(new QName("id")); +							 +							switch (qname.getLocalPart()) { +							case "ProcessDefinition": +								if (id != null) { +									pd.setId(id.getValue()); +								} +								break; +							case "StartEvent": +								StartEvent startEvent = new StartEvent(); +								if (id != null) { +									startEvent.setId(id.getValue()); +								} +								startEvents.add(startEvent); +								break; +							case "EndEvent": +								EndEvent endEvent = new EndEvent(); +								if (id != null) { +									endEvent.setId(id.getValue()); +									pd.getEndEvents().put(id.getValue(), endEvent); +								} +								break; +							case "Transition": +								transitionElements.add(element); +								break; +							case "Task": +								TaskInfo taskInfo = new TaskInfo(); +								if (id != null) { +									taskInfo.setId(id.getValue()); +									pd.getTaskInfos().put(id.getValue(), taskInfo); +								} +								Attribute async = element.getAttributeByName(new QName("async")); +								if (async != null) { +									taskInfo.setAsync(Boolean.valueOf(async.getValue())); +								} +								Attribute implementingClass = element.getAttributeByName(new QName("class")); +								if (implementingClass != null) { +									taskInfo.setTaskImplementingClass(implementingClass.getValue()); +								} +								break; +							} +							 +						} +						 +						break; +					} + +					return event; +				} + +			}; + +			// validator is not thread-safe +			Validator validator = LazyProcessDefinitionSchemaHolder.PD_SCHEMA_INSTANCE.newValidator(); +			validator.validate(new StAXSource(reader)); +			log.trace("Process definition successfully schema validated."); + +			// perform some basic checks +			log.trace("Building model and performing some plausibility checks."); +			if (startEvents.size() != 1) { +				throw new ProcessDefinitionParserException("A ProcessDefinition must contain exactly one single StartEvent."); +			} +			pd.setStartEvent(startEvents.get(0)); +			 +			// link transitions +			Iterator<StartElement> transitions = transitionElements.iterator(); +			while (transitions.hasNext()) { +				StartElement element = transitions.next(); +				Transition transition = new Transition(); +				Attribute id = element.getAttributeByName(new QName("id")); +				if (id != null) { +					transition.setId(id.getValue()); +				} +				Attribute conditionExpression = element.getAttributeByName(new QName("conditionExpression")); +				if (conditionExpression != null) { +					transition.setConditionExpression(conditionExpression.getValue()); +				} +				Attribute from = element.getAttributeByName(new QName("from")); +				if (from != null) { +					ProcessNode fromNode = pd.getProcessNode(from.getValue()); +					if (fromNode == null) { +						throw new ProcessDefinitionParserException("Transition's 'from'-attribute refers to a non-existing event or task '" + from.getValue() + '.'); +					} +					if (fromNode instanceof EndEvent) { +						throw new ProcessDefinitionParserException("Transition cannot start from end event."); +					} +					transition.setFrom(fromNode); +					fromNode.getOutgoingTransitions().add(transition); +				} +				Attribute to = element.getAttributeByName(new QName("to")); +				if (to != null) { +					ProcessNode toNode = pd.getProcessNode(to.getValue()); +					if (toNode == null) { +						throw new ProcessDefinitionParserException("Transition's 'to'-attribute refers to a non-existing event or task '" + to.getValue() + '.'); +					} +					transition.setTo(toNode); +					toNode.getIncomingTransitions().add(transition); +				} +				if (transition.getConditionExpression() == null && Objects.equals(transition.getFrom(), transition.getTo())) { +					throw new ProcessDefinitionParserException("Transition's 'from' equals its 'to'. Since no 'conditionExpression' has been set this will cause a loop."); +				} +			} +			log.debug("Process definition '{}' successfully parsed.", pd.getId()); +			return pd; + +		} catch (ProcessDefinitionParserException e) { +			throw e; +		} catch (XMLStreamException|IOException e) { +			throw new ProcessDefinitionParserException("Unable to read process definition from inputstream.", e); +		} catch (SAXException e) { +			throw new ProcessDefinitionParserException("Schema validation of process description failed.", e); +		} catch (Exception e) { +			throw new ProcessDefinitionParserException("Internal error creating process definition from inputstream.", e); +		} finally { +			if (reader != null) { +				try { +					reader.close(); +				} catch (XMLStreamException e) { +					// error freeing resources +				} +			} +		} +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java new file mode 100644 index 000000000..0c214750d --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessDefinitionParserException.java @@ -0,0 +1,35 @@ +package at.gv.egovernment.moa.id.process; + +/** + * Exception thrown in case of error parsing a process definition. + *  + * @author tknall + *  + */ +public class ProcessDefinitionParserException extends Exception { + +	private static final long serialVersionUID = 1L; + +	/** +	 * Creates a new parser exception providing a {@code message} describing the reason and the {@code cause}. +	 *  +	 * @param message +	 *            The message. +	 * @param cause +	 *            The cause. +	 */ +	public ProcessDefinitionParserException(String message, Throwable cause) { +		super(message, cause); +	} + +	/** +	 * Creates a new parser exception providing a {@code message} describing the reason. +	 *  +	 * @param message +	 *            The message. +	 */ +	public ProcessDefinitionParserException(String message) { +		super(message); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java new file mode 100644 index 000000000..5cf84abed --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngine.java @@ -0,0 +1,98 @@ +package at.gv.egovernment.moa.id.process; + + +import java.io.InputStream; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; + +/** + * Process engine providing means for starting and resuming processes. + *  + * @author tknall + */ +public interface ProcessEngine { + +	/** +	 * Registers a new process definition. Note that existing definitions with the same identifier will be replaced. +	 *  +	 * @param processDefinition +	 *            The process definition to be registered. +	 */ +	void registerProcessDefinition(ProcessDefinition processDefinition); + +	/** +	 * Registers a new process definition given as {@link InputStream}. Note that existing definitions with the same identifier will be replaced. +	 * +	 * @param processDefinitionInputStream The input stream to the definition to be registered. +	 * @throws ProcessDefinitionParserException Thrown in case of an error parsing the process definition. +	 * @return The process definition's identifier. +	 */ +	String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException; + +	/** +	 * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. +	 * <p/> +	 * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue +	 * process execution after asynchronous task execution (refer to {@link #start(String)} and +	 * {@link #signal(String)} for further information). +	 *  +	 * @param processDefinitionId +	 *            The identifier of the respective process definition. +	 * @param executionContext The execution context (may be {@code null}). +	 * @return The id of the newly created process instance (never {@code null}). +	 * @throws ProcessExecutionException +	 *             Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. +	 */ +	String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException; + +	/** +	 * Creates a process instance according to the referenced process definition, persists it into the database and returns it identifier. +	 * <p/> +	 * Note that the method returns the identifier of a process instance which will be needed in order to start a process or to continue +	 * process execution after asynchronous task execution (refer to {@link #start(String)} and +	 * {@link #signal(String)} for further information). +	 *  +	 * @param processDefinitionId +	 *            The identifier of the respective process definition. +	 * @return The id of the newly created process instance (never {@code null}). +	 * @throws ProcessExecutionException +	 *             Thrown in case of error, e.g. when a {@code processDefinitionId} is referenced that does not exist. +	 */ +	String createProcessInstance(String processDefinitionId) throws ProcessExecutionException; + +	/** +	 * Returns the process instance with a given {@code processInstanceId}. +	 *  +	 * @param processInstanceId +	 *            The process instance id. +	 * @return The process instance (never {@code null}). +	 * @throws IllegalArgumentException +	 *             In case the process instance does not/no longer exist. +	 * @throws RuntimeException +	 *             In case the process instance could not be retrieved from persistence. +	 */ +	ProcessInstance getProcessInstance(String processInstanceId); + +	/** +	 * Starts the process using the given {@code processInstanceId}. +	 *  +	 * @param processInstanceId +	 *            The process instance id. +	 * @throws ProcessExecutionException +	 *             Thrown in case of error. +	 */ +	void start(String processInstanceId) throws ProcessExecutionException; + + +	/** +	 * Resumes process execution after an asynchronous task has been executed. +	 *  +	 * @param processInstanceId +	 *            The process instance id. +	 * @throws ProcessExecutionException +	 *             Thrown in case of error. +	 */ +	void signal(String processInstanceId) throws ProcessExecutionException; + +}
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java new file mode 100644 index 000000000..096e5ee9e --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessEngineImpl.java @@ -0,0 +1,356 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.InputStream; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.collections4.Predicate; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; +import at.gv.egovernment.moa.id.process.api.Task; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAO; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl; +import at.gv.egovernment.moa.id.process.model.EndEvent; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.model.ProcessNode; +import at.gv.egovernment.moa.id.process.model.StartEvent; +import at.gv.egovernment.moa.id.process.model.TaskInfo; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Process engine implementation allowing starting and continuing processes as well as providing means for cleanup actions. + */ +public class ProcessEngineImpl implements ProcessEngine { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	private ProcessDefinitionParser pdp = new ProcessDefinitionParser(); + +	ProcessInstanceStoreDAO piStoreDao = ProcessInstanceStoreDAOImpl.getInstance(); + +	private Map<String, ProcessDefinition> processDefinitions = new ConcurrentHashMap<String, ProcessDefinition>(); + +	private final static String MDC_CTX_PI_NAME = "processInstanceId"; +	private final static String MDC_CTX_TASK_NAME = "taskId"; + +	private ExpressionEvaluator transitionConditionExpressionEvaluator; + +	@Override +	public void registerProcessDefinition(ProcessDefinition processDefinition) { +		log.info("Registering process definition '{}'.", processDefinition.getId()); +		processDefinitions.put(processDefinition.getId(), processDefinition); +	} + +	@Override +	public String registerProcessDefinition(InputStream processDefinitionInputStream) throws ProcessDefinitionParserException{ +		ProcessDefinition pd = pdp.parse(processDefinitionInputStream); +		registerProcessDefinition(pd); +		return pd.getId(); +	} + +	/** +	 * Sets the process definitions. +	 * +	 * @param processDefinitions +	 *            The process definitions. +	 * @throws IllegalArgumentException +	 *             In case the process definitions contain definitions with the same identifier. +	 */ +	public void setProcessDefinitions(Iterable<ProcessDefinition> processDefinitions) { +		this.processDefinitions.clear(); +		for (ProcessDefinition pd : processDefinitions) { +			if (this.processDefinitions.containsKey(pd.getId())) { +				throw new IllegalArgumentException("Duplicate process definition identifier '" + pd.getId() + "'."); +			} +			registerProcessDefinition(pd); +		} +	} + +	/** +	 * Sets an expression evaluator that should be used to process transition condition expressions. +	 * @param transitionConditionExpressionEvaluator The expression evaluator. +	 */ +	public void setTransitionConditionExpressionEvaluator( +			ExpressionEvaluator transitionConditionExpressionEvaluator) { +		this.transitionConditionExpressionEvaluator = transitionConditionExpressionEvaluator; +	} + + +	@Override +	public String createProcessInstance(String processDefinitionId, ExecutionContext executionContext) throws ProcessExecutionException { +		// look for respective process definition +		ProcessDefinition pd = processDefinitions.get(processDefinitionId); +		if (pd == null) { +			throw new ProcessExecutionException("Unable to find process definition for process '" + processDefinitionId + "'."); +		} +		// create and keep process instance +		ProcessInstance pi = new ProcessInstance(pd, executionContext); +		log.info("Creating process instance from process definition '{}': {}", processDefinitionId, pi.getId()); + +		try { +			saveOrUpdateProcessInstance(pi); +		} catch (MOADatabaseException e) { +			throw new ProcessExecutionException("Unable to persist process instance.", e); +		} + +		return pi.getId(); +	} + +	@Override +	public String createProcessInstance(String processDefinitionId) throws ProcessExecutionException { +		return createProcessInstance(processDefinitionId, null); +	} + +	@Override +	public void start(String processInstanceId) throws ProcessExecutionException { + +		try { +			ProcessInstance pi = loadProcessInstance(processInstanceId); + +			MDC.put(MDC_CTX_PI_NAME, pi.getId()); + +			if (!ProcessInstanceState.NOT_STARTED.equals(pi.getState())) { +				throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has already been started (current state is " + pi.getState() + ")."); +			} +			log.info("Starting process instance '{}'.", pi.getId()); +			// execute process +			pi.setState(ProcessInstanceState.STARTED); +			execute(pi); + +			saveOrUpdateProcessInstance(pi); +		} catch (MOADatabaseException e) { +			throw new ProcessExecutionException("Unable to load/save process instance.", e); + +		} finally { +			MDC.remove(MDC_CTX_PI_NAME); +		} +	} +	 +	@Override +	public void signal(String processInstanceId) throws ProcessExecutionException { + +		try { +			ProcessInstance pi = loadProcessInstance(processInstanceId); + +			MDC.put(MDC_CTX_PI_NAME, pi.getId()); + +			if (!ProcessInstanceState.SUSPENDED.equals(pi.getState())) { +				throw new ProcessExecutionException("Process instance '" + pi.getId() + "' has not been suspended (current state is " + pi.getState() + ")."); +			} + +			log.info("Waking up process instance '{}'.", pi.getId()); +			pi.setState(ProcessInstanceState.STARTED); +			execute(pi); + +			saveOrUpdateProcessInstance(pi); +		} catch (MOADatabaseException e) { +			throw new ProcessExecutionException("Unable to load/save process instance.", e); + +		} finally { +			MDC.remove(MDC_CTX_PI_NAME); +		} +	} +	 + +	/** +	 * Instantiates a task implementation given by a {@link TaskInfo}. +	 * @param ti The task info. +	 * @return A Task implementation or {@code null} if the task info does not reference any task implementing classes. +	 * @throws ProcessExecutionException Thrown in case of error (when the referenced class does not implement {@link Task} for instance). +	 */ +	private Task createTaskInstance(TaskInfo ti) throws ProcessExecutionException { +		String clazz = StringUtils.trimToNull(ti.getTaskImplementingClass()); +		Task task = null; +		 +		if (clazz != null) { +			log.debug("Instantiating task implementing class '{}'.", clazz); +			Class<?> instanceClass = null; +			try { +				instanceClass = Class.forName(clazz, true, Thread.currentThread().getContextClassLoader()); +			} catch (Exception e) { +				throw new ProcessExecutionException("Unable to get class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); +			} +			if (!Task.class.isAssignableFrom(instanceClass)) { +				throw new ProcessExecutionException("Class '" + clazz + "' associated with task '" + ti.getId() + "' is not assignable to " + Task.class.getName() + "."); +			} +			try { +				task = (Task) instanceClass.newInstance(); +			} catch (Exception e) { +				throw new ProcessExecutionException("Unable to instantiate class '" + clazz + "' associated with task '" + ti.getId() + "' .", e); +			} +		} + +		return task; +	} + +	/** +	 * Starts/executes a given process instance. +	 * @param pi The process instance. +	 * @throws ProcessExecutionException Thrown in case of error. +	 */ +	private void execute(final ProcessInstance pi) throws ProcessExecutionException { +		if (ProcessInstanceState.ENDED.equals(pi.getState())) { +			throw new ProcessExecutionException("Process for instance '" + pi.getId() + "' has already been ended."); +		} +		ProcessDefinition pd = pi.getProcessDefinition(); +		ProcessNode processNode = pd.getProcessNode(pi.getNextId()); +		log.debug("Processing node '{}'.", processNode.getId()); +		 +		// distinguish process node types StartEvent, TaskInfo and EndEvent +		 +		if (processNode instanceof TaskInfo) { +			// TaskInfo types need to be executed +			TaskInfo ti = (TaskInfo) processNode; +			MDC.put(MDC_CTX_TASK_NAME, ti.getId()); +			try { +				log.info("Processing task '{}'.", ti.getId()); +				Task task = createTaskInstance(ti); +				if (task != null) { +					try { +						log.info("Executing task implementation for task '{}'.", ti.getId()); +						log.debug("Execution context before task execution: {}", pi.getExecutionContext().keySet()); +						task.execute(pi.getExecutionContext()); +						log.info("Returned from execution of task '{}'.", ti.getId()); +						log.debug("Execution context after task execution: {}", pi.getExecutionContext().keySet()); +					} catch (Throwable t) { +						throw new ProcessExecutionException("Error executing task '" + ti.getId() + "'.", t); +					} +				} else { +					log.debug("No task implementing class set."); +				} +			} finally { +				MDC.remove(MDC_CTX_TASK_NAME); +			} +			 +		} else if (processNode instanceof EndEvent) { +			log.info("Finishing process instance '{}'.", pi.getId()); + +			try { +				piStoreDao.remove(pi.getId()); +			} catch (MOADatabaseException e) { +				throw new ProcessExecutionException("Unable to remove process instance.", e); +			} +			pi.setState(ProcessInstanceState.ENDED); +			log.debug("Final process context: {}", pi.getExecutionContext().keySet()); +			return; +		} +		 +		final ExpressionEvaluationContext expressionContext = new ExpressionEvaluationContextImpl(pi); +		 +		// traverse pointer +		Transition t = CollectionUtils.find(processNode.getOutgoingTransitions(), new Predicate<Transition>() { +			@Override +			public boolean evaluate(Transition transition) { +				if (transitionConditionExpressionEvaluator != null && transition.getConditionExpression() != null) { +					log.trace("Evaluating transition expression '{}'.", transition.getConditionExpression()); +					return transitionConditionExpressionEvaluator.evaluate(expressionContext, transition.getConditionExpression()); +				} +				return true; +			} +		}); +		if (t == null) { +			throw new ProcessExecutionException("No valid transition starting from process node '" + processNode.getId()+ "'."); +		} +		log.trace("Found suitable transition: {}", t); +		// update pointer +		log.trace("Shifting process token from '{}' to '{}'.", pi.getNextId(), t.getTo().getId()); +		pi.setNextId(t.getTo().getId()); +		 +		// inspect current task +		if (t.getTo() instanceof TaskInfo && (((TaskInfo) t.getTo()).isAsync())) { +			// immediately return in case of asynchonous task +			log.info("Suspending process instance '{}' for asynchronous task '{}'.", pi.getId(), t.getTo().getId()); +			pi.setState(ProcessInstanceState.SUSPENDED); +			return; +		} +		 +		// continue execution in case of StartEvent or Task +		if (processNode instanceof StartEvent || processNode instanceof TaskInfo) { +			execute(pi); +		} +	} + +	@Override +	public ProcessInstance getProcessInstance(String processInstanceId) { + +		ProcessInstance processInstance; +		try { +			processInstance = loadProcessInstance(processInstanceId); + +		} catch (MOADatabaseException e) { +			throw new RuntimeException("The process instance '" + processInstanceId + "' could not be retrieved.", e); +		} + +		if (processInstance == null) { +			throw new IllegalArgumentException("The process instance '" + processInstanceId + "' does not/no longer exist."); +		} + +		return processInstance; +	} + +	/** +	 * Persists a {@link ProcessInstance} to the database. +	 * @param processInstance The object to persist. +	 * @throws MOADatabaseException Thrown if an error occurs while accessing the database. +	 */ +	private void saveOrUpdateProcessInstance(ProcessInstance processInstance) throws MOADatabaseException { +		ProcessInstanceStore store = new ProcessInstanceStore(); + +		ExecutionContext ctx = processInstance.getExecutionContext(); + +		Map<String, Serializable> ctxData = new HashMap<String, Serializable>(); +		for (String key : ctx.keySet()) { +			ctxData.put(key, ctx.get(key)); +		} +		store.setExecutionContextData(ctxData); + +		store.setNextTaskId(processInstance.getNextId()); +		store.setProcessDefinitionId(processInstance.getProcessDefinition().getId()); + +		store.setProcessInstanceId(processInstance.getId()); +		store.setProcessState(processInstance.getState()); + +		piStoreDao.saveOrUpdate(store); +	} + +	/** +	 * Load a {@link ProcessInstance} with a certain id from the database. +	 * @param processInstanceId The process instance id +	 * @return The process instance corresponding to the id or {@code null} if no such object is found. +	 * @throws MOADatabaseException Thrown if an error occurs while accessing the database. +	 */ +	private ProcessInstance loadProcessInstance(String processInstanceId) throws MOADatabaseException { + +		ProcessInstanceStore piStore = piStoreDao.load(processInstanceId); + +		if (piStore == null) { +			return null; +		} + +		ExecutionContext executionContext = new ExecutionContextImpl(piStore.getProcessInstanceId()); + +		Map<String, Serializable> executionContextData = piStore.getExecutionContextData(); +		for (String key : executionContextData.keySet()) { +			executionContext.put(key, executionContextData.get(key)); +		} + +		ProcessInstance pi = new ProcessInstance(processDefinitions.get(piStore.getProcessDefinitionId()), executionContext); +		pi.setNextId(piStore.getNextTaskId()); +		pi.setState(piStore.getProcessState()); + +		return pi; +	} +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java new file mode 100644 index 000000000..821bbe6dc --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessExecutionException.java @@ -0,0 +1,36 @@ +package at.gv.egovernment.moa.id.process; + +/** + * Indicates a problem when executing a process. + *  + * @author tknall + *  + */ +public class ProcessExecutionException extends Exception { + +	private static final long serialVersionUID = 1L; + +	/** +	 * Creates a new process execution exception providing a {@code message} describing the reason and the respective +	 * {@code cause}. +	 *  +	 * @param message +	 *            The message. +	 * @param cause +	 *            The cause. +	 */ +	public ProcessExecutionException(String message, Throwable cause) { +		super(message, cause); +	} + +	/** +	 * Creates a new process execution exception providing a {@code message} describing the reason. +	 *  +	 * @param message +	 *            The message. +	 */ +	public ProcessExecutionException(String message) { +		super(message); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java new file mode 100644 index 000000000..a6cf3b57f --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstance.java @@ -0,0 +1,164 @@ +package at.gv.egovernment.moa.id.process; + +import java.io.Serializable; +import java.util.Date; + +import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.support.SecureRandomHolder; + +/** + * Represents a process being executed. The process instance provides information about the process and its state. + *  + * @author tknall + *  + */ +public class ProcessInstance implements Serializable { + +	private static final long serialVersionUID = 1L; +	private static final int RND_ID_LENGTH = 22; + +	private ProcessDefinition processDefinition; +	private String nextId; +	private Date lru; +	private ExecutionContext executionContext; +	private ProcessInstanceState state = ProcessInstanceState.NOT_STARTED; + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	/** +	 * Creates a new process instance, based on a given process definition and a +	 * given execution context. If the given execution context is {@code null} a new execution context will be created.<p/> +	 * The process instance id of the execution context will be newly generated if it is {@code null} in the execution context. +	 *  +	 * @param processDefinition +	 *            The process definition. +	 * @param executionContext +	 *            The execution context (may be {@code null}). If {@code null} a new execution context will be created internally. +	 */ +	ProcessInstance(ProcessDefinition processDefinition, ExecutionContext executionContext) { +		this.processDefinition = processDefinition; +		nextId = processDefinition.getStartEvent().getId(); +		if (executionContext == null) { +			executionContext = new ExecutionContextImpl(); +		} +		if (executionContext.getProcessInstanceId() == null) { +			String pdIdLocalPart = RandomStringUtils.random(RND_ID_LENGTH, 0, 0, true, true, null, +					SecureRandomHolder.getInstance()); +			executionContext.setProcessInstanceId(this.processDefinition.getId() + "-" + pdIdLocalPart); +		} else { +			log.debug("Using process instance id from execution context."); +		} +		log.debug("Creating process instance with id '{}'.", executionContext.getProcessInstanceId()); +		this.executionContext = executionContext; +		touch(); +	} + +	/** +	 * Returns the underlying process definition. +	 *  +	 * @return The underlying process definition. +	 */ +	ProcessDefinition getProcessDefinition() { +		touch(); +		return processDefinition; +	} + +	/** +	 * Returns the id of the process node to be executed next. +	 *  +	 * @return The process node pointer indicating the process node to be executed next. +	 */ +	public String getNextId() { +		touch(); +		return nextId; +	} + +	/** +	 * Sets the internal pointer to the process node to be executed next. +	 *  +	 * @param nextId +	 *            The process node id to be executed next. +	 */ +	void setNextId(String nextId) { +		touch(); +		this.nextId = nextId; +	} + +	/** +	 * Returns the current state of the process instance. +	 *  +	 * @return The current state. +	 */ +	public ProcessInstanceState getState() { +		touch(); +		return state; +	} + +	/** +	 * Sets the current state of the process instance. +	 *  +	 * @param state +	 *            The current state. +	 */ +	void setState(ProcessInstanceState state) { +		touch(); +		this.state = state; +	} + +	public String getId() { +		touch(); +		return executionContext.getProcessInstanceId(); +	} + +	/** +	 * Updates the last recently used date of the process instance. +	 */ +	private void touch() { +		lru = new Date(); +	} + +	/** +	 * Returns the date the process instance has been accessed last. +	 *  +	 * @return The last recently used date. +	 */ +	Date getLru() { +		return lru; +	} + +	/** +	 * Returns the associated execution context. +	 * @return The execution context (never {@code null}). +	 */ +	public ExecutionContext getExecutionContext() { +		touch(); +		return executionContext; +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("ProcessInstance ["); +		builder.append("id=").append(executionContext.getProcessInstanceId()); +		builder.append(", idle since=").append( +				DurationFormatUtils.formatDurationWords(new Date().getTime() - this.lru.getTime(), true, true)); +		if (processDefinition != null) { +			builder.append(", processDefinition.id="); +			builder.append(processDefinition.getId()); +		} +		if (nextId != null) { +			builder.append(", nextId="); +			builder.append(nextId); +		} +		builder.append(", executionContext=").append(executionContext); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java new file mode 100644 index 000000000..2765283a0 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/ProcessInstanceState.java @@ -0,0 +1,30 @@ +package at.gv.egovernment.moa.id.process; + +/** + * Represents a certain process instance state. + * @author tknall + * + */ +public enum ProcessInstanceState { +	 +	/** +	 * Indicates that the process with this process instance has not yet been started. +	 */ +	NOT_STARTED, +	 +	/** +	 * Indicates that the process is currently running. +	 */ +	STARTED, +	 +	/** +	 * Indicates that the process has been suspended until being waken up by someonce calling {@code signal}. +	 */ +	SUSPENDED, +	 +	/** +	 * Indicates that the process has been completed. +	 */ +	ENDED + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java new file mode 100644 index 000000000..4a9dfc336 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExecutionContext.java @@ -0,0 +1,63 @@ +package at.gv.egovernment.moa.id.process.api; + +import java.io.Serializable; +import java.util.Set; + +/** + * Encapsulates data needed for or provided by task execution. + *  + * @author tknall + *  + */ +public interface ExecutionContext extends Serializable { + +	/** +	 * Returns the identifier of underlying process instance. +	 *  +	 * @return The identifier of the process instance. +	 */ +	String getProcessInstanceId(); + +	/** +	 * Sets the identifier of underlying process instance. +	 *  +	 * @param processInstanceId +	 *            The identifier of the process instance. +	 */ +	void setProcessInstanceId(String processInstanceId); + +	/** +	 * Stores a serializable object using {@code key}. +	 *  +	 * @param key +	 *            The key under that the {@code object} should be stored. +	 * @param object The object to be stored. +	 */ +	void put(String key, Serializable object); + +	/** +	 * Returns an serializable object stored within this process context using {@code key}. +	 *  +	 * @param key +	 *            The key that has been used to store the serializable object (may be {@code null}). +	 * @return The object or {@code null} in case the key does not relate to a stored object or the stored object itself +	 *         was {@code null}. +	 */ +	Serializable get(String key); +	 +	/** +	 * Removes the object stored using {@code key}. +	 * @param key +	 *            The key that has been used to store the serializable object (may be {@code null}). +	 * @return The object that has been removed or {@code null} there was no object stored using {@code key}. +	 */ +	Serializable remove(String key); + +	/** +	 * Returns an unmodifiable set containing the stored keys. +	 *  +	 * @return The keyset (never {@code null}). +	 */ +	Set<String> keySet(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java new file mode 100644 index 000000000..94854dcad --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluationContext.java @@ -0,0 +1,23 @@ +package at.gv.egovernment.moa.id.process.api; + +import java.io.Serializable; +import java.util.Map; + +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Context used for evaluation of condition expressions set for {@linkplain Transition Transitions}. + *  + * @author tknall + *  + */ +public interface ExpressionEvaluationContext extends Serializable { + +	/** +	 * Returns the context data map used for expression evaluation. +	 *  +	 * @return An unmodifiable map (never {@code null}). +	 */ +	Map<String, Serializable> getCtx(); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java new file mode 100644 index 000000000..fe0743201 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/ExpressionEvaluator.java @@ -0,0 +1,25 @@ +package at.gv.egovernment.moa.id.process.api; + +/** + * Evaluates a given {@code expression} returning a boolean value. + *  + * @author tknall + */ +public interface ExpressionEvaluator { + +	/** +	 * Evaluates a given {@code expression} returning a boolean value. +	 *  +	 * @param expressionContext +	 *            The context which can be used for evaluation of the expression. +	 * @param expression +	 *            The expression resulting in a boolean (must not be {@code null}). +	 * @return A boolean value. +	 * @throws IllegalArgumentException +	 *             In case of an invalid {@code expression}. +	 * @throws NullPointerException +	 *             In case of a {@code null} expression. +	 */ +	boolean evaluate(ExpressionEvaluationContext expressionContext, String expression); + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java new file mode 100644 index 000000000..343b8fe0c --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/api/Task.java @@ -0,0 +1,23 @@ +package at.gv.egovernment.moa.id.process.api; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; + + +/** + * Represents a single task to be performed upon process execution. + *  + * @author tknall + *  + */ +public interface Task { + +	/** +	 * Executes this task. +	 *  +	 * @param executionContext +	 *            Provides execution related information. +	 * @throws Exception An exception upon task execution. +	 */ +	void execute(ExecutionContext executionContext) throws TaskExecutionException; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java new file mode 100644 index 000000000..d690c37bf --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStore.java @@ -0,0 +1,89 @@ +package at.gv.egovernment.moa.id.process.dao; + +import java.io.Serializable; +import java.util.Map; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.Id; +import javax.persistence.Lob; +import javax.persistence.Table; + +import org.hibernate.internal.util.SerializationHelper; + +import at.gv.egovernment.moa.id.process.ProcessInstanceState; + +@Entity +@Table(name = "processinstance") +public class ProcessInstanceStore { + +	/** +	 * A process instance identifier qualifies as natural primary key by satisfying these requirements +	 * ("unique, constant, required"): +	 * <ul> +	 * <li>unique value</li> +	 * <li>never changes (immutable)</li> +	 * <li>never {@code null}</li> +	 * </ul> +	 */ +	@Id +	private String processInstanceId; + +	@Column(name = "processDefinitionId", nullable = false) +	private String processDefinitionId; + +	@Column(name = "nextTaskId", nullable = false) +	private String nextTaskId; + +	@Column(name = "processState", nullable = false) +	@Enumerated(value = EnumType.STRING) +	private ProcessInstanceState processState; + +	@Column(name = "executionContextData", nullable = false) +	@Lob +	private byte[] executionContextData; + +	public String getProcessInstanceId() { +		return processInstanceId; +	} + +	public String getProcessDefinitionId() { +		return processDefinitionId; +	} + +	public String getNextTaskId() { +		return nextTaskId; +	} + +	public ProcessInstanceState getProcessState() { +		return processState; +	} + +	@SuppressWarnings("unchecked") +	public Map<String, Serializable> getExecutionContextData() { +		return  (Map<String, Serializable>) SerializationHelper.deserialize(executionContextData); +	} + +	public void setProcessInstanceId(String processInstanceId) { +		this.processInstanceId = processInstanceId; +	} + +	public void setProcessDefinitionId(String processDefinitionId) { +		this.processDefinitionId = processDefinitionId; +	} + +	public void setNextTaskId(String nextTaskId) { +		this.nextTaskId = nextTaskId; +	} + +	public void setProcessState(ProcessInstanceState processState) { +		this.processState = processState; +	} + +	public void setExecutionContextData(Map<String, Serializable> executionContextData) { +		this.executionContextData = SerializationHelper.serialize((Serializable) executionContextData); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java new file mode 100644 index 000000000..57ce70c08 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAO.java @@ -0,0 +1,43 @@ +package at.gv.egovernment.moa.id.process.dao; + +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.ProcessInstance; + +public interface ProcessInstanceStoreDAO { + +	/** +	 * Stores a {@link ProcessInstance} defined by {@code pIStore} in the +	 * database. +	 *  +	 * @param pIStore +	 *            the {@link ProcessInstanceStore} to persist. +	 * @throws MOADatabaseException +	 *             is thrown if a problem occurs while accessing the database. +	 */ +	void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException; + +	/** +	 * Returns a {@link ProcessInstanceStore}, defined by +	 * {@code processInstanceID} from the database, or {@code null} if the +	 * object could not be found. +	 *  +	 * @param processInstanceId +	 *            the id of the {@code ProcessInstanceStore} to retrieve. +	 * @return a ProcessInstanceStore, or {@code null}. +	 * @throws MOADatabaseException +	 *             is thrown if a problem occurs while accessing the database. +	 */ +	ProcessInstanceStore load(String processInstanceId) throws MOADatabaseException; + +	/** +	 * Deletes the {@link ProcessInstance} corresponding with the +	 * {@code processInstanceId}. +	 *  +	 * @param processInstanceId +	 *            the id of the {@code ProcessInstance} to be deleted. +	 * @throws MOADatabaseException +	 *             is thrown if a problem occurs while accessing the database. +	 */ +	void remove(String processInstanceId) throws MOADatabaseException; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java new file mode 100644 index 000000000..012dfe90b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/dao/ProcessInstanceStoreDAOImpl.java @@ -0,0 +1,90 @@ +package at.gv.egovernment.moa.id.process.dao; + +import org.hibernate.Criteria; +import org.hibernate.Session; +import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; + +/** + * Database backed implementation of the {@link ProcessInstanceStoreDAO} + * interface. + */ +public class ProcessInstanceStoreDAOImpl implements ProcessInstanceStoreDAO { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	private static ProcessInstanceStoreDAO instance = new ProcessInstanceStoreDAOImpl(); + +	public static ProcessInstanceStoreDAO getInstance() { +		return instance; +	} + +	@Override +	public void saveOrUpdate(ProcessInstanceStore pIStore) throws MOADatabaseException { +		try { +			MOASessionDBUtils.saveOrUpdate(pIStore); +			log.debug("Store process instance with='{}' in the database.", pIStore.getProcessInstanceId()); +		} catch (MOADatabaseException e) { +			log.warn("ProcessInstanceStore could not be persisted to the database."); +			throw e; +		} +	} + +	@Override +	public ProcessInstanceStore load(String processInstanceId) throws MOADatabaseException { + +		log.debug("Retrieve the ProcessInstanceStore for id='{}' from the database.", processInstanceId); +		Session session = MOASessionDBUtils.getCurrentSession(); + +		ProcessInstanceStore result = null; +		Transaction tx = null; +		synchronized (session) { +			try { + +				tx = session.beginTransaction(); +				// select all where processInstanceId equals processInstanceId +				Criteria criteria = session.createCriteria(ProcessInstanceStore.class); +				criteria.add(Restrictions.eq("processInstanceId", processInstanceId)); +				result = (ProcessInstanceStore) criteria.uniqueResult(); +				tx.commit(); + +			} catch (Exception e) { +				log.error("There are multiple persisted processes with the same process instance id '{}'", +						processInstanceId); +				if (tx != null) { +					tx.rollback(); +				} +				throw e; +			} finally { +				MOASessionDBUtils.closeSession(); +			} +		} +		if (result != null) { +			log.debug("Found process instance store for instance '{}'.", processInstanceId); +		} else { +			log.debug("Unable to find process instance store for instance '{}'.", processInstanceId); +		} +		return result; +	} + +	@Override +	public void remove(String processInstanceId) throws MOADatabaseException { + +		log.debug("Delete the ProcessInstanceStore for id='{}' from the database.", processInstanceId); +		ProcessInstanceStore toBeDeleted = load(processInstanceId); +		if (toBeDeleted != null) { +			if (!MOASessionDBUtils.delete(toBeDeleted)) { +				log.warn("Could not delete the ProcessInstanceStore with process instance id '{}'", processInstanceId); +				throw new MOADatabaseException("Could not delete the ProcessInstanceStore with process instance id '" +						+ processInstanceId + "'."); +			} +		} else  +			log.trace("ProcessInstanceStore for id='{}' was not found and could therefore not be deleted.", processInstanceId); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java new file mode 100644 index 000000000..49fb082ea --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/EndEvent.java @@ -0,0 +1,42 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import org.apache.commons.collections4.CollectionUtils; + +/** + * Represents an end event. Process execution terminates when an end event is reached. + *  + * @author tknall + */ +public class EndEvent extends ProcessNode implements Serializable { + +	private static final long serialVersionUID = 1L; + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("EndEvent ["); +		if (getId() != null) { +			builder.append("id="); +			builder.append(getId()); +		} +		if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("incomingTransitions="); +			builder.append(getIncomingTransitions()); +		} +		if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("outgoingTransitions="); +			builder.append(getOutgoingTransitions()); +		} +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java new file mode 100644 index 000000000..518409ecf --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessDefinition.java @@ -0,0 +1,158 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Objects; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; + +/** + * Represents a single process definition containing + * <ul> + * <li>a {@link StartEvent},</li> + * <li>one or more {@linkplain TaskInfo Tasks},</li> + * <li>one or more {@linkplain EndEvent EndEvents} and</li> + * <li>some {@linkplain Transition Transitions} linking StartEvents, Tasks and EndEvents. + * </ul> + *  + * @author tknall + *  + */ +public class ProcessDefinition { + +	private String id; +	private StartEvent startEvent; +	private Map<String, TaskInfo> taskInfos = new LinkedHashMap<>(); +	private Map<String, EndEvent> endEvents = new LinkedHashMap<>(); + +	/** +	 * Returns the unique identifier of the process definition. +	 *  +	 * @return The unique identifier (never {@code null} if process definition comes from +	 *         {@link ProcessDefinitionParser}). +	 */ +	public String getId() { +		return id; +	} + +	/** +	 * Sets the unique identifier of the process definition. +	 *  +	 * @param id +	 *            The unique identifier. +	 */ +	public void setId(String id) { +		this.id = id; +	} + +	/** +	 * Returns the start event of the process definition. +	 *  +	 * @return The start event (never {@code null} if process definition comes from {@link ProcessDefinitionParser}). +	 */ +	public StartEvent getStartEvent() { +		return startEvent; +	} + +	/** +	 * Sets the start event of the process definition. +	 *  +	 * @param startEvent +	 *            The start event. +	 */ +	public void setStartEvent(StartEvent startEvent) { +		this.startEvent = startEvent; +	} + +	/** +	 * Returns a map containing the tasks of the process definition. +	 *  +	 * @return The tasks (map is never {@code null} if process definition comes from {@link ProcessDefinitionParser}). +	 */ +	public Map<String, TaskInfo> getTaskInfos() { +		return taskInfos; +	} + +	/** +	 * Sets the map containing the tasks. +	 *  +	 * @param taskInfos +	 *            The map containing the tasks. +	 */ +	public void setTaskInfos(Map<String, TaskInfo> taskInfos) { +		this.taskInfos = taskInfos; +	} + +	/** +	 * Returns a map containing the end events of the process description. +	 *  +	 * @return The map containing the end events (map is never {@code null} if process definition comes from +	 *         {@link ProcessDefinitionParser}). +	 */ +	public Map<String, EndEvent> getEndEvents() { +		return endEvents; +	} + +	/** +	 * Sets a map containing the end events of the process description. +	 *  +	 * @param endEvents +	 *            The map containing the end events. +	 */ +	public void setEndEvents(Map<String, EndEvent> endEvents) { +		this.endEvents = endEvents; +	} + +	/** +	 * Returns the process node associated with the given {@code id}. +	 *  +	 * @param id +	 *            The identifier of the process node. +	 * @return The process node (may be {code null} when no process node with the given {@code id} exists). +	 */ +	public ProcessNode getProcessNode(String id) { +		Objects.requireNonNull(id, "Identifier must not be null."); +		if (startEvent != null && id.equals(startEvent.getId())) { +			return startEvent; +		} +		TaskInfo task = taskInfos.get(id); +		if (task != null) { +			return task; +		} +		return endEvents.get(id); +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		if (id != null) { +			builder.append("id="); +			builder.append(id); +		} +		if (startEvent != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("startEvent="); +			builder.append(startEvent); +		} +		if (taskInfos != null && !taskInfos.isEmpty()) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("tasksInfos="); +			builder.append(taskInfos.values()); +		} +		if (endEvents != null && !endEvents.isEmpty()) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("endEvents="); +			builder.append(endEvents.values()); +		} +		builder.insert(0, "ProcessDefinition ["); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java new file mode 100644 index 000000000..42f2e3cc2 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/ProcessNode.java @@ -0,0 +1,69 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.util.ArrayList; +import java.util.List; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; + +/** + * Represents a {@link StartEvent}, an {@link EndEvent} or a {@linkplain TaskInfo Task}. + * @author tknall + * + */ +public abstract class ProcessNode { + +	private String id; +	private List<Transition> outgoingTransitions = new ArrayList<>(); +	private List<Transition> incomingTransitions = new ArrayList<>(); + +	/** +	 * Returns the unique identifier of the process node. +	 *  +	 * @return The unique identifier (never {@code null} if process node comes from a process definition from +	 *         {@link ProcessDefinitionParser}). +	 */ +	public String getId() { +		return id; +	} + +	/** +	 * Sets the unique identifier of the process node. +	 * @param id The unique identifier. +	 */ +	public void setId(String id) { +		this.id = id; +	} + +	/** +	 * Returns a list of transitions pointing from this process node to another one. +	 * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}). +	 */ +	public List<Transition> getOutgoingTransitions() { +		return outgoingTransitions; +	} + +	/** +	 * Sets the list of transitions pointing from this process node to another one. +	 * @param outgoingTransitions The list of transitions originating from this process node. +	 */ +	public void setOutgoingTransitions(List<Transition> outgoingTransitions) { +		this.outgoingTransitions = outgoingTransitions; +	} + +	/** +	 * Returns a list of transitions pointing from another process node to this one. +	 * @return A list of transitions (never {@code null} if process node comes from a process definition from {@link ProcessDefinitionParser}). +	 */ +	public List<Transition> getIncomingTransitions() { +		return incomingTransitions; +	} + +	/** +	 * Sets the list of transitions pointing from another process node to this one. +	 * @param incomingTransitions A list of transitions pointing to this process node. +	 */ +	public void setIncomingTransitions(List<Transition> incomingTransitions) { +		this.incomingTransitions = incomingTransitions; +	} +	 +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java new file mode 100644 index 000000000..60175e09c --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/StartEvent.java @@ -0,0 +1,45 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import org.apache.commons.collections4.CollectionUtils; + +/** + * Represents a start event. Each process description contains a single start event. Process execution starts with a + * start event. + *  + * @author tknall + *  + */ +public class StartEvent extends ProcessNode implements Serializable { + +	private static final long serialVersionUID = 1L; + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		builder.append("StartEvent ["); +		if (getId() != null) { +			builder.append("id="); +			builder.append(getId()); +		} +		if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("incomingTransitions="); +			builder.append(getIncomingTransitions()); +		} +		if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("outgoingTransitions="); + +			builder.append(getOutgoingTransitions()); +		} +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java new file mode 100644 index 000000000..78a9d6a0a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/TaskInfo.java @@ -0,0 +1,94 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import org.apache.commons.collections4.CollectionUtils; + +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Represents information about a single task to be performed upon process execution. + * @author tknall + * + */ +public class TaskInfo extends ProcessNode implements Serializable { + +	private static final long serialVersionUID = 1L; +	private static final boolean DEFAULT_ASYNC = false; +	 +	private String taskImplementingClass; +	private boolean async = DEFAULT_ASYNC; +	 +	/** +	 * Determines if the task is marked asynchronous ({@code true}) or synchronous ({@code false}). +	 * @return A flag indicating if the task should be executed asynchronously or synchronously. (Default: {@code false}) +	 */ +	public boolean isAsync() { +		return async; +	} + +	/** +	 * Marks a task to executed asynchronously ({@code true}) or synchronously ({@code false}). +	 * @param async The flag. +	 */ +	public void setAsync(boolean async) { +		this.async = async; +	} + +	/** +	 * Returns the class that implements the actual task (must implement {@link Task}). +	 * @return The task implementing class. +	 */ +	public String getTaskImplementingClass() { +		return taskImplementingClass; +	} + +	/** +	 * Sets the class that implements the actual task (must implement {@link Task}). +	 * @param taskImplementingClass The task implementing class. +	 */ +	public void setTaskImplementingClass(String taskImplementingClass) { +		this.taskImplementingClass = taskImplementingClass; +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		if (getId() != null) { +			builder.append("id="); +			builder.append(getId()); +		} +		if (async != DEFAULT_ASYNC) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("async="); +			builder.append(async); +		} +		if (taskImplementingClass != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("taskImplementingClass="); +			builder.append(taskImplementingClass); +		} +		if (CollectionUtils.isNotEmpty(getIncomingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("incomingTransitions="); +			builder.append(getIncomingTransitions()); +		} +		if (CollectionUtils.isNotEmpty(getOutgoingTransitions())) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("outgoingTransitions="); +			builder.append(getOutgoingTransitions()); +		} +		builder.insert(0, "TaskInfo ["); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java new file mode 100644 index 000000000..bc3005534 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/model/Transition.java @@ -0,0 +1,136 @@ +package at.gv.egovernment.moa.id.process.model; + +import java.io.Serializable; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; + +/** + * Represents a single transition from a {@link StartEvent} or {@linkplain TaskInfo Task} to another + * {@linkplain TaskInfo Task} or {@link EndEvent}. + *  + * @author tknall + *  + */ +public class Transition implements Serializable { + +	private static final long serialVersionUID = 1L; + +	private String id; +	private String conditionExpression; +	private ProcessNode from; +	private ProcessNode to; + +	/** +	 * Returns the process node (effectively a {@link StartEvent} or {@linkplain TaskInfo Task}) the transition is +	 * pointing from. +	 *  +	 * @return The transition's source process node (never {@code null} if transition comes from a process definition +	 *         from {@link ProcessDefinitionParser}). +	 */ +	public ProcessNode getFrom() { +		return from; +	} + +	/** +	 * Sets the process node the transition is pointing from. +	 *  +	 * @param from +	 *            The transition's source process node. +	 */ +	public void setFrom(ProcessNode from) { +		this.from = from; +	} + +	/** +	 * Returns the process node (effectively a {@linkplain TaskInfo Task} or {@link EndEvent}) the transition is +	 * pointing to. +	 *  +	 * @return The transition's destination process node (never {@code null} if transition comes from a process +	 *         definition from {@link ProcessDefinitionParser}). +	 */ +	public ProcessNode getTo() { +		return to; +	} + +	/** +	 * Sets the process node the transition is pointing to. +	 *  +	 * @param to +	 *            The transition's destination process node. +	 */ +	public void setTo(ProcessNode to) { +		this.to = to; +	} + +	/** +	 * Returns the unique identifier of the transition. +	 *  +	 * @return The unique identifier (may be {@code null}). +	 */ +	public String getId() { +		return id; +	} + +	/** +	 * Sets the unique identifier of the transition. +	 *  +	 * @param id +	 *            The unique identifier. +	 */ +	public void setId(String id) { +		this.id = id; +	} + +	/** +	 * Returns the condition expression for this transition. +	 *  +	 * @return The condition expression (may be {@code null}). +	 */ +	public String getConditionExpression() { +		return conditionExpression; +	} + +	/** +	 * Sets the condition expression for this transition. +	 *  +	 * @param conditionExpression +	 *            The condition expression. +	 */ +	public void setConditionExpression(String conditionExpression) { +		this.conditionExpression = conditionExpression; +	} + +	@Override +	public String toString() { +		StringBuilder builder = new StringBuilder(); +		if (id != null) { +			builder.append("id="); +			builder.append(id); +		} +		if (from != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("from.id="); +			builder.append(from.getId()); +		} +		if (to != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("to.id="); +			builder.append(to.getId()); +		} +		if (conditionExpression != null) { +			if (builder.length() > 0) { +				builder.append(", "); +			} +			builder.append("conditionExpression="); +			builder.append(conditionExpression); +		} +		builder.insert(0, "Transition ["); +		builder.append("]"); +		return builder.toString(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java new file mode 100644 index 000000000..5b30c7172 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/spring/SpringExpressionEvaluator.java @@ -0,0 +1,61 @@ +package at.gv.egovernment.moa.id.process.spring; + +import java.util.Objects; + +import javax.annotation.PostConstruct; + +import org.apache.commons.lang3.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.expression.Expression; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Expression evaluator for processing {@link Transition} conditions allowing to reference Spring beans from the + * application context. + *  + * @author tknall + *  + */ +public class SpringExpressionEvaluator implements ExpressionEvaluator { + +	private Logger log = LoggerFactory.getLogger(getClass()); +	private ExpressionParser parser = new SpelExpressionParser(); +	private StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + +	@Autowired(required = false) +	private ApplicationContext ctx; + +	@PostConstruct +	private void init() { +		if (ctx != null) { +			evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); +		} +	} + +	@Override +	public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { +		Objects.requireNonNull(expression, "Expression must not be null."); +		log.trace("Evaluating '{}'.", expression); + +		Expression expr = parser.parseExpression(expression); +		Boolean result = expr.getValue(evaluationContext, expressionContext, Boolean.class); +		if (result == null) { +			log.warn("Evaluation of '{}' results in null-value.", expression); +		} else { +			log.debug("Expression '{}' -> {}", expression, result); +		} + +		return BooleanUtils.isTrue(result); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java new file mode 100644 index 000000000..738b58834 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/AbstractAuthSourceServlet.java @@ -0,0 +1,116 @@ +package at.gv.egovernment.moa.id.process.springweb; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.beans.factory.NoUniqueBeanDefinitionException; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; + +/** + * Abstract HttpServlet that provides means for retrieving the process engine (Spring Web required) as well as + * retrieving the underlying process instance and execution context evaluating a certain request parameter. + *  + * @author tknall + *  + */ +public abstract class AbstractAuthSourceServlet extends HttpServlet { + +	private static final long serialVersionUID = 1L; + +	private ProcessEngine processEngine; +	 +	/** +	 * Returns the name of the request parameter representing the respective instance id. +	 * <p/>Default is {@code processInstanceId}. +	 * @return The request parameter name. +	 */ +	public String getProcessInstanceIdParameterName() { +		return "processInstanceId"; +	} + +	/** +	 * Returns the underlying process engine instance. +	 *  +	 * @return The process engine (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 */ +	public synchronized ProcessEngine getProcessEngine() { +		if (processEngine == null) { +			WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(getServletContext()); +			if (ctx == null) { +				throw new IllegalStateException( +						"Unable to find Spring WebApplicationContext. Servlet needs to be executed within a Spring web environment."); +			} +			processEngine = ctx.getBean(ProcessEngine.class); +		} +		return processEngine; +	} + +	/** +	 * Retrieves the process instance referenced by the request parameter {@link #getProcessInstanceIdParameterName()}. +	 *  +	 * @param request +	 *            The HttpServletRequest. +	 * @return The process instance (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 * @throws IllegalArgumentException +	 *             in case the process instance id referenced by the request parameter +	 *             {@link #getProcessInstanceIdParameterName()} does not exist. +	 */ +	public ProcessInstance getProcessInstance(HttpServletRequest request) { +		String processInstanceId = StringUtils.trimToNull(request.getParameter(getProcessInstanceIdParameterName())); +		if (processInstanceId == null) { +			throw new IllegalArgumentException("Missing request parameter '" + getProcessInstanceIdParameterName() + "'."); +		} +		return getProcessEngine().getProcessInstance(processInstanceId); +	} + +	/** +	 * Retrieves the execution context for the respective process instance referenced by the request parameter +	 * {@link #getProcessInstanceIdParameterName()}. +	 *  +	 * @param request +	 *            The HttpServletRequest. +	 * @return The execution context (never {@code null}). +	 * @throws NoSuchBeanDefinitionException +	 *             if no {@link ProcessEngine} bean was found. +	 * @throws NoUniqueBeanDefinitionException +	 *             if more than one {@link ProcessEngine} bean was found. +	 * @throws BeansException +	 *             if a problem getting the {@link ProcessEngine} bean occurred. +	 * @throws IllegalStateException +	 *             if the Spring WebApplicationContext was not found, which means that the servlet is used outside a +	 *             Spring web environment. +	 * @throws IllegalArgumentException +	 *             in case the process instance id referenced by the request parameter +	 *             {@link #getProcessInstanceIdParameterName()} does not exist. +	 */ +	public ExecutionContext getExecutionContext(HttpServletRequest request) { +		return getProcessInstance(request).getExecutionContext(); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java new file mode 100644 index 000000000..fb75fc8d7 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/MoaIdTask.java @@ -0,0 +1,74 @@ +package at.gv.egovernment.moa.id.process.springweb; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.filter.RequestContextFilter; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Abstract task implementation providing {@link HttpServletRequest} and {@link HttpServletResponse}. + * <p/> + * Note that this abstract task requires the Spring (web) framework including a {@link RequestContextFilter} to be set + * within {@code web.xml}. + *  + * <pre> + * ... + * <filter> + *   <filter-name>requestContextFilter</filter-name> + *   <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class> + * </filter> + * <filter-mapping> + *   <filter-name>requestContextFilter</filter-name> + *   <url-pattern>/*</url-pattern> + * </filter-mapping> + * ... + * </pre> + *  + * @author tknall + *  + */ +public abstract class MoaIdTask implements Task { + +	/** +	 * Executes the task providing the underlying {@link ExecutionContext} {@code executionContext} as well as the +	 * respective {@link HttpServletRequest} and {@link HttpServletResponse}. +	 *  +	 * @param executionContext +	 *            The execution context (never {@code null}). +	 * @param request +	 *            The HttpServletRequest (never {@code null}). +	 * @param response +	 *            The HttpServletResponse (never {@code null}). +	 * @throws IllegalStateException +	 *             Thrown in case the task is nur being run within the required environment. Refer to javadoc for +	 *             further information. +	 * @throws Exception +	 *             Thrown in case of error executing the task. +	 */ +	public abstract void execute(ExecutionContext executionContext, HttpServletRequest request, +			HttpServletResponse response) throws TaskExecutionException; + +	@Override +	public void execute(ExecutionContext executionContext) throws TaskExecutionException { +		RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); +		if (requestAttributes != null && requestAttributes instanceof ServletRequestAttributes) { +			HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest(); +			HttpServletResponse response = ((ServletRequestAttributes) requestAttributes).getResponse(); +			if (request == null || response == null) { +				throw new IllegalStateException( +						"Spring's RequestContextHolder did not provide HttpServletResponse. Did you forget to set the required org.springframework.web.filter.RequestContextFilter in your web.xml."); +			} +			execute(executionContext, request, response); +		} else { +			throw new IllegalStateException("Task needs to be executed within a Spring web environment."); +		} +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java new file mode 100644 index 000000000..af6822ba6 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/springweb/SpringWebExpressionEvaluator.java @@ -0,0 +1,143 @@ +package at.gv.egovernment.moa.id.process.springweb; + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; + +import javax.annotation.PostConstruct; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.BooleanUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.expression.Expression; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; +import at.gv.egovernment.moa.id.process.model.Transition; + +/** + * Expression evaluator for processing {@link Transition} conditions allowing to + * <ul> + * <li>reference Spring beans from the application context using {@code @myBeanName...},</li> + * <li>{@link ExecutionContext} properties using {@code ctx['property']},</li> + * <li>Multi valued {@link HttpServletRequest} parameters using {@code requestParameters['foo']} (keep in mind that this + * expression returns an array of String values) and</li> + * <li>Single valued {@link HttpServletRequest} parameters using {@code requestParameter['foo']}</li> + * </ul> + *  + * @author tknall + *  + */ +public class SpringWebExpressionEvaluator implements ExpressionEvaluator { + +	private Logger log = LoggerFactory.getLogger(getClass()); +	private ExpressionParser parser = new SpelExpressionParser(); +	private StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + +	@Autowired(required = false) +	private ApplicationContext ctx; + +	@Autowired(required = false) +	private HttpServletRequest request; + +	@PostConstruct +	private void init() { +		if (ctx != null) { +			evaluationContext.setBeanResolver(new BeanFactoryResolver(ctx)); +		} +	} + +	/** +	 * Evaluation context that provides access to {@link HttpServletRequest} parameters using +	 * {@code requestParameter['foo']} for single value parameters or {@code requestParameters['foo']} for multi value +	 * parameters. Basic calls to {@code ctx} will be delegated. +	 *  +	 * @author tknall +	 *  +	 */ +	private class SpringWebExpressionEvaluationContext implements ExpressionEvaluationContext { + +		private static final long serialVersionUID = 1L; + +		/** +		 * Creates a new expression evaluation context, providing access to HttpServletRequest parameter(s). +		 *  +		 * @param delegate +		 *            The original {@link ExpressionEvaluationContext} to be delegated to for {@code ctx['foo']} +		 *            expressions. +		 */ +		public SpringWebExpressionEvaluationContext(ExpressionEvaluationContext delegate) { +			this.delegate = delegate; +		} + +		private ExpressionEvaluationContext delegate; + +		@Override +		public Map<String, Serializable> getCtx() { +			return delegate.getCtx(); +		} + +		@SuppressWarnings("unused") +		public Map<String, String> getRequestParameter() { +			if (request != null) { +				Map<String, String> singleValueMap = new HashMap<String, String>(); +				Iterator<Entry<String, String[]>> it = request.getParameterMap().entrySet().iterator(); +				while (it.hasNext()) { +					Entry<String, String[]> entry = it.next(); +					if (ArrayUtils.isNotEmpty(entry.getValue())) { +						singleValueMap.put(entry.getKey(), entry.getValue()[0]); +					} +				} +				return singleValueMap; +			} else { +				return Collections.<String, String> emptyMap(); +			} +		} + +		@SuppressWarnings("unused") +		public Map<String, String[]> getRequestParameters() { +			if (request != null) { +				return request.getParameterMap(); +			} else { +				return Collections.<String, String[]> emptyMap(); +			} +		} + +	} + +	@Override +	public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { +		Objects.requireNonNull(expression, "Expression must not be null."); +		log.trace("Evaluating '{}'.", expression); + +		Expression expr = parser.parseExpression(expression); +		Boolean result = null; +		try { +			result = expr.getValue(evaluationContext, new SpringWebExpressionEvaluationContext(expressionContext), +					Boolean.class); +			if (result == null) { +				log.warn("Evaluation of '{}' results in null-value.", expression); +			} else { +				log.debug("Expression '{}' -> {}", expression, result); +			} +		} catch (Exception e) { +			log.warn("Expression '{}' could not be processed.", expression, e); +		} + +		return BooleanUtils.isTrue(result); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java new file mode 100644 index 000000000..72677739a --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/process/support/SecureRandomHolder.java @@ -0,0 +1,35 @@ +package at.gv.egovernment.moa.id.process.support; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * Holder for a secure random instance following the initialization on demand holder design pattern. The secure random + * instance is a singleton that is initialized on first usage. + *  + * @author tknall + *  + */ +public class SecureRandomHolder { + +	private SecureRandomHolder() { +	} + +	private static final SecureRandom SRND_INSTANCE; +	static { +		try { +			SRND_INSTANCE = SecureRandom.getInstance("SHA1PRNG"); +		} catch (NoSuchAlgorithmException e) { +			throw new RuntimeException("Unable to instantiate SHA1PRNG.", e); +		} +	} + +	/** +	 * Returns a secure random generator instance. +	 * @return The secure random instance. +	 */ +	public static SecureRandom getInstance() { +		return SecureRandomHolder.SRND_INSTANCE; +	} + +}
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java index 1f3e86ff6..168f2362a 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVPConstants.java @@ -237,12 +237,12 @@ public interface PVPConstants {  	public static final String MANDATE_PROF_REP_OID_OID = "1.2.40.0.10.2.1.1.261.86";  	public static final String MANDATE_PROF_REP_OID_NAME = URN_OID_PREFIX + MANDATE_PROF_REP_OID_OID; -	public static final String MANDATE_PROF_REP_OID_FRIENDLY_NAME = "MANDATOR-PROF-REP-OID"; +	public static final String MANDATE_PROF_REP_OID_FRIENDLY_NAME = "MANDATE-PROF-REP-OID";  	public static final int MANDATE_PROF_REP_OID_MAX_LENGTH = 256;  	public static final String MANDATE_PROF_REP_DESC_OID = "1.2.40.0.10.2.1.1.261.88";  	public static final String MANDATE_PROF_REP_DESC_NAME = URN_OID_PREFIX + MANDATE_PROF_REP_DESC_OID; -	public static final String MANDATE_PROF_REP_DESC_FRIENDLY_NAME = "MANDATOR-PROF-REP-DESCRIPTION"; +	public static final String MANDATE_PROF_REP_DESC_FRIENDLY_NAME = "MANDATE-PROF-REP-DESCRIPTION";  	public static final int MANDATE_PROF_REP_DESC_MAX_LENGTH = 1024;  	public static final String MANDATE_REFERENCE_VALUE_OID = "1.2.40.0.10.2.1.1.261.90"; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java index b22941216..aa154b84b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/SingleLogOutAction.java @@ -135,8 +135,10 @@ public class SingleLogOutAction implements IAction {  					if (MiscUtil.isEmpty(ssoID)) {  						Logger.warn("Can not find active Session. Single LogOut not possible!");  						SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); -						LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); -						SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState()); +						//LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); +						LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, null); +						Logger.info("Sending SLO success message to requester ..."); +						SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());						  						return null;  					} else { @@ -147,7 +149,9 @@ public class SingleLogOutAction implements IAction {  						} catch (MOADatabaseException e) {  							Logger.warn("Can not find active Session. Single LogOut not possible!");  							SingleLogoutService sloService = SingleLogOutBuilder.getResponseSLODescriptor(pvpReq); -							LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); +							//LogoutResponse message = SingleLogOutBuilder.buildSLOErrorResponse(sloService, pvpReq, StatusCode.RESPONDER_URI); +							LogoutResponse message = SingleLogOutBuilder.buildSLOResponseMessage(sloService, pvpReq, null); +							Logger.info("Sending SLO success message to requester ...");  							SingleLogOutBuilder.sendFrontChannelSLOMessage(sloService, message, httpReq, httpResp, samlReq.getRelayState());  							return null; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java index 01139d95c..50f42d928 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/SingleLogOutBuilder.java @@ -43,6 +43,7 @@ import org.opensaml.saml2.core.StatusCode;  import org.opensaml.saml2.core.StatusMessage;  import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.metadata.EntityDescriptor; +import org.opensaml.saml2.metadata.IDPSSODescriptor;  import org.opensaml.saml2.metadata.SPSSODescriptor;  import org.opensaml.saml2.metadata.SSODescriptor;  import org.opensaml.saml2.metadata.SingleLogoutService; @@ -348,17 +349,29 @@ public class SingleLogOutBuilder {  	public static SingleLogoutService getResponseSLODescriptor(PVPTargetConfiguration spRequest) throws NoMetadataInformationException, NOSLOServiceDescriptorException {  		MOARequest moaReq = (MOARequest) spRequest.getRequest();  		EntityDescriptor metadata = moaReq.getEntityMetadata(); -		SPSSODescriptor spsso = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); +		SSODescriptor ssodesc = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); +		 +		if (ssodesc == null) { +			Logger.debug("No PVP SPSSO descriptor found --> search IDPSSO descriptor"); +			ssodesc = metadata.getIDPSSODescriptor(SAMLConstants.SAML20P_NS); +						 +		} + +		if (ssodesc == null) { +			Logger.error("Found no SLO ServiceDescriptor in Metadata");				 +			throw new NOSLOServiceDescriptorException("NO SLO ServiceDescriptor", null); +		} +		  		SingleLogoutService sloService = null;			 -		for (SingleLogoutService el : spsso.getSingleLogoutServices()) { +		for (SingleLogoutService el : ssodesc.getSingleLogoutServices()) {  			if (el.getBinding().equals(spRequest.getBinding()))  				sloService = el;  		}  		if (sloService == null)  { -			if (spsso.getSingleLogoutServices().size() != 0)		 -				sloService = spsso.getSingleLogoutServices().get(0); +			if (ssodesc.getSingleLogoutServices().size() != 0)		 +				sloService = ssodesc.getSingleLogoutServices().get(0);  			else {  				Logger.error("Found no SLO ServiceDescriptor in Metadata");				 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java index 4c981cb24..e7ba26158 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/attributes/MandateProfRepDescAttributeBuilder.java @@ -22,10 +22,14 @@   *******************************************************************************/  package at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes; +import org.w3c.dom.Element; + +import at.gv.e_government.reference.namespace.mandates._20040701_.Mandate;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.data.IAuthData;  import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.AttributeException;  import at.gv.egovernment.moa.id.protocols.pvp2x.builder.attributes.exceptions.NoMandateDataAttributeException; +import at.gv.egovernment.moa.id.util.MandateBuilder;  import at.gv.egovernment.moa.id.util.client.mis.simple.MISMandate;  import at.gv.egovernment.moa.util.MiscUtil; @@ -37,23 +41,36 @@ public class MandateProfRepDescAttributeBuilder implements IPVPAttributeBuilder  	public <ATT> ATT build(OAAuthParameter oaParam, IAuthData authData,  			IAttributeGenerator<ATT> g) throws AttributeException { -		if(authData.isUseMandate()) {			 -			MISMandate mandate = authData.getMISMandate(); - +		if(authData.isUseMandate()) { +			String text = null; -			if(mandate == null) { +			MISMandate misMandate = authData.getMISMandate(); +			 +			if(misMandate == null) {  				throw new NoMandateDataAttributeException();  			} +		 +			text = misMandate.getTextualDescriptionOfOID(); -			String text = mandate.getTextualDescriptionOfOID(); +			if (MiscUtil.isEmpty(text)) {			 +				Element mandate = authData.getMandate(); +				if (mandate == null) { +					throw new NoMandateDataAttributeException(); +				} -			if(MiscUtil.isEmpty(text)) { -				return null; +				Mandate mandateObject = MandateBuilder.buildMandate(authData.getMandate()); +				if (mandateObject == null) { +					throw new NoMandateDataAttributeException(); +				} + +				text = mandateObject.getAnnotation(); -			} else				 +			} +			 +			if(MiscUtil.isNotEmpty(text))   				return g.buildStringAttribute(MANDATE_PROF_REP_DESC_FRIENDLY_NAME,   						MANDATE_PROF_REP_DESC_NAME, text); -			 +										  		}  		return null; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java new file mode 100644 index 000000000..fc4ed1f28 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/SchemaValidationException.java @@ -0,0 +1,52 @@ +/* + * Copyright 2014 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.protocols.pvp2x.exceptions; + +/** + * @author tlenz + * + */ +public class SchemaValidationException extends PVP2Exception { + +	/** +	 *  +	 */ +	private static final long serialVersionUID = 1L; + +	/** +	 * @param messageId +	 * @param parameters +	 */ +	public SchemaValidationException(String messageId, Object[] parameters) { +		super(messageId, parameters); +	} +	 +	/** +	 * @param messageId +	 * @param parameters +	 */ +	public SchemaValidationException(String messageId, Object[] parameters, Throwable e) { +		super(messageId, parameters, e); +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SchemaValidationException.java index 4e26b1ce8..8da5edeed 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/monitoring/TestModuleInterface.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SchemaValidationException.java @@ -1,4 +1,4 @@ -/******************************************************************************* +/*   * Copyright 2014 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. @@ -19,16 +19,25 @@   * 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.monitoring; + */ +package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter; -import java.util.List; +import org.opensaml.saml2.metadata.provider.FilterException; -public interface TestModuleInterface { +/** + * @author tlenz + * + */ +public class SchemaValidationException extends FilterException { + +	/** +	 * @param string +	 */ +	public SchemaValidationException(String string) { +		super(string); +		 +	} + +	private static final long serialVersionUID = 1L; -	public List<String> performTests() throws Exception; -	 -	public void initializeTest(long delayParam, String url) throws Exception;  -	 -	public String getName();  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java new file mode 100644 index 000000000..86a6a777b --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/filter/SignatureValidationException.java @@ -0,0 +1,58 @@ +/* + * Copyright 2014 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.protocols.pvp2x.exceptions.filter; + +import org.opensaml.saml2.metadata.provider.FilterException; + +/** + * @author tlenz + * + */ +public class SignatureValidationException extends FilterException { + +	/** +	 * @param string +	 */ +	public SignatureValidationException(String string) { +		super(string); +		 +	} + +	/** +	 * @param e +	 */ +	public SignatureValidationException(Exception e) { +		super(e); +	} + +	/** +	 * @param string +	 * @param object +	 */ +	public SignatureValidationException(String string, Exception e) { +		super(string, e); +	} + +	private static final long serialVersionUID = 1L; + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html index 3eff06daf..5ae76ed96 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/loginFormFull.html @@ -842,7 +842,7 @@ input {  				src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java index cba64e080..d493ef9e0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/metadata/MOAMetadataProvider.java @@ -55,8 +55,11 @@ import at.gv.egovernment.moa.id.commons.ex.MOAHttpProtocolSocketFactoryException  import at.gv.egovernment.moa.id.commons.utils.MOAHttpProtocolSocketFactory;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.InterfederatedIDPPublicServiceFilter;  import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.MetadataFilterChain; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.metadata.SchemaValidationFilter;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil; @@ -324,6 +327,7 @@ public class MOAMetadataProvider implements MetadataProvider {  	private MetadataFilterChain buildMetadataFilterChain(OnlineApplication oa, String metadataURL, byte[] certificate) throws CertificateException {  		MetadataFilterChain filterChain = new MetadataFilterChain(metadataURL, certificate); +		filterChain.getFilters().add(new SchemaValidationFilter());  		if (oa.isIsInterfederationIDP() != null && oa.isIsInterfederationIDP()) {  			Logger.info("Online-Application is an interfederated IDP. Add addional Metadata policies"); @@ -374,12 +378,22 @@ public class MOAMetadataProvider implements MetadataProvider {  			httpProvider.setMetadataFilter(filter);  			httpProvider.initialize(); +			httpProvider.setRequireValidMetadata(true); +			  			return httpProvider; -		} catch (Throwable e) { +		} catch (Throwable e) {			  			if (e.getCause() != null && e.getCause().getCause() instanceof SSLHandshakeException) {  				Logger.warn("SSL-Server certificate for metadata "  -						+ metadataURL + " not trusted.", e);				 +						+ metadataURL + " not trusted.", e); +				 +			} if (e.getCause() != null && e.getCause().getCause() instanceof SignatureValidationException) {				 +				Logger.warn("Signature verification for metadata"  +						+ metadataURL + " FAILED.", e); +			 +			} if (e.getCause() != null && e.getCause().getCause() instanceof SchemaValidationException) { +				Logger.warn("Schema validation for metadata "  +						+ metadataURL + " FAILED.", e);								  			}  			Logger.error( diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java index f0373e214..26b3bfbd1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/AssertionAttributeExtractor.java @@ -54,8 +54,7 @@ public class AssertionAttributeExtractor {  	private final List<String> minimalAttributeNameList = Arrays.asList(  			PVPConstants.PRINCIPAL_NAME_NAME,  -			PVPConstants.GIVEN_NAME_NAME, -			PVPConstants.BIRTHDATE_NAME); +			PVPConstants.GIVEN_NAME_NAME);  	public AssertionAttributeExtractor(StatusResponseType samlResponse) throws AssertionAttributeExtractorExeption { @@ -119,16 +118,21 @@ public class AssertionAttributeExtractor {  		//first check if a bPK or an encrypted bPK is available  		if (attributs.containsKey(PVPConstants.ENC_BPK_LIST_NAME) ||  -				(attributs.containsKey(PVPConstants.BPK_NAME) && attributs.containsKey(PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME))) { +				(attributs.containsKey(PVPConstants.BPK_NAME))) {			  			boolean flag = true;  			for (String attr : attributeNameList) { -				if (!attributs.containsKey(attr)) +				if (!attributs.containsKey(attr)) {  					flag = false; +					Logger.debug("Assertion contains no Attribute " + attr); +					 +				} +					  			}  			return flag; -		}			 +		} +		Logger.debug("Assertion contains no bPK or encryptedbPK.");  		return false;  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java index 4ba93f8fe..257f9dac4 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/SAMLVerificationEngine.java @@ -25,14 +25,20 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.verification;  import java.util.ArrayList;  import java.util.List; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; +  import org.joda.time.DateTime;  import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.common.xml.SAMLSchemaBuilder;  import org.opensaml.saml2.core.Conditions;  import org.opensaml.saml2.core.EncryptedAssertion;  import org.opensaml.saml2.core.RequestAbstractType;  import org.opensaml.saml2.core.Response;  import org.opensaml.saml2.core.StatusCode;  import org.opensaml.saml2.core.StatusResponseType; +import org.opensaml.saml2.core.validator.AuthnRequestSchemaValidator;  import org.opensaml.saml2.encryption.Decrypter;  import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver;  import org.opensaml.saml2.metadata.IDPSSODescriptor; @@ -51,11 +57,14 @@ import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver;  import org.opensaml.xml.security.x509.X509Credential;  import org.opensaml.xml.signature.SignatureTrustEngine;  import org.opensaml.xml.validation.ValidationException; +import org.w3c.dom.Element; +import org.xml.sax.SAXException;  import at.gv.egovernment.moa.id.auth.exception.InvalidProtocolRequestException;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SchemaValidationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; @@ -81,9 +90,15 @@ public class SAMLVerificationEngine {  		SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();  		try {  		    profileValidator.validate(samlObj.getSignature()); +		    performSchemaValidation(samlObj.getDOM()); +		      		} catch (ValidationException e) { -		    // Indicates signature did not conform to SAML Signature profile -		    e.printStackTrace(); +			 Logger.warn("Signature is not conform to SAML signature profile", e); +			 throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); +		 +		} catch (SchemaValidationException e) {			 +			throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); +		  		}  		CriteriaSet criteriaSet = new CriteriaSet(); @@ -103,12 +118,17 @@ public class SAMLVerificationEngine {  	public void verifyRequest(RequestAbstractType samlObj, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {  		SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); -		  		try { -		    profileValidator.validate(samlObj.getSignature()); +		    profileValidator.validate(samlObj.getSignature());		     +		    performSchemaValidation(samlObj.getDOM()); +		      		} catch (ValidationException e) { -		    // Indicates signature did not conform to SAML Signature profile -		    e.printStackTrace(); +		    Logger.warn("Signature is not conform to SAML signature profile", e); +		    throw new InvalidProtocolRequestException("pvp2.21", new Object[] {}); +		     +		} catch (SchemaValidationException e) {			 +			throw new InvalidProtocolRequestException("pvp2.22", new Object[] {e.getMessage()}); +			  		}  		CriteriaSet criteriaSet = new CriteriaSet(); @@ -173,16 +193,27 @@ public class SAMLVerificationEngine {  				List<org.opensaml.saml2.core.Assertion> validatedassertions = new ArrayList<org.opensaml.saml2.core.Assertion>();				  				for (org.opensaml.saml2.core.Assertion saml2assertion : saml2assertions) { -					Conditions conditions = saml2assertion.getConditions(); -					DateTime notbefore = conditions.getNotBefore(); +					try { +						performSchemaValidation(saml2assertion.getDOM()); +											 +						Conditions conditions = saml2assertion.getConditions(); +					DateTime notbefore = conditions.getNotBefore().minusMinutes(5);  					DateTime notafter = conditions.getNotOnOrAfter();  					if ( notbefore.isAfterNow() || notafter.isBeforeNow() ) { -						Logger.warn("PVP2 Assertion is out of Date"); +						Logger.warn("PVP2 Assertion is out of Date. " +								+ "{ Current : " + new DateTime()  +								+ " NotBefore: " + notbefore  +								+ " NotAfter : " + notafter +								+ " }");; -					} else { -						validatedassertions.add(saml2assertion); +						} else { +							validatedassertions.add(saml2assertion); +						 +						} +						 +					} catch (SchemaValidationException e) { -					}							 +					}  				}  				if (validatedassertions.isEmpty()) { @@ -213,4 +244,35 @@ public class SAMLVerificationEngine {  			throw new AssertionValidationExeption("pvp.12", null, e);  		} 		  	} +	 +	private static void performSchemaValidation(Element source) throws SchemaValidationException { +		 +		String err = null; +		try { +			Schema test = SAMLSchemaBuilder.getSAML11Schema(); +			Validator val = test.newValidator();		 +			val.validate(new DOMSource(source)); +			Logger.debug("Schema validation check done OK"); +			return; +		 +		} catch (SAXException e) { +			err = e.getMessage(); +			if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) +				Logger.warn("Schema validation FAILED with exception:", e); +			else +				Logger.warn("Schema validation FAILED with message: "+ e.getMessage()); +						 +		} catch (Exception e) { +			err = e.getMessage(); +			if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) +				Logger.warn("Schema validation FAILED with exception:", e); +			else +				Logger.warn("Schema validation FAILED with message: "+ e.getMessage()); +						 +		} +		 +		throw new SchemaValidationException("pvp2.22", new Object[]{err}); +		 +	} +	  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java index 3d608fd6d..4d9b97a52 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/InterfederatedIDPPublicServiceFilter.java @@ -26,7 +26,6 @@ import org.opensaml.saml2.metadata.provider.FilterException;  import org.opensaml.saml2.metadata.provider.MetadataFilter;  import org.opensaml.xml.XMLObject; -import at.gv.egovernment.moa.id.commons.db.dao.config.InterfederationIDPType;  import at.gv.egovernment.moa.id.commons.validation.ValidationHelper;  import at.gv.egovernment.moa.logging.Logger; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java index 0405fa114..6dac4bba1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/MetadataSignatureFilter.java @@ -39,6 +39,7 @@ import org.opensaml.xml.security.x509.BasicX509Credential;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoCredentialsException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.filter.SignatureValidationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.verification.EntityVerifier;  import at.gv.egovernment.moa.logging.Logger; @@ -126,7 +127,7 @@ public class MetadataSignatureFilter implements MetadataFilter {  		desc.getEntityDescriptors().addAll(verifiedEntIT);  	} -	public void doFilter(XMLObject metadata) throws FilterException { +	public void doFilter(XMLObject metadata) throws SignatureValidationException {  		try {  			if (metadata instanceof EntitiesDescriptor) {  				EntitiesDescriptor entitiesDescriptor = (EntitiesDescriptor) metadata; @@ -155,7 +156,7 @@ public class MetadataSignatureFilter implements MetadataFilter {  			Logger.info("Metadata signature policy check done OK");  		} catch (MOAIDException e) {  			Logger.warn("Metadata signature policy check FAILED.", e); -			throw new FilterException(e); +			throw new SignatureValidationException(e);  		}  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java new file mode 100644 index 000000000..f73b541bf --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/verification/metadata/SchemaValidationFilter.java @@ -0,0 +1,109 @@ +/* + * Copyright 2014 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.protocols.pvp2x.verification.metadata; + +import org.opensaml.saml2.metadata.provider.FilterException; +import org.opensaml.saml2.metadata.provider.MetadataFilter; +import org.opensaml.xml.XMLObject; + +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import org.opensaml.common.xml.SAMLSchemaBuilder; + +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.id.protocols.pvp2x.exceptions.filter.SchemaValidationException; +import at.gv.egovernment.moa.logging.Logger; + +/** + * @author tlenz + * + */ +public class SchemaValidationFilter implements MetadataFilter { + +	private boolean isActive = true; +	 +	public SchemaValidationFilter() { +		try { +			isActive = AuthConfigurationProvider.getInstance().isPVPSchemaValidationActive(); +			 +		} catch (ConfigurationException e) { +			e.printStackTrace(); +		} +	} +	 +	/** +	 *  +	 */ +	public SchemaValidationFilter(boolean useSchemaValidation) { +		this.isActive = useSchemaValidation; +	} +	 +	 +	/* (non-Javadoc) +	 * @see org.opensaml.saml2.metadata.provider.MetadataFilter#doFilter(org.opensaml.xml.XMLObject) +	 */ +	@Override +	public void doFilter(XMLObject arg0) throws SchemaValidationException { +		 +		String errString = null; +		 +		if (isActive) { +			try { +				Schema test = SAMLSchemaBuilder.getSAML11Schema(); +				Validator val = test.newValidator(); +				DOMSource source = new DOMSource(arg0.getDOM());		 +				val.validate(source); +				Logger.info("Metadata Schema validation check done OK"); +				return; +			 +			} catch (SAXException e) { +				if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) +					Logger.warn("Metadata Schema validation FAILED with exception:", e); +				else +					Logger.warn("Metadata Schema validation FAILED with message: "+ e.getMessage()); + +				errString = e.getMessage(); +				 +			} catch (Exception e) { +				if (Logger.isDebugEnabled() || Logger.isTraceEnabled()) +					Logger.warn("Metadata Schema validation FAILED with exception:", e); +				else +					Logger.warn("Metadata Schema validation FAILED with message: "+ e.getMessage()); +				 +				errString = e.getMessage(); +				 +			} +			 +			throw new SchemaValidationException("Metadata Schema validation FAILED with message: "+ errString); +			 +		} else		 +			Logger.info("Metadata Schema validation check is DEACTIVATED!"); +		 +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java index 67f780b3a..4cdd1db01 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/GetArtifactAction.java @@ -83,7 +83,7 @@ public class GetArtifactAction implements IAction {  				String url = AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/RedirectServlet";  				url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(oaURL, "UTF-8"));  				if (!oaParam.getBusinessService()) -					url = addURLParameter(url, PARAM_TARGET, URLEncoder.encode(oaParam.getTarget(), "UTF-8")); +					url = addURLParameter(url, PARAM_TARGET, URLEncoder.encode(req.getTarget(), "UTF-8"));  				url = addURLParameter(url, PARAM_SAMLARTIFACT, URLEncoder.encode(samlArtifactBase64, "UTF-8"));  				url = httpResp.encodeRedirectURL(url); @@ -95,7 +95,7 @@ public class GetArtifactAction implements IAction {  				String redirectURL = oaURL;		  				if (!oaParam.getBusinessService()) {  					redirectURL = addURLParameter(redirectURL, PARAM_TARGET, -					URLEncoder.encode(oaParam.getTarget(), "UTF-8")); +					URLEncoder.encode(req.getTarget(), "UTF-8"));  				} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java index 65e520cc3..c8a480cac 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1AuthenticationServer.java @@ -64,6 +64,7 @@ import at.gv.egovernment.moa.logging.Logger;  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.MiscUtil;  import at.gv.egovernment.moa.util.StringUtils;  import at.gv.util.xsd.persondata.IdentificationType;  import at.gv.util.xsd.persondata.IdentificationType.Value; @@ -222,8 +223,14 @@ public class SAML1AuthenticationServer extends AuthenticationServer {  				Value value = new Value();  				id.setValue(value  ); -				id.setType(Constants.URN_PREFIX_BASEID); -				value.setValue("");				 +				id.setType(authData.getIdentificationType()); +				//add baseID if it is requested and available +				if ( MiscUtil.isNotEmpty(authData.getIdentificationValue()) &&  +						saml1parameter.isProvideIdentityLink() ) +					value.setValue(authData.getIdentificationValue()); +				else +					value.setValue(""); +				  				familyName.setValue(authData.getFamilyName());  				familyName.setPrimary("undefined");  				name.getGivenName().add(authData.getGivenName()); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java index 8f7f17e2e..9934c339d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/saml1/SAML1Protocol.java @@ -132,7 +132,7 @@ public class SAML1Protocol implements IModulInfo, MOAIDAuthConstants {  		if (!ParamValidatorUtils.isValidOA(oaURL))  			throw new WrongParametersException("StartAuthentication", PARAM_OA,  					"auth.12"); -	 +		  		config.setOAURL(oaURL);  		Logger.info("Dispatch SAML1 Request: OAURL=" + oaURL); @@ -156,8 +156,13 @@ public class SAML1Protocol implements IModulInfo, MOAIDAuthConstants {  					new Object[] { null });  		} -		config.setSourceID(sourceID);		 -		config.setTarget(oaParam.getTarget()); +		config.setSourceID(sourceID); +		if (MiscUtil.isNotEmpty(target)) +			config.setTarget(target); +		 +		else +			config.setTarget(oaParam.getTarget()); +			  		return config;  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java index 8322f0cea..42e9bf25d 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AttributeCollector.java @@ -26,12 +26,8 @@ import java.util.ArrayList;  import java.util.Iterator;  import java.util.List; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException; -import at.gv.egovernment.moa.id.commons.db.dao.config.AttributeProviderPlugin; -import at.gv.egovernment.moa.id.commons.db.dao.config.OAStorkAttribute; -import at.gv.egovernment.moa.id.commons.db.dao.config.StorkAttribute;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider;  import at.gv.egovernment.moa.id.config.auth.OAAuthParameter; @@ -54,7 +50,7 @@ import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  /** - * the AttributeCollector Action tries to get all requested attributes from a set of {@link AttributeProvider} Plugins. + * The AttributeCollector Action tries to get all requested attributes from a set of {@link AttributeProvider} Plugins.   * The class is called whenever the {@link AuthenticationRequest} Action is invoked and checks for missing attributes.   * Furthermore, the class can handle direct posts. That is when the class triggers an attribute query which needs user   * interaction, redirect to another portal, etc. The redirect will hit here and the class can continue to fetch attributes. @@ -84,8 +80,6 @@ public class AttributeCollector implements IAction {  		} -        //   TODO extract attribute response and check if it corresponds to the container -          if (httpReq.getParameter("SAMLResponse") != null) {              Logger.info("Got SAML response from external attribute provider."); @@ -110,7 +104,7 @@ public class AttributeCollector implements IAction {              STORKAuthnResponse authnResponse = null; -            // check if valid authn request is contained +            // check if valid authn response is contained              try {                  authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, httpReq.getRemoteAddr());              } catch (STORKSAMLEngineException ex) { @@ -119,9 +113,25 @@ public class AttributeCollector implements IAction {              STORK2Response.setSTORKAuthnResponseToken(decSamlToken); +            // check if the attributes are provided for the same person from request +            // requires presence of eIdentifier for unambigious correlation +            Logger.debug("Checking if the attribute relates to the correct person.."); +            try { +                String remoteEIdentifier= authnResponse.getPersonalAttributeList().get("eIdentifier").getValue().get(0); +                String localEidentifier= container.getResponse().getStorkAuthnResponse().getPersonalAttributeList().get("eIdentifier").getValue().get(0); +                    if (!remoteEIdentifier.equals(localEidentifier)) { +                        Logger.error("The attribute is not provided for the same person!"); +                        throw new MOAIDException("stork.25", null); +                    } +            } catch (NullPointerException ex) { +                Logger.warn("Could not check the correlation of attributes from external provider. Ignoring the check."); +                //Logger.debug(ex); +                //throw new MOAIDException("stork.04", null); // TODO revise message, raise exception when ehvd checked +            } +              if (authnResponse.getPersonalAttributeList().size() > 0) {                  Logger.info("Response from external attribute provider contains " + authnResponse.getPersonalAttributeList().size() + " attributes."); -                addOrUpdateAll(container.getResponse().getPersonalAttributeList(), authnResponse.getPersonalAttributeList()); +                container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), authnResponse.getPersonalAttributeList()));              }          } @@ -157,7 +167,7 @@ public class AttributeCollector implements IAction {          // - insert the embedded attribute(s) into the container          if (null != newAttributes) -            addOrUpdateAll(container.getResponse().getPersonalAttributeList(), newAttributes); +        	container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), newAttributes));          // see if we need some more attributes          SLOInformationImpl sloInfo = (SLOInformationImpl) processRequest(container, httpReq, httpResp, authData, oaParam); @@ -184,9 +194,21 @@ public class AttributeCollector implements IAction {          IPersonalAttributeList requestAttributeList = container.getRequest().getPersonalAttributeList();          IPersonalAttributeList responseAttributeList = container.getResponse().getPersonalAttributeList();          List<PersonalAttribute> missingAttributes = new ArrayList<PersonalAttribute>(); +        Logger.debug("aquire list of missing attributes");          for (PersonalAttribute current : requestAttributeList) -            if (!responseAttributeList.containsKey(current.getName())) -                missingAttributes.add(current); +            if (!responseAttributeList.containsKey(current.getName())) { +                if(null == current.getStatus() || (null != current.getStatus() && !current.getStatus().equals(AttributeStatusType.WITHHELD.value()))) { +                    // add the ones we need +                    missingAttributes.add(current); +                    Logger.debug("add " + current.getName() + " to the list of missing attributes"); +                } +            } else { +                // remove the ones we do not want to share from the response list +                if(null != current.getStatus() && current.getStatus().equals(AttributeStatusType.WITHHELD.value())) { +                    responseAttributeList.remove(current.getName()); +                    Logger.debug("remove " + current.getName() + " from the list of resulting attributes because the user does not want to disclose the data"); +                } +            }          Logger.info("collecting attributes...");  		Logger.debug("found " + missingAttributes.size() + " missing attributes"); @@ -203,7 +225,8 @@ public class AttributeCollector implements IAction {  				IPersonalAttributeList aquiredAttributes = new PersonalAttributeList();  				currentAttribute.setStatus(AttributeStatusType.NOT_AVAILABLE.value());  				aquiredAttributes.add((PersonalAttribute) currentAttribute.clone()); -				addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes); +				container.getResponse().setPersonalAttributeList( +						addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes));              	// - check if we can find a suitable AttributeProvider Plugin  		        Iterator<AttributeProvider> attibuteProvidersInterator = AttributeProviderFactory.getConfiguredPlugins(oaParam.getStorkAPs());         @@ -247,15 +270,12 @@ public class AttributeCollector implements IAction {  					Logger.error("We have no suitable plugin for obtaining the attribute '" + currentAttribute.getName() + "'");  				} else  					// else, update any existing attributes -					addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes); +					container.getResponse().setPersonalAttributeList(addOrUpdateAll(container.getResponse().getPersonalAttributeList(), aquiredAttributes));              }              Logger.info("collecting attributes done");              // ask for consent if necessary -            if(oaParam.isRequireConsentForStorkAttributes()) -            	new ConsentEvaluator().requestConsent(container, response, oaParam); -            else -            	new ConsentEvaluator().generateSTORKResponse(response, container); +            new ConsentEvaluator().generateSTORKResponse(response, container);              return null; // AssertionId                              // TODO @@ -296,15 +316,21 @@ public class AttributeCollector implements IAction {       *       * @param target the target       * @param source the source +     * @return        * @throws MOAIDException        */ -	private void addOrUpdateAll(IPersonalAttributeList target, IPersonalAttributeList source) throws MOAIDException { +	private PersonalAttributeList addOrUpdateAll(IPersonalAttributeList target, IPersonalAttributeList source) throws MOAIDException { + +		PersonalAttributeList updatedList = new PersonalAttributeList(); +		for (PersonalAttribute el : target) +			updatedList.add(el); +		  		Logger.debug("Updating " + source.size() + " attributes...");  		for (PersonalAttribute current : source) {  			Logger.debug("treating " + current.getName());  			// check if we need to update the current pa -			if (target.containsKey(current.getName())) { +			if (updatedList.containsKey(current.getName())) {  				PersonalAttribute existing = target.get(current.getName());  				if(!(existing.isEmptyValue() && existing.isEmptyComplexValue()))  					if(!(existing.getValue().equals(current.getValue()) || existing.getComplexValue().equals(current.getComplexValue()))) { @@ -312,14 +338,16 @@ public class AttributeCollector implements IAction {  		                throw new MOAIDException("stork.16", new Object[] {existing.getName()});  					} -				target.get(current.getName()).setStatus(current.getStatus()); -				target.get(current.getName()).setValue(current.getValue()); -				target.get(current.getName()).setComplexValue(current.getComplexValue()); +				updatedList.get(current.getName()).setStatus(current.getStatus()); +				updatedList.get(current.getName()).setValue(current.getValue()); +				updatedList.get(current.getName()).setComplexValue(current.getComplexValue());  			} else -				target.add(current); +				updatedList.add(current); -			Logger.debug("...successfully treated " + current.getName()); +			Logger.debug("...successfully treated " + current.getName());			  		} +		 +		return updatedList;  	}      /* (non-Javadoc) diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java index 859f4900b..01f84125f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/AuthenticationRequest.java @@ -163,7 +163,12 @@ public class AuthenticationRequest implements IAction {              Logger.debug("Data container prepared"); -            return (new AttributeCollector()).processRequest(container, httpReq, httpResp, authData, oaParam); +            if(oaParam.isRequireConsentForStorkAttributes()) +                new ConsentEvaluator().requestConsent(container, httpReq, httpResp, authData, oaParam); +            else +                new AttributeCollector().processRequest(container, httpReq, httpResp, authData, oaParam); + +            return null;          }  //        // check if we are getting request for citizen of some other country  //        else if (req instanceof MOASTORKRequest) { @@ -494,11 +499,11 @@ public class AuthenticationRequest implements IAction {                  Logger.debug("Personal attribute found in request: " + personalAttribute.getName() + " isRequired: " + personalAttribute.isRequired());                  moaAttributeProvider.populateAttribute(attributeList, personalAttribute);              	 } catch (Exception e) { -                     Logger.error("Exception, attributes: " + e.getMessage()); +                     Logger.error("Exception, attributes: " + e.getMessage(), e);                   }              }          } catch (Exception e) { -            Logger.error("Exception, attributes: " + e.getMessage()); +            Logger.error("Exception, attributes: " + e.getMessage(), e);          }          Logger.trace("AUTHBLOCK " + authData.getAuthBlock()); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java index 2c5728798..3acd1039f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/ConsentEvaluator.java @@ -23,13 +23,17 @@  package at.gv.egovernment.moa.id.protocols.stork2;  import java.io.StringWriter; + +import at.gv.egovernment.moa.id.auth.exception.AuthenticationException; +  import java.util.ArrayList;  import java.util.HashMap; -import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; +import java.util.Map.Entry; +  import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException;  import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProvider; -import at.gv.egovernment.moa.id.config.auth.IOAAuthParameters; +import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.data.IAuthData;  import at.gv.egovernment.moa.id.data.SLOInformationInterface;  import at.gv.egovernment.moa.id.moduls.IAction; @@ -39,14 +43,13 @@ import at.gv.egovernment.moa.id.util.VelocityProvider;  import at.gv.egovernment.moa.logging.Logger;  import eu.stork.peps.auth.commons.PEPSUtil;  import eu.stork.peps.auth.commons.PersonalAttribute; -import eu.stork.peps.auth.commons.STORKAuthnResponse;  import eu.stork.peps.auth.engine.STORKSAMLEngine;  import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType;  import eu.stork.peps.exceptions.STORKSAMLEngineException; +  import org.apache.velocity.Template;  import org.apache.velocity.VelocityContext;  import org.apache.velocity.app.VelocityEngine; -import org.joda.time.DateTime;  import org.opensaml.common.impl.SecureRandomIdentifierGenerator;  import javax.servlet.http.HttpServletRequest; @@ -72,23 +75,28 @@ public class ConsentEvaluator implements IAction {  		DataContainer container;  		try {  			container = AssertionStorage.getInstance().get(artifactId, DataContainer.class); +			req = container.getRequest();  		} catch (MOADatabaseException e) {  			Logger.error("Error fetching incomplete Stork response from temporary storage. Most likely a timeout occured.", e);  			throw new MOAIDException("stork.17", null);  		}  		// evaluate response -		for(PersonalAttribute current : container.getResponse().getPersonalAttributeList()) { +		for(PersonalAttribute current : container.getRequest().getPersonalAttributeList()) {  			if(null == httpReq.getParameter(current.getName())) { -				current.setStatus(AttributeStatusType.NOT_AVAILABLE.value()); +				current.setStatus(AttributeStatusType.WITHHELD.value());  				current.setValue(new ArrayList<String>());  				current.setComplexValue(new HashMap<String, String>());  			}  		} -        // build and send response -        generateSTORKResponse(httpResp, container); -         +        //TODO: CHECK: req.getOAURL() should return the unique OA identifier +		OAAuthParameter oaParam = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(req.getOAURL()); +		if (oaParam == null) +			throw new AuthenticationException("stork.12", new Object[]{req.getOAURL()}); + +		new AttributeCollector().processRequest(container, httpReq, httpResp, authData, oaParam); +          return null; // AssertionId      } @@ -96,12 +104,19 @@ public class ConsentEvaluator implements IAction {  	 * Fills the given HttpResponse with the required web page.  	 *  	 * @param container the container +	 * @param authData   	 * @param response the response  	 * @param oaParam the oa param  	 * @return the string  	 * @throws MOAIDException the mOAID exception  	 */ -	public String requestConsent(DataContainer container, HttpServletResponse response, IOAAuthParameters oaParam) throws MOAIDException { +	public String requestConsent(DataContainer container, HttpServletRequest httpReq, HttpServletResponse httpResp, IAuthData authData, OAAuthParameter oaParam) throws MOAIDException { +		//check if we need to collect consent +        if(!oaParam.isRequireConsentForStorkAttributes()) { +            (new AttributeCollector()).processRequest(container, httpReq, httpResp, authData, oaParam); +            return ""; +        } +  		// prepare redirect  		String newArtifactId;  		try { @@ -130,19 +145,20 @@ public class ConsentEvaluator implements IAction {  			Template template = velocityEngine.getTemplate("/resources/templates/stork2_consent.html");  			VelocityContext context = new VelocityContext(); -			context.put("action", AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/stork2/CompleteAuthentication?" + ARTIFACT_ID + "=" + newArtifactId); +			context.put("action", AuthConfigurationProvider.getInstance().getPublicURLPrefix() + "/stork2/GetConsent?" + ARTIFACT_ID + "=" + newArtifactId);  			// assemble table  			String table = ""; -			for (PersonalAttribute current : container.getResponse().getPersonalAttributeList()) -				if ("Available".equals(current.getStatus())) -					table += "<tr><td><input type=\"checkbox\" checked=\"yes\" name=\"" + current.getName() + "\"></td><td>" + current.getName() + "</td></tr>\n"; +			for (PersonalAttribute current : container.getRequest().getPersonalAttributeList()) +				table += "<tr><td><input type=\"checkbox\" checked=\"yes\" name=\"" + current.getName() + "\"></td><td>" + current.getName() + (current.isRequired() ? "" : " (optional)") + "</td></tr>\n";  			context.put("tablecontent", table); +			for(Entry<String, String> current : oaParam.getFormCustomizaten().entrySet()) +				context.put(current.getKey().replace("#", ""), current.getValue());  			StringWriter writer = new StringWriter();  			template.merge(context, writer); -			response.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8")); +			httpResp.getOutputStream().write(writer.getBuffer().toString().getBytes("UTF-8"));  		} catch (Exception e) {  			Logger.error("Velocity error: " + e.getMessage()); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java index 136200ed0..2c7e5b539 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MOAAttributeProvider.java @@ -26,21 +26,20 @@ import at.gv.egovernment.moa.id.auth.builder.BPKBuilder;  import at.gv.egovernment.moa.id.auth.exception.BuildException;  import at.gv.egovernment.moa.id.data.AuthenticationRole;  import at.gv.egovernment.moa.id.data.IAuthData; +import at.gv.egovernment.moa.id.protocols.pvp2x.PVPConstants;  import at.gv.egovernment.moa.id.util.PVPtoSTORKMapper;  import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil;  import eu.stork.peps.auth.commons.PersonalAttribute;  import eu.stork.peps.auth.commons.PersonalAttributeList;  import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.AttributeStatusType; +import org.joda.time.Period; +  import java.lang.reflect.InvocationTargetException;  import java.lang.reflect.Method;  import java.text.DateFormat;  import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*;  /**   * @author bsuzic @@ -55,63 +54,116 @@ public class MOAAttributeProvider {      private static final Map<String, String> storkAttributeFunctionMapping;      private final MOASTORKRequest moastorkRequest; +    // mappings for attribute population methods +    // based on mapping of moa authndata and executing functions to extract attributes      static {          Map<String, String> tempSimpleMap = new HashMap<String, String>();          tempSimpleMap.put("givenName", "getGivenName"); -        tempSimpleMap.put("surname", "getFamilyName"); +        tempSimpleMap.put("surname", "getFamilyName");         +        tempSimpleMap.put("MSOrganization", "getPvpAttribute_OU");          storkAttributeSimpleMapping = Collections.unmodifiableMap(tempSimpleMap); +                          Map<String, String> tempFunctionMap = new HashMap<String, String>();          tempFunctionMap.put("eIdentifier", "geteIdentifier");          tempFunctionMap.put("ECApplicationRole","getECApplicationRole");          tempFunctionMap.put("dateOfBirth", "getFormatedDateOfBirth"); +        tempFunctionMap.put("MSOrganization", "getMSOrganization"); +        tempFunctionMap.put("age", "getAge"); +        tempFunctionMap.put("isAgeOver", "getIsAgeOver"); +        tempFunctionMap.put("citizenQAALevel", "getQAALevel");          storkAttributeFunctionMapping = Collections.unmodifiableMap(tempFunctionMap); +              }      public MOAAttributeProvider(IAuthData authData, MOASTORKRequest moastorkRequest) {          this.authData = authData;          this.moastorkRequest = moastorkRequest; -        Logger.debug("identity " + authData.getIdentificationType() + " " + authData.getIdentificationValue()); +              }      public void populateAttribute(PersonalAttributeList attributeList, PersonalAttribute requestedAttribute ) {          String storkAttribute = requestedAttribute.getName(); -        if (storkAttributeSimpleMapping.containsKey(storkAttribute)) { + +        // TODO: check if authData gets populated with stork attributtes during previous steps; it seems it is not +        if (null != authData && null != authData.getStorkAttributes() && authData.getStorkAttributes().containsKey(requestedAttribute.getName())) { +            Logger.debug("Trying to get value for attribute directly from STORK2 response [" + storkAttribute + "]"); +            try { +                PersonalAttribute tmp = authData.getStorkAttributes().get(requestedAttribute.getName()); +                attributeList.add((PersonalAttribute) tmp.clone()); +            } catch(Exception e) { +                Logger.error("Could not retrieve attribute from STORK2 response: " + storkAttribute); +                Logger.debug(e); +            } +        } else if (storkAttributeSimpleMapping.containsKey(storkAttribute)) {              Logger.debug("Trying to get value for attribute using simple mapping [" + storkAttribute + "]");              try {                  Method method = authData.getClass().getDeclaredMethod(storkAttributeSimpleMapping.get(storkAttribute)); -                populateAttributeWithMethod(method, authData, attributeList, storkAttribute, requestedAttribute.isRequired()); +                populateAttributeWithMethod(method, authData, attributeList, storkAttribute, requestedAttribute);              } catch (NoSuchMethodException e) {                  Logger.error("Could not found MOA extraction method while getting attribute: " + storkAttribute); -                e.printStackTrace(); +                Logger.debug(e); +            } catch (NullPointerException e) { +                Logger.error("Error getting MOA extraction method while getting attribute: " + storkAttribute); +                Logger.debug(e);              }          } else if (storkAttributeFunctionMapping.containsKey(storkAttribute)) {              Logger.debug("Trying to get value for attribute using function mapping [" + storkAttribute + "]");              try { -                Method method = this.getClass().getDeclaredMethod(storkAttributeFunctionMapping.get(storkAttribute)); -                populateAttributeWithMethod(method, this, attributeList, storkAttribute, requestedAttribute.isRequired()); +                Method method = this.getClass().getDeclaredMethod(storkAttributeFunctionMapping.get(storkAttribute), PersonalAttribute.class); +                populateAttributeWithMethod(method, this, attributeList, storkAttribute, requestedAttribute);              } catch (NoSuchMethodException e) {                  Logger.error("Could not found MOA extraction method while getting attribute: " + storkAttribute); -                e.printStackTrace();              }          } else {              Logger.debug("MOA method for extraction of attribute " + storkAttribute + " not defined.");          }      } -    private String geteIdentifier() { +    private String getAge(PersonalAttribute personalAttribute) { +        if (authData.getDateOfBirth() != null) { +            Integer age = new Period(authData.getDateOfBirth().getTime(), Calendar.getInstance().getTime().getTime()).getYears(); +            return age >= 0 ? age.toString() : null; +        } +        return null; // WP4 D4.2, Table 12:age, description - considerations +    } + +    private String getIsAgeOver(PersonalAttribute personalAttribute) +    { +        try { +            if ((authData.getDateOfBirth() != null) && (personalAttribute.getValue() != null) && (personalAttribute.getValue().size() > 0)) { +                Integer ageOver = Integer.parseInt(personalAttribute.getValue().get(0)); +                Integer age = new Period(authData.getDateOfBirth().getTime(), Calendar.getInstance().getTime().getTime()).getYears(); +                return age >= ageOver ? ageOver.toString() : ""; +            } +        } catch (Exception ex) { +            Logger.error("Error encountered when determining isAgeOver"); +            Logger.debug(ex); +        } +        return null; +    } + +    public String getQAALevel(PersonalAttribute personalAttribute) { +        if (authData.getQAALevel().startsWith(PVPConstants.STORK_QAA_PREFIX)) +            return authData.getQAALevel().substring(PVPConstants.STORK_QAA_PREFIX.length()); +        else +            return null; +    } + + +    private String geteIdentifier(PersonalAttribute personalAttribute) {          Logger.debug("Using base urn for identification value: " + authData.getIdentificationType() + " and target country: " + moastorkRequest.getStorkAuthnRequest().getSpCountry());          try { -            return new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(),  -            			moastorkRequest.getStorkAuthnRequest().getSpCountry()); +            return new BPKBuilder().buildStorkeIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(), +                    moastorkRequest.getStorkAuthnRequest().getSpCountry());          } catch (BuildException be) {              Logger.error("Stork eid could not be constructed; " + be.getMessage());              return null; // TODO error          }      } -    private List<String> getECApplicationRole() {    	 +    private List<String> getECApplicationRole(PersonalAttribute personalAttribute) {      	List<String> storkRoles = null;      	if (authData.getAuthenticationRoles() != null  @@ -123,29 +175,32 @@ public class MOAAttributeProvider {      			String storkRole = mapper.map(el);      			if (MiscUtil.isNotEmpty(storkRole))      				storkRoles.add(storkRole); -    			      		}    		      	}    	      	return storkRoles;      } - -    private String getFormatedDateOfBirth() { +     +    private String getFormatedDateOfBirth(PersonalAttribute personalAttribute) {  		if (authData.getDateOfBirth() != null) {  			DateFormat fmt = new SimpleDateFormat("yyyyMMdd");      		return  fmt.format(authData.getDateOfBirth());  		}     		else     			return null; -    	      } -    private void populateAttributeWithMethod(Method method, Object object, PersonalAttributeList attributeList, String storkAttribute, Boolean isRequired) { +    private void populateAttributeWithMethod(Method method, Object object, PersonalAttributeList attributeList, String storkAttribute, PersonalAttribute requestedAttribute) {          try { -            Object attributeValue = method.invoke(object, new Class[]{});        // (Object[]) -             +            Object attributeValue; +            if (storkAttributeSimpleMapping.containsValue(method.getName())) { +                attributeValue = method.invoke(object, new Class[]{}); +            }  else { +                attributeValue = method.invoke(object, requestedAttribute); +            } +              PersonalAttribute newAttribute = new PersonalAttribute();              newAttribute.setName(storkAttribute); -            newAttribute.setIsRequired(isRequired); +            newAttribute.setIsRequired(requestedAttribute.isRequired());              if (attributeValue != null) {              	newAttribute.setStatus(AttributeStatusType.AVAILABLE.value()); @@ -178,10 +233,13 @@ public class MOAAttributeProvider {          } catch (InvocationTargetException e) {              Logger.error("Invocation target exception while getting attribute: " + storkAttribute); -            e.printStackTrace(); +            Logger.debug(e);          } catch (IllegalAccessException e) {              Logger.error("Illegal access exception while getting attribute: " + storkAttribute); -            e.printStackTrace(); +            Logger.debug(e); +        } catch (NullPointerException e) { +            Logger.error("Could not find method: " + storkAttribute); +            Logger.debug(e);          }      } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java index 9207cc2dc..a3fac0f6e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateContainer.java @@ -165,7 +165,8 @@ public abstract class MandateContainer {      }      public void setPhysicalRepresentativeBirthDate(String physicalRepresentativeBirthDate) { -        this.physicalRepresentativeBirthDate = physicalRepresentativeBirthDate; +        // making it conform to STORK dateOfBirth specifications, removing dash +        this.physicalRepresentativeBirthDate = physicalRepresentativeBirthDate.replaceAll("-","");      }      public String getAnnotation() { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java index e6fff76ab..c529a8465 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/MandateRetrievalRequest.java @@ -41,7 +41,6 @@ import eu.stork.peps.auth.commons.PersonalAttribute;  import eu.stork.peps.auth.commons.PersonalAttributeList;  import eu.stork.peps.auth.commons.STORKAttrQueryResponse;  import eu.stork.peps.complex.attributes.eu.stork.names.tc.stork._1_0.assertion.*; -import org.apache.commons.codec.binary.Base64;  import org.apache.commons.codec.binary.StringUtils;  import javax.servlet.http.HttpServletRequest; @@ -54,14 +53,14 @@ import javax.xml.datatype.DatatypeFactory;  import javax.xml.datatype.XMLGregorianCalendar;  import javax.xml.namespace.QName;  import java.io.StringWriter; -import java.math.BigInteger;  import java.util.ArrayList;  import java.util.Arrays;  import java.util.HashMap;  import java.util.regex.Pattern;  /** - * + * Entry point for mandate retrieval. Processes MIS data and transforms into STORK mandate attribute. + * Additionally provides eIdentifier attribute (if requested) in order to enable identity correlation   */  public class MandateRetrievalRequest implements IAction { @@ -78,8 +77,13 @@ public class MandateRetrievalRequest implements IAction {          this.QAALevel = translateQAALevel(authData.getQAALevel());          // preparing original content and removing sensitive data from it -        this.originalContent = authData.getMISMandate().getMandate(); // TODO ERROR -        //Logger.debug("Original content " + StringUtils.newStringUtf8(authData.getMISMandate().getMandate())); +        try { +            this.originalContent = authData.getMISMandate().getMandate(); +        } catch (Exception e) { +            Logger.error("Could not extract mandate"); +            Logger.debug(e); +            throw new MOAIDException("stork.26", new Object[]{}); +        }          String originalMandate = StringUtils.newStringUtf8(authData.getMISMandate().getMandate()).replaceAll("<pd:Value>.*?==</pd:Value><pd:Type>urn:publicid:gv.at:baseid</pd:Type>","<pd:Value></pd:Value><pd:Type></pd:Type>");;          Logger.debug("Removing personal identification value and type from original mandate ");          originalContent = StringUtils.getBytesUtf8(originalMandate); @@ -97,13 +101,13 @@ public class MandateRetrievalRequest implements IAction {              this.moaStorkRequest = (MOASTORKRequest) req;          } else {              Logger.error("Internal error - did not receive MOASTORKRequest as expected"); -            throw new MOAIDException("stork.16", new Object[]{}); // TODO +            throw new MOAIDException("stork.27", new Object[]{});          }          if (!(moaStorkRequest.isAttrRequest() || moaStorkRequest.getStorkAttrQueryRequest() == null)) {              Logger.error("Did not receive attribute request as expected"); -            throw new MOAIDException("stork.16", new Object[]{}); // TODO +            throw new MOAIDException("stork.27", new Object[]{});          }          MandateContainer mandateContainer = null; @@ -115,7 +119,7 @@ public class MandateRetrievalRequest implements IAction {                  mandateContainer = new PhyPersonMandateContainer(new String(authData.getMISMandate().getMandate(), "UTF-8"));              } catch (Exception ex2) {                  Logger.error("Could not extract data and create mandate container."); -                throw new MOAIDException("stork.16", new Object[]{}); // TODO +                throw new MOAIDException("stork.27", new Object[]{});              }          } @@ -123,26 +127,21 @@ public class MandateRetrievalRequest implements IAction {          IPersonalAttributeList attributeList = new PersonalAttributeList(); +        // according to new mapping, only mandate attribute is directly relevant          for (PersonalAttribute currentAttribute : sourceAttributeList) { -            Logger.debug("Evaluating currentattribute " + currentAttribute.getName()); -            if (currentAttribute.getName().equals("mandateContent")) { +            Logger.debug("Evaluating attributes, current attribute: " + currentAttribute.getName()); +            if (currentAttribute.getName().equals("mandateContent")) {   // deprecated                  MandateContentType mandateContent = getMandateContent(mandateContainer, currentAttribute);                  attributeList.add(marshallComplexAttribute(currentAttribute, mandateContent)); -            } else if (currentAttribute.getName().equals("representative")) {  //  TODO CHECK IN DETAIL +            } else if (currentAttribute.getName().equals("representative")) {  //  deprecated                  RepresentationPersonType representative = getRepresentative(mandateContainer, currentAttribute);                  attributeList.add(marshallComplexAttribute(currentAttribute, representative)); - -                //attributeList.add(getRepresentative(mandateContainer, currentAttribute));              } else if (currentAttribute.getName().equals("represented")) { -                //attributeList.add(getRepresented(mandateContainer, currentAttribute));                  RepresentationPersonType represented = getRepresented(mandateContainer, currentAttribute);                  attributeList.add(marshallComplexAttribute(currentAttribute, represented)); -              } else if (currentAttribute.getName().equals("mandate")) { -                //attributeList.add(getMandateType(mandateContainer, currentAttribute));                  MandateType mandateType = getMandateType(mandateContainer, currentAttribute);                  attributeList.add(marshallComplexAttribute(currentAttribute, mandateType)); -              } else if (currentAttribute.getName().equals("legalName")) {                  String legalName = getLegalName(mandateContainer, currentAttribute);                  if (legalName.length() > 0) { @@ -180,6 +179,11 @@ public class MandateRetrievalRequest implements IAction {                  }              } +            if (currentAttribute.getName().equals("eIdentifier")) { +                attributeList.add(new PersonalAttribute(currentAttribute.getName(), currentAttribute.isRequired(), Arrays.asList(geteIdentifier(authData.getIdentificationType(), authData.getIdentificationValue(), moaStorkRequest.getStorkAttrQueryRequest().getSpCountry())), AttributeStatusType.AVAILABLE.value())); +                Logger.info("Adding eIdentifier for mandate holder using SP country: " + moaStorkRequest.getStorkAttrQueryRequest().getSpCountry()); +            } +          } @@ -211,7 +215,7 @@ public class MandateRetrievalRequest implements IAction {          // ask for consent if necessary          if (oaParam.isRequireConsentForStorkAttributes()) -            new ConsentEvaluator().requestConsent(container, httpResp, oaParam); +            new ConsentEvaluator().requestConsent(container, httpReq, httpResp, authData, oaParam);          else              new ConsentEvaluator().generateSTORKResponse(httpResp, container); @@ -228,7 +232,7 @@ public class MandateRetrievalRequest implements IAction {          if (qaaLevel.equals(PVPConstants.STORK_QAA_1_4))              return 4;          Logger.error("Wrong QAA Number format"); -        throw new MOAIDException("stork.16", new Object[]{}); +        throw new MOAIDException("stork.28", new Object[]{});      }      private String geteLPIdentifier(MandateContainer mandateContainer, PersonalAttribute currentAttribute) throws MOAIDException { @@ -237,11 +241,20 @@ public class MandateRetrievalRequest implements IAction {              return represented.getELPIdentifier();          } else if (currentAttribute.isRequired()) {              Logger.error("Cannot provide eLPIdentifier for natural person."); -            throw new MOAIDException("stork.19", new Object[]{currentAttribute.getName()});    // TODO +            throw new MOAIDException("stork.29", new Object[]{currentAttribute.getName()});          }          return "";      } +    private String geteIdentifier(String identificationType, String identificationValue, String destinationCountry) throws MOAIDException { +        BPKBuilder bpkBuilder = new BPKBuilder(); +        try { +            return bpkBuilder.buildStorkeIdentifier(identificationType, identificationValue, destinationCountry); +        } catch (BuildException be) { +            Logger.error("Could not build STORK eIdentifier while generating mandate assertion."); +            throw new MOAIDException("stork.29", new Object[]{}); +        } +    }      private PersonalAttribute marshallComplexAttribute(PersonalAttribute currentAttribute, Object obj) {    // TODO refactor          StringWriter stringWriter = new StringWriter(); @@ -456,7 +469,6 @@ public class MandateRetrievalRequest implements IAction {      private String getRepresentedStorkeIdentifier(MandateContainer mandateContainer) throws MOAIDException { -        //String identificationType, String identificationValue          if (!(mandateContainer instanceof PhyPersonMandateContainer)) {              Logger.error("Physical person mandate container missing");              throw new MOAIDException("stork.20", new Object[]{}); // TODO @@ -479,13 +491,7 @@ public class MandateRetrievalRequest implements IAction {              throw new MOAIDException("stork.20", new Object[]{}); // TODO          } -        BPKBuilder bpkBuilder = new BPKBuilder(); -        try { -            return bpkBuilder.buildStorkeIdentifier(phyPersonMandateContainer.getPhyPersMandatorIdentificationType(), phyPersonMandateContainer.getPhyPersMandatorIdentificationValue(), this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry()); -        } catch (BuildException be) { -            Logger.error("Could not build STORK eIdentifier while generating mandate assertion."); -            throw new MOAIDException("stork.20", new Object[]{}); // TODO -        } +        return geteIdentifier(phyPersonMandateContainer.getPhyPersMandatorIdentificationType(), phyPersonMandateContainer.getPhyPersMandatorIdentificationValue(), this.moaStorkRequest.getStorkAttrQueryRequest().getSpCountry());      }      private String getRepresentingStorkeIdentifier(MandateContainer mandateContainer) throws MOAIDException { @@ -522,6 +528,7 @@ public class MandateRetrievalRequest implements IAction {              Logger.error("Could not build STORK eIdentifier while generating mandate assertion.");              throw new MOAIDException("stork.20", new Object[]{}); // TODO          } +      }      private RepresentationPersonType getRepresentative(MandateContainer mandateContainer, PersonalAttribute sourceAttribute) throws MOAIDException { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java index ba89663ab..c715b65eb 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/PhyPersonMandateContainer.java @@ -109,7 +109,8 @@ public class PhyPersonMandateContainer extends MandateContainer {      }      public void setPhyPersMandatorBirthDate(String phyPersMandatorBirthDate) { -        this.phyPersMandatorBirthDate = phyPersMandatorBirthDate; +        // making it conform to STORK dateOfBirth specifications, removing dash +        this.phyPersMandatorBirthDate = phyPersMandatorBirthDate.replaceAll("-","");      }      public String getPhyPersMandatorIdentificationValue() { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java index d923eccde..123d32af4 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/STORKPVPUtilits.java @@ -32,7 +32,7 @@ import java.util.List;  public class STORKPVPUtilits {  	public static final List<String> attributesRequirePVPAuthentication =  -			Arrays.asList("ECApplicationRole"); +			Arrays.asList("ECApplicationRole", "MSOrganization"); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java index f4d963645..f671f0807 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/MandateAttributeRequestProvider.java @@ -73,6 +73,7 @@ public class MandateAttributeRequestProvider extends AttributeProvider {          return "MandateAttributeRequestProvider";      } +    // TODO check if used      @Override  	protected IPersonalAttributeList acquire(PersonalAttribute attribute, MOASTORKRequest moastorkRequest, IAuthData authData) throws UnsupportedAttributeException, ExternalAttributeRequestRequiredException, MOAIDException {          Logger.info("Acquiring attribute: " + attribute.getName() + ", by: " + getAttrProviderName()); @@ -85,10 +86,14 @@ public class MandateAttributeRequestProvider extends AttributeProvider {              Logger.info("Attribute " + attribute.getName() + " not supported by the provider: " + getAttrProviderName());              throw new UnsupportedAttributeException();          } -        PersonalAttributeList result = new PersonalAttributeList(); -        //return result; - +        // check if there is eIdentifier included and add if necessary +//        if (!requestedAttributes.containsKey("eIdentifier")) { +//            PersonalAttribute eIdentifier = new PersonalAttribute(); + //           eIdentifier.setName("eIdentifier"); +//            eIdentifier.setIsRequired(true); +//            requestedAttributes.add(eIdentifier); +//        }          Logger.info("Thrown external request by: " + getAttrProviderName());          throw new ExternalAttributeRequestRequiredException(this); @@ -111,10 +116,12 @@ public class MandateAttributeRequestProvider extends AttributeProvider {          // continue with other attribute providers if there are no attributes current provider is able to handle          if (requestedAttributes.size() == 0) { -            Logger.info("Attribute(s) " + attributes.toString()  + " not supported by the provider: " + getAttrProviderName()); +            Logger.info("Attribute(s) " + attributes.toString() + " not supported by the provider: " + getAttrProviderName());              throw new UnsupportedAttributeException();          } + +          Logger.info("Thrown external request by: " + getAttrProviderName());          throw new ExternalAttributeRequestRequiredException(this);      } @@ -144,7 +151,14 @@ public class MandateAttributeRequestProvider extends AttributeProvider {          } - +        // TODO ensure that other providers request eidentifier +        // check if there is eIdentifier included and add if necessary +        if (!requestedAttributes.containsKey("eIdentifier")) { +            PersonalAttribute eIdentifier = new PersonalAttribute(); +            eIdentifier.setName("eIdentifier"); +            eIdentifier.setIsRequired(true); +            requestedAttributes.add(eIdentifier); +        }          //generate AttrQueryRequest          STORKAttrQueryRequest attributeRequest = new STORKAttrQueryRequest(); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java index 96aa55bcf..7f06c604b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/PVPAuthenticationProvider.java @@ -80,7 +80,7 @@ public class PVPAuthenticationProvider extends AttributeProvider {  		this.moastorkRequest = moastorkRequest;          // break if we cannot handle the requested attribute -        if (!attributes.contains(attribute.getName())) { +        if (!getSupportedAttributeNames().contains(attribute.getName())) {              Logger.info("Attribute " + attribute.getName() + " not supported by the provider: " + getAttrProviderName());              throw new UnsupportedAttributeException(); @@ -193,33 +193,34 @@ public class PVPAuthenticationProvider extends AttributeProvider {  	public IPersonalAttributeList parse(HttpServletRequest httpReq)  			throws UnsupportedAttributeException, MOAIDException { -		Logger.info(this.getClass().getSimpleName() + " tries to extract SAMLResponse out of HTTP Request"); +		throw new UnsupportedAttributeException(); -		//extract STORK Response from HTTP Request -		//Decodes SAML Response -		byte[] decSamlToken; -		try { -			decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse")); -		} catch(NullPointerException e) { -			throw new UnsupportedAttributeException(); -		} - -		//Get SAMLEngine instance -		STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); - -		STORKAuthnResponse authnResponse = null; -		try { -			//validate SAML Token -			Logger.debug("Starting validation of SAML response"); -			authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) httpReq.getRemoteHost()); -			Logger.info("SAML response successfully verified!"); -			 -		}catch(STORKSAMLEngineException e){ -			Logger.error("Failed to verify STORK SAML Response", e); -			throw new MOAIDException("stork.05", null); -		} -		 -		return authnResponse.getPersonalAttributeList(); +//		Logger.info(this.getClass().getSimpleName() + " tries to extract SAMLResponse out of HTTP Request");		 +//		//extract STORK Response from HTTP Request +//		//Decodes SAML Response +//		byte[] decSamlToken; +//		try { +//			decSamlToken = PEPSUtil.decodeSAMLToken(httpReq.getParameter("SAMLResponse")); +//		} catch(NullPointerException e) { +//			throw new UnsupportedAttributeException(); +//		} +// +//		//Get SAMLEngine instance +//		STORKSAMLEngine engine = STORKSAMLEngine.getInstance("VIDP"); +// +//		STORKAuthnResponse authnResponse = null; +//		try { +//			//validate SAML Token +//			Logger.debug("Starting validation of SAML response"); +//			authnResponse = engine.validateSTORKAuthnResponse(decSamlToken, (String) httpReq.getRemoteHost()); +//			Logger.info("SAML response successfully verified!"); +//			 +//		}catch(STORKSAMLEngineException e){ +//			Logger.error("Failed to verify STORK SAML Response", e); +//			throw new MOAIDException("stork.05", null); +//		} +//		 +//		return authnResponse.getPersonalAttributeList();  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java index bb3d8b1fd..2c77db94e 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/stork2/attributeproviders/SignedDocAttributeRequestProvider.java @@ -189,6 +189,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {  				IOUtils.copy(istr, writer, "UTF-8");  				signResponseString = writer.toString();  				Logger.info("SignResponse with error (unmodified):"+signResponseString); +				istr.close();  			}  			else  			{ @@ -198,6 +199,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {  				ByteArrayOutputStream baos = new ByteArrayOutputStream();  				IOUtils.copy(dataSource.getInputStream(), baos);  				byte[] data = baos.toByteArray(); +				baos.close();  				//update doc in DTL  				String docId, dssId = "";	 @@ -255,7 +257,8 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {  							StringWriter writer = new StringWriter();  							IOUtils.copy(istr, writer, "UTF-8");  							signResponseString = writer.toString(); -							Logger.info("SignResponse overwritten:"+signResponseString);	 +							Logger.info("SignResponse overwritten:"+signResponseString); +							istr.close();  						}  						else  						{ @@ -304,6 +307,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {  							IOUtils.copy(istr, writer, "UTF-8");  							signResponseString = writer.toString();  							Logger.info("SignResponse overwritten:"+signResponseString); +							istr.close();  						}  				}  				else @@ -424,6 +428,7 @@ public class SignedDocAttributeRequestProvider extends AttributeProvider {  						signRequestString = writer.toString();  						Logger.info("Signrequest overwritten");	  						Logger.debug("Signrequest overwritten:"+signRequestString);	 +						istr.close();  					} catch (Exception e) {  						e.printStackTrace();  						throw new Exception("Could not marshall sign request", e); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java index a9f5ed60a..4288f48ad 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/storage/AuthenticationSessionStoreage.java @@ -48,6 +48,7 @@ import at.gv.egovernment.moa.id.config.auth.OAAuthParameter;  import at.gv.egovernment.moa.id.data.EncryptedData;  import at.gv.egovernment.moa.id.data.SLOInformationInterface;  import at.gv.egovernment.moa.id.moduls.IRequest; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStoreDAOImpl;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionAttributeExtractorExeption;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.AssertionAttributeExtractor;  import at.gv.egovernment.moa.id.util.Random; @@ -912,19 +913,28 @@ public class AuthenticationSessionStoreage {  	} -	private static void cleanDelete(AuthenticatedSessionStore result) {		 +	private static void cleanDelete(AuthenticatedSessionStore result) { + +		try { +			AuthenticationSession session = getSession(result.getSessionid()); +			if (session.getProcessInstanceId() != null) { +				ProcessInstanceStoreDAOImpl.getInstance().remove(session.getProcessInstanceId()); +			} + +		} catch (MOADatabaseException e) { +			Logger.warn("Removing process associated with moa session " + result.getSessionid() + " FAILED.", e); +		} +  		try {  			result.setSession("blank".getBytes());  			MOASessionDBUtils.saveOrUpdate(result); -			 +  		} catch (MOADatabaseException e) {  			Logger.warn("Blank authenticated session with sessionID=" + result.getSessionid() + " FAILED.", e); -			 +  		} finally {  			if (!MOASessionDBUtils.delete(result)) -				Logger.error("Authenticated session with sessionID=" + result.getSessionid()  -							+ " not removed! (Error during Database communication)"); -			 +				Logger.error("Authenticated session with sessionID=" + result.getSessionid() + " not removed! (Error during Database communication)");  		}  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java index 090bea486..520b81b17 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/IdentityLinkReSigner.java @@ -71,13 +71,9 @@ public class IdentityLinkReSigner {  		return instance;  	} -	public Element resignIdentityLink(Element idl) throws MOAIDException { +	public Element resignIdentityLink(Element idl, String keyGroupId) throws MOAIDException {  		try { -			AuthConfigurationProvider config = AuthConfigurationProvider.getInstance(); -						 -			if (config.isIdentityLinkResigning()) { -				  				if (idl == null) {  					Logger.warn("IdentityLink is empty");  					return null; @@ -91,7 +87,6 @@ public class IdentityLinkReSigner {  				SPSSFactory spssFac = SPSSFactory.getInstance(); -				String keyGroupId = config.getIdentityLinkResigningKey();  				if (MiscUtil.isEmpty(keyGroupId)) {  					Logger.warn("No IdentityLink reSigning-Key definded");  					throw new MOAIDException("config.19", new Object[]{}); @@ -166,9 +161,6 @@ public class IdentityLinkReSigner {  			    	Logger.warn("Allgemeiner Fehler beim Aufruf von MOA-SS: Unbekannter ResponseType von MOA-SS");  			    	throw new MOAIDException("builder.05", new Object[]{});  			    } -			    				 -			} else  -				return idl;  		} catch (ConfigurationException e) {  			Logger.warn("Configuration can not be loaded", e); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java index 0ea03e29d..5ef9494f4 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/PVPtoSTORKMapper.java @@ -36,6 +36,7 @@ import at.gv.egovernment.moa.util.MiscUtil;  public class PVPtoSTORKMapper {  	private static final String PVP_SECCLASS_PREFIX = "http://www.ref.gv.at/ns/names/agiz/pvp/"; +	private static final String STORK_QAA_PREFIX = "http://www.stork.gov.eu/1.0/";  	private static final String MAPPING_RESOURCE =   			"resources/properties/pvp-stork_mapping.properties"; @@ -67,12 +68,31 @@ public class PVPtoSTORKMapper {  	} +	/**Map a STORK QAA level to PVP SecClass +	 *  +	 * @param STORK-QAA level +	 * @return PVP SecClass pvpQAALevel +	 */	 +	public String mapToSecClass(String storkQAALevel) { +		if (mapping != null) { +			String input = storkQAALevel.substring(STORK_QAA_PREFIX.length());			 +			String mappedQAA = mapping.getProperty(input); +			if (MiscUtil.isNotEmpty(mappedQAA)) { +				Logger.info("Map STORK-QAA " + storkQAALevel + " to PVP SecClass " + mappedQAA); +				return mappedQAA; +				 +			}						 +		}		 +		Logger.warn("No mapping for STORK-QAA " + storkQAALevel +" !"); +		return null; +	} +	  	/**Map a PVP SecClass to STORK QAA level  	 *   	 * @param PVP SecClass pvpQAALevel  	 * @return STORK-QAA level  	 */	 -	public String mapQAALevel(String pvpQAALevel) { +	public String mapToQAALevel(String pvpQAALevel) {  		if (mapping != null) {  			String input = pvpQAALevel.substring(PVP_SECCLASS_PREFIX.length());			  			String mappedQAA = mapping.getProperty(input); @@ -93,13 +113,16 @@ public class PVPtoSTORKMapper {  	 */  	public String map(AuthenticationRole el) {  		if (mapping != null) { -			String ecRole = mapping.getProperty(el.getRawRoleString()); +			//String ecRole = mapping.getProperty(el.getRawRoleString()); +			String ecRole = mapping.getProperty(el.getRoleName());  			if (MiscUtil.isNotEmpty(ecRole)) { -				Logger.info("Map PVPRole " + el.getRawRoleString() + " to ECRole " + ecRole); +				//Logger.info("Map PVPRole " + el.getRawRoleString() + " to ECRole " + ecRole); +				Logger.info("Map PVPRole " + el.getRoleName() + " to ECRole " + ecRole);  				return ecRole;  			}			  		} -		Logger.warn("NO mapping for PVPRole "+ el.getRawRoleString() + " !"); +		//Logger.warn("NO mapping for PVPRole "+ el.getRawRoleString() + " !"); +		Logger.warn("NO mapping for PVPRole "+ el.getRoleName() + " !");  		return null;  	}  } diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java index 56e59a4aa..3dbc0ab7b 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/ServletUtils.java @@ -113,14 +113,13 @@ public class ServletUtils {     * depending on the requests starting text.
     * 
     * @param resp The httpServletResponse
 -   * @param session The current AuthenticationSession
     * @param createXMLSignatureRequestOrRedirect The request
     * @param servletGoal The servlet to which the redirect should happen
     * @param servletName The servlet name for debug purposes
     * @throws MOAIDException
     * @throws IOException
     */
 -  public static void writeCreateXMLSignatureRequest(HttpServletResponse resp, AuthenticationSession session, String createXMLSignatureRequestOrRedirect, String servletGoal, String servletName, String dataURL) 
 +  public static void writeCreateXMLSignatureRequest(HttpServletResponse resp, String createXMLSignatureRequestOrRedirect, String servletGoal, String servletName, String dataURL) 
    throws MOAIDException,
           IOException
    { 
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java index 20cabaf4d..1edb8d1f3 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISMandate.java @@ -66,6 +66,9 @@ public class MISMandate implements Serializable{  	final static public String OID_ORGANWALTER = "1.2.40.0.10.3.4";
  	final static private String TEXT_ORGANWALTER = "Organwalter";
 +	final static public String OID_ELGA_OMBUTSSTELLE = "1.2.40.0.34.3.1.3";
 +	final static public String OID_ELGA_OMBUTSSTELLE_TEST = "1.2.40.0.34.3.1.2.99.9";
 +	final static private String TEXT_ELGA_OMBUTSSTELLE = "ELGA-Ombudsstelle";
  	private String oid = null;
  	private byte[] mandate = null;
 @@ -102,7 +105,10 @@ public class MISMandate implements Serializable{  				return TEXT_ZIVILTECHNIKER;
  			if (this.oid.equalsIgnoreCase(OID_ORGANWALTER))
  				return TEXT_ORGANWALTER;
 -		
 +			if (this.oid.equalsIgnoreCase(OID_ELGA_OMBUTSSTELLE) 
 +					|| this.oid.equalsIgnoreCase(OID_ELGA_OMBUTSSTELLE_TEST))
 +				return TEXT_ELGA_OMBUTSSTELLE;
 +			
  			return "Keine textuelle Beschreibung für OID " + oid;
  		} else {
 diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java index 15b2a89b5..24c96a78f 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/util/client/mis/simple/MISSimpleClient.java @@ -56,6 +56,7 @@ import javax.xml.parsers.ParserConfigurationException;  import javax.xml.transform.TransformerException;
  import org.apache.commons.codec.binary.Base64;
 +import org.apache.commons.httpclient.HostConfiguration;
  import org.apache.commons.httpclient.HttpClient;
  import org.apache.commons.httpclient.methods.PostMethod;
  import org.apache.commons.httpclient.methods.StringRequestEntity;
 @@ -70,6 +71,7 @@ import org.xml.sax.SAXException;  import at.gv.egovernment.moa.id.auth.exception.MISSimpleClientException;
  import at.gv.egovernment.moa.id.auth.validator.parep.client.szrgw.SZRGWSecureSocketFactory;
 +import at.gv.egovernment.moa.id.commons.utils.HttpClientWithProxySupport;
  import at.gv.egovernment.moa.logging.Logger;
  import at.gv.egovernment.moa.util.DOMUtils;
  import at.gv.egovernment.moa.util.StringUtils;
 @@ -300,7 +302,7 @@ public class MISSimpleClient {  			throw new NullPointerException("Argument request must not be null.");
  		}
  		try {
 -			HttpClient httpclient = new HttpClient();
 +			HttpClient httpclient = HttpClientWithProxySupport.getHttpClient();
  			PostMethod post = new PostMethod(webServiceURL);
  			StringRequestEntity re = new StringRequestEntity(DOMUtils.serializeNode(packIntoSOAP(request)),"text/xml", "UTF-8");
  			post.setRequestEntity(re);
 diff --git a/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java b/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java new file mode 100644 index 000000000..968d3491d --- /dev/null +++ b/id/server/idserverlib/src/main/java/iaik/IAIKRuntimeException.java @@ -0,0 +1,18 @@ +package iaik;
 +
 +/**
 + * Adapter class providing {@code iaik.RuntimeException} for libraries that have not been updated in order to consider
 + * the fact that the class {@code IAIKRuntimeException} has been moved.
 + * 
 + * @author tknall
 + * 
 + */
 +public class IAIKRuntimeException extends iaik.server.modules.IAIKRuntimeException {
 +
 +	private static final long serialVersionUID = 1L;
 +
 +	public IAIKRuntimeException(String reason, Throwable wrapped, String uniqueIdentifier) {
 +		super(reason, wrapped, uniqueIdentifier);
 +	}
 +
 +}
 diff --git a/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule b/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule new file mode 100644 index 000000000..865096055 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/META-INF/services/at.gv.egovernment.moa.id.auth.modules.AuthModule @@ -0,0 +1,2 @@ +# The default moaid process +at.gv.egovernment.moa.id.auth.modules.internal.DefaultAuthModuleImpl diff --git a/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml new file mode 100644 index 000000000..3860ddef4 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/auth/modules/internal/DefaultAuthentication.process.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8"?>
 +<pd:ProcessDefinition id="DefaultAuthentication" xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1">
 +
 +<!--
 +	- National authentication with Austrian Citizen Card and mobile signature with our without mandate.
 +	- Legacy authentication for foreign citizens using MOCCA supported signature cards.
 +-->
 +	<pd:Task id="createIdentityLinkForm"    class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.CreateIdentityLinkFormTask" />
 +	<pd:Task id="verifyIdentityLink"        class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyIdentityLinkTask"        async="true" />
 +	<pd:Task id="verifyAuthBlock"           class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyAuthenticationBlockTask" async="true" />
 +	<pd:Task id="verifyCertificate"         class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.VerifyCertificateTask"         async="true" />
 +	<pd:Task id="getMISSessionID"           class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetMISSessionIDTask"           async="true" />
 +	<pd:Task id="certificateReadRequest"    class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.CertificateReadRequestTask" />
 +	<pd:Task id="prepareAuthBlockSignature" class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.PrepareAuthBlockSignatureTask" />
 +	<pd:Task id="getForeignID"              class="at.gv.egovernment.moa.id.auth.modules.internal.tasks.GetForeignIDTask"              async="true" />
 +
 +	<!-- Process is triggered either by GenerateIFrameTemplateServlet (upon bku selection) or by AuthenticationManager (upon legacy authentication start using legacy parameters. -->
 +	<pd:StartEvent id="start" />
 +	
 +	<pd:Transition from="start"                     to="createIdentityLinkForm" />
 +	
 +	<pd:Transition from="createIdentityLinkForm"    to="verifyIdentityLink" />
 +	
 +	<pd:Transition from="verifyIdentityLink"        to="certificateReadRequest" conditionExpression="!ctx['identityLinkAvailable'] || ctx['useMandate']" />
 +	<pd:Transition from="verifyIdentityLink"        to="prepareAuthBlockSignature" />
 +	
 +	<pd:Transition from="prepareAuthBlockSignature" to="verifyAuthBlock" />
 +	<!-- Note: verifyAuthBlock still creates a MIS session and redirects the user to the MIS gui. This should be separated from the auth block verification. -->
 +	
 +	<pd:Transition from="certificateReadRequest"    to="verifyCertificate" />
 +	<!-- Note: verifyCertificate still creates the auth block to be signed which should be separated from certificat verification. -->
 +	
 +	<pd:Transition from="verifyCertificate"         to="verifyAuthBlock" conditionExpression="ctx['useMandate']" />
 +	<pd:Transition from="verifyCertificate"         to="getForeignID" />
 +	
 +	<pd:Transition from="verifyAuthBlock"           to="getMISSessionID" conditionExpression="ctx['useMandate']" />
 +	<pd:Transition from="verifyAuthBlock"           to="end" />
 +	
 +	<pd:Transition from="getMISSessionID"           to="end" />
 +	<pd:Transition from="getForeignID"              to="end" />
 +	
 +	<pd:EndEvent id="end" />
 +
 +</pd:ProcessDefinition>
 diff --git a/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd new file mode 100644 index 000000000..d6ab7ae46 --- /dev/null +++ b/id/server/idserverlib/src/main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" +	targetNamespace="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	elementFormDefault="qualified" version="1.0"> + +	<xsd:element name="ProcessDefinition"> +		<xsd:complexType> +			<xsd:sequence> +				<xsd:choice minOccurs="0" maxOccurs="unbounded"> +					<xsd:element name="StartEvent" type="tns:StartEventType" /> +					<xsd:element name="Task" type="tns:TaskType" /> +					<xsd:element name="Transition" type="tns:TransitionType" /> +					<xsd:element name="EndEvent" type="tns:EndEventType" /> +				</xsd:choice> +			</xsd:sequence> +			<xsd:attribute name="id" type="xsd:ID" use="required" /> +		</xsd:complexType> +	</xsd:element> + +	<xsd:complexType name="ProcessNodeType" abstract="true"> +		<xsd:attribute name="id" type="xsd:ID" use="required" /> +	</xsd:complexType> + +	<xsd:complexType name="StartEventType"> +		<xsd:complexContent> +			<xsd:extension base="tns:ProcessNodeType" /> +		</xsd:complexContent> +	</xsd:complexType> + +	<xsd:complexType name="TransitionType"> +		<xsd:attribute name="from" type="xsd:IDREF" use="required" /> +		<xsd:attribute name="to" type="xsd:IDREF" use="required" /> +		<xsd:attribute name="id" type="xsd:ID" /> +		<xsd:attribute name="conditionExpression" type="xsd:string" /> +	</xsd:complexType> + +	<xsd:complexType name="EndEventType"> +		<xsd:complexContent> +			<xsd:extension base="tns:ProcessNodeType" /> +		</xsd:complexContent> +	</xsd:complexType> + +	<xsd:complexType name="TaskType"> +		<xsd:complexContent> +			<xsd:extension base="tns:ProcessNodeType"> +				<xsd:attribute name="async" type="xsd:boolean" default="false"/> +				<xsd:attribute name="class" type="xsd:string" /> +			</xsd:extension> +		</xsd:complexContent> +	</xsd:complexType> + +</xsd:schema> 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 8fda4566c..0d91fc2c0 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 @@ -229,6 +229,14 @@ stork.18=STORK-SAML Engine konnte nicht initialisiert werden.  stork.19=Das erforderliche Attribut ist f\u00FCr naturliche Personen nicht vorhanden\: {0}
  stork.20=Fehler bei der Datenkonversion - eingegebens Datum fehlerhaft
  stork.21=Der angeforderte QAA-level {0} ist h\u00F6her als der QAA-level der Authentifizierung {1}
 +stork.22=Der STORK Authentifizierung erfordert die Auswahl des Herkunftslandes der Betroffenen.
 +stork.23=Die STORK Authentifizierung f\u00FCr "{0}" wird nicht unterst\u00FCtzt.
 +stork.24=Die STORK Authentifizierungsantwort enth\uFFFDlt leere Angaben zum Geschlecht.
 +stork.25=Die Attribute referenzieren verschiedene Personen.
 +stork.26=Fehler bei der Extrahierung von Vollmachtendaten.
 +stork.27=Fehler bei der Verarbeitung von STORKRequest.
 +stork.28=Fehler bei der Umwandelung von QAA Daten.
 +stork.29=Fehler bei der Generierung von STORK-Attribut (eIdentifier/eLPIdentifier)
  pvp2.00={0} ist kein gueltiger consumer service index
  pvp2.01=Fehler beim kodieren der PVP2 Antwort
 @@ -266,4 +274,7 @@ oauth20.09=Zertifikat fuer JSON Web-Token ist falsch konfiguriert. Fehler bei "{  slo.00=Sie konnten erfolgreich von allen Online-Applikation abgemeldet werden.
  slo.01=Sie konnten NICHT erfolgreich von allen Online-Applikationen abgemeldet werden\!<BR>Bitte schlie\u00DFen Sie aus sicherheitsgr\u00FCnden Ihren Browser.
 -slo.02=Es wurde keine aktive SSO Session gefunden oder Sie sind bei keiner Online-Applikation angemeldet.
\ No newline at end of file +slo.02=Es wurde keine aktive SSO Session gefunden oder Sie sind bei keiner Online-Applikation angemeldet.
 +
 +process.01=Fehler beim Ausf\u00FChren des Prozesses.
 +process.02=Fehler beim Erstellen eines geeigneten Prozesses f\u00FCr die SessionID {0}.
 diff --git a/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties b/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties index 63745f826..ca12fada4 100644 --- a/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties +++ b/id/server/idserverlib/src/main/resources/resources/properties/pvp-stork_mapping.properties @@ -1,9 +1,31 @@  ##PVP role mapping  viewer=CIRCABC/viewer  CIRCABC-viewer=CIRCABC/viewer +CIRCABC-DIRECTOR=CIRCABC/DIRECTOR +CIRCABC-SECRETARY=CIRCABC/SECRETARY +CIRCABC-MEMBER=CIRCABC/MEMBER -##PVP SecClass mapping +ecas-demo-EUROPEAN_COMMISSION=ecas-demo/EUROPEAN_COMMISSION +ecas-demo-EXTERNAL_INTRAMUROS=ecas-demo/EXTERNAL_INTRAMUROS +ecas-demo-INTERNET=ecas-demo/INTERNET +ecas-demo-LIVENEWS=ecas-demo/LIVENEWS + +DIGIT-EUROPEAN_COMMISSION=DIGIT/EUROPEAN_COMMISSION +DIGIT-EXTERNAL_INTRAMUROS=DIGIT/EXTERNAL_INTRAMUROS +DIGIT-INTERNET=DIGIT/INTERNET +DIGIT-LIVENEWS=DIGIT/LIVENEWS + + + + +##PVP SecClass to STORK-QAA mapping  secclass/0=http://www.stork.gov.eu/1.0/citizenQAALevel/1  secclass/0-1=http://www.stork.gov.eu/1.0/citizenQAALevel/2 -secclass/0-2=http://www.stork.gov.eu/1.0/citizenQAALevel/3 -secclass/0-3=http://www.stork.gov.eu/1.0/citizenQAALevel/4
\ No newline at end of file +secclass/0-2=http://www.stork.gov.eu/1.0/citizenQAALevel/4 +secclass/0-3=http://www.stork.gov.eu/1.0/citizenQAALevel/4 + +##STORK-QAA to PVP SecClass mapping +citizenQAALevel/1=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0 +citizenQAALevel/2=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-1 +citizenQAALevel/3=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-2 +citizenQAALevel/4=http://www.ref.gv.at/ns/names/agiz/pvp/secclass/0-2
\ No newline at end of file diff --git a/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html b/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html index 7e2ddc491..e293d8456 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/loginFormFull.html @@ -837,7 +837,7 @@  				src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html b/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html index e75bef70c..033a574b9 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/sendAssertionFormFull.html @@ -545,7 +545,7 @@ button:hover,button:focus,button:active,.sendButton:hover,.sendButton:focus,.sen  				src="#CONTEXTPATH#/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html index b241e85cf..8976b2bd6 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/slo_template.html @@ -436,7 +436,7 @@  				src="$contextpath/img/valid-html5-blue.png" alt="HTML5 ist valide!" />  			</a> <a href="http://jigsaw.w3.org/css-validator/"> <img  				style="border: 0; width: 88px; height: 31px" -				src="http://jigsaw.w3.org/css-validator/images/vcss-blue" +				src="https://jigsaw.w3.org/css-validator/images/vcss-blue"  				alt="CSS ist valide!" />  			</a>  		</div> diff --git a/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html b/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html index e21a61665..0ab41f146 100644 --- a/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html +++ b/id/server/idserverlib/src/main/resources/resources/templates/stork2_consent.html @@ -80,6 +80,7 @@  				  overflow:auto;	            min-width: 190px;            height: 260px; +          padding: 20px;  			  }          h2#tabheader{ @@ -134,6 +135,7 @@          #bkulogin {          min-height: 150px; +        padding: 20px;          }         } @@ -146,6 +148,7 @@          #bkulogin {            height: 180px; +          padding: 20px;          }          } @@ -175,7 +178,7 @@  					color : #000;  			  	text-align: center;            font-size: 100%; -			  	background-color: #MAIN_BACKGOUNDCOLOR#; +			  	background-color: ${MAIN_BACKGOUNDCOLOR};  				}  			  #page { @@ -230,6 +233,7 @@         	#bkulogin {	            min-width: 190px;            height: 155px;	 +          padding: 20px;  			 }  			 .setAssertionButton_full { @@ -249,7 +253,7 @@  			* {  				margin: 0;  				padding: 0; -        font-family: #FONTTYPE#; +        font-family: ${FONTTYPE};  			}  			#selectArea { @@ -333,13 +337,13 @@  			}  			.hell { -				background-color : #MAIN_BACKGOUNDCOLOR#; -        color: #MAIN_COLOR#;	 +				background-color : ${MAIN_BACKGOUNDCOLOR}; +        color: ${MAIN_COLOR};	  			}  			.dunkel { -				background-color: #HEADER_BACKGROUNDCOLOR#; -        color: #HEADER_COLOR#; +				background-color: ${HEADER_BACKGROUNDCOLOR}; +        color: ${HEADER_COLOR};  			}  			.main_header { @@ -404,7 +408,7 @@      }  	</script> -<title>#HEADER_TEXT#</title> +<title>Informationsfreigabe</title>  </head>  <body onload="onChangeChecks();" onresize="onChangeChecks();">  	<div id="page"> @@ -417,7 +421,7 @@  							<h2 id="tabheader" class="dunkel" role="heading">STORK Informationsfreigabe</h2>  						</div>  						<div id="bkulogin" class="hell" role="form"> -							Alle angehakten Daten werden an das fragende Drittland übermittelt. +							Wählen Sie jene Daten, die, wenn verfügbar, an ein Drittland weitergegeben werden sollen:</br>  	  						<table>  	  							${tablecontent}  							</table> diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/ExpressionContextAdapter.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/ExpressionContextAdapter.java new file mode 100644 index 000000000..c26236619 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/ExpressionContextAdapter.java @@ -0,0 +1,52 @@ +package at.gv.egovernment.moa.id.process.spring.test; + + +import java.io.Serializable; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; + +/** + * Adapter class for {@link ExpressionEvaluationContext}. Intended to be used for testing purposes. + *  + * @author tknall + *  + */ +public class ExpressionContextAdapter implements ExpressionEvaluationContext { + +	private static final long serialVersionUID = 1L; + +	private Map<String, Serializable> ctxData = Collections.synchronizedMap(new HashMap<String, Serializable>()); + +	/** +	 * Returns a certain {@link Serializable} object associated with a certain {@code key}. +	 *  +	 * @param key +	 *            The key. +	 * @return The object or {@code null} if no object was found stored with that key or if a {@code null} value was +	 *         stored. +	 */ +	Serializable get(String key) { +		return ctxData.get(key); +	} + +	/** +	 * Stores a {@link Serializable} with a certain {@code key}. +	 *  +	 * @param key +	 *            The key. +	 * @param object +	 *            The object. +	 */ +	void put(String key, Serializable object) { +		ctxData.put(key, object); +	} + +	@Override +	public Map<String, Serializable> getCtx() { +		return Collections.unmodifiableMap(ctxData); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SimplePojo.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SimplePojo.java new file mode 100644 index 000000000..89f3c0383 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SimplePojo.java @@ -0,0 +1,41 @@ +package at.gv.egovernment.moa.id.process.spring.test; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; + +/** + * A dummy pojo used to test {@link ExpressionEvaluator} with Spring EL referencing Spring beans. + *  + * @author tknall + *  + */ +public class SimplePojo { + +	private Boolean booleanValue; +	private String stringValue; +	private Integer integerValue; + +	public Boolean getBooleanValue() { +		return booleanValue; +	} + +	public void setBooleanValue(Boolean booleanValue) { +		this.booleanValue = booleanValue; +	} + +	public String getStringValue() { +		return stringValue; +	} + +	public void setStringValue(String stringValue) { +		this.stringValue = stringValue; +	} + +	public Integer getIntegerValue() { +		return integerValue; +	} + +	public void setIntegerValue(Integer integerValue) { +		this.integerValue = integerValue; +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest.java new file mode 100644 index 000000000..5355f14d3 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest.java @@ -0,0 +1,116 @@ +package at.gv.egovernment.moa.id.process.spring.test; + +import static at.gv.egovernment.moa.id.process.ProcessInstanceState.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.hibernate.cfg.Configuration; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessEngineImpl; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; +import at.gv.egovernment.moa.id.process.spring.SpringExpressionEvaluator; + +/** + * Tests the process engine using processes based on Spring EL referencing the process context and further Spring beans. + *  + * @author tknall + *  + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class SpringExpressionAwareProcessEngineTest { + +	 +	private static ProcessEngine pe; + +	@BeforeClass +	public static void init() throws IOException, ProcessDefinitionParserException { + +		pe = new ProcessEngineImpl(); +		((ProcessEngineImpl) pe).setTransitionConditionExpressionEvaluator(new SpringExpressionEvaluator()); +		try (InputStream in = SpringExpressionAwareProcessEngineTest.class.getResourceAsStream("SampleProcessDefinitionWithExpression1.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(in); +		} +		try (InputStream in = SpringExpressionAwareProcessEngineTest.class.getResourceAsStream("SampleProcessDefinitionForSAML1Authentication.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(in); +		} + +		initHibernateForTesting(); +	} + +	private static void initHibernateForTesting() throws IOException{ + +		InputStream in = SpringExpressionAwareProcessEngineTest.class.getResourceAsStream("/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties"); +		Properties props = new Properties(); +		props.load(in); + +		try { +			ConfigurationDBUtils.initHibernate(props); +			Configuration config = new Configuration(); +			config.addProperties(props); +			config.addAnnotatedClass(ProcessInstanceStore.class); +			config.addAnnotatedClass(InterfederationSessionStore.class); +			MOASessionDBUtils.initHibernate(config, props); +		} catch (MOADatabaseException e) { +			e.printStackTrace(); +		} +	} + + +	@Test +	public void testSampleProcessDefinitionWithExpression1() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcessWithExpression1"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); +		 +		 +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); +	} + +	@Test +	public void testSampleProcessDefinitionForSAML1Authentication() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcessDefinitionForSAML1Authentication"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); + +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); + +		pi = pe.getProcessInstance(piId); +		ExecutionContext ec = pi.getExecutionContext(); +		assertNotNull(ec); +		System.out.println(ec.keySet()); + +		assertNotNull(ec.get("bkuURL")); +		assertNotNull(ec.get("IdentityLink")); +		assertNotNull(ec.get("isIdentityLinkValidated")); +		assertNotNull(ec.get("SignedAuthBlock")); +		assertNotNull(ec.get("isSignedAuthBlockValidated")); +		assertNotNull(ec.get("SAML1Assertion")); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest.java new file mode 100644 index 000000000..bc9d1d399 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest.java @@ -0,0 +1,54 @@ +package at.gv.egovernment.moa.id.process.spring.test; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; + +/** + * Tests the {@link ExpressionEvaluator} using a Spring EL based implementation capable of dereferencing Spring beans. + *  + * @author tknall + *  + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration +public class SpringExpressionEvaluatorTest { + +	private ExpressionContextAdapter ctx; + +	@Autowired +	private ExpressionEvaluator expressionEvaluator; + +	@Before +	public void prepareTest() { +		ctx = new ExpressionContextAdapter(); +	} + +	@Test +	public void testEvaluateSimpleExpression() { +		assertTrue(expressionEvaluator.evaluate(ctx, "'true'")); +	} + +	@Test +	public void testEvaluateExpressionWithCtx() { +		ctx.put("myProperty", false); +		assertFalse(expressionEvaluator.evaluate(ctx, "ctx['myProperty']")); +	} + +	@Test +	public void testEvaluateExpressionWithBeanReference() { +		assertTrue(expressionEvaluator.evaluate(ctx, "@simplePojo.booleanValue")); +		assertTrue(expressionEvaluator.evaluate(ctx, "'HelloWorld'.equals(@simplePojo.stringValue)")); +		assertTrue(expressionEvaluator.evaluate(ctx, "@simplePojo.integerValue == 42")); +		assertTrue(expressionEvaluator.evaluate(ctx, "@simplePojo.stringValue.length() == 10")); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/CreateSAML1AssertionTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/CreateSAML1AssertionTask.java new file mode 100644 index 000000000..ebda3c5c3 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/CreateSAML1AssertionTask.java @@ -0,0 +1,59 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Objects; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the creation of a SAML1 assertion. + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * <li>{@code isIdentityLinkValidated}</li> + * <li>{@code SignedAuthBlock}</li> + * <li>{@code isSignedAuthBlockValidated}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code SAML1Assertion}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class CreateSAML1AssertionTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws TaskExecutionException { +		Objects.requireNonNull(executionContext.get("IdentityLink")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isIdentityLinkValidated")))); +		Objects.requireNonNull(executionContext.get("SignedAuthBlock")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isSignedAuthBlockValidated")))); + +		log.debug("Using IdentityLink and signed auth block in order to create SAML1 assertion."); + +		try (InputStream in = getClass().getResourceAsStream("SAML1Assertion.xml")) { +			executionContext.put("SAML1Assertion", IOUtils.toString(in, Charset.forName("UTF-8"))); +			 +		} catch (IOException e) { +			throw new TaskExecutionException("", e); +		} + +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/GetIdentityLinkTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/GetIdentityLinkTask.java new file mode 100644 index 000000000..bd08ec6a1 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/GetIdentityLinkTask.java @@ -0,0 +1,54 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Objects; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the retrieval of an IdentityLink. + * <p/> + * Asynchonous + * <p> + * Requires context data: + * <ul> + * <li>{@code bkuURL}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code IdentityLink}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class GetIdentityLinkTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws TaskExecutionException { +		Objects.requireNonNull(executionContext.get("bkuURL")); + +		log.debug("Using bkuURL in order to retrieve IdentityLink."); + +		try (InputStream in = getClass().getResourceAsStream("IdentityLink_Max_Mustermann.xml")) { +			executionContext.put("IdentityLink", IOUtils.toString(in, Charset.forName("UTF-8"))); +			 +		} catch (IOException e) { +			throw new TaskExecutionException("", e); +		} +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SelectBKUTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SelectBKUTask.java new file mode 100644 index 000000000..54195ec91 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SelectBKUTask.java @@ -0,0 +1,33 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating a bku selection. + * <p/> + * Asynchonous + * <p> + * Enriches context data with: + * <ul> + * <li>{@code bkuURL}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class SelectBKUTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) { +		log.debug("Providing BKU selection."); +		executionContext.put("bkuURL", "https://127.0.0.1:3496/https-security-layer-request"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SignAuthBlockTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SignAuthBlockTask.java new file mode 100644 index 000000000..8f9b72cea --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/SignAuthBlockTask.java @@ -0,0 +1,57 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.util.Objects; + +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the signature of an auth block. + * <p/> + * Asynchonous + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * <li>{@code isIdentityLinkValidated}</li> + * <li>{@code bkuURL}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code SignedAuthBlock}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class SignAuthBlockTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws TaskExecutionException { +		Objects.requireNonNull(executionContext.get("IdentityLink")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isIdentityLinkValidated")))); +		Objects.requireNonNull(executionContext.get("bkuURL")); + +		log.debug("Using validated IdentityLink and bkuURL in order to sign auth block."); +		try (InputStream in = getClass().getResourceAsStream("SignedAuthBlock.xml")) { +			executionContext.put("SignedAuthBlock", IOUtils.toString(in, Charset.forName("UTF-8"))); +		} catch (IOException e) { +			throw new TaskExecutionException("", e); +			 +		} +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateIdentityLinkTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateIdentityLinkTask.java new file mode 100644 index 000000000..a8e7df3d7 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateIdentityLinkTask.java @@ -0,0 +1,42 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Dummy task simulating the validation of an IdentityLink. + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code isIdentityLinkValidated}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class ValidateIdentityLinkTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) { +		Objects.requireNonNull(executionContext.get("IdentityLink")); + +		log.debug("Validating IdentityLink."); + +		executionContext.put("isIdentityLinkValidated", true); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateSignedAuthBlockTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateSignedAuthBlockTask.java new file mode 100644 index 000000000..cece373d4 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/spring/test/task/ValidateSignedAuthBlockTask.java @@ -0,0 +1,47 @@ +package at.gv.egovernment.moa.id.process.spring.test.task; + +import java.util.Objects; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import at.gv.egovernment.moa.id.auth.modules.TaskExecutionException; +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * A dummy task simulating the validation of an auth block. + * <p> + * Requires context data: + * <ul> + * <li>{@code IdentityLink}</li> + * <li>{@code isIdentityLinkValidated}</li> + * <li>{@code SignedAuthBlock}</li> + * </ul> + * </p> + * <p> + * Enriches context data with: + * <ul> + * <li>{@code isSignedAuthBlockValidated}</li> + * </ul> + * </p> + *  + * @author tknall + *  + */ +public class ValidateSignedAuthBlockTask implements Task { + +	private Logger log = LoggerFactory.getLogger(getClass()); + +	@Override +	public void execute(ExecutionContext executionContext) throws TaskExecutionException { +		Objects.requireNonNull(executionContext.get("IdentityLink")); +		assert (Boolean.TRUE.equals(Objects.requireNonNull(executionContext.get("isIdentityLinkValidated")))); +		Objects.requireNonNull(executionContext.get("SignedAuthBlock")); + +		log.debug("Using validated IdentityLink and signed auth block in order to validate signed auth block."); + +		executionContext.put("isSignedAuthBlockValidated", true); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/BooleanStringExpressionEvaluator.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/BooleanStringExpressionEvaluator.java new file mode 100644 index 000000000..20dfc50ef --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/BooleanStringExpressionEvaluator.java @@ -0,0 +1,24 @@ +package at.gv.egovernment.moa.id.process.test; + +import java.util.Objects; + +import org.apache.commons.lang3.BooleanUtils; + +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluationContext; +import at.gv.egovernment.moa.id.process.api.ExpressionEvaluator; + +/** + * Expression evaluator that guesses the boolean value from a String. Refer to {@link BooleanUtils#toBoolean(String)} + * for further information. + *  + * @author tknall + *  + */ +public class BooleanStringExpressionEvaluator implements ExpressionEvaluator { + +	@Override +	public boolean evaluate(ExpressionEvaluationContext expressionContext, String expression) { +		return BooleanUtils.toBoolean(Objects.requireNonNull(expression, "Expression must not be null.")); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HalloWeltTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HalloWeltTask.java new file mode 100644 index 000000000..d05200ee8 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HalloWeltTask.java @@ -0,0 +1,19 @@ +package at.gv.egovernment.moa.id.process.test; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Simple task that just outputs a "Hallo World" text to the console. + *  + * @author tknall + *  + */ +public class HalloWeltTask implements Task { + +	@Override +	public void execute(ExecutionContext executionContext) { +		System.out.println("Hallo Welt"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HelloWorldTask.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HelloWorldTask.java new file mode 100644 index 000000000..e79bb8198 --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/HelloWorldTask.java @@ -0,0 +1,19 @@ +package at.gv.egovernment.moa.id.process.test; + +import at.gv.egovernment.moa.id.process.api.ExecutionContext; +import at.gv.egovernment.moa.id.process.api.Task; + +/** + * Simple task that just outputs a "Hello World" text to the console. + *  + * @author tknall + *  + */ +public class HelloWorldTask implements Task { + +	@Override +	public void execute(ExecutionContext executionContext) { +		System.out.println("Hello World"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessDefinitionParserTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessDefinitionParserTest.java new file mode 100644 index 000000000..df13f064b --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessDefinitionParserTest.java @@ -0,0 +1,137 @@ +package at.gv.egovernment.moa.id.process.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.InputStream; + +import org.junit.Test; + +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.model.EndEvent; +import at.gv.egovernment.moa.id.process.model.ProcessDefinition; +import at.gv.egovernment.moa.id.process.model.ProcessNode; +import at.gv.egovernment.moa.id.process.model.StartEvent; +import at.gv.egovernment.moa.id.process.model.TaskInfo; +import at.gv.egovernment.moa.id.process.model.Transition; + +public class ProcessDefinitionParserTest { +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_MultipleStartEvents() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_MultipleStartEvents.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_TransitionLoop() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_TransitionLoop.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_TransitionStartsFromEndEvent() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_TransitionStartsFromEndEvent.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_TransitionRefsTransition() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_TransitionRefsTransition.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test(expected = ProcessDefinitionParserException.class) +	public void testParseInvalidProcessDefinition_NoStartEvents() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("InvalidProcessDefinition_NoStartEvents.xml")) { +			new ProcessDefinitionParser().parse(in); +		} +	} +	 +	@Test +	public void testParseSampleProcessDefinition() throws IOException, ProcessDefinitionParserException { +		try (InputStream in = getClass().getResourceAsStream("SampleProcessDefinition1.xml")) { +			 +			ProcessDefinitionParser parser = new ProcessDefinitionParser(); +			ProcessDefinition pd = parser.parse(in); +			 +			assertNotNull(pd); +			assertEquals("SampleProcess1", pd.getId()); +			 +			// first assert tasks then transitions +			// start event +			StartEvent startEvent = pd.getStartEvent(); +			assertNotNull(startEvent); +			assertEquals("start", startEvent.getId()); +			assertEquals(startEvent, pd.getProcessNode("start")); +			// task1 +			ProcessNode processNode = pd.getProcessNode("task1"); +			assertNotNull(processNode); +			assertTrue(processNode instanceof TaskInfo); +			TaskInfo task1 = (TaskInfo) processNode; +			assertEquals("task1", task1.getId()); +			assertFalse(task1.isAsync()); +			// task2  +			processNode = pd.getProcessNode("task2"); +			assertNotNull(processNode); +			assertTrue(processNode instanceof TaskInfo); +			TaskInfo task2 = (TaskInfo) processNode; +			assertEquals("task2", task2.getId()); +			assertTrue(task2.isAsync()); +			// end event +			processNode = pd.getProcessNode("end"); +			assertNotNull(processNode); +			assertTrue(processNode instanceof EndEvent); +			EndEvent endEvent = (EndEvent) processNode; +			assertEquals("end", endEvent.getId()); +			 +			// assert transitions +			// start event +			assertNotNull(startEvent.getIncomingTransitions()); +			assertTrue(startEvent.getIncomingTransitions().isEmpty()); +			assertNotNull(startEvent.getOutgoingTransitions()); +			assertEquals(1, startEvent.getOutgoingTransitions().size()); +			// transition from start to task1 +			Transition startToTask1 = startEvent.getOutgoingTransitions().get(0); +			assertEquals("fromStart", startToTask1.getId()); +			assertEquals(startEvent, startToTask1.getFrom()); +			assertEquals(task1, startToTask1.getTo()); +			assertEquals("true", startToTask1.getConditionExpression()); +			// task1 +			assertNotNull(task1.getIncomingTransitions()); +			assertEquals(1, task1.getIncomingTransitions().size()); +			assertEquals(startToTask1, task1.getIncomingTransitions().get(0)); +			assertNotNull(task1.getOutgoingTransitions()); +			assertEquals(1, task1.getOutgoingTransitions().size()); +			// transition from task1 to task2 +			Transition task1ToTask2 = task1.getOutgoingTransitions().get(0); +			assertNull(task1ToTask2.getId()); +			assertEquals(task1, task1ToTask2.getFrom()); +			assertEquals(task2, task1ToTask2.getTo()); +			assertNull(task1ToTask2.getConditionExpression()); +			// task2 +			assertNotNull(task2.getIncomingTransitions()); +			assertEquals(1, task2.getIncomingTransitions().size()); +			assertEquals(task1ToTask2, task2.getIncomingTransitions().get(0)); +			assertNotNull(task2.getOutgoingTransitions()); +			assertEquals(1, task2.getOutgoingTransitions().size()); +			// transition from task2 to end +			Transition task2ToEnd = task2.getOutgoingTransitions().get(0); +			assertNull(task2ToEnd.getId()); +			assertEquals(task2, task2ToEnd.getFrom()); +			assertEquals(endEvent, task2ToEnd.getTo()); +			assertNull(task2ToEnd.getConditionExpression()); +			 +		} +	} + +} diff --git a/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessEngineTest.java b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessEngineTest.java new file mode 100644 index 000000000..4f24468fe --- /dev/null +++ b/id/server/idserverlib/src/test/java/at/gv/egovernment/moa/id/process/test/ProcessEngineTest.java @@ -0,0 +1,108 @@ +package at.gv.egovernment.moa.id.process.test; + +import static at.gv.egovernment.moa.id.process.ProcessInstanceState.*; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +import org.hibernate.cfg.Configuration; +import org.junit.BeforeClass; +import org.junit.Test; + +import at.gv.egovernment.moa.id.commons.db.ConfigurationDBUtils; +import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils; +import at.gv.egovernment.moa.id.commons.db.dao.session.InterfederationSessionStore; +import at.gv.egovernment.moa.id.commons.db.ex.MOADatabaseException; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParser; +import at.gv.egovernment.moa.id.process.ProcessDefinitionParserException; +import at.gv.egovernment.moa.id.process.ProcessEngine; +import at.gv.egovernment.moa.id.process.ProcessEngineImpl; +import at.gv.egovernment.moa.id.process.ProcessExecutionException; +import at.gv.egovernment.moa.id.process.ProcessInstance; +import at.gv.egovernment.moa.id.process.dao.ProcessInstanceStore; + +public class ProcessEngineTest { +	 +	private static ProcessEngine pe; + +	@BeforeClass +	public static void init() throws IOException, ProcessDefinitionParserException { + +		ProcessDefinitionParser pdp = new ProcessDefinitionParser(); + +		pe = new ProcessEngineImpl(); + +		((ProcessEngineImpl) pe).setTransitionConditionExpressionEvaluator(new BooleanStringExpressionEvaluator()); +		try (InputStream in = ProcessEngineTest.class.getResourceAsStream("SampleProcessDefinition1.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in)); +		} +		try (InputStream in = ProcessEngineTest.class.getResourceAsStream("SampleProcessDefinition2.xml")) { +			((ProcessEngineImpl) pe).registerProcessDefinition(pdp.parse(in)); +		} + +		initHibernateForTesting(); +	} + + +	private static void initHibernateForTesting() throws IOException{ + +		InputStream in = ProcessEngineTest.class.getResourceAsStream("/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties"); +		Properties props = new Properties(); +		props.load(in); + +		try { +			ConfigurationDBUtils.initHibernate(props); +			Configuration config = new Configuration(); +			config.addProperties(props); +			config.addAnnotatedClass(ProcessInstanceStore.class); +			config.addAnnotatedClass(InterfederationSessionStore.class); +			MOASessionDBUtils.initHibernate(config, props); +		} catch (MOADatabaseException e) { +			e.printStackTrace(); +		} +	} +	 +	@Test +	public void testSampleProcess1() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcess1"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); + +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(SUSPENDED, pi.getState()); + +		System.out.println("Do something asynchronously"); +		pe.signal(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); +	} +	 +	@Test +	public void testSampleProcess2() throws IOException, ProcessDefinitionParserException, ProcessExecutionException { + +		String piId = pe.createProcessInstance("SampleProcess2"); +		ProcessInstance pi = pe.getProcessInstance(piId); +		assertEquals(NOT_STARTED, pi.getState()); + +		// start process +		pe.start(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(SUSPENDED, pi.getState()); + +		System.out.println("Do something asynchronously"); +		pe.signal(piId); +		pi = pe.getProcessInstance(piId); +		assertEquals(ENDED, pi.getState()); +	} + +	@Test(expected = IllegalArgumentException.class) +	public void testProcessInstanceDoesNotExist() { +		pe.getProcessInstance("does not exist"); +	} + +} diff --git a/id/server/idserverlib/src/test/java/test/tlenz/simpletest.java b/id/server/idserverlib/src/test/java/test/tlenz/simpletest.java index ec908f78b..549eb4f2b 100644 --- a/id/server/idserverlib/src/test/java/test/tlenz/simpletest.java +++ b/id/server/idserverlib/src/test/java/test/tlenz/simpletest.java @@ -1,3 +1,8 @@ +package test.tlenz; + +import at.gv.egovernment.moa.id.data.AuthenticationRole; +import at.gv.egovernment.moa.id.data.AuthenticationRoleFactory; +  /*******************************************************************************   * Copyright 2014 Federal Chancellery Austria   * MOA-ID has been developed in a cooperation between BRZ, the Federal @@ -38,12 +43,19 @@  //import at.gv.egovernment.moa.id.storage.AssertionStorage;  //import at.gv.egovernment.moa.util.MiscUtil;  // -//public class simpletest { +public class simpletest {  // -//	public static void main(String[] args) { +	public static void main(String[] args) { +		 +		AuthenticationRole test = AuthenticationRoleFactory.buildFormPVPole("ecas-demo-EUROPEAN_COMMISSION(key=A\\,B)"); +		 +		test = AuthenticationRoleFactory.buildFormPVPole("ecas-demo-EUROPEAN_COMMISSION"); +		test = AuthenticationRoleFactory.buildFormPVPole("ecas-demo-EUROPEAN_COMMISSION(key=A)"); +		test = AuthenticationRoleFactory.buildFormPVPole("ecas-demo-EUROPEAN_COMMISSION(keyA=A,keyB=B)"); +		  //		  //		System.setProperty("mandates.configuration", "D:/Projekte/svn/moa-id/moa-id.properties"); -//		String propertiesFileLocation = System.getProperty("mandates.configuration"); +//		String propertiesFileLocation = Systm.getProperty("mandates.configuration");  //		  //		MiscUtil.assertNotNull(propertiesFileLocation, "propertiesFileName");  //		File propertiesFile = new File(propertiesFileLocation); @@ -95,5 +107,5 @@  //		  //		  //		 -//	} -//} +	} +} diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties new file mode 100644 index 000000000..c4faa6d09 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/hibernate.configuration.test.properties @@ -0,0 +1,12 @@ +# minimal Hibnerate configuration for testing the process engine +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.connection.url=jdbc:h2:mem:moa.id-session;DB_CLOSE_DELAY=-1 +hibernate.connection.charSet=utf-8 +hibernate.connection.driver_class=org.h2.Driver +hibernate.connection.username= +hibernate.connection.password= + +hibernate.format_sql=true +hibernate.show_sql=false +hibernate.transaction.auto_close_session=true +hibernate.hbm2ddl.auto=update diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionForSAML1Authentication.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionForSAML1Authentication.xml new file mode 100644 index 000000000..764ad6405 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionForSAML1Authentication.xml @@ -0,0 +1,54 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	id="SampleProcessDefinitionForSAML1Authentication"> + +	<!-- +		returns String 'bkuURL' +	--> +	<pd:Task id="bkuSelectionTask" class="at.gv.egovernment.moa.id.process.spring.test.task.SelectBKUTask" /> + +	<!-- +		requires 'bkuURL' +		returns String 'IdentityLink' +	--> +	<pd:Task id="getIdentityLinkTask" class="at.gv.egovernment.moa.id.process.spring.test.task.GetIdentityLinkTask" /> + +	<!-- +		requires 'IdentityLink' +		returns Boolean 'isIdentityLinkValidated' +	--> +	<pd:Task id="validateIdentityLinkTask" class="at.gv.egovernment.moa.id.process.spring.test.task.ValidateIdentityLinkTask" /> + +	<!-- +		requires 'IdentityLink', 'isIdentityLinkValidated', 'bkuURL' +		returns String 'SignedAuthBlock' +	--> +	<pd:Task id="signAuthBlockTask" class="at.gv.egovernment.moa.id.process.spring.test.task.SignAuthBlockTask" /> + +	<!-- +		requires 'IdentityLink', 'isIdentityLinkValidated', 'SignedAuthBlock' +		returns Boolean 'isSignedAuthBlockValidated' +	--> +	<pd:Task id="validateSignedAuthBlockTask" class="at.gv.egovernment.moa.id.process.spring.test.task.ValidateSignedAuthBlockTask" /> +	 +	<!-- +		requires 'IdentityLink', 'isIdentityLinkValidated', 'SignedAuthBlock', 'isSignedAuthBlockValidated'; +		returns 'SAML1Assertion' +	--> +	<pd:Task id="createAssertionTask" class="at.gv.egovernment.moa.id.process.spring.test.task.CreateSAML1AssertionTask" /> + +	<pd:StartEvent id="start" /> +	<pd:EndEvent id="end" /> + +	<pd:Transition from="start" to="bkuSelectionTask"    conditionExpression="ctx['bkuURL'] == null" /> +	<pd:Transition from="start" to="getIdentityLinkTask"  /> +	 +	<pd:Transition from="bkuSelectionTask"            to="getIdentityLinkTask" /> +	<pd:Transition from="getIdentityLinkTask"         to="validateIdentityLinkTask" /> +	<pd:Transition from="validateIdentityLinkTask"    to="signAuthBlockTask"            conditionExpression="ctx['isIdentityLinkValidated']" /> +	<pd:Transition from="signAuthBlockTask"           to="validateSignedAuthBlockTask" /> +	<pd:Transition from="validateSignedAuthBlockTask" to="createAssertionTask"          conditionExpression="ctx['isSignedAuthBlockValidated']" /> +	 +	<pd:Transition from="createAssertionTask" to="end" /> + +</pd:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionWithExpression1.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionWithExpression1.xml new file mode 100644 index 000000000..dfe186423 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SampleProcessDefinitionWithExpression1.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<pd:ProcessDefinition xmlns:pd="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	id="SampleProcessWithExpression1"> + +	<pd:Task id="task1" /> +	<pd:Task id="task2" /> +	<pd:Task id="task3" /> +	<pd:Task id="task4" /> + +	<pd:StartEvent id="start" /> +	<pd:EndEvent id="end" /> + +	<pd:Transition from="start" to="task1" conditionExpression="'true'" /> +	<pd:Transition from="task1" to="task2" conditionExpression="'true'" /> +	<pd:Transition from="task2" to="task3" conditionExpression="'true'" /> +	<pd:Transition from="task3" to="task4" conditionExpression="'true'" /> +	<pd:Transition from="task4" to="end"   conditionExpression="'true'" /> +	 +</pd:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml new file mode 100644 index 000000000..9a381d83a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionAwareProcessEngineTest-context.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xmlns:task="http://www.springframework.org/schema/task" +	xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd +		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + +	<bean id="springElAwareExpressionEvaluator" class="at.gv.egovernment.moa.id.process.spring.SpringExpressionEvaluator" /> + +	<bean id="processEngine" class="at.gv.egovernment.moa.id.process.ProcessEngineImpl"> +		<property name="transitionConditionExpressionEvaluator" ref="springElAwareExpressionEvaluator" /> +	</bean> +</beans> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest-context.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest-context.xml new file mode 100644 index 000000000..95b88ca1a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/SpringExpressionEvaluatorTest-context.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<beans xmlns="http://www.springframework.org/schema/beans" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + +	<bean id="simplePojo" class="at.gv.egovernment.moa.id.process.spring.test.SimplePojo"> +		<property name="booleanValue" value="true" /> +		<property name="integerValue" value="42" /> +		<property name="stringValue" value="HelloWorld" /> +	</bean> +	 +	<bean id="expressionEvaluator" class="at.gv.egovernment.moa.id.process.spring.SpringExpressionEvaluator" /> + +</beans> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/IdentityLink_Max_Mustermann.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/IdentityLink_Max_Mustermann.xml new file mode 100644 index 000000000..c68972f13 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/IdentityLink_Max_Mustermann.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="UTF-8"?><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" AssertionID="szr.bmi.gv.at-AssertionID132860852347311974" IssueInstant="2012-02-07T10:55:23+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0"> +	<saml:AttributeStatement> +		<saml:Subject> +			<saml:SubjectConfirmation> +				<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> +				<saml:SubjectConfirmationData> +					<pr:Person si:type="pr:PhysicalPersonType"><pr:Identification><pr:Value>tqCQEC7+AqGEeeL390V5Jg==</pr:Value><pr:Type>urn:publicid:gv.at:baseid</pr:Type></pr:Identification><pr:Name><pr:GivenName>Max</pr:GivenName><pr:FamilyName primary="undefined">Mustermann</pr:FamilyName></pr:Name><pr:DateOfBirth>1940-01-01</pr:DateOfBirth></pr:Person> +				</saml:SubjectConfirmationData> +			</saml:SubjectConfirmation> +		</saml:Subject> +	<saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"><saml:AttributeValue><ecdsa:ECDSAKeyValue><ecdsa:DomainParameters><ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.7"/></ecdsa:DomainParameters><ecdsa:PublicKey><ecdsa:X Value="111409151487007036894649069746411000129419717653159596280366627647453458115517" si:type="ecdsa:PrimeFieldElemType"/><ecdsa:Y Value="94725036374184689337892465478597728884477416796494369571140658859618867645034" si:type="ecdsa:PrimeFieldElemType"/></ecdsa:PublicKey></ecdsa:ECDSAKeyValue></saml:AttributeValue></saml:Attribute></saml:AttributeStatement> +	<dsig:Signature> +		<dsig:SignedInfo> +			<dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +			<dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> +			<dsig:Reference URI=""> +				<dsig:Transforms> +					<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +						<dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath> +					</dsig:Transform> +					<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +				</dsig:Transforms> +				<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +				<dsig:DigestValue>Rmr5vkWXL/PvpoXnbK632QmzYms=</dsig:DigestValue> +			</dsig:Reference> +			<dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest"> +				<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +				<dsig:DigestValue>HoPZWYll8aMFpKOlRSwckt5iCQk=</dsig:DigestValue> +			</dsig:Reference> +		</dsig:SignedInfo> +		<dsig:SignatureValue> +    NPpRwVo5/5kf5iHUyaEc7d7So3W4oPgOCYNgnKpgdZfttFkFFN+9oG60w7YvKEYSeTPhP3zp7eaH +ZFapj+naD+wd0y5ELWep9Y+s+qP7fNLrFECHQxQasLWtR4akxlWDpYQ0bvOuepK2ip1EQ6pRlccA +wJ1l4iOWFhfdA9YAg5QLkBqWSwgrNUswhLnDBM+Ot6Gj5g2rpYY7aoAOXvTR8B5Dkg94ASb4u0wv +VPV8+4mjOfP+l6QWLqywzcq3qj/qFZkbujjZbV/fNPDnDD1ff/M6ZfCGO8xzlYfjfEA7cmHuiJf2 +/ey/3nT7vI5XbpBPWChT5Sl4DQysxlfE6e4MZw== +  </dsig:SignatureValue><dsig:KeyInfo><dsig:X509Data><dsig:X509Certificate>MIIF3TCCBMWgAwIBAgIDByniMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAyMB4XDTEwMDcyODExMzY0M1oXDTE1MDcyODExMzY0M1owgbYxCzAJBgNVBAYTAkFUMR4wHAYDVQQKDBVEYXRlbnNjaHV0emtvbW1pc3Npb24xIjAgBgNVBAsMGVN0YW1temFobHJlZ2lzdGVyYmVob2VyZGUxLjAsBgNVBAMMJVNpZ25hdHVyc2VydmljZSBEYXRlbnNjaHV0emtvbW1pc3Npb24xFTATBgNVBAUTDDMyNTkyODMyMzk5ODEcMBoGCSqGSIb3DQEJARYNZHNrQGRzay5ndi5hdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN+dBSEBGj2jUXIK1Mp3lVxc/Za+pJMiyKrX3G1ZxgX/ikx7D9scsPYMt473LlAWl9cmCbHbJK+PV2XNNdURLMUCIX+4vUNs2MHeDTQtX8BXjJFpwJYSoaRJQ39FVS/1r5sWcra9Hhdm7w5Gtx/2ukyDX0kdkxawkhP4EQEzi/SI+Fugn+WqgQ1nAdlbxb/dcBw5w1h9b3lmuwUf4z3ooQWUD2DgA/kKd1KejNR43mLUsmvSzevPxT9zs78pOR1OacB7IszTVJPXeOEaaNZHnnB/UeO3g8LEV/3OkXcUgcMkbIIiaBHlll71Pq0COj9kqjXoe7OrRjLY5i3KwOpa6TMCAwEAAaOCAgcwggIDMBMGA1UdIwQMMAqACEkcWDpP6A0DMH8GCCsGAQUFBwEBBHMwcTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3AuYS10cnVzdC5hdC9vY3NwMEYGCCsGAQUFBzAChjpodHRwOi8vd3d3LmEtdHJ1c3QuYXQvY2VydHMvYS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMmEuY3J0MFQGA1UdIARNMEswSQYGKigAEQESMD8wPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cuYS10cnVzdC5hdC9kb2NzL2NwL2Etc2lnbi1BbXRzc2lnbmF0dXIwgZ4GA1UdHwSBljCBkzCBkKCBjaCBioaBh2xkYXA6Ly9sZGFwLmEtdHJ1c3QuYXQvb3U9YS1zaWduLWNvcnBvcmF0ZS1saWdodC0wMixvPUEtVHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQITAgOnhr0tbowDgYDVR0PAQH/BAQDAgSwMCAGA1UdEQQZMBeBFW1hcmN1cy5oaWxkQGRzay5ndi5hdDAJBgNVHRMEAjAAMA4GByooAAoBBwEEAwEB/zAUBgcqKAAKAQEBBAkMB0JTQi1EU0swDQYJKoZIhvcNAQEFBQADggEBAHTklnvPCH/bJSOlIPbLUEkSGuFHsektSZ8Vr22x/Yv7EzsxoQrJIiz2mQ2gQqFuExdWYxvsowjiSbiis9iUf1c0zscvDS3mIZxGs4M89XHsjHnIyb+Fuwnamw65QrFvM1tNB1ZMjxJ3x+YmHLHdtT3BEBcr3/NCRHd2S0HoBspNz9HVgJaZY1llR7poKBvnAc4g1i+QTvyVb00PtKxR9Lw/9ABInX/1pzpxqrPy7Ib2OP8z6dd3WHmIsCiSHUaj0Dxwwln6fYJjhxZ141SnbovlCLYtrsZLXoi9ljIqX4xO0PwMI2RfNc9cXxTRrRS6rEOvX7PpvgXiDXhp592Yyp4=</dsig:X509Certificate></dsig:X509Data></dsig:KeyInfo> +		<dsig:Object> +			<dsig:Manifest Id="manifest"> +				<dsig:Reference URI=""> +					<dsig:Transforms> +						<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +							<dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath> +						</dsig:Transform> +					</dsig:Transforms> +					<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					<dsig:DigestValue>7IkIdYti2dh3VZQ4Fp+9lPT67cM=</dsig:DigestValue> +				</dsig:Reference> +			</dsig:Manifest> +		</dsig:Object> +	</dsig:Signature> +</saml:Assertion>
\ No newline at end of file diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SAML1Assertion.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SAML1Assertion.xml new file mode 100644 index 000000000..3aeedd590 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SAML1Assertion.xml @@ -0,0 +1,487 @@ +<?xml version="1.0" encoding="UTF-8"?> +<saml:Assertion AssertionID="6025428631468682100" IssueInstant="2008-07-14T17:51:38+02:00" Issuer="https://localhost:18443/moa-id-auth/" MajorVersion="1" MinorVersion="0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:si="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +  <saml:AttributeStatement> +	 <saml:Subject> +		<saml:NameIdentifier NameQualifier="urn:publicid:gv.at:wbpk+FN+www.act.at">K2YMyx3/5kIpNJR+SAD/rbRYH+c=</saml:NameIdentifier> +		<saml:SubjectConfirmation> +		  <saml:ConfirmationMethod>http://reference.e-government.gv.at/namespace/moa/20020822#cm</saml:ConfirmationMethod> +		  <saml:SubjectConfirmationData> +			 <saml:Assertion AssertionID="any" IssueInstant="2008-07-14T17:51:26+02:00" Issuer="Thomas Knall" MajorVersion="1" MinorVersion="0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"> +				<saml:AttributeStatement> +				  <saml:Subject> +					 <saml:NameIdentifier>https://localhost:18443/moa-id-auth/</saml:NameIdentifier> +				  </saml:Subject> +				  <saml:Attribute AttributeName="wbPK" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +					 <saml:AttributeValue> +						<pr:Identification> +						  <pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +						  <pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +						</pr:Identification> +					 </saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="OA" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +					 <saml:AttributeValue>https://localhost:48443/mandates/</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="Geburtsdatum" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +					 <saml:AttributeValue>1978-04-29</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="RepresentationType" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +					 <saml:AttributeValue>Vollmachtsvertreter</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="MandatorName" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +					 <saml:AttributeValue>MeineTestFirma</saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="MandatorWbpk" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +					 <saml:AttributeValue>123456i</saml:AttributeValue> +				  </saml:Attribute> +				</saml:AttributeStatement> +				<dsig:Signature Id="signature-1216050695-35956125-21395" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +				  <dsig:SignedInfo> +					 <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> +					 <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/> +					 <dsig:Reference Id="signed-data-reference-0-1216050695-35956125-19584" URI=""> +						<dsig:Transforms> +						  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116"> +							 <xsl:stylesheet version="1.0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> +								<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml"> +								  <html xmlns="http://www.w3.org/1999/xhtml"> +									 <head> +										<title>Signatur der Anmeldedaten</title> +										<style media="screen" type="text/css"> +		  .boldstyle { font-weight: bold; } +		  .italicstyle { font-style: italic; } +		  .annotationstyle { font-size: small; } +		  </style> +									 </head> +									 <body> +										<h1>Signatur der Anmeldedaten</h1> +										<p/> +										<h4>Mit meiner elektronischen Signatur beantrage ich, +			 <span class="boldstyle"> +											 <xsl:value-of select="//@Issuer"/> +										  </span>, geboren am +			 <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"/>. +			 <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"/>. +			 <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"/>, +			 <xsl:if test="//saml:Attribute[@AttributeName='OIDTextualDescription']"> +				in der Rolle als <xsl:value-of select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"/> +				(OID***= <xsl:value-of select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"/>), +			 </xsl:if> +			 den Zugang zur gesicherten Anwendung. +		  </h4> +										<p/> +										<h4>Datum und Uhrzeit: +			 <xsl:value-of select="substring(//@IssueInstant,9,2)"/>. +			 <xsl:value-of select="substring(//@IssueInstant,6,2)"/>. +			 <xsl:value-of select="substring(//@IssueInstant,1,4)"/>, +			 <xsl:value-of select="substring(//@IssueInstant,12,2)"/>: +			 <xsl:value-of select="substring(//@IssueInstant,15,2)"/>: +			 <xsl:value-of select="substring(//@IssueInstant,18,2)"/> +										</h4> +										<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +										  <h4>HPI(**): <xsl:value-of select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"/> +										  </h4> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +										  <h4>wbPK(*): <xsl:value-of select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"/> +										  </h4> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='MandatorName']"> +										  <hr/> +										  <h4>Ich bin weiters ermächtigt als <xsl:value-of select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"/> +				von <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/> +											 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']">, geboren am +				  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"/>. +				  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"/>. +				  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"/> +											 </xsl:if> +											 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']">, +				  <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"/> +											 </xsl:if>, in deren Auftrag zu handeln. +			 </h4> +										  <xsl:if test="//saml:Attribute[@AttributeName='MandatorWbpk']"> +											 <h4>wbPK(*) des Vollmachtgebers: <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"/> +											 </h4> +										  </xsl:if> +										  <p/> +										</xsl:if> +										<xsl:choose> +										  <xsl:when test="//saml:Attribute[@AttributeName='OID']"> +											 <p/> +											 <hr/> +										  </xsl:when> +										  <xsl:when test="//saml:Attribute[@AttributeName='HPI']"> +											 <p/> +											 <hr/> +										  </xsl:when> +										  <xsl:when test="//saml:Attribute[@AttributeName='wbPK']"> +											 <p/> +											 <hr/> +										  </xsl:when> +										</xsl:choose> +										<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +										  <div class="annotationstyle">(*) wbPK: Das <span class="italicstyle">wirtschaftsbereichsspezifische Personenkennzeichen</span> wird aus den +			 jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum +			 Wirtschaftsunternehmen.</div> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +										  <div class="annotationstyle">(**) HPI: Der <span class="italicstyle">eHealth Professional Identifier</span> wird aus den jeweiligen +			 Stammzahlen der Gesundheitsdiensteanbieterinnen / Gesundheitsdiensteanbieter berechnet und ermöglicht eine eindeutige Zuordnung der +			 Gesundheitsdiensteanbieterin / des Gesundheitsdiensteanbieters im Gesundheitsbereich.</div> +										</xsl:if> +										<xsl:if test="//saml:Attribute[@AttributeName='OID']"> +										  <div class="annotationstyle">(***) OID: <span class="italicstyle">Object Identifier</span> sind standardisierte Objekt-Bezeichner und +			 beschreiben eindeutig die Rollen des GDA-Token Inhabers.</div> +										</xsl:if> +									 </body> +								  </html> +								</xsl:template> +							 </xsl:stylesheet> +						  </dsig:Transform> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/> +						</dsig:Transforms> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>0q9QWyqAyyiVNNLu1rIcU+nKsEE=</dsig:DigestValue> +					 </dsig:Reference> +					 <dsig:Reference Id="etsi-data-reference-0-1216050695-35956125-7815" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1216050695-35956125-20638')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>WtB0/ptvoB/r/7+fauSUIBULymg=</dsig:DigestValue> +					 </dsig:Reference> +				  </dsig:SignedInfo> +				  <dsig:SignatureValue>mZt9DuZiDqG81scsf30qjSDdy6vKC2/n034ZZwMUAvfWOXy3+Ubsk5X5CHhz ++lyI</dsig:SignatureValue> +				  <dsig:KeyInfo> +					 <dsig:X509Data> +						<dsig:X509Certificate>MIIEtDCCA5ygAwIBAgIDAgTEMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQG +EwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lz +dGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVh +LXNpZ24tUHJlbWl1bS1TaWctMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVt +LVNpZy0wMjAeFw0wNjA0MDQwOTUyMjhaFw0xMTA0MDQwOTUyMjhaMGkxCzAJ +BgNVBAYTAkFUMRUwEwYDVQQDDAxUaG9tYXMgS25hbGwxDjAMBgNVBAQMBUtu +YWxsMQ8wDQYDVQQqDAZUaG9tYXMxFTATBgNVBAUTDDUzNTE5ODkyMzM0OTEL +MAkGA1UEDAwCREkwSTATBgcqhkjOPQIBBggqhkjOPQMBAQMyAARrnYW5sXCQ +6M3irWaanDPi/ROXueKWiPRyZGjNH0Cp/NaiOuvrpv2RDVEKQm2tBiajggIP +MIICCzATBgNVHSMEDDAKgAhN3+H/S9nJ3zAnBggrBgEFBQcBAwEB/wQYMBYw +CAYGBACORgEBMAoGCCsGAQUFBwsBMHsGCCsGAQUFBwEBBG8wbTBCBggrBgEF +BQcwAoY2aHR0cDovL3d3dy5hLXRydXN0LmF0L2NlcnRzL2Etc2lnbi1QcmVt +aXVtLVNpZy0wMmEuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5hLXRy +dXN0LmF0L29jc3AwWQYDVR0gBFIwUDBEBgYqKAARAQswOjA4BggrBgEFBQcC +ARYsaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVByZW1p +dW0wCAYGBACLMAEBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8v +bGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEt +VHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2Jq +ZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQI +SNyH29WUoCgwDgYDVR0PAQH/BAQDAgbAMCgGA1UdCQQhMB8wHQYIKwYBBQUH +CQExERgPMTk3ODA0MjkwMDAwMDBaMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEF +BQADggEBAFkSCJE0YD4p4izU3ekQYPv4Z7gm/VFlpma5hXNvwkajVjHlAqo/ +ylYn8NQ4mMkD+yCDNtm8m8nr0K/yICb8Gnkbv59i6nh2AbzYBBb49VnYYGL6 +uunLH0aFUpAhy+3mDdlH8uhhIQBHwCfgwG1qa5zXY7bz4Vzkac/h6T+JVFkI +egO8OHQDadhgJvW80qspiao2DTac6vVgx4tGvjpdmw1R2pXBYhHD5rkPHlkf +GoeL3ak6hq4ea94Oy5VfNTIJv5MA0J2G1mwnW9B8uPWSM5EYPoWJyBOWcKBL +SSUqOt9D/9215ZGfbchkdRZjx0dTAD3FIhgG8nA72/uCFrBzyTk= +</dsig:X509Certificate> +					 </dsig:X509Data> +				  </dsig:KeyInfo> +				  <dsig:Object Id="etsi-data-object-0-1216050695-35956125-20638"> +					 <etsi:QualifyingProperties Target="#signature-1216050695-35956125-21395" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"> +						<etsi:SignedProperties> +						  <etsi:SignedSignatureProperties> +							 <etsi:SigningTime>2008-07-14T15:51:35Z</etsi:SigningTime> +							 <etsi:SigningCertificate> +								<etsi:Cert> +								  <etsi:CertDigest> +									 <etsi:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +									 <etsi:DigestValue>inMYWBmAxMHP7mDENjLFaEtv0Zk=</etsi:DigestValue> +								  </etsi:CertDigest> +								  <etsi:IssuerSerial> +									 <dsig:X509IssuerName>CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT</dsig:X509IssuerName> +									 <dsig:X509SerialNumber>132292</dsig:X509SerialNumber> +								  </etsi:IssuerSerial> +								</etsi:Cert> +							 </etsi:SigningCertificate> +							 <etsi:SignaturePolicyIdentifier> +								<etsi:SignaturePolicyImplied/> +							 </etsi:SignaturePolicyIdentifier> +						  </etsi:SignedSignatureProperties> +						  <etsi:SignedDataObjectProperties> +							 <etsi:DataObjectFormat ObjectReference="#signed-data-reference-0-1216050695-35956125-19584"> +								<etsi:MimeType>application/xhtml+xml</etsi:MimeType> +							 </etsi:DataObjectFormat> +						  </etsi:SignedDataObjectProperties> +						</etsi:SignedProperties> +					 </etsi:QualifyingProperties> +				  </dsig:Object> +				</dsig:Signature> +			 </saml:Assertion> +			 <saml:Assertion AssertionID="szr.bmi.gv.at-AssertionID11936526102761952" IssueInstant="2007-10-29T10:10:10+01:00" Issuer="http://portal.bmi.gv.at/ref/szr/issuer" MajorVersion="1" MinorVersion="0" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:ecdsa="http://www.w3.org/2001/04/xmldsig-more#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:si="http://www.w3.org/2001/XMLSchema-instance"> +				<saml:AttributeStatement> +				  <saml:Subject> +					 <saml:SubjectConfirmation> +						<saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:sender-vouches</saml:ConfirmationMethod> +						<saml:SubjectConfirmationData> +						  <pr:Person si:type="pr:PhysicalPersonType"> +							 <pr:Identification> +								<pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +								<pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +							 </pr:Identification> +							 <pr:Name> +								<pr:GivenName>Thomas</pr:GivenName> +								<pr:FamilyName primary="undefined">Knall</pr:FamilyName> +							 </pr:Name> +							 <pr:DateOfBirth>1978-04-29</pr:DateOfBirth> +						  </pr:Person> +						</saml:SubjectConfirmationData> +					 </saml:SubjectConfirmation> +				  </saml:Subject> +				  <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"> +					 <saml:AttributeValue> +						<ecdsa:ECDSAKeyValue> +						  <ecdsa:DomainParameters> +							 <ecdsa:NamedCurve URN="urn:oid:1.2.840.10045.3.1.1"/> +						  </ecdsa:DomainParameters> +						  <ecdsa:PublicKey> +							 <ecdsa:X Value="2638720011055700682018137297354399374048880611104468142324" si:type="ecdsa:PrimeFieldElemType"/> +							 <ecdsa:Y Value="2804889174475641803405778188053052844820705830770276369958" si:type="ecdsa:PrimeFieldElemType"/> +						  </ecdsa:PublicKey> +						</ecdsa:ECDSAKeyValue> +					 </saml:AttributeValue> +				  </saml:Attribute> +				  <saml:Attribute AttributeName="CitizenPublicKey" AttributeNamespace="urn:publicid:gv.at:namespaces:identitylink:1.2"> +					 <saml:AttributeValue> +						<dsig:RSAKeyValue> +						  <dsig:Modulus>sWOqPZzPTn9VvBR5LjuopIWYdh5aGzuX2vMjofhn8bStba1CDW1qkDdlYW4Rs/DfU/I1uqor4Lje +/G3Yzh82yD0MHdzlW8MYUJ8RJe+czbjRUPaSbC/NRqhyF3eKnflxM++sJb2abrUH/9TV0q8P5QRS +uZC/JpAEYpSazysPz/fv8AEnU8oxcTvCiax1jf2GZPmm3qFjPc4qDYNHqfnE8yWYt7kHeqPV/cRw +x3aMGW8mRwQZb7VRFLW5g37nrt9N</dsig:Modulus> +						  <dsig:Exponent>AQAB</dsig:Exponent> +						</dsig:RSAKeyValue> +					 </saml:AttributeValue> +				  </saml:Attribute> +				</saml:AttributeStatement> +				<dsig:Signature> +				  <dsig:SignedInfo> +					 <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +					 <dsig:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> +					 <dsig:Reference URI=""> +						<dsig:Transforms> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +							 <dsig:XPath>not(ancestor-or-self::pr:Identification)</dsig:XPath> +						  </dsig:Transform> +						  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						</dsig:Transforms> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>b3d/wcQb0Bl0/6GSPsrMxWpdRLA=</dsig:DigestValue> +					 </dsig:Reference> +					 <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#manifest"> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>eet0q3Thmw6+cbO1fazbEg0556I=</dsig:DigestValue> +					 </dsig:Reference> +				  </dsig:SignedInfo> +				  <dsig:SignatureValue> +oy55Cq7IyYy7z/TO2a3+m7tjG/ztiKhxhGzVqEYIWIObEOs/GVJDCCI4oe/HS8Fhc4TaXDcZXk4y +qBp4JJ288TeaNjPYkPzp38nWJ4xRatEyo7VaySXy+TqgwiBT5uhxrwkroCr4ZIWwOvt1uR5UBVAf +qk1ii+LPW2WYE3bMpoHfrM9CdFSPzWTRl/0zsEURc64EBPyIdKz+c70DaexeX2E0JVelKcj+jDaJ +mHsFhi/9QoscqPEVA87qv07yhyK5S41+f3HDvpuhYwvQDdOq50sclfsI+g9r473VxiRsOmJ9Ak4/ +k2KP0tgfAQ+h5hRGQUUo5LYPywjg7zPxe8SGGA== +</dsig:SignatureValue> +				  <dsig:KeyInfo> +					 <dsig:X509Data> +						<dsig:X509Certificate> +MIIFZTCCBE2gAwIBAgIDAt4cMA0GCSqGSIb3DQEBBQUAMIGfMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMSIwIAYDVQQLDBlhLXNpZ24tY29y +cG9yYXRlLWxpZ2h0LTAzMSIwIAYDVQQDDBlhLXNpZ24tY29ycG9yYXRlLWxpZ2h0 +LTAzMB4XDTA3MDExOTA5MDY0OFoXDTEyMDExOTA5MDY0OFowgZwxCzAJBgNVBAYT +AkFUMRkwFwYDVQQKDBBCdW5kZXNrYW56bGVyYW10MR4wHAYDVQQLDBVEYXRlbnNj +aHV0emtvbW1pc3Npb24xHTAbBgNVBAMMFERyLiBXYWx0cmF1dCBLb3RzY2h5MRUw +EwYDVQQFEww3MDAyNDc0OTk4MDQxHDAaBgkqhkiG9w0BCQEWDWRza0Bkc2suZ3Yu +YXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDfnQUhARo9o1FyCtTK +d5VcXP2WvqSTIsiq19xtWcYF/4pMew/bHLD2DLeO9y5QFpfXJgmx2ySvj1dlzTXV +ESzFAiF/uL1DbNjB3g00LV/AV4yRacCWEqGkSUN/RVUv9a+bFnK2vR4XZu8ORrcf +9rpMg19JHZMWsJIT+BEBM4v0iPhboJ/lqoENZwHZW8W/3XAcOcNYfW95ZrsFH+M9 +6KEFlA9g4AP5CndSnozUeN5i1LJr0s3rz8U/c7O/KTkdTmnAeyLM01ST13jhGmjW +R55wf1Hjt4PCxFf9zpF3FIHDJGyCImgR5ZZe9T6tAjo/ZKo16Huzq0Yy2OYtysDq +WukzAgMBAAGjggGpMIIBpTATBgNVHSMEDDAKgAhBkWkcv63YmDBVBggrBgEFBQcB +AQRJMEcwRQYIKwYBBQUHMAKGOWh0dHA6Ly93d3cuYS10cnVzdC5hdC9jZXJ0cy9h +LXNpZ24tY29ycG9yYXRlLWxpZ2h0LTAzLmNydDBYBgNVHSAEUTBPME0GByooABEB +BwEwQjBABggrBgEFBQcCARY0aHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3Av +YS1zaWduLWNvcnBvcmF0ZS1saWdodDCBngYDVR0fBIGWMIGTMIGQoIGNoIGKhoGH +bGRhcDovL2xkYXAuYS10cnVzdC5hdC9vdT1hLXNpZ24tY29ycG9yYXRlLWxpZ2h0 +LTAzLG89QS1UcnVzdCxjPUFUP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3Q/YmFz +ZT9vYmplY3RjbGFzcz1laWRDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5MBEGA1UdDgQK +BAhMCA6eGvS1ujAOBgNVHQ8BAf8EBAMCBLAwCQYDVR0TBAIwADAOBgcqKAAKAQcB +BAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAEoIvqPLAg0n2wCS27zTL+hmLi7zSbes +Od4e6pFT1l3cwGfdTkhiHVPnPRaDGLQkS384fAXBrOp6W13X9m2jD9csO6vZhd+T +nERXN1AqayoaecXFyHPykVUTLhn6pMdiSE21mEozfGLUDGMz74lvphEKFAOOCgp1 +o5ZCR09RbGAEbQNNn+ucXJxIa3mYjr1h3AElVbXoeoz12qUpqsNm9znymSkcmcNo +B5Pk6qXXx9UeC/Tj0aTglNkcMOSCFayldzOBaY6+qWKguPdzQUEryhGiNuARQpM5 +KMzvI0rmpc4Gau5HT9rQZHadr++VS8v1k6935uIyyZF9s+gdS5ywnSM= +</dsig:X509Certificate> +					 </dsig:X509Data> +				  </dsig:KeyInfo> +				  <dsig:Object> +					 <dsig:Manifest Id="manifest"> +						<dsig:Reference URI=""> +						  <dsig:Transforms> +							 <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +								<dsig:XPath>not(ancestor-or-self::dsig:Signature)</dsig:XPath> +							 </dsig:Transform> +						  </dsig:Transforms> +						  <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						  <dsig:DigestValue>JZGwiDzQAtJtnJMeeXyypTrDjwY=</dsig:DigestValue> +						</dsig:Reference> +					 </dsig:Manifest> +				  </dsig:Object> +				</dsig:Signature> +			 </saml:Assertion> +		  </saml:SubjectConfirmationData> +		</saml:SubjectConfirmation> +	 </saml:Subject> +	 <saml:Attribute AttributeName="PersonData" AttributeNamespace="http://reference.e-government.gv.at/namespace/persondata/20020228#"> +		<saml:AttributeValue> +		  <pr:Person si:type="pr:PhysicalPersonType" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:si="http://www.w3.org/2001/XMLSchema-instance"> +			 <pr:Identification> +				<pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +				<pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +			 </pr:Identification> +			 <pr:Name> +				<pr:GivenName>Thomas</pr:GivenName> +				<pr:FamilyName primary="undefined">Knall</pr:FamilyName> +			 </pr:Name> +			 <pr:DateOfBirth>1978-04-29</pr:DateOfBirth> +		  </pr:Person> +		</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="isQualifiedCertificate" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +		<saml:AttributeValue>true</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="bkuURL" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +		<saml:AttributeValue>https://127.0.0.1:3496/https-security-layer-request</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="SignerCertificate" AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#"> +		<saml:AttributeValue>MIIEtDCCA5ygAwIBAgIDAgTEMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQGEwJB +VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp +bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVhLXNpZ24tUHJl +bWl1bS1TaWctMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVtLVNpZy0wMjAeFw0w +NjA0MDQwOTUyMjhaFw0xMTA0MDQwOTUyMjhaMGkxCzAJBgNVBAYTAkFUMRUwEwYD +VQQDDAxUaG9tYXMgS25hbGwxDjAMBgNVBAQMBUtuYWxsMQ8wDQYDVQQqDAZUaG9t +YXMxFTATBgNVBAUTDDUzNTE5ODkyMzM0OTELMAkGA1UEDAwCREkwSTATBgcqhkjO +PQIBBggqhkjOPQMBAQMyAARrnYW5sXCQ6M3irWaanDPi/ROXueKWiPRyZGjNH0Cp +/NaiOuvrpv2RDVEKQm2tBiajggIPMIICCzATBgNVHSMEDDAKgAhN3+H/S9nJ3zAn +BggrBgEFBQcBAwEB/wQYMBYwCAYGBACORgEBMAoGCCsGAQUFBwsBMHsGCCsGAQUF +BwEBBG8wbTBCBggrBgEFBQcwAoY2aHR0cDovL3d3dy5hLXRydXN0LmF0L2NlcnRz +L2Etc2lnbi1QcmVtaXVtLVNpZy0wMmEuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8v +b2NzcC5hLXRydXN0LmF0L29jc3AwWQYDVR0gBFIwUDBEBgYqKAARAQswOjA4Bggr +BgEFBQcCARYsaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVBy +ZW1pdW0wCAYGBACLMAEBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8v +bGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEtVHJ1 +c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2JqZWN0Y2xh +c3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQISNyH29WUoCgw +DgYDVR0PAQH/BAQDAgbAMCgGA1UdCQQhMB8wHQYIKwYBBQUHCQExERgPMTk3ODA0 +MjkwMDAwMDBaMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADggEBAFkSCJE0YD4p +4izU3ekQYPv4Z7gm/VFlpma5hXNvwkajVjHlAqo/ylYn8NQ4mMkD+yCDNtm8m8nr +0K/yICb8Gnkbv59i6nh2AbzYBBb49VnYYGL6uunLH0aFUpAhy+3mDdlH8uhhIQBH +wCfgwG1qa5zXY7bz4Vzkac/h6T+JVFkIegO8OHQDadhgJvW80qspiao2DTac6vVg +x4tGvjpdmw1R2pXBYhHD5rkPHlkfGoeL3ak6hq4ea94Oy5VfNTIJv5MA0J2G1mwn +W9B8uPWSM5EYPoWJyBOWcKBLSSUqOt9D/9215ZGfbchkdRZjx0dTAD3FIhgG8nA7 +2/uCFrBzyTk=</saml:AttributeValue> +	 </saml:Attribute> +	 <saml:Attribute AttributeName="Mandate" AttributeNamespace="http://reference.e-government.gv.at/namespace/mandates/20040701#"> +		<saml:AttributeValue> +		  <md:Mandate MandateID="https://egov.act.at/mandates/20080714174835/886164" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:md="http://reference.e-government.gv.at/namespace/mandates/20040701#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#"> +			 <md:Annotation>Prokura - MeineTestFirma</md:Annotation> +			 <md:StatusInformationService>http://localhost:58080/omsp/OMSPRequest</md:StatusInformationService> +			 <md:Representative> +				<pr:PhysicalPerson> +				  <pr:Identification> +					 <pr:Value>K2YMyx3/5kIpNJR+SAD/rbRYH+c=</pr:Value> +					 <pr:Type>urn:publicid:gv.at:wbpk+FN+www.act.at</pr:Type> +				  </pr:Identification> +				  <pr:Name> +					 <pr:GivenName>Thomas</pr:GivenName> +					 <pr:FamilyName primary="undefined">Knall</pr:FamilyName> +				  </pr:Name> +				  <pr:DateOfBirth>1978-04-29</pr:DateOfBirth> +				</pr:PhysicalPerson> +			 </md:Representative> +			 <md:Mandator> +				<pr:CorporateBody> +				  <pr:Identification> +					 <pr:Value>123456i</pr:Value> +					 <pr:Type>urn:publicid:gv.at:baseid+XFN</pr:Type> +				  </pr:Identification> +				  <pr:FullName>MeineTestFirma</pr:FullName> +				</pr:CorporateBody> +			 </md:Mandator> +			 <md:Issued> +				<md:Place>Wien</md:Place> +				<md:Date>2008-07-14</md:Date> +			 </md:Issued> +			 <md:Properties> +				<md:SubstitutionAllowed>false</md:SubstitutionAllowed> +			 </md:Properties> +			 <md:SimpleMandateContent> +				<md:TextualDescription>Der/Die Bevollmächtigte wird zum Prokuristen/Prokuristin bestellt.</md:TextualDescription> +			 </md:SimpleMandateContent> +			 <dsig:Signature Id="signature-1-1" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +				<dsig:SignedInfo> +				  <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> +				  <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/> +				  <dsig:Reference Id="reference-1-1" URI=""> +					 <dsig:Transforms> +						<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +						  <dsig:XPath xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:moa="http://reference.e-government.gv.at/namespace/moa/20020822#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#">not(ancestor-or-self::pr:Identification or ancestor-or-self::dsig:Signature)</dsig:XPath> +						</dsig:Transform> +						<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						<dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +					 </dsig:Transforms> +					 <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					 <dsig:DigestValue>PRRF0sWBgoywztCKWEXafZfhpd0=</dsig:DigestValue> +				  </dsig:Reference> +				  <dsig:Reference Type="http://www.w3.org/2000/09/xmldsig#Manifest" URI="#dsig-manifest-1-1"> +					 <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					 <dsig:DigestValue>NorNorUqPFMA06JfxSJopOq7Qv0=</dsig:DigestValue> +				  </dsig:Reference> +				</dsig:SignedInfo> +				<dsig:SignatureValue>IQMZFc57XZd9LjeiaZqSfzZtWuXhuikAqbKA7pWuDK02DLFSYZPXsGjcvnwNdVaP</dsig:SignatureValue> +				<dsig:KeyInfo> +				  <dsig:X509Data> +					 <dsig:X509Certificate>MIICtjCCAm6gAwIBAgIBATAJBgcqhkjOPQQBMGoxCzAJBgNVBAYTAkFUMQ0wCwYD +VQQHEwRXaWVuMRkwFwYDVQQJExBFc3NsaW5nZ2Fzc2UgNS85MQwwCgYDVQQKEwNB +Q1QxIzAhBgNVBAMTGlZvbGxtYWNodGVuIFNpZ25hdHVyZGllbnN0MB4XDTA4MDcw +ODE1MTk1MFoXDTEyMTIzMTIxNTk1OVowajELMAkGA1UEBhMCQVQxDTALBgNVBAcT +BFdpZW4xGTAXBgNVBAkTEEVzc2xpbmdnYXNzZSA1LzkxDDAKBgNVBAoTA0FDVDEj +MCEGA1UEAxMaVm9sbG1hY2h0ZW4gU2lnbmF0dXJkaWVuc3QwgfMwgbwGByqGSM49 +AgEwgbACAQEwJAYHKoZIzj0BAQIZAP////////////////////7//////////zA0 +BBj////////////////////+//////////wEGGQhBRnlnIDnD6fpq3IkMEn+uN7s +wUa5sQQxBBiNqA6wMJD2fL8g60OhiAD0/wr9gv8QEgcZK5X/yNp4YxAR7WskzdVz ++XehHnlIEQIZAP///////////////5ne+DYUa8mxtNIoMQIBAQMyAAS908G9FD5/ +LLYruwFbp9giXahdQ1FAqKwzohSn9pgsVTQBnvXxU8IWIzhPHs49DZCjazBpMAwG +A1UdEwEB/wQCMAAwHQYDVR0OBBYEFLOSgnkLSJ3l4Ah49rHX/FAV1wWcMBkGA1Ud +IAQSMBAwDgYMKwYBBAGVEgECBAEBMB8GA1UdIwQYMBaAFLOSgnkLSJ3l4Ah49rHX +/FAV1wWcMAkGByqGSM49BAEDNwAwNAIYTTppZzS6wqoLDFcf9frHzf1kMheY04dT +Ahg4Nrb54vE3DTRf9sbO4xs4dTARHSt1ihA=</dsig:X509Certificate> +				  </dsig:X509Data> +				</dsig:KeyInfo> +				<dsig:Object> +				  <dsig:Manifest Id="dsig-manifest-1-1"> +					 <dsig:Reference Id="reference-1-2" URI=""> +						<dsig:Transforms> +						  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116"> +							 <dsig:XPath xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:moa="http://reference.e-government.gv.at/namespace/moa/20020822#" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#">not(ancestor-or-self::dsig:Signature)</dsig:XPath> +						  </dsig:Transform> +						  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +						  <dsig:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> +						</dsig:Transforms> +						<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +						<dsig:DigestValue>oz6ThHPL3V7RNibfPrDSWVhUgi8=</dsig:DigestValue> +					 </dsig:Reference> +				  </dsig:Manifest> +				</dsig:Object> +			 </dsig:Signature> +		  </md:Mandate> +		</saml:AttributeValue> +	 </saml:Attribute> +  </saml:AttributeStatement> +</saml:Assertion> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SignedAuthBlock.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SignedAuthBlock.xml new file mode 100644 index 000000000..450ba90f3 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/spring/test/task/SignedAuthBlock.xml @@ -0,0 +1,179 @@ +<?xml version="1.0" encoding="UTF-8"?> +<dsig:Signature Id="signature-1216050695-35956125-21395" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"> +  <dsig:SignedInfo> +	 <dsig:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> +	 <dsig:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"/> +	 <dsig:Reference Id="signed-data-reference-0-1216050695-35956125-19584" URI=""> +		<dsig:Transforms> +		  <dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> +		  <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116"> +			 <xsl:stylesheet version="1.0" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> +				<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml"> +				  <html xmlns="http://www.w3.org/1999/xhtml"> +					 <head> +						<title>Signatur der Anmeldedaten</title> +						<style media="screen" type="text/css"> +.boldstyle { font-weight: bold; } +.italicstyle { font-style: italic; } +.annotationstyle { font-size: small; } +</style> +					 </head> +					 <body> +						<h1>Signatur der Anmeldedaten</h1> +						<p/> +						<h4>Mit meiner elektronischen Signatur beantrage ich, +<span class="boldstyle"> +							 <xsl:value-of select="//@Issuer"/> +						  </span>, geboren am +<xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"/>. +<xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"/>. +<xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"/>, +<xsl:if test="//saml:Attribute[@AttributeName='OIDTextualDescription']"> +in der Rolle als <xsl:value-of select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"/> +(OID***= <xsl:value-of select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"/>), +</xsl:if> +den Zugang zur gesicherten Anwendung. +</h4> +						<p/> +						<h4>Datum und Uhrzeit: +<xsl:value-of select="substring(//@IssueInstant,9,2)"/>. +<xsl:value-of select="substring(//@IssueInstant,6,2)"/>. +<xsl:value-of select="substring(//@IssueInstant,1,4)"/>, +<xsl:value-of select="substring(//@IssueInstant,12,2)"/>: +<xsl:value-of select="substring(//@IssueInstant,15,2)"/>: +<xsl:value-of select="substring(//@IssueInstant,18,2)"/> +						</h4> +						<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +						  <h4>HPI(**): <xsl:value-of select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"/> +						  </h4> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +						  <h4>wbPK(*): <xsl:value-of select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"/> +						  </h4> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='MandatorName']"> +						  <hr/> +						  <h4>Ich bin weiters ermächtigt als <xsl:value-of select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"/> +von <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/> +							 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']">, geboren am +  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"/>. +  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"/>. +  <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"/> +							 </xsl:if> +							 <xsl:if test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']">, +  <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"/> +							 </xsl:if>, in deren Auftrag zu handeln. +</h4> +						  <xsl:if test="//saml:Attribute[@AttributeName='MandatorWbpk']"> +							 <h4>wbPK(*) des Vollmachtgebers: <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"/> +							 </h4> +						  </xsl:if> +						  <p/> +						</xsl:if> +						<xsl:choose> +						  <xsl:when test="//saml:Attribute[@AttributeName='OID']"> +							 <p/> +							 <hr/> +						  </xsl:when> +						  <xsl:when test="//saml:Attribute[@AttributeName='HPI']"> +							 <p/> +							 <hr/> +						  </xsl:when> +						  <xsl:when test="//saml:Attribute[@AttributeName='wbPK']"> +							 <p/> +							 <hr/> +						  </xsl:when> +						</xsl:choose> +						<xsl:if test="//saml:Attribute[@AttributeName='wbPK']"> +						  <div class="annotationstyle">(*) wbPK: Das <span class="italicstyle">wirtschaftsbereichsspezifische Personenkennzeichen</span> wird aus den +jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum +Wirtschaftsunternehmen.</div> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='HPI']"> +						  <div class="annotationstyle">(**) HPI: Der <span class="italicstyle">eHealth Professional Identifier</span> wird aus den jeweiligen +Stammzahlen der Gesundheitsdiensteanbieterinnen / Gesundheitsdiensteanbieter berechnet und ermöglicht eine eindeutige Zuordnung der +Gesundheitsdiensteanbieterin / des Gesundheitsdiensteanbieters im Gesundheitsbereich.</div> +						</xsl:if> +						<xsl:if test="//saml:Attribute[@AttributeName='OID']"> +						  <div class="annotationstyle">(***) OID: <span class="italicstyle">Object Identifier</span> sind standardisierte Objekt-Bezeichner und +beschreiben eindeutig die Rollen des GDA-Token Inhabers.</div> +						</xsl:if> +					 </body> +				  </html> +				</xsl:template> +			 </xsl:stylesheet> +		  </dsig:Transform> +		  <dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/> +		</dsig:Transforms> +		<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +		<dsig:DigestValue>0q9QWyqAyyiVNNLu1rIcU+nKsEE=</dsig:DigestValue> +	 </dsig:Reference> +	 <dsig:Reference Id="etsi-data-reference-0-1216050695-35956125-7815" Type="http://uri.etsi.org/01903/v1.1.1#SignedProperties" URI="#xmlns(etsi=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('etsi-data-object-0-1216050695-35956125-20638')/child::etsi:QualifyingProperties/child::etsi:SignedProperties)"> +		<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +		<dsig:DigestValue>WtB0/ptvoB/r/7+fauSUIBULymg=</dsig:DigestValue> +	 </dsig:Reference> +  </dsig:SignedInfo> +  <dsig:SignatureValue>mZt9DuZiDqG81scsf30qjSDdy6vKC2/n034ZZwMUAvfWOXy3+Ubsk5X5CHhz ++lyI</dsig:SignatureValue> +  <dsig:KeyInfo> +	 <dsig:X509Data> +		<dsig:X509Certificate>MIIEtDCCA5ygAwIBAgIDAgTEMA0GCSqGSIb3DQEBBQUAMIGXMQswCQYDVQQG +EwJBVDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lz +dGVtZSBpbSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMR4wHAYDVQQLDBVh +LXNpZ24tUHJlbWl1bS1TaWctMDIxHjAcBgNVBAMMFWEtc2lnbi1QcmVtaXVt +LVNpZy0wMjAeFw0wNjA0MDQwOTUyMjhaFw0xMTA0MDQwOTUyMjhaMGkxCzAJ +BgNVBAYTAkFUMRUwEwYDVQQDDAxUaG9tYXMgS25hbGwxDjAMBgNVBAQMBUtu +YWxsMQ8wDQYDVQQqDAZUaG9tYXMxFTATBgNVBAUTDDUzNTE5ODkyMzM0OTEL +MAkGA1UEDAwCREkwSTATBgcqhkjOPQIBBggqhkjOPQMBAQMyAARrnYW5sXCQ +6M3irWaanDPi/ROXueKWiPRyZGjNH0Cp/NaiOuvrpv2RDVEKQm2tBiajggIP +MIICCzATBgNVHSMEDDAKgAhN3+H/S9nJ3zAnBggrBgEFBQcBAwEB/wQYMBYw +CAYGBACORgEBMAoGCCsGAQUFBwsBMHsGCCsGAQUFBwEBBG8wbTBCBggrBgEF +BQcwAoY2aHR0cDovL3d3dy5hLXRydXN0LmF0L2NlcnRzL2Etc2lnbi1QcmVt +aXVtLVNpZy0wMmEuY3J0MCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5hLXRy +dXN0LmF0L29jc3AwWQYDVR0gBFIwUDBEBgYqKAARAQswOjA4BggrBgEFBQcC +ARYsaHR0cDovL3d3dy5hLXRydXN0LmF0L2RvY3MvY3AvYS1zaWduLVByZW1p +dW0wCAYGBACLMAEBMIGaBgNVHR8EgZIwgY8wgYyggYmggYaGgYNsZGFwOi8v +bGRhcC5hLXRydXN0LmF0L291PWEtc2lnbi1QcmVtaXVtLVNpZy0wMixvPUEt +VHJ1c3QsYz1BVD9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0P2Jhc2U/b2Jq +ZWN0Y2xhc3M9ZWlkQ2VydGlmaWNhdGlvbkF1dGhvcml0eTARBgNVHQ4ECgQI +SNyH29WUoCgwDgYDVR0PAQH/BAQDAgbAMCgGA1UdCQQhMB8wHQYIKwYBBQUH +CQExERgPMTk3ODA0MjkwMDAwMDBaMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEF +BQADggEBAFkSCJE0YD4p4izU3ekQYPv4Z7gm/VFlpma5hXNvwkajVjHlAqo/ +ylYn8NQ4mMkD+yCDNtm8m8nr0K/yICb8Gnkbv59i6nh2AbzYBBb49VnYYGL6 +uunLH0aFUpAhy+3mDdlH8uhhIQBHwCfgwG1qa5zXY7bz4Vzkac/h6T+JVFkI +egO8OHQDadhgJvW80qspiao2DTac6vVgx4tGvjpdmw1R2pXBYhHD5rkPHlkf +GoeL3ak6hq4ea94Oy5VfNTIJv5MA0J2G1mwnW9B8uPWSM5EYPoWJyBOWcKBL +SSUqOt9D/9215ZGfbchkdRZjx0dTAD3FIhgG8nA72/uCFrBzyTk= +</dsig:X509Certificate> +	 </dsig:X509Data> +  </dsig:KeyInfo> +  <dsig:Object Id="etsi-data-object-0-1216050695-35956125-20638"> +	 <etsi:QualifyingProperties Target="#signature-1216050695-35956125-21395" xmlns:etsi="http://uri.etsi.org/01903/v1.1.1#"> +		<etsi:SignedProperties> +		  <etsi:SignedSignatureProperties> +			 <etsi:SigningTime>2008-07-14T15:51:35Z</etsi:SigningTime> +			 <etsi:SigningCertificate> +				<etsi:Cert> +				  <etsi:CertDigest> +					 <etsi:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> +					 <etsi:DigestValue>inMYWBmAxMHP7mDENjLFaEtv0Zk=</etsi:DigestValue> +				  </etsi:CertDigest> +				  <etsi:IssuerSerial> +					 <dsig:X509IssuerName>CN=a-sign-Premium-Sig-02,OU=a-sign-Premium-Sig-02,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT</dsig:X509IssuerName> +					 <dsig:X509SerialNumber>132292</dsig:X509SerialNumber> +				  </etsi:IssuerSerial> +				</etsi:Cert> +			 </etsi:SigningCertificate> +			 <etsi:SignaturePolicyIdentifier> +				<etsi:SignaturePolicyImplied/> +			 </etsi:SignaturePolicyIdentifier> +		  </etsi:SignedSignatureProperties> +		  <etsi:SignedDataObjectProperties> +			 <etsi:DataObjectFormat ObjectReference="#signed-data-reference-0-1216050695-35956125-19584"> +				<etsi:MimeType>application/xhtml+xml</etsi:MimeType> +			 </etsi:DataObjectFormat> +		  </etsi:SignedDataObjectProperties> +		</etsi:SignedProperties> +	 </etsi:QualifyingProperties> +  </dsig:Object> +</dsig:Signature>
\ No newline at end of file diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_MultipleStartEvents.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_MultipleStartEvents.xml new file mode 100644 index 000000000..17fa17cb4 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_MultipleStartEvents.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess2" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:StartEvent id="start1" /> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" class="at.gv.egovernment.moa.id.process.test.HalloWeltTask" /> +	<tns:Task id="task3" /> + +	<tns:StartEvent id="start2" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start1" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="task3" /> +	<tns:Transition from="task3" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_NoStartEvents.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_NoStartEvents.xml new file mode 100644 index 000000000..008309e3a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_NoStartEvents.xml @@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:EndEvent id="end" /> + +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionLoop.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionLoop.xml new file mode 100644 index 000000000..14b281192 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionLoop.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> + +	<!-- Must be loop since we have no conditionExpression set. --> +	<tns:Transition id="loop" from="task1" to="task1" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionRefsTransition.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionRefsTransition.xml new file mode 100644 index 000000000..1152f3503 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionRefsTransition.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition id="invalidTransition" from="task1" to="fromStart" /> +	<tns:Transition from="task2" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionStartsFromEndEvent.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionStartsFromEndEvent.xml new file mode 100644 index 000000000..94bd25c9a --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/InvalidProcessDefinition_TransitionStartsFromEndEvent.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> +	<tns:Transition from="end" to="task1" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition1.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition1.xml new file mode 100644 index 000000000..c161900c5 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition1.xml @@ -0,0 +1,18 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess1" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" /> + +	<tns:StartEvent id="start" /> +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="end" /> +	 +</tns:ProcessDefinition> diff --git a/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition2.xml b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition2.xml new file mode 100644 index 000000000..9e419e124 --- /dev/null +++ b/id/server/idserverlib/src/test/resources/at/gv/egovernment/moa/id/process/test/SampleProcessDefinition2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<tns:ProcessDefinition +	id="SampleProcess2" +	xmlns:tns="http://reference.e-government.gv.at/namespace/moa/process/definition/v1" +	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +	xsi:schemaLocation="http://reference.e-government.gv.at/namespace/moa/process/definition/v1 ../../main/resources/at/gv/egovernment/moa/id/process/ProcessDefinition.xsd "> + +	<tns:StartEvent id="start" /> + +	<tns:Task id="task1" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task2" async="true" class="at.gv.egovernment.moa.id.process.test.HelloWorldTask" /> +	<tns:Task id="task3" /> + +	<tns:EndEvent id="end" /> + +	<tns:Transition id="fromStart" from="start" to="task1" conditionExpression="true" /> +	<tns:Transition from="task1" to="task2" /> +	<tns:Transition from="task2" to="task3" /> +	<tns:Transition from="task3" to="end" /> +	 +</tns:ProcessDefinition> | 
