Project

General

Profile

1 503 bojilova
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An implementation of the AuthInterface interface that
4
 *             allows Metacat to use the LDAP protocol for
5
 *             directory services
6
 *  Copyright: 2000 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    Authors: Matt Jones
9
 *
10
 *   '$Author$'
11
 *     '$Date$'
12
 * '$Revision$'
13 669 jones
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 503 bojilova
 */
28
29
package edu.ucsb.nceas.metacat;
30
31
import java.net.ConnectException;
32
import javax.naming.AuthenticationException;
33
import javax.naming.Context;
34 787 bojilova
import javax.naming.NamingEnumeration;
35
import javax.naming.NamingException;
36 873 jones
import javax.naming.SizeLimitExceededException;
37 503 bojilova
import javax.naming.directory.Attribute;
38
import javax.naming.directory.Attributes;
39 504 jones
import javax.naming.directory.DirContext;
40
import javax.naming.directory.InitialDirContext;
41
import javax.naming.directory.SearchResult;
42 723 bojilova
import javax.naming.directory.SearchControls;
43 868 berkley
import javax.naming.ReferralException;
44 3022 sgarg
import javax.naming.ldap.InitialLdapContext;
45
import javax.naming.ldap.LdapContext;
46
import javax.naming.ldap.StartTlsRequest;
47
import javax.naming.ldap.StartTlsResponse;
48
import javax.net.ssl.SSLSession;
49 2666 sgarg
50
import org.apache.log4j.Logger;
51
52 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
53 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
54
55 5157 daigle
import java.io.IOException;
56 4080 daigle
import java.lang.InstantiationException;
57 1988 jones
import java.net.URLDecoder;
58 503 bojilova
import java.util.Iterator;
59
import java.util.HashMap;
60
import java.util.Hashtable;
61 730 bojilova
import java.util.Enumeration;
62 503 bojilova
import java.util.Set;
63
import java.util.Vector;
64
65
/**
66 4629 daigle
 * An implementation of the AuthInterface interface that allows Metacat to use
67
 * the LDAP protocol for directory services. The LDAP authentication service is
68
 * used to determine if a user is authenticated, and whether they are a member
69
 * of a particular group.
70 503 bojilova
 */
71 3155 cjones
public class AuthLdap implements AuthInterface {
72 4629 daigle
	private String ldapUrl;
73
	private String ldapsUrl;
74
	private String ldapBase;
75
	private String referral;
76
	private String ldapConnectTimeLimit;
77
	private int ldapSearchTimeLimit;
78
	private int ldapSearchCountLimit;
79
	private String currentReferralInfo;
80 5158 daigle
	Hashtable<String, String> env = new Hashtable<String, String>(11);
81 4629 daigle
	private Context rContext;
82
	private String userName;
83
	private String userPassword;
84
	ReferralException refExc;
85 503 bojilova
86 4629 daigle
	private static Logger logMetacat = Logger.getLogger(AuthLdap.class);
87
88
	/**
89 4080 daigle
	 * Construct an AuthLdap
90
	 */
91
	public AuthLdap() throws InstantiationException {
92
		// Read LDAP URI for directory service information
93
		try {
94 4587 daigle
			this.ldapUrl = PropertyService.getProperty("auth.url");
95
			this.ldapsUrl = PropertyService.getProperty("auth.surl");
96 4729 daigle
			this.ldapBase = PropertyService.getProperty("auth.base");
97 4080 daigle
			this.referral = PropertyService.getProperty("ldap.referral");
98
			this.ldapConnectTimeLimit = PropertyService
99
					.getProperty("ldap.connectTimeLimit");
100
			this.ldapSearchTimeLimit = Integer.parseInt(PropertyService
101
					.getProperty("ldap.searchTimeLimit"));
102
			this.ldapSearchCountLimit = Integer.parseInt(PropertyService
103
					.getProperty("ldap.searchCountLimit"));
104
		} catch (PropertyNotFoundException pnfe) {
105
			throw new InstantiationException(
106
					"Could not instantiate AuthLdap.  Property not found: "
107
							+ pnfe.getMessage());
108
		} catch (NumberFormatException nfe) {
109
			throw new InstantiationException(
110
					"Could not instantiate AuthLdap.  Bad number format when converting properties: "
111
							+ nfe.getMessage());
112
		}
113 728 bojilova
114 4080 daigle
		// Store referral info for use in building group DNs in getGroups()
115
		this.currentReferralInfo = "";
116
	}
117
118 4629 daigle
	/**
119 4080 daigle
	 * Determine if a user/password are valid according to the authentication
120
	 * service.
121
	 *
122
	 * @param user
123
	 *            the name of the principal to authenticate
124
	 * @param password
125
	 *            the password to use for authentication
126
	 * @returns boolean true if authentication successful, false otherwise
127
	 */
128 4629 daigle
	public boolean authenticate(String user, String password) throws ConnectException {
129
		String ldapUrl = this.ldapUrl;
130
		String ldapsUrl = this.ldapsUrl;
131
		String ldapBase = this.ldapBase;
132
		boolean authenticated = false;
133
		String identifier = user;
134 3022 sgarg
135 4629 daigle
		// get uid here.
136
		if (user.indexOf(",") == -1) {
137
			throw new ConnectException("Invalid LDAP user credential: " + user
138
					+ ".  Missing ','");
139
		}
140
		String uid = user.substring(0, user.indexOf(","));
141
		user = user.substring(user.indexOf(","), user.length());
142 3022 sgarg
143 5157 daigle
		logMetacat.debug("AuthLdap.authenticate - identifier: " + identifier +
144
				", uid: " + uid +", user: " + user);
145 3022 sgarg
146 4629 daigle
		try {
147
			// Check the usename as passed in
148 5157 daigle
			logMetacat.info("AuthLdap.authenticate - Calling ldapAuthenticate" +
149
				" with user as identifier: " + identifier);
150 3022 sgarg
151 4629 daigle
			authenticated = ldapAuthenticate(identifier, password, (new Boolean(
152
					PropertyService.getProperty("ldap.onlySecureConnection")))
153
					.booleanValue());
154
			// if not found, try looking up a valid DN then auth again
155
			if (!authenticated) {
156 5157 daigle
				logMetacat.info("AuthLdap.authenticate - Not Authenticated");
157
				logMetacat.info("AuthLdap.authenticate - Looking up DN for: " + identifier);
158 4629 daigle
				identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
159
				if (identifier == null) {
160 5157 daigle
					logMetacat.info("AuthLdap.authenticate - No DN found from getIdentifyingName");
161 4629 daigle
					return authenticated;
162
				}
163 503 bojilova
164 5157 daigle
				logMetacat.info("AuthLdap.authenticate - DN found from getIdentifyingName: " + identifier);
165 4629 daigle
				String decoded = URLDecoder.decode(identifier);
166 5157 daigle
				logMetacat.info("AuthLdap.authenticate - DN decoded: " + decoded);
167 4629 daigle
				identifier = decoded;
168
				String refUrl = "";
169
				String refBase = "";
170
				if (identifier.startsWith("ldap")) {
171 5157 daigle
					logMetacat.debug("AuthLdap.authenticate - identifier starts with \"ldap\"");
172 1005 jones
173 4629 daigle
					refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1);
174
					int position = identifier.indexOf(",");
175
					int position2 = identifier.indexOf(",", position + 1);
176 2058 sgarg
177 4629 daigle
					refBase = identifier.substring(position2 + 1);
178
					identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
179 3022 sgarg
180 5157 daigle
					logMetacat.info("AuthLdap.authenticate - Calling ldapAuthenticate: " +
181
						"with user as identifier: " + identifier + " and refUrl as: " +
182
						refUrl + " and refBase as: " + refBase);
183 934 tao
184 4629 daigle
					authenticated = ldapAuthenticate(identifier, password, refUrl,
185
							refBase, (new Boolean(PropertyService
186
									.getProperty("ldap.onlySecureReferalsConnection")))
187
									.booleanValue());
188
				} else {
189 5157 daigle
					logMetacat.info("AuthLdap.authenticate - identifier doesnt start with ldap");
190 4629 daigle
					identifier = identifier + "," + ldapBase;
191 852 jones
192 5157 daigle
					logMetacat.info("AuthLdap.authenticate - Calling ldapAuthenticate" +
193
							"with user as identifier: " + identifier);
194 3022 sgarg
195 4629 daigle
					authenticated = ldapAuthenticate(identifier, password, (new Boolean(
196
							PropertyService.getProperty("ldap.onlySecureConnection")))
197
							.booleanValue());
198
				}
199
			}
200 5157 daigle
		} catch (NullPointerException npe) {
201
			logMetacat.error("AuthLdap.authenticate - NullPointerException while authenticating in "
202
					+ "AuthLdap.authenticate: " + npe);
203
			npe.printStackTrace();
204 4080 daigle
205 5157 daigle
			throw new ConnectException("AuthLdap.authenticate - NullPointerException while authenticating in "
206
					+ "AuthLdap.authenticate: " + npe);
207
		} catch (NamingException ne) {
208
			logMetacat.error("AuthLdap.authenticate - Naming exception while authenticating in "
209
					+ "AuthLdap.authenticate: " + ne);
210
			ne.printStackTrace();
211
		} catch (PropertyNotFoundException pnfe) {
212
			logMetacat.error("AuthLdap.authenticate - Property exception while authenticating in "
213
					+ "AuthLdap.authenticate: " + pnfe.getMessage());
214 4629 daigle
		}
215 723 bojilova
216 4629 daigle
		return authenticated;
217
	}
