/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2005 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
* https://opensso.dev.java.net/public/CDDLv1.0.html or
* opensso/legal/CDDLv1.0.txt
* 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: OrgConfigViaAMSDK.java,v 1.14 2009/11/20 23:52:56 ww203982 Exp $
*
* Portions Copyrighted 2011-2015 ForgeRock AS.
*/
package com.sun.identity.sm;
import static org.forgerock.openam.ldap.LDAPUtils.*;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.RDN;
import com.iplanet.am.sdk.AMConstants;
import com.iplanet.am.sdk.AMException;
import com.iplanet.am.sdk.AMNamingAttrManager;
import com.iplanet.am.sdk.AMObject;
import com.iplanet.am.sdk.AMOrganization;
import com.iplanet.am.sdk.AMSDKBundle;
import com.iplanet.am.sdk.AMStoreConnection;
import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;
import com.sun.identity.common.CaseInsensitiveHashMap;
import com.sun.identity.common.DNUtils;
import com.sun.identity.delegation.DelegationEvaluator;
import com.sun.identity.delegation.DelegationEvaluatorImpl;
import com.sun.identity.delegation.DelegationException;
import com.sun.identity.delegation.DelegationPermission;
import com.sun.identity.idm.IdConstants;
import com.sun.identity.security.AdminTokenAction;
import com.sun.identity.shared.debug.Debug;
// This class provides support for OrganizationConfigManager
// in coexistence mode. This class interfaces with AMSDK
// to manage organization names and organization attributes.
public class OrgConfigViaAMSDK {
// Instance variables
private SSOToken token;
private String parentOrgName;
private String smsOrgName;
private AMOrganization parentOrg;
private AMOrganization parentOrgWithAdminToken;
private ServiceConfig serviceConfig;
private int objType;
// permissions for the user token
boolean hasReadPermissionOnly;
// Cache of organization names to ServiceConfig that
// contains the attribute mappings
static Map attributeMappings = new CaseInsensitiveHashMap();
static Map reverseAttributeMappings = new CaseInsensitiveHashMap();
static Map attributeMappingServiceConfigs = new HashMap();
static final String IDREPO_SERVICE = "sunidentityrepositoryservice";
static final String MAPPING_ATTR_NAME = "sunCoexistenceAttributeMapping";
// Cache of AMSDK organization names to SMS relam dn
static Map amsdkdn2realmname = new CaseInsensitiveHashMap();
static Map amsdkConfiguredRealms = new CaseInsensitiveHashMap();
// Debug & Locale
static Debug debug = SMSEntry.debug;
ResourceBundle bundle = SMSEntry.bundle;
// When DIT not migrated to AM 7.0 we need to use static mapping
static Map notMigratedAttributeMappings;
static Map notMigratedReverseAttributeMappings;
static {
if (!ServiceManager.isConfigMigratedTo70()) {
notMigratedAttributeMappings = new CaseInsensitiveHashMap();
notMigratedAttributeMappings.put("sunPreferredDomain",
"sunPreferredDomain");
notMigratedAttributeMappings.put("sunOrganizationStatus",
"inetDomainStatus");
notMigratedAttributeMappings.put("sunOrganizationAliases",
"sunOrganizationAlias");
notMigratedAttributeMappings.put("sunDNSAliases",
"associatedDomain");
notMigratedReverseAttributeMappings = new CaseInsensitiveHashMap();
notMigratedReverseAttributeMappings.put("sunPreferredDomain",
"sunPreferredDomain");
notMigratedReverseAttributeMappings.put("inetDomainStatus",
"sunOrganizationStatus");
notMigratedReverseAttributeMappings.put("sunOrganizationAlias",
"sunOrganizationAliases");
notMigratedReverseAttributeMappings.put("associatedDomain",
"sunDNSAliases");
}
}
/**
* Constructor for Realm management via AMSDK The parameter
* <code>orgName</code> must be LDAP organization name
*/
OrgConfigViaAMSDK(SSOToken token, String orgName, String smsOrgName)
throws SMSException {
this.token = token;
parentOrgName = orgName;
this.smsOrgName = smsOrgName;
// Get admin SSOToken for operations to bypass ACIs and delegation
SSOToken adminToken = (SSOToken) AccessController
.doPrivileged(AdminTokenAction.getInstance());
try {
// Check if the user has realm privileges, if yes use
// admin SSOToken to bypass directory ACIs.
// Look if the incoming request is from client or server.
// If client,(SMSJAXRPCObjectFlg=true), and since it is a JAXRPC
// call, the permission checking would be done at the server.
// So client need not have this check.(checkRealmPermission)
if (!SMSEntry.SMSJAXRPCObjectFlg) {
if (checkRealmPermission(token, smsOrgName,
SMSEntry.modifyActionSet)) {
token = adminToken;
} else if (checkRealmPermission(token, smsOrgName,
SMSEntry.readActionSet)) {
hasReadPermissionOnly = true;
}
}
AMStoreConnection amcom = new AMStoreConnection(token);
parentOrg = amcom.getOrganization(orgName);
if (hasReadPermissionOnly) {
// Construct parent org with admin token for reads
amcom = new AMStoreConnection(adminToken);
parentOrgWithAdminToken = amcom.getOrganization(orgName);
}
// Get the Realm <---> LDAP Org attribute mappings.
// To get the service config of idrepo service.
String newOrg = orgName;
if (!SMSEntry.getRootSuffix().equalsIgnoreCase(
SMSEntry.getAMSdkBaseDN())) {
newOrg = smsOrgName;
}
if (ServiceManager.isConfigMigratedTo70() &&
(serviceConfig = (ServiceConfig) attributeMappingServiceConfigs
.get(orgName)) == null) {
ServiceConfigManager scm = new ServiceConfigManager(
IDREPO_SERVICE, adminToken);
// Do we need to use internal token?
serviceConfig = scm.getOrganizationConfig(newOrg, null);
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::constructor"
+ ": serviceConfig" + serviceConfig);
}
attributeMappingServiceConfigs.put(orgName, serviceConfig);
}
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
}
/**
* Create a suborganization using AMSDK. The code checks if the DIT has been
* migrated to AM 7.0 to add the objectclass "sunRelamService".
*/
void createSubOrganization(String subOrgName) throws SMSException {
// Check if suborg exists
if (!getSubOrganizationNames(subOrgName, false).isEmpty()
|| subOrgName.startsWith(SMSEntry.SUN_INTERNAL_REALM_NAME)) {
// Sub-org already exists or it is a hidden realm
return;
}
// Create the organization
try {
if (ServiceManager.isConfigMigratedTo70()) {
Map attrs = new HashMap();
Set attrValues = new HashSet();
attrValues.add(SMSEntry.OC_REALM_SERVICE);
attrs.put(SMSEntry.ATTR_OBJECTCLASS, attrValues);
Map subOrgs = new HashMap();
subOrgs.put(subOrgName, attrs);
parentOrg.createSubOrganizations(subOrgs);
} else {
Set subOrgs = new HashSet();
subOrgs.add(subOrgName);
parentOrg.createSubOrganizations(subOrgs);
}
} catch (AMException ame) {
// Ignore if it is Organization already exists
if (!ame.getErrorCode().equals("474")) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::createSubOrganization"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame
.getMessage(), ame, ame.getMessage()));
}
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
}
/**
* Returns the set of assigned services for the organization
*/
Set getAssignedServices() throws SMSException {
try {
if (hasReadPermissionOnly) {
return (parentOrgWithAdminToken.getRegisteredServiceNames());
} else {
return (parentOrg.getRegisteredServiceNames());
}
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::getAssignedServices"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame.getMessage(),
ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
}
/**
* Assigns the service to the organization
*/
void assignService(String serviceName) throws SMSException {
try {
// Check if it is a hidden realm
if (ServiceManager.isCoexistenceMode() &&
(parentOrgName.startsWith(SMSEntry.SUN_INTERNAL_REALM_PREFIX)))
{
return;
}
// Check if service is already assigned
if (!getAssignedServices().contains(serviceName)) {
parentOrg.registerService(serviceName, false, false);
}
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::assignService"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame.getMessage(),
ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
}
/**
* Unassigns the service from the organization
*/
void unassignService(String serviceName) throws SMSException {
try {
// Check if service is already unassigned
if (getAssignedServices().contains(serviceName)) {
parentOrg.unregisterService(serviceName);
}
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::unassignService"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame.getMessage(),
ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
}
/**
* Returns sub-organization names using AMSKK APIs. The returned names are
* in "/" separated format and are normailized using DNMapper.
*/
Set getSubOrganizationNames(String pattern, boolean recursive)
throws SMSException {
try {
// Search for sub-organization names
Set subOrgDNs;
if (hasReadPermissionOnly) {
subOrgDNs = parentOrgWithAdminToken.searchSubOrganizations(
pattern, recursive ? AMConstants.SCOPE_SUB
: AMConstants.SCOPE_ONE);
} else {
subOrgDNs = parentOrg.searchSubOrganizations(pattern,
recursive ? AMConstants.SCOPE_SUB
: AMConstants.SCOPE_ONE);
}
// Convert DNs to "/" seperated relam names
if (subOrgDNs != null && !subOrgDNs.isEmpty()) {
Set subOrgs = new HashSet();
for (Iterator items = subOrgDNs.iterator(); items.hasNext();) {
subOrgs.add(DNMapper.orgNameToDN((String) items.next()));
}
return SMSEntry.parseResult(subOrgs, smsOrgName);
}
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::getSubOrganizationNames"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame.getMessage(),
ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
return (Collections.EMPTY_SET);
}
/**
* Deletes sub-organiation using AMSDK. If recursive flag is set, then all
* sub-entries are also removed. Else if sub-entries are present this will
* throw an exception.
*/
void deleteSubOrganization(String subOrgName) throws SMSException {
try {
// Check if subOrgName is empty or null
if (subOrgName == null || subOrgName.trim().length() == 0) {
if (parentOrg.isExists()) {
parentOrg.delete(true);
}
return;
}
// Check if it is a hidden realm
if (subOrgName.startsWith(SMSEntry.SUN_INTERNAL_REALM_NAME)) {
return;
}
// Get the suborg DN
Set subOrgDNs = parentOrg.searchSubOrganizations(subOrgName,
AMConstants.SCOPE_ONE);
if (subOrgDNs != null && !subOrgDNs.isEmpty()) {
for (Iterator items = subOrgDNs.iterator(); items.hasNext();) {
String dn = (String) items.next();
AMOrganization subOrg = parentOrg.getSubOrganization(dn);
if (subOrg != null) {
subOrg.delete(true);
}
}
} else {
AMOrganization subOrg = parentOrg
.getSubOrganization(subOrgName);
if (subOrg != null) {
subOrg.delete(true);
}
}
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::deleteSubOrganization"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame.getMessage(),
ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
}
/**
* Returns the AMSDK Organization attributes. The return attributes are
* defined in the IdRepo service and can be configured per organization.
*/
Map getAttributes() throws SMSException {
Map answer = null;
try {
// Get the list of attribute names
Map attrMapping = getReverseAttributeMapping();
Set attrNames = attrMapping.keySet();
if (!attrNames.isEmpty()) {
// Perform AMSDK search
Map attributes;
if (hasReadPermissionOnly) {
attributes = parentOrgWithAdminToken
.getAttributes(attrNames);
} else {
attributes = parentOrg.getAttributes(attrNames);
}
if (attributes != null && !attributes.isEmpty()) {
// Do reverse name mapping, and copy to answer
for (Iterator items = attributes.keySet().iterator(); items
.hasNext();) {
String key = (String) items.next();
Set values = (Set) attributes.get(key);
if (values != null && !values.isEmpty()) {
if (answer == null) {
answer = new HashMap();
}
answer.put(attrMapping.get(key), values);
}
}
}
}
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::getAttributes"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame.getMessage(),
ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle.getString("sms-INVALID_SSO_TOKEN"),
ssoe, "sms-INVALID_SSO_TOKEN"));
}
return (answer == null ? Collections.EMPTY_MAP : answer);
}
/**
* Adds attributes to AMSDK Organization. The organziation attribute names
* are defined in the IdRepo service.
*/
void addAttributeValues(String attrName, Set values) throws SMSException {
// Get the attribute values, add the new values
// and set the attribute
if (attrName != null && values != null && !values.isEmpty()) {
// First get the attribute values, remove the
// specified valued and then set the attributes
Map attrs = getAttributes();
Set origValues = (Set) attrs.get(attrName);
Set newValues = new HashSet(values);
if (origValues != null && !origValues.isEmpty()) {
newValues.addAll(origValues);
}
Map newAttrs = new HashMap();
newAttrs.put(attrName, newValues);
setAttributes(newAttrs);
}
}
/**
* Sets attributes to AMSDK Organization. The organziation attribute names
* are defined in the IdRepo service.
*/
void setAttributes(Map attributes) throws SMSException {
Map amsdkAttrs = null;
// Need to get attributes such as domain name, alias names
// and org status from attributes and set them.
// These attributes must be defined in ../idm/xml/idRepoService.xml
if (attributes != null && !attributes.isEmpty()) {
Map smsIdRepoAttrs = new CaseInsensitiveHashMap(attributes);
// Iterate through the attribute mappings
Map attrs = getAttributeMapping();
Map existingAttributes = getAttributes();
if (attrs != null && !attrs.isEmpty()) {
for (Iterator items = attrs.keySet().iterator(); items
.hasNext();) {
String key = (String) items.next();
Set value = (Set) smsIdRepoAttrs.get(key);
if (value != null) {
if (amsdkAttrs == null) {
amsdkAttrs = new HashMap();
}
boolean notEmptyFlg = false;
if (!value.isEmpty()) {
for (Iterator iter = value.iterator(); iter
.hasNext();) {
String val = (String) iter.next();
// Avoid empty string storage.
if (val.length() > 0) {
notEmptyFlg = true;
}
}
if (notEmptyFlg) {
amsdkAttrs.put(attrs.get(key), value);
}
} else {
Set existingValues = (Set) existingAttributes
.get(key);
if (existingValues != null
&& !existingValues.isEmpty()) {
amsdkAttrs.put(attrs.get(key), value);
}
}
}
}
}
}
// Update the organization entry
if (amsdkAttrs != null) {
try {
parentOrg.setAttributes(amsdkAttrs);
parentOrg.store();
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::createSub"
+ "Organization: failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame
.getMessage(), ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle
.getString("sms-INVALID_SSO_TOKEN"), ssoe,
"sms-INVALID_SSO_TOKEN"));
}
}
}
/**
* Removes the specified attribute from AMSDK organization. The organziation
* attribute names are defined in the IdRepo service.
*/
void removeAttribute(String attrName) throws SMSException {
if (attrName == null) {
return;
}
// Get the attribute mapping and removed specified attribute
Map attrMap = getAttributeMapping();
String amsdkAttrName = (String) attrMap.get(attrName);
if (amsdkAttrName != null) {
HashSet set = new HashSet();
set.add(amsdkAttrName);
try {
parentOrg.removeAttributes(set);
parentOrg.store();
} catch (AMException ame) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK::removeAttribute"
+ ": failed with AMException", ame);
}
throw (new SMSException(AMSDKBundle.BUNDLE_NAME, ame
.getMessage(), ame, ame.getMessage()));
} catch (SSOException ssoe) {
throw (new SMSException(bundle
.getString("sms-INVALID_SSO_TOKEN"), ssoe,
"sms-INVALID_SSO_TOKEN"));
}
}
}
/**
* Removes the specified attribute values from AMSDK organization. The
* organziation attribute names are defined in the IdRepo service.
*/
void removeAttributeValues(String attrName, Set values) throws SMSException
{
if (attrName != null) {
// First get the attribute values, remove the
// specified valued and then set the attributes
Map attrs = getAttributes();
Set origValues = (Set) attrs.get(attrName);
if (origValues != null && !origValues.isEmpty()) {
Set newValues = new HashSet(origValues);
newValues.removeAll(values);
if (newValues.isEmpty()) {
removeAttribute(attrName);
} else {
Map newAttrs = new HashMap();
newAttrs.put(attrName, newValues);
setAttributes(newAttrs);
}
}
}
}
/**
* Returns the SMS attribute name to AMSDK attribute name mappings for the
* organization
*/
private Map getAttributeMapping() throws SMSException {
if (!ServiceManager.isConfigMigratedTo70()) {
return (notMigratedAttributeMappings);
}
// Check the cache
Map answer = (Map) attributeMappings.get(parentOrgName);
if (answer != null)
return (answer);
// Construct the attribute mappings
Map attrs = serviceConfig.getAttributes();
if (attrs != null && !attrs.isEmpty()) {
Set mapAttrs = (Set) attrs.get(MAPPING_ATTR_NAME);
if (mapAttrs != null && !mapAttrs.isEmpty()) {
for (Iterator items = mapAttrs.iterator(); items.hasNext();) {
String attrMapping = (String) items.next();
String[] maps = DNMapper.splitString(attrMapping);
if (answer == null) {
answer = new CaseInsensitiveHashMap();
}
answer.put(maps[0], maps[1]);
}
}
}
if (answer == null) {
answer = Collections.EMPTY_MAP;
}
// Add to cache
attributeMappings.put(parentOrgName, answer);
return (answer);
}
/**
* Returns the AMSDK attribute name to SMS attribute name mappings for the
* organization
*/
private Map getReverseAttributeMapping() throws SMSException {
if (!ServiceManager.isConfigMigratedTo70()) {
return (notMigratedReverseAttributeMappings);
}
// Check the cache
Map answer = (Map) reverseAttributeMappings.get(parentOrgName);
if (answer != null)
return (answer);
// Get the attribute mapping and reverse it
Map attrMaps = getAttributeMapping();
for (Iterator items = attrMaps.entrySet().iterator(); items.hasNext();)
{
Map.Entry entry = (Map.Entry) items.next();
if (answer == null) {
answer = new CaseInsensitiveHashMap();
}
answer.put(entry.getValue(), entry.getKey().toString());
}
if (answer == null) {
answer = Collections.EMPTY_MAP;
}
reverseAttributeMappings.put(parentOrgName, answer);
return (answer);
}
// Check to see if the user has realm permissions
private boolean checkRealmPermission(SSOToken token, String realm,
Set action) {
boolean answer = false;
if (token != null) {
try {
DelegationEvaluator de = new DelegationEvaluatorImpl();
DelegationPermission dp = new DelegationPermission(realm,
com.sun.identity.sm.SMSEntry.REALM_SERVICE, "1.0", "*",
"*", action, Collections.EMPTY_MAP);
answer = de.isAllowed(token, dp, null);
} catch (DelegationException dex) {
debug.error("OrgConfigViaAMSDK.checkRealmPermission: "
+ "Got Delegation Exception: ", dex);
} catch (SSOException ssoe) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK.checkRealmPermission: "
+ "Invalid SSOToken: ", ssoe);
}
}
}
return (answer);
}
static String getNamingAttrForOrg() {
return (ServiceManager.isAMSDKEnabled()) ?
AMNamingAttrManager.getNamingAttr(AMObject.ORGANIZATION) :
SMSEntry.ORG_PLACEHOLDER_RDN;
}
static String getNamingAttrForOrgUnit() {
return AMNamingAttrManager.getNamingAttr(AMObject.ORGANIZATIONAL_UNIT);
}
public Set getSDKAttributeValue(String key) {
Set attrSet = new HashSet();
try {
attrSet = parentOrg.getAttribute(key);
} catch (AMException ame) {
if (debug.warningEnabled()) {
debug.warning("OrgConfigViaAMSDK::getSDKAttributeValue"
+ ": failed with AMException", ame);
}
} catch (SSOException ssoe) {
if (debug.warningEnabled()) {
debug.warning("OrgConfigViaAMSDK::getSDKAttributeValue"
+ ": failed with SSOException", ssoe);
}
}
return (attrSet);
}
/**
* Clears the cache
*/
protected static void clearCache() {
attributeMappings = new CaseInsensitiveHashMap();
reverseAttributeMappings = new CaseInsensitiveHashMap();
amsdkdn2realmname = new CaseInsensitiveHashMap();
amsdkConfiguredRealms = new CaseInsensitiveHashMap();
}
protected static void updateAMSDKConfiguredRealms(
String realm, boolean configured) {
if (!amsdkConfiguredRealms.keySet().contains(realm)) {
amsdkConfiguredRealms.put(realm, Boolean.valueOf(configured));
}
}
/**
* Returns the true if AMSDK plugin is configured for the realm,
* else returns false.
*/
public static boolean isAMSDKConfigured(String realm) {
if (ServiceManager.isCoexistenceMode()) {
return (true);
}
// Check the cache
realm = DNUtils.normalizeDN(realm);
Boolean answer = (Boolean) amsdkConfiguredRealms.get(realm);
if (answer == null) {
try {
SSOToken token = (SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance());
OrganizationConfigManagerImpl ocm =
OrganizationConfigManagerImpl.getInstance(token, realm);
String orgname = getAmsdkdn(token, ocm);
answer = Boolean.valueOf(orgname != null);
} catch (SSOException ssoe) {
answer = Boolean.FALSE;
} catch (SMSException smse) {
answer = Boolean.FALSE;
}
// Update cache
amsdkConfiguredRealms.put(realm, answer);
}
return (answer.booleanValue());
}
/**
* Returns the realm name that contains the AMSDK plugin with the
* given organization dn. The function optionally takes "inrealm"
* the realm, where the initial search would be done
* If not found, returns null.
*/
public static String getRealmForAMSDK(String amsdkdn,
String inrealm) {
// If in legacy mode, return amsdkdn
if (ServiceManager.isCoexistenceMode()) {
return (amsdkdn);
}
String realm = inrealm;
// Check the cache
amsdkdn = DNUtils.normalizeDN(amsdkdn);
// if amsdk was not in DN format then normalizeDN will return null
if(amsdkdn == null) {
return null;
}
String orgname = (String) amsdkdn2realmname.get(amsdkdn);
if (orgname != null) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK:getRealmForAMSDK " +
"from cache: orgdn=" + amsdkdn + " realm=" + orgname);
}
return (orgname);
}
// First check with "inrealm" and then with "amsdkdn"
OrganizationConfigManagerImpl ocm = null;
SSOToken token = (SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance());
try {
// Check inrealm first
if (inrealm != null) {
ocm = OrganizationConfigManagerImpl.getInstance(
token, inrealm);
orgname = getAmsdkdn(token, ocm);
}
// Need to check for the following conditions before
// using amsdkdn as the realm name to determine the
// AMSDK plugin organization name
// i) "inrealm" is null (realm name is not provided)
// ii) orgname != null && !orgname.equals(realm)
// (since orgname is not null, AMSDK has been configured
// configured for the realm, but it does not match the
// provided "amsdkdn", hence need to check for amsdkdn realm
// iii) !inrealm.equals(amsdkdn)
// If same, the check has been done. No need to repeat
// iv) If the dn starts with ou then the realm for the orgUnit
// is hidden. So first replace values of all ou's in the
// amsdkdn and then find the realm for it.
if ((inrealm == null) ||
((orgname != null) && !orgname.equals(realm)) ||
((orgname != null) &&
!amsdkdn.equals(DNUtils.normalizeDN(inrealm)))) {
String dn = hideOrgUnits(amsdkdn);
ocm = OrganizationConfigManagerImpl.getInstance(
token, dn);
orgname = getAmsdkdn(token, ocm);
if ((orgname != null) && orgname.equals(amsdkdn)) {
realm = ocm.getOrgDN();
}
}
} catch (SMSException sme) {
// Ignore the exception, since the realm is not present
// and an explicit search would be done below
} catch (SSOException ssoe) {
// Ignore the exception, since the realm is not present
// and an explicit search would be done below
}
if (realm != null) {
amsdkdn2realmname.put(amsdkdn, realm);
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK:getRealmForAMSDK " +
"first realm lookup: orgdn=" + amsdkdn +
" realm=" + realm);
}
} else {
// If realm is still null, need to search the realm tree
try {
ocm = OrganizationConfigManagerImpl.getInstance(token, "/");
updateAmsdk2RealmNameCache(token, ocm, amsdkdn);
realm = (String) amsdkdn2realmname.get(amsdkdn);
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK:getRealmForAMSDK " +
"full search orgdn=" + amsdkdn + " realm=" + realm);
}
} catch (SMSException e) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK:getRealmForAMSDK" +
" Exception: ", e);
}
} catch (SSOException ssoe) {
if (debug.messageEnabled()) {
debug.message("OrgConfigViaAMSDK:getRealmForAMSDK" +
" SSException: ", ssoe);
}
}
}
return (realm);
}
/**
* This method checks if the dn starts with org unit naming attr.
* If yes, then it replaces values of all ou's by prefixing
* SMSEntry.SUN_INTERNAL_REALM_NAME because all realms mapping to
* orgUnits are hidden.
* If the dn does not start with org unit naming attr then it is
* returned as-is.
* For example,
* ou=X,ou=Y,o=DevSample,dc=red,dc=iplanet,dc=com
* is replaced with
* ou=sunamhiddenrealmX,ou=sunamhiddenrealmY,o=DevSample,dc=red,dc=iplanet,dc=com
*
* @param orgUnitDN String can not be null
*/
private static String hideOrgUnits(String orgUnitDN) {
String ou = getNamingAttrForOrgUnit();
if(!orgUnitDN.startsWith(ou)) {
return orgUnitDN;
}
DN result = DN.rootDN();
DN rdns = DN.valueOf(orgUnitDN);
for (int i = rdns.size() - 1; i >= 0; i--) {
RDN rdn = rdns.parent(i).rdn();
if(rdnType(rdn).equals(ou)) {
result = result.child(new RDN(ou, SMSEntry.SUN_INTERNAL_REALM_NAME + rdnValue(rdn)));
} else {
result = result.child(rdn);
}
}
return result.toString();
}
private static boolean updateAmsdk2RealmNameCache(SSOToken token,
OrganizationConfigManagerImpl ocm, String amsdkdn)
throws SMSException, SSOException {
boolean foundEntry = false;
// Get the AMSDK DN configured for the realm, update cache
String orgname = getAmsdkdn(token, ocm);
if (orgname != null) {
amsdkdn2realmname.put(orgname, ocm.getOrgDN());
if (orgname.equals(amsdkdn)) {
foundEntry = true;
}
}
// Walk down the realm tree if entry is not found
if (!foundEntry) {
Set subRealmNames = ocm.getSubOrganizationNames(token);
if ((subRealmNames != null) && !subRealmNames.isEmpty()) {
for (Iterator realms = subRealmNames.iterator();
realms.hasNext();) {
OrganizationConfigManagerImpl socm =
OrganizationConfigManagerImpl.getInstance(
token, "o=" + realms.next() + "," +
ocm.getOrgDN());
if ((foundEntry = updateAmsdk2RealmNameCache(
token, socm, amsdkdn))) {
break;
}
}
}
}
return (foundEntry);
}
public static String getAmsdkdn(SSOToken token,
OrganizationConfigManagerImpl ocm)
throws SMSException, SSOException {
if (ServiceManager.isCoexistenceMode()) {
return ocm.getOrgDN();
}
String orgdn = null;
// Get idrepo plugins and check for amsdkdn plugin
ServiceConfigManagerImpl sci = ServiceConfigManagerImpl
.getInstance(token, ServiceManager.REALM_SERVICE, "1.0");
if (sci != null) {
ServiceConfigImpl sc = sci.getOrganizationConfig(
token, ocm.getOrgDN(), null);
if (sc != null) {
Set plugins = sc.getSubConfigNames(token);
if (plugins != null && !plugins.isEmpty()) {
for (Iterator items = plugins.iterator();
items.hasNext();) {
ServiceConfigImpl ssc = sc.getSubConfig(
token, (String) items.next());
if (ssc.getSchemaID().equalsIgnoreCase(
IdConstants.AMSDK_PLUGIN_NAME)) {
Map cMap = ssc.getAttributesForRead();
if ((cMap != null) && !cMap.isEmpty()) {
Set orgs = (Set) cMap.get("amSDKOrgName");
if ((orgs != null) && !orgs.isEmpty()) {
orgdn = DNUtils.normalizeDN(
(String) orgs.iterator().next());
}
}
break;
}
}
}
}
}
return (orgdn);
}
// Returns the organization type for AMSDK DN.
private int getObjectType() {
if (objType == 0) {
try {
AMStoreConnection amcom = new AMStoreConnection(
(SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance()));
objType = amcom.getAMObjectType(parentOrgName);
} catch(AMException ame) {
// set as organizational unit
objType = AMObject.ORGANIZATIONAL_UNIT;
debug.error("OrgConfigViaAMSDK: Unable to determine type");
} catch (SSOException ssoe) {
// set as organizational unit
objType = AMObject.ORGANIZATIONAL_UNIT;
}
}
return (objType);
}
}