diff options
Diffstat (limited to 'id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java')
-rw-r--r-- | id/server/idserverlib/src/main/java/at/gv/egovernment/moa/id/protocols/pvp2x/PVP2XProtocol.java | 233 |
1 files changed, 152 insertions, 81 deletions
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 639b8672b..d04480ff5 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 iaik.pkcs.pkcs11.objects.Object; +import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -31,59 +32,66 @@ import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.xml.transform.TransformerException; import org.apache.commons.lang.StringEscapeUtils; import org.joda.time.DateTime; import org.opensaml.common.xml.SAMLConstants; +import org.opensaml.saml2.core.AttributeQuery; import org.opensaml.saml2.core.AuthnRequest; -import org.opensaml.saml2.core.Conditions; -import org.opensaml.saml2.core.EncryptedAssertion; -import org.opensaml.saml2.core.RequestAbstractType; +import org.opensaml.saml2.core.Issuer; +import org.opensaml.saml2.core.LogoutRequest; +import org.opensaml.saml2.core.LogoutResponse; +import org.opensaml.saml2.core.NameID; 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.encryption.Decrypter; -import org.opensaml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolver; import org.opensaml.saml2.metadata.AssertionConsumerService; import org.opensaml.saml2.metadata.AttributeConsumingService; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.SPSSODescriptor; -import org.opensaml.xml.encryption.ChainingEncryptedKeyResolver; -import org.opensaml.xml.encryption.DecryptionException; -import org.opensaml.xml.encryption.InlineEncryptedKeyResolver; -import org.opensaml.xml.encryption.SimpleRetrievalMethodEncryptedKeyResolver; -import org.opensaml.xml.security.keyinfo.StaticKeyInfoCredentialResolver; -import org.opensaml.xml.security.x509.X509Credential; +import org.opensaml.xml.io.MarshallingException; +import org.opensaml.xml.signature.SignableXMLObject; + +import edu.emory.mathcs.backport.java.util.Arrays; 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.MOAIDException; import at.gv.egovernment.moa.id.auth.exception.ProtocolNotActiveException; +import at.gv.egovernment.moa.id.auth.exception.WrongParametersException; 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.IAction; import at.gv.egovernment.moa.id.moduls.IModulInfo; import at.gv.egovernment.moa.id.moduls.IRequest; import at.gv.egovernment.moa.id.moduls.NoPassivAuthenticationException; import at.gv.egovernment.moa.id.moduls.RequestImpl; 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.config.PVPConfiguration; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AssertionValidationExeption; +import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.AttributQueryException; 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.signer.CredentialProvider; -import at.gv.egovernment.moa.id.protocols.pvp2x.signer.CredentialsNotAvailableException; 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.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; +import at.gv.egovernment.moa.id.storage.AuthenticationSessionStoreage; +import at.gv.egovernment.moa.id.util.ParamValidatorUtils; import at.gv.egovernment.moa.id.util.VelocityLogAdapter; import at.gv.egovernment.moa.logging.Logger; @@ -96,18 +104,27 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { public static final String POST = "Post"; public static final String SOAP = "Soap"; public static final String METADATA = "Metadata"; + public static final String ATTRIBUTEQUERY = "AttributeQuery"; private static List<IDecoder> decoder = new ArrayList<IDecoder>(); private static HashMap<String, IAction> actions = new HashMap<String, IAction>(); + @SuppressWarnings("unchecked") + public static final List<String> DEFAULTREQUESTEDATTRFORINTERFEDERATION = Arrays.asList( + new String[] { + PVPConstants.EID_SECTOR_FOR_IDENTIFIER_NAME + }); + static { decoder.add(new PostBinding()); decoder.add(new RedirectBinding()); + decoder.add(new SoapBinding()); actions.put(REDIRECT, new AuthenticationAction()); actions.put(POST, new AuthenticationAction()); actions.put(METADATA, new MetadataAction()); + actions.put(ATTRIBUTEQUERY, new AttributQueryAction()); //TODO: insert getArtifact action @@ -179,9 +196,22 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { } - if (msg instanceof MOARequest) + if (msg instanceof MOARequest && + ((MOARequest)msg).getSamlRequest() instanceof AuthnRequest) return preProcessAuthRequest(request, response, (MOARequest) msg); + else if (msg instanceof MOARequest && + ((MOARequest)msg).getSamlRequest() instanceof AttributeQuery) + return preProcessAttributQueryRequest(request, response, (MOARequest) msg); + + else if (msg instanceof MOARequest && + ((MOARequest)msg).getSamlRequest() instanceof LogoutRequest) + return preProcessLogOut(request, response, (MOARequest) msg); + + else if (msg instanceof MOARequest && + ((MOARequest)msg).getSamlRequest() instanceof LogoutResponse) + return preProcessLogOut(request, response, (MOARequest) msg); + else if (msg instanceof MOAResponse) { //load service provider AuthRequest from session @@ -192,12 +222,17 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { MOAResponse processedMsg = preProcessAuthResponse((MOAResponse) msg); if ( processedMsg != null ) { - iReqSP.setInterfederationResponse((MOAResponse) msg); + iReqSP.setInterfederationResponse(processedMsg); } else { Logger.info("Receive NO valid SSO session from " + msg.getEntityID() - +". Switch to local authentication process ..."); - iReqSP.setRequestedIDP(null); + +". Switch to local authentication process ..."); + + SSOManager ssomanager = SSOManager.getInstance(); + ssomanager.removeInterfederatedSSOIDP(msg.getEntityID(), request); + + iReqSP.setRequestedIDP(null); + } return iReqSP; @@ -206,11 +241,8 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { Logger.error("Stored PVP21 authrequest from service provider has an unsuppored type."); return null; - - } - - - else { + + } else { Logger.error("Receive unsupported PVP21 message"); throw new MOAIDException("Unsupported PVP21 message", new Object[] {}); } @@ -273,16 +305,27 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { samlResponse.setStatus(status); String remoteSessionID = SAML2Utils.getSecureIdentifier(); samlResponse.setID(remoteSessionID); - + + samlResponse.setIssueInstant(new DateTime()); + Issuer nissuer = SAML2Utils.createSAMLObject(Issuer.class); + nissuer.setValue(PVPConfiguration.getInstance().getIDPPublicPath()); + nissuer.setFormat(NameID.ENTITY); + samlResponse.setIssuer(nissuer); + IEncoder encoder = null; - if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { + if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { encoder = new RedirectBinding(); - } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_ARTIFACT_BINDING_URI)) { + + } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_ARTIFACT_BINDING_URI)) { // TODO: not supported YET!! //binding = new ArtifactBinding(); + } else if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_POST_BINDING_URI)) { encoder = new PostBinding(); + + } else if (pvpRequest.getBinding().equals(SAMLConstants.SAML2_SOAP11_BINDING_URI)) { + encoder = new SoapBinding(); } if(encoder == null) { @@ -323,10 +366,75 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { return true; } + + /** + * PreProcess Single LogOut request + * @param request + * @param response + * @param msg + * @return + */ + private IRequest preProcessLogOut(HttpServletRequest request, + HttpServletResponse response, MOARequest msg) { + // TODO Auto-generated method stub + return null; + } + + /** + * PreProcess AttributeQuery request + * @param request + * @param response + * @param moaRequest + * @return + * @throws Throwable + */ + private IRequest preProcessAttributQueryRequest(HttpServletRequest request, + HttpServletResponse response, MOARequest moaRequest) throws Throwable { + + AttributeQuery attrQuery = (AttributeQuery) moaRequest.getSamlRequest(); + moaRequest.setEntityID(attrQuery.getIssuer().getValue()); + + //validate destination + String destinaten = attrQuery.getDestination(); + if (!PVPConfiguration.getInstance().getIDPAttributeQueryService().equals(destinaten)) { + Logger.warn("AttributeQuery destination does not match IDP AttributeQueryService URL"); + throw new AttributQueryException("AttributeQuery destination does not match IDP AttributeQueryService URL", null); + + } + + //check if Issuer is an interfederation IDP + // check parameter + if (!ParamValidatorUtils.isValidOA(moaRequest.getEntityID())) + throw new WrongParametersException("StartAuthentication", + PARAM_OA, "auth.12"); + + OAAuthParameter oa = AuthConfigurationProvider.getInstance().getOnlineApplicationParameter(moaRequest.getEntityID()); + if (!oa.isInderfederationIDP()) { + Logger.warn("AttributeQuery requests are only allowed for interfederation IDPs."); + throw new AttributQueryException("AttributeQuery requests are only allowed for interfederation IDPs.", null); + + } + + PVPTargetConfiguration config = new PVPTargetConfiguration(); + config.setRequest(moaRequest); + config.setOAURL(moaRequest.getEntityID()); + config.setBinding(SAMLConstants.SAML2_SOAP11_BINDING_URI); + + return config; + } + + /** + * PreProcess Authn request + * @param request + * @param response + * @param moaRequest + * @return + * @throws Throwable + */ private IRequest preProcessAuthRequest(HttpServletRequest request, HttpServletResponse response, MOARequest moaRequest) throws Throwable { - RequestAbstractType samlReq = moaRequest.getSamlRequest(); + SignableXMLObject samlReq = moaRequest.getSamlRequest(); if(!(samlReq instanceof AuthnRequest)) { throw new MOAIDException("Unsupported request", new Object[] {}); @@ -398,6 +506,7 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { } /** + * PreProcess AuthResponse and Assertion * @param msg */ private MOAResponse preProcessAuthResponse(MOAResponse msg) { @@ -406,67 +515,29 @@ public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { try { if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.SUCCESS_URI)) { - List<org.opensaml.saml2.core.Assertion> saml2assertions = new ArrayList<org.opensaml.saml2.core.Assertion>(); - //check encrypted Assertion - List<EncryptedAssertion> encryAssertionList = samlResp.getEncryptedAssertions(); - if (encryAssertionList != null && encryAssertionList.size() > 0) { - //decrypt assertions - - Logger.debug("Found encryped assertion. Start decryption ..."); - - X509Credential authDecCredential = CredentialProvider.getIDPAssertionEncryptionCredential(); - - StaticKeyInfoCredentialResolver skicr = - new StaticKeyInfoCredentialResolver(authDecCredential); - - ChainingEncryptedKeyResolver encryptedKeyResolver = new ChainingEncryptedKeyResolver(); - encryptedKeyResolver.getResolverChain().add( new InlineEncryptedKeyResolver() ); - encryptedKeyResolver.getResolverChain().add( new EncryptedElementTypeEncryptedKeyResolver() ); - encryptedKeyResolver.getResolverChain().add( new SimpleRetrievalMethodEncryptedKeyResolver() ); - - Decrypter samlDecrypter = - new Decrypter(null, skicr, encryptedKeyResolver); - - for (EncryptedAssertion encAssertion : encryAssertionList) { - saml2assertions.add(samlDecrypter.decrypt(encAssertion)); - - } - - Logger.debug("Assertion decryption finished. "); - - } else { - saml2assertions = samlResp.getAssertions(); - - } + //validate PVP 2.1 assertion + SAMLVerificationEngine.validateAssertion(samlResp, true); + + msg.setSAMLMessage(SAML2Utils.asDOMDocument(samlResp).getDocumentElement()); + return msg; + + } else if (samlResp.getStatus().getStatusCode().getValue().equals(StatusCode.NO_PASSIVE_URI)) { + Logger.info("Interfederation IDP has no valid Single Sign-On session. Starting local authentication ..."); - for (org.opensaml.saml2.core.Assertion saml2assertion : saml2assertions) { - - Conditions conditions = saml2assertion.getConditions(); - DateTime notbefore = conditions.getNotBefore(); - DateTime notafter = conditions.getNotOnOrAfter(); - if ( notbefore.isAfterNow() || notafter.isBeforeNow() ) { - Logger.warn("PVP2 Assertion is out of Date"); - return null; - - } - - samlResp.getAssertions().clear(); - samlResp.getEncryptedAssertions().clear(); - samlResp.getAssertions().addAll(saml2assertions); - - msg.setSAMLMessage(samlResp.getDOM()); - return msg; - - } } + + } catch (IOException e) { + Logger.warn("Interfederation response marshaling FAILED.", e); - } catch (CredentialsNotAvailableException e) { - Logger.warn("Assertion decrypt FAILED - No Credentials", e); + } catch (MarshallingException e) { + Logger.warn("Interfederation response marshaling FAILED.", e); - } catch (DecryptionException e) { - Logger.warn("Assertion decrypt FAILED.", e); + } catch (TransformerException e) { + Logger.warn("Interfederation response marshaling FAILED.", e); + } catch (AssertionValidationExeption e) { + //error is already logged, to nothing } return null; |