Package org.dspace.authenticate

Source Code of org.dspace.authenticate.LDAPAuthentication$SpeakerToLDAP

/*
* LDAPAuthentication.java
*
* Version: $Revision: 3735 $
*
* Date: $Date: 2009-04-24 04:05:53 +0000 (Fri, 24 Apr 2009) $
*
* Copyright (c) 2002-2009, The DSpace Foundation.  All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.authenticate;

import java.sql.SQLException;
import java.util.Hashtable;

import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchResult;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.core.LogManager;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;

/**
* Authentication module to authenticate against a flat LDAP tree where
* all users are in the same unit.
*
* @author Larry Stone, Stuart Lewis
* @version $Revision: 3735 $
*/
public class LDAPAuthentication
    implements AuthenticationMethod {

    /** log4j category */
    private static Logger log = Logger.getLogger(LDAPAuthentication.class);

    /**
     * Let a real auth method return true if it wants.
     */
    public boolean canSelfRegister(Context context,
                                   HttpServletRequest request,
                                   String username)
        throws SQLException
    {
        // XXX might also want to check that username exists in LDAP.

        return ConfigurationManager.getBooleanProperty("webui.ldap.autoregister");
    }

    /**
     *  Nothing here, initialization is done when auto-registering.
     */
    public void initEPerson(Context context, HttpServletRequest request,
            EPerson eperson)
        throws SQLException
    {
        // XXX should we try to initialize netid based on email addr,
        // XXX  for eperson created by some other method??
    }

    /**
     * Cannot change LDAP password through dspace, right?
     */
    public boolean allowSetPassword(Context context,
                                    HttpServletRequest request,
                                    String username)
        throws SQLException
    {
        // XXX is this right?
        return false;
    }

    /*
     * This is an explicit method.
     */
    public boolean isImplicit()
    {
        return false;
    }

    /*
     * Add authenticated users to the group defined in dspace.cfg by
     * the ldap.login.specialgroup key.
     */
    public int[] getSpecialGroups(Context context, HttpServletRequest request)
    {
    // Prevents anonymous users from being added to this group, and the second check
    // ensures they are LDAP users
    try
    {
      if (!context.getCurrentUser().getNetid().equals(""))
      {
        String groupName = ConfigurationManager.getProperty("ldap.login.specialgroup");
        if ((groupName != null) && (!groupName.trim().equals("")))
        {
        Group ldapGroup = Group.findByName(context, groupName);
          if (ldapGroup == null)
          {
            // Oops - the group isn't there.
            log.warn(LogManager.getHeader(context,
                "ldap_specialgroup",
                "Group defined in ldap.login.specialgroup does not exist"));
            return new int[0];
          } else
          {
            return new int[] { ldapGroup.getID() };
          }
        }
      }
    }
    catch (Exception npe) {
      // The user is not an LDAP user, so we don't need to worry about them
    }
    return new int[0];
    }
 
  /*
     * MIT policy on certs and groups, so always short-circuit.
     *
     * @return One of:
     *   SUCCESS, BAD_CREDENTIALS, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS
     */
    public int authenticate(Context context,
                            String netid,
                            String password,
                            String realm,
                            HttpServletRequest request)
        throws SQLException
    {
        log.info(LogManager.getHeader(context, "auth", "attempting trivial auth of user="+netid));

        // Skip out when no netid or password is given.
        if (netid == null || password == null)
          return BAD_ARGS;

        // Locate the eperson
        EPerson eperson = null;
        try
        {
            eperson = EPerson.findByNetid(context, netid.toLowerCase());
        }
        catch (SQLException e)
        {
        }
        boolean loggedIn = false;
        SpeakerToLDAP ldap = new SpeakerToLDAP(log);

        // if they entered a netid that matches an eperson
        if (eperson != null)
        {
            // e-mail address corresponds to active account
            if (eperson.getRequireCertificate())
                return CERT_REQUIRED;
            else if (!eperson.canLogIn())
                return BAD_ARGS;
            {
                if (ldap.ldapAuthenticate(netid, password, context))
                {
                    context.setCurrentUser(eperson = EPerson.findByNetid(context, netid.toLowerCase()));
                    log.info(LogManager
                        .getHeader(context, "authenticate", "type=ldap"));
                    return SUCCESS;
                }
                else
                   return BAD_CREDENTIALS;
            }
        }

        // the user does not already exist so try and authenticate them
        // with ldap and create an eperson for them
        else
        {
            if (ldap.ldapAuthenticate(netid, password, context))
            {
                // Register the new user automatically
                log.info(LogManager.getHeader(context,
                                "autoregister", "netid=" + netid));

                if ((ldap.ldapEmail!=null)&&(!ldap.ldapEmail.equals("")))
                {
                    try
                    {
                        eperson = EPerson.findByEmail(context, ldap.ldapEmail);
                      if (eperson!=null)
                      {
                          log.info(LogManager.getHeader(context,
                                  "type=ldap-login", "type=ldap_but_already_email"));
                          context.setIgnoreAuthorization(true);
                          eperson.setNetid(netid.toLowerCase());
                          eperson.update();
                          context.commit();
                          context.setIgnoreAuthorization(false);
                          context.setCurrentUser(eperson);
                          return SUCCESS;
                      }
                      else
                      {
                          if (canSelfRegister(context, request, netid))
                          {
                              // TEMPORARILY turn off authorisation
                              try
                              {
                                  context.setIgnoreAuthorization(true);
                                  eperson = EPerson.create(context);
                                  if ((ldap.ldapEmail!=null)&&(!ldap.ldapEmail.equals(""))) eperson.setEmail(ldap.ldapEmail);
                                  else eperson.setEmail(netid);
                                  if ((ldap.ldapGivenName!=null)&&(!ldap.ldapGivenName.equals(""))) eperson.setFirstName(ldap.ldapGivenName);
                                  if ((ldap.ldapSurname!=null)&&(!ldap.ldapSurname.equals(""))) eperson.setLastName(ldap.ldapSurname);
                                  if ((ldap.ldapPhone!=null)&&(!ldap.ldapPhone.equals(""))) eperson.setMetadata("phone", ldap.ldapPhone);
                                  eperson.setNetid(netid.toLowerCase());
                                  eperson.setCanLogIn(true);
                                  AuthenticationManager.initEPerson(context, request, eperson);
                                  eperson.update();
                                  context.commit();
                  context.setCurrentUser(eperson);
                }
                              catch (AuthorizeException e)
                              {
                                  return NO_SUCH_USER;
                              }
                              finally
                              {
                                  context.setIgnoreAuthorization(false);
                              }

                              log.info(LogManager.getHeader(context, "authenticate",
                                          "type=ldap-login, created ePerson"));
                              return SUCCESS;
                          }
                          else
                          {
                              // No auto-registration for valid certs
                              log.info(LogManager.getHeader(context,
                                              "failed_login", "type=ldap_but_no_record"));
                              return NO_SUCH_USER;
                          }
                      }
                    }
                    catch (AuthorizeException e)
                    {
                        eperson = null;
                    }
                    finally
                    {
                        context.setIgnoreAuthorization(false);
                    }
                }
            }
        }
        return BAD_ARGS;
    }

    /**
     * Internal class to manage LDAP query and results, mainly
     * because there are multiple values to return.
     */
    public class SpeakerToLDAP {

        private Logger log = null;

        /** ldap email result */
        protected String ldapEmail = null;

        /** ldap name result */
        protected String ldapGivenName = null;
        protected String ldapSurname = null;
        protected String ldapPhone = null;

        SpeakerToLDAP(Logger thelog)
        {
            log = thelog;
        }

        /**
         * contact the ldap server and attempt to authenticate
         */
        protected boolean ldapAuthenticate(String netid, String password, Context context)
        {
            if (!password.equals(""))
            {
                String ldap_provider_url = ConfigurationManager.getProperty("ldap.provider_url");
                String ldap_id_field = ConfigurationManager.getProperty("ldap.id_field");
                String ldap_search_context = ConfigurationManager.getProperty("ldap.search_context");
                String ldap_object_context = ConfigurationManager.getProperty("ldap.object_context");

                // Set up environment for creating initial context
                Hashtable env = new Hashtable(11);
                env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
                env.put(javax.naming.Context.PROVIDER_URL, ldap_provider_url);

                // Authenticate
                env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple");
                env.put(javax.naming.Context.SECURITY_PRINCIPAL, ldap_id_field+"="+netid+","+ldap_object_context);
                env.put(javax.naming.Context.SECURITY_CREDENTIALS, password);

                DirContext ctx = null;
                try
                {
                    // Create initial context
                    ctx = new InitialDirContext(env);

                    String ldap_email_field = ConfigurationManager.getProperty("ldap.email_field");
                    String ldap_givenname_field = ConfigurationManager.getProperty("ldap.givenname_field");
                    String ldap_surname_field = ConfigurationManager.getProperty("ldap.surname_field");
                    String ldap_phone_field = ConfigurationManager.getProperty("ldap.phone_field");

                    Attributes matchAttrs = new BasicAttributes(true);
                    matchAttrs.put(new BasicAttribute(ldap_id_field, netid));

                    String attlist[] = {ldap_email_field, ldap_givenname_field, ldap_surname_field, ldap_phone_field};

                    // look up attributes
                    try
                    {
                        NamingEnumeration answer = ctx.search(ldap_search_context, matchAttrs, attlist);
                        while(answer.hasMore()) {
                            SearchResult sr = (SearchResult)answer.next();
                            Attributes atts = sr.getAttributes();
                            Attribute att;

                            if (attlist[0]!=null)
                            {
                                    att = atts.get(attlist[0]);
                                    if (att != null) ldapEmail = (String)att.get();
                            }

                            if (attlist[1]!=null)
                            {
                                    att = atts.get(attlist[1]);
                                    if (att != null) ldapGivenName = (String)att.get();
                            }

                            if (attlist[2]!=null)
                            {
                                    att = atts.get(attlist[2]);
                                    if (att != null) ldapSurname = (String)att.get();
                            }

                            if (attlist[3]!=null)
                            {
                                    att = atts.get(attlist[3]);
                                    if (att != null) ldapPhone = (String)att.get();
                            }
                        }
                    }
                    catch (NamingException e)
                    {
                        // if the lookup fails go ahead and create a new record for them because the authentication
                        // succeeded
                        log.warn(LogManager.getHeader(context,
                                        "ldap_attribute_lookup", "type=failed_search "+e));
                        return true;
                    }
                }
                catch (NamingException e)
                {
                    log.warn(LogManager.getHeader(context,
                                        "ldap_authentication", "type=failed_auth "+e));
                    return false;
                }
                finally
                {
                    // Close the context when we're done
                    try
                    {
                        if (ctx != null)
                            ctx.close();
                    }
                    catch (NamingException e)
                    {
                    }
                }
            }
            else
            {
                return false;
            }

            return true;
        }


    }

    /*
     * Returns URL to which to redirect to obtain credentials (either password
     * prompt or e.g. HTTPS port for client cert.); null means no redirect.
     *
     * @param context
     *  DSpace context, will be modified (ePerson set) upon success.
     *
     * @param request
     *  The HTTP request that started this operation, or null if not applicable.
     *
     * @param response
     *  The HTTP response from the servlet method.
     *
     * @return fully-qualified URL
     */
    public String loginPageURL(Context context,
                            HttpServletRequest request,
                            HttpServletResponse response)
    {
        return response.encodeRedirectURL(request.getContextPath() +
                                          "/ldap-login");
    }

    /**
     * Returns message key for title of the "login" page, to use
     * in a menu showing the choice of multiple login methods.
     *
     * @param context
     *  DSpace context, will be modified (ePerson set) upon success.
     *
     * @return Message key to look up in i18n message catalog.
     */
    public String loginPageTitle(Context context)
    {
        return "org.dspace.eperson.LDAPAuthentication.title";
    }
}
TOP

Related Classes of org.dspace.authenticate.LDAPAuthentication$SpeakerToLDAP

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.