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: 2009-12-18 13:37:26 -0800 (Fri, 18 Dec 2009) $'
12
 * '$Revision: 5167 $'
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.properties.PropertyService;
53
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
54

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

    
65
/**
66
 * 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
 */
71
public class AuthLdap implements AuthInterface {
72
	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<String, String> env = new Hashtable<String, String>(11);
81
	private Context rContext;
82
	private String userName;
83
	private String userPassword;
84
	ReferralException refExc;
85

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

    
88
	/**
89
	 * Construct an AuthLdap
90
	 */
91
	public AuthLdap() throws InstantiationException {
92
		// Read LDAP URI for directory service information
93
		try {
94
			this.ldapUrl = PropertyService.getProperty("auth.url");
95
			this.ldapsUrl = PropertyService.getProperty("auth.surl");
96
			this.ldapBase = PropertyService.getProperty("auth.base");
97
			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

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

    
118
	/**
119
	 * 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
	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

    
135
		// 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

    
143
		logMetacat.debug("AuthLdap.authenticate - identifier: " + identifier + 
144
				", uid: " + uid +", user: " + user);
145

    
146
		try {
147
			// Check the usename as passed in
148
			logMetacat.info("AuthLdap.authenticate - Calling ldapAuthenticate" +
149
				" with user as identifier: " + identifier);
150

    
151
			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
				logMetacat.info("AuthLdap.authenticate - Not Authenticated");
157
				logMetacat.info("AuthLdap.authenticate - Looking up DN for: " + identifier);
158
				identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
159
				if (identifier == null) {
160
					logMetacat.info("AuthLdap.authenticate - No DN found from getIdentifyingName");
161
					return authenticated;
162
				}
163

    
164
				logMetacat.info("AuthLdap.authenticate - DN found from getIdentifyingName: " + identifier);
165
				String decoded = URLDecoder.decode(identifier);
166
				logMetacat.info("AuthLdap.authenticate - DN decoded: " + decoded);
167
				identifier = decoded;
168
				String refUrl = "";
169
				String refBase = "";
170
				if (identifier.startsWith("ldap")) {
171
					logMetacat.debug("AuthLdap.authenticate - identifier starts with \"ldap\"");
172

    
173
					refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1);
174
					int position = identifier.indexOf(",");
175
					int position2 = identifier.indexOf(",", position + 1);
176

    
177
					refBase = identifier.substring(position2 + 1);
178
					identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
179

    
180
					logMetacat.info("AuthLdap.authenticate - Calling ldapAuthenticate: " +
181
						"with user as identifier: " + identifier + " and refUrl as: " + 
182
						refUrl + " and refBase as: " + refBase);
183

    
184
					authenticated = ldapAuthenticate(identifier, password, refUrl,
185
							refBase, (new Boolean(PropertyService
186
									.getProperty("ldap.onlySecureReferalsConnection")))
187
									.booleanValue());
188
				} else {
189
					logMetacat.info("AuthLdap.authenticate - identifier doesnt start with ldap");
190
					identifier = identifier + "," + ldapBase;
191

    
192
					logMetacat.info("AuthLdap.authenticate - Calling ldapAuthenticate" + 
193
							"with user as identifier: " + identifier);
194

    
195
					authenticated = ldapAuthenticate(identifier, password, (new Boolean(
196
							PropertyService.getProperty("ldap.onlySecureConnection")))
197
							.booleanValue());
198
				}
199
			}
200
		} catch (NullPointerException npe) {
201
			logMetacat.error("AuthLdap.authenticate - NullPointerException while authenticating in "
202
					+ "AuthLdap.authenticate: " + npe);
203
			npe.printStackTrace();
204

    
205
			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
		}
215

    
216
		return authenticated;
217
	}
218

    
219
	/**
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

    
235
	/**
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

    
245
	private boolean ldapAuthenticate(String dn, String password, String rootServer,
246
			String rootBase, boolean secureConnectionOnly) {
247

    
248
		boolean authenticated = false;
249

    
250
		String server = "";
251
		String userDN = "";
252
		logMetacat.info("AuthLdap.ldapAuthenticate - dn is: " + dn);
253

    
254
		int position = dn.lastIndexOf("/");
255
		logMetacat.debug("AuthLdap.ldapAuthenticate - position is: " + position);
256
		if (position == -1) {
257
			server = rootServer;
258
			if (dn.indexOf(userDN) < 0) {
259
				userDN = dn + "," + rootBase;
260
			} else {
261
				userDN = dn;
262
			}
263
			logMetacat.info("AuthLdap.ldapAuthenticate - userDN is: " + userDN);
264

    
265
		} else {
266
			server = dn.substring(0, position + 1);
267
			userDN = dn.substring(position + 1);
268
			logMetacat.info("AuthLdap.ldapAuthenticate - server is: " + server);
269
			logMetacat.info("AuthLdap.ldapAuthenticate - userDN is: " + userDN);
270
		}
271

    
272
		logMetacat.warn("AuthLdap.ldapAuthenticate - Trying to authenticate: " + 
273
				userDN + " Using server: " + server);
274

    
275
		try {
276
			Hashtable<String, String> env = new Hashtable<String, String>();
277
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
278
			env.put(Context.PROVIDER_URL, server);
279
			env.put(Context.REFERRAL, "throw");
280
			
281
			try {
282
				authenticated = authenticateTLS(env, userDN, password);
283
			} catch (AuthTLSException ate) {
284
				logMetacat.info("AuthLdap.ldapAuthenticate - error while negotiating TLS: "
285
						+ ate.getMessage());
286

    
287
				if (secureConnectionOnly) {
288
					return authenticated;
289

    
290
				} else {
291
					authenticated = authenticateNonTLS(env, userDN, password);
292
				}
293
			}
294
		} catch (AuthenticationException ae) {
295
			logMetacat.warn("Authentication exception: " + ae.getMessage());
296
			authenticated = false;
297
		} catch (javax.naming.InvalidNameException ine) {
298
			logMetacat.error("AuthLdap.ldapAuthenticate - An invalid DN was provided: " + ine.getMessage());
299
		} catch (NamingException ne) {
300
			logMetacat.warn("AuthLdap.ldapAuthenticate - Caught NamingException in login: " + ne.getClass().getName());
301
			logMetacat.info(ne.toString() + "  " + ne.getRootCause());
302
		}
303

    
304
		return authenticated;
305
	}
306
	
307
	private boolean authenticateTLS(Hashtable<String, String> env, String userDN, String password)
308
			throws AuthTLSException{	
309
		logMetacat.info("AuthLdap.authenticateTLS - Trying to authenticate with TLS");
310
		try {
311
			LdapContext ctx = null;
312
			double startTime;
313
			double stopTime;
314
			startTime = System.currentTimeMillis();
315
			ctx = new InitialLdapContext(env, null);
316
			// Start up TLS here so that we don't pass our jewels in
317
			// cleartext
318
			StartTlsResponse tls = 
319
				(StartTlsResponse) ctx.extendedOperation(new StartTlsRequest());
320
			// tls.setHostnameVerifier(new SampleVerifier());
321
			SSLSession sess = tls.negotiate();
322
			ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
323
			ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
324
			ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
325
			ctx.reconnect(null);
326
			stopTime = System.currentTimeMillis();
327
			logMetacat.info("AuthLdap.authenticateTLS - Connection time thru "
328
					+ ldapsUrl + " was: " + (stopTime - startTime) / 1000 + " seconds.");
329
		} catch (NamingException ne) {
330
			throw new AuthTLSException("AuthLdap.authenticateTLS - Naming error when athenticating via TLS: " + ne.getMessage());
331
		} catch (IOException ioe) {
332
			throw new AuthTLSException("AuthLdap.authenticateTLS - I/O error when athenticating via TLS: " + ioe.getMessage());
333
		}
334
		return true;
335
	}
336
	
337
	private boolean authenticateNonTLS(Hashtable<String, String> env, String userDN, String password) 
338
			throws NamingException {
339
		LdapContext ctx = null;
340
		double startTime;
341
		double stopTime;
342
		
343
		logMetacat.info("AuthLdap.authenticateNonTLS - Trying to authenticate without TLS");
344
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
345
		env.put(Context.SECURITY_PRINCIPAL, userDN);
346
		env.put(Context.SECURITY_CREDENTIALS, password);
347

    
348
		startTime = System.currentTimeMillis();
349
		ctx = new InitialLdapContext(env, null);
350
		stopTime = System.currentTimeMillis();
351
		logMetacat.info("AuthLdap.authenticateNonTLS - Connection time thru " + ldapsUrl + " was: "
352
				+ (stopTime - startTime) / 1000 + " seconds.");
353

    
354
		return true;
355
	}
356

    
357
	/**
358
	 * Get the identifying name for a given userid or name. This is the name
359
	 * that is used in conjunction withthe LDAP BaseDN to create a distinguished
360
	 * name (dn) for the record
361
	 * 
362
	 * @param user
363
	 *            the user for which the identifying name is requested
364
	 * @returns String the identifying name for the user, or null if not found
365
	 */
366
	private String getIdentifyingName(String user, String ldapUrl, String ldapBase)
367
			throws NamingException {
368

    
369
		String identifier = null;
370
		Hashtable env = new Hashtable();
371
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
372
		env.put(Context.REFERRAL, "throw");
373
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
374
		try {
375
			int position = user.indexOf(",");
376
			String uid = user.substring(user.indexOf("=") + 1, position);
377
			logMetacat.info("AuthLdap.getIdentifyingName - uid is: " + uid);
378
			String org = user.substring(user.indexOf("=", position + 1) + 1, user
379
					.indexOf(",", position + 1));
380
			logMetacat.info("AuthLdap.getIdentifyingName - org is: " + org);
381

    
382
			DirContext sctx = new InitialDirContext(env);
383
			SearchControls ctls = new SearchControls();
384
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
385
			String filter = "(&(uid=" + uid + ")(o=" + org + "))";
386
			logMetacat.warn("AuthLdap.getIdentifyingName - Searching for DNs with following filter: " + filter);
387

    
388
			for (boolean moreReferrals = true; moreReferrals;) {
389
				try {
390
					// Perform the search
391
					NamingEnumeration answer = sctx.search("", filter, ctls);
392

    
393
					// Return the answer
394
					while (answer.hasMore()) {
395
						SearchResult sr = (SearchResult) answer.next();
396
						identifier = sr.getName();
397
						return identifier;
398
					}
399
					// The search completes with no more referrals
400
					moreReferrals = false;
401
				} catch (ReferralException e) {
402
					logMetacat.info("AuthLdap.getIdentifyingName - Got referral: " + e.getReferralInfo());
403
					// Point to the new context from the referral
404
					if (moreReferrals) {
405
						sctx = (DirContext) e.getReferralContext();
406
					}
407
				}
408
			}
409
		} catch (NamingException e) {
410
			logMetacat.error("AuthLdap.getIdentifyingName - Naming exception while getting dn: " + e);
411
			throw new NamingException("Naming exception in AuthLdap.getIdentifyingName: "
412
					+ e);
413
		}
414
		return identifier;
415
	}
416

    
417
	/**
418
	 * Get all users from the authentication service
419
	 * 
420
	 * @param user
421
	 *            the user for authenticating against the service
422
	 * @param password
423
	 *            the password for authenticating against the service
424
	 * @returns string array of all of the user names
425
	 */
426
	public String[][] getUsers(String user, String password) throws ConnectException {
427
		String[][] users = null;
428

    
429
		// Identify service provider to use
430
		Hashtable env = new Hashtable(11);
431
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
432
		env.put(Context.REFERRAL, referral);
433
		env.put(Context.PROVIDER_URL, ldapUrl);
434
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
435

    
436
		try {
437

    
438
			// Create the initial directory context
439
			DirContext ctx = new InitialDirContext(env);
440

    
441
			// Specify the attributes to match.
442
			// Users are objects that have the attribute
443
			// objectclass=InetOrgPerson.
444
			SearchControls ctls = new SearchControls();
445
			String[] attrIDs = { "dn", "cn", "o", "ou", "mail" };
446
			ctls.setReturningAttributes(attrIDs);
447
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
448
			ctls.setTimeLimit(ldapSearchTimeLimit);
449
			// ctls.setCountLimit(1000);
450
			String filter = "(objectClass=inetOrgPerson)";
451
			NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
452

    
453
			// Store the users in a vector
454
			Vector uvec = new Vector();
455
			Vector uname = new Vector();
456
			Vector uorg = new Vector();
457
			Vector uou = new Vector();
458
			Vector umail = new Vector();
459
			Attributes tempAttr = null;
460
			try {
461
				while (namingEnum.hasMore()) {
462
					SearchResult sr = (SearchResult) namingEnum.next();
463
					tempAttr = sr.getAttributes();
464

    
465
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
466
						uname.add((tempAttr.get("cn") + "").substring(4));
467
					} else {
468
						uname.add(tempAttr.get("cn") + "");
469
					}
470

    
471
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
472
						uorg.add((tempAttr.get("o") + "").substring(3));
473
					} else {
474
						uorg.add(tempAttr.get("o") + "");
475
					}
476

    
477
					if ((tempAttr.get("ou") + "").startsWith("ou: ")) {
478
						uou.add((tempAttr.get("ou") + "").substring(4));
479
					} else {
480
						uou.add(tempAttr.get("ou") + "");
481
					}
482

    
483
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
484
						umail.add((tempAttr.get("mail") + "").substring(6));
485
					} else {
486
						umail.add(tempAttr.get("mail") + "");
487
					}
488

    
489
					uvec.add(sr.getName() + "," + ldapBase);
490
				}
491
			} catch (SizeLimitExceededException slee) {
492
				logMetacat.error("AuthLdap.getUsers - LDAP Server size limit exceeded. "
493
						+ "Returning incomplete record set.");
494
			}
495

    
496
			// initialize users[]; fill users[]
497
			users = new String[uvec.size()][5];
498
			for (int i = 0; i < uvec.size(); i++) {
499
				users[i][0] = (String) uvec.elementAt(i);
500
				users[i][1] = (String) uname.elementAt(i);
501
				users[i][2] = (String) uorg.elementAt(i);
502
				users[i][3] = (String) uorg.elementAt(i);
503
				users[i][4] = (String) umail.elementAt(i);
504
			}
505

    
506
			// Close the context when we're done
507
			ctx.close();
508

    
509
		} catch (NamingException e) {
510
			logMetacat.error("AuthLdap.getUsers - Problem getting users in AuthLdap.getUsers:" + e);
511
			// e.printStackTrace(System.err);
512
			/*
513
			 * throw new ConnectException( "Problem getting users in
514
			 * AuthLdap.getUsers:" + e);
515
			 */
516
		}
517

    
518
		return users;
519
	}
