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
	Hashtable env = new Hashtable(11);
81
	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
		LdapContext ctx = null;
276
		double startTime;
277
		double stopTime;
278
		try {
279
			Hashtable env = new Hashtable();
280
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
281
			env.put(Context.PROVIDER_URL, server);
282
			env.put(Context.REFERRAL, "throw");
283
			try {
284 723 bojilova
285 4629 daigle
				startTime = System.currentTimeMillis();
286
				ctx = new InitialLdapContext(env, null);
287
				// Start up TLS here so that we don't pass our jewels in
288
				// cleartext
289
				StartTlsResponse tls = (StartTlsResponse) ctx
290
						.extendedOperation(new StartTlsRequest());
291
				// tls.setHostnameVerifier(new SampleVerifier());
292
				SSLSession sess = tls.negotiate();
293
				ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
294
				ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
295
				ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
296
				ctx.reconnect(null);
297
				stopTime = System.currentTimeMillis();
298 5157 daigle
				logMetacat.info("AuthLdap.ldapAuthenticate - Connection time thru " + ldapsUrl + " was: "
299 4629 daigle
						+ (stopTime - startTime) / 1000 + " seconds.");
300
				authenticated = true;
301 5157 daigle
			} catch (IOException ioe) {
302
				logMetacat.info("AuthLdap.ldapAuthenticate - Caught IOException in login while negotiating TLS: "
303 4629 daigle
						+ ioe.getMessage());
304 723 bojilova
305 4629 daigle
				if (secureConnectionOnly) {
306
					return authenticated;
307 723 bojilova
308 4629 daigle
				} else {
309 5157 daigle
					logMetacat.info("AuthLdap.ldapAuthenticate - Trying to authenticate without TLS");
310 4629 daigle
					env.put(Context.SECURITY_AUTHENTICATION, "simple");
311
					env.put(Context.SECURITY_PRINCIPAL, userDN);
312
					env.put(Context.SECURITY_CREDENTIALS, password);
313 723 bojilova
314 4629 daigle
					startTime = System.currentTimeMillis();
315
					ctx = new InitialLdapContext(env, null);
316
					stopTime = System.currentTimeMillis();
317 5157 daigle
					logMetacat.info("AuthLdap.ldapAuthenticate - Connection time thru " + ldapsUrl + " was: "
318 4629 daigle
							+ (stopTime - startTime) / 1000 + " seconds.");
319
					authenticated = true;
320
				}
321
			}
322
		} catch (AuthenticationException ae) {
323 5157 daigle
			logMetacat.warn("Authentication exception: " + ae.getMessage());
324 4629 daigle
			authenticated = false;
325
		} catch (javax.naming.InvalidNameException ine) {
326 5157 daigle
			logMetacat.error("AuthLdap.ldapAuthenticate - An invalid DN was provided: " + ine.getMessage());
327
		} catch (NamingException ne) {
328
			logMetacat.warn("AuthLdap.ldapAuthenticate - Caught NamingException in login: " + ne.getClass().getName());
329
			logMetacat.info(ne.toString() + "  " + ne.getRootCause());
330 4629 daigle
		}
331 503 bojilova
332 4629 daigle
		return authenticated;
333
	}
334 2679 sgarg
335 4629 daigle
	/**
336
	 * Get the identifying name for a given userid or name. This is the name
337
	 * that is used in conjunction withthe LDAP BaseDN to create a distinguished
338
	 * name (dn) for the record
339
	 *
340
	 * @param user
341
	 *            the user for which the identifying name is requested
342
	 * @returns String the identifying name for the user, or null if not found
343
	 */
344
	private String getIdentifyingName(String user, String ldapUrl, String ldapBase)
345
			throws NamingException {
346 2679 sgarg
347 4629 daigle
		String identifier = null;
348
		Hashtable env = new Hashtable();
349
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
350
		env.put(Context.REFERRAL, "throw");
351
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
352
		try {
353
			int position = user.indexOf(",");
354
			String uid = user.substring(user.indexOf("=") + 1, position);
355
			logMetacat.info("uid is: " + uid);
356
			String org = user.substring(user.indexOf("=", position + 1) + 1, user
357
					.indexOf(",", position + 1));
358
			logMetacat.info("org is: " + org);
359 2697 sgarg
360 4629 daigle
			DirContext sctx = new InitialDirContext(env);
361
			SearchControls ctls = new SearchControls();
362
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
363
			String filter = "(&(uid=" + uid + ")(o=" + org + "))";
364
			logMetacat.warn("Searching for DNs with following filter: " + filter);
365 2679 sgarg
366 4629 daigle
			for (boolean moreReferrals = true; moreReferrals;) {
367
				try {
368
					// Perform the search
369
					NamingEnumeration answer = sctx.search("", filter, ctls);
370 2679 sgarg
371 4629 daigle
					// Return the answer
372
					while (answer.hasMore()) {
373
						SearchResult sr = (SearchResult) answer.next();
374
						identifier = sr.getName();
375
						return identifier;
376
					}
377
					// The search completes with no more referrals
378
					moreReferrals = false;
379
				} catch (ReferralException e) {
380
					logMetacat.info("Got referral: " + e.getReferralInfo());
381
					// Point to the new context from the referral
382
					if (moreReferrals) {
383
						sctx = (DirContext) e.getReferralContext();
384
					}
385
				}
386
			}
387
		} catch (NamingException e) {
388
			logMetacat.error("Naming exception while getting dn: " + e);
389
			throw new NamingException("Naming exception in AuthLdap.getIdentifyingName: "
390
					+ e);
391
		}
392
		return identifier;
393
	}
