Project

General

Profile

1
/**
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: daigle $'
11
 *     '$Date: 2008-11-25 10:50:45 -0800 (Tue, 25 Nov 2008) $'
12
 * '$Revision: 4629 $'
13
 *
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
 */
28

    
29
package edu.ucsb.nceas.metacat;
30

    
31
import java.net.ConnectException;
32
import javax.naming.AuthenticationException;
33
import javax.naming.Context;
34
import javax.naming.NamingEnumeration;
35
import javax.naming.NamingException;
36
import javax.naming.SizeLimitExceededException;
37
import javax.naming.directory.Attribute;
38
import javax.naming.directory.Attributes;
39
import javax.naming.directory.DirContext;
40
import javax.naming.directory.InitialDirContext;
41
import javax.naming.directory.SearchResult;
42
import javax.naming.directory.SearchControls;
43
import javax.naming.ReferralException;
44
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

    
50
import org.apache.log4j.Logger;
51

    
52
import edu.ucsb.nceas.metacat.service.PropertyService;
53
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
54

    
55
import java.lang.InstantiationException;
56
import java.net.URLDecoder;
57
import java.util.Iterator;
58
import java.util.HashMap;
59
import java.util.Hashtable;
60
import java.util.Enumeration;
61
import java.util.Set;
62
import java.util.Vector;
63

    
64
/**
65
 * An implementation of the AuthInterface interface that allows Metacat to use
66
 * the LDAP protocol for directory services. The LDAP authentication service is
67
 * used to determine if a user is authenticated, and whether they are a member
68
 * of a particular group.
69
 */
70
public class AuthLdap implements AuthInterface {
71
	private String ldapUrl;
72
	private String ldapsUrl;
73
	private String ldapBase;
74
	private String referral;
75
	private String ldapConnectTimeLimit;
76
	private int ldapSearchTimeLimit;
77
	private int ldapSearchCountLimit;
78
	private String currentReferralInfo;
79
	Hashtable env = new Hashtable(11);
80
	private Context rContext;
81
	private String userName;
82
	private String userPassword;
83
	ReferralException refExc;
84

    
85
	private static Logger logMetacat = Logger.getLogger(AuthLdap.class);
86

    
87
	/**
88
	 * Construct an AuthLdap
89
	 */
90
	public AuthLdap() throws InstantiationException {
91
		// Read LDAP URI for directory service information
92
		try {
93
			this.ldapUrl = PropertyService.getProperty("auth.url");
94
			this.ldapsUrl = PropertyService.getProperty("auth.surl");
95
			// use the NCEAS base as a fallback. Normally, the base will be
96
			// parsed from the user during authentication
97
			// TODO MCD this may need to remain always at NCEAS value
98
			this.ldapBase = PropertyService.getProperty("organization.base.NCEAS");
99
			this.referral = PropertyService.getProperty("ldap.referral");
100
			this.ldapConnectTimeLimit = PropertyService
101
					.getProperty("ldap.connectTimeLimit");
102
			this.ldapSearchTimeLimit = Integer.parseInt(PropertyService
103
					.getProperty("ldap.searchTimeLimit"));
104
			this.ldapSearchCountLimit = Integer.parseInt(PropertyService
105
					.getProperty("ldap.searchCountLimit"));
106
		} catch (PropertyNotFoundException pnfe) {
107
			throw new InstantiationException(
108
					"Could not instantiate AuthLdap.  Property not found: "
109
							+ pnfe.getMessage());
110
		} catch (NumberFormatException nfe) {
111
			throw new InstantiationException(
112
					"Could not instantiate AuthLdap.  Bad number format when converting properties: "
113
							+ nfe.getMessage());
114
		}
115

    
116
		// Store referral info for use in building group DNs in getGroups()
117
		this.currentReferralInfo = "";
118
	}
119

    
120
	/**
121
	 * Determine if a user/password are valid according to the authentication
122
	 * service.
123
	 * 
124
	 * @param user
125
	 *            the name of the principal to authenticate
126
	 * @param password
127
	 *            the password to use for authentication
128
	 * @returns boolean true if authentication successful, false otherwise
129
	 */
130

    
131
	public boolean authenticate(String user, String password) throws ConnectException {
132
		String ldapUrl = this.ldapUrl;
133
		String ldapsUrl = this.ldapsUrl;
134
		String ldapBase = this.ldapBase;
135
		boolean authenticated = false;
136
		String identifier = user;
137

    
138
		// get uid here.
139
		if (user.indexOf(",") == -1) {
140
			throw new ConnectException("Invalid LDAP user credential: " + user
141
					+ ".  Missing ','");
142
		}
143
		String uid = user.substring(0, user.indexOf(","));
144
		user = user.substring(user.indexOf(","), user.length());
145

    
146
		logMetacat.debug("identifier: " + identifier);
147
		logMetacat.debug("uid: " + uid);
148
		logMetacat.debug("user: " + user);
149

    
150
		try {
151
			// Check the usename as passed in
152
			logMetacat.info("Calling ldapAuthenticate");
153
			logMetacat.info("with user as identifier: " + identifier);
154

    
155
			authenticated = ldapAuthenticate(identifier, password, (new Boolean(
156
					PropertyService.getProperty("ldap.onlySecureConnection")))
157
					.booleanValue());
158
			// if not found, try looking up a valid DN then auth again
159
			if (!authenticated) {
160
				logMetacat.info("Not Authenticated");
161
				logMetacat.info("Looking up DN for: " + identifier);
162
				identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
163
				if (identifier == null) {
164
					logMetacat.info("No DN found from getIdentifyingName");
165
					return authenticated;
166
				}
167

    
168
				logMetacat.info("DN found from getIdentifyingName: " + identifier);
169
				String decoded = URLDecoder.decode(identifier);
170
				logMetacat.info("DN decoded: " + decoded);
171
				identifier = decoded;
172
				String refUrl = "";
173
				String refBase = "";
174
				if (identifier.startsWith("ldap")) {
175
					logMetacat.debug("identifier starts with \"ldap\"");
176

    
177
					refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1);
178
					int position = identifier.indexOf(",");
179
					int position2 = identifier.indexOf(",", position + 1);
180

    
181
					refBase = identifier.substring(position2 + 1);
182
					identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
183

    
184
					logMetacat.info("Calling ldapAuthenticate:");
185
					logMetacat.info("with user as identifier: " + identifier);
186
					logMetacat.info("and refUrl as: " + refUrl);
187
					logMetacat.info("and refBase as: " + refBase);
188

    
189
					authenticated = ldapAuthenticate(identifier, password, refUrl,
190
							refBase, (new Boolean(PropertyService
191
									.getProperty("ldap.onlySecureReferalsConnection")))
192
									.booleanValue());
193
				} else {
194
					logMetacat.info("identifier doesnt start with ldap");
195
					identifier = identifier + "," + ldapBase;
196

    
197
					logMetacat.info("Calling ldapAuthenticate");
198
					logMetacat.info("with user as identifier: " + identifier);
199

    
200
					authenticated = ldapAuthenticate(identifier, password, (new Boolean(
201
							PropertyService.getProperty("ldap.onlySecureConnection")))
202
							.booleanValue());
203
				}
204
			}
205
		} catch (NullPointerException e) {
206
			logMetacat.error("NullPointerException while authenticating in "
207
					+ "AuthLdap.authenticate: " + e);
208
			e.printStackTrace();
209

    
210
			throw new ConnectException("NullPointerException while authenticating in "
211
					+ "AuthLdap.authenticate: " + e);
212
		} catch (NamingException e) {
213
			logMetacat.error("Naming exception while authenticating in "
214
					+ "AuthLdap.authenticate: " + e);
215
			e.printStackTrace();
216
		} catch (Exception e) {
217
			logMetacat.error(e.getMessage());
218
		}
219

    
220
		return authenticated;
221
	}