520

    
521
	/**
522
	 * Get all users from the authentication service
523
	 * 
524
	 * @param user
525
	 *            the user for authenticating against the service
526
	 * @param password
527
	 *            the password for authenticating against the service
528
	 * @returns string array of all of the user names
529
	 */
530
	public String[] getUserInfo(String user, String password) throws ConnectException {
531
		String[] userinfo = new String[3];
532

    
533
		// Identify service provider to use
534
		Hashtable env = new Hashtable(11);
535
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
536
		env.put(Context.REFERRAL, referral);
537
		env.put(Context.PROVIDER_URL, ldapUrl);
538

    
539
		try {
540

    
541
			// Create the initial directory context
542
			DirContext ctx = new InitialDirContext(env);
543
			// Specify the attributes to match.
544
			// Users are objects that have the attribute
545
			// objectclass=InetOrgPerson.
546
			SearchControls ctls = new SearchControls();
547
			String[] attrIDs = { "cn", "o", "mail" };
548
			ctls.setReturningAttributes(attrIDs);
549
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
550
			// ctls.setCountLimit(1000);
551
			// create the filter based on the uid
552

    
553
			String filter = null;
554

    
555
			if (user.indexOf("o=") > 0) {
556
				String tempStr = user.substring(user.indexOf("o="));
557
				filter = "(&(" + user.substring(0, user.indexOf(",")) + ")("
558
						+ tempStr.substring(0, tempStr.indexOf(",")) + "))";
559
			} else {
560
				filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
561
			}
562
			filter = "(&(" + user.substring(0, user.indexOf(",")) + "))";
563

    
564
			NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
565

    
566
			Attributes tempAttr = null;
567
			try {
568
				while (namingEnum.hasMore()) {
569
					SearchResult sr = (SearchResult) namingEnum.next();
570
					tempAttr = sr.getAttributes();
571

    
572
					if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
573
						userinfo[0] = (tempAttr.get("cn") + "").substring(4);
574
					} else {
575
						userinfo[0] = (tempAttr.get("cn") + "");
576
					}
577

    
578
					if ((tempAttr.get("o") + "").startsWith("o: ")) {
579
						userinfo[1] = (tempAttr.get("o") + "").substring(3);
580
					} else {
581
						userinfo[1] = (tempAttr.get("o") + "");
582
					}
583

    
584
					if ((tempAttr.get("mail") + "").startsWith("mail: ")) {
585
						userinfo[2] = (tempAttr.get("mail") + "").substring(6);
586
					} else {
587
						userinfo[2] = (tempAttr.get("mail") + "");
588
					}
589
				}
590
			} catch (SizeLimitExceededException slee) {
591
				logMetacat.error("AuthLdap.getUserInfo - LDAP Server size limit exceeded. "
592
						+ "Returning incomplete record set.");
593
			}
594

    
595
			// Close the context when we're done
596
			ctx.close();
597

    
598
		} catch (NamingException e) {
599
			logMetacat.error("AuthLdap.getUserInfo - Problem getting users:" + e);
600
			// e.printStackTrace(System.err);
601
			throw new ConnectException("Problem getting users in AuthLdap.getUsers:" + e);
602
		}