394 2679 sgarg
395 4629 daigle
	/**
396
	 * Get all users from the authentication service
397
	 *
398
	 * @param user
399
	 *            the user for authenticating against the service
400
	 * @param password
401
	 *            the password for authenticating against the service
402
	 * @returns string array of all of the user names
403
	 */
404
	public String[][] getUsers(String user, String password) throws ConnectException {
405
		String[][] users = null;
406 2679 sgarg
407 4629 daigle
		// Identify service provider to use
408
		Hashtable env = new Hashtable(11);
409
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
410
		env.put(Context.REFERRAL, referral);
411
		env.put(Context.PROVIDER_URL, ldapUrl);
412
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
413 2679 sgarg
414 4629 daigle
		try {
415 2679 sgarg
416 4629 daigle
			// Create the initial directory context
417
			DirContext ctx = new InitialDirContext(env);
418 2679 sgarg
419 4629 daigle
			// Specify the attributes to match.
420
			// Users are objects that have the attribute
421
			// objectclass=InetOrgPerson.
422
			SearchControls ctls = new SearchControls();
423
			String[] attrIDs = { "dn", "cn", "o", "ou", "mail" };
424
			ctls.setReturningAttributes(attrIDs);
425
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
426
			ctls.setTimeLimit(ldapSearchTimeLimit);
427
			// ctls.setCountLimit(1000);
428
			String filter = "(objectClass=inetOrgPerson)";
429
			NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
430 723 bojilova
431 4629 daigle
			// Store the users in a vector
432
			Vector uvec = new Vector();
433
			Vector uname = new Vector();
434
			Vector uorg = new Vector();
435
			Vector uou = new Vector();
436
			Vector umail = new Vector();
437
			Attributes tempAttr = null;
438
			try {
439
				while (namingEnum.hasMore()) {
440
					SearchResult sr = (SearchResult) namingEnum.next();
441
					tempAttr = sr.getAttributes();
442 723 bojilova
443 4629 daigle
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
444
						uname.add((tempAttr.get("cn") + "").substring(4));
445
					} else {
446
						uname.add(tempAttr.get("cn") + "");
447
					}
448 723 bojilova
449 4629 daigle
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
450
						uorg.add((tempAttr.get("o") + "").substring(3));
451
					} else {
452
						uorg.add(tempAttr.get("o") + "");
453
					}
454 723 bojilova
455 4629 daigle
					if ((tempAttr.get("ou") + "").startsWith("ou: ")) {
456
						uou.add((tempAttr.get("ou") + "").substring(4));
457
					} else {
458
						uou.add(tempAttr.get("ou") + "");
459
					}
460 723 bojilova
461 4629 daigle
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
462
						umail.add((tempAttr.get("mail") + "").substring(6));
463
					} else {
464
						umail.add(tempAttr.get("mail") + "");
465
					}
466 723 bojilova
467 4629 daigle
					uvec.add(sr.getName() + "," + ldapBase);
468
				}
469
			} catch (SizeLimitExceededException slee) {
470
				logMetacat.error("LDAP Server size limit exceeded. "
471
						+ "Returning incomplete record set.");
472
			}
473 723 bojilova
474 4629 daigle
			// initialize users[]; fill users[]
475
			users = new String[uvec.size()][5];
476
			for (int i = 0; i < uvec.size(); i++) {
477
				users[i][0] = (String) uvec.elementAt(i);
478
				users[i][1] = (String) uname.elementAt(i);
479
				users[i][2] = (String) uorg.elementAt(i);
480
				users[i][3] = (String) uorg.elementAt(i);
481
				users[i][4] = (String) umail.elementAt(i);
482
			}
483 723 bojilova
484 4629 daigle
			// Close the context when we're done
485
			ctx.close();
486 723 bojilova
487 4629 daigle
		} catch (NamingException e) {
488
			logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
489
			// e.printStackTrace(System.err);
490
			/*
491
			 * throw new ConnectException( "Problem getting users in
492
			 * AuthLdap.getUsers:" + e);
493
			 */
494
		}
495 723 bojilova
496 4629 daigle
		return users;
497
	}
498 503 bojilova
499 4629 daigle
	/**
500
	 * Get all users from the authentication service
501
	 *
502
	 * @param user
503
	 *            the user for authenticating against the service
504
	 * @param password
505
	 *            the password for authenticating against the service
506
	 * @returns string array of all of the user names
507
	 */