222

    
223
	/**
224
	 * Connect to the LDAP directory and do the authentication using the
225
	 * username and password as passed into the routine.
226
	 * 
227
	 * @param identifier
228
	 *            the distinguished name to check against LDAP
229
	 * @param password
230
	 *            the password for authentication
231
	 */
232
	private boolean ldapAuthenticate(String identifier, String password,
233
			boolean secureConnectionOnly) throws ConnectException, NamingException,
234
			NullPointerException {
235
		return ldapAuthenticate(identifier, password, this.ldapsUrl, this.ldapBase,
236
				secureConnectionOnly);
237
	}
238

    
239
	/**
240
	 * Connect to the LDAP directory and do the authentication using the
241
	 * username and password as passed into the routine.
242
	 * 
243
	 * @param identifier
244
	 *            the distinguished name to check against LDAP
245
	 * @param password
246
	 *            the password for authentication
247
	 */
248

    
249
	private boolean ldapAuthenticate(String dn, String password, String rootServer,
250
			String rootBase, boolean secureConnectionOnly) {
251

    
252
		boolean authenticated = false;
253

    
254
		String server = "";
255
		String userDN = "";
256
		logMetacat.info("dn is: " + dn);
257

    
258
		int position = dn.lastIndexOf("/");
259
		logMetacat.debug("position is: " + position);
260
		if (position == -1) {
261
			server = rootServer;
262
			if (dn.indexOf(userDN) < 0) {
263
				userDN = dn + "," + rootBase;
264
			} else {
265
				userDN = dn;
266
			}
267
			logMetacat.info("userDN is: " + userDN);
268

    
269
		} else {
270
			server = dn.substring(0, position + 1);
271
			userDN = dn.substring(position + 1);
272
			logMetacat.info("server is: " + server);
273
			logMetacat.info("userDN is: " + userDN);
274
		}
275

    
276
		logMetacat.warn("Trying to authenticate: " + userDN);
277
		logMetacat.warn("          Using server: " + server);
278

    
279
		LdapContext ctx = null;
280
		double startTime;
281
		double stopTime;
282
		try {
283
			Hashtable env = new Hashtable();
284
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
285
			env.put(Context.PROVIDER_URL, server);
286
			env.put(Context.REFERRAL, "throw");
287
			try {
288

    
289
				startTime = System.currentTimeMillis();
290
				ctx = new InitialLdapContext(env, null);
291
				// Start up TLS here so that we don't pass our jewels in
292
				// cleartext
293
				StartTlsResponse tls = (StartTlsResponse) ctx
294
						.extendedOperation(new StartTlsRequest());
295
				// tls.setHostnameVerifier(new SampleVerifier());
296
				SSLSession sess = tls.negotiate();
297
				ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
298
				ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
299
				ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
300
				ctx.reconnect(null);
301
				stopTime = System.currentTimeMillis();
302
				logMetacat.info("Connection time thru " + ldapsUrl + " was: "
303
						+ (stopTime - startTime) / 1000 + " seconds.");
304
				authenticated = true;
305
			} catch (Exception ioe) {
306
				logMetacat.info("Caught IOException in login while negotiating TLS: "
307
						+ ioe.getMessage());
308

    
309
				if (secureConnectionOnly) {
310
					return authenticated;
311

    
312
				} else {
313
					logMetacat.info("Trying to authenticate without TLS");
314
					env.put(Context.SECURITY_AUTHENTICATION, "simple");
315
					env.put(Context.SECURITY_PRINCIPAL, userDN);
316
					env.put(Context.SECURITY_CREDENTIALS, password);
317

    
318
					startTime = System.currentTimeMillis();
319
					ctx = new InitialLdapContext(env, null);
320
					stopTime = System.currentTimeMillis();
321
					logMetacat.info("Connection time thru " + ldapsUrl + " was: "
322
							+ (stopTime - startTime) / 1000 + " seconds.");
323
					authenticated = true;
324
				}
325
			}
326
		} catch (AuthenticationException ae) {
327
			authenticated = false;
328
		} catch (javax.naming.InvalidNameException ine) {
329
			logMetacat.error("An invalid DN was provided!");
330
		} catch (NamingException e) {
331
			logMetacat.warn("Caught NamingException in login: " + e.getClass().getName());
332
			logMetacat.info(e.toString() + "  " + e.getRootCause());
333
		}
334

    
335
		return authenticated;
336
	}