603

    
604
		return userinfo;
605
	}
606

    
607
	/**
608
	 * Get the users for a particular group from the authentication service
609
	 * 
610
	 * @param user
611
	 *            the user for authenticating against the service
612
	 * @param password
613
	 *            the password for authenticating against the service
614
	 * @param group
615
	 *            the group whose user list should be returned
616
	 * @returns string array of the user names belonging to the group
617
	 */
618
	public String[] getUsers(String user, String password, String group)
619
			throws ConnectException {
620
		String[] users = null;
621

    
622
		// Identify service provider to use
623
		Hashtable env = new Hashtable(11);
624
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
625
		env.put(Context.REFERRAL, referral);
626
		env.put(Context.PROVIDER_URL, ldapUrl);
627

    
628
		try {
629

    
630
			// Create the initial directory context
631
			DirContext ctx = new InitialDirContext(env);
632

    
633
			// Specify the ids of the attributes to return
634
			String[] attrIDs = { "uniqueMember" };
635

    
636
			Attributes answer = ctx.getAttributes(group, attrIDs);
637

    
638
			Vector uvec = new Vector();
639
			try {
640
				for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) {
641
					Attribute attr = (Attribute) ae.next();
642
					for (NamingEnumeration e = attr.getAll(); e.hasMore(); uvec.add(e
643
							.next())) {
644
						;
645
					}
646
				}
647
			} catch (SizeLimitExceededException slee) {
648
				logMetacat.error("AuthLdap.getUsers - LDAP Server size limit exceeded. "
649
						+ "Returning incomplete record set.");
650
			}
651

    
652
			// initialize users[]; fill users[]
653
			users = new String[uvec.size()];
654
			for (int i = 0; i < uvec.size(); i++) {
655
				users[i] = (String) uvec.elementAt(i);
656
			}
657

    
658
			// Close the context when we're done
659
			ctx.close();
660

    
661
		} catch (NamingException e) {
662
			logMetacat.error("AuthLdap.getUsers - Problem getting users for a group in "
663
					+ "AuthLdap.getUsers:" + e);
664
			/*
665
			 * throw new ConnectException( "Problem getting users for a group in
666
			 * AuthLdap.getUsers:" + e);
667
			 */
668
		}
