Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements administrative methods 
4
 *  Copyright: 2008 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Michael Daigle
7
 * 
8
 *   '$Author: daigle $'
9
 *     '$Date: 2008-11-24 15:42:55 -0800 (Mon, 24 Nov 2008) $'
10
 * '$Revision: 4627 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacat.util;
28

    
29
import java.util.Calendar;
30
import java.util.Vector;
31

    
32
import javax.naming.AuthenticationException;
33
import javax.naming.NamingException;
34
import javax.servlet.http.HttpServletRequest;
35
import javax.servlet.http.HttpSession;
36

    
37
import edu.ucsb.nceas.metacat.AuthLdap;
38
import edu.ucsb.nceas.metacat.AuthSession;
39
import edu.ucsb.nceas.metacat.service.PropertyService;
40
import edu.ucsb.nceas.metacat.service.SessionService;
41
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
42
import edu.ucsb.nceas.utilities.StringUtil;
43

    
44
public class AuthUtil {
45

    
46
	private static Vector<String> administrators = null;
47
	private static Vector<String> moderators = null;
48
	private static Vector<String> allowedSubmitters = null;
49
	private static Vector<String> deniedSubmitters = null;
50

    
51
	/**
52
	 * private constructor - all methods are static so there is no no need to
53
	 * instantiate.
54
	 */
55
	private AuthUtil() {}
56

    
57
	/**
58
	 * Get the administrators from metacat.properties
59
	 * 
60
	 * @return a Vector of Strings holding the administrators
61
	 */
62
	public static Vector<String> getAdministrators() throws UtilException {
63
		if (administrators == null) {
64
			populateAdministrators();
65
		}
66
		return administrators;
67
	}
68
	
69
	/**
70
	 * Get the allowed submitters from metacat.properties
71
	 * 
72
	 * @return a Vector of Strings holding the submitters
73
	 */
74
	public static Vector<String> getAllowedSubmitters() throws UtilException {
75
		if (allowedSubmitters == null) {			
76
			populateAllowedSubmitters();	
77
		}
78
		return allowedSubmitters;
79
	}
80
	
81
	/**
82
	 * Get the denied submitters from metacat.properties
83
	 * 
84
	 * @return a Vector of Strings holding the denied submitters
85
	 */
86
	public static Vector<String> getDeniedSubmitters() throws UtilException {
87
		if (deniedSubmitters == null) {
88
			populateDeniedSubmitters();
89
		}
90
		return deniedSubmitters;
91
	}
92
	
93
	/**
94
	 * Get the moderators from metacat.properties
95
	 * 
96
	 * @return a Vector of Strings holding the moderators
97
	 */
98
	public static Vector<String> getModerators() throws UtilException {
99
		if (moderators == null) {
100
			populateModerators();
101
		}
102
		return moderators;
103
	}
104
	
105
	/**
106
	 * Get the vector of administrator credentials from metacat.properties
107
	 * and put into global administrators list
108
	 */
109
	private static void populateAdministrators() throws UtilException {
110
		String administratorString = null;
111
		try {
112
			administratorString = 
113
				PropertyService.getProperty("auth.administrators");
114
		} catch (PropertyNotFoundException pnfe) {
115
			throw new UtilException("Could not get metacat property: auth.administrators. "
116
							+ "There will be no registered metacat adminstrators: "
117
							+ pnfe.getMessage());
118
		}
119
		administrators = StringUtil.toVector(administratorString, ':');
120
	}
121
	
122
	/**
123
	 * Get the vector of allowed submitter credentials from metacat.properties
124
	 * and put into global allowedSubmitters list
125
	 */
126
	private static void populateAllowedSubmitters() throws UtilException {
127
		String allowedSubmitterString = null;
128
		try {
129
			allowedSubmitterString = PropertyService.getProperty("auth.allowedSubmitters");
130
		} catch (PropertyNotFoundException pnfe) {
131
			throw new UtilException("Could not get metacat property: auth.allowedSubmitters. "
132
					+ "Anyone will be allowed to submit: "
133
					+ pnfe.getMessage());
134
		}		
135
		allowedSubmitters = StringUtil.toVector(allowedSubmitterString, ':');		
136
	}
137
	
138
	/**
139
	 * Get the vector of denied submitter credentials from metacat.properties
140
	 * and put into global deniedSubmitters list
141
	 */
142
	private static void populateDeniedSubmitters() throws UtilException {
143
		String deniedSubmitterString = null;
144
		try {
145
			deniedSubmitterString = PropertyService.getProperty("auth.deniedSubmitters");
146
		} catch (PropertyNotFoundException pnfe) {
147
			throw new UtilException("Could not get metacat property: auth.deniedSubmitters: "
148
					+ pnfe.getMessage());
149
		}		
150
		deniedSubmitters = StringUtil.toVector(deniedSubmitterString, ':');		
151
	}
152
	
153
	/**
154
	 * Get the vector of moderator credentials from metacat.properties
155
	 * and put into global administrators list
156
	 */
157
	private static void populateModerators() throws UtilException {
158
		String moderatorString = null;
159
		try {
160
			moderatorString = 
161
				PropertyService.getProperty("auth.moderators");
162
		} catch (PropertyNotFoundException pnfe) {
163
			throw new UtilException("Could not get metacat property: auth.moderators. "
164
							+ "There will be no registered metacat moderators: "
165
							+ pnfe.getMessage());
166
		}
167
		moderators = StringUtil.toVector(moderatorString, ':');
168
	}
169

    
170
//	/**
171
//	 * Validate connectivity to the ldap server. This does not test user
172
//	 * authentication. Validation methods return a string error message if there
173
//	 * is an issue. This allows the calling code to run several validations and
174
//	 * compile the errors into a list that can be displayed on a web page if
175
//	 * desired.
176
//	 * 
177
//	 * @param ldapurl
178
//	 *            the url of the ldap server
179
//	 * @param ldapbase
180
//	 *            the ldap base value to test
181
//	 * @return a string holding error message if validation fails.
182
//	 */
183
//	public static String validateLDAPConnectivity(String ldapurl,
184
//			String ldapbase) {
185
//		try {
186
//			AuthLdap authLdap = new AuthLdap();
187
//			authLdap.testCredentials(
188
//					"uid=bogusname,o=NCEAS,dc=ecoinformatics,dc=org",
189
//					"boguspassword", ldapurl, ldapbase);
190
//		} catch (AuthenticationException ae) {
191
//			// Do nothing here. We are using dummy uid and password, so we
192
//			// expect authentication exceptions
193
//		} catch (javax.naming.InvalidNameException ine) {
194
//			return "An invalid domain name was provided: " + ine.getMessage();
195
//		} catch (NamingException ne) {
196
//			return "An invalid ldap name was provided: " + ne.getMessage();
197
//		} catch (InstantiationException ie) {
198
//			return "Could not instantiate AuthLdap: " + ie.getMessage();
199
//		}
200
//
201
//		return null;
202
//	}
203

    
204
	/**
205
	 * log the user in against ldap.  If the login is successful, add
206
	 * the session information to the session list in SessionUtil.
207
	 * 
208
	 * @param request the http request.
209
	 */
210
	public static boolean logUserIn(HttpServletRequest request, String userName, String password) throws UtilException {
211
		AuthSession authSession = null;
212

    
213
		// make sure we have username and password.
214
		if (userName == null || password == null) {
215
			throw new UtilException("null username, password, or dn list when logging user in");
216
		}
217

    
218
		// put the login credentials into an LDAP string
219
//		String ldapString = createLDAPString(userName, organization, dnList);
220

    
221
		// Create auth session
222
		try {
223
			authSession = new AuthSession();
224
		} catch (Exception e) {
225
			throw new UtilException("Could not instantiate AuthSession: "
226
					+ e.getMessage());
227
		}
228
		// authenticate user against ldap
229
		boolean isValid = authSession.authenticate(request, userName,
230
				password);
231
		
232
		// if login was successful, add the session information to the 
233
		// global session list.
234
		if (isValid) {
235
			HttpSession session = authSession.getSessions();
236
			String sessionId = session.getId();
237
			SessionService.registerSession(sessionId, 
238
					(String) session.getAttribute("username"), 
239
					(String[]) session.getAttribute("groupnames"),
240
					(String) session.getAttribute("password"));
241
		}
242
		
243
		return isValid;
244
	}
245

    
246
	/**
247
	 * Checks to see if the user is logged in by grabbing the session from the
248
	 * request and seeing if it exists in the global session list.
249
	 * 
250
	 * @param request the http request that holds the login session
251
	 * @return boolean that is true if the user is logged in, false otherwise
252
	 */
253
	public static boolean isUserLoggedIn(HttpServletRequest request) throws UtilException{
254
		SessionData sessionData = null;
255
		String sessionId = request.getSession().getId();
256

    
257
		try {
258

    
259
			if (sessionId != null && SessionService.isSessionRegistered(sessionId)) {
260
				// get the registered session data
261
				sessionData = SessionService.getRegisteredSession(sessionId);
262

    
263
				// get the timeout limit
264
				String sessionTimeout = PropertyService.getProperty("auth.timeoutMinutes");
265
				int sessionTimeoutInt = Integer.parseInt(sessionTimeout);
266

    
267
				// get the last time the session was accessed
268
				Calendar lastAccessedTime = sessionData.getLastAccessedTime();
269
				// get the current time and set back "sessionTimoutInt" minutes
270
				Calendar now = Calendar.getInstance();
271
				now.add(Calendar.MINUTE, 0 - sessionTimeoutInt);
272

    
273
				// if the last accessed time is before now minus the timeout,
274
				// the session has expired. Unregister it and return false.
275
				if (lastAccessedTime.before(now)) {
276
					SessionService.unRegisterSession(sessionId);
277
					return false;
278
				}
279

    
280
				return true;
281
			}
282
			
283
		} catch (PropertyNotFoundException pnfe) {
284
			throw new UtilException("Could not determine if user is logged in because " 
285
					+ "of property error: " + pnfe.getMessage());
286
		} catch (NumberFormatException nfe) {
287
			throw new UtilException("Could not determine if user is logged in because " 
288
					+ "of number conversion error: " + nfe.getMessage());
289
		}
290

    
291
		return false;
292
	}
293

    
294
	/**
295
	 * Checks to see if the user is logged in as admin by first checking if the
296
	 * user is logged in and then seeing if the user's account is on the
297
	 * administrators list in metacat.properties.
298
	 * 
299
	 * @param request
300
	 *            the http request that holds the login session
301
	 * @return boolean that is true if the user is logged in as admin, false
302
	 *         otherwise
303
	 */
304
	public static boolean isUserLoggedInAsAdmin(HttpServletRequest request) throws UtilException {
305
		if (!isUserLoggedIn(request)) {
306
			return false;
307
		}
308

    
309
		String userName = getUserName(request);
310
		boolean isAdmin = isAdministrator(userName, null);
311

    
312
		return isAdmin;
313
	}
314

    
315
	/**
316
	 * Gets the user name from the login session on the http request
317
	 * 
318
	 * @param request
319
	 *            the http request that holds the login session
320
	 * @return String that holds the user name
321
	 */
322
	public static String getUserName(HttpServletRequest request) {
323
		String userName = (String)request.getSession().getAttribute("username");
324

    
325
		return userName;
326
	}
327

    
328
	/**
329
	 * Gets the user group names from the login session on the http request
330
	 * 
331
	 * @param request
332
	 *            the http request that holds the login session
333
	 * @return String array that holds the user groups
334
	 */
335
	public static String[] getGroupNames(HttpServletRequest request) {
336
		String sessionId = request.getSession().getId();;
337
		SessionData sessionData = SessionService.getRegisteredSession(sessionId);
338
		String[] groupNames = { "" };
339

    
340
		if (sessionData != null) {
341
			groupNames = sessionData.getGroupNames();
342
		}
343

    
344
		return groupNames;
345
	}
346

    
347
	/**
348
	 * Creates an ldap credentail string from the username, organization
349
	 * and dn list.
350
	 * 
351
	 * @param username the user name
352
	 * @param organization the organization
353
	 * @param dnList a list of dns
354
	 * @return String holding the ldap login string
355
	 */	
356
	public static String createLDAPString(String username, String organization,
357
			Vector<String> dnList) throws UtilException {
358

    
359
		if (username == null || organization == null || dnList == null || dnList.size() == 0) {
360
			throw new UtilException("Could not generate LDAP user string.  One of the following is null: username, organization or dnlist");
361
		}
362

    
363
		String ldapString = "uid=" + username + ",o=" + organization;
364

    
365
		for (String dn : dnList) {
366
			ldapString += "," + dn;
367
		}
368

    
369
		return ldapString;
370
	}
371

    
372
	/**
373
	 * Reports whether LDAP is fully configured.
374
	 * 
375
	 * @return a boolean that is true if all sections are configured and false
376
	 *         otherwise
377
	 */
378
	public static boolean isAuthConfigured() throws UtilException {
379
		String authConfiguredString = PropertyService.UNCONFIGURED;
380
		try {
381
			authConfiguredString = PropertyService.getProperty("configutil.authConfigured");
382
		} catch (PropertyNotFoundException pnfe) {
383
			throw new UtilException("Could not determine if LDAP is configured: "
384
					+ pnfe.getMessage());
385
		}
386
		return !authConfiguredString.equals(PropertyService.UNCONFIGURED);
387
	}
388

    
389
	/**
390
	 * Check if the specified user is part of the administrators list
391
	 * 
392
	 * @param username
393
	 *            the user login credentails
394
	 * @param groups
395
	 *            a list of the user's groups
396
	 */
397
	public static boolean isAdministrator(String username, String[] groups)
398
			throws UtilException {
399
		return onAccessList(getAdministrators(), username, groups);
400
	}
401

    
402
	/**
403
	 * Check if the specified user is part of the moderators list
404
	 * 
405
	 * @param username
406
	 *            the user login credentails
407
	 * @param groups
408
	 *            a list of the user's groups
409
	 */
410
	public static boolean isModerator(String username, String[] groups) throws UtilException{
411
		return onAccessList(getModerators(), username, groups);
412
	}
413

    
414
	/**
415
	 * Check if the specified user is part of the moderators list
416
	 * 
417
	 * @param username
418
	 *            the user login credentails
419
	 * @param groups
420
	 *            a list of the user's groups
421
	 */
422
	public static boolean isAllowedSubmitter(String username, String[] groups)
423
			throws UtilException {
424
		if (getAllowedSubmitters().size() == 0) {
425
			// no allowedSubmitters list specified -
426
			// hence everyone should be allowed
427
			return true;
428
		}
429
		return (onAccessList(getAllowedSubmitters(), username, groups));
430
	}
431

    
432
	/**
433
	 * Check if the specified user is part of the moderators list
434
	 * 
435
	 * @param username
436
	 *            the user login credentails
437
	 * @param groups
438
	 *            a list of the user's groups
439
	 */
440
	public static boolean isDeniedSubmitter(String username, String[] groups)
441
			throws UtilException {
442
		return (onAccessList(getDeniedSubmitters(), username, groups));
443
	}
444

    
445
	/**
446
	 * Check if the specified user can insert the document
447
	 * 
448
	 * @param username
449
	 *            the user login credentails
450
	 * @param groups
451
	 *            a list of the user's groups
452
	 */
453
	public static boolean canInsertOrUpdate(String username, String[] groups)
454
			throws UtilException {
455
		return (isAllowedSubmitter(username, groups) && !isDeniedSubmitter(username,
456
				groups));
457
	}
458

    
459
	/**
460
	 * Check if the user is on a given access list.  This is true if either the 
461
	 * user or the user's group is on the list.
462
	 * 
463
	 * @param accessList the list we want to check against
464
	 * @param username the name of the user we want to check
465
	 * @param groups a list of the user's groups
466
	 */
467
	private static boolean onAccessList(Vector<String> accessList, String username,
468
			String[] groups) {
469

    
470
		// this should never happen.  All calls to this method should use the 
471
		// appropriate getter to retrieve the accessList.  That should guarentee
472
		// that the access is at least an empty Vector.
473
		if (accessList == null) {
474
			return false;
475
		}
476

    
477
		// Check that the user is authenticated as an administrator account
478
		for (String accessString : accessList) {
479
			// check the given admin dn is a group dn...
480
			if (groups != null && accessString.startsWith("cn=")) {
481
				// is a group dn
482
				for (int j = 0; j < groups.length; j++) {
483
					if (groups[j].equals(accessString)) {
484
						return true;
485
					}
486
				}
487
			} else {
488
				// is a user dn
489
				if (username != null && username.equals(accessString)) {
490
					return true;
491
				}
492
			}
493
		}
494
		return false;
495
	}
496

    
497
}
(1-1/11)