337

    
338
	/**
339
	 * Get the identifying name for a given userid or name. This is the name
340
	 * that is used in conjunction withthe LDAP BaseDN to create a distinguished
341
	 * name (dn) for the record
342
	 * 
343
	 * @param user
344
	 *            the user for which the identifying name is requested
345
	 * @returns String the identifying name for the user, or null if not found
346
	 */
347
	private String getIdentifyingName(String user, String ldapUrl, String ldapBase)
348
			throws NamingException {
349

    
350
		String identifier = null;
351
		Hashtable env = new Hashtable();
352
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
353
		env.put(Context.REFERRAL, "throw");
354
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
355
		try {
356
			int position = user.indexOf(",");
357
			String uid = user.substring(user.indexOf("=") + 1, position);
358
			logMetacat.info("uid is: " + uid);
359
			String org = user.substring(user.indexOf("=", position + 1) + 1, user
360
					.indexOf(",", position + 1));
361
			logMetacat.info("org is: " + org);
362

    
363
			DirContext sctx = new InitialDirContext(env);
364
			SearchControls ctls = new SearchControls();
365
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
366
			String filter = "(&(uid=" + uid + ")(o=" + org + "))";
367
			logMetacat.warn("Searching for DNs with following filter: " + filter);
368

    
369
			for (boolean moreReferrals = true; moreReferrals;) {
370
				try {
371
					// Perform the search
372
					NamingEnumeration answer = sctx.search("", filter, ctls);
373

    
374
					// Return the answer
375
					while (answer.hasMore()) {
376
						SearchResult sr = (SearchResult) answer.next();
377
						identifier = sr.getName();
378
						return identifier;
379
					}
380
					// The search completes with no more referrals
381
					moreReferrals = false;
382
				} catch (ReferralException e) {
383
					logMetacat.info("Got referral: " + e.getReferralInfo());
384
					// Point to the new context from the referral
385
					if (moreReferrals) {
386
						sctx = (DirContext) e.getReferralContext();
387
					}
388
				}
389
			}
390
		} catch (NamingException e) {
391
			logMetacat.error("Naming exception while getting dn: " + e);
392
			throw new NamingException("Naming exception in AuthLdap.getIdentifyingName: "
393
					+ e);
394
		}
395
		return identifier;
396
	}
397

    
398
	/**
399
	 * Get all users from the authentication service
400
	 * 
401
	 * @param user
402
	 *            the user for authenticating against the service
403
	 * @param password
404
	 *            the password for authenticating against the service
405
	 * @returns string array of all of the user names
406
	 */
407
	public String[][] getUsers(String user, String password) throws ConnectException {
408
		String[][] users = null;
409

    
410
		// Identify service provider to use
411
		Hashtable env = new Hashtable(11);
412
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
413
		env.put(Context.REFERRAL, referral);
414
		env.put(Context.PROVIDER_URL, ldapUrl);
415
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
416

    
417
		try {
418

    
419
			// Create the initial directory context
420
			DirContext ctx = new InitialDirContext(env);
421

    
422
			// Specify the attributes to match.
423
			// Users are objects that have the attribute
424
			// objectclass=InetOrgPerson.
425
			SearchControls ctls = new SearchControls();
426
			String[] attrIDs = { "dn", "cn", "o", "ou", "mail" };
427
			ctls.setReturningAttributes(attrIDs);
428
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
429
			ctls.setTimeLimit(ldapSearchTimeLimit);
430
			// ctls.setCountLimit(1000);
431
			String filter = "(objectClass=inetOrgPerson)";
432
			NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
433

    
434
			// Store the users in a vector
435
			Vector uvec = new Vector();
436
			Vector uname = new Vector();
437
			Vector uorg = new Vector();
438
			Vector uou = new Vector();
439
			Vector umail = new Vector();
440
			Attributes tempAttr = null;
441
			try {
442
				while (namingEnum.hasMore()) {
443
					SearchResult sr = (SearchResult) namingEnum.next();
444
					tempAttr = sr.getAttributes();
445

    
446
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
447
						uname.add((tempAttr.get("cn") + "").substring(4));
448
					} else {
449
						uname.add(tempAttr.get("cn") + "");
450
					}
451

    
452
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
453
						uorg.add((tempAttr.get("o") + "").substring(3));
454
					} else {
455
						uorg.add(tempAttr.get("o") + "");
456
					}
457

    
458
					if ((tempAttr.get("ou") + "").startsWith("ou: ")) {
459
						uou.add((tempAttr.get("ou") + "").substring(4));
460
					} else {
461
						uou.add(tempAttr.get("ou") + "");
462
					}
463

    
464
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
465
						umail.add((tempAttr.get("mail") + "").substring(6));
466
					} else {
467
						umail.add(tempAttr.get("mail") + "");
468
					}
469

    
470
					uvec.add(sr.getName() + "," + ldapBase);
471
				}
472
			} catch (SizeLimitExceededException slee) {
473
				logMetacat.error("LDAP Server size limit exceeded. "
474
						+ "Returning incomplete record set.");
475
			}
476

    
477
			// initialize users[]; fill users[]
478
			users = new String[uvec.size()][5];
479
			for (int i = 0; i < uvec.size(); i++) {
480
				users[i][0] = (String) uvec.elementAt(i);
481
				users[i][1] = (String) uname.elementAt(i);
482
				users[i][2] = (String) uorg.elementAt(i);
483
				users[i][3] = (String) uorg.elementAt(i);
484
				users[i][4] = (String) umail.elementAt(i);
485
			}
486

    
487
			// Close the context when we're done
488
			ctx.close();
489

    
490
		} catch (NamingException e) {
491
			logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
492
			// e.printStackTrace(System.err);
493
			/*
494
			 * throw new ConnectException( "Problem getting users in
495
			 * AuthLdap.getUsers:" + e);
496
			 */
497
		}
498

    
499
		return users;
500
	}
501

    
502
	/**
503
	 * Get all users from the authentication service
504
	 * 
505
	 * @param user
506
	 *            the user for authenticating against the service
507
	 * @param password
508
	 *            the password for authenticating against the service
509
	 * @returns string array of all of the user names
510
	 */