669

    
670
		return users;
671
	}
672

    
673
	/**
674
	 * Get all groups from the authentication service
675
	 * 
676
	 * @param user
677
	 *            the user for authenticating against the service
678
	 * @param password
679
	 *            the password for authenticating against the service
680
	 * @returns string array of the group names
681
	 */
682
	public String[][] getGroups(String user, String password) throws ConnectException {
683
		return getGroups(user, password, null);
684
	}
685

    
686
	/**
687
	 * Get the groups for a particular user from the authentication service
688
	 * 
689
	 * @param user
690
	 *            the user for authenticating against the service
691
	 * @param password
692
	 *            the password for authenticating against the service
693
	 * @param foruser
694
	 *            the user whose group list should be returned
695
	 * @returns string array of the group names
696
	 */
697
	public String[][] getGroups(String user, String password, String foruser)
698
			throws ConnectException {
699

    
700
		logMetacat.debug("AuthLdap.getGroups - getGroups() called.");
701

    
702
		// create vectors to store group and dscription values returned from the
703
		// ldap servers
704
		Vector gvec = new Vector();
705
		Vector desc = new Vector();
706
		Attributes tempAttr = null;
707
		Attributes rsrAttr = null;
708

    
709
		// DURING getGroups(), DO WE NOT BIND USING userName AND userPassword??
710
		// NEED TO FIX THIS ...
711
		userName = user;
712
		userPassword = password;
713
		// Identify service provider to use
714
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
715
		env.put(Context.REFERRAL, "throw");
716
		env.put(Context.PROVIDER_URL, ldapUrl);
717
		env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
718

    
719
		// Iterate through the referrals, handling NamingExceptions in the
720
		// outer catch statement, ReferralExceptions in the inner catch
721
		// statement
722
		try { // outer try
723

    
724
			// Create the initial directory context
725
			DirContext ctx = new InitialDirContext(env);
726

    
727
			// Specify the attributes to match.
728
			// Groups are objects with attribute objectclass=groupofuniquenames.
729
			// and have attribute uniquemember: uid=foruser,ldapbase.
730
			SearchControls ctls = new SearchControls();
731
			// Specify the ids of the attributes to return
732
			String[] attrIDs = { "cn", "o", "description" };
733
			ctls.setReturningAttributes(attrIDs);
734
			// set the ldap search scope
735
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
736
			// set a 10 second time limit on searches to limit non-responding
737
			// servers
738
			ctls.setTimeLimit(ldapSearchTimeLimit);
739
			// return at most 20000 entries
740
			ctls.setCountLimit(ldapSearchCountLimit);
741

    
742
			// build the ldap search filter that represents the "group" concept
743
			String filter = null;
744
			String gfilter = "(objectClass=groupOfUniqueNames)";
745
			if (null == foruser) {
746
				filter = gfilter;
747
			} else {
748
				filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
749
			}
750
			logMetacat.info("AuthLdap.getGroups - group filter is: " + filter);
751

    
752
			// now, search and iterate through the referrals
753
			for (boolean moreReferrals = true; moreReferrals;) {
754
				try { // inner try
755

    
756
					NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
757

    
758
					// Print the groups
759
					while (namingEnum.hasMore()) {
760
						SearchResult sr = (SearchResult) namingEnum.next();
761

    
762
						tempAttr = sr.getAttributes();
763

    
764
						if ((tempAttr.get("description") + "")
765
								.startsWith("description: ")) {
766
							desc.add((tempAttr.get("description") + "").substring(13));
767
						} else {
768
							desc.add(tempAttr.get("description") + "");
769
						}
770

    
771
						// check for an absolute URL value or an answer value
772
						// relative
773
						// to the target context
774
						if (!sr.getName().startsWith("ldap") && sr.isRelative()) {
775
							logMetacat.debug("AuthLdap.getGroups - Search result entry is relative ...");
776
							gvec.add(sr.getName() + "," + ldapBase);
777
							logMetacat.info("AuthLdap.getGroups - group " + sr.getName() + "," + ldapBase
778
									+ " added to the group vector");
779
						} else {
780
							logMetacat.debug("AuthLdap.getGroups - Search result entry is absolute ...");
781

    
782
							// search the top level directory for referral
783
							// objects and match
784
							// that of the search result's absolute URL. This
785
							// will let us
786
							// rebuild the group name from the search result,
787
							// referral point
788
							// in the top directory tree, and ldapBase.
789

    
790
							// configure a new directory search first
791
							Hashtable envHash = new Hashtable(11);
792
							// Identify service provider to use
793
							envHash.put(Context.INITIAL_CONTEXT_FACTORY,
794
									"com.sun.jndi.ldap.LdapCtxFactory");
795
							envHash.put(Context.REFERRAL, "ignore");
796
							envHash.put(Context.PROVIDER_URL, ldapUrl);
797
							envHash.put("com.sun.jndi.ldap.connect.timeout",
798
									ldapConnectTimeLimit);
799

    
800
							try {
801
								// Create the initial directory context
802
								DirContext DirCtx = new InitialDirContext(envHash);
803

    
804
								SearchControls searchCtls = new SearchControls();
805
								// Specify the ids of the attributes to return
806
								String[] attrNames = { "o" };
807
								searchCtls.setReturningAttributes(attrNames);
808
								// set the ldap search scope - only look for top
809
								// level referrals
810
								searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
811
								// set a time limit on searches to limit
812
								// non-responding servers
813
								searchCtls.setTimeLimit(ldapSearchTimeLimit);
814
								// return the configured number of entries
815
								searchCtls.setCountLimit(ldapSearchCountLimit);
816

    
817
								// Specify the attributes to match.
818
								// build the ldap search filter to match
819
								// referral entries that
820
								// match the search result
821
								String rFilter = "(&(objectClass=referral)(ref="
822
										+ currentReferralInfo.substring(0,
823
												currentReferralInfo.indexOf("?")) + "))";
824
								logMetacat.debug("AuthLdap.getGroups - rFilter is: " + rFilter);
825

    
826
								NamingEnumeration rNamingEnum = DirCtx.search(ldapBase,
827
										rFilter, searchCtls);
828

    
829
								while (rNamingEnum.hasMore()) {
830
									SearchResult rsr = (SearchResult) rNamingEnum.next();
831
									rsrAttr = rsr.getAttributes();
832
									logMetacat.debug("AuthLdap.getGroups - referral search result is: "
833
											+ rsr.toString());
834

    
835
									// add the returned groups to the group
836
									// vector. Test the
837
									// syntax of the returned attributes -
838
									// sometimes they are
839
									// preceded with the attribute id and a
840
									// colon
841
									if ((tempAttr.get("cn") + "").startsWith("cn: ")) {
842
										gvec.add("cn="
843
												+ (tempAttr.get("cn") + "").substring(4)
844
												+ "," + "o="
845
												+ (rsrAttr.get("o") + "").substring(3)
846
												+ "," + ldapBase);
847
										logMetacat.info("AuthLdap.getGroups - group "
848
												+ (tempAttr.get("cn") + "").substring(4)
849
												+ "," + "o="
850
												+ (rsrAttr.get("o") + "").substring(3)
851
												+ "," + ldapBase
852
												+ " added to the group vector");
853
									} else {
854
										gvec.add("cn=" + tempAttr.get("cn") + "," + "o="
855
												+ rsrAttr.get("o") + "," + ldapBase);
856
										logMetacat.info("AuthLdap.getGroups - group " + "cn="
857
												+ tempAttr.get("cn") + "," + "o="
858
												+ rsrAttr.get("o") + "," + ldapBase
859
												+ " added to the group vector");
860
									}
861
								}
862

    
863
							} catch (NamingException nameEx) {
864
								logMetacat.debug("AuthLdap.getGroups - Caught naming exception: ");
865
								nameEx.printStackTrace(System.err);
866
							}
867
						}
868
					}// end while
869

    
870
					moreReferrals = false;
871

    
872
				} catch (ReferralException re) {
873

    
874
					logMetacat
875
							.info("AuthLdap.getGroups -  caught referral exception: "
876
									+ re.getReferralInfo());
877
					this.currentReferralInfo = (String) re.getReferralInfo();
878

    
879
					// set moreReferrals to true and set the referral context
880
					moreReferrals = true;
881
					ctx = (DirContext) re.getReferralContext();
882

    
883
				}// end inner try
884
			}// end for
885

    
886
			// close the context now that all initial and referral
887
			// searches are processed
888
			ctx.close();
889

    
890
		} catch (NamingException e) {
891

    
892
			// naming exceptions get logged, groups are returned
893
			logMetacat.info("AuthLdap.getGroups - caught naming exception: ");
894
			e.printStackTrace(System.err);
895

    
896
		} finally {
897
			// once all referrals are followed, report and return the groups
898
			// found
899
			logMetacat.warn("AuthLdap.getGroups - The user is in the following groups: " + gvec.toString());
900
			// build and return the groups array
901
			String groups[][] = new String[gvec.size()][2];
902
			for (int i = 0; i < gvec.size(); i++) {
903
				groups[i][0] = (String) gvec.elementAt(i);
904
				groups[i][1] = (String) desc.elementAt(i);
905
			}
906
			return groups;
907
		}// end outer try
908
	}
