001: /*
002: * LDAPServlet.java
003: *
004: * Version: $Revision: 2168 $
005: *
006: * Date: $Date: 2007-08-27 17:40:09 -0500 (Mon, 27 Aug 2007) $
007: *
008: * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
009: * Institute of Technology. All rights reserved.
010: *
011: * Redistribution and use in source and binary forms, with or without
012: * modification, are permitted provided that the following conditions are
013: * met:
014: *
015: * - Redistributions of source code must retain the above copyright
016: * notice, this list of conditions and the following disclaimer.
017: *
018: * - Redistributions in binary form must reproduce the above copyright
019: * notice, this list of conditions and the following disclaimer in the
020: * documentation and/or other materials provided with the distribution.
021: *
022: * - Neither the name of the Hewlett-Packard Company nor the name of the
023: * Massachusetts Institute of Technology nor the names of their
024: * contributors may be used to endorse or promote products derived from
025: * this software without specific prior written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
030: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
032: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
033: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
034: * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
035: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
036: * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
037: * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
038: * DAMAGE.
039: */
040:
041: package org.dspace.app.webui.servlet;
042:
043: import java.io.IOException;
044: import java.sql.SQLException;
045: import javax.servlet.ServletException;
046: import javax.servlet.http.HttpServlet;
047: import javax.servlet.http.HttpServletRequest;
048: import javax.servlet.http.HttpServletResponse;
049:
050: import org.apache.log4j.Logger;
051:
052: import org.dspace.app.webui.util.Authenticate;
053: import org.dspace.app.webui.util.JSPManager;
054: import org.dspace.authenticate.AuthenticationManager;
055: import org.dspace.authorize.AuthorizeException;
056: import org.dspace.core.ConfigurationManager;
057: import org.dspace.core.Context;
058: import org.dspace.core.LogManager;
059: import org.dspace.eperson.EPerson;
060: import java.util.Hashtable;
061:
062: import javax.naming.directory.*;
063: import javax.naming.*;
064:
065: // Internal class to pass LDAP details from authentication method
066: class LDAPResult {
067: String email;
068: String givenName;
069: String surname;
070: String phone;
071: }
072:
073: /**
074: * LDAP username and password authentication servlet. Displays the
075: * login form <code>/login/ldap.jsp</code> on a GET,
076: * otherwise process the parameters as an ldap username and password.
077: *
078: * @author John Finlay (Brigham Young University)
079: * @version $Revision: 2168 $
080: */
081: public class LDAPServlet extends DSpaceServlet {
082: /** log4j logger */
083: private static Logger log = Logger.getLogger(LDAPServlet.class);
084:
085: protected void doDSGet(Context context, HttpServletRequest request,
086: HttpServletResponse response) throws ServletException,
087: IOException, SQLException, AuthorizeException {
088: // check if ldap is enables and forward to the correct login form
089: boolean ldap_enabled = ConfigurationManager
090: .getBooleanProperty("ldap.enable");
091: if (ldap_enabled)
092: JSPManager.showJSP(request, response, "/login/ldap.jsp");
093: else
094: JSPManager
095: .showJSP(request, response, "/login/password.jsp");
096: }
097:
098: protected void doDSPost(Context context,
099: HttpServletRequest request, HttpServletResponse response)
100: throws ServletException, IOException, SQLException,
101: AuthorizeException {
102: // Process the POSTed email and password
103: String netid = request.getParameter("login_netid");
104: String password = request.getParameter("login_password");
105:
106: // Locate the eperson
107: EPerson eperson = EPerson.findByNetid(context, netid
108: .toLowerCase());
109: EPerson eperson2 = EPerson.findByEmail(context, netid
110: .toLowerCase());
111: boolean loggedIn = false;
112:
113: // make sure ldap values are null with every request
114: LDAPResult ldapResult = new LDAPResult();
115:
116: ldapResult.givenName = null;
117: ldapResult.surname = null;
118: ldapResult.email = null;
119: ldapResult.phone = null;
120:
121: // if they entered a netid that matches an eperson
122: if (eperson != null && eperson.canLogIn()) {
123: // e-mail address corresponds to active account
124: if (eperson.getRequireCertificate()) {
125: // they must use a certificate
126: JSPManager.showJSP(request, response,
127: "/error/require-certificate.jsp");
128: return;
129: } else {
130: if (ldapAuthenticate(netid, password, context,
131: ldapResult)) {
132: // Logged in OK.
133: Authenticate.loggedIn(context, request, eperson);
134:
135: log.info(LogManager.getHeader(context, "login",
136: "type=ldap"));
137:
138: // resume previous request
139: Authenticate.resumeInterruptedRequest(request,
140: response);
141: return;
142: } else {
143: JSPManager.showJSP(request, response,
144: "/login/ldap-incorrect.jsp");
145: return;
146: }
147: }
148: }
149: // if they entered an email address that matches an eperson
150: else if (eperson2 != null && eperson2.canLogIn()) {
151: // e-mail address corresponds to active account
152: if (eperson2.getRequireCertificate()) {
153: // they must use a certificate
154: JSPManager.showJSP(request, response,
155: "/error/require-certificate.jsp");
156: return;
157: } else {
158: if (eperson2.checkPassword(password)) {
159: // Logged in OK.
160: Authenticate.loggedIn(context, request, eperson2);
161:
162: log.info(LogManager.getHeader(context, "login",
163: "type=password"));
164:
165: // resume previous request
166: Authenticate.resumeInterruptedRequest(request,
167: response);
168: return;
169: } else {
170: JSPManager.showJSP(request, response,
171: "/login/ldap-incorrect.jsp");
172: return;
173: }
174: }
175: }
176: // the user does not already exist so try and authenticate them with ldap and create an eperson for them
177: else {
178: if (ldapAuthenticate(netid, password, context, ldapResult)) {
179: if (ConfigurationManager
180: .getBooleanProperty("webui.ldap.autoregister")) {
181: // Register the new user automatically
182: log.info(LogManager.getHeader(context,
183: "autoregister", "netid=" + netid));
184:
185: if ((ldapResult.email != null)
186: && (!ldapResult.email.equals(""))) {
187: eperson = EPerson.findByEmail(context,
188: ldapResult.email);
189: if (eperson != null) {
190: log.info(LogManager.getHeader(context,
191: "failed_autoregister",
192: "type=ldap_but_already_email"));
193: JSPManager.showJSP(request, response,
194: "/register/already-registered.jsp");
195: return;
196: }
197: }
198: // TEMPORARILY turn off authorisation
199: context.setIgnoreAuthorization(true);
200: eperson = EPerson.create(context);
201: if ((ldapResult.email != null)
202: && (!ldapResult.email.equals("")))
203: eperson.setEmail(ldapResult.email);
204: else
205: eperson.setEmail(netid);
206: if ((ldapResult.givenName != null)
207: && (!ldapResult.givenName.equals("")))
208: eperson.setFirstName(ldapResult.givenName);
209: if ((ldapResult.surname != null)
210: && (!ldapResult.surname.equals("")))
211: eperson.setLastName(ldapResult.surname);
212: if ((ldapResult.phone != null)
213: && (!ldapResult.phone.equals("")))
214: eperson.setMetadata("phone", ldapResult.phone);
215: eperson.setNetid(netid);
216: eperson.setCanLogIn(true);
217: AuthenticationManager.initEPerson(context, request,
218: eperson);
219: eperson.update();
220: context.commit();
221: context.setIgnoreAuthorization(false);
222:
223: Authenticate.loggedIn(context, request, eperson);
224: log.info(LogManager.getHeader(context, "login",
225: "type=ldap-login"));
226: Authenticate.resumeInterruptedRequest(request,
227: response);
228: return;
229: } else {
230: // No auto-registration for valid certs
231: log.info(LogManager.getHeader(context,
232: "failed_login", "type=ldap_but_no_record"));
233: JSPManager.showJSP(request, response,
234: "/login/not-in-records.jsp");
235: return;
236: }
237: }
238: }
239:
240: // If we reach here, supplied email/password was duff.
241: log.info(LogManager.getHeader(context, "failed_login", "netid="
242: + netid));
243: JSPManager.showJSP(request, response,
244: "/login/ldap-incorrect.jsp");
245: }
246:
247: /**
248: * contact the ldap server and attempt to authenticate
249: */
250: protected boolean ldapAuthenticate(String netid, String password,
251: Context context, LDAPResult ldapResult) {
252: //--------- START LDAP AUTH SECTION -------------
253: if (!password.equals("")) {
254: String ldap_provider_url = ConfigurationManager
255: .getProperty("ldap.provider_url");
256: String ldap_id_field = ConfigurationManager
257: .getProperty("ldap.id_field");
258: String ldap_search_context = ConfigurationManager
259: .getProperty("ldap.search_context");
260: String ldap_object_context = ConfigurationManager
261: .getProperty("ldap.object_context");
262:
263: // Set up environment for creating initial context
264: Hashtable env = new Hashtable(11);
265: env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY,
266: "com.sun.jndi.ldap.LdapCtxFactory");
267: env.put(javax.naming.Context.PROVIDER_URL,
268: ldap_provider_url);
269:
270: // Authenticate
271: env.put(javax.naming.Context.SECURITY_AUTHENTICATION,
272: "simple");
273: env.put(javax.naming.Context.SECURITY_PRINCIPAL,
274: ldap_id_field + "=" + netid + ","
275: + ldap_object_context);
276: env
277: .put(javax.naming.Context.SECURITY_CREDENTIALS,
278: password);
279:
280: try {
281: // Create initial context
282: DirContext ctx = new InitialDirContext(env);
283:
284: String ldap_email_field = ConfigurationManager
285: .getProperty("ldap.email_field");
286: String ldap_givenname_field = ConfigurationManager
287: .getProperty("ldap.givenname_field");
288: String ldap_surname_field = ConfigurationManager
289: .getProperty("ldap.surname_field");
290: String ldap_phone_field = ConfigurationManager
291: .getProperty("ldap.phone_field");
292:
293: Attributes matchAttrs = new BasicAttributes(true);
294: matchAttrs
295: .put(new BasicAttribute(ldap_id_field, netid));
296:
297: String attlist[] = { ldap_email_field,
298: ldap_givenname_field, ldap_surname_field,
299: ldap_phone_field };
300:
301: // look up attributes
302: try {
303: NamingEnumeration answer = ctx.search(
304: ldap_search_context, matchAttrs, attlist);
305: while (answer.hasMore()) {
306: SearchResult sr = (SearchResult) answer.next();
307: Attributes atts = sr.getAttributes();
308: Attribute att;
309:
310: if (attlist[0] != null) {
311: att = atts.get(attlist[0]);
312: if (att != null)
313: ldapResult.email = (String) att.get();
314: }
315:
316: if (attlist[1] != null) {
317: att = atts.get(attlist[1]);
318: if (att != null)
319: ldapResult.givenName = (String) att
320: .get();
321: }
322:
323: if (attlist[2] != null) {
324: att = atts.get(attlist[2]);
325: if (att != null)
326: ldapResult.surname = (String) att.get();
327: }
328:
329: if (attlist[3] != null) {
330: att = atts.get(attlist[3]);
331: if (att != null)
332: ldapResult.phone = (String) att.get();
333: }
334: }
335: } catch (NamingException e) {
336: // if the lookup fails go ahead and create a new record for them because the authentication
337: // succeeded
338: log.warn(LogManager.getHeader(context,
339: "ldap_attribute_lookup",
340: "type=failed_search " + e));
341: return true;
342: }
343: // Close the context when we're done
344: ctx.close();
345: } catch (NamingException e) {
346: log
347: .warn(LogManager.getHeader(context,
348: "ldap_authentication",
349: "type=failed_auth " + e));
350: return false;
351: }
352: } else {
353: return false;
354: }
355: //--------- END LDAP AUTH SECTION -------------
356:
357: return true;
358: }
359: }
|