511
	public String[] getUserInfo(String user, String password) throws ConnectException {
512
		String[] userinfo = new String[3];
513

    
514
		// Identify service provider to use
515
		Hashtable env = new Hashtable(11);
516
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
517
		env.put(Context.REFERRAL, referral);
518
		env.put(Context.PROVIDER_URL, ldapUrl);
519

    
520
		try {
521

    
522
			// Create the initial directory context
523
			DirContext ctx = new InitialDirContext(env);
524
			// Specify the attributes to match.
525
			// Users are objects that have the attribute
526
			// objectclass=InetOrgPerson.
527
			SearchControls ctls = new SearchControls();
528
			String[] attrIDs = { "cn", "o", "mail" };
529
			ctls.setReturningAttributes(attrIDs);
530
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
531
			// ctls.setCountLimit(1000);
532
			// create the filter based on the uid
533

    
534
			String filter = null;
535

    
536
			if (user.indexOf("o=") > 0) {
537
				String tempStr = user.substring(user.indexOf("o="));
538
				filter = "(&(" + user.substring(0, user.indexOf(",")) + ")("
539
						+ tempStr.substring(0, tempStr.indexOf(",")) + "))";
540
			} else {
541
				filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
542
			}
543
			filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
544

    
545
			NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
546

    
547
			Attributes tempAttr = null;
548
			try {
549
				while (namingEnum.hasMore()) {
550
					SearchResult sr = (SearchResult) namingEnum.next();
551
					tempAttr = sr.getAttributes();
552

    
553
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
554
						userinfo[0] = (tempAttr.get("cn") + "").substring(4);
555
					} else {
556
						userinfo[0] = (tempAttr.get("cn") + "");
557
					}
558

    
559
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
560
						userinfo[1] = (tempAttr.get("o") + "").substring(3);
561
					} else {
562
						userinfo[1] = (tempAttr.get("o") + "");
563
					}
564

    
565
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
566
						userinfo[2] = (tempAttr.get("mail") + "").substring(6);
567
					} else {
568
						userinfo[2] = (tempAttr.get("mail") + "");
569
					}
570
				}
571
			} catch (SizeLimitExceededException slee) {
572
				logMetacat.error("LDAP Server size limit exceeded. "
573
						+ "Returning incomplete record set.");
574
			}
575

    
576
			// Close the context when we're done
577
			ctx.close();
578

    
579
		} catch (NamingException e) {
580
			logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
581
			// e.printStackTrace(System.err);
582
			throw new ConnectException("Problem getting users in AuthLdap.getUsers:" + e);
583
		}
584

    
585
		return userinfo;
586
	}
587

    
588
	/**
589
	 * Get the users for a particular group from the authentication service
590
	 * 
591
	 * @param user
592
	 *            the user for authenticating against the service
593
	 * @param password
594
	 *            the password for authenticating against the service
595
	 * @param group
596
	 *            the group whose user list should be returned
597
	 * @returns string array of the user names belonging to the group
598
	 */
599
	public String[] getUsers(String user, String password, String group)
600
			throws ConnectException {
601
		String[] users = null;
602

    
603
		// Identify service provider to use
604
		Hashtable env = new Hashtable(11);
605
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
606
		env.put(Context.REFERRAL, referral);
607
		env.put(Context.PROVIDER_URL, ldapUrl);
608

    
609
		try {
610

    
611
			// Create the initial directory context
612
			DirContext ctx = new InitialDirContext(env);
613

    
614
			// Specify the ids of the attributes to return
615
			String[] attrIDs = { "uniqueMember" };
616

    
617
			Attributes answer = ctx.getAttributes(group, attrIDs);
618

    
619
			Vector uvec = new Vector();
620
			try {
621
				for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) {
622
					Attribute attr = (Attribute) ae.next();
623
					for (NamingEnumeration e = attr.getAll(); e.hasMore(); uvec.add(e
624
							.next())) {
625
						;
626
					}
627
				}
628
			} catch (SizeLimitExceededException slee) {
629
				logMetacat.error("LDAP Server size limit exceeded. "
630
						+ "Returning incomplete record set.");
631
			}
632

    
633
			// initialize users[]; fill users[]
634
			users = new String[uvec.size()];
635
			for (int i = 0; i < uvec.size(); i++) {
636
				users[i] = (String) uvec.elementAt(i);
637
			}
638

    
639
			// Close the context when we're done
640
			ctx.close();
641

    
642
		} catch (NamingException e) {
643
			logMetacat.error("Problem getting users for a group in "
644
					+ "AuthLdap.getUsers:" + e);
645
			/*
646
			 * throw new ConnectException( "Problem getting users for a group in
647
			 * AuthLdap.getUsers:" + e);
648
			 */
649
		}
650

    
651
		return users;
652
	}
653

    
654
	/**
655
	 * Get all groups from the authentication service
656
	 * 
657
	 * @param user
658
	 *            the user for authenticating against the service
659
	 * @param password
660
	 *            the password for authenticating against the service
661
	 * @returns string array of the group names
662
	 */
663
	public String[][] getGroups(String user, String password) throws ConnectException {
664
		return getGroups(user, password, null);
665
	}
666

    
667
	/**
668
	 * Get the groups for a particular user from the authentication service
669
	 * 
670
	 * @param user
671
	 *            the user for authenticating against the service
672
	 * @param password
673
	 *            the password for authenticating against the service
674
	 * @param foruser
675
	 *            the user whose group list should be returned
676
	 * @returns string array of the group names
677
	 */
678
	public String[][] getGroups(String user, String password, String foruser)