909

    
910
	/**
911
	 * Get attributes describing a user or group
912
	 * 
913
	 * @param foruser
914
	 *            the user for which the attribute list is requested
915
	 * @returns HashMap a map of attribute name to a Vector of values
916
	 */
917
	public HashMap<String, Vector<String>> getAttributes(String foruser)
918
			throws ConnectException {
919
		return getAttributes(null, null, foruser);
920
	}
921

    
922
	/**
923
	 * Get attributes describing a user or group
924
	 * 
925
	 * @param user
926
	 *            the user for authenticating against the service
927
	 * @param password
928
	 *            the password for authenticating against the service
929
	 * @param foruser
930
	 *            the user whose attributes should be returned
931
	 * @returns HashMap a map of attribute name to a Vector of values
932
	 */
933
	public HashMap<String, Vector<String>> getAttributes(String user, String password,
934
			String foruser) throws ConnectException {
935
		HashMap<String, Vector<String>> attributes = new HashMap<String, Vector<String>>();
936
		String ldapUrl = this.ldapUrl;
937
		String ldapBase = this.ldapBase;
938
		String userident = foruser;
939

    
940
		// Identify service provider to use
941
		Hashtable env = new Hashtable(11);
942
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
943
		env.put(Context.REFERRAL, referral);
944
		env.put(Context.PROVIDER_URL, ldapUrl);
945

    
946
		try {
947

    
948
			// Create the initial directory context
949
			DirContext ctx = new InitialDirContext(env);
950

    
951
			// Ask for all attributes of the user
952
			// Attributes attrs = ctx.getAttributes(userident);
953
			Attributes attrs = ctx.getAttributes(foruser);
954

    
955
			// Print all of the attributes
956
			NamingEnumeration en = attrs.getAll();
957
			while (en.hasMore()) {
958
				Attribute att = (Attribute) en.next();
959
				Vector<String> values = new Vector();
960
				String attName = att.getID();
961
				NamingEnumeration attvalues = att.getAll();
962
				while (attvalues.hasMore()) {
963
					String value = (String) attvalues.next();
964
					values.add(value);
965
				}
966
				attributes.put(attName, values);
967
			}
968

    
969
			// Close the context when we're done
970
			ctx.close();
971
		} catch (NamingException e) {
972
			logMetacat.error("AuthLdap.getAttributes - Problem getting attributes:"
973
					+ e);
974
			throw new ConnectException(
975
					"Problem getting attributes in AuthLdap.getAttributes:" + e);
976
		}
977

    
978
		return attributes;
979
	}