508
	public String[] getUserInfo(String user, String password) throws ConnectException {
509
		String[] userinfo = new String[3];
510 503 bojilova
511 4629 daigle
		// Identify service provider to use
512
		Hashtable env = new Hashtable(11);
513
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
514
		env.put(Context.REFERRAL, referral);
515
		env.put(Context.PROVIDER_URL, ldapUrl);
516 2058 sgarg
517 4629 daigle
		try {
518 991 tao
519 4629 daigle
			// Create the initial directory context
520
			DirContext ctx = new InitialDirContext(env);
521
			// Specify the attributes to match.
522
			// Users are objects that have the attribute
523
			// objectclass=InetOrgPerson.
524
			SearchControls ctls = new SearchControls();
525
			String[] attrIDs = { "cn", "o", "mail" };
526
			ctls.setReturningAttributes(attrIDs);
527
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
528
			// ctls.setCountLimit(1000);
529
			// create the filter based on the uid
530 2058 sgarg
531 4629 daigle
			String filter = null;
532 991 tao
533 4629 daigle
			if (user.indexOf("o=") > 0) {
534
				String tempStr = user.substring(user.indexOf("o="));
535
				filter = "(&(" + user.substring(0, user.indexOf(",")) + ")("
536
						+ tempStr.substring(0, tempStr.indexOf(",")) + "))";
537
			} else {
538
				filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
539
			}
540
			filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
541 503 bojilova
542 4629 daigle
			NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
543 503 bojilova
544 4629 daigle
			Attributes tempAttr = null;
545
			try {
546
				while (namingEnum.hasMore()) {
547
					SearchResult sr = (SearchResult) namingEnum.next();
548
					tempAttr = sr.getAttributes();
549 2058 sgarg
550 4629 daigle
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
551
						userinfo[0] = (tempAttr.get("cn") + "").substring(4);
552
					} else {
553
						userinfo[0] = (tempAttr.get("cn") + "");
554
					}
555 503 bojilova
556 4629 daigle
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
557
						userinfo[1] = (tempAttr.get("o") + "").substring(3);
558
					} else {
559
						userinfo[1] = (tempAttr.get("o") + "");
560
					}
561 2058 sgarg
562 4629 daigle
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
563
						userinfo[2] = (tempAttr.get("mail") + "").substring(6);
564
					} else {
565
						userinfo[2] = (tempAttr.get("mail") + "");
566
					}
567
				}
568
			} catch (SizeLimitExceededException slee) {
569
				logMetacat.error("LDAP Server size limit exceeded. "
570
						+ "Returning incomplete record set.");
571
			}
572 2058 sgarg
573 4629 daigle
			// Close the context when we're done
574
			ctx.close();
575 2058 sgarg
576 4629 daigle
		} catch (NamingException e) {
577
			logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
578
			// e.printStackTrace(System.err);
579
			throw new ConnectException("Problem getting users in AuthLdap.getUsers:" + e);
580
		}
581 2058 sgarg
582 4629 daigle
		return userinfo;
583
	}
584 503 bojilova
585 4629 daigle
	/**
586
	 * Get the users for a particular group from the authentication service
587
	 *
588
	 * @param user
589
	 *            the user for authenticating against the service
590
	 * @param password
591
	 *            the password for authenticating against the service
592
	 * @param group
593
	 *            the group whose user list should be returned
594
	 * @returns string array of the user names belonging to the group
595
	 */
596
	public String[] getUsers(String user, String password, String group)
597
			throws ConnectException {
598
		String[] users = null;
599 503 bojilova
600 4629 daigle
		// Identify service provider to use
601
		Hashtable env = new Hashtable(11);
602
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
603
		env.put(Context.REFERRAL, referral);
604
		env.put(Context.PROVIDER_URL, ldapUrl);
605 504 jones
606 4629 daigle
		try {
607 2129 sgarg
608 4629 daigle
			// Create the initial directory context
609
			DirContext ctx = new InitialDirContext(env);
610 504 jones
611 4629 daigle
			// Specify the ids of the attributes to return
612
			String[] attrIDs = { "uniqueMember" };
613 504 jones
614 4629 daigle
			Attributes answer = ctx.getAttributes(group, attrIDs);
615 730 bojilova
616 4629 daigle
			Vector uvec = new Vector();
617
			try {
618
				for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) {
619
					Attribute attr = (Attribute) ae.next();
620
					for (NamingEnumeration e = attr.getAll(); e.hasMore(); uvec.add(e
621
							.next())) {
622
						;
623
					}
624
				}
625
			} catch (SizeLimitExceededException slee) {
626
				logMetacat.error("LDAP Server size limit exceeded. "
627
						+ "Returning incomplete record set.");
628
			}
629 2058 sgarg
630 4629 daigle
			// initialize users[]; fill users[]
631
			users = new String[uvec.size()];
632
			for (int i = 0; i < uvec.size(); i++) {
633
				users[i] = (String) uvec.elementAt(i);
634
			}
635 730 bojilova
636 4629 daigle
			// Close the context when we're done
637
			ctx.close();
638 730 bojilova
639 4629 daigle
		} catch (NamingException e) {
640
			logMetacat.error("Problem getting users for a group in "
641
					+ "AuthLdap.getUsers:" + e);
642
			/*
643
			 * throw new ConnectException( "Problem getting users for a group in
644
			 * AuthLdap.getUsers:" + e);
645
			 */
646
		}
647 2121 sgarg
648 4629 daigle
		return users;
649
	}
650 2121 sgarg
651 4629 daigle
	/**
652
	 * Get all groups from the authentication service
653
	 *
654
	 * @param user
655
	 *            the user for authenticating against the service
656
	 * @param password
657
	 *            the password for authenticating against the service
658
	 * @returns string array of the group names
659
	 */
660
	public String[][] getGroups(String user, String password) throws ConnectException {
661
		return getGroups(user, password, null);
662
	}
663 2121 sgarg
664 4629 daigle
	/**
665
	 * Get the groups for a particular user from the authentication service
666
	 *
667
	 * @param user
668
	 *            the user for authenticating against the service
669
	 * @param password
670
	 *            the password for authenticating against the service
671
	 * @param foruser
672
	 *            the user whose group list should be returned
673
	 * @returns string array of the group names
674
	 */
675
	public String[][] getGroups(String user, String password, String foruser)