679
			throws ConnectException {
680

    
681
		logMetacat.debug("getGroups() called.");
682

    
683
		// create vectors to store group and dscription values returned from the
684
		// ldap servers
685
		Vector gvec = new Vector();
686
		Vector desc = new Vector();
687
		Attributes tempAttr = null;
688
		Attributes rsrAttr = null;
689

    
690
		// DURING getGroups(), DO WE NOT BIND USING userName AND userPassword??
691
		// NEED TO FIX THIS ...
692
		userName = user;
693
		userPassword = password;
694
		// Identify service provider to use
695
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
696
		env.put(Context.REFERRAL, "throw");
697
		env.put(Context.PROVIDER_URL, ldapUrl);
698
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
699

    
700
		// Iterate through the referrals, handling NamingExceptions in the
701
		// outer catch statement, ReferralExceptions in the inner catch
702
		// statement
703
		try { // outer try
704

    
705
			// Create the initial directory context
706
			DirContext ctx = new InitialDirContext(env);
707

    
708
			// Specify the attributes to match.
709
			// Groups are objects with attribute objectclass=groupofuniquenames.
710
			// and have attribute uniquemember: uid=foruser,ldapbase.
711
			SearchControls ctls = new SearchControls();
712
			// Specify the ids of the attributes to return
713
			String[] attrIDs = { "cn", "o", "description" };
714
			ctls.setReturningAttributes(attrIDs);
715
			// set the ldap search scope
716
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
717
			// set a 10 second time limit on searches to limit non-responding
718
			// servers
719
			ctls.setTimeLimit(ldapSearchTimeLimit);
720
			// return at most 20000 entries
721
			ctls.setCountLimit(ldapSearchCountLimit);
722

    
723
			// build the ldap search filter that represents the "group" concept
724
			String filter = null;
725
			String gfilter = "(objectClass=groupOfUniqueNames)";
726
			if (null == foruser) {
727
				filter = gfilter;
728
			} else {
729
				filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
730
			}
731
			logMetacat.info("group filter is: " + filter);
732

    
733
			// now, search and iterate through the referrals
734
			for (boolean moreReferrals = true; moreReferrals;) {
735
				try { // inner try
736

    
737
					NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
738

    
739
					// Print the groups
740
					while (namingEnum.hasMore()) {
741
						SearchResult sr = (SearchResult) namingEnum.next();
742

    
743
						tempAttr = sr.getAttributes();
744

    
745
						if ((tempAttr.get("description") + "")
746
								.startsWith("description: ")) {
747
							desc.add((tempAttr.get("description") + "").substring(13));
748
						} else {
749
							desc.add(tempAttr.get("description") + "");
750
						}
751

    
752
						// check for an absolute URL value or an answer value
753
						// relative
754
						// to the target context
755
						if (!sr.getName().startsWith("ldap") && sr.isRelative()) {
756
							logMetacat.debug("Search result entry is relative ...");
757
							gvec.add(sr.getName() + "," + ldapBase);
758
							logMetacat.info("group " + sr.getName() + "," + ldapBase
759
									+ " added to the group vector");
760
						} else {
761
							logMetacat.debug("Search result entry is absolute ...");
762

    
763
							// search the top level directory for referral
764
							// objects and match
765
							// that of the search result's absolute URL. This
766
							// will let us
767
							// rebuild the group name from the search result,
768
							// referral point
769
							// in the top directory tree, and ldapBase.
770

    
771
							// configure a new directory search first
772
							Hashtable envHash = new Hashtable(11);
773
							// Identify service provider to use
774
							envHash.put(Context.INITIAL_CONTEXT_FACTORY,
775
									"com.sun.jndi.ldap.LdapCtxFactory");
776
							envHash.put(Context.REFERRAL, "ignore");
777
							envHash.put(Context.PROVIDER_URL, ldapUrl);
778
							envHash.put("com.sun.jndi.ldap.connect.timeout",
779
									ldapConnectTimeLimit);
780

    
781
							try {
782
								// Create the initial directory context
783
								DirContext DirCtx = new InitialDirContext(envHash);
784

    
785
								SearchControls searchCtls = new SearchControls();
786
								// Specify the ids of the attributes to return
787
								String[] attrNames = { "o" };
788
								searchCtls.setReturningAttributes(attrNames);
789
								// set the ldap search scope - only look for top
790
								// level referrals
791
								searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
792
								// set a time limit on searches to limit
793
								// non-responding servers
794
								searchCtls.setTimeLimit(ldapSearchTimeLimit);
795
								// return the configured number of entries
796
								searchCtls.setCountLimit(ldapSearchCountLimit);
797

    
798
								// Specify the attributes to match.
799
								// build the ldap search filter to match
800
								// referral entries that
801
								// match the search result
802
								String rFilter = "(&(objectClass=referral)(ref="
803
										+ currentReferralInfo.substring(0,
804
												currentReferralInfo.indexOf("?")) + "))";
805
								logMetacat.debug("rFilter is: " + rFilter);
806

    
807
								NamingEnumeration rNamingEnum = DirCtx.search(ldapBase,
808
										rFilter, searchCtls);
809

    
810
								while (rNamingEnum.hasMore()) {
811
									SearchResult rsr = (SearchResult) rNamingEnum.next();
812
									rsrAttr = rsr.getAttributes();
813
									logMetacat.debug("referral search result is: "
814
											+ rsr.toString());
815

    
816
									// add the returned groups to the group
817
									// vector. Test the
818
									// syntax of the returned attributes -
819
									// sometimes they are
820
									// preceded with the attribute id and a
821
									// colon
822
									if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
823
										gvec.add("cn="
824
												+ (tempAttr.get("cn") + "").substring(4)
825
												+ "," + "o="
826
												+ (rsrAttr.get("o") + "").substring(3)
827
												+ "," + ldapBase);
828
										logMetacat.info("group "
829
												+ (tempAttr.get("cn") + "").substring(4)
830
												+ "," + "o="
831
												+ (rsrAttr.get("o") + "").substring(3)
832
												+ "," + ldapBase
833
												+ " added to the group vector");
834
									} else {
835
										gvec.add("cn=" + tempAttr.get("cn") + "," + "o="
836
												+ rsrAttr.get("o") + "," + ldapBase);
837
										logMetacat.info("group " + "cn="
838
												+ tempAttr.get("cn") + "," + "o="
839
												+ rsrAttr.get("o") + "," + ldapBase
840
												+ " added to the group vector");
841
									}
842
								}
843

    
844
							} catch (NamingException nameEx) {
845
								logMetacat.debug("Caught naming exception: ");
846
								nameEx.printStackTrace(System.err);
847
							}
848
						}
849
					}// end while
850

    
851
					moreReferrals = false;
852

    
853
				} catch (ReferralException re) {
854

    
855
					logMetacat
856
							.info("In AuthLdap.getGroups(), caught referral exception: "
857
									+ re.getReferralInfo());
858
					this.currentReferralInfo = (String) re.getReferralInfo();
859

    
860
					// set moreReferrals to true and set the referral context
861
					moreReferrals = true;
862
					ctx = (DirContext) re.getReferralContext();
863

    
864
				}// end inner try
865
			}// end for
866

    
867
			// close the context now that all initial and referral
868
			// searches are processed
869
			ctx.close();
870

    
871
		} catch (NamingException e) {
872

    
873
			// naming exceptions get logged, groups are returned
874
			logMetacat.info("In AuthLdap.getGroups(), caught naming exception: ");
875
			e.printStackTrace(System.err);
876

    
877
		} finally {
878
			// once all referrals are followed, report and return the groups
879
			// found
880
			logMetacat.warn("The user is in the following groups: " + gvec.toString());
881
			// build and return the groups array
882
			String groups[][] = new String[gvec.size()][2];
883
			for (int i = 0; i < gvec.size(); i++) {
884
				groups[i][0] = (String) gvec.elementAt(i);
885
				groups[i][1] = (String) desc.elementAt(i);
886
			}
887
			return groups;
888
		}// end outer try