980

    
981
	/**
982
	 * Get list of all subtrees holding Metacat's groups and users starting from
983
	 * the Metacat LDAP root, i.e.
984
	 * ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
985
	 */
986
	private Hashtable getSubtrees(String user, String password, String ldapUrl,
987
			String ldapBase) throws ConnectException {
988
		logMetacat.debug("AuthLdap.getSubtrees - getting subtrees for user: " + user + 
989
				", ldapUrl: " + ldapUrl + ", ldapBase: " + ldapBase);
990
		Hashtable trees = new Hashtable();
991

    
992
		// Identify service provider to use
993
		Hashtable env = new Hashtable(11);
994
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
995
		// env.put(Context.REFERRAL, referral);
996
		// Using 'ignore' here instead of 'follow' as 'ignore' seems
997
		// to do the job better. 'follow' was not bringing up the UCNRS
998
		// and PISCO tree whereas 'ignore' brings up the tree.
999

    
1000
		env.put(Context.REFERRAL, "ignore");
1001
		env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
1002

    
1003
		try {
1004

    
1005
			// Create the initial directory context
1006
			DirContext ctx = new InitialDirContext(env);
1007

    
1008
			// Specify the ids of the attributes to return
1009
			String[] attrIDs = { "o", "ref" };
1010
			SearchControls ctls = new SearchControls();
1011
			ctls.setReturningAttributes(attrIDs);
1012
			ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
1013

    
1014
			// Specify the attributes to match.
1015
			// Subtrees from the main server are found as objects with attribute
1016
			// objectclass=organization or objectclass=referral to the subtree
1017
			// resided on other server.
1018
			String filter = "(|(objectclass=organization)(objectclass=referral))";
1019

    
1020
			// Search for objects in the current context
1021
			NamingEnumeration namingEnum = ctx.search("", filter, ctls);
1022

    
1023
			// Print the subtrees' <ldapURL, baseDN>
1024
			while (namingEnum.hasMore()) {
1025

    
1026
				SearchResult sr = (SearchResult) namingEnum.next();
1027
				logMetacat.debug("AuthLdap.getSubtrees - search result: " + sr.toString());
1028

    
1029
				Attributes attrs = sr.getAttributes();
1030
				NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref"
1031
															// attrs
1032

    
1033
				if (enum1.hasMore()) {
1034
					Attribute attr = (Attribute) enum1.next();
1035
					String attrValue = (String) attr.get();
1036
					String attrName = (String) attr.getID();
1037

    
1038
					if (enum1.hasMore()) {
1039
						attr = (Attribute) enum1.next();
1040
						String refValue = (String) attr.get();
1041
						String refName = (String) attr.getID();
1042
						if (ldapBase.startsWith(refName + "=" + refValue)) {
1043
							trees.put(ldapBase, attrValue.substring(0, attrValue
1044
									.lastIndexOf("/") + 1));
1045
						} else {
1046
							// this is a referral - so organization name is
1047
							// appended in front of the ldapbase.... later it is 
1048
							// stripped out in getPrincipals
1049
							trees.put("[" + refName + "=" + refValue + "]" + 
1050
									attrValue.substring(attrValue.lastIndexOf("/") + 1,
1051
											attrValue.length()), attrValue.substring(0,
1052
													attrValue.lastIndexOf("/") + 1));
1053

    
1054
							// trees.put(refName + "=" + refValue + "," +
1055
							// ldapBase, attrValue.substring(0, attrValue.lastIndexOf("/")
1056
							// + 1));
1057
						}
1058

    
1059
					} else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
1060
						trees.put(ldapBase, ldapUrl);
1061
					} else {
1062
						if (sr.isRelative()) {
1063
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1064
									ldapUrl);
1065
						} else {
1066
							String referenceURL = sr.getName();
1067
							referenceURL = referenceURL.substring(0, referenceURL
1068
									.lastIndexOf("/") + 1);
1069
							trees.put(attrName + "=" + attrValue + "," + ldapBase,
1070
									referenceURL);
1071
						}
1072

    
1073
					}
1074
				}
1075
			}
1076

    
1077
			// Close the context when we're done
1078
			ctx.close();
