/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.server.security.servletfilters.ldap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.servlet.FilterConfig;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import fedora.server.errors.authorization.PasswordComparisonException;
import fedora.server.security.servletfilters.BaseCaching;
import fedora.server.security.servletfilters.CacheElement;
import fedora.server.security.servletfilters.FilterSetup;
/**
* @author Bill Niebel
*/
public class FilterLdap
extends BaseCaching {
protected static Log log = LogFactory.getLog(FilterLdap.class);
public static final String CONTEXT_VERSION_KEY = "java.naming.ldap.version";
public static final String VERSION_KEY = "version";
public static final String BIND_FILTER_KEY = "bind-filter";
public static final String URL_KEY = "url";
public static final String BASE_KEY = "search-base";
public static final String FILTER_KEY = "search-filter";
public static final String USERID_KEY = "id-attribute";
public static final String PASSWORD_KEY = "password-attribute";
public static final String ATTRIBUTES2RETURN_KEY = "attributes";
public static final String GROUPS_NAME_KEY = "attributes-common-name";
public static final String SECURITY_AUTHENTICATION_KEY =
"security-authentication";
public static final String SECURITY_PRINCIPAL_KEY = "security-principal";
public static final String SECURITY_CREDENTIALS_KEY =
"security-credentials";
private String[] DIRECTORY_ATTRIBUTES_NEEDED = null;
private String VERSION = "2";
private String BIND_FILTER = "";
private String URL = "";
private String BASE = "";
private String FILTER = "";
private String PASSWORD = "";
private String[] ATTRIBUTES2RETURN = null;
private String GROUPS_NAME = null;
public String SECURITY_AUTHENTICATION = "none";
public String SECURITY_PRINCIPAL = null;
public String SECURITY_CREDENTIALS = null;
//public Boolean REQUIRE_RETURNED_ATTRS = Boolean.FALSE;
@Override
public void init(FilterConfig filterConfig) {
String m = "L init() ";
try {
log.debug(m + ">");
super.init(filterConfig);
m = FilterSetup.getFilterNameAbbrev(FILTER_NAME) + " init() ";
inited = false;
if (!initErrors) {
Set temp = new HashSet();
if (ATTRIBUTES2RETURN == null) {
ATTRIBUTES2RETURN = new String[0];
} else {
for (String element : ATTRIBUTES2RETURN) {
temp.add(element);
}
}
if (AUTHENTICATE && PASSWORD != null && !"".equals(PASSWORD)) {
temp.add(PASSWORD);
}
DIRECTORY_ATTRIBUTES_NEEDED =
(String[]) temp.toArray(StringArrayPrototype);
boolean haveBindMethod = false;
if (SECURITY_AUTHENTICATION != null
&& !"".equals(SECURITY_AUTHENTICATION)) {
haveBindMethod = true;
}
boolean haveSuperUser = false;
if (SECURITY_PRINCIPAL != null
&& !"".equals(SECURITY_PRINCIPAL)) {
haveSuperUser = true;
}
boolean haveSuperUserPassword = false;
if (SECURITY_CREDENTIALS != null
&& !"".equals(SECURITY_CREDENTIALS)) {
haveSuperUserPassword = true;
}
boolean haveUserPasswordAttributeName = false;
if (PASSWORD != null && !"".equals(PASSWORD)) {
haveUserPasswordAttributeName = true;
}
boolean commonBindConfigured = false;
if (haveBindMethod && haveSuperUserPassword) {
boolean error = false;
if (!haveSuperUser) {
error = true;
}
if (error) {
initErrors = true;
} else {
commonBindConfigured = true;
}
}
boolean individualBindConfigured = false;
boolean individualBindTestConfigured = false;
if (haveBindMethod && !haveSuperUserPassword) {
if (haveSuperUser) {
individualBindTestConfigured = true;
} else {
individualBindConfigured = true;
}
}
boolean individualCompareConfigured = false;
if (haveUserPasswordAttributeName) {
individualCompareConfigured = true;
}
}
if (initErrors) {
log.error(m + "not initialized; see previous error");
}
inited = true;
} finally {
log.debug(m + "<");
}
}
@Override
public void destroy() {
String m = FilterSetup.getFilterNameAbbrev(FILTER_NAME) + " destroy() ";
try {
log.debug(m + ">");
super.destroy();
} finally {
log.debug(m + "<");
}
}
@Override
protected void initThisSubclass(String key, String value) {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " initThisSubclass() ";
try {
log.debug(m + ">");
log.debug(m + key + "==" + value);
boolean setLocally = false;
if (VERSION_KEY.equals(key)) {
VERSION = value;
setLocally = true;
} else if (BIND_FILTER_KEY.equals(key)) {
BIND_FILTER = value;
setLocally = true;
} else if (URL_KEY.equals(key)) {
URL = value;
setLocally = true;
} else if (BASE_KEY.equals(key)) {
BASE = value;
setLocally = true;
} else if (USERID_KEY.equals(key)) {
setLocally = true;
} else if (ATTRIBUTES2RETURN_KEY.equals(key)) {
if (value.indexOf(",") < 0) {
if ("".equals(value)) {
ATTRIBUTES2RETURN = null;
} else {
ATTRIBUTES2RETURN = new String[1];
ATTRIBUTES2RETURN[0] = value;
}
} else {
ATTRIBUTES2RETURN = value.split(",");
}
setLocally = true;
} else if (GROUPS_NAME_KEY.equals(key)) {
GROUPS_NAME = value;
setLocally = true;
} else if (FILTER_KEY.equals(key)) {
FILTER = value;
setLocally = true;
} else if (PASSWORD_KEY.equals(key)) {
PASSWORD = value;
setLocally = true;
} else if (SECURITY_AUTHENTICATION_KEY.equals(key)) {
SECURITY_AUTHENTICATION = value;
setLocally = true;
} else if (SECURITY_PRINCIPAL_KEY.equals(key)) {
SECURITY_PRINCIPAL = value;
setLocally = true;
} else if (SECURITY_CREDENTIALS_KEY.equals(key)) {
SECURITY_CREDENTIALS = value;
setLocally = true;
/*
* } else if (REQUIRE_RETURNED_ATTRS_KEY.equals(key)) {
* REQUIRE_RETURNED_ATTRS = Boolean.valueOf(value); setLocally =
* true;
*/
} else {
log.debug(m + "deferring to super");
super.initThisSubclass(key, value);
}
if (setLocally) {
log.info(m + "known parameter " + key + "==" + value);
}
} finally {
log.debug(m + "<");
}
}
private final String applyFilter(String filter, String[] args) {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " applyFilter() ";
String result = filter;
log.debug(m + "result==" + result);
int i = args.length - 1;
for (; i >= 0; i--) {
String regex = "\\{" + Integer.toString(i) + "\\}";
log.debug(m + "regex ==" + regex);
log.debug(m + "arg ==" + args[i]);
result = result.replaceFirst(regex, args[i]);
log.debug(m + "result==" + result);
}
return result;
}
private boolean bindRequired() {
boolean bindRequired = "simple".equals(SECURITY_AUTHENTICATION);
return bindRequired;
}
private boolean individualUserBind() {
boolean individualUserBind =
bindRequired() && AUTHENTICATE
&& (PASSWORD == null || "".equals(PASSWORD));
return individualUserBind;
}
private boolean individualUserComparison() {
boolean individualUserComparison =
AUTHENTICATE && PASSWORD != null && !"".equals(PASSWORD);
return individualUserComparison;
}
private Hashtable getEnvironment(String userid, String password) {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " getEnvironment() ";
Hashtable env = null;
try {
env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
if (VERSION != null && !"".equals(VERSION)) {
log.debug(m + "ldap explicit version==" + VERSION);
env.put(CONTEXT_VERSION_KEY, VERSION);
}
log.debug(m + "ldap version==" + env.get(CONTEXT_VERSION_KEY));
env.put(Context.PROVIDER_URL, URL);
log.debug(m + "ldap url==" + env.get(Context.PROVIDER_URL));
if (!bindRequired()) {
log.debug(m + "\"binding\" anonymously");
} else {
env.put(Context.SECURITY_AUTHENTICATION,
SECURITY_AUTHENTICATION);
String userForBind = null;
String passwordForBind = null;
if (!individualUserBind()) {
userForBind = SECURITY_PRINCIPAL;
passwordForBind = SECURITY_CREDENTIALS;
log.debug(m + "binding to protected directory");
} else {
passwordForBind = password;
if (SECURITY_PRINCIPAL == null
|| "".equals(SECURITY_PRINCIPAL)) {
userForBind = userid;
log.debug(m + "binding for real user");
} else {
//simulate test against user-bind at directory server
userForBind = SECURITY_PRINCIPAL;
log.debug(m + "binding for --test-- user");
}
}
env.put(Context.SECURITY_CREDENTIALS, passwordForBind);
String[] parms = {userForBind};
String userFormattedForBind = applyFilter(BIND_FILTER, parms);
env.put(Context.SECURITY_PRINCIPAL, userFormattedForBind);
}
log.debug(m + "bind w " + env.get(Context.SECURITY_AUTHENTICATION));
log.debug(m + "user== " + env.get(Context.SECURITY_PRINCIPAL));
log.debug(m + "passwd==" + env.get(Context.SECURITY_CREDENTIALS));
} catch (Throwable th) {
if (LOG_STACK_TRACES) {
log.error(m + "couldn't set up env for DirContext", th);
} else {
log.error(m + "couldn't set up env for DirContext"
+ th.getMessage());
}
} finally {
log.debug(m + "< " + env);
}
return env;
}
private final String getFilter(String userid) {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME) + " getFilter() ";
log.debug(m + ">");
String filter = null;
try {
filter = new String(FILTER);
filter = filter.replaceFirst("\\{0}", userid);
} catch (Throwable th) {
if (LOG_STACK_TRACES) {
log.error(m + "couldn't set up filter for dir search", th);
} else {
log.error(m + "couldn't set up filter for dir search"
+ th.getMessage());
}
} finally {
log.debug(m + "< " + filter);
}
return filter;
}
private final SearchControls getSearchControls() {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " getSearchControls() ";
log.debug(m + ">");
SearchControls searchControls = null;
try {
int nEntries2return = 0;
int millisecondTimeLimit = 0;
boolean retobj = true;
boolean deref = true;
searchControls =
new SearchControls(SearchControls.SUBTREE_SCOPE,
nEntries2return,
millisecondTimeLimit,
DIRECTORY_ATTRIBUTES_NEEDED,
retobj,
deref);
} catch (Throwable th) {
if (LOG_STACK_TRACES) {
log.error(m + "couldn't set up search controls for dir search",
th);
} else {
log.error(m + "couldn't set up search controls for dir search"
+ th.getMessage());
}
} finally {
log.debug(m + "< " + searchControls);
}
return searchControls;
}
private NamingEnumeration getBasicNamingEnumeration(String userid,
String password,
String filter,
SearchControls searchControls,
Hashtable env)
throws NamingException, Exception {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " getNamingEnumeration() ";
log.debug(m + ">");
NamingEnumeration ne = null;
try {
DirContext ctx;
try {
ctx = new InitialDirContext(env);
} catch (NamingException th) {
String msg = "exception getting ldap context";
if (LOG_STACK_TRACES) {
log.error(m + msg, th);
} else {
log.error(m + msg + " " + th.getMessage());
}
throw th;
}
if (ctx == null) {
log.error(m + "unexpected null ldap context");
throw new NamingException("");
}
try {
ne = ctx.search(BASE, filter, searchControls);
} catch (NamingException th) {
String msg = "exception getting ldap enumeration";
if (LOG_STACK_TRACES) {
log.error(m + msg, th);
} else {
log.error(m + msg + " " + th.getMessage());
}
throw th;
}
if (ne == null) {
log.error(m + "unexpected null ldap enumeration");
throw new NamingException("");
}
} finally {
log.debug(m + "< " + ne);
}
return ne;
}
private NamingEnumeration getNamingEnumeration(String userid,
String password,
String filter,
SearchControls searchControls,
Hashtable env)
throws NamingException, Exception {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " getNamingEnumeration() ";
log.debug(m + ">");
// this condition is to -further- protect against behavior suggested by
// log from hull (see below for first-line protection)
// the idea here is to steer clear of possible trouble in underlying
// code and avoid calling ldap w/o a needed and practical password
String msg = "[LDAP: error code 49 - Bind failed: ";
if (!individualUserBind()) {
log.info(m + "-not- binding individual user");
} else {
log.info(m + "-binding- individual user");
if (password == null) {
log.debug(m + "null password");
if (USE_FILTER.equalsIgnoreCase(PW_NULL)) {
log.debug(m + "-no- pre null password handling");
} else {
if (AUTHENTICATE) {
log.info(m + "-doing- pre null password handling");
if (UNAUTHENTICATE_USER_UNCONDITIONALLY
.equalsIgnoreCase(PW_NULL)) {
log.info(m
+ "pre unauthenticating for null password");
throw new NamingException(msg + "null password]");
} else if (SKIP_FILTER.equalsIgnoreCase(PW_NULL)) {
log.info(m + "pre ignoring for null passwd");
throw new Exception(msg + "null password]");
} else {
assert true : "bad value for PW_NULL==" + PW_NULL;
}
}
}
} else if ("".equals(password)) {
log.debug(m + "0-length password");
if (USE_FILTER.equalsIgnoreCase(PW_0)) {
log.debug(m + "-no- pre 0-length password handling");
} else {
if (AUTHENTICATE) {
log.info(m + "-doing- pre 0-length password handling");
if (UNAUTHENTICATE_USER_UNCONDITIONALLY
.equalsIgnoreCase(PW_0)) {
log
.info(m
+ "pre unauthenticating for 0-length password");
throw new NamingException(msg
+ "0-length password]");
} else if (SKIP_FILTER.equalsIgnoreCase(PW_0)) {
log.info(m + "pre ignoring for 0-length passwd");
throw new Exception(msg + "0-length password]");
} else {
assert true : "bad value for PW_0==" + PW_0;
}
}
}
} else {
assert password.length() > 0;
}
}
NamingEnumeration ne = null;
try {
ne =
getBasicNamingEnumeration(userid,
password,
filter,
searchControls,
env);
assert ne != null;
if (ne.hasMoreElements()) {
log.debug(m + "enumeration has elements");
} else {
log.debug(m + "enumeration has no elements, yet no exceptions");
if (bindRequired() && !individualUserBind()) {
log.debug(m + "failed security bind");
throw new NamingException(msg + "failed security bind]");
}
if (!AUTHENTICATE) {
log.debug(m
+ "user authentication -not- done by this filter");
} else {
log.debug(m + "user authentication -done- by this filter");
if (!bindRequired()) {
log.debug(m + "but -not- binding");
} else {
log.debug(m + "-and- binding");
if (SKIP_FILTER.equalsIgnoreCase(EMPTY_RESULTS)) {
log.debug(m + "passing thru for EMPTY_RESULTS");
throw new Exception(msg + "null password]");
} else if (UNAUTHENTICATE_USER_UNCONDITIONALLY
.equalsIgnoreCase(EMPTY_RESULTS)) {
log.debug(m + "failing for EMPTY_RESULTS");
throw new NamingException(msg + "null password]");
} else if (USE_FILTER.equalsIgnoreCase(EMPTY_RESULTS)) {
log.debug(m + "passing for EMPTY_RESULTS");
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
} else if (UNAUTHENTICATE_USER_CONDITIONALLY
.equalsIgnoreCase(EMPTY_RESULTS)) {
if (ATTRIBUTES2RETURN == null
|| ATTRIBUTES2RETURN.length < 1) {
log.debug(m + "fair enough");
} else {
throw new NamingException(msg + "expected some");
}
} else {
assert true : "bad value for EMPTY_RESULTS=="
+ EMPTY_RESULTS;
}
}
}
}
} finally {
log.debug(m + "< " + ne);
}
return ne;
}
private static Boolean comparePassword(Attributes attributes,
String password,
String passwordAttribute)
throws PasswordComparisonException {
String m = "- comparePassword() ";
log.debug(m + ">");
Boolean rc = null;
try {
log.debug(m + "looking for return attribute==" + passwordAttribute);
Attribute attribute = attributes.get(passwordAttribute);
if (attribute == null) {
log.error(m + "null object");
} else {
int size = attribute.size();
log.debug(m + "object with n==" + size);
for (int j = 0; j < size; j++) {
Object o = attribute.get(j);
if (password.equals(o.toString())) {
log.debug(m + "compares true");
if (rc == null) {
log.debug(m + "1st comp: authenticate");
rc = Boolean.TRUE;
} else {
log.error(m + "dup comp: keep previous rc==" + rc);
}
} else {
log.debug(m + "compares false, -un-authenticate");
if (rc == null) {
log.debug(m + "1st comp (fyi)");
} else {
log.error(m + "dup comp (fyi)");
}
rc = Boolean.FALSE;
}
}
}
} catch (Throwable th) {
log.error(m + "resetting to null rc==" + rc + th.getMessage());
throw new PasswordComparisonException("in ldap servlet filter", th);
} finally {
log.debug(m + "< " + rc);
}
return rc;
}
private void getAttributes(Attributes attributes, Map map) throws Throwable {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " getAttributes() ";
log.debug(m + ">");
try {
for (String key : ATTRIBUTES2RETURN) {
log.debug(m + "looking for return attribute==" + key);
Attribute attribute = attributes.get(key);
if (attribute == null) {
log.error(m + "null object...continue to next attr sought");
continue;
}
if (GROUPS_NAME != null && !"".equals(GROUPS_NAME)) {
key = GROUPS_NAME;
log.debug(m
+ "values collected and interpreted as groups=="
+ key);
}
Set values;
if (map.containsKey(key)) {
log.debug(m + "already a value-set for attribute==" + key);
values = (Set) map.get(key);
} else {
log.debug(m + "making+storing a value-set for attribute=="
+ key);
values = new HashSet();
map.put(key, values);
}
int size = attribute.size();
log.debug(m + "object with n==" + size);
for (int j = 0; j < size; j++) {
Object o = attribute.get(j);
values.add(o);
log.debug(m + "added value==" + o.toString() + ", class=="
+ o.getClass().getName());
}
}
} finally {
log.debug(m + "<");
}
}
private Boolean processNamingEnumeration(NamingEnumeration ne,
String password,
Boolean authenticated,
Map map) {
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " processNamingEnumeration() ";
log.debug(m + ">");
try {
boolean errorOnSomeComparison = false;
while (ne.hasMoreElements()) {
log.debug(m + "another element");
SearchResult s = null;
try {
Object o = ne.nextElement();
log.debug(m + "got a " + o.getClass().getName());
s = (SearchResult) o;
} catch (Throwable th) {
log.error(m + "naming enum contains obj not SearchResult");
continue;
}
Attributes attributes = s.getAttributes();
getAttributes(attributes, map);
if (individualUserComparison()) {
Boolean temp = null;
try {
temp = comparePassword(attributes, password, PASSWORD);
log.debug(m + "-this- comp yields " + temp);
if (authenticated != null && !authenticated) {
log.debug(m + "keeping prev failed authn");
} else {
log.debug(m + "replacing prvsuccess or null authn");
if (errorOnSomeComparison) {
log.debug(m + "errorOnSomeComparison=="
+ errorOnSomeComparison);
} else {
authenticated = temp;
}
}
} catch (Throwable th) {
log.debug(m
+ "in iUC conditional, caught throwable th=="
+ th);
errorOnSomeComparison = true;
authenticated = null;
}
}
}
if (individualUserComparison()) {
if (errorOnSomeComparison) {
log.debug(m + "exception, so assuring authenticated=="
+ authenticated);
authenticated = null;
map.clear();
} else if (authenticated == null) {
authenticated = Boolean.FALSE;
log.debug(m + "no passwd attr found, so authenticated=="
+ authenticated);
}
}
} catch (Throwable th) { // play it safe:
map.clear();
if (authenticated != null && authenticated) {
// drop an earlier authentication, before exception was thrown
authenticated = null;
} // but leave alone a earlier -failed- authentication
if (LOG_STACK_TRACES) {
log.error(m + "ldap filter failure", th);
} else {
log.error(m + "ldap filter failure" + th.getMessage());
}
} finally {
log.debug(m + "< authenticated==" + authenticated + " map==" + map);
}
return authenticated;
}
@Override
public void populateCacheElement(CacheElement cacheElement, String password) {
//this is heavy on logging for field reporting
String m =
FilterSetup.getFilterNameAbbrev(FILTER_NAME)
+ " populateCacheElement() ";
log.debug(m + ">");
Boolean authenticated = null;
Map map = new Hashtable();
try {
log.debug(m + "about to call getNamingEnumeration()");
String filter = getFilter(cacheElement.getUserid());
SearchControls searchControls = getSearchControls();
Hashtable env = getEnvironment(cacheElement.getUserid(), password);
NamingEnumeration ne = null;
try {
ne =
getNamingEnumeration(cacheElement.getUserid(),
password,
filter,
searchControls,
env);
assert ne != null;
log.debug(m + "got expected non-null ne, no exception thrown");
if (AUTHENTICATE && individualUserBind()) {
authenticated = Boolean.TRUE;
}
if (AUTHENTICATE && individualUserBind()
&& !authenticated.booleanValue()) {
log.debug(m + "-not- calling processNamingEnumeration()");
} else {
log.debug(m + "about to call processNamingEnumeration()");
assert map.isEmpty();
try {
authenticated =
processNamingEnumeration(ne,
password,
authenticated,
map);
log.debug(m + "back from pNE. AUTHENTICATE=="
+ AUTHENTICATE + " authenticated=="
+ authenticated + " map==" + map);
if (authenticated != null) {
log.debug(m + "authenticated.booleanValue()=="
+ authenticated.booleanValue());
}
if (map != null) {
log.debug(m + "map.isEmpty()==" + map.isEmpty());
}
if (AUTHENTICATE
&& (authenticated == null || !authenticated
.booleanValue())) {
map.clear();
}
log.debug(m + "before catch");
} catch (Throwable th) {
map.clear();
if (AUTHENTICATE && individualUserBind()) {
authenticated = Boolean.FALSE;
} else {
//to be sure: likely hasn't changed from initial
authenticated = null;
}
if (LOG_STACK_TRACES) {
log.error(m + "caught th==" + th);
} else {
log.error(m + "caught th==" + th.getMessage());
}
}
}
} catch (NamingException e) {
// the -error- logs here are because, though ne==null
// never before seen, yet hull log suggests caution and
// preemptive logging
log.error(m + "unexpected null ne w/o exception thrown");
if (!AUTHENTICATE) {
log.error(m + "wasn't authenticating");
} else {
authenticated = Boolean.FALSE;
if (individualUserComparison()) {
log.error(m + "can't do password comparison, so false");
} else if (individualUserBind()) {
log.error(m + "accept to mean failed bind, so false");
} else {
log.error(m + "authenticating, so now set false");
}
}
} catch (Exception e) {
// this seemingly was a condition reached at hull, of course
// though, in an earlier different code version
if (AUTHENTICATE && individualUserComparison()) {
authenticated = null; //Boolean.FALSE; PASSTHROUGH
log.error(m + "has no ret vals, so reject authentication");
} else if (AUTHENTICATE && individualUserBind()) {
authenticated = null; //Boolean.FALSE; PASSTHROUGH
log.error(m + "has no ret vals, so reject authentication");
}
}
} finally {
log.debug(m + "in finally, authenticated==" + authenticated
+ " map==" + map);
cacheElement.populate(authenticated, null, map, null);
log.debug(m + "<");
}
}
}