/* * Copyright 2005-2014 WSO2, Inc. (http://wso2.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wso2.carbon.identity.tools.saml.validator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.opensaml.saml2.core.AuthnRequest; import org.opensaml.saml2.core.Response; import org.opensaml.xml.XMLObject; import org.wso2.carbon.identity.base.IdentityException; import org.wso2.carbon.identity.core.model.SAMLSSOServiceProviderDO; import org.wso2.carbon.identity.sso.saml.util.SAMLSSOUtil; import org.wso2.carbon.identity.tools.saml.validator.dto.GeneratedResponseDTO; import org.wso2.carbon.identity.tools.saml.validator.dto.ValidatedItemDTO; import org.wso2.carbon.identity.tools.saml.validator.processors.SAMLAuthnRequestValidator; import org.wso2.carbon.identity.tools.saml.validator.processors.SAMLResponseBuilder; import org.wso2.carbon.identity.tools.saml.validator.util.SAMLValidatorConstants; import org.wso2.carbon.identity.tools.saml.validator.util.SAMLValidatorUtil; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; public class SAMLValidatorService { private static Log log = LogFactory.getLog(SAMLValidatorService.class); public ValidatedItemDTO[] validateAuthnRequest(String samlRequest, boolean isPost) { List<ValidatedItemDTO> validatedItems = new ArrayList<ValidatedItemDTO>(); XMLObject request; String decodedRequest = null; String queryString = null; if (isPost) { try { decodedRequest = SAMLSSOUtil.decodeForPost(samlRequest); validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, true, SAMLValidatorConstants.ValidationMessage.VAL_DECODE_SUCCESS)); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, false, SAMLValidatorConstants.ValidationMessage.VAL_DECODE_FAIL)); } } else { boolean isExtractSuccess = false; queryString = SAMLValidatorUtil.getQueryString(samlRequest); if (queryString != null && !queryString.isEmpty()) { try { samlRequest = SAMLValidatorUtil.getSAMLRequestFromURL(samlRequest); isExtractSuccess = samlRequest != null ? true : false; } catch (UnsupportedEncodingException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, false, SAMLValidatorConstants.ValidationMessage.VAL_DECODE_QUERY_STRING_FAIL)); } } else { validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, false, SAMLValidatorConstants.ValidationMessage.VAL_EXTRACT_SAML_REQ_FAIL)); } if (isExtractSuccess && samlRequest != null) { try { decodedRequest = SAMLSSOUtil.decode(samlRequest); validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, true, SAMLValidatorConstants.ValidationMessage.VAL_DECODE_SUCCESS)); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, false, SAMLValidatorConstants.ValidationMessage.VAL_DECODE_FAIL)); } } else { validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_DECODE, false, SAMLValidatorConstants.ValidationMessage.VAL_DECODE_FAIL)); } } if (decodedRequest == null) { return validatedItems.toArray(new ValidatedItemDTO[validatedItems.size()]); } else { try { request = SAMLSSOUtil.unmarshall(decodedRequest); validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_UNMARSHAL, true, SAMLValidatorConstants.ValidationMessage.VAL_UNMARSHAL_SUCCESS)); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_UNMARSHAL, false, SAMLValidatorConstants.ValidationMessage.VAL_UNMARSHAL_FAIL)); if (isPost) { if (isDecodeableAsRedirect(samlRequest)) { validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_WRONG_BINDING, false, SAMLValidatorConstants.ValidationMessage.VAL_WRONG_BINDING_MSG)); } } return validatedItems.toArray(new ValidatedItemDTO[validatedItems.size()]); } } if (request instanceof AuthnRequest) { SAMLAuthnRequestValidator authnRequestValidator = new SAMLAuthnRequestValidator( (AuthnRequest) request); authnRequestValidator.setPost(isPost); authnRequestValidator.setQueryString(queryString); try { authnRequestValidator.validate(validatedItems); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } return validatedItems.toArray(new ValidatedItemDTO[validatedItems.size()]); } } else { validatedItems.add(new ValidatedItemDTO( SAMLValidatorConstants.ValidationType.VAL_UNMARSHAL, false, SAMLValidatorConstants.ValidationMessage.VAL_AUTHN_REQUEST_FAIL)); return validatedItems.toArray(new ValidatedItemDTO[validatedItems.size()]); } return validatedItems.toArray(new ValidatedItemDTO[validatedItems.size()]); } public GeneratedResponseDTO buildResponse(String issuer, String userName) { if (issuer == null || issuer.isEmpty() || userName == null || userName.isEmpty()) { return new GeneratedResponseDTO( false, SAMLValidatorConstants.ErrorMessage.ERROR_INCOMPLETE_DATA); } SAMLSSOServiceProviderDO ssoIdPConfigs = null; String xmlResponse = null; String encodeResponse = null; try { ssoIdPConfigs = SAMLValidatorUtil.getServiceProviderConfig(issuer); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } return new GeneratedResponseDTO( false, String.format(SAMLValidatorConstants.ErrorMessage.ERROR_CONFIG_NOT_AVAIL, issuer)); } SAMLResponseBuilder responseBuilder = new SAMLResponseBuilder(); try { Response reponse = responseBuilder.buildSAMLResponse(ssoIdPConfigs, userName); if (reponse != null) { xmlResponse = SAMLSSOUtil.marshall(reponse); encodeResponse = SAMLSSOUtil.encode(xmlResponse); } } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } return new GeneratedResponseDTO( false, String.format(SAMLValidatorConstants.ErrorMessage.ERROR_BUILD_FAIL, e.getMessage())); } return new GeneratedResponseDTO(true, null, xmlResponse, encodeResponse); } public String[] getIssuersOfSAMLServiceProviders() { try { return SAMLValidatorUtil.getIssuersOfSAMLServiceProviders(); } catch (IdentityException e) { if (log.isDebugEnabled()) { log.debug(e.getMessage()); } } return null; } private boolean isDecodeableAsRedirect(String samlRequest) { String decodedRequest = null; try { decodedRequest = SAMLSSOUtil.decode(samlRequest); } catch (IdentityException e) { return false; } if (decodedRequest != null && !decodedRequest.isEmpty()) { try { SAMLSSOUtil.unmarshall(decodedRequest); return true; } catch (IdentityException e) { return false; } } return false; } }