/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2007 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: AttributeQueryUtil.java,v 1.11 2009/07/24 22:51:48 madan_ranganath Exp $
*
* Portions copyright 2010-2016 ForgeRock AS.
*/
/**
* This class provides methods to send or process <code>AttributeQuery</code>.
*
* @supported.api
*/
public class AttributeQueryUtil {
"urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified";
static {
try {
} catch (SAML2Exception se) {
}
}
private AttributeQueryUtil() {
}
/**
* Sends the <code>AttributeQuery</code> to specified
* attribute authority and returns <code>Response</code> coming
* from the attribute authority.
*
* @param attrQuery the <code>AttributeQuery</code> object
* @param attrAuthorityEntityID entity ID of attribute authority
* @param realm the realm of hosted entity
* @param attrQueryProfile the attribute query profile or null to ignore
* @param attrProfile the attribute profile
* @param binding the binding
*
* @return the <code>Response</code> object
* @exception SAML2Exception if the operation is not successful
*
* @supported.api
*/
try {
} catch (SAML2MetaException sme) {
sme);
throw new SAML2Exception(
}
throw new SAML2Exception(
}
throw new SAML2Exception(
}
throw new SAML2Exception(
}
} else {
throw new SAML2Exception(
}
}
/**
* Sends the <code>AttributeQuery</code> to specified
* attribute authority and returns <code>Response</code> coming
* from the attribute authority.
*
* @param attrQuery the <code>AttributeQuery</code> object
* @param request the HTTP Request
* @param response the HTTP Response
* @param attrAuthorityEntityID entity ID of attribute authority
* @param realm the realm of hosted entity
* @param attrQueryProfile the attribute query profile or null to ignore
* @param attrProfile the attribute profile
* @param binding the binding
*
* @exception SAML2Exception if the operation is not successful
*
* @supported.api
*/
try {
} catch (SAML2MetaException sme) {
sme);
throw new SAML2Exception(
}
throw new SAML2Exception(
}
throw new SAML2Exception(
}
throw new SAML2Exception(
}
} else {
throw new SAML2Exception(
}
}
/**
* Processes the <code>AttributeQuery</code> coming
* from a requester.
*
* @param attrQuery the <code>AttributeQuery</code> object
* @param request the <code>HttpServletRequest</code> object
* @param response the <code>HttpServletResponse</code> object
* @param attrAuthorityEntityID entity ID of attribute authority
* @param realm the realm of hosted entity
* @param attrQueryProfileAlias the attribute query profile alias
*
* @return the <code>Response</code> object
* @exception SAML2Exception if the operation is not successful
*/
try {
} catch(SAML2Exception se) {
"processAttributeQuery: ", se);
}
}
try {
} catch(SAML2Exception se) {
se);
}
try {
} catch (SAML2MetaException sme) {
sme);
}
}
try {
} catch (SAML2Exception se) {
"processAttributeQuery: ", se);
}
}
"processAttributeQuery: unable to find identity.");
}
}
// Addition to support changing of desired attributes list
if (desiredAttrs == null) {
}
try {
} catch (SAML2Exception se) {
}
}
try {
} catch (SAML2Exception se) {
"AttributeQueryUtil.processAttributeQuery:", se);
}
}
if (encryptedID != null) {
try {
} catch (SAML2Exception se) {
"AttributeQueryUtil.processAttributeQuery:", se);
}
}
} else {
}
return samlResp;
}
/**
* Converts attribute query profile alias to attribute query profile.
*
* @param attrQueryProfileAlias attribute query profile alias
*
* @return attribute query profile
*/
if (attrQueryProfileAlias == null) {
return null;
} else if (attrQueryProfileAlias.equals(
} else if (attrQueryProfileAlias.equals(
}
return null;
}
if (signingKey == null) {
throw new SAML2Exception(
}
if (includeCert) {
}
if (signingKey != null) {
}
}
"attrQueryIssuerInvalid"));
}
} else {
"attrQueryIssuerInvalid"));
}
}
/**
* Checks if the attribute query signature is valid.
*
* @param attrQuery attribute query
* @param attrAuthorityEntityID entity ID of attribute authority
* @param realm the realm of hosted entity
*
* @exception SAML2Exception if the attribute query signature is not valid.
*/
throws SAML2Exception {
"attrQueryNotSigned"));
}
"attrQueryIssuerNotFound"));
}
if (!signingCerts.isEmpty()) {
"AttributeQueryUtil.verifyAttributeQuery: " +
"Signature validity is : " + valid);
}
if (!valid) {
"invalidSignatureAttrQuery"));
}
} else {
throw new SAML2Exception(
}
}
throws SAML2Exception {
if (encryptedID != null) {
} else {
}
"unsupportedAttrQuerySubjectNameID"));
}
"x509SubjectMappingNotConfigured"));
}
"AttributeQueryUtil.getIdentityFromDataStoreX509Subject: " +
"mappingAttrName = " + mappingAttrName +
", X509 subject DN = " + x509SubjectDN);
}
try {
} catch (DataStoreProviderException dse) {
"AttributeQueryUtil.getIdentityFromDataStoreX509Subject:",dse);
}
}
if (encryptedID != null) {
} else {
}
// NameIDFormat is "transient"
} else
// NameIDFormat is "unspecified"
break;
}
}
}
try {
} catch (DataStoreProviderException dse) {
"AttributeQueryUtil.getIdentityFromDataStore1:", dse);
}
} else {
try {
} catch (DataStoreProviderException dse) {
"AttributeQueryUtil.getIdentityFromDataStore:", dse);
}
}
}
throws SAML2Exception {
"AttributeQueryUtil.getUserAttributes: " +
"remote SP attribute map = " + configMap);
}
"AttributeQueryUtil.getUserAttributes:" +
"Configuration map is not defined.");
}
return null;
}
"AttributeQueryUtil.getUserAttributes: " +
"hosted IDP attribute map=" + configMap);
}
}
try {
} catch (DataStoreProviderException dse) {
"AttributeQueryUtil.getUserAttributes:", dse);
}
}
"AttributeQueryUtil.getUserAttributes:" +
" user profile does not have value for " +
}
} else {
localAttributeValues = (String[])
}
}
if ((localAttributeValues == null) ||
"AttributeQueryUtil.getUserAttributes:" +
" user does not have " + localAttribute);
}
continue;
}
}
return attributes;
}
throws SAML2Exception {
if (signingKey == null) {
throw new SAML2Exception(
}
if (includeCert) {
}
if (signingKey != null) {
}
}
}
return assertion;
}
throws SAML2Exception {
if (includeCert) {
}
if (signingKey != null) {
}
}
throws SAML2Exception {
"EncryptedAssertion");
}
return desiredAttrs;
}
return convertAttributes(supportedAttrs);
}
boolean isAttrValid = false;
while (supportedAttrIterator.hasNext()) {
isAttrValid = true;
//By removing the attribute from the supported list we make sure that an AttributeQuery can
//not request the same Attribute more than once, see SAML core 3.3.2.3.
break;
} else {
throw new SAML2Exception("Attribute value not supported");
}
}
}
if (!isAttrValid) {
throw new SAML2Exception("Attribute name not supported");
}
}
return desiredAttrs;
}
throws SAML2Exception {
}
}
}
}
}
return resultAttrs;
}
private static List<Attribute> filterAttributes(List<Attribute> attributes, List<Attribute> desiredAttrs) {
return attributes;
}
return attributes;
}
if (!desiredAttrs.isEmpty()) {
//let's copy FriendlyName if exists
try {
} catch (SAML2Exception e) {
//do nothing, attribute will be sent without
//friendlyName set
}
}
}
break;
}
}
}
}
return returnAttributes;
}
}
return attr;
}
return null;
}
}
}
if (newValuesD.isEmpty()) {
return null;
}
return desiredAttr;
}
try {
return newAttr;
} catch(SAML2Exception se) {
"AttributeQueryUtil.filterAttributeValues:", se);
}
return null;
}
}
}
/**
* Determines whether the desired Attribute NameFormat matches with the available attribute's NameFormat. When
* the NameFormat isn't specified in the request, the
* <code>urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</code> default NameFormat needs to be used (see
* SAML core spec 2.7.3.1).
* The different attribute profiles (SAML profiles spec section 8) each determine how the attribute comparison
* should be performed, however there is no clear way to actually determine which attribute profile is being used
* when the Attribute Authority supports more than one profile. Because of this, the unspecified Attribute
* NameFormat has been implemented as a wildcard match, much similarly to how requesting the unspecified
* NameID-Format allows the IdP to choose an arbitrary NameID-Format when generating the assertion for an SP.
*
* @param desiredNameFormat The NameFormat of the Attribute defined in the AttributeQuery request.
* @param availableNameFormat The NameFormat of the Attribute defined in the server configuration.
* @return <code>true</code> if the desired NameFormat is unspecified, or if it is the same as the NameFormat
* defined in the server configuration.
*/
}
return true;
}
return true;
}
}
try {
"AttributeQueryUtil.isValueValid:", ex);
}
return false;
}
}
"AttributeQueryUtil.sendAttributeQuerySOAP: " +
"attrQueryXMLString = " + attrQueryXMLString);
"AttributeQueryUtil.sendAttributeQuerySOAP: " +
"attributeServiceURL = " + attributeServiceURL);
}
try {
attributeServiceURL, true);
} catch (SOAPException se) {
"AttributeQueryUtil.sendAttributeQuerySOAP: ", se);
throw new SAML2Exception(
}
"AttributeQueryUtil.sendAttributeQuerySOAP: " +
}
"AttributeQueryUtil.sendAttributeQuerySOAP: " +
}
return response;
}
throws SAML2Exception {
if ((attrQueryID != null) &&
throw new SAML2Exception(
}
if (respIssuer == null) {
return;
}
"responseIssuerMismatch"));
}
"responseNotSigned"));
}
if (!signingCerts.isEmpty()) {
"AttributeQueryUtil.verifyResponse: " +
"Signature validity is : " + valid);
}
if (!valid) {
"invalidSignatureOnResponse"));
}
} else {
throw new SAML2Exception(
}
}
if (attrProfile != null) {
SAML2Utils.debug.message("AttributeQueryUtil.findLocation: attrProfiles is null or empty and attrProfile is null");
return null;
}
SAML2Utils.debug.message("AttributeQueryUtil.findLocation: attrProfile not found in the attrProfiles");
return null;
}
attrQueryProfile)) {
return attrService.getLocation();
}
}
SAML2Utils.debug.message("AttributeQueryUtil.findLocation: nothing found, leaving last line with null");
return null;
}
return false;
}
if (attrQueryProfile == null) {
return false;
}
return ((attrQueryProfile.equals(
}
/**
* Returns an <code>AttributeAuthorityMapper</code>
*
* @param realm the realm name
* @param attrAuthorityEntityID the entity id of the attribute authority
* @param attrQueryProfileAlias attribute profile alias
*
* @return the <code>AttributeAuthorityMapper</code>
* @exception SAML2Exception if the operation is not successful
*/
throws SAML2Exception {
try {
if (attrAuthorityMapperName == null) {
"AttributeQueryUtil.getAttributeAuthorityMapper: use "+
}
}
if (attrAuthorityMapper == null) {
} else {
"AttributeQueryUtil.getAttributeAuthorityMapper: " +
"got the AttributeAuthorityMapper from cache");
}
}
"AttributeQueryUtil.getAttributeAuthorityMapper: " +
"Unable to get IDP Attribute Mapper.", ex);
throw new SAML2Exception(ex);
}
return attrAuthorityMapper;
}
{
try {
}
return value;
} catch (SAML2MetaException sme) {
"getAttributeValueFromAttrAuthorityConfig: " +
"get AttributeAuthorityConfig failed", sme);
}
}
return null;
}
/**
* Sends the AttributeQuery to specified attribute authority,
* validates the response and returns the attribute map
* <code>Map<String, String></code> to the Fedlet
*
* @param spEntityID SP entity ID
* @param idpEntityID IDP entity ID
* @param nameIDValue NameID value
* @param attrsList The list of attributes whose values need to be
* fetched from IDP
* @param attrQueryProfileAlias Attribute Query Profile Alias
* @param subjectDN Attribute name which contains X.509 subject DN
*
* @return the <code>Map</code> object
* @exception SAML2Exception if the operation is not successful
*
* @deprecated Use {@link #getAttributesForFedlet(String, String, String, List, String, String)}
*/
throws SAML2Exception {
Map<String, Set<String>> attrMap = getAttributesForFedlet(spEntityID, idpEntityID, nameIDValue, attrsList,
// Multiple attribute values
// are seperated with "|"
}
}
}
return newAttrMap;
}
/**
* Sends the AttributeQuery to specified attribute authority,
* validates the response and returns the attribute map
* <code>Map<String, Set<String>></code> to the Fedlet
*
* @param spEntityID SP entity ID
* @param idpEntityID IDP entity ID
* @param nameIDValue NameID value
* @param attrsList The list of attributes whose values need to be
* fetched from IDP
* @param attrQueryProfileAlias Attribute Query Profile Alias
* @param subjectDN Attribute name which contains X.509 subject DN
*
* @return the <code>Map</code> object
* @exception SAML2Exception if the operation is not successful
*
* @supported.api
*/
public static Map<String, Set<String>> getAttributesForFedlet(String spEntityID, String idpEntityID,
throws SAML2Exception {
if (attrQueryConfig == null) {
}
return null;
}
if (attrqMetaAlias == null) {
}
return null;
}
AttributeQuery attrQuery = constructAttrQueryForFedlet(spEntityID, idpEntityID, nameIDValue, attrsList,
}
// Validate the response
if (validResp) {
// Return back the AttributeMap
if (wantNameIDEncrypted) {
} else {
}
if (wantNameIDEncrypted) {
} else {
}
}
} else {
}
}
} else {
}
}
}
}
}
} else {
}
}
// Return the attribute map and to the fedlet
return attrMap;
}
private static Map<String, Set<String>> mapAttributes(String realm, String spEntityID, String idpEntityID,
}
/**
* Constructs the Attribute Query used by the Fedlet to retrieve the
* values from IDP
*
* @param samlResp saml response
*
* @exception SAML2Exception if the operation is not successful
*
* @supported.api
*/
boolean wantNameIDEncrypted) throws SAML2Exception
{
}
}
}
if (!wantNameIDEncrypted) {
} else {
}
return attrQuery;
}
/**
* Validates the SAML response obtained from Attribute Authortity
*
* @param samlResp saml response
*
* @exception SAML2Exception if the operation is not successful
*
* @supported.api
*/
private static boolean validateSAMLResponseForFedlet(
boolean wantNameIDEncrypted) throws SAML2Exception
{
boolean resp = true;
if (wantNameIDEncrypted) {
} else {
}
if (assertions == null) {
return false;
}
if (wantNameIDEncrypted) {
} else {
}
if (conditions != null) {
resp = false;
break;
}
}
resp = false;
break;
}
}
}
} else {
resp = false;
}
return resp;
}
/**
* Returns the decrypted assertion
*
* @param samlResp saml response
*
* @exception SAML2Exception if the operation is not successful
*
* @supported.api
*/
{
if (eAssertion != null) {
return eAssertion.decrypt(KeyUtil.getDecryptionKeys("/", spEntityID, SAML2Constants.ATTR_QUERY_ROLE));
}
return null;
}
}