package at.gv.egovernment.moa.id.protocols.pvp2x; import iaik.pkcs.pkcs11.objects.Object; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.StringEscapeUtils; import org.opensaml.DefaultBootstrap; import org.opensaml.common.xml.SAMLConstants; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.RequestAbstractType; 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.metadata.AssertionConsumerService; import org.opensaml.saml2.metadata.AttributeConsumingService; import org.opensaml.saml2.metadata.EntityDescriptor; import org.opensaml.saml2.metadata.SPSSODescriptor; import org.opensaml.xml.ConfigurationException; import at.gv.egovernment.moa.id.MOAIDException; import at.gv.egovernment.moa.id.auth.MOAIDAuthConstants; import at.gv.egovernment.moa.id.auth.WrongParametersException; 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.ServletInfo; import at.gv.egovernment.moa.id.moduls.ServletType; 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.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.config.PVPConfiguration; import at.gv.egovernment.moa.id.protocols.pvp2x.exceptions.MandateAttributesNotHandleAbleException; 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.verification.SAMLVerificationEngine; import at.gv.egovernment.moa.id.protocols.pvp2x.verification.TrustEngineFactory; import at.gv.egovernment.moa.id.util.ParamValidatorUtils; public class PVP2XProtocol implements IModulInfo, MOAIDAuthConstants { public static final String NAME = PVP2XProtocol.class.getName(); public static final String PATH = "id_pvp2x"; public static final String REDIRECT = "Redirect"; public static final String POST = "Post"; public static final String SOAP = "Soap"; public static final String METADATA = "Metadata"; private static List servletList = new ArrayList(); private static List decoder = new ArrayList(); private static HashMap actions = new HashMap(); static { servletList.add(new ServletInfo(PVPProcessor.class, REDIRECT, ServletType.AUTH)); servletList.add(new ServletInfo(PVPProcessor.class, POST, ServletType.AUTH)); decoder.add(new PostBinding()); decoder.add(new RedirectBinding()); actions.put(REDIRECT, new AuthenticationAction()); actions.put(POST, new AuthenticationAction()); actions.put(METADATA, new MetadataAction()); instance = new PVP2XProtocol(); } private static PVP2XProtocol instance = null; public static PVP2XProtocol getInstance() { if (instance == null) { instance = new PVP2XProtocol(); } return instance; } public List getServlets() { return servletList; } public String getName() { return NAME; } public String getPath() { return PATH; } private IDecoder findDecoder(String action, HttpServletRequest req) { Iterator decoderIT = decoder.iterator(); while (decoderIT.hasNext()) { IDecoder decoder = decoderIT.next(); if (decoder.handleDecode(action, req)) { return decoder; } } return null; } public PVP2XProtocol() { super(); } public IRequest preProcess(HttpServletRequest request, HttpServletResponse response, String action) throws MOAIDException { if(METADATA.equals(action)) { return new PVPTargetConfiguration(); } IDecoder decoder = findDecoder(action, request); if (decoder == null) { return null; } try { PVPTargetConfiguration config = new PVPTargetConfiguration(); MOARequest moaRequest = decoder.decodeRequest(request, response); RequestAbstractType samlReq = moaRequest.getSamlRequest(); //String xml = PrettyPrinter.prettyPrint(SAML2Utils.asDOMDocument(samlReq)); //Logger.info("SAML : " + xml); if(!moaRequest.isVerified()) { SAMLVerificationEngine engine = new SAMLVerificationEngine(); engine.verifyRequest(samlReq, TrustEngineFactory.getSignatureKnownKeysTrustEngine()); moaRequest.setVerified(true); } if(!(samlReq instanceof AuthnRequest)) { throw new MOAIDException("Unsupported request", new Object[] {}); } AuthnRequest authnRequest = (AuthnRequest)samlReq; Integer aIdx = authnRequest.getAssertionConsumerServiceIndex(); int assertionidx = 0; if(aIdx != null) { assertionidx = aIdx.intValue(); } aIdx = authnRequest.getAttributeConsumingServiceIndex(); int attributeIdx = 0; if(aIdx != null) { attributeIdx = aIdx.intValue(); } EntityDescriptor metadata = moaRequest.getEntityMetadata(); if(metadata == null) { throw new NoMetadataInformationException(); } SPSSODescriptor spSSODescriptor = metadata.getSPSSODescriptor(SAMLConstants.SAML20P_NS); AssertionConsumerService consumerService = spSSODescriptor.getAssertionConsumerServices().get(assertionidx); AttributeConsumingService attributeConsumer = spSSODescriptor.getAttributeConsumingServices().get(attributeIdx); String oaURL = consumerService.getLocation(); String binding = consumerService.getBinding(); String entityID = moaRequest.getEntityMetadata().getEntityID(); //String oaURL = (String) request.getParameter(PARAM_OA); oaURL = StringEscapeUtils.escapeHtml(oaURL); if (!ParamValidatorUtils.isValidOA(oaURL)) throw new WrongParametersException("StartAuthentication", PARAM_OA, "auth.12"); config.setOAURL(oaURL); config.setBinding(binding); config.setRequest(moaRequest); config.setTarget(PVPConfiguration.getInstance().getTargetForSP(entityID)); String useMandate = request.getParameter(PARAM_USEMANDATE); if(useMandate != null) { if(useMandate.equals("true")) { if(!CheckMandateAttributes.canHandleMandate(attributeConsumer)) { throw new MandateAttributesNotHandleAbleException(); } } } request.getSession().setAttribute(PARAM_OA, oaURL); return config; } catch (Exception e) { e.printStackTrace(); throw new MOAIDException(e.getMessage(), new Object[] {}); } } public boolean generateErrorMessage(Throwable e, HttpServletRequest request, HttpServletResponse response, IRequest protocolRequest) throws Throwable { if(protocolRequest == null) { throw e; } if(!(protocolRequest instanceof PVPTargetConfiguration) ) { throw e; } PVPTargetConfiguration pvpRequest = (PVPTargetConfiguration)protocolRequest; Response samlResponse = SAML2Utils.createSAMLObject(Response.class); Status status = SAML2Utils.createSAMLObject(Status.class); StatusCode statusCode = SAML2Utils.createSAMLObject(StatusCode.class); StatusMessage statusMessage = SAML2Utils.createSAMLObject(StatusMessage.class); if(e instanceof NoPassivAuthenticationException) { statusCode.setValue(StatusCode.NO_PASSIVE_URI); statusMessage.setMessage(e.getLocalizedMessage()); } else if(e instanceof PVP2Exception) { PVP2Exception ex = (PVP2Exception) e; statusCode.setValue(ex.getStatusCodeValue()); String statusMessageValue = ex.getStatusMessageValue(); if(statusMessageValue != null) { statusMessage.setMessage(statusMessageValue); } } else { statusCode.setValue(StatusCode.RESPONDER_URI); statusMessage.setMessage(e.getLocalizedMessage()); } status.setStatusCode(statusCode); if(statusMessage.getMessage() != null) { status.setStatusMessage(statusMessage); } samlResponse.setStatus(status); IEncoder encoder = null; if(pvpRequest.getBinding().equals(SAMLConstants.SAML2_REDIRECT_BINDING_URI)) { encoder = new RedirectBinding(); } 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(); } if(encoder == null) { // default to redirect binding encoder = new RedirectBinding(); } encoder.encodeRespone(request, response, samlResponse, protocolRequest.getOAURL()); return true; } public IAction getAction(String action) { return actions.get(action); } public IAction canHandleRequest(HttpServletRequest request, HttpServletResponse response) { if(request.getParameter("SAMLRequest") != null && request.getMethod().equals("GET")) { return getAction(REDIRECT); } else if(request.getParameter("SAMLRequest") != null && request.getMethod().equals("POST")) { return getAction(POST); } if(METADATA.equals(request.getParameter("action"))) { return getAction(METADATA); } return null; } public boolean validate(HttpServletRequest request, HttpServletResponse response, IRequest pending) { // TODO implement validation! return true; } }