/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2006 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: AuthenticatedSharedAgents.java,v 1.3 2009/07/16 17:45:58 qcheng Exp $
*
*/
package com.sun.identity.policy.plugins;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;
import com.iplanet.sso.SSOTokenManager;
import com.sun.identity.common.DNUtils;
import com.sun.identity.idm.AMIdentity;
import com.sun.identity.idm.IdRepoException;
import com.sun.identity.idm.IdConstants;
import com.sun.identity.idm.IdType;
import com.sun.identity.idm.IdUtils;
import com.sun.identity.policy.PolicyException;
import com.sun.identity.policy.PolicyManager;
import com.sun.identity.policy.Syntax;
import com.sun.identity.policy.ValidValues;
import com.sun.identity.policy.interfaces.Subject;
import com.sun.identity.security.AdminTokenAction;
import com.sun.identity.shared.Constants;
import com.sun.identity.shared.debug.Debug;
import com.sun.identity.sm.SMSException;
import com.sun.identity.sm.ServiceConfigManager;
import com.sun.identity.sm.ServiceConfig;
import com.sun.identity.sm.ServiceListener;
import com.sun.identity.shared.ldap.LDAPDN;
import com.sun.identity.shared.ldap.util.DN;
/**
* This subject applies to all users/agents with valid SSOToken.
*/
public class AuthenticatedSharedAgents implements Subject {
private static final String version = "1.0";
private static final String agentserviceName = IdConstants.AGENT_SERVICE;
private static ServiceConfigManager scm = null;
private static Set sharedAgentsCache = new HashSet();
private static Map realmCache = new HashMap(2);
private static ValidValues validValues =
new ValidValues(ValidValues.SUCCESS, Collections.EMPTY_SET);
static Debug debug = Debug.getInstance("AuthAgents");
static {
SSOToken adminToken = (SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance());
if (debug.messageEnabled()) {
debug.message(": AuthenticatedSharedAgents adding Listener");
}
try {
scm = new ServiceConfigManager(adminToken, agentserviceName,
version);
scm.addListener(new ServiceListenerImpl());
} catch (SMSException smse) {
if (debug.warningEnabled()) {
debug.warning("AuthenticatedSharedAgents: "
+ "Unable to init scm due to " + smse);
}
} catch (SSOException ssoe) {
if (debug.warningEnabled()) {
debug.warning("AuthenticatedSharedAgents: "
+ "Unable to init scm due to " + ssoe);
}
}
}
/**
* Default Constructor
*/
public AuthenticatedSharedAgents() {
}
/**
* Initialize the subject. No properties are required for this
* subject.
* @param configParams configurational information
*/
public void initialize(Map configParams) {
// do nothing
}
/**
* Returns the syntax of the subject type.
* @see com.sun.identity.policy.Syntax
* @param token the SSOToken. Not used for this subject.
* @return Syntax for this subject.
*/
public Syntax getValueSyntax(SSOToken token) {
return (Syntax.CONSTANT);
}
/**
* Returns an empty list as possible values.
* @param token the SSOToken
* @return ValidValues object with empty list.
*
*/
public ValidValues getValidValues(SSOToken token) {
return validValues;
}
/**
* Returns an empty list as possible values.
*
* @param token the SSOToken
* @param pattern the pattern to match in valid values. Ignored for this
* subject
* @return ValidValues object with empty list.
*
*/
public ValidValues getValidValues(SSOToken token, String pattern) {
return (validValues);
}
/**
* This method does nothing as there are no values to display for this
* subject.
*
*/
public String getDisplayNameForValue(String value, Locale locale) {
// does nothing
return(value);
}
/**
* Returns an empty collection as value.
* @return an empty set
*/
public Set getValues() {
return (Collections.EMPTY_SET);
}
/**
* This method does nothing for this subject as there are no values to set
* for this subject.
*/
public void setValues(Set names) {
// does nothing
}
/**
* Determines if the agent belongs to the
* AuthenticatedSharedAgents object.
* @param token SSOToken of the agent
* @return true if the agent SSOToken is valid.
* false otherwise.
* @exception SSOException if error occurs while validating the token.
*/
public boolean isMember(SSOToken token) throws SSOException {
boolean ismember = false;
int errCode = 0;
if ((token != null) && (SSOTokenManager.getInstance().
isValidToken(token))) {
try {
String userDN = null;
String userDNUnivId = null;
AMIdentity amId = IdUtils.getIdentity(token);
IdType idType = amId.getType();
userDN = amId.getName();
userDNUnivId = amId.getUniversalId();
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents:isMember:"+
"idType = " + idType + ", userDN = " + userDN);
}
if ((userDN != null) && (idType.equals(IdType.AGENT) ||
idType.equals(IdType.AGENTONLY))) {
String rlmName = amId.getRealm();
if (isSharedAgent(token, userDN, userDNUnivId, rlmName)) {
errCode = 1;
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents:isMember:"+
"YES");
}
} else {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents:isMember:"+
"NO");
}
}
} else {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents.isMember():"
+"userDN is null or invalid IdType "+userDN +
"IdType :" + idType);
debug.message("AuthenticatedSharedAgents.isMember():"
+"returning false");
}
errCode = 0;
}
} catch (IdRepoException ire) {
debug.error("AuthenticatedSharedAgents:isMember:" +
" IdRepoException:msg = " + ire.getMessage());
errCode = 0;
}
if (errCode == 1) {
ismember = true;
}
}
return ismember;
}
/**
* Creates and returns a copy of this object.
*
* @return a copy of this object
*/
public Object clone() {
AuthenticatedSharedAgents theClone = null;
try {
theClone = (AuthenticatedSharedAgents) super.clone();
} catch (CloneNotSupportedException e) {
// this should never happen
throw new InternalError();
}
return theClone;
}
/**
* Return a hash code for this AuthenticatedSharedAgents.
* @return a hash code for this AuthenticatedSharedAgents
* object.
*/
public int hashCode() {
return super.hashCode();
}
/**
* Checks if distinguished user name is a shared user/agent
* if returns true if so.
*/
protected boolean isSharedAgent(SSOToken token, String userName,
String userDNUnivId, String rlmName) {
boolean isSharedAgent = false;
try {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents:isSharedAgent:"+
"userName = " + userName + " Realm Name = " + rlmName);
}
if (userName != null) {
String agentName = userName;
if (DN.isDN(userName)) {
agentName = LDAPDN.explodeDN(userName, true)[0];
}
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents:isSharedAgent:"+
"agentName = " + agentName);
}
// Check in cache
if ((sharedAgentsCache != null) &&
(!sharedAgentsCache.isEmpty()) &&
(sharedAgentsCache.contains(userDNUnivId))) {
return (true);
}
SSOToken adminToken = (SSOToken) AccessController.doPrivileged(
AdminTokenAction.getInstance());
ServiceConfig oc = getOrgConfig(adminToken, rlmName);
// Get the agent's schemaID from the config.
ServiceConfig aCfg = oc.getSubConfig(agentName);
if (aCfg != null) {
String agentType = aCfg.getSchemaID();
if ((oc.getSubConfigNames().contains(agentName)) &&
(agentType.equalsIgnoreCase("SharedAgent"))) {
isSharedAgent = true;
updateCache(userDNUnivId);
}
}
}
} catch (SSOException ssoe) {
if (debug.warningEnabled()) {
debug.warning("AuthenticatedSharedAgents.isSharedAgent(): "
+ "SSOException: " + ssoe);
}
} catch (SMSException smse) {
if (debug.warningEnabled()) {
debug.warning("AuthenticatedSharedAgents.isSharedAgent(): "
+ "SMSException: " + smse);
}
}
return isSharedAgent;
}
// Returns the organization configuration of the 'default' group
// from AgentService.
private ServiceConfig getOrgConfig(SSOToken token, String realmName) {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents.getOrgConfig() called. ");
}
ServiceConfig orgConfigCache = null;
try {
// Check in cache first
if ((realmCache != null) && (!realmCache.isEmpty()) &&
(realmCache.containsKey(realmName))) {
orgConfigCache = (ServiceConfig) realmCache.get(realmName);
if (orgConfigCache.isValid()) {
debug.message("AuthenticatedSharedAgents.getOrgConfig() found in cache.");
return (orgConfigCache);
}
}
if (scm == null) {
scm = new ServiceConfigManager(token, agentserviceName,
version);
}
orgConfigCache = scm.getOrganizationConfig(realmName, null);
// Update the realm cache.
updateRealmCache(realmName, orgConfigCache);
} catch (SMSException smse) {
if (debug.warningEnabled()) {
debug.warning("AuthenticatedSharedAgents.getOrgConfig(): "
+ "Unable to get organization config due to " + smse);
}
} catch (SSOException ssoe) {
if (debug.warningEnabled()) {
debug.warning("AuthenticatedSharedAgents.getOrgConfig(): "
+ "Unable to get organization config due to " + ssoe);
}
}
return (orgConfigCache);
}
// Stores the shared agent name in Universal Id format
// as there may be same agent names in multiple sub realms.
private static void updateCache(String userDNUnivId) {
Set nset = new HashSet();
nset.addAll(sharedAgentsCache);
nset.add(userDNUnivId);
sharedAgentsCache = nset;
}
// Clears the cache where the agent name is stored.
static void clearCache() {
sharedAgentsCache = new HashSet();
realmCache = new HashMap(2);
}
// Cache to store the realm name and the organization config.
private static void updateRealmCache(String realmName,
ServiceConfig orgConfig) {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents.updateRealmCache: " +
"update cache for realm " + realmName);
}
Map rmap = new HashMap(2);
rmap.putAll(realmCache);
rmap.put(realmName, orgConfig);
realmCache = rmap;
}
private static class ServiceListenerImpl implements ServiceListener {
// The following three methods implement ServiceListener interface
/*
* (non-Javadoc)
*
* @see com.sun.identity.sm.ServiceListener#globalConfigChanged(
* java.lang.String,
* java.lang.String, java.lang.String, java.lang.String, int)
*/
public void globalConfigChanged(String serviceName, String version,
String groupName, String serviceComponent, int type) {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents.globalConfigChanged..");
}
clearCache();
}
/*
* (non-Javadoc)
*
* @see com.sun.identity.sm.ServiceListener#organizationConfigChanged(
* java.lang.String,
* java.lang.String, java.lang.String, java.lang.String,
* java.lang.String, int)
*/
public void organizationConfigChanged(String serviceName, String version,
String orgName, String groupName, String serviceComponent, int type)
{
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents."+
"organizationConfigChanged..");
}
clearCache();
}
/*
* (non-Javadoc)
*
* @see com.sun.identity.sm.ServiceListener#schemaChanged(java.lang.String,
* java.lang.String)
*/
public void schemaChanged(String serviceName, String version) {
if (debug.messageEnabled()) {
debug.message("AuthenticatedSharedAgents.schemaChanged..");
}
clearCache();
}
}
}