diff options
Diffstat (limited to 'id/server/idserverlib')
6 files changed, 244 insertions, 74 deletions
| 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 34366b790..d58b7b267 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 @@ -54,6 +54,7 @@ import at.gv.egovernment.moa.id.moduls.ModulStorage;  import at.gv.egovernment.moa.id.moduls.NoPassivAuthenticationException;  import at.gv.egovernment.moa.id.moduls.RequestStorage;  import at.gv.egovernment.moa.id.moduls.SSOManager; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AuthnRequestValidatorException;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.storage.DBExceptionStoreImpl;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; @@ -320,7 +321,12 @@ public class DispatcherServlet extends AuthServlet{  						resp.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());  						return; -						 +					} catch (AuthnRequestValidatorException e) { +						//log Error Message +						StatisticLogger logger = StatisticLogger.getInstance(); +						logger.logErrorOperation(e, e.getErrorRequest());						 +						return; +											  					} catch (MOAIDException e) {  						Logger.error("Failed to generate a valid protocol request!");  						resp.setContentType("text/html;charset=UTF-8"); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java index e5158f4bf..804688de5 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java @@ -40,6 +40,7 @@ import org.opensaml.saml2.core.Response;  import org.opensaml.saml2.core.Status;  import org.opensaml.saml2.core.StatusCode;  import org.opensaml.saml2.core.StatusMessage; +import org.opensaml.saml2.core.impl.AuthnRequestImpl;  import org.opensaml.saml2.metadata.AssertionConsumerService;  import org.opensaml.saml2.metadata.AttributeConsumingService;  import org.opensaml.saml2.metadata.EntityDescriptor; @@ -58,11 +59,14 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.MOARequest;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.PostBinding;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AuthnRequestValidatorException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotHandleAbleException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NameIDFormatNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.CheckMandateAttributes;  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils; +import at.gv.egovernment.moa.id.protocols.pvp2x.validation.AuthnRequestValidator;  import at.gv.egovernment.moa.id.protocols.pvp2x.verification.SAMLVerificationEngine;  import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory;  import at.gv.egovernment.moa.id.util.VelocityLogAdapter; @@ -169,7 +173,7 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  			if(!(samlReq instanceof AuthnRequest)) {  				throw new MOAIDException("Unsupported request", new Object[] {});  			} -			 +						  			EntityDescriptor metadata = moaRequest.getEntityMetadata();  			if(metadata == null) {  				throw new NoMetadataInformationException(); @@ -203,7 +207,7 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  					spSSODescriptor.getAttributeConsumingServices().size() > 0) {  				attributeConsumer  = spSSODescriptor.getAttributeConsumingServices().get(attributeIdx);  			}  -			 +						  			String oaURL = moaRequest.getEntityMetadata().getEntityID();  			String binding = consumerService.getBinding();  //			String entityID = moaRequest.getEntityMetadata().getEntityID(); @@ -225,11 +229,30 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  					}  				}  			} -			 -			request.getSession().setAttribute(PARAM_OA, oaURL); +			//validate AuthnRequest +			try { +				AuthnRequestValidator.validate((AuthnRequestImpl) samlReq); +				 +			} catch (AuthnRequestValidatorException e) { +				if (generateErrorMessage(e, request, response, config)) { +					throw new AuthnRequestValidatorException(e.getMessage(),  +							new Object[] {}, config); +					 +				} else { +					throw new MOAIDException(e.getMessage(), new Object[] {}); +	 +				}			 +			} + +			request.getSession().setAttribute(PARAM_OA, oaURL); +			  			return config; -		} catch (Exception e) { + +		} catch (PVP2Exception e) { +			throw e; +			 +		} catch (Throwable e) {  			e.printStackTrace();  			throw new MOAIDException(e.getMessage(), new Object[] {});  		} @@ -256,6 +279,11 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  		if(e instanceof NoPassivAuthenticationException) {  			statusCode.setValue(StatusCode.NO_PASSIVE_URI);  			statusMessage.setMessage(e.getLocalizedMessage());	 +			 +		} else if (e instanceof NameIDFormatNotSupportedException) { +			statusCode.setValue(StatusCode.INVALID_NAMEID_POLICY_URI); +			statusMessage.setMessage(e.getLocalizedMessage()); +			  		} else if(e instanceof PVP2Exception) {  			PVP2Exception ex = (PVP2Exception) e;  			statusCode.setValue(ex.getStatusCodeValue()); @@ -263,6 +291,7 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants {  			if(statusMessageValue != null) {  				statusMessage.setMessage(statusMessageValue);  			} +			  		} else {  			statusCode.setValue(StatusCode.RESPONDER_URI);  			statusMessage.setMessage(e.getLocalizedMessage()); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java index bc90da8df..e834797b1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/builder/assertion/PVP2AssertionBuilder.java @@ -22,6 +22,7 @@   *******************************************************************************/  package at.gv.egovernment.moa.id.protocols.pvp2x.builder.assertion; +import java.security.MessageDigest;  import java.util.Iterator;  import java.util.List; @@ -43,6 +44,7 @@ import org.opensaml.saml2.core.RequestedAuthnContext;  import org.opensaml.saml2.core.Subject;  import org.opensaml.saml2.core.SubjectConfirmation;  import org.opensaml.saml2.core.SubjectConfirmationData; +import org.opensaml.saml2.core.impl.AuthnRequestImpl;  import org.opensaml.saml2.metadata.AssertionConsumerService;  import org.opensaml.saml2.metadata.AttributeConsumingService;  import org.opensaml.saml2.metadata.EntityDescriptor; @@ -75,7 +77,9 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.UnprovideableAttribut  import at.gv.egovernment.moa.id.protocols.pvp2x.utils.SAML2Utils;  import at.gv.egovernment.moa.id.util.MandateBuilder;  import at.gv.egovernment.moa.id.util.QAALevelVerifier; +import at.gv.egovernment.moa.id.util.Random;  import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.Base64Utils;  import at.gv.egovernment.moa.util.Constants;  public class PVP2AssertionBuilder implements PVPConstants { @@ -95,54 +99,55 @@ public class PVP2AssertionBuilder implements PVPConstants {  						peerEntity.getEntityID());  		if (reqAuthnContext == null) { -			 authnContextClassRef.setAuthnContextClassRef(STORK_QAA_1_4); +			 authnContextClassRef.setAuthnContextClassRef(authSession.getQAALevel()); -		} +		} else { -		boolean stork_qaa_1_4_found = false; +			boolean stork_qaa_1_4_found = false; -		 List<AuthnContextClassRef> reqAuthnContextClassRefIt = reqAuthnContext -				.getAuthnContextClassRefs(); +			List<AuthnContextClassRef> reqAuthnContextClassRefIt = reqAuthnContext +					.getAuthnContextClassRefs(); -		 if (reqAuthnContextClassRefIt.size() == 0) { +			if (reqAuthnContextClassRefIt.size() == 0) { -			 QAALevelVerifier.verifyQAALevel(authSession.getQAALevel(),  -					 STORK_QAA_1_4); +				QAALevelVerifier.verifyQAALevel(authSession.getQAALevel(),  +						STORK_QAA_1_4); -			 stork_qaa_1_4_found = true; -			 authnContextClassRef.setAuthnContextClassRef(STORK_QAA_1_4); +				stork_qaa_1_4_found = true; +				authnContextClassRef.setAuthnContextClassRef(STORK_QAA_1_4); -		 } else { -			 for (AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) { -				 String qaa_uri = authnClassRef.getAuthnContextClassRef(); -				 if (qaa_uri.trim().equals(STORK_QAA_1_4) -						 || qaa_uri.trim().equals(STORK_QAA_1_3) -						 || qaa_uri.trim().equals(STORK_QAA_1_2) -						 || qaa_uri.trim().equals(STORK_QAA_1_1)) { +			} else { +				for (AuthnContextClassRef authnClassRef : reqAuthnContextClassRefIt) { +					String qaa_uri = authnClassRef.getAuthnContextClassRef(); +					if (qaa_uri.trim().equals(STORK_QAA_1_4) +							|| qaa_uri.trim().equals(STORK_QAA_1_3) +							|| qaa_uri.trim().equals(STORK_QAA_1_2) +							|| qaa_uri.trim().equals(STORK_QAA_1_1)) { -					 if (authSession.isForeigner()) { -						 QAALevelVerifier.verifyQAALevel(authSession.getQAALevel(),  -								 STORK_QAA_PREFIX + oaParam.getQaaLevel()); -						  -						 stork_qaa_1_4_found = true; -						 authnContextClassRef.setAuthnContextClassRef(authSession.getQAALevel()); -						  -					 } else { -						  -						 QAALevelVerifier.verifyQAALevel(authSession.getQAALevel(),  -								 qaa_uri.trim()); -						  -						 stork_qaa_1_4_found = true; -						 authnContextClassRef.setAuthnContextClassRef(authSession.getQAALevel()); -						 							  +						 if (authSession.isForeigner()) { +							 QAALevelVerifier.verifyQAALevel(authSession.getQAALevel(),  +									 STORK_QAA_PREFIX + oaParam.getQaaLevel()); +							  +							 stork_qaa_1_4_found = true; +							 authnContextClassRef.setAuthnContextClassRef(authSession.getQAALevel()); +							  +						 } else { +							  +							 QAALevelVerifier.verifyQAALevel(authSession.getQAALevel(),  +									 qaa_uri.trim()); +							  +							 stork_qaa_1_4_found = true; +							 authnContextClassRef.setAuthnContextClassRef(authSession.getQAALevel()); +							 							  +						 } +						 break;  					 } -					 break;  				 }  			 } -		 } - -		if (!stork_qaa_1_4_found) { -			throw new QAANotSupportedException(STORK_QAA_1_4); +	 +			if (!stork_qaa_1_4_found) { +				throw new QAANotSupportedException(STORK_QAA_1_4); +			}  		}  //		reqAuthnContextClassRefIt = reqAuthnContext.getAuthnContextClassRefs() @@ -196,33 +201,6 @@ public class PVP2AssertionBuilder implements PVPConstants {  				.createSAMLObject(AttributeStatement.class);  		Subject subject = SAML2Utils.createSAMLObject(Subject.class); -		NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); -		boolean foundFormat = false; - -		// TL: AuthData generation is moved to Assertion generation. - -		Iterator<NameIDFormat> formatIt = spSSODescriptor.getNameIDFormats() -				.iterator(); -		while (formatIt.hasNext()) { -			if (formatIt.next().getFormat().equals(NameID.PERSISTENT)) { -				foundFormat = true; -				break; -			} -		} -		if (!foundFormat) { -			// TODO use correct exception -			throw new NameIDFormatNotSupportedException(""); -		} - -		// TODO: Check if we need to hide source pin -		/* -		 * if(authSession.getUseMandate()) { Element mandate = -		 * authSession.getMandate(); if(authSession.getBusinessService()) { // -		 * Hide Source PIN! ParepUtils.HideStammZahlen(mandate, true, null, -		 * authSession.getDomainIdentifier(), true); } else { -		 * ParepUtils.HideStammZahlen(mandate, false, authSession.getTarget(), -		 * null, true); } } -		 */  		AuthenticationData authData = AuthenticationServer  				.buildAuthenticationData(authSession, oaParam, @@ -263,9 +241,9 @@ public class PVP2AssertionBuilder implements PVPConstants {  		if (attributeStatement.getAttributes().size() > 0) {  			assertion.getAttributeStatements().add(attributeStatement);  		} - -		subjectNameID.setFormat(NameID.PERSISTENT); +		NameID subjectNameID = SAML2Utils.createSAMLObject(NameID.class); +  		//TLenz: set correct bPK Type and Value from AuthData  		if (authSession.getUseMandate()) {  			Element mandate = authSession.getMandate(); @@ -295,6 +273,7 @@ public class PVP2AssertionBuilder implements PVPConstants {  			String bpktype = id.getType();  			String bpk = id.getValue().getValue(); +			  			if (bpktype.equals(Constants.URN_PREFIX_BASEID)) {  				if (authSession.getBusinessService()) {						      					subjectNameID.setValue(new BPKBuilder().buildWBPK(bpk, oaParam.getIdentityLinkDomainIdentifier())); @@ -322,7 +301,43 @@ public class PVP2AssertionBuilder implements PVPConstants {  			subjectNameID.setValue(authData.getBPK());  		} - +		String nameIDFormat = NameID.TRANSIENT; +		 +		//get NameIDFormat from request		 +		AuthnRequest authnReq = (AuthnRequestImpl) authnRequest; +		if (authnReq.getNameIDPolicy() != null) { +			nameIDFormat = authnReq.getNameIDPolicy().getFormat(); +			 +		} else { +			//get NameIDFormat from metadata +			List<NameIDFormat> metadataNameIDFormats = spSSODescriptor.getNameIDFormats(); +			 +			if (metadataNameIDFormats != null) { +				if (metadataNameIDFormats.size() == 1) +					nameIDFormat = metadataNameIDFormats.get(0).getFormat(); +				 +			} +		} +	 +		if (NameID.TRANSIENT.equals(nameIDFormat) || NameID.UNSPECIFIED.equals(nameIDFormat)) { +			String random = Random.nextRandom(); +			String nameID = subjectNameID.getValue(); +			 +			try { +				MessageDigest md = MessageDigest.getInstance("SHA-1"); +				byte[] hash = md.digest((nameID + random).getBytes("ISO-8859-1"));			 +				subjectNameID.setValue(Base64Utils.encode(hash)); +				subjectNameID.setFormat(NameID.TRANSIENT); +				 +			} catch (Exception e) { +				Logger.warn("PVP2 subjectNameID error", e); +				throw new MOAIDException("pvp2.13", null, e); +			} +			 +		} else  +			subjectNameID.setFormat(nameIDFormat);			 +		 +		  		subject.setNameID(subjectNameID);  		SubjectConfirmation subjectConfirmation = SAML2Utils diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnRequestValidatorException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnRequestValidatorException.java new file mode 100644 index 000000000..7ed438471 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/AuthnRequestValidatorException.java @@ -0,0 +1,62 @@ +/* + * 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; + +import at.gv.egovernment.moa.id.moduls.IRequest; + +/** + * @author tlenz + * + */ +public class AuthnRequestValidatorException extends PVP2Exception { + +	private IRequest errorRequest = null; +	 +	/** +	 *  +	 */ +	private static final long serialVersionUID = 4939651000658508576L; + +	/** +	 * @param messageId +	 * @param parameters +	 */ +	public AuthnRequestValidatorException(String messageId, Object[] parameters) { +		super(messageId, parameters); +		 +	} +	 +	public AuthnRequestValidatorException(String messageId, Object[] parameters, IRequest errorRequest) { +		super(messageId, parameters); +		this.errorRequest = errorRequest; +		 +	} + +	/** +	 * @return the errorRequest +	 */ +	public IRequest getErrorRequest() { +		return errorRequest; +	} + +} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NameIDFormatNotSupportedException.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NameIDFormatNotSupportedException.java index 5a393062f..b5facde34 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NameIDFormatNotSupportedException.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/exceptions/NameIDFormatNotSupportedException.java @@ -22,7 +22,7 @@   *******************************************************************************/  package at.gv.egovernment.moa.id.protocols.pvp2x.exceptions; -public class NameIDFormatNotSupportedException extends PVP2Exception { +public class NameIDFormatNotSupportedException extends AuthnRequestValidatorException {  	public NameIDFormatNotSupportedException(String nameIDFormat) {  		super("pvp2.12", new Object[] {nameIDFormat}); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AuthnRequestValidator.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AuthnRequestValidator.java new file mode 100644 index 000000000..ab8fab5d1 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AuthnRequestValidator.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.validation; + +import org.opensaml.saml2.core.AuthnRequest; +import org.opensaml.saml2.core.NameID; +import org.opensaml.saml2.core.NameIDPolicy; + +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AuthnRequestValidatorException; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NameIDFormatNotSupportedException; + +/** + * @author tlenz + * + */ +public class AuthnRequestValidator { + +	public static void validate(AuthnRequest req) throws AuthnRequestValidatorException{ + +		//validate NameIDPolicy +		NameIDPolicy nameIDPolicy = req.getNameIDPolicy(); +		if (nameIDPolicy != null) { +			String nameIDFormat = nameIDPolicy.getFormat(); +			 +			if ( !(nameIDFormat != null && +					(NameID.TRANSIENT.equals(nameIDFormat) || +							NameID.PERSISTENT.equals(nameIDFormat) || +							NameID.UNSPECIFIED.equals(nameIDFormat))) ) { +			 +				throw new NameIDFormatNotSupportedException(nameIDFormat); +				 +			} +		} +		 +		 +		 +	} +} | 
