diff options
Diffstat (limited to 'id/server')
12 files changed, 405 insertions, 72 deletions
| 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 dc4d7845b..514430b23 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 @@ -134,12 +134,13 @@ public class AuthenticationDataBuilder extends MOAIDAuthConstants {  		AuthenticationData authdata = null;		 -		try {			 +		try { +			//check if SAML1 authentication module is in Classpath  			Class<?> saml1RequstTemplate = Class.forName("at.gv.egovernment.moa.id.protocols.saml1.SAML1RequestImpl");  			IAuthData saml1authdata = (IAuthData) Class.forName("at.gv.egovernment.moa.id.protocols.saml1.SAML1AuthenticationData").newInstance();			  			if (saml1RequstTemplate != null &&   					saml1RequstTemplate.isInstance(protocolRequest)) {				 -				//request is SAML1 +				//request is SAML1  --> invoke SAML1 protocol specific methods   				if (session.getExtendedSAMLAttributesOA() == null) {  					saml1authdata.getClass().getMethod("setExtendedSAMLAttributesOA", List.class).invoke(saml1authdata, new ArrayList<ExtendedSAMLAttribute>()); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java index b7148a318..fe5cd1ac0 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/auth/servlet/IDPSingleLogOutServlet.java @@ -63,6 +63,23 @@ public class IDPSingleLogOutServlet extends AuthServlet {  	protected void doGet(HttpServletRequest req, HttpServletResponse resp)  			    throws ServletException, IOException {  		Logger.debug("receive IDP SingleLogOut Request"); +		 +		String authURL = HTTPUtils.extractAuthURLFromRequest(req); +		try { +			if (!AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix().contains(authURL)) {		 +				Logger.warn("Requested URL " + authURL + " is not in PublicPrefix Configuration"); +				resp.sendError(HttpServletResponse.SC_FORBIDDEN, "Request not allowed"); +				return; +			 +			} +			 +		} catch (MOAIDException e) { +			Logger.error("Internal Server Error.", e); +			resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Internal Server Error"); +			return; +			 +		} +		  		SSOManager ssomanager = SSOManager.getInstance();		  		String ssoid = ssomanager.getSSOSessionID(req); @@ -110,7 +127,7 @@ public class IDPSingleLogOutServlet extends AuthServlet {  						AuthenticationSession authSession = AuthenticationSessionStoreage  								.getSession(moaSessionID);  						if(authSession != null) { -							authmanager.performSingleLogOut(req, resp, authSession, null); +							authmanager.performSingleLogOut(req, resp, authSession, authURL);  							return;  						} 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 0fec742b1..8122d2b1c 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 @@ -71,6 +71,7 @@ import at.gv.egovernment.moa.id.auth.data.AuthenticationSession;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSessionExtensions;  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.InvalidProtocolRequestException;  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.commons.db.dao.session.InterfederationSessionStore; @@ -95,6 +96,8 @@ 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.pvp2x.verification.SAMLVerificationEngine; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory;  import at.gv.egovernment.moa.id.storage.AssertionStorage;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.util.MOAIDMessageProvider; @@ -164,7 +167,20 @@ public class AuthenticationManager extends MOAIDAuthConstants {  	}  	public void performSingleLogOut(HttpServletRequest httpReq, -	HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException {		 +	HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq) throws MOAIDException { +		performSingleLogOut(httpReq, httpResp, session, pvpReq, null); +		 +	} +	 +	public void performSingleLogOut(HttpServletRequest httpReq, +	HttpServletResponse httpResp, AuthenticationSession session, String authURL) throws MOAIDException { +		performSingleLogOut(httpReq, httpResp, session, null, authURL); +		 +	} +	 +	 +	private void performSingleLogOut(HttpServletRequest httpReq, +	HttpServletResponse httpResp, AuthenticationSession session, PVPTargetConfiguration pvpReq, String authURL) throws MOAIDException {		  		String pvpSLOIssuer = null;  		String inboundRelayState = null; @@ -173,6 +189,7 @@ public class AuthenticationManager extends MOAIDAuthConstants {  			LogoutRequest logOutReq = (LogoutRequest) samlReq.getSamlRequest();  			pvpSLOIssuer = logOutReq.getIssuer().getValue();  			inboundRelayState = samlReq.getRelayState(); +			  		}  		SSOManager ssomanager = SSOManager.getInstance(); @@ -216,8 +233,13 @@ public class AuthenticationManager extends MOAIDAuthConstants {  							+ " FAILED. NO LogOut response received.");  					sloContainer.putFailedOA(sloReq.getIssuer().getValue()); +				} else { +					SAMLVerificationEngine engine = new SAMLVerificationEngine(); +					engine.verifySLOResponse(sloResp,  +							TrustEngineFactory.getSignatureKnownKeysTrustEngine()); +					  				} -				 +								  				SingleLogOutBuilder.checkStatusCode(sloContainer, sloResp);  			} catch (SOAPException e) { @@ -225,7 +247,7 @@ public class AuthenticationManager extends MOAIDAuthConstants {  						+ " FAILED.", e);  				sloContainer.putFailedOA(sloReq.getIssuer().getValue()); -			} catch (SecurityException e) { +			} catch (SecurityException | InvalidProtocolRequestException e) {  				Logger.warn("Single LogOut for OA " + sloReq.getIssuer().getValue()  						+ " FAILED.", e);  				sloContainer.putFailedOA(sloReq.getIssuer().getValue()); @@ -255,7 +277,10 @@ public class AuthenticationManager extends MOAIDAuthConstants {  				AssertionStorage.getInstance().put(relayState, sloContainer); -				String timeOutURL = pvpReq.getAuthURL() +				if (MiscUtil.isEmpty(authURL)) +					authURL = pvpReq.getAuthURL(); +				 +				String timeOutURL = authURL  						+ "/idpSingleLogout"  						+ "?restart=" + relayState; 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 544fd9925..6ed3f0eb5 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 @@ -24,6 +24,7 @@ package at.gv.egovernment.moa.id.protocols.pvp2x;  import java.io.IOException;  import java.util.ArrayList; +import java.util.Arrays;  import java.util.HashMap;  import java.util.Iterator;  import java.util.List; @@ -55,8 +56,6 @@ import org.opensaml.xml.io.MarshallingException;  import org.opensaml.xml.security.SecurityException;  import org.opensaml.xml.signature.SignableXMLObject; -import java.util.Arrays; -  import at.gv.egovernment.moa.id.advancedlogging.MOAIDEventConstants;  import at.gv.egovernment.moa.id.advancedlogging.MOAReversionLogger;  import at.gv.egovernment.moa.id.advancedlogging.TransactionIDUtils; @@ -76,12 +75,9 @@ import at.gv.egovernment.moa.id.moduls.RequestStorage;  import at.gv.egovernment.moa.id.moduls.SSOManager;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IDecoder;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.SoapBinding; -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;  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.binding.SoapBinding;  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.AttributQueryException; @@ -92,6 +88,9 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NameIDFormatNotSuppor  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.exceptions.SLOException; +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;  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; @@ -232,7 +231,7 @@ public class PVP2XProtocol extends MOAIDAuthConstants implements IModulInfo  {  				SAMLVerificationEngine engine = new SAMLVerificationEngine();  				engine.verify(msg, TrustEngineFactory.getSignatureKnownKeysTrustEngine());  				msg.setVerified(true); -				 +								  			}  			if (msg instanceof MOARequest &&  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 911197a05..d405e71dc 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 @@ -23,42 +23,20 @@  package at.gv.egovernment.moa.id.protocols.pvp2x;  import java.io.Serializable; -import java.io.StringWriter;  import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator;  import java.util.List; -import java.util.Map.Entry;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;  import org.apache.commons.lang.SerializationUtils; -import org.apache.velocity.Template; -import org.apache.velocity.VelocityContext; -import org.apache.velocity.app.VelocityEngine;  import org.hibernate.HibernateException;  import org.hibernate.Query;  import org.hibernate.Session;  import org.hibernate.Transaction; -import org.opensaml.common.SAMLObject; -import org.opensaml.common.binding.BasicSAMLMessageContext; -import org.opensaml.common.xml.SAMLConstants;  import org.opensaml.saml2.core.LogoutRequest;  import org.opensaml.saml2.core.LogoutResponse; -import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.Status; -import org.opensaml.saml2.core.StatusCode; -import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.metadata.SingleLogoutService; -import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder; -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.opensaml.xml.security.x509.X509Credential;  import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants;  import at.gv.egovernment.moa.id.auth.data.AuthenticationSession; @@ -67,35 +45,22 @@ import at.gv.egovernment.moa.id.auth.exception.MOAIDException;  import at.gv.egovernment.moa.id.auth.servlet.RedirectServlet;  import at.gv.egovernment.moa.id.commons.db.MOASessionDBUtils;  import at.gv.egovernment.moa.id.commons.db.dao.session.AssertionStore; -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; -import at.gv.egovernment.moa.id.config.auth.AuthConfigurationProviderFactory;  import at.gv.egovernment.moa.id.data.IAuthData;  import at.gv.egovernment.moa.id.data.SLOInformationContainer; -import at.gv.egovernment.moa.id.data.SLOInformationImpl;  import at.gv.egovernment.moa.id.data.SLOInformationInterface;  import at.gv.egovernment.moa.id.moduls.AuthenticationManager;  import at.gv.egovernment.moa.id.moduls.IAction;  import at.gv.egovernment.moa.id.moduls.IRequest;  import at.gv.egovernment.moa.id.moduls.SSOManager; -import at.gv.egovernment.moa.id.opemsaml.MOAStringRedirectDeflateEncoder; -import at.gv.egovernment.moa.id.protocols.pvp2x.binding.IEncoder; -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.builder.SingleLogOutBuilder; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.SLOException;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.utils.MOASAMLSOAPClient;  import at.gv.egovernment.moa.id.storage.AssertionStorage;  import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage;  import at.gv.egovernment.moa.id.util.Random; -import at.gv.egovernment.moa.id.util.VelocityProvider;  import at.gv.egovernment.moa.logging.Logger; -import at.gv.egovernment.moa.util.MessageProvider;  import at.gv.egovernment.moa.util.MiscUtil;  import at.gv.egovernment.moa.util.URLEncoder; @@ -275,7 +240,7 @@ public class SingleLogOutAction implements IAction {  								}								  								//redirect to Redirect Servlet -								String url = AuthConfigurationProviderFactory.getInstance().getPublicURLPrefix() + "/RedirectServlet"; +								String url = req.getAuthURL() + "/RedirectServlet";  								url = addURLParameter(url, RedirectServlet.REDIRCT_PARAM_URL, URLEncoder.encode(redirectURL, "UTF-8"));  								url = httpResp.encodeRedirectURL(url); diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java index 1e0a9cf32..8a6b09376 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/PostBinding.java @@ -32,27 +32,25 @@ import org.opensaml.common.xml.SAMLConstants;  import org.opensaml.saml2.binding.decoding.HTTPPostDecoder;  import org.opensaml.saml2.binding.encoding.HTTPPostEncoder;  import org.opensaml.saml2.core.RequestAbstractType; -import org.opensaml.saml2.core.Response;  import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.metadata.IDPSSODescriptor;  import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.saml2.metadata.SingleLogoutService;  import org.opensaml.saml2.metadata.SingleSignOnService;  import org.opensaml.saml2.metadata.impl.SingleSignOnServiceBuilder;  import org.opensaml.ws.message.decoder.MessageDecodingException;  import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.ws.security.SecurityPolicyResolver; +import org.opensaml.ws.security.provider.BasicSecurityPolicy; +import org.opensaml.ws.security.provider.StaticSecurityPolicyResolver;  import org.opensaml.ws.transport.http.HttpServletRequestAdapter;  import org.opensaml.ws.transport.http.HttpServletResponseAdapter;  import org.opensaml.xml.parse.BasicParserPool;  import org.opensaml.xml.security.SecurityException; -import org.opensaml.xml.security.credential.Credential; -import org.opensaml.xml.security.x509.KeyStoreX509CredentialAdapter;  import org.opensaml.xml.security.x509.X509Credential;  import at.gv.egovernment.moa.id.config.ConfigurationException;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol;  import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessage;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; @@ -60,6 +58,8 @@ import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOAResponse;  import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider;  import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialProvider;  import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; +import at.gv.egovernment.moa.id.protocols.pvp2x.validation.MOAPVPSignedRequestPolicyRule; +import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory;  import at.gv.egovernment.moa.id.util.HTTPUtils;  import at.gv.egovernment.moa.id.util.VelocityProvider;  import at.gv.egovernment.moa.logging.Logger; @@ -164,7 +164,16 @@ public class PostBinding implements IDecoder, IEncoder {  		}  		messageContext.setMetadataProvider(MOAMetadataProvider.getInstance()); -				 +		 +		//set security policy context +		BasicSecurityPolicy policy = new BasicSecurityPolicy(); +		policy.getPolicyRules().add( +				new MOAPVPSignedRequestPolicyRule( +						TrustEngineFactory.getSignatureKnownKeysTrustEngine(), +						messageContext.getPeerEntityRole()));		 +		SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy); +		messageContext.setSecurityPolicyResolver(secResolver); +		  		decode.decode(messageContext);  		InboundMessage msg = null;		 @@ -190,8 +199,9 @@ public class PostBinding implements IDecoder, IEncoder {  			if (MiscUtil.isEmpty(msg.getEntityID()))  				Logger.info("No Metadata found for OA with EntityID " + messageContext.getInboundMessageIssuer());  		} -		 -		msg.setVerified(false); +				 + +		msg.setVerified(true);  		msg.setRelayState(messageContext.getRelayState());  		return msg; diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java index a2583c706..2ef861e20 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/binding/SoapBinding.java @@ -36,7 +36,6 @@ import org.opensaml.saml2.core.StatusResponseType;  import org.opensaml.saml2.metadata.SPSSODescriptor;  import org.opensaml.ws.message.decoder.MessageDecodingException;  import org.opensaml.ws.message.encoder.MessageEncodingException; -import org.opensaml.ws.soap.client.BasicSOAPMessageContext;  import org.opensaml.ws.soap.soap11.Envelope;  import org.opensaml.ws.soap.soap11.decoder.http.HTTPSOAP11Decoder;  import org.opensaml.ws.transport.http.HttpServletRequestAdapter; @@ -49,7 +48,6 @@ import org.opensaml.xml.signature.SignableXMLObject;  import at.gv.egovernment.moa.id.protocols.pvp2x.PVP2XProtocol;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; -import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.PVP2Exception;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.InboundMessageInterface;  import at.gv.egovernment.moa.id.protocols.pvp2x.messages.MOARequest; @@ -70,9 +68,23 @@ public class SoapBinding implements IDecoder, IEncoder {  		messageContext  				.setInboundMessageTransport(new HttpServletRequestAdapter(  						req));		 -		//messageContext.setPeerEntityRole(SPSSODescriptor.DEFAULT_ELEMENT_NAME);  		messageContext.setMetadataProvider(MOAMetadataProvider.getInstance()); -				 + +		//TODO: update in a futher version:  +		//      requires a special SignedSOAPRequestPolicyRole because  +		//		messageContext.getInboundMessage() is not directly signed +		 +		//set security context +//		BasicSecurityPolicy policy = new BasicSecurityPolicy(); +//		policy.getPolicyRules().add( +//				new MOAPVPSignedRequestPolicyRule( +//						TrustEngineFactory.getSignatureKnownKeysTrustEngine(), +//						SPSSODescriptor.DEFAULT_ELEMENT_NAME));		 +//		SecurityPolicyResolver resolver = new StaticSecurityPolicyResolver( +//				policy);			 +//		messageContext.setSecurityPolicyResolver(resolver); +		 +		//decode message  		soapDecoder.decode(messageContext);  		Envelope inboundMessage = (Envelope) messageContext 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 df68a1029..dbbc21ec9 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 @@ -27,8 +27,11 @@ import java.util.List;  import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory;  import org.joda.time.DateTime; +import org.opensaml.Configuration;  import org.opensaml.common.SAMLObject;  import org.opensaml.common.binding.BasicSAMLMessageContext;  import org.opensaml.common.impl.SecureRandomIdentifierGenerator; @@ -43,15 +46,18 @@ 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;  import org.opensaml.saml2.metadata.impl.SingleLogoutServiceBuilder;  import org.opensaml.saml2.metadata.provider.MetadataProviderException;  import org.opensaml.ws.message.encoder.MessageEncodingException; +import org.opensaml.xml.io.Marshaller;  import org.opensaml.xml.security.SecurityException;  import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.signature.Signature; +import org.opensaml.xml.signature.SignatureConstants; +import org.opensaml.xml.signature.Signer; +import org.w3c.dom.Document;  import at.gv.egovernment.moa.id.auth.exception.AuthenticationException;  import at.gv.egovernment.moa.id.auth.exception.MOAIDException; @@ -63,7 +69,6 @@ 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;  import at.gv.egovernment.moa.id.protocols.pvp2x.binding.RedirectBinding; -import at.gv.egovernment.moa.id.protocols.pvp2x.config.PVPConfiguration;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.BindingNotSupportedException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NOSLOServiceDescriptorException;  import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.NoMetadataInformationException; @@ -228,7 +233,35 @@ public class SingleLogOutBuilder {  		nameID.setFormat(sloInfo.getUserNameIDFormat());  		nameID.setValue(sloInfo.getUserNameIdentifier());  		sloReq.setNameID(nameID ); -				 + +		//sign message +		try { +			X509Credential idpSigningCredential = CredentialProvider.getIDPAssertionSigningCredential(); +		 +			Signature signer = SAML2Utils.createSAMLObject(Signature.class); +			signer.setSignatureAlgorithm(SignatureConstants.ALGO_ID_SIGNATURE_RSA_SHA256); +			signer.setCanonicalizationAlgorithm(SignatureConstants.ALGO_ID_C14N_EXCL_OMIT_COMMENTS); +			signer.setSigningCredential(idpSigningCredential); +			sloReq.setSignature(signer); + +			DocumentBuilder builder; +			DocumentBuilderFactory factory = DocumentBuilderFactory +					.newInstance(); + +			builder = factory.newDocumentBuilder(); +			Document document = builder.newDocument(); +			Marshaller out = Configuration.getMarshallerFactory() +					.getMarshaller(sloReq); +			out.marshall(sloReq, document); + +			Signer.signObject(signer); +		 +		} catch (Exception e) { +			Logger.error("Single LogOut request signing FAILED!", e); +			throw new MOAIDException("pvp2.19", null); +			 +		} +		  		return sloReq;		  	} diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java index 4d12c38da..75ef7e5a1 100644 --- a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/utils/MOASAMLSOAPClient.java @@ -57,6 +57,15 @@ public class MOASAMLSOAPClient {  		BasicSOAPMessageContext soapContext = new BasicSOAPMessageContext();  		soapContext.setOutboundMessage(soapRequest); + +		//set security policy context +//		BasicSecurityPolicy policy = new BasicSecurityPolicy(); +//		policy.getPolicyRules().add( +//				new MOAPVPSignedRequestPolicyRule( +//						TrustEngineFactory.getSignatureKnownKeysTrustEngine(), +//						SPSSODescriptor.DEFAULT_ELEMENT_NAME));		 +//		SecurityPolicyResolver secResolver = new StaticSecurityPolicyResolver(policy); +//		soapContext.setSecurityPolicyResolver(secResolver);  		HttpClientBuilder clientBuilder = new HttpClientBuilder();  		if (destination.startsWith("https")) { diff --git a/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AbstractRequestSignedSecurityPolicyRule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AbstractRequestSignedSecurityPolicyRule.java new file mode 100644 index 000000000..31e960d59 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/AbstractRequestSignedSecurityPolicyRule.java @@ -0,0 +1,184 @@ +/* + * 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 javax.xml.namespace.QName; +import javax.xml.transform.dom.DOMSource; +import javax.xml.validation.Schema; +import javax.xml.validation.Validator; + +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.common.xml.SAMLSchemaBuilder; +import org.opensaml.security.MetadataCriteria; +import org.opensaml.security.SAMLSignatureProfileValidator; +import org.opensaml.ws.message.MessageContext; +import org.opensaml.ws.security.SecurityPolicyException; +import org.opensaml.ws.security.SecurityPolicyRule; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.security.CriteriaSet; +import org.opensaml.xml.security.credential.UsageType; +import org.opensaml.xml.security.criteria.EntityIDCriteria; +import org.opensaml.xml.security.criteria.UsageCriteria; +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.protocols.pvp2x.exceptions.SchemaValidationException; +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.util.MiscUtil; + +/** + * @author tlenz + * + */ +public abstract class AbstractRequestSignedSecurityPolicyRule implements SecurityPolicyRule { + +	private SignatureTrustEngine trustEngine = null; +	private QName peerEntityRole = null; +	/** +	 * @param peerEntityRole  +	 *  +	 */ +	public AbstractRequestSignedSecurityPolicyRule(SignatureTrustEngine trustEngine, QName peerEntityRole) { +		this.trustEngine = trustEngine; +		this.peerEntityRole = peerEntityRole; +		 +	} +	 +	 +	/** +	 * Reload the PVP metadata for a given entity +	 *  +	 * @param entityID for which the metadata should be refreshed. +	 * @return true if the refresh was successful, otherwise false +	 */ +	protected abstract boolean refreshMetadataProvider(String entityID); +	 +	 +	protected abstract SignableSAMLObject getSignedSAMLObject(XMLObject inboundData); +	 +	/* (non-Javadoc) +	 * @see org.opensaml.ws.security.SecurityPolicyRule#evaluate(org.opensaml.ws.message.MessageContext) +	 */ +	@Override +	public void evaluate(MessageContext context) throws SecurityPolicyException { +		try { +			verifySignature(context); +			 +		} catch (SecurityPolicyException e) { +			if (MiscUtil.isEmpty(context.getInboundMessageIssuer())) { +				throw e; +			 +			}			 +			Logger.debug("PVP2X message validation FAILED. Relead metadata for entityID: " + context.getInboundMessageIssuer()); +			if (!refreshMetadataProvider(context.getInboundMessageIssuer())) +				throw e; +			 +			else { +				Logger.trace("PVP2X metadata reload finished. Check validate message again.");					 +				verifySignature(context); +										 +			} +			Logger.trace("Second PVP2X message validation finished"); +			 +		} + +		 +	} + +	private void verifySignature(MessageContext context) throws SecurityPolicyException { +		SignableSAMLObject samlObj = getSignedSAMLObject(context.getInboundMessage());			 +		if (samlObj != null && samlObj.getSignature() != null) { +						 +			SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator(); +			try { +				profileValidator.validate(samlObj.getSignature());		     +				performSchemaValidation(samlObj.getDOM()); +		     +			} catch (ValidationException e) { +				Logger.warn("Signature is not conform to SAML signature profile", e); +				throw new SecurityPolicyException("Signature is not conform to SAML signature profile"); +		     +			} catch (SchemaValidationException e) { +				Logger.warn("Signature is not conform to SAML signature profile", e); +				throw new SecurityPolicyException("Signature is not conform to SAML signature profile"); +			 +			} +			 +			 +			 +			CriteriaSet criteriaSet = new CriteriaSet(); +			criteriaSet.add( new EntityIDCriteria(context.getInboundMessageIssuer()) ); +			criteriaSet.add( new MetadataCriteria(peerEntityRole, SAMLConstants.SAML20P_NS) ); +			criteriaSet.add( new UsageCriteria(UsageType.SIGNING) ); +						 +			try { +				if (!trustEngine.validate(samlObj.getSignature(), criteriaSet)) { +					throw new SecurityPolicyException("Signature validation FAILED."); +					 +				} +			} catch (org.opensaml.xml.security.SecurityException e) { +				Logger.warn("PVP2x message signature validation FAILED.", e); +				throw new SecurityPolicyException("Signature validation FAILED."); +				 +			} +			 +		} else { +			throw new SecurityPolicyException("Request is not signed."); +			 +		} +	} +	 +	private 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/validation/MOAPVPSignedRequestPolicyRule.java b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/MOAPVPSignedRequestPolicyRule.java new file mode 100644 index 000000000..932f3b818 --- /dev/null +++ b/id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/validation/MOAPVPSignedRequestPolicyRule.java @@ -0,0 +1,70 @@ +/* + * 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 javax.xml.namespace.QName; + +import org.opensaml.common.SignableSAMLObject; +import org.opensaml.xml.XMLObject; +import org.opensaml.xml.signature.SignatureTrustEngine; + +import at.gv.egovernment.moa.id.protocols.pvp2x.metadata.MOAMetadataProvider; + +/** + * @author tlenz + * + */ +public class MOAPVPSignedRequestPolicyRule extends +		AbstractRequestSignedSecurityPolicyRule { + +	/** +	 * @param trustEngine +	 * @param peerEntityRole +	 */ +	public MOAPVPSignedRequestPolicyRule(SignatureTrustEngine trustEngine, +			QName peerEntityRole) { +		super(trustEngine, peerEntityRole); +	} + +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#refreshMetadataProvider(java.lang.String) +	 */ +	@Override +	protected boolean refreshMetadataProvider(String entityID) { +		return MOAMetadataProvider.getInstance().refreshMetadataProvider(entityID); +		 +	} + +	/* (non-Javadoc) +	 * @see at.gv.egovernment.moa.id.protocols.pvp2x.validation.AbstractRequestSignedSecurityPolicyRule#getSignedSAMLObject(org.opensaml.xml.XMLObject) +	 */ +	@Override +	protected SignableSAMLObject getSignedSAMLObject(XMLObject inboundData) { +		if (inboundData instanceof SignableSAMLObject) +			return (SignableSAMLObject) inboundData; +		 +		else +			return null; +	} + +} 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 2e5f78611..812e27a36 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,6 +25,7 @@ package at.gv.egovernment.moa.id.protocols.pvp2x.verification;  import java.util.ArrayList;  import java.util.List; +import javax.xml.namespace.QName;  import javax.xml.transform.dom.DOMSource;  import javax.xml.validation.Schema;  import javax.xml.validation.Validator; @@ -62,7 +63,6 @@ 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.config.auth.AuthConfigurationProviderFactory; -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; @@ -75,7 +75,6 @@ import at.gv.egovernment.moa.logging.Logger;  import at.gv.egovernment.moa.util.MiscUtil;  public class SAMLVerificationEngine { -  	public void verify(InboundMessage msg, SignatureTrustEngine sigTrustEngine ) throws org.opensaml.xml.security.SecurityException, Exception {  		try {		 @@ -84,7 +83,7 @@ public class SAMLVerificationEngine {  				verifyRequest(((RequestAbstractType)((MOARequest)msg).getSamlRequest()), sigTrustEngine);  			else -				verifyResponse(((MOAResponse)msg).getResponse(), sigTrustEngine); +				verifyIDPResponse(((MOAResponse)msg).getResponse(), sigTrustEngine);  		} catch (InvalidProtocolRequestException e) {  			if (MiscUtil.isEmpty(msg.getEntityID())) { @@ -103,15 +102,24 @@ public class SAMLVerificationEngine {  					verifyRequest(((RequestAbstractType)((MOARequest)msg).getSamlRequest()), sigTrustEngine);  				else -					verifyResponse(((MOAResponse)msg).getResponse(), sigTrustEngine); +					verifyIDPResponse(((MOAResponse)msg).getResponse(), sigTrustEngine);  			}  			Logger.trace("Second PVP2X message validation finished");  		}		  	} +	public void verifyIDPResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine) throws InvalidProtocolRequestException{ +		verifyResponse(samlObj, sigTrustEngine, IDPSSODescriptor.DEFAULT_ELEMENT_NAME); +		 +	} +	 +	public void verifySLOResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException { +		verifyResponse(samlObj, sigTrustEngine, SPSSODescriptor.DEFAULT_ELEMENT_NAME); +		 +	} -	public void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine ) throws InvalidProtocolRequestException{ +	private void verifyResponse(StatusResponseType samlObj, SignatureTrustEngine sigTrustEngine, QName defaultElementName)  throws InvalidProtocolRequestException{  		SAMLSignatureProfileValidator profileValidator = new SAMLSignatureProfileValidator();  		try {  		    profileValidator.validate(samlObj.getSignature()); @@ -128,7 +136,7 @@ public class SAMLVerificationEngine {  		CriteriaSet criteriaSet = new CriteriaSet();  		criteriaSet.add( new EntityIDCriteria(samlObj.getIssuer().getValue()) ); -		criteriaSet.add( new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS) ); +		criteriaSet.add( new MetadataCriteria(defaultElementName, SAMLConstants.SAML20P_NS) );  		criteriaSet.add( new UsageCriteria(UsageType.SIGNING) );  		try { | 
