fedora.server.security.servletfilters.ldap.FilterLdap.java Source code

Java tutorial

Introduction

Here is the source code for fedora.server.security.servletfilters.ldap.FilterLdap.java

Source

/* 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 + "<");
        }

    }

}