889
	}
890

    
891
	/**
892
	 * Get attributes describing a user or group
893
	 * 
894
	 * @param foruser
895
	 *            the user for which the attribute list is requested
896
	 * @returns HashMap a map of attribute name to a Vector of values
897
	 */
898
	public HashMap<String, Vector<String>> getAttributes(String foruser)
899
			throws ConnectException {
900
		return getAttributes(null, null, foruser);
901
	}
902

    
903
	/**
904
	 * Get attributes describing a user or group
905
	 * 
906
	 * @param user
907
	 *            the user for authenticating against the service
908
	 * @param password
909
	 *            the password for authenticating against the service
910
	 * @param foruser
911
	 *            the user whose attributes should be returned
912
	 * @returns HashMap a map of attribute name to a Vector of values
913
	 */
914
	public HashMap<String, Vector<String>> getAttributes(String user, String password,
915
			String foruser) throws ConnectException {
916
		HashMap<String, Vector<String>> attributes = new HashMap<String, Vector<String>>();
917
		String ldapUrl = this.ldapUrl;
918
		String ldapBase = this.ldapBase;
919
		String userident = foruser;
920

    
921
		// Identify service provider to use
922
		Hashtable env = new Hashtable(11);
923
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
924
		env.put(Context.REFERRAL, referral);
925
		env.put(Context.PROVIDER_URL, ldapUrl);
926

    
927
		try {
928

    
929
			// Create the initial directory context
930
			DirContext ctx = new InitialDirContext(env);
931

    
932
			// Ask for all attributes of the user
933
			// Attributes attrs = ctx.getAttributes(userident);
934
			Attributes attrs = ctx.getAttributes(foruser);
935

    
936
			// Print all of the attributes
937
			NamingEnumeration en = attrs.getAll();
938
			while (en.hasMore()) {
939
				Attribute att = (Attribute) en.next();
940
				Vector<String> values = new Vector();
941
				String attName = att.getID();
942
				NamingEnumeration attvalues = att.getAll();
943
				while (attvalues.hasMore()) {
944
					String value = (String) attvalues.next();
945
					values.add(value);
946
				}
947
				attributes.put(attName, values);
948
			}
949

    
950
			// Close the context when we're done
951
			ctx.close();
952
		} catch (NamingException e) {
953
			logMetacat.error("Problem getting attributes in " + "AuthLdap.getAttributes:"
954
					+ e);
955
			throw new ConnectException(
956
					"Problem getting attributes in AuthLdap.getAttributes:" + e);
957
		}
958

    
959
		return attributes;
960
	}
961

    
962
	/**
963
	 * Get list of all subtrees holding Metacat's groups and users starting from
964
	 * the Metacat LDAP root, i.e.
965
	 * ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
966
	 */
967
	private Hashtable getSubtrees(String user, String password, String ldapUrl,
968
			String ldapBase) throws ConnectException {
969
		Hashtable trees = new Hashtable();
970

    
971
		// Identify service provider to use
972
		Hashtable env = new Hashtable(11);
973
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
974
		// env.put(Context.REFERRAL, referral);
975
		// Using 'ignore' here instead of 'follow' as 'ignore' seems
976
		// to do the job better. 'follow' was not bringing up the UCNRS
977
		// and PISCO tree whereas 'ignore' brings up the tree.
978

    
979
		env.put(Context.REFERRAL, "ignore");
980
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
981

    
982
		try {
983

    
984
			// Create the initial directory context
985
			DirContext ctx = new InitialDirContext(env);
986

    
987
			// Specify the ids of the attributes to return
988
			String[] attrIDs = { "o", "ref" };
989
			SearchControls ctls = new SearchControls();
990
			ctls.setReturningAttributes(attrIDs);
991
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
992

    
993
			// Specify the attributes to match.
994
			// Subtrees from the main server are found as objects with attribute
995
			// objectclass=organization or objectclass=referral to the subtree
996
			// resided on other server.
997
			String filter = "(|(objectclass=organization)(objectclass=referral))";
998

    
999
			// Search for objects in the current context
1000
			NamingEnumeration namingEnum = ctx.search("", filter, ctls);
1001

    
1002
			// Print the subtrees' <ldapURL, baseDN>
1003
			while (namingEnum.hasMore()) {
1004

    
1005
				SearchResult sr = (SearchResult) namingEnum.next();
1006

    
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
							// appended in
1026
							// front of the ldapbase.... later it is stripped
1027
							// out
1028
							// in getPrincipals
1029
							trees.put("["
1030
									+ refName
1031
									+ "="
1032
									+ refValue
1033
									+ "]"
1034
									+ attrValue.substring(attrValue.lastIndexOf("/") + 1,
1035
											attrValue.length()), attrValue.substring(0,
1036
									attrValue.lastIndexOf("/") + 1));
1037

    
1038
							// trees.put(refName + "=" + refValue + "," +
1039
							// ldapBase,
1040
							// attrValue.substring(0, attrValue.lastIndexOf("/")
1041
							// + 1));
1042
						}
1043

    
1044
					} else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
1045
						trees.put(ldapBase, ldapUrl);
1046
					} else {
1047
						if (sr.isRelative()) {
1048
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1049
									ldapUrl);
1050
						} else {
1051
							String referenceURL = sr.getName();
1052
							referenceURL = referenceURL.substring(0, referenceURL
1053
									.lastIndexOf("/") + 1);
1054
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1055
									referenceURL);