676
			throws ConnectException {
677 2121 sgarg
678 4629 daigle
		logMetacat.debug("getGroups() called.");
679 2129 sgarg
680 4629 daigle
		// create vectors to store group and dscription values returned from the
681
		// ldap servers
682
		Vector gvec = new Vector();
683
		Vector desc = new Vector();
684
		Attributes tempAttr = null;
685
		Attributes rsrAttr = null;
686 2058 sgarg
687 4629 daigle
		// DURING getGroups(), DO WE NOT BIND USING userName AND userPassword??
688
		// NEED TO FIX THIS ...
689
		userName = user;
690
		userPassword = password;
691
		// Identify service provider to use
692
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
693
		env.put(Context.REFERRAL, "throw");
694
		env.put(Context.PROVIDER_URL, ldapUrl);
695
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
696 2121 sgarg
697 4629 daigle
		// Iterate through the referrals, handling NamingExceptions in the
698
		// outer catch statement, ReferralExceptions in the inner catch
699
		// statement
700
		try { // outer try
701 730 bojilova
702 4629 daigle
			// Create the initial directory context
703
			DirContext ctx = new InitialDirContext(env);
704 730 bojilova
705 4629 daigle
			// Specify the attributes to match.
706
			// Groups are objects with attribute objectclass=groupofuniquenames.
707
			// and have attribute uniquemember: uid=foruser,ldapbase.
708
			SearchControls ctls = new SearchControls();
709
			// Specify the ids of the attributes to return
710
			String[] attrIDs = { "cn", "o", "description" };
711
			ctls.setReturningAttributes(attrIDs);
712
			// set the ldap search scope
713
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
714
			// set a 10 second time limit on searches to limit non-responding
715
			// servers
716
			ctls.setTimeLimit(ldapSearchTimeLimit);
717
			// return at most 20000 entries
718
			ctls.setCountLimit(ldapSearchCountLimit);
719 504 jones
720 4629 daigle
			// build the ldap search filter that represents the "group" concept
721
			String filter = null;
722
			String gfilter = "(objectClass=groupOfUniqueNames)";
723
			if (null == foruser) {
724
				filter = gfilter;
725
			} else {
726
				filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
727
			}
728
			logMetacat.info("group filter is: " + filter);
729 504 jones
730 4629 daigle
			// now, search and iterate through the referrals
731
			for (boolean moreReferrals = true; moreReferrals;) {
732
				try { // inner try
733 2058 sgarg
734 4629 daigle
					NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
735 2058 sgarg
736 4629 daigle
					// Print the groups
737
					while (namingEnum.hasMore()) {
738
						SearchResult sr = (SearchResult) namingEnum.next();
739 730 bojilova
740 4629 daigle
						tempAttr = sr.getAttributes();
741 730 bojilova
742 4629 daigle
						if ((tempAttr.get("description") + "")
743
								.startsWith("description: ")) {
744
							desc.add((tempAttr.get("description") + "").substring(13));
745
						} else {
746
							desc.add(tempAttr.get("description") + "");
747
						}
748 2058 sgarg
749 4629 daigle
						// check for an absolute URL value or an answer value
750
						// relative
751
						// to the target context
752
						if (!sr.getName().startsWith("ldap") && sr.isRelative()) {
753
							logMetacat.debug("Search result entry is relative ...");
754
							gvec.add(sr.getName() + "," + ldapBase);
755
							logMetacat.info("group " + sr.getName() + "," + ldapBase
756
									+ " added to the group vector");
757
						} else {
758
							logMetacat.debug("Search result entry is absolute ...");
759 2058 sgarg
760 4629 daigle
							// search the top level directory for referral
761
							// objects and match
762
							// that of the search result's absolute URL. This
763
							// will let us
764
							// rebuild the group name from the search result,
765
							// referral point
766
							// in the top directory tree, and ldapBase.
767 2058 sgarg
768 4629 daigle
							// configure a new directory search first
769
							Hashtable envHash = new Hashtable(11);
770
							// Identify service provider to use
771
							envHash.put(Context.INITIAL_CONTEXT_FACTORY,
772
									"com.sun.jndi.ldap.LdapCtxFactory");
773
							envHash.put(Context.REFERRAL, "ignore");
774
							envHash.put(Context.PROVIDER_URL, ldapUrl);
775
							envHash.put("com.sun.jndi.ldap.connect.timeout",
776
									ldapConnectTimeLimit);
777 725 bojilova
778 4629 daigle
							try {
779
								// Create the initial directory context
780
								DirContext DirCtx = new InitialDirContext(envHash);
781 2058 sgarg
782 4629 daigle
								SearchControls searchCtls = new SearchControls();
783
								// Specify the ids of the attributes to return
784
								String[] attrNames = { "o" };
785
								searchCtls.setReturningAttributes(attrNames);
786
								// set the ldap search scope - only look for top
787
								// level referrals
788
								searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
789
								// set a time limit on searches to limit
790
								// non-responding servers
791
								searchCtls.setTimeLimit(ldapSearchTimeLimit);
792
								// return the configured number of entries
793
								searchCtls.setCountLimit(ldapSearchCountLimit);
794 503 bojilova
795 4629 daigle
								// Specify the attributes to match.
796
								// build the ldap search filter to match
797
								// referral entries that
798
								// match the search result
799
								String rFilter = "(&(objectClass=referral)(ref="
800
										+ currentReferralInfo.substring(0,
801
												currentReferralInfo.indexOf("?")) + "))";
802
								logMetacat.debug("rFilter is: " + rFilter);
803 503 bojilova
804 4629 daigle
								NamingEnumeration rNamingEnum = DirCtx.search(ldapBase,
805
										rFilter, searchCtls);
806 2058 sgarg
807 4629 daigle
								while (rNamingEnum.hasMore()) {
808
									SearchResult rsr = (SearchResult) rNamingEnum.next();
809
									rsrAttr = rsr.getAttributes();
810
									logMetacat.debug("referral search result is: "
811
											+ rsr.toString());
812 725 bojilova
813 4629 daigle
									// add the returned groups to the group
814
									// vector. Test the
815
									// syntax of the returned attributes -
816
									// sometimes they are
817
									// preceded with the attribute id and a
818
									// colon
819
									if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
820
										gvec.add("cn="
821
												+ (tempAttr.get("cn") + "").substring(4)
822
												+ "," + "o="
823
												+ (rsrAttr.get("o") + "").substring(3)
824
												+ "," + ldapBase);
825
										logMetacat.info("group "
826
												+ (tempAttr.get("cn") + "").substring(4)
827
												+ "," + "o="
828
												+ (rsrAttr.get("o") + "").substring(3)
829
												+ "," + ldapBase
830
												+ " added to the group vector");
831
									} else {
832
										gvec.add("cn=" + tempAttr.get("cn") + "," + "o="
833
												+ rsrAttr.get("o") + "," + ldapBase);
834
										logMetacat.info("group " + "cn="
835
												+ tempAttr.get("cn") + "," + "o="
836
												+ rsrAttr.get("o") + "," + ldapBase
837
												+ " added to the group vector");
838
									}
839
								}
840 723 bojilova
841 4629 daigle
							} catch (NamingException nameEx) {
842
								logMetacat.debug("Caught naming exception: ");
843
								nameEx.printStackTrace(System.err);
844
							}
845
						}
846
					}// end while
847 725 bojilova
848 4629 daigle
					moreReferrals = false;
849
850
				} catch (ReferralException re) {
851
852
					logMetacat
853
							.info("In AuthLdap.getGroups(), caught referral exception: "
854
									+ re.getReferralInfo());
855
					this.currentReferralInfo = (String) re.getReferralInfo();
856
857
					// set moreReferrals to true and set the referral context
858
					moreReferrals = true;
859
					ctx = (DirContext) re.getReferralContext();
860
861
				}// end inner try
862
			}// end for
863
864
			// close the context now that all initial and referral
865
			// searches are processed
866
			ctx.close();
867
868
		} catch (NamingException e) {
869
870
			// naming exceptions get logged, groups are returned
871
			logMetacat.info("In AuthLdap.getGroups(), caught naming exception: ");
872
			e.printStackTrace(System.err);
873
874
		} finally {
875
			// once all referrals are followed, report and return the groups
876
			// found
877
			logMetacat.warn("The user is in the following groups: " + gvec.toString());
878
			// build and return the groups array
879
			String groups[][] = new String[gvec.size()][2];
880
			for (int i = 0; i < gvec.size(); i++) {
881
				groups[i][0] = (String) gvec.elementAt(i);
882
				groups[i][1] = (String) desc.elementAt(i);
883
			}
884
			return groups;
885
		}// end outer try