218 2058 sgarg
219 4629 daigle
	/**
220
	 * Connect to the LDAP directory and do the authentication using the
221
	 * username and password as passed into the routine.
222
	 *
223
	 * @param identifier
224
	 *            the distinguished name to check against LDAP
225
	 * @param password
226
	 *            the password for authentication
227
	 */
228
	private boolean ldapAuthenticate(String identifier, String password,
229
			boolean secureConnectionOnly) throws ConnectException, NamingException,
230
			NullPointerException {
231
		return ldapAuthenticate(identifier, password, this.ldapsUrl, this.ldapBase,
232
				secureConnectionOnly);
233
	}
234 723 bojilova
235 4629 daigle
	/**
236
	 * Connect to the LDAP directory and do the authentication using the
237
	 * username and password as passed into the routine.
238
	 *
239
	 * @param identifier
240
	 *            the distinguished name to check against LDAP
241
	 * @param password
242
	 *            the password for authentication
243
	 */
244 723 bojilova
245 4629 daigle
	private boolean ldapAuthenticate(String dn, String password, String rootServer,
246
			String rootBase, boolean secureConnectionOnly) {
247 2058 sgarg
248 4629 daigle
		boolean authenticated = false;
249 2058 sgarg
250 4629 daigle
		String server = "";
251
		String userDN = "";
252 5157 daigle
		logMetacat.info("AuthLdap.ldapAuthenticate - dn is: " + dn);
253 2058 sgarg
254 4629 daigle
		int position = dn.lastIndexOf("/");
255 5157 daigle
		logMetacat.debug("AuthLdap.ldapAuthenticate - position is: " + position);
256 4629 daigle
		if (position == -1) {
257
			server = rootServer;
258
			if (dn.indexOf(userDN) < 0) {
259
				userDN = dn + "," + rootBase;
260
			} else {
261
				userDN = dn;
262
			}
263 5157 daigle
			logMetacat.info("AuthLdap.ldapAuthenticate - userDN is: " + userDN);
264 2116 sgarg
265 4629 daigle
		} else {
266
			server = dn.substring(0, position + 1);
267
			userDN = dn.substring(position + 1);
268 5157 daigle
			logMetacat.info("AuthLdap.ldapAuthenticate - server is: " + server);
269
			logMetacat.info("AuthLdap.ldapAuthenticate - userDN is: " + userDN);
270 4629 daigle
		}
271 2130 sgarg
272 5157 daigle
		logMetacat.warn("AuthLdap.ldapAuthenticate - Trying to authenticate: " +
273
				userDN + " Using server: " + server);
274 2058 sgarg
275 4629 daigle
		try {
276 5158 daigle
			Hashtable<String, String> env = new Hashtable<String, String>();
277 4629 daigle
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
278
			env.put(Context.PROVIDER_URL, server);
279
			env.put(Context.REFERRAL, "throw");
280 5158 daigle
281 4629 daigle
			try {
282 5158 daigle
				authenticated = authenticateTLS(env, userDN, password);
283
			} catch (AuthTLSException ate) {
284
				logMetacat.info("AuthLdap.ldapAuthenticate - error while negotiating TLS: "
285
						+ ate.getMessage());
286 723 bojilova
287 4629 daigle
				if (secureConnectionOnly) {
288
					return authenticated;
289 723 bojilova
290 4629 daigle
				} else {
291 5158 daigle
					authenticated = authenticateNonTLS(env, userDN, password);
292 4629 daigle
				}
293
			}
294
		} catch (AuthenticationException ae) {
295 5157 daigle
			logMetacat.warn("Authentication exception: " + ae.getMessage());
296 4629 daigle
			authenticated = false;
297
		} catch (javax.naming.InvalidNameException ine) {
298 5157 daigle
			logMetacat.error("AuthLdap.ldapAuthenticate - An invalid DN was provided: " + ine.getMessage());
299
		} catch (NamingException ne) {
300
			logMetacat.warn("AuthLdap.ldapAuthenticate - Caught NamingException in login: " + ne.getClass().getName());
301
			logMetacat.info(ne.toString() + "  " + ne.getRootCause());
302 4629 daigle
		}
303 503 bojilova
304 4629 daigle
		return authenticated;
305
	}
306 5158 daigle
307
	private boolean authenticateTLS(Hashtable<String, String> env, String userDN, String password)
308
			throws AuthTLSException{
309
		logMetacat.info("AuthLdap.authenticateTLS - Trying to authenticate with TLS");
310
		try {
311
			LdapContext ctx = null;
312
			double startTime;
313
			double stopTime;
314
			startTime = System.currentTimeMillis();
315
			ctx = new InitialLdapContext(env, null);
316
			// Start up TLS here so that we don't pass our jewels in
317
			// cleartext
318
			StartTlsResponse tls =
319
				(StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
320
			// tls.setHostnameVerifier(new SampleVerifier());
321
			SSLSession sess = tls.negotiate();
322
			ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
323
			ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
324
			ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
325
			ctx.reconnect(null);
326
			stopTime = System.currentTimeMillis();
327
			logMetacat.info("AuthLdap.authenticateTLS - Connection time thru "
328
					+ ldapsUrl + " was: " + (stopTime - startTime) / 1000 + " seconds.");
329
		} catch (NamingException ne) {
330
			throw new AuthTLSException("AuthLdap.authenticateTLS - Naming error when athenticating via TLS: " + ne.getMessage());
331
		} catch (IOException ioe) {
332
			throw new AuthTLSException("AuthLdap.authenticateTLS - I/O error when athenticating via TLS: " + ioe.getMessage());
333
		}
334
		return true;
335
	}
336
337
	private boolean authenticateNonTLS(Hashtable<String, String> env, String userDN, String password)
338
			throws NamingException {
339
		LdapContext ctx = null;
340
		double startTime;
341
		double stopTime;
342
343
		logMetacat.info("AuthLdap.authenticateNonTLS - Trying to authenticate without TLS");
344
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
345
		env.put(Context.SECURITY_PRINCIPAL, userDN);
346
		env.put(Context.SECURITY_CREDENTIALS, password);
347 2679 sgarg
348 5158 daigle
		startTime = System.currentTimeMillis();
349
		ctx = new InitialLdapContext(env, null);
350
		stopTime = System.currentTimeMillis();
351
		logMetacat.info("AuthLdap.authenticateNonTLS - Connection time thru " + ldapsUrl + " was: "
352
				+ (stopTime - startTime) / 1000 + " seconds.");
353
354
		return true;
355
	}
356
357 4629 daigle
	/**
358
	 * Get the identifying name for a given userid or name. This is the name
359
	 * that is used in conjunction withthe LDAP BaseDN to create a distinguished
360
	 * name (dn) for the record
361
	 *
362
	 * @param user
363
	 *            the user for which the identifying name is requested
364
	 * @returns String the identifying name for the user, or null if not found
365
	 */
366
	private String getIdentifyingName(String user, String ldapUrl, String ldapBase)
367
			throws NamingException {
368 2679 sgarg
369 4629 daigle
		String identifier = null;
370
		Hashtable env = new Hashtable();
371
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
372
		env.put(Context.REFERRAL, "throw");
373
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
374
		try {
375
			int position = user.indexOf(",");
376
			String uid = user.substring(user.indexOf("=") + 1, position);
377 5167 daigle
			logMetacat.info("AuthLdap.getIdentifyingName - uid is: " + uid);
378 4629 daigle
			String org = user.substring(user.indexOf("=", position + 1) + 1, user
379
					.indexOf(",", position + 1));
380 5167 daigle
			logMetacat.info("AuthLdap.getIdentifyingName - org is: " + org);
381 2697 sgarg
382 4629 daigle
			DirContext sctx = new InitialDirContext(env);
383
			SearchControls ctls = new SearchControls();
384
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
385
			String filter = "(&(uid=" + uid + ")(o=" + org + "))";
386 5167 daigle
			logMetacat.warn("AuthLdap.getIdentifyingName - Searching for DNs with following filter: " + filter);
387 2679 sgarg
388 4629 daigle
			for (boolean moreReferrals = true; moreReferrals;) {
389
				try {
390
					// Perform the search
391
					NamingEnumeration answer = sctx.search("", filter, ctls);
392 2679 sgarg
393 4629 daigle
					// Return the answer
394
					while (answer.hasMore()) {
395
						SearchResult sr = (SearchResult) answer.next();
396
						identifier = sr.getName();
397
						return identifier;
398
					}
399
					// The search completes with no more referrals
400
					moreReferrals = false;
401
				} catch (ReferralException e) {
402 5167 daigle
					logMetacat.info("AuthLdap.getIdentifyingName - Got referral: " + e.getReferralInfo());
403 4629 daigle
					// Point to the new context from the referral
404
					if (moreReferrals) {
405 5292 leinfelder
						// try following referral, skip if error
406
						boolean referralError = true;
407
						while (referralError) {
408
							try {
409
								sctx = (DirContext) e.getReferralContext();
410
								referralError = false;
411
							}
412
							catch (NamingException ne) {
413
								logMetacat.error("NamingException when getting referral contex. Skipping this referral. " + ne.getMessage());
414
								e.skipReferral();
415
								referralError = true;
416
							}
417
						}
418 4629 daigle
					}
419 5292 leinfelder
				}
420 4629 daigle
			}
421
		} catch (NamingException e) {
422 5167 daigle
			logMetacat.error("AuthLdap.getIdentifyingName - Naming exception while getting dn: " + e);
423 4629 daigle
			throw new NamingException("Naming exception in AuthLdap.getIdentifyingName: "
424
					+ e);
425
		}
426
		return identifier;
427
	}
428 2679 sgarg
429 4629 daigle
	/**
430
	 * Get all users from the authentication service
431
	 *
432
	 * @param user
433
	 *            the user for authenticating against the service
434
	 * @param password
435
	 *            the password for authenticating against the service
436
	 * @returns string array of all of the user names
437
	 */
438
	public String[][] getUsers(String user, String password) throws ConnectException {
439
		String[][] users = null;
440 2679 sgarg
441 4629 daigle
		// Identify service provider to use
442
		Hashtable env = new Hashtable(11);
443
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
444
		env.put(Context.REFERRAL, referral);
445
		env.put(Context.PROVIDER_URL, ldapUrl);
446
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
447 2679 sgarg
448 4629 daigle
		try {
449 2679 sgarg
450 4629 daigle
			// Create the initial directory context
451
			DirContext ctx = new InitialDirContext(env);
452 2679 sgarg
453 4629 daigle
			// Specify the attributes to match.
454
			// Users are objects that have the attribute
455
			// objectclass=InetOrgPerson.
456
			SearchControls ctls = new SearchControls();
457
			String[] attrIDs = { "dn", "cn", "o", "ou", "mail" };
458
			ctls.setReturningAttributes(attrIDs);
459
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
460
			ctls.setTimeLimit(ldapSearchTimeLimit);
461
			// ctls.setCountLimit(1000);
462
			String filter = "(objectClass=inetOrgPerson)";
463
			NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
464 723 bojilova
465 4629 daigle
			// Store the users in a vector
466
			Vector uvec = new Vector();
467
			Vector uname = new Vector();
468
			Vector uorg = new Vector();
469
			Vector uou = new Vector();
470
			Vector umail = new Vector();
471
			Attributes tempAttr = null;
472
			try {
473
				while (namingEnum.hasMore()) {
474
					SearchResult sr = (SearchResult) namingEnum.next();
475
					tempAttr = sr.getAttributes();
476 723 bojilova
477 4629 daigle
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
478
						uname.add((tempAttr.get("cn") + "").substring(4));
479
					} else {
480
						uname.add(tempAttr.get("cn") + "");
481
					}
482 723 bojilova
483 4629 daigle
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
484
						uorg.add((tempAttr.get("o") + "").substring(3));
485
					} else {
486
						uorg.add(tempAttr.get("o") + "");
487
					}
488 723 bojilova
489 4629 daigle
					if ((tempAttr.get("ou") + "").startsWith("ou: ")) {
490
						uou.add((tempAttr.get("ou") + "").substring(4));
491
					} else {
492
						uou.add(tempAttr.get("ou") + "");
493
					}
494 723 bojilova
495 4629 daigle
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
496
						umail.add((tempAttr.get("mail") + "").substring(6));
497
					} else {
498
						umail.add(tempAttr.get("mail") + "");
499
					}
500 723 bojilova
501 4629 daigle
					uvec.add(sr.getName() + "," + ldapBase);
502
				}
503
			} catch (SizeLimitExceededException slee) {
504 5167 daigle
				logMetacat.error("AuthLdap.getUsers - LDAP Server size limit exceeded. "
505 4629 daigle
						+ "Returning incomplete record set.");
506
			}
507 723 bojilova
508 4629 daigle
			// initialize users[]; fill users[]
509
			users = new String[uvec.size()][5];
510
			for (int i = 0; i < uvec.size(); i++) {
511
				users[i][0] = (String) uvec.elementAt(i);
512
				users[i][1] = (String) uname.elementAt(i);
513
				users[i][2] = (String) uorg.elementAt(i);
514
				users[i][3] = (String) uorg.elementAt(i);
515
				users[i][4] = (String) umail.elementAt(i);
516
			}
517 723 bojilova
518 4629 daigle
			// Close the context when we're done
519
			ctx.close();
520 723 bojilova
521 4629 daigle
		} catch (NamingException e) {
522 5167 daigle
			logMetacat.error("AuthLdap.getUsers - Problem getting users in AuthLdap.getUsers:" + e);
523 4629 daigle
			// e.printStackTrace(System.err);
524
			/*
525
			 * throw new ConnectException( "Problem getting users in
526
			 * AuthLdap.getUsers:" + e);
527
			 */
528
		}
529 723 bojilova
530 4629 daigle
		return users;
531
	}
532 503 bojilova
533 4629 daigle
	/**
534
	 * Get all users from the authentication service
535
	 *
536
	 * @param user
537
	 *            the user for authenticating against the service
538
	 * @param password
539
	 *            the password for authenticating against the service
540
	 * @returns string array of all of the user names
541
	 */
542
	public String[] getUserInfo(String user, String password) throws ConnectException {
543
		String[] userinfo = new String[3];
544 503 bojilova
545 4629 daigle
		// Identify service provider to use
546
		Hashtable env = new Hashtable(11);
547
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
548
		env.put(Context.REFERRAL, referral);
549
		env.put(Context.PROVIDER_URL, ldapUrl);
550 2058 sgarg
551 4629 daigle
		try {
552 991 tao
553 4629 daigle
			// Create the initial directory context
554
			DirContext ctx = new InitialDirContext(env);
555
			// Specify the attributes to match.
556
			// Users are objects that have the attribute
557
			// objectclass=InetOrgPerson.
558
			SearchControls ctls = new SearchControls();
559
			String[] attrIDs = { "cn", "o", "mail" };
560
			ctls.setReturningAttributes(attrIDs);
561
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
562
			// ctls.setCountLimit(1000);
563
			// create the filter based on the uid
564 2058 sgarg
565 4629 daigle
			String filter = null;
566 991 tao
567 4629 daigle
			if (user.indexOf("o=") > 0) {
568
				String tempStr = user.substring(user.indexOf("o="));
569
				filter = "(&(" + user.substring(0, user.indexOf(",")) + ")("
570
						+ tempStr.substring(0, tempStr.indexOf(",")) + "))";
571
			} else {
572
				filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
573
			}
574
			filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
575 503 bojilova
576 4629 daigle
			NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
577 503 bojilova
578 4629 daigle
			Attributes tempAttr = null;
579
			try {
580
				while (namingEnum.hasMore()) {
581
					SearchResult sr = (SearchResult) namingEnum.next();
582
					tempAttr = sr.getAttributes();
583 2058 sgarg
584 4629 daigle
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
585
						userinfo[0] = (tempAttr.get("cn") + "").substring(4);
586
					} else {
587
						userinfo[0] = (tempAttr.get("cn") + "");
588
					}
589 503 bojilova
590 4629 daigle
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
591
						userinfo[1] = (tempAttr.get("o") + "").substring(3);
592
					} else {
593
						userinfo[1] = (tempAttr.get("o") + "");
594
					}
595 2058 sgarg
596 4629 daigle
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
597
						userinfo[2] = (tempAttr.get("mail") + "").substring(6);
598
					} else {
599
						userinfo[2] = (tempAttr.get("mail") + "");
600
					}
601
				}
602
			} catch (SizeLimitExceededException slee) {
603 5167 daigle
				logMetacat.error("AuthLdap.getUserInfo - LDAP Server size limit exceeded. "
604 4629 daigle
						+ "Returning incomplete record set.");
605
			}
606 2058 sgarg
607 4629 daigle
			// Close the context when we're done
608
			ctx.close();
609 2058 sgarg
610 4629 daigle
		} catch (NamingException e) {
611 5167 daigle
			logMetacat.error("AuthLdap.getUserInfo - Problem getting users:" + e);
612 4629 daigle
			// e.printStackTrace(System.err);
613
			throw new ConnectException("Problem getting users in AuthLdap.getUsers:" + e);
614
		}
615 2058 sgarg
616 4629 daigle
		return userinfo;
617
	}
618 503 bojilova
619 4629 daigle
	/**
620
	 * Get the users for a particular group from the authentication service
621
	 *
622
	 * @param user
623
	 *            the user for authenticating against the service
624
	 * @param password
625
	 *            the password for authenticating against the service
626
	 * @param group
627
	 *            the group whose user list should be returned
628
	 * @returns string array of the user names belonging to the group
629
	 */
630
	public String[] getUsers(String user, String password, String group)
631
			throws ConnectException {
632
		String[] users = null;
633 503 bojilova
634 4629 daigle
		// Identify service provider to use
635
		Hashtable env = new Hashtable(11);
636
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
637
		env.put(Context.REFERRAL, referral);
638
		env.put(Context.PROVIDER_URL, ldapUrl);
639 504 jones
640 4629 daigle
		try {
641 2129 sgarg
642 4629 daigle
			// Create the initial directory context
643
			DirContext ctx = new InitialDirContext(env);
644 504 jones
645 4629 daigle
			// Specify the ids of the attributes to return
646
			String[] attrIDs = { "uniqueMember" };
647 504 jones
648 4629 daigle
			Attributes answer = ctx.getAttributes(group, attrIDs);
649 730 bojilova
650 4629 daigle
			Vector uvec = new Vector();
651
			try {
652
				for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) {
653
					Attribute attr = (Attribute) ae.next();
654
					for (NamingEnumeration e = attr.getAll(); e.hasMore(); uvec.add(e
655
							.next())) {
656
						;
657
					}
658
				}
659
			} catch (SizeLimitExceededException slee) {
660 5167 daigle
				logMetacat.error("AuthLdap.getUsers - LDAP Server size limit exceeded. "
661 4629 daigle
						+ "Returning incomplete record set.");
662
			}
663 2058 sgarg
664 4629 daigle
			// initialize users[]; fill users[]
665
			users = new String[uvec.size()];
666
			for (int i = 0; i < uvec.size(); i++) {
667
				users[i] = (String) uvec.elementAt(i);
668
			}
669 730 bojilova
670 4629 daigle
			// Close the context when we're done
671
			ctx.close();
672 730 bojilova
673 4629 daigle
		} catch (NamingException e) {
674 5167 daigle
			logMetacat.error("AuthLdap.getUsers - Problem getting users for a group in "
675 4629 daigle
					+ "AuthLdap.getUsers:" + e);
676
			/*
677
			 * throw new ConnectException( "Problem getting users for a group in
678
			 * AuthLdap.getUsers:" + e);
679
			 */
680
		}
681 2121 sgarg
682 4629 daigle
		return users;
683
	}
684 2121 sgarg
685 4629 daigle
	/**
686
	 * Get all groups from the authentication service
687
	 *
688
	 * @param user
689
	 *            the user for authenticating against the service
690
	 * @param password
691
	 *            the password for authenticating against the service
692
	 * @returns string array of the group names
693
	 */
694
	public String[][] getGroups(String user, String password) throws ConnectException {
695
		return getGroups(user, password, null);
696
	}
697 2121 sgarg
698 4629 daigle
	/**
699
	 * Get the groups for a particular user from the authentication service
700
	 *
701
	 * @param user
702
	 *            the user for authenticating against the service
703
	 * @param password
704
	 *            the password for authenticating against the service
705
	 * @param foruser
706
	 *            the user whose group list should be returned
707
	 * @returns string array of the group names
708
	 */
709
	public String[][] getGroups(String user, String password, String foruser)