1056
						}
1057

    
1058
					}
1059
				}
1060
			}
1061

    
1062
			// Close the context when we're done
1063
			ctx.close();
1064

    
1065
		} catch (NamingException e) {
1066
			logMetacat.error("Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1067
			throw new ConnectException(
1068
					"Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1069
		}
1070

    
1071
		return trees;
1072
	}
1073

    
1074
	/**
1075
	 * Get all groups and users from authentication scheme. The output is
1076
	 * formatted in XML.
1077
	 * 
1078
	 * @param user
1079
	 *            the user which requests the information
1080
	 * @param password
1081
	 *            the user's password
1082
	 */
1083
	public String getPrincipals(String user, String password) throws ConnectException {
1084
		StringBuffer out = new StringBuffer();
1085

    
1086
		out.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
1087
		out.append("<principals>\n");
1088

    
1089
		/*
1090
		 * get all subtrees first in the current dir context and then the
1091
		 * Metacat users under them
1092
		 */
1093
		Hashtable subtrees = getSubtrees(user, password, this.ldapUrl, this.ldapBase);
1094

    
1095
		Enumeration keyEnum = subtrees.keys();
1096
		while (keyEnum.hasMoreElements()) {
1097
			this.ldapBase = (String) keyEnum.nextElement();
1098
			this.ldapUrl = (String) subtrees.get(ldapBase);
1099
			logMetacat.info("ldapBase " + ldapBase);
1100
			logMetacat.info("ldapUrl " + ldapUrl);
1101
			/*
1102
			 * code to get the organization name from ldapBase
1103
			 */
1104
			String orgName = this.ldapBase;
1105
			if (orgName.startsWith("[")) {
1106
				// if orgName starts with [ then it is a referral URL...
1107
				// (see code in getSubtress)
1108
				// hence orgName can be retrieved by getting the string between
1109
				// 'o=' and ']'
1110
				// also the string between [ and ] needs to be striped out from
1111
				// this.ldapBase
1112
				this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1113
				if (orgName != null && orgName.indexOf("o=") > -1) {
1114
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1115
					orgName = orgName.substring(0, orgName.indexOf("]"));
1116
				}
1117
			} else {
1118
				// else it is not referral
1119
				// hence orgName can be retrieved by getting the string between
1120
				// 'o=' and ','
1121
				if (orgName != null && orgName.indexOf("o=") > -1) {
1122
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1123
					if (orgName.indexOf(",") > -1) {
1124
						orgName = orgName.substring(0, orgName.indexOf(","));
1125
					}
1126
				}
1127
			}
1128
			logMetacat.info("org name is  " + orgName);
1129
			out.append("  <authSystem URI=\"" + this.ldapUrl + this.ldapBase
1130
					+ "\" organization=\"" + orgName + "\">\n");
1131

    
1132
			// get all groups for directory context
1133
			String[][] groups = getGroups(user, password);
1134
			logMetacat.debug("after getting groups " + groups);
1135
			String[][] users = getUsers(user, password);
1136
			logMetacat.debug("after getting users " + users);
1137
			int userIndex = 0;
1138

    
1139
			// for the groups and users that belong to them
1140
			if (groups != null && users != null && groups.length > 0) {
1141
				for (int i = 0; i < groups.length; i++) {
1142
					out.append("    <group>\n");
1143
					out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1144
					out.append("      <description>" + groups[i][1] + "</description>\n");
1145
					String[] usersForGroup = getUsers(user, password, groups[i][0]);
1146
					for (int j = 0; j < usersForGroup.length; j++) {
1147
						userIndex = searchUser(usersForGroup[j], users);
1148
						out.append("      <user>\n");
1149

    
1150
						if (userIndex < 0) {
1151
							out.append("        <username>" + usersForGroup[j]
1152
									+ "</username>\n");
1153
						} else {
1154
							out.append("        <username>" + users[userIndex][0]
1155
									+ "</username>\n");
1156
							out.append("        <name>" + users[userIndex][1]
1157
									+ "</name>\n");
1158
							out.append("        <organization>" + users[userIndex][2]
1159
									+ "</organization>\n");
1160
							if (users[userIndex][3].compareTo("null") != 0) {
1161
								out.append("      <organizationUnitName>"
1162
										+ users[userIndex][3]
1163
										+ "</organizationUnitName>\n");
1164
							}
1165
							out.append("        <email>" + users[userIndex][4]
1166
									+ "</email>\n");
1167
						}
1168

    
1169
						out.append("      </user>\n");
1170
					}
1171
					out.append("    </group>\n");
1172
				}
1173
			}
1174

    
1175
			if (users != null) {
1176
				// for the users not belonging to any grou8p
1177
				for (int j = 0; j < users.length; j++) {
1178
					out.append("    <user>\n");
1179
					out.append("      <username>" + users[j][0] + "</username>\n");
1180
					out.append("      <name>" + users[j][1] + "</name>\n");
1181
					out
1182
							.append("      <organization>" + users[j][2]
1183
									+ "</organization>\n");
1184
					if (users[j][3].compareTo("null") != 0) {
1185
						out.append("      <organizationUnitName>" + users[j][3]
1186
								+ "</organizationUnitName>\n");
1187
					}
1188
					out.append("      <email>" + users[j][4] + "</email>\n");
1189
					out.append("    </user>\n");
1190
				}
1191
			}
1192

    
1193
			out.append("  </authSystem>\n");
1194
		}
1195
		out.append("</principals>");
1196
		return out.toString();
1197
	}
1198

    
1199
	/**
1200
	 * Method for getting index of user DN in User info array
1201
	 */
1202
	int searchUser(String user, String userGroup[][]) {
1203
		for (int j = 0; j < userGroup.length; j++) {
1204
			if (user.compareTo(userGroup[j][0]) == 0) {
1205
				return j;
1206
			}
1207
		}
1208
		return -1;
1209
	}
1210

    
1211
	public void testCredentials(String dn, String password, String rootServer,
1212
			String rootBase) throws NamingException {
1213

    
1214
		String server = "";
1215
		String userDN = "";
1216
		logMetacat.debug("dn is: " + dn);
1217

    
1218
		int position = dn.lastIndexOf("/");
1219
		logMetacat.debug("position is: " + position);
1220
		if (position == -1) {
1221
			server = rootServer;
1222
			if (dn.indexOf(userDN) < 0) {
1223
				userDN = dn + "," + rootBase;
1224
			} else {
1225
				userDN = dn;
1226
			}
1227
			logMetacat.debug("userDN is: " + userDN);
1228

    
1229
		} else {
1230
			server = dn.substring(0, position + 1);
1231
			userDN = dn.substring(position + 1);
1232
			logMetacat.debug("server is: " + server);
1233
			logMetacat.debug("userDN is: " + userDN);
1234
		}
1235

    
1236
		logMetacat.debug("Trying to authenticate: " + userDN);
1237
		logMetacat.debug("          Using server: " + server);
1238

    
1239
		// /* try {
1240
		LdapContext ctx = null;
1241

    
1242
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1243
		env.put(Context.REFERRAL, "follow");
1244
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
1245
		env.put(Context.SECURITY_PRINCIPAL, userDN);
1246
		env.put(Context.SECURITY_CREDENTIALS, password);
1247
		env.put(Context.PROVIDER_URL, rootServer);
1248

    
1249
		ctx = new InitialLdapContext(env, null);
1250

    
1251
	}
1252

    
1253
	/**
1254
	 * Test method for the class
1255
	 */
1256
	public static void main(String[] args) {
1257

    
1258
		// Provide a user, such as: "Matt Jones", or "jones"
1259
		String user = args[0];
1260
		String password = args[1];
1261
		String org = args[2];
1262

    
1263
		logMetacat.warn("Creating session...");
1264
		AuthLdap authservice = null;
1265
		try {
1266
			authservice = new AuthLdap();
1267
		} catch (Exception e) {
1268
			logMetacat.error("Could not instantiate AuthLdap: " + e.getMessage());
1269
			return;
1270
		}
1271
		logMetacat.warn("Session exists...");
1272

    
1273
		boolean isValid = false;
1274
		try {
1275
			logMetacat.warn("Authenticating...");
1276
			isValid = authservice.authenticate(user, password);
1277
			if (isValid) {
1278
				logMetacat.warn("Authentication successful for: " + user);
1279
			} else {
1280
				logMetacat.warn("Authentication failed for: " + user);
1281
			}
1282

    
1283
			// Get attributes for the user
1284
			if (isValid) {
1285
				logMetacat.info("\nGetting attributes for user....");
1286
				HashMap userInfo = authservice.getAttributes(user, password, user);
1287
				// Print all of the attributes
1288
				Iterator attList = (Iterator) (((Set) userInfo.keySet()).iterator());
1289
				while (attList.hasNext()) {
1290
					String att = (String) attList.next();
1291
					Vector values = (Vector) userInfo.get(att);
1292
					Iterator attvalues = values.iterator();
1293
					while (attvalues.hasNext()) {
1294
						String value = (String) attvalues.next();
1295
						logMetacat.warn(att + ": " + value);
1296
					}
1297
				}
1298
			}
1299

    
1300
			// get the groups
1301
			if (isValid) {
1302
				logMetacat.warn("\nGetting all groups....");
1303
				String[][] groups = authservice.getGroups(user, password);
1304
				logMetacat.info("Groups found: " + groups.length);
1305
				for (int i = 0; i < groups.length; i++) {
1306
					logMetacat.info("Group " + i + ": " + groups[i][0]);
1307
				}
1308
			}
1309

    
1310
			// get the groups for the user
1311
			String savedGroup = null;
1312
			if (isValid) {
1313
				logMetacat.warn("\nGetting groups for user....");
1314
				String[][] groups = authservice.getGroups(user, password, user);
1315
				logMetacat.info("Groups found: " + groups.length);
1316
				for (int i = 0; i < groups.length; i++) {
1317
					logMetacat.info("Group " + i + ": " + groups[i][0]);
1318
					savedGroup = groups[i][0];
1319
				}
1320
			}
1321

    
1322
			// get the users for a group
1323
			if (isValid) {
1324
				logMetacat.warn("\nGetting users for group....");
1325
				logMetacat.info("Group: " + savedGroup);
1326
				String[] users = authservice.getUsers(user, password, savedGroup);
1327
				logMetacat.info("Users found: " + users.length);
1328
				for (int i = 0; i < users.length; i++) {
1329
					logMetacat.warn("User " + i + ": " + users[i]);
1330
				}
1331
			}
1332

    
1333
			// get all users
1334
			if (isValid) {
1335
				logMetacat.warn("\nGetting all users ....");
1336
				String[][] users = authservice.getUsers(user, password);
1337
				logMetacat.info("Users found: " + users.length);
1338

    
1339
			}
1340

    
1341
			// get the whole list groups and users in XML format
1342
			if (isValid) {
1343
				logMetacat.warn("\nTrying principals....");
1344
				authservice = new AuthLdap();
1345
				String out = authservice.getPrincipals(user, password);
1346
				java.io.File f = new java.io.File("principals.xml");
1347
				java.io.FileWriter fw = new java.io.FileWriter(f);
1348
				java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1349
				buff.write(out);
1350
				buff.flush();
1351
				buff.close();
1352
				fw.close();
1353
				logMetacat.warn("\nFinished getting principals.");
1354
			}
1355

    
1356
		} catch (ConnectException ce) {
1357
			logMetacat.error(ce.getMessage());
1358
		} catch (java.io.IOException ioe) {
1359
			logMetacat.error("I/O Error writing to file principals.txt: "
1360
					+ ioe.getMessage());
1361
		} catch (InstantiationException ie) {
1362
			logMetacat.error("Instantiation error writing to file principals.txt: "
1363
					+ ie.getMessage());
1364
		}
1365
	}
1366

    
1367
	/**
1368
	 * This method will be called by start a thread. It can handle if a referral
1369
	 * exception happend.
1370
	 */
1371
}
(10-10/68)