886
	}
887
888
	/**
889
	 * Get attributes describing a user or group
890
	 *
891
	 * @param foruser
892
	 *            the user for which the attribute list is requested
893
	 * @returns HashMap a map of attribute name to a Vector of values
894
	 */
895
	public HashMap<String, Vector<String>> getAttributes(String foruser)
896
			throws ConnectException {
897
		return getAttributes(null, null, foruser);
898
	}
899
900
	/**
901
	 * Get attributes describing a user or group
902
	 *
903
	 * @param user
904
	 *            the user for authenticating against the service
905
	 * @param password
906
	 *            the password for authenticating against the service
907
	 * @param foruser
908
	 *            the user whose attributes should be returned
909
	 * @returns HashMap a map of attribute name to a Vector of values
910
	 */
911
	public HashMap<String, Vector<String>> getAttributes(String user, String password,
912
			String foruser) throws ConnectException {
913
		HashMap<String, Vector<String>> attributes = new HashMap<String, Vector<String>>();
914
		String ldapUrl = this.ldapUrl;
915
		String ldapBase = this.ldapBase;
916
		String userident = foruser;
917
918
		// Identify service provider to use
919
		Hashtable env = new Hashtable(11);
920
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
921
		env.put(Context.REFERRAL, referral);
922
		env.put(Context.PROVIDER_URL, ldapUrl);
923
924
		try {
925
926
			// Create the initial directory context
927
			DirContext ctx = new InitialDirContext(env);
928
929
			// Ask for all attributes of the user
930
			// Attributes attrs = ctx.getAttributes(userident);
931
			Attributes attrs = ctx.getAttributes(foruser);
932
933
			// Print all of the attributes
934
			NamingEnumeration en = attrs.getAll();
935
			while (en.hasMore()) {
936
				Attribute att = (Attribute) en.next();
937
				Vector<String> values = new Vector();
938
				String attName = att.getID();
939
				NamingEnumeration attvalues = att.getAll();
940
				while (attvalues.hasMore()) {
941
					String value = (String) attvalues.next();
942
					values.add(value);
943
				}
944
				attributes.put(attName, values);
945
			}
946
947
			// Close the context when we're done
948
			ctx.close();
949
		} catch (NamingException e) {
950
			logMetacat.error("Problem getting attributes in " + "AuthLdap.getAttributes:"
951
					+ e);
952
			throw new ConnectException(
953
					"Problem getting attributes in AuthLdap.getAttributes:" + e);
954
		}
955
956
		return attributes;
957
	}