710
			throws ConnectException {
711 2121 sgarg
712 5167 daigle
		logMetacat.debug("AuthLdap.getGroups - getGroups() called.");
713 2129 sgarg
714 4629 daigle
		// create vectors to store group and dscription values returned from the
715
		// ldap servers
716
		Vector gvec = new Vector();
717
		Vector desc = new Vector();
718
		Attributes tempAttr = null;
719
		Attributes rsrAttr = null;
720 2058 sgarg
721 4629 daigle
		// DURING getGroups(), DO WE NOT BIND USING userName AND userPassword??
722
		// NEED TO FIX THIS ...
723
		userName = user;
724
		userPassword = password;
725
		// Identify service provider to use
726
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
727
		env.put(Context.REFERRAL, "throw");
728
		env.put(Context.PROVIDER_URL, ldapUrl);
729
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
730 2121 sgarg
731 4629 daigle
		// Iterate through the referrals, handling NamingExceptions in the
732
		// outer catch statement, ReferralExceptions in the inner catch
733
		// statement
734
		try { // outer try
735 730 bojilova
736 4629 daigle
			// Create the initial directory context
737
			DirContext ctx = new InitialDirContext(env);
738 730 bojilova
739 4629 daigle
			// Specify the attributes to match.
740
			// Groups are objects with attribute objectclass=groupofuniquenames.
741
			// and have attribute uniquemember: uid=foruser,ldapbase.
742
			SearchControls ctls = new SearchControls();
743
			// Specify the ids of the attributes to return
744
			String[] attrIDs = { "cn", "o", "description" };
745
			ctls.setReturningAttributes(attrIDs);
746
			// set the ldap search scope
747
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
748
			// set a 10 second time limit on searches to limit non-responding
749
			// servers
750
			ctls.setTimeLimit(ldapSearchTimeLimit);
751
			// return at most 20000 entries
752
			ctls.setCountLimit(ldapSearchCountLimit);
753 504 jones
754 4629 daigle
			// build the ldap search filter that represents the "group" concept
755
			String filter = null;
756
			String gfilter = "(objectClass=groupOfUniqueNames)";
757
			if (null == foruser) {
758
				filter = gfilter;
759
			} else {
760
				filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
761
			}
762 5167 daigle
			logMetacat.info("AuthLdap.getGroups - group filter is: " + filter);
763 504 jones
764 4629 daigle
			// now, search and iterate through the referrals
765
			for (boolean moreReferrals = true; moreReferrals;) {
766
				try { // inner try
767 2058 sgarg
768 4629 daigle
					NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
769 2058 sgarg
770 4629 daigle
					// Print the groups
771
					while (namingEnum.hasMore()) {
772
						SearchResult sr = (SearchResult) namingEnum.next();
773 730 bojilova
774 4629 daigle
						tempAttr = sr.getAttributes();
775 730 bojilova
776 4629 daigle
						if ((tempAttr.get("description") + "")
777
								.startsWith("description: ")) {
778
							desc.add((tempAttr.get("description") + "").substring(13));
779
						} else {
780
							desc.add(tempAttr.get("description") + "");
781
						}
782 2058 sgarg
783 4629 daigle
						// check for an absolute URL value or an answer value
784
						// relative
785
						// to the target context
786
						if (!sr.getName().startsWith("ldap") && sr.isRelative()) {
787 5167 daigle
							logMetacat.debug("AuthLdap.getGroups - Search result entry is relative ...");
788 4629 daigle
							gvec.add(sr.getName() + "," + ldapBase);
789 5167 daigle
							logMetacat.info("AuthLdap.getGroups - group " + sr.getName() + "," + ldapBase
790 4629 daigle
									+ " added to the group vector");
791
						} else {
792 5167 daigle
							logMetacat.debug("AuthLdap.getGroups - Search result entry is absolute ...");
793 2058 sgarg
794 4629 daigle
							// search the top level directory for referral
795
							// objects and match
796
							// that of the search result's absolute URL. This
797
							// will let us
798
							// rebuild the group name from the search result,
799
							// referral point
800
							// in the top directory tree, and ldapBase.
801 2058 sgarg
802 4629 daigle
							// configure a new directory search first
803
							Hashtable envHash = new Hashtable(11);
804
							// Identify service provider to use
805
							envHash.put(Context.INITIAL_CONTEXT_FACTORY,
806
									"com.sun.jndi.ldap.LdapCtxFactory");
807
							envHash.put(Context.REFERRAL, "ignore");
808
							envHash.put(Context.PROVIDER_URL, ldapUrl);
809
							envHash.put("com.sun.jndi.ldap.connect.timeout",
810
									ldapConnectTimeLimit);
811 725 bojilova
812 4629 daigle
							try {
813
								// Create the initial directory context
814
								DirContext DirCtx = new InitialDirContext(envHash);
815 2058 sgarg
816 4629 daigle
								SearchControls searchCtls = new SearchControls();
817
								// Specify the ids of the attributes to return
818
								String[] attrNames = { "o" };
819
								searchCtls.setReturningAttributes(attrNames);
820
								// set the ldap search scope - only look for top
821
								// level referrals
822
								searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
823
								// set a time limit on searches to limit
824
								// non-responding servers
825
								searchCtls.setTimeLimit(ldapSearchTimeLimit);
826
								// return the configured number of entries
827
								searchCtls.setCountLimit(ldapSearchCountLimit);
828 503 bojilova
829 4629 daigle
								// Specify the attributes to match.
830
								// build the ldap search filter to match
831
								// referral entries that
832
								// match the search result
833
								String rFilter = "(&(objectClass=referral)(ref="
834
										+ currentReferralInfo.substring(0,
835
												currentReferralInfo.indexOf("?")) + "))";
836 5167 daigle
								logMetacat.debug("AuthLdap.getGroups - rFilter is: " + rFilter);
837 503 bojilova
838 4629 daigle
								NamingEnumeration rNamingEnum = DirCtx.search(ldapBase,
839
										rFilter, searchCtls);
840 2058 sgarg
841 4629 daigle
								while (rNamingEnum.hasMore()) {
842
									SearchResult rsr = (SearchResult) rNamingEnum.next();
843
									rsrAttr = rsr.getAttributes();
844 5167 daigle
									logMetacat.debug("AuthLdap.getGroups - referral search result is: "
845 4629 daigle
											+ rsr.toString());
846 725 bojilova
847 4629 daigle
									// add the returned groups to the group
848
									// vector. Test the
849
									// syntax of the returned attributes -
850
									// sometimes they are
851
									// preceded with the attribute id and a
852
									// colon
853
									if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
854
										gvec.add("cn="
855
												+ (tempAttr.get("cn") + "").substring(4)
856
												+ "," + "o="
857
												+ (rsrAttr.get("o") + "").substring(3)
858
												+ "," + ldapBase);
859 5167 daigle
										logMetacat.info("AuthLdap.getGroups - group "
860 4629 daigle
												+ (tempAttr.get("cn") + "").substring(4)
861
												+ "," + "o="
862
												+ (rsrAttr.get("o") + "").substring(3)
863
												+ "," + ldapBase
864
												+ " added to the group vector");
865
									} else {
866
										gvec.add("cn=" + tempAttr.get("cn") + "," + "o="
867
												+ rsrAttr.get("o") + "," + ldapBase);
868 5167 daigle
										logMetacat.info("AuthLdap.getGroups - group " + "cn="
869 4629 daigle
												+ tempAttr.get("cn") + "," + "o="
870
												+ rsrAttr.get("o") + "," + ldapBase
871
												+ " added to the group vector");
872
									}
873
								}
874 723 bojilova
875 4629 daigle
							} catch (NamingException nameEx) {
876 5167 daigle
								logMetacat.debug("AuthLdap.getGroups - Caught naming exception: ");
877 4629 daigle
								nameEx.printStackTrace(System.err);
878
							}
879
						}
880
					}// end while
881 725 bojilova
882 4629 daigle
					moreReferrals = false;
883
884
				} catch (ReferralException re) {
885
886
					logMetacat
887 5167 daigle
							.info("AuthLdap.getGroups -  caught referral exception: "
888 4629 daigle
									+ re.getReferralInfo());
889
					this.currentReferralInfo = (String) re.getReferralInfo();
890
891
					// set moreReferrals to true and set the referral context
892
					moreReferrals = true;
893 5293 leinfelder
894
					// try following referral, skip if error
895
					boolean referralError = true;
896
					while (referralError) {
897
						try {
898
							ctx = (DirContext) re.getReferralContext();
899
							referralError = false;
900
						}
901
						catch (NamingException ne) {
902
							logMetacat.error("NamingException when getting referral contex. Skipping this referral. " + ne.getMessage());
903
							re.skipReferral();
904
							referralError = true;
905
						}
906
					}
907 4629 daigle
908
				}// end inner try
909
			}// end for
910
911
			// close the context now that all initial and referral
912
			// searches are processed
913
			ctx.close();
914
915
		} catch (NamingException e) {
916
917
			// naming exceptions get logged, groups are returned
918 5167 daigle
			logMetacat.info("AuthLdap.getGroups - caught naming exception: ");
919 4629 daigle
			e.printStackTrace(System.err);
920
921
		} finally {
922
			// once all referrals are followed, report and return the groups
923
			// found
924 5167 daigle
			logMetacat.warn("AuthLdap.getGroups - The user is in the following groups: " + gvec.toString());
925 4629 daigle
			// build and return the groups array
926
			String groups[][] = new String[gvec.size()][2];
927
			for (int i = 0; i < gvec.size(); i++) {
928
				groups[i][0] = (String) gvec.elementAt(i);
929
				groups[i][1] = (String) desc.elementAt(i);
930
			}
931
			return groups;
932
		}// end outer try
933
	}
934
935
	/**
936
	 * Get attributes describing a user or group
937
	 *
938
	 * @param foruser
939
	 *            the user for which the attribute list is requested
940
	 * @returns HashMap a map of attribute name to a Vector of values
941
	 */
942
	public HashMap<String, Vector<String>> getAttributes(String foruser)
943
			throws ConnectException {
944
		return getAttributes(null, null, foruser);
945
	}
946
947
	/**
948
	 * Get attributes describing a user or group
949
	 *
950
	 * @param user
951
	 *            the user for authenticating against the service
952
	 * @param password
953
	 *            the password for authenticating against the service
954
	 * @param foruser
955
	 *            the user whose attributes should be returned
956
	 * @returns HashMap a map of attribute name to a Vector of values
957
	 */
958
	public HashMap<String, Vector<String>> getAttributes(String user, String password,
959
			String foruser) throws ConnectException {
960
		HashMap<String, Vector<String>> attributes = new HashMap<String, Vector<String>>();
961
		String ldapUrl = this.ldapUrl;
962
		String ldapBase = this.ldapBase;
963
		String userident = foruser;
964
965
		// Identify service provider to use
966
		Hashtable env = new Hashtable(11);
967
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
968
		env.put(Context.REFERRAL, referral);
969
		env.put(Context.PROVIDER_URL, ldapUrl);
970
971
		try {
972
973
			// Create the initial directory context
974
			DirContext ctx = new InitialDirContext(env);
975
976
			// Ask for all attributes of the user
977
			// Attributes attrs = ctx.getAttributes(userident);
978
			Attributes attrs = ctx.getAttributes(foruser);
979
980
			// Print all of the attributes
981
			NamingEnumeration en = attrs.getAll();
982
			while (en.hasMore()) {
983
				Attribute att = (Attribute) en.next();
984
				Vector<String> values = new Vector();
985
				String attName = att.getID();
986
				NamingEnumeration attvalues = att.getAll();
987
				while (attvalues.hasMore()) {
988
					String value = (String) attvalues.next();
989
					values.add(value);
990
				}
991
				attributes.put(attName, values);
992
			}
993
994
			// Close the context when we're done
995
			ctx.close();
996
		} catch (NamingException e) {
997 5167 daigle
			logMetacat.error("AuthLdap.getAttributes - Problem getting attributes:"
998 4629 daigle
					+ e);
999
			throw new ConnectException(
1000
					"Problem getting attributes in AuthLdap.getAttributes:" + e);
1001
		}
1002
1003
		return attributes;
1004
	}
1005
1006
	/**
1007
	 * Get list of all subtrees holding Metacat's groups and users starting from
1008
	 * the Metacat LDAP root, i.e.
1009
	 * ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
1010
	 */
1011
	private Hashtable getSubtrees(String user, String password, String ldapUrl,
1012
			String ldapBase) throws ConnectException {
1013 5157 daigle
		logMetacat.debug("AuthLdap.getSubtrees - getting subtrees for user: " + user +
1014
				", ldapUrl: " + ldapUrl + ", ldapBase: " + ldapBase);
1015 4629 daigle
		Hashtable trees = new Hashtable();
1016
1017
		// Identify service provider to use
1018
		Hashtable env = new Hashtable(11);
1019
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1020
		// env.put(Context.REFERRAL, referral);
1021
		// Using 'ignore' here instead of 'follow' as 'ignore' seems
1022
		// to do the job better. 'follow' was not bringing up the UCNRS
1023
		// and PISCO tree whereas 'ignore' brings up the tree.
1024
1025
		env.put(Context.REFERRAL, "ignore");
1026
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
1027
1028
		try {
1029
1030
			// Create the initial directory context
1031
			DirContext ctx = new InitialDirContext(env);
1032
1033
			// Specify the ids of the attributes to return
1034
			String[] attrIDs = { "o", "ref" };
1035
			SearchControls ctls = new SearchControls();
1036
			ctls.setReturningAttributes(attrIDs);
1037
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
1038
1039
			// Specify the attributes to match.
1040
			// Subtrees from the main server are found as objects with attribute
1041
			// objectclass=organization or objectclass=referral to the subtree
1042
			// resided on other server.
1043
			String filter = "(|(objectclass=organization)(objectclass=referral))";
1044
1045
			// Search for objects in the current context
1046
			NamingEnumeration namingEnum = ctx.search("", filter, ctls);
1047
1048
			// Print the subtrees' <ldapURL, baseDN>
1049
			while (namingEnum.hasMore()) {
1050
1051
				SearchResult sr = (SearchResult) namingEnum.next();
1052 5157 daigle
				logMetacat.debug("AuthLdap.getSubtrees - search result: " + sr.toString());
1053 4629 daigle
1054
				Attributes attrs = sr.getAttributes();
1055
				NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref"
1056
															// attrs
1057
1058
				if (enum1.hasMore()) {
1059
					Attribute attr = (Attribute) enum1.next();
1060
					String attrValue = (String) attr.get();
1061
					String attrName = (String) attr.getID();
1062
1063
					if (enum1.hasMore()) {
1064
						attr = (Attribute) enum1.next();
1065
						String refValue = (String) attr.get();
1066
						String refName = (String) attr.getID();
1067
						if (ldapBase.startsWith(refName + "=" + refValue)) {
1068
							trees.put(ldapBase, attrValue.substring(0, attrValue
1069
									.lastIndexOf("/") + 1));
1070
						} else {
1071
							// this is a referral - so organization name is
1072 5157 daigle
							// appended in front of the ldapbase.... later it is
1073
							// stripped out in getPrincipals
1074
							trees.put("[" + refName + "=" + refValue + "]" +
1075
									attrValue.substring(attrValue.lastIndexOf("/") + 1,
1076 4629 daigle
											attrValue.length()), attrValue.substring(0,
1077 5157 daigle
													attrValue.lastIndexOf("/") + 1));
1078 4629 daigle
1079
							// trees.put(refName + "=" + refValue + "," +
1080 5157 daigle
							// ldapBase, attrValue.substring(0, attrValue.lastIndexOf("/")
1081 4629 daigle
							// + 1));
1082
						}
1083
1084
					} else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
1085
						trees.put(ldapBase, ldapUrl);
1086
					} else {
1087
						if (sr.isRelative()) {
1088
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1089
									ldapUrl);
1090
						} else {
1091
							String referenceURL = sr.getName();
1092
							referenceURL = referenceURL.substring(0, referenceURL
1093
									.lastIndexOf("/") + 1);
1094
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1095
									referenceURL);
1096
						}
1097
1098
					}
1099
				}
1100
			}
1101
1102
			// Close the context when we're done
1103
			ctx.close();
1104
1105
		} catch (NamingException e) {
1106 5157 daigle
			logMetacat.error("AuthLdap.getSubtrees - Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1107 4629 daigle
			throw new ConnectException(
1108
					"Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1109
		}
1110
1111
		return trees;
1112
	}
1113
1114
	/**
1115
	 * Get all groups and users from authentication scheme. The output is
1116
	 * formatted in XML.
1117
	 *
1118
	 * @param user
1119
	 *            the user which requests the information
1120
	 * @param password
1121
	 *            the user's password
1122
	 */
1123
	public String getPrincipals(String user, String password) throws ConnectException {
1124
		StringBuffer out = new StringBuffer();
1125
1126
		out.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
1127
		out.append("<principals>\n");
1128
1129
		/*
1130
		 * get all subtrees first in the current dir context and then the
1131
		 * Metacat users under them
1132
		 */
1133
		Hashtable subtrees = getSubtrees(user, password, this.ldapUrl, this.ldapBase);
1134
1135
		Enumeration keyEnum = subtrees.keys();
1136
		while (keyEnum.hasMoreElements()) {
1137
			this.ldapBase = (String) keyEnum.nextElement();
1138
			this.ldapUrl = (String) subtrees.get(ldapBase);
1139 5157 daigle
			logMetacat.info("AuthLdap.getPrincipals - ldapBase: " + ldapBase +
1140
					", ldapUrl: " + ldapUrl);
1141 4629 daigle
			/*
1142
			 * code to get the organization name from ldapBase
1143
			 */
1144
			String orgName = this.ldapBase;
1145
			if (orgName.startsWith("[")) {
1146
				// if orgName starts with [ then it is a referral URL...
1147 5157 daigle
				// (see code in getSubtress) hence orgName can be retrieved by
1148
				// getting the string between 'o=' and ']' also the string between
1149
				// [ and ] needs to be striped out from this.ldapBase
1150 4629 daigle
				this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1151
				if (orgName != null && orgName.indexOf("o=") > -1) {
1152
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1153
					orgName = orgName.substring(0, orgName.indexOf("]"));
1154
				}
1155
			} else {
1156
				// else it is not referral
1157
				// hence orgName can be retrieved by getting the string between
1158
				// 'o=' and ','
1159
				if (orgName != null && orgName.indexOf("o=") > -1) {
1160
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1161
					if (orgName.indexOf(",") > -1) {
1162
						orgName = orgName.substring(0, orgName.indexOf(","));
1163
					}
1164
				}
1165
			}
1166 5157 daigle
			logMetacat.info("AuthLdap.getPrincipals - org name is  " + orgName);
1167 4629 daigle
			out.append("  <authSystem URI=\"" + this.ldapUrl + this.ldapBase
1168
					+ "\" organization=\"" + orgName + "\">\n");
1169
1170
			// get all groups for directory context
1171
			String[][] groups = getGroups(user, password);
1172 5157 daigle
			logMetacat.debug("AuthLdap.getPrincipals - after getting groups " + groups);
1173 4629 daigle
			String[][] users = getUsers(user, password);
1174 5157 daigle
			logMetacat.debug("AuthLdap.getPrincipals - after getting users " + users);
1175 4629 daigle
			int userIndex = 0;
1176
1177
			// for the groups and users that belong to them
1178
			if (groups != null && users != null && groups.length > 0) {
1179
				for (int i = 0; i < groups.length; i++) {
1180
					out.append("    <group>\n");
1181
					out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1182
					out.append("      <description>" + groups[i][1] + "</description>\n");
1183
					String[] usersForGroup = getUsers(user, password, groups[i][0]);
1184
					for (int j = 0; j < usersForGroup.length; j++) {
1185
						userIndex = searchUser(usersForGroup[j], users);
1186
						out.append("      <user>\n");
1187
1188
						if (userIndex < 0) {
1189
							out.append("        <username>" + usersForGroup[j]
1190
									+ "</username>\n");
1191
						} else {
1192
							out.append("        <username>" + users[userIndex][0]
1193
									+ "</username>\n");
1194
							out.append("        <name>" + users[userIndex][1]
1195
									+ "</name>\n");
1196
							out.append("        <organization>" + users[userIndex][2]
1197
									+ "</organization>\n");
1198
							if (users[userIndex][3].compareTo("null") != 0) {
1199
								out.append("      <organizationUnitName>"
1200
										+ users[userIndex][3]
1201
										+ "</organizationUnitName>\n");
1202
							}
1203
							out.append("        <email>" + users[userIndex][4]
1204
									+ "</email>\n");
1205
						}
1206
1207
						out.append("      </user>\n");
1208
					}
1209
					out.append("    </group>\n");
1210
				}
1211
			}
1212
1213
			if (users != null) {
1214
				// for the users not belonging to any grou8p
1215
				for (int j = 0; j < users.length; j++) {
1216
					out.append("    <user>\n");
1217
					out.append("      <username>" + users[j][0] + "</username>\n");
1218
					out.append("      <name>" + users[j][1] + "</name>\n");
1219
					out
1220
							.append("      <organization>" + users[j][2]
1221
									+ "</organization>\n");
1222
					if (users[j][3].compareTo("null") != 0) {
1223
						out.append("      <organizationUnitName>" + users[j][3]
1224
								+ "</organizationUnitName>\n");
1225
					}
1226
					out.append("      <email>" + users[j][4] + "</email>\n");
1227
					out.append("    </user>\n");
1228
				}
1229
			}
1230
1231
			out.append("  </authSystem>\n");
1232
		}
1233
		out.append("</principals>");
1234
		return out.toString();
1235
	}
1236
1237
	/**
1238
	 * Method for getting index of user DN in User info array
1239
	 */
1240
	int searchUser(String user, String userGroup[][]) {
1241
		for (int j = 0; j < userGroup.length; j++) {
1242
			if (user.compareTo(userGroup[j][0]) == 0) {
1243
				return j;
1244
			}
1245
		}
1246
		return -1;
1247
	}
1248
1249
	public void testCredentials(String dn, String password, String rootServer,
1250
			String rootBase) throws NamingException {
1251
1252
		String server = "";
1253
		String userDN = "";
1254
		logMetacat.debug("dn is: " + dn);
1255
1256
		int position = dn.lastIndexOf("/");
1257 5167 daigle
		logMetacat.debug("AuthLdap.testCredentials - position is: " + position);
1258 4629 daigle
		if (position == -1) {
1259
			server = rootServer;
1260
			if (dn.indexOf(userDN) < 0) {
1261
				userDN = dn + "," + rootBase;
1262
			} else {
1263
				userDN = dn;
1264
			}
1265 5167 daigle
			logMetacat.debug("AuthLdap.testCredentials - userDN is: " + userDN);
1266 4629 daigle
1267
		} else {
1268
			server = dn.substring(0, position + 1);
1269
			userDN = dn.substring(position + 1);
1270 5167 daigle
			logMetacat.debug("AuthLdap.testCredentials - server is: " + server);
1271
			logMetacat.debug("AuthLdap.testCredentials - userDN is: " + userDN);
1272 4629 daigle
		}
1273
1274 5167 daigle
		logMetacat.debug("AuthLdap.testCredentials - Trying to authenticate: " + userDN + " using server: " + server);
1275 4629 daigle
1276
		// /* try {
1277
		LdapContext ctx = null;
1278
1279
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1280
		env.put(Context.REFERRAL, "follow");
1281
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
1282
		env.put(Context.SECURITY_PRINCIPAL, userDN);
1283
		env.put(Context.SECURITY_CREDENTIALS, password);
1284
		env.put(Context.PROVIDER_URL, rootServer);
1285
1286
		ctx = new InitialLdapContext(env, null);
1287
1288
	}
1289
1290
	/**
1291 4080 daigle
	 * Test method for the class
1292
	 */
1293
	public static void main(String[] args) {
1294 871 jones
1295 4080 daigle
		// Provide a user, such as: "Matt Jones", or "jones"
1296
		String user = args[0];
1297
		String password = args[1];
1298
		String org = args[2];
1299 871 jones
1300 5167 daigle
		logMetacat.warn("AuthLdap.main - Creating session...");
1301 4080 daigle
		AuthLdap authservice = null;
1302
		try {
1303
			authservice = new AuthLdap();
1304
		} catch (Exception e) {
1305 5167 daigle
			logMetacat.error("AuthLdap.main - Could not instantiate AuthLdap: " + e.getMessage());
1306 4080 daigle
			return;
1307
		}
1308 5167 daigle
		logMetacat.warn("AuthLdap.main - Session exists...");
1309 2058 sgarg
1310 4080 daigle
		boolean isValid = false;
1311
		try {
1312 5167 daigle
			logMetacat.warn("AuthLdap.main - Authenticating...");
1313 4080 daigle
			isValid = authservice.authenticate(user, password);
1314
			if (isValid) {
1315 5167 daigle
				logMetacat.warn("AuthLdap.main - Authentication successful for: " + user);
1316 4080 daigle
			} else {
1317 5167 daigle
				logMetacat.warn("AuthLdap.main - Authentication failed for: " + user);
1318 4080 daigle
			}
1319 873 jones
1320 4080 daigle
			// Get attributes for the user
1321
			if (isValid) {
1322 5167 daigle
				logMetacat.info("AuthLdap.main - Getting attributes for user....");
1323 4629 daigle
				HashMap userInfo = authservice.getAttributes(user, password, user);
1324 4080 daigle
				// Print all of the attributes
1325 4629 daigle
				Iterator attList = (Iterator) (((Set) userInfo.keySet()).iterator());
1326 4080 daigle
				while (attList.hasNext()) {
1327
					String att = (String) attList.next();
1328
					Vector values = (Vector) userInfo.get(att);
1329
					Iterator attvalues = values.iterator();
1330
					while (attvalues.hasNext()) {
1331
						String value = (String) attvalues.next();
1332 5167 daigle
						logMetacat.warn("AuthLdap.main - " + att + ": " + value);
1333 4080 daigle
					}
1334
				}
1335
			}
1336 873 jones
1337 4080 daigle
			// get the groups
1338
			if (isValid) {
1339 5167 daigle
				logMetacat.warn("AuthLdap.main - Getting all groups....");
1340 4080 daigle
				String[][] groups = authservice.getGroups(user, password);
1341 5167 daigle
				logMetacat.info("AuthLdap.main - Groups found: " + groups.length);
1342 4080 daigle
				for (int i = 0; i < groups.length; i++) {
1343 5167 daigle
					logMetacat.info("AuthLdap.main - Group " + i + ": " + groups[i][0]);
1344 4080 daigle
				}
1345
			}
1346 2058 sgarg
1347 4080 daigle
			// get the groups for the user
1348
			String savedGroup = null;
1349
			if (isValid) {
1350 5167 daigle
				logMetacat.warn("AuthLdap.main - Getting groups for user....");
1351 4080 daigle
				String[][] groups = authservice.getGroups(user, password, user);
1352 5167 daigle
				logMetacat.info("AuthLdap.main - Groups found: " + groups.length);
1353 4080 daigle
				for (int i = 0; i < groups.length; i++) {
1354 5167 daigle
					logMetacat.info("AuthLdap.main - Group " + i + ": " + groups[i][0]);
1355 4080 daigle
					savedGroup = groups[i][0];
1356
				}
1357
			}
1358
1359
			// get the users for a group
1360
			if (isValid) {
1361 5167 daigle
				logMetacat.warn("AuthLdap.main - Getting users for group....");
1362
				logMetacat.info("AuthLdap.main - Group: " + savedGroup);
1363 4629 daigle
				String[] users = authservice.getUsers(user, password, savedGroup);
1364 5167 daigle
				logMetacat.info("AuthLdap.main - Users found: " + users.length);
1365 4080 daigle
				for (int i = 0; i < users.length; i++) {
1366 5167 daigle
					logMetacat.warn("AuthLdap.main - User " + i + ": " + users[i]);
1367 4080 daigle
				}
1368
			}
1369
1370
			// get all users
1371
			if (isValid) {
1372 5167 daigle
				logMetacat.warn("AuthLdap.main - Getting all users ....");
1373 4080 daigle
				String[][] users = authservice.getUsers(user, password);
1374 5167 daigle
				logMetacat.info("AuthLdap.main - Users found: " + users.length);
1375 4080 daigle
1376
			}
1377
1378
			// get the whole list groups and users in XML format
1379
			if (isValid) {
1380 5167 daigle
				logMetacat.warn("AuthLdap.main - Trying principals....");
1381 4080 daigle
				authservice = new AuthLdap();
1382
				String out = authservice.getPrincipals(user, password);
1383
				java.io.File f = new java.io.File("principals.xml");
1384
				java.io.FileWriter fw = new java.io.FileWriter(f);
1385
				java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1386
				buff.write(out);
1387
				buff.flush();
1388
				buff.close();
1389
				fw.close();
1390 5167 daigle
				logMetacat.warn("AuthLdap.main - Finished getting principals.");
1391 4080 daigle
			}
1392
1393
		} catch (ConnectException ce) {
1394 5167 daigle
			logMetacat.error("AuthLdap.main - " + ce.getMessage());
1395 4080 daigle
		} catch (java.io.IOException ioe) {
1396 5167 daigle
			logMetacat.error("AuthLdap.main - I/O Error writing to file principals.txt: "
1397 4080 daigle
					+ ioe.getMessage());
1398
		} catch (InstantiationException ie) {
1399 5167 daigle
			logMetacat.error("AuthLdap.main - Instantiation error writing to file principals.txt: "
1400 4629 daigle
					+ ie.getMessage());
1401 4080 daigle
		}
1402
	}
1403
1404 4629 daigle
	/**
1405
	 * This method will be called by start a thread. It can handle if a referral
1406
	 * exception happend.
1407
	 */
1408 503 bojilova
}