1079

    
1080
		} catch (NamingException e) {
1081
			logMetacat.error("AuthLdap.getSubtrees - Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1082
			throw new ConnectException(
1083
					"Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1084
		}
1085

    
1086
		return trees;
1087
	}
1088

    
1089
	/**
1090
	 * Get all groups and users from authentication scheme. The output is
1091
	 * formatted in XML.
1092
	 * 
1093
	 * @param user
1094
	 *            the user which requests the information
1095
	 * @param password
1096
	 *            the user's password
1097
	 */
1098
	public String getPrincipals(String user, String password) throws ConnectException {
1099
		StringBuffer out = new StringBuffer();
1100

    
1101
		out.append("<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n");
1102
		out.append("<principals>\n");
1103

    
1104
		/*
1105
		 * get all subtrees first in the current dir context and then the
1106
		 * Metacat users under them
1107
		 */
1108
		Hashtable subtrees = getSubtrees(user, password, this.ldapUrl, this.ldapBase);
1109

    
1110
		Enumeration keyEnum = subtrees.keys();
1111
		while (keyEnum.hasMoreElements()) {
1112
			this.ldapBase = (String) keyEnum.nextElement();
1113
			this.ldapUrl = (String) subtrees.get(ldapBase);
1114
			logMetacat.info("AuthLdap.getPrincipals - ldapBase: " + ldapBase + 
1115
					", ldapUrl: " + ldapUrl);
1116
			/*
1117
			 * code to get the organization name from ldapBase
1118
			 */
1119
			String orgName = this.ldapBase;
1120
			if (orgName.startsWith("[")) {
1121
				// if orgName starts with [ then it is a referral URL...
1122
				// (see code in getSubtress) hence orgName can be retrieved by 
1123
				// getting the string between 'o=' and ']' also the string between 
1124
				// [ and ] needs to be striped out from this.ldapBase
1125
				this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1126
				if (orgName != null && orgName.indexOf("o=") > -1) {
1127
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1128
					orgName = orgName.substring(0, orgName.indexOf("]"));
1129
				}
1130
			} else {
1131
				// else it is not referral
1132
				// hence orgName can be retrieved by getting the string between
1133
				// 'o=' and ','
1134
				if (orgName != null && orgName.indexOf("o=") > -1) {
1135
					orgName = orgName.substring(orgName.indexOf("o=") + 2);
1136
					if (orgName.indexOf(",") > -1) {
1137
						orgName = orgName.substring(0, orgName.indexOf(","));
1138
					}
1139
				}
1140
			}
1141
			logMetacat.info("AuthLdap.getPrincipals - org name is  " + orgName);
1142
			out.append("  <authSystem URI=\"" + this.ldapUrl + this.ldapBase
1143
					+ "\" organization=\"" + orgName + "\">\n");
1144

    
1145
			// get all groups for directory context
1146
			String[][] groups = getGroups(user, password);
1147
			logMetacat.debug("AuthLdap.getPrincipals - after getting groups " + groups);
1148
			String[][] users = getUsers(user, password);
1149
			logMetacat.debug("AuthLdap.getPrincipals - after getting users " + users);
1150
			int userIndex = 0;
1151

    
1152
			// for the groups and users that belong to them
1153
			if (groups != null && users != null && groups.length > 0) {
1154
				for (int i = 0; i < groups.length; i++) {
1155
					out.append("    <group>\n");
1156
					out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1157
					out.append("      <description>" + groups[i][1] + "</description>\n");
1158
					String[] usersForGroup = getUsers(user, password, groups[i][0]);
1159
					for (int j = 0; j < usersForGroup.length; j++) {
1160
						userIndex = searchUser(usersForGroup[j], users);
1161
						out.append("      <user>\n");
1162

    
1163
						if (userIndex < 0) {
1164
							out.append("        <username>" + usersForGroup[j]
1165
									+ "</username>\n");
1166
						} else {
1167
							out.append("        <username>" + users[userIndex][0]
1168
									+ "</username>\n");
1169
							out.append("        <name>" + users[userIndex][1]
1170
									+ "</name>\n");
1171
							out.append("        <organization>" + users[userIndex][2]
1172
									+ "</organization>\n");
1173
							if (users[userIndex][3].compareTo("null") != 0) {
1174
								out.append("      <organizationUnitName>"
1175
										+ users[userIndex][3]
1176
										+ "</organizationUnitName>\n");
1177
							}
1178
							out.append("        <email>" + users[userIndex][4]
1179
									+ "</email>\n");
1180
						}
1181

    
1182
						out.append("      </user>\n");
1183
					}
1184
					out.append("    </group>\n");
1185
				}
1186
			}
1187

    
1188
			if (users != null) {
1189
				// for the users not belonging to any grou8p
1190
				for (int j = 0; j < users.length; j++) {
1191
					out.append("    <user>\n");
1192
					out.append("      <username>" + users[j][0] + "</username>\n");
1193
					out.append("      <name>" + users[j][1] + "</name>\n");
1194
					out
1195
							.append("      <organization>" + users[j][2]
1196
									+ "</organization>\n");
1197
					if (users[j][3].compareTo("null") != 0) {
1198
						out.append("      <organizationUnitName>" + users[j][3]
1199
								+ "</organizationUnitName>\n");
1200
					}
1201
					out.append("      <email>" + users[j][4] + "</email>\n");
1202
					out.append("    </user>\n");
1203
				}
1204
			}
1205

    
1206
			out.append("  </authSystem>\n");
1207
		}
1208
		out.append("</principals>");
1209
		return out.toString();
1210
	}
1211

    
1212
	/**
1213
	 * Method for getting index of user DN in User info array
1214
	 */
1215
	int searchUser(String user, String userGroup[][]) {
1216
		for (int j = 0; j < userGroup.length; j++) {
1217
			if (user.compareTo(userGroup[j][0]) == 0) {
1218
				return j;
1219
			}
1220
		}
1221
		return -1;
1222
	}
1223

    
1224
	public void testCredentials(String dn, String password, String rootServer,
1225
			String rootBase) throws NamingException {
1226

    
1227
		String server = "";
1228
		String userDN = "";
1229
		logMetacat.debug("dn is: " + dn);
1230

    
1231
		int position = dn.lastIndexOf("/");
1232
		logMetacat.debug("AuthLdap.testCredentials - position is: " + position);
1233
		if (position == -1) {
1234
			server = rootServer;
1235
			if (dn.indexOf(userDN) < 0) {
1236
				userDN = dn + "," + rootBase;
1237
			} else {
1238
				userDN = dn;
1239
			}
1240
			logMetacat.debug("AuthLdap.testCredentials - userDN is: " + userDN);
1241

    
1242
		} else {
1243
			server = dn.substring(0, position + 1);
1244
			userDN = dn.substring(position + 1);
1245
			logMetacat.debug("AuthLdap.testCredentials - server is: " + server);
1246
			logMetacat.debug("AuthLdap.testCredentials - userDN is: " + userDN);
1247
		}
1248

    
1249
		logMetacat.debug("AuthLdap.testCredentials - Trying to authenticate: " + userDN + " using server: " + server);
1250

    
1251
		// /* try {
1252
		LdapContext ctx = null;
1253

    
1254
		env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1255
		env.put(Context.REFERRAL, "follow");
1256
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
1257
		env.put(Context.SECURITY_PRINCIPAL, userDN);
1258
		env.put(Context.SECURITY_CREDENTIALS, password);
1259
		env.put(Context.PROVIDER_URL, rootServer);
1260

    
1261
		ctx = new InitialLdapContext(env, null);
1262

    
1263
	}
1264

    
1265
	/**
1266
	 * Test method for the class
1267
	 */
1268
	public static void main(String[] args) {
1269

    
1270
		// Provide a user, such as: "Matt Jones", or "jones"
1271
		String user = args[0];
1272
		String password = args[1];
1273
		String org = args[2];
1274

    
1275
		logMetacat.warn("AuthLdap.main - Creating session...");
1276
		AuthLdap authservice = null;
1277
		try {
1278
			authservice = new AuthLdap();
1279
		} catch (Exception e) {
1280
			logMetacat.error("AuthLdap.main - Could not instantiate AuthLdap: " + e.getMessage());
1281
			return;
1282
		}
1283
		logMetacat.warn("AuthLdap.main - Session exists...");
1284

    
1285
		boolean isValid = false;
1286
		try {
1287
			logMetacat.warn("AuthLdap.main - Authenticating...");
1288
			isValid = authservice.authenticate(user, password);
1289
			if (isValid) {
1290
				logMetacat.warn("AuthLdap.main - Authentication successful for: " + user);
1291
			} else {
1292
				logMetacat.warn("AuthLdap.main - Authentication failed for: " + user);
1293
			}
1294

    
1295
			// Get attributes for the user
1296
			if (isValid) {
1297
				logMetacat.info("AuthLdap.main - Getting attributes for user....");
1298
				HashMap userInfo = authservice.getAttributes(user, password, user);
1299
				// Print all of the attributes
1300
				Iterator attList = (Iterator) (((Set) userInfo.keySet()).iterator());
1301
				while (attList.hasNext()) {
1302
					String att = (String) attList.next();
1303
					Vector values = (Vector) userInfo.get(att);
1304
					Iterator attvalues = values.iterator();
1305
					while (attvalues.hasNext()) {
1306
						String value = (String) attvalues.next();
1307
						logMetacat.warn("AuthLdap.main - " + att + ": " + value);
1308
					}
1309
				}
1310
			}
1311

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

    
1322
			// get the groups for the user
1323
			String savedGroup = null;
1324
			if (isValid) {
1325
				logMetacat.warn("AuthLdap.main - Getting groups for user....");
1326
				String[][] groups = authservice.getGroups(user, password, user);
1327
				logMetacat.info("AuthLdap.main - Groups found: " + groups.length);
1328
				for (int i = 0; i < groups.length; i++) {
1329
					logMetacat.info("AuthLdap.main - Group " + i + ": " + groups[i][0]);
1330
					savedGroup = groups[i][0];
1331
				}
1332
			}
1333

    
1334
			// get the users for a group
1335
			if (isValid) {
1336
				logMetacat.warn("AuthLdap.main - Getting users for group....");
1337
				logMetacat.info("AuthLdap.main - Group: " + savedGroup);
1338
				String[] users = authservice.getUsers(user, password, savedGroup);
1339
				logMetacat.info("AuthLdap.main - Users found: " + users.length);
1340
				for (int i = 0; i < users.length; i++) {
1341
					logMetacat.warn("AuthLdap.main - User " + i + ": " + users[i]);
1342
				}
1343
			}
1344

    
1345
			// get all users
1346
			if (isValid) {
1347
				logMetacat.warn("AuthLdap.main - Getting all users ....");
1348
				String[][] users = authservice.getUsers(user, password);
1349
				logMetacat.info("AuthLdap.main - Users found: " + users.length);
1350

    
1351
			}
1352

    
1353
			// get the whole list groups and users in XML format
1354
			if (isValid) {
1355
				logMetacat.warn("AuthLdap.main - Trying principals....");
1356
				authservice = new AuthLdap();
1357
				String out = authservice.getPrincipals(user, password);
1358
				java.io.File f = new java.io.File("principals.xml");
1359
				java.io.FileWriter fw = new java.io.FileWriter(f);
1360
				java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1361
				buff.write(out);
1362
				buff.flush();
1363
				buff.close();
1364
				fw.close();
1365
				logMetacat.warn("AuthLdap.main - Finished getting principals.");
1366
			}
1367

    
1368
		} catch (ConnectException ce) {
1369
			logMetacat.error("AuthLdap.main - " + ce.getMessage());
1370
		} catch (java.io.IOException ioe) {
1371
			logMetacat.error("AuthLdap.main - I/O Error writing to file principals.txt: "
1372
					+ ioe.getMessage());
1373
		} catch (InstantiationException ie) {
1374
			logMetacat.error("AuthLdap.main - Instantiation error writing to file principals.txt: "
1375
					+ ie.getMessage());
1376
		}
1377
	}
1378

    
1379
	/**
1380
	 * This method will be called by start a thread. It can handle if a referral
1381
	 * exception happend.
1382
	 */
1383
}
(6-6/60)