958
959
	/**
960
	 * Get list of all subtrees holding Metacat's groups and users starting from
961
	 * the Metacat LDAP root, i.e.
962
	 * ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
963
	 */
964
	private Hashtable getSubtrees(String user, String password, String ldapUrl,
965
			String ldapBase) throws ConnectException {
966 5157 daigle
		logMetacat.debug("AuthLdap.getSubtrees - getting subtrees for user: " + user +
967
				", ldapUrl: " + ldapUrl + ", ldapBase: " + ldapBase);
968 4629 daigle
		Hashtable trees = new Hashtable();
969
970
		// Identify service provider to use
971
		Hashtable env = new Hashtable(11);
972
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
973
		// env.put(Context.REFERRAL, referral);
974
		// Using 'ignore' here instead of 'follow' as 'ignore' seems
975
		// to do the job better. 'follow' was not bringing up the UCNRS
976
		// and PISCO tree whereas 'ignore' brings up the tree.
977
978
		env.put(Context.REFERRAL, "ignore");
979
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
980
981
		try {
982
983
			// Create the initial directory context
984
			DirContext ctx = new InitialDirContext(env);
985
986
			// Specify the ids of the attributes to return
987
			String[] attrIDs = { "o", "ref" };
988
			SearchControls ctls = new SearchControls();
989
			ctls.setReturningAttributes(attrIDs);
990
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
991
992
			// Specify the attributes to match.
993
			// Subtrees from the main server are found as objects with attribute
994
			// objectclass=organization or objectclass=referral to the subtree
995
			// resided on other server.
996
			String filter = "(|(objectclass=organization)(objectclass=referral))";
997
998
			// Search for objects in the current context
999
			NamingEnumeration namingEnum = ctx.search("", filter, ctls);
1000
1001
			// Print the subtrees' <ldapURL, baseDN>
1002
			while (namingEnum.hasMore()) {
1003
1004
				SearchResult sr = (SearchResult) namingEnum.next();
1005 5157 daigle
				logMetacat.debug("AuthLdap.getSubtrees - search result: " + sr.toString());
1006 4629 daigle
1007
				Attributes attrs = sr.getAttributes();
1008
				NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref"
1009
															// attrs
1010
1011
				if (enum1.hasMore()) {
1012
					Attribute attr = (Attribute) enum1.next();
1013
					String attrValue = (String) attr.get();
1014
					String attrName = (String) attr.getID();
1015
1016
					if (enum1.hasMore()) {
1017
						attr = (Attribute) enum1.next();
1018
						String refValue = (String) attr.get();
1019
						String refName = (String) attr.getID();
1020
						if (ldapBase.startsWith(refName + "=" + refValue)) {
1021
							trees.put(ldapBase, attrValue.substring(0, attrValue
1022
									.lastIndexOf("/") + 1));
1023
						} else {
1024
							// this is a referral - so organization name is
1025 5157 daigle
							// appended in front of the ldapbase.... later it is
1026
							// stripped out in getPrincipals
1027
							trees.put("[" + refName + "=" + refValue + "]" +
1028
									attrValue.substring(attrValue.lastIndexOf("/") + 1,
1029 4629 daigle
											attrValue.length()), attrValue.substring(0,
1030 5157 daigle
													attrValue.lastIndexOf("/") + 1));
1031 4629 daigle
1032
							// trees.put(refName + "=" + refValue + "," +
1033 5157 daigle
							// ldapBase, attrValue.substring(0, attrValue.lastIndexOf("/")
1034 4629 daigle
							// + 1));
1035
						}
1036
1037
					} else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
1038
						trees.put(ldapBase, ldapUrl);
1039
					} else {
1040
						if (sr.isRelative()) {
1041
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1042
									ldapUrl);
1043
						} else {
1044
							String referenceURL = sr.getName();
1045
							referenceURL = referenceURL.substring(0, referenceURL
1046
									.lastIndexOf("/") + 1);
1047
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1048
									referenceURL);
1049
						}
1050
1051
					}
1052
				}
1053
			}
1054
1055
			// Close the context when we're done
1056
			ctx.close();
1057
1058
		} catch (NamingException e) {
1059 5157 daigle
			logMetacat.error("AuthLdap.getSubtrees - Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1060 4629 daigle
			throw new ConnectException(
1061
					"Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1062
		}
1063
1064
		return trees;
1065
	}
1066
1067
	/**
1068
	 * Get all groups and users from authentication scheme. The output is
1069
	 * formatted in XML.
1070
	 *
1071
	 * @param user
1072
	 *            the user which requests the information
1073
	 * @param password
1074
	 *            the user's password
1075
	 */
1076
	public String getPrincipals(String user, String password) throws ConnectException {
1077
		StringBuffer out = new StringBuffer();
1078
1079
		out.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
1080
		out.append("<principals>\n");
1081
1082
		/*
1083
		 * get all subtrees first in the current dir context and then the
1084
		 * Metacat users under them
1085
		 */
1086
		Hashtable subtrees = getSubtrees(user, password, this.ldapUrl, this.ldapBase);
1087
1088
		Enumeration keyEnum = subtrees.keys();
1089
		while (keyEnum.hasMoreElements()) {
1090
			this.ldapBase = (String) keyEnum.nextElement();
1091
			this.ldapUrl = (String) subtrees.get(ldapBase);
1092 5157 daigle
			logMetacat.info("AuthLdap.getPrincipals - ldapBase: " + ldapBase +
1093
					", ldapUrl: " + ldapUrl);
1094 4629 daigle
			/*
1095
			 * code to get the organization name from ldapBase
1096
			 */
1097
			String orgName = this.ldapBase;
1098
			if (orgName.startsWith("[")) {
1099
				// if orgName starts with [ then it is a referral URL...
1100 5157 daigle
				// (see code in getSubtress) hence orgName can be retrieved by
1101
				// getting the string between 'o=' and ']' also the string between
1102
				// [ and ] needs to be striped out from this.ldapBase
1103 4629 daigle
				this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1104
				if (orgName != null && orgName.indexOf("o=") > -1) {
1105
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1106
					orgName = orgName.substring(0, orgName.indexOf("]"));
1107
				}
1108
			} else {
1109
				// else it is not referral
1110
				// hence orgName can be retrieved by getting the string between
1111
				// 'o=' and ','
1112
				if (orgName != null && orgName.indexOf("o=") > -1) {
1113
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1114
					if (orgName.indexOf(",") > -1) {
1115
						orgName = orgName.substring(0, orgName.indexOf(","));
1116
					}
1117
				}
1118
			}
1119 5157 daigle
			logMetacat.info("AuthLdap.getPrincipals - org name is  " + orgName);
1120 4629 daigle
			out.append("  <authSystem URI=\"" + this.ldapUrl + this.ldapBase
1121
					+ "\" organization=\"" + orgName + "\">\n");
1122
1123
			// get all groups for directory context
1124
			String[][] groups = getGroups(user, password);
1125 5157 daigle
			logMetacat.debug("AuthLdap.getPrincipals - after getting groups " + groups);
1126 4629 daigle
			String[][] users = getUsers(user, password);
1127 5157 daigle
			logMetacat.debug("AuthLdap.getPrincipals - after getting users " + users);
1128 4629 daigle
			int userIndex = 0;
1129
1130
			// for the groups and users that belong to them
1131
			if (groups != null && users != null && groups.length > 0) {
1132
				for (int i = 0; i < groups.length; i++) {
1133
					out.append("    <group>\n");
1134
					out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1135
					out.append("      <description>" + groups[i][1] + "</description>\n");
1136
					String[] usersForGroup = getUsers(user, password, groups[i][0]);
1137
					for (int j = 0; j < usersForGroup.length; j++) {
1138
						userIndex = searchUser(usersForGroup[j], users);
1139
						out.append("      <user>\n");
1140
1141
						if (userIndex < 0) {
1142
							out.append("        <username>" + usersForGroup[j]
1143
									+ "</username>\n");
1144
						} else {
1145
							out.append("        <username>" + users[userIndex][0]
1146
									+ "</username>\n");
1147
							out.append("        <name>" + users[userIndex][1]
1148
									+ "</name>\n");
1149
							out.append("        <organization>" + users[userIndex][2]
1150
									+ "</organization>\n");
1151
							if (users[userIndex][3].compareTo("null") != 0) {
1152
								out.append("      <organizationUnitName>"
1153
										+ users[userIndex][3]
1154
										+ "</organizationUnitName>\n");
1155
							}
1156
							out.append("        <email>" + users[userIndex][4]
1157
									+ "</email>\n");
1158
						}
1159
1160
						out.append("      </user>\n");
1161
					}
1162
					out.append("    </group>\n");
1163
				}
1164
			}
1165
1166
			if (users != null) {
1167
				// for the users not belonging to any grou8p
1168
				for (int j = 0; j < users.length; j++) {
1169
					out.append("    <user>\n");
1170
					out.append("      <username>" + users[j][0] + "</username>\n");
1171
					out.append("      <name>" + users[j][1] + "</name>\n");
1172
					out
1173
							.append("      <organization>" + users[j][2]
1174
									+ "</organization>\n");
1175
					if (users[j][3].compareTo("null") != 0) {
1176
						out.append("      <organizationUnitName>" + users[j][3]
1177
								+ "</organizationUnitName>\n");
1178
					}
1179
					out.append("      <email>" + users[j][4] + "</email>\n");
1180
					out.append("    </user>\n");
1181
				}
1182
			}
1183
1184
			out.append("  </authSystem>\n");
1185
		}
1186
		out.append("</principals>");
1187
		return out.toString();
1188
	}
1189
1190
	/**
1191
	 * Method for getting index of user DN in User info array
1192
	 */
1193
	int searchUser(String user, String userGroup[][]) {
1194
		for (int j = 0; j < userGroup.length; j++) {
1195
			if (user.compareTo(userGroup[j][0]) == 0) {
1196
				return j;
1197
			}
1198
		}
1199
		return -1;
1200
	}
1201
1202
	public void testCredentials(String dn, String password, String rootServer,
1203
			String rootBase) throws NamingException {
1204
1205
		String server = "";
1206
		String userDN = "";
1207
		logMetacat.debug("dn is: " + dn);
1208
1209
		int position = dn.lastIndexOf("/");
1210
		logMetacat.debug("position is: " + position);
1211
		if (position == -1) {
1212
			server = rootServer;
1213
			if (dn.indexOf(userDN) < 0) {
1214
				userDN = dn + "," + rootBase;
1215
			} else {
1216
				userDN = dn;
1217
			}
1218
			logMetacat.debug("userDN is: " + userDN);
1219
1220
		} else {
1221
			server = dn.substring(0, position + 1);
1222
			userDN = dn.substring(position + 1);
1223
			logMetacat.debug("server is: " + server);
1224
			logMetacat.debug("userDN is: " + userDN);
1225
		}
1226
1227
		logMetacat.debug("Trying to authenticate: " + userDN);
1228
		logMetacat.debug("          Using server: " + server);
1229
1230
		// /* try {
1231
		LdapContext ctx = null;
1232
1233
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1234
		env.put(Context.REFERRAL, "follow");
1235
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
1236
		env.put(Context.SECURITY_PRINCIPAL, userDN);
1237
		env.put(Context.SECURITY_CREDENTIALS, password);
1238
		env.put(Context.PROVIDER_URL, rootServer);
1239
1240
		ctx = new InitialLdapContext(env, null);
1241
1242
	}
1243
1244
	/**
1245 4080 daigle
	 * Test method for the class
1246
	 */
1247
	public static void main(String[] args) {
1248 871 jones
1249 4080 daigle
		// Provide a user, such as: "Matt Jones", or "jones"
1250
		String user = args[0];
1251
		String password = args[1];
1252
		String org = args[2];
1253 871 jones
1254 4080 daigle
		logMetacat.warn("Creating session...");
1255
		AuthLdap authservice = null;
1256
		try {
1257
			authservice = new AuthLdap();
1258
		} catch (Exception e) {
1259 4629 daigle
			logMetacat.error("Could not instantiate AuthLdap: " + e.getMessage());
1260 4080 daigle
			return;
1261
		}
1262
		logMetacat.warn("Session exists...");
1263 2058 sgarg
1264 4080 daigle
		boolean isValid = false;
1265
		try {
1266
			logMetacat.warn("Authenticating...");
1267
			isValid = authservice.authenticate(user, password);
1268
			if (isValid) {
1269
				logMetacat.warn("Authentication successful for: " + user);
1270
			} else {
1271
				logMetacat.warn("Authentication failed for: " + user);
1272
			}
1273 873 jones
1274 4080 daigle
			// Get attributes for the user
1275
			if (isValid) {
1276
				logMetacat.info("\nGetting attributes for user....");
1277 4629 daigle
				HashMap userInfo = authservice.getAttributes(user, password, user);
1278 4080 daigle
				// Print all of the attributes
1279 4629 daigle
				Iterator attList = (Iterator) (((Set) userInfo.keySet()).iterator());
1280 4080 daigle
				while (attList.hasNext()) {
1281
					String att = (String) attList.next();
1282
					Vector values = (Vector) userInfo.get(att);
1283
					Iterator attvalues = values.iterator();
1284
					while (attvalues.hasNext()) {
1285
						String value = (String) attvalues.next();
1286
						logMetacat.warn(att + ": " + value);
1287
					}
1288
				}
1289
			}
1290 873 jones
1291 4080 daigle
			// get the groups
1292
			if (isValid) {
1293
				logMetacat.warn("\nGetting all groups....");
1294
				String[][] groups = authservice.getGroups(user, password);
1295
				logMetacat.info("Groups found: " + groups.length);
1296
				for (int i = 0; i < groups.length; i++) {
1297
					logMetacat.info("Group " + i + ": " + groups[i][0]);
1298
				}
1299
			}
1300 2058 sgarg
1301 4080 daigle
			// get the groups for the user
1302
			String savedGroup = null;
1303
			if (isValid) {
1304
				logMetacat.warn("\nGetting groups for user....");
1305
				String[][] groups = authservice.getGroups(user, password, user);
1306
				logMetacat.info("Groups found: " + groups.length);
1307
				for (int i = 0; i < groups.length; i++) {
1308
					logMetacat.info("Group " + i + ": " + groups[i][0]);
1309
					savedGroup = groups[i][0];
1310
				}
1311
			}
1312
1313
			// get the users for a group
1314
			if (isValid) {
1315
				logMetacat.warn("\nGetting users for group....");
1316
				logMetacat.info("Group: " + savedGroup);
1317 4629 daigle
				String[] users = authservice.getUsers(user, password, savedGroup);
1318 4080 daigle
				logMetacat.info("Users found: " + users.length);
1319
				for (int i = 0; i < users.length; i++) {
1320
					logMetacat.warn("User " + i + ": " + users[i]);
1321
				}
1322
			}
1323
1324
			// get all users
1325
			if (isValid) {
1326
				logMetacat.warn("\nGetting all users ....");
1327
				String[][] users = authservice.getUsers(user, password);
1328
				logMetacat.info("Users found: " + users.length);
1329
1330
			}
1331
1332
			// get the whole list groups and users in XML format
1333
			if (isValid) {
1334
				logMetacat.warn("\nTrying principals....");
1335
				authservice = new AuthLdap();
1336
				String out = authservice.getPrincipals(user, password);
1337
				java.io.File f = new java.io.File("principals.xml");
1338
				java.io.FileWriter fw = new java.io.FileWriter(f);
1339
				java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1340
				buff.write(out);
1341
				buff.flush();
1342
				buff.close();
1343
				fw.close();
1344
				logMetacat.warn("\nFinished getting principals.");
1345
			}
1346
1347
		} catch (ConnectException ce) {
1348
			logMetacat.error(ce.getMessage());
1349
		} catch (java.io.IOException ioe) {
1350
			logMetacat.error("I/O Error writing to file principals.txt: "
1351
					+ ioe.getMessage());
1352
		} catch (InstantiationException ie) {
1353
			logMetacat.error("Instantiation error writing to file principals.txt: "
1354 4629 daigle
					+ ie.getMessage());
1355 4080 daigle
		}
1356
	}
1357
1358 4629 daigle
	/**
1359
	 * This method will be called by start a thread. It can handle if a referral
1360
	 * exception happend.
1361
	 */
1362 503 bojilova
}