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-07-06 21:25:34 -0700 (Sun, 06 Jul 2008) $'
12
 * '$Revision: 4080 $'
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.InvalidSearchFilterException;
38
import javax.naming.directory.Attribute;
39
import javax.naming.directory.Attributes;
40
import javax.naming.directory.DirContext;
41
import javax.naming.directory.InitialDirContext;
42
import javax.naming.directory.SearchResult;
43
import javax.naming.directory.SearchControls;
44
import javax.naming.ReferralException;
45
import javax.naming.ldap.InitialLdapContext;
46
import javax.naming.ldap.LdapContext;
47
import javax.naming.ldap.StartTlsRequest;
48
import javax.naming.ldap.StartTlsResponse;
49
import javax.net.ssl.SSLSession;
50

    
51
import org.apache.log4j.Logger;
52

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

    
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
67
 * allows Metacat to use the LDAP protocol for directory services.
68
 * The LDAP authentication service is used to determine if a user
69
 * is authenticated, and whether they are a member 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 Context referralContext;
80
  private String currentReferralInfo;
81
  Hashtable env = new Hashtable(11);
82
  private Context rContext;
83
  private String userName;
84
  private String userPassword;
85
  ReferralException refExc;
86

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

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

    
121
  /**
122
	 * Determine if a user/password are valid according to the authentication
123
	 * service.
124
	 * 
125
	 * @param user
126
	 *            the name of the principal to authenticate
127
	 * @param password
128
	 *            the password to use for authentication
129
	 * @returns boolean true if authentication successful, false otherwise
130
	 */
131
  
132
  public boolean authenticate(String user, String password) throws 
133
    ConnectException {
134
    String ldapUrl = this.ldapUrl;
135
    String ldapsUrl = this.ldapsUrl;
136
    String ldapBase = this.ldapBase;
137
    boolean authenticated = false;
138
    String identifier = user;
139
    
140
    //get uid here.
141
    String uid=user.substring(0, user.indexOf(","));
142
    user = user.substring(user.indexOf(","), user.length());
143

    
144
    logMetacat.debug("identifier: " + identifier);
145
    logMetacat.debug("uid: " + uid);
146
    logMetacat.debug("user: " + user);
147
    
148
    try {
149
    	// Check the usename as passed in
150
        logMetacat.info("Calling ldapAuthenticate");
151
        logMetacat.info("with user as identifier: " + identifier);
152

    
153
        authenticated = ldapAuthenticate(identifier, password, 
154
        		(new Boolean(PropertyService.getProperty("ldap.onlySecureConnection"))).booleanValue());
155
        // if not found, try looking up a valid DN then auth again
156
        if (!authenticated) {
157
        	logMetacat.info("Not Authenticated");
158
        	logMetacat.info("Looking up DN for: " + identifier);
159
        	identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
160
        	if(identifier == null){
161
        		logMetacat.info("No DN found from getIdentifyingName");
162
        		return authenticated;
163
        	}
164
        	
165
           	logMetacat.info("DN found from getIdentifyingName: " + identifier);
166
        	String decoded = URLDecoder.decode(identifier);
167
        	logMetacat.info("DN decoded: " + decoded);
168
        	identifier = decoded;
169
        	String refUrl = "";
170
        	String refBase = "";
171
        	if (identifier.startsWith("ldap")) {
172
        		logMetacat.debug("identifier starts with \"ldap\"");
173

    
174
        		refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1);
175
        		int position = identifier.indexOf(",");
176
        		int position2 = identifier.indexOf(",", position + 1);
177
        		
178
        		refBase = identifier.substring(position2 + 1);
179
        		identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
180
        		
181
        		logMetacat.info("Calling ldapAuthenticate:");
182
        		logMetacat.info("with user as identifier: " + identifier);
183
        		logMetacat.info("and refUrl as: " + refUrl);
184
        		logMetacat.info("and refBase as: " + refBase);
185

    
186
        		authenticated = ldapAuthenticate(identifier, password, refUrl, refBase,
187
                		(new Boolean(PropertyService.getProperty("ldap.onlySecureReferalsConnection")))
188
                			.booleanValue());
189
        	} else {
190
        		logMetacat.info("identifier doesnt start with ldap");
191
        		identifier = identifier + "," + ldapBase;
192
        		
193
        		logMetacat.info("Calling ldapAuthenticate");
194
        		logMetacat.info("with user as identifier: " + identifier);
195
        		
196
        		authenticated = ldapAuthenticate(identifier, password,
197
            		(new Boolean(PropertyService.getProperty("ldap.onlySecureConnection"))).booleanValue());
198
        	}
199
        }
200
    } catch (NullPointerException e) {
201
    	logMetacat.error("NullPointerException while authenticating in " +
202
                        "AuthLdap.authenticate: " + e);
203
    	e.printStackTrace();
204

    
205
    	throw new ConnectException(
206
          "NullPointerException while authenticating in " +
207
          "AuthLdap.authenticate: " + e);
208
    } catch (NamingException e) {
209
    	logMetacat.error("Naming exception while authenticating in " +
210
                        "AuthLdap.authenticate: " + e);
211
    	e.printStackTrace();
212
    } catch (Exception e) {
213
    	logMetacat.error(e.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 the distinguished name to check against LDAP
224
   * @param password the password for authentication
225
   */
226
  private boolean ldapAuthenticate(String identifier, String password, boolean 
227
    secureConnectionOnly) throws ConnectException, NamingException, 
228
    NullPointerException {
229
    return ldapAuthenticate(identifier, password,
230
                            this.ldapsUrl, this.ldapBase, secureConnectionOnly);
231
  }
232

    
233
  /**
234
   * Connect to the LDAP directory and do the authentication using the
235
   * username and password as passed into the routine.
236
   *
237
   * @param identifier the distinguished name to check against LDAP
238
   * @param password the password for authentication
239
   */
240
  
241
  private boolean ldapAuthenticate(String dn, String password, 
242
    String rootServer, String rootBase, boolean secureConnectionOnly){
243
	  
244
	  boolean authenticated = false;
245
		
246
	  String server = "";
247
	  String userDN = "";
248
	  logMetacat.info("dn is: " + dn);
249

    
250
	  int position = dn.lastIndexOf("/");
251
      logMetacat.debug("position is: " + position);
252
	  if (position == -1) {
253
		  server = rootServer;
254
		  if(dn.indexOf(userDN) < 0){
255
			  userDN = dn + "," + rootBase;
256
		  } else {
257
			  userDN = dn;
258
		  }
259
		  logMetacat.info("userDN is: " + userDN);
260

    
261
       } else {
262
		  server = dn.substring(0, position+1);
263
		  userDN = dn.substring(position+1);
264
		  logMetacat.info("server is: " + server);
265
		  logMetacat.info("userDN is: " + userDN);
266
	   }
267
		          
268
	   logMetacat.warn("Trying to authenticate: " + userDN);
269
	   logMetacat.warn("          Using server: " + server);
270
		          
271
	   LdapContext ctx = null;
272
	   double startTime;
273
	   double stopTime;
274
	   try 
275
     {
276
		   Hashtable env = new Hashtable();
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
		   try 
281
       {
282
			   
283
			   startTime = System.currentTimeMillis();
284
			   ctx = new InitialLdapContext(env, null);
285
			   // Start up TLS here so that we don't pass our jewels in cleartext
286
		       StartTlsResponse tls =
287
		              (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
288
		       //tls.setHostnameVerifier(new SampleVerifier());
289
		       SSLSession sess = tls.negotiate();
290
		       ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
291
			   ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
292
			   ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
293
			   ctx.reconnect(null);
294
			   stopTime = System.currentTimeMillis();
295
			   logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
296
                       	(stopTime - startTime) / 1000 + " seconds.");
297
			   authenticated = true;
298
		   } 
299
       catch (Exception ioe) 
300
       {
301
			   logMetacat.info("Caught IOException in login while negotiating TLS: "
302
	                                 + ioe.getMessage());
303
			   
304
			   if(secureConnectionOnly)
305
         {
306
				   return authenticated;
307
			   
308
			   } 
309
         else 
310
         {
311
				   logMetacat.info("Trying to authenticate without TLS");
312
				   env.put(Context.SECURITY_AUTHENTICATION, "simple");
313
				   env.put(Context.SECURITY_PRINCIPAL, userDN);
314
				   env.put(Context.SECURITY_CREDENTIALS, password);
315
				   
316
				   startTime = System.currentTimeMillis();
317
				   ctx = new InitialLdapContext(env, null);				
318
				   stopTime = System.currentTimeMillis();
319
				   logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
320
	                       	(stopTime - startTime) / 1000 + " seconds.");
321
				   authenticated = true;
322
			   }
323
		   }
324
	   } 
325
     catch (AuthenticationException ae) 
326
     {
327
		   authenticated = false;
328
	   } 
329
     catch (javax.naming.InvalidNameException ine) 
330
     {
331
	        logMetacat.error("An invalid DN was provided!");
332
	   } 
333
     catch (NamingException e) 
334
     {
335
		   logMetacat.warn("Caught NamingException in login: " + e.getClass().getName());
336
		   logMetacat.info(e.toString() + "  " + e.getRootCause());
337
     }
338

    
339
       return authenticated;
340
  }
341

    
342

    
343
  /**
344
   * Get the identifying name for a given userid or name.  This is the name
345
   * that is used in conjunction withthe LDAP BaseDN to create a
346
   * distinguished name (dn) for the record
347
   *
348
   * @param user the user for which the identifying name is requested
349
   * @returns String the identifying name for the user,
350
   *          or null if not found
351
   */
352
  private String getIdentifyingName(String user, String ldapUrl, 
353
    String ldapBase) throws NamingException {
354
	  
355
      String identifier = null;
356
      Hashtable env = new Hashtable();
357
      env.put(Context.INITIAL_CONTEXT_FACTORY,
358
              "com.sun.jndi.ldap.LdapCtxFactory");
359
      env.put(Context.REFERRAL, "throw");
360
      env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
361
      try {
362
    	  int position = user.indexOf(",");
363
          String uid = user.substring(user.indexOf("=") + 1, position);
364
          logMetacat.info("uid is: " + uid);
365
          String org = user.substring(user.indexOf("=", position + 1) + 1,
366
                                        user.indexOf(",", position + 1));
367
          logMetacat.info("org is: " + org);
368
           
369
          DirContext sctx = new InitialDirContext(env);
370
          SearchControls ctls = new SearchControls();
371
          ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
372
          String filter = "(&(uid=" + uid + ")(o=" + org + "))";
373
          logMetacat.warn("Searching for DNs with following filter: " + filter);
374
          
375
          for (boolean moreReferrals = true; moreReferrals;) {
376
              try {
377
                  // Perform the search
378
                  NamingEnumeration answer = 
379
                      sctx.search("", filter, ctls);
380

    
381
                  // Return the answer
382
                  while (answer.hasMore()) {
383
                      SearchResult sr = (SearchResult)answer.next();
384
                      identifier = sr.getName();
385
                      return identifier;
386
                  }
387
                  // The search completes with no more referrals
388
                  moreReferrals = false;
389
              } catch (ReferralException e) {
390
            	  logMetacat.info("Got referral: " + e.getReferralInfo());
391
            	  // Point to the new context from the referral
392
                  if (moreReferrals) {
393
                      sctx = (DirContext) e.getReferralContext();
394
                  }
395
              }
396
          }
397
      } catch (NamingException e) {
398
    	     logMetacat.error("Naming exception while getting dn: " + e);
399
    	      throw new NamingException(
400
    	          "Naming exception in AuthLdap.getIdentifyingName: " + e);
401
    	      }
402
      return identifier;
403
  }
404
  
405
  /**
406
   * Get all users from the authentication service
407
   *
408
   * @param user the user for authenticating against the service
409
   * @param password the password for authenticating against the service
410
   * @returns string array of all of the user names
411
   */
412
  public String[][] getUsers(String user, String password) throws 
413
    ConnectException {
414
    String[][] users = null;
415

    
416
    // Identify service provider to use
417
    Hashtable env = new Hashtable(11);
418
    env.put(Context.INITIAL_CONTEXT_FACTORY,
419
            "com.sun.jndi.ldap.LdapCtxFactory");
420
    env.put(Context.REFERRAL, referral);
421
    env.put(Context.PROVIDER_URL, ldapUrl);
422
    env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
423

    
424
    try {
425

    
426
      // Create the initial directory context
427
      DirContext ctx = new InitialDirContext(env);
428

    
429
      // Specify the attributes to match.
430
      // Users are objects that have the attribute objectclass=InetOrgPerson.
431
      SearchControls ctls = new SearchControls();
432
      String[] attrIDs = {
433
          "dn", "cn", "o", "ou", "mail"};
434
      ctls.setReturningAttributes(attrIDs);
435
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
436
      ctls.setTimeLimit(ldapSearchTimeLimit);
437
      //ctls.setCountLimit(1000);
438
      String filter = "(objectClass=inetOrgPerson)";
439
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
440

    
441
      // Store the users in a vector
442
      Vector uvec = new Vector();
443
      Vector uname = new Vector();
444
      Vector uorg = new Vector();
445
      Vector uou = new Vector();
446
      Vector umail = new Vector();
447
      Attributes tempAttr = null;
448
      try {
449
        while (namingEnum.hasMore()) {
450
          SearchResult sr = (SearchResult) namingEnum.next();
451
          tempAttr = sr.getAttributes();
452

    
453
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
454
            uname.add( (tempAttr.get("cn") + "").substring(4));
455
          }
456
          else {
457
            uname.add(tempAttr.get("cn") + "");
458
          }
459

    
460
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
461
            uorg.add( (tempAttr.get("o") + "").substring(3));
462
          }
463
          else {
464
            uorg.add(tempAttr.get("o") + "");
465
          }
466

    
467
          if ( (tempAttr.get("ou") + "").startsWith("ou: ")) {
468
            uou.add( (tempAttr.get("ou") + "").substring(4));
469
          }
470
          else {
471
            uou.add(tempAttr.get("ou") + "");
472
          }
473

    
474
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
475
            umail.add( (tempAttr.get("mail") + "").substring(6));
476
          }
477
          else {
478
            umail.add(tempAttr.get("mail") + "");
479
          }
480

    
481
          uvec.add(sr.getName() + "," + ldapBase);
482
        }
483
      }
484
      catch (SizeLimitExceededException slee) {
485
        logMetacat.error("LDAP Server size limit exceeded. " +
486
                          "Returning incomplete record set.");
487
      }
488

    
489
      // initialize users[]; fill users[]
490
      users = new String[uvec.size()][5];
491
      for (int i = 0; i < uvec.size(); i++) {
492
        users[i][0] = (String) uvec.elementAt(i);
493
        users[i][1] = (String) uname.elementAt(i);
494
        users[i][2] = (String) uorg.elementAt(i);
495
        users[i][3] = (String) uorg.elementAt(i);
496
        users[i][4] = (String) umail.elementAt(i);
497
      }
498

    
499
      // Close the context when we're done
500
      ctx.close();
501

    
502
    }
503
    catch (NamingException e) {
504
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
505
      //e.printStackTrace(System.err);
506
     /* throw new ConnectException(
507
          "Problem getting users in AuthLdap.getUsers:" + e);*/
508
    }
509

    
510
    return users;
511
  }
512

    
513
  
514
  /**
515
   * Get all users from the authentication service
516
   *
517
   * @param user the user for authenticating against the service
518
   * @param password the password for authenticating against the service
519
   * @returns string array of all of the user names
520
   */
521
  public String[] getUserInfo(String user, String password) throws 
522
    ConnectException {
523
    String[] userinfo = new String[3];
524

    
525
    // Identify service provider to use
526
    Hashtable env = new Hashtable(11);
527
    env.put(Context.INITIAL_CONTEXT_FACTORY,
528
            "com.sun.jndi.ldap.LdapCtxFactory");
529
    env.put(Context.REFERRAL, referral);
530
    env.put(Context.PROVIDER_URL, ldapUrl);
531

    
532
    try {
533
      
534
      // Create the initial directory context
535
      DirContext ctx = new InitialDirContext(env);
536
      // Specify the attributes to match.
537
      // Users are objects that have the attribute objectclass=InetOrgPerson.
538
      SearchControls ctls = new SearchControls();
539
      String[] attrIDs = {
540
          "cn", "o", "mail"};
541
      ctls.setReturningAttributes(attrIDs);
542
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
543
      //ctls.setCountLimit(1000);
544
      // create the filter based on the uid
545
      
546
      String filter = null;
547
      
548
      if(user.indexOf("o=")>0){
549
    	  String tempStr = user.substring(user.indexOf("o="));
550
    	  filter = "(&(" + user.substring(0, user.indexOf(",")) 
551
			+ ")(" + tempStr.substring(0, tempStr.indexOf(",")) 
552
			+ "))";      
553
      } else{
554
    	  filter = "(&(" + user.substring(0, user.indexOf(",")) 
555
			+ "))";          		  
556
      }
557
   	  filter = "(&(" + user.substring(0, user.indexOf(",")) 
558
		+ "))";          		  
559

    
560
      NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
561
      
562
      Attributes tempAttr = null;
563
      try {
564
        while (namingEnum.hasMore()) {
565
          SearchResult sr = (SearchResult) namingEnum.next();
566
          tempAttr = sr.getAttributes();
567

    
568
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
569
        	  userinfo[0] = (tempAttr.get("cn") + "").substring(4);
570
          }
571
          else {
572
        	  userinfo[0] = (tempAttr.get("cn") + "");
573
          }
574

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

    
582
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
583
        	  userinfo[2] =  (tempAttr.get("mail") + "").substring(6);
584
          }
585
          else {
586
        	  userinfo[2] = (tempAttr.get("mail") + "");
587
          }
588
        }
589
      }
590
      catch (SizeLimitExceededException slee) {
591
        logMetacat.error("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
    }
599
    catch (NamingException e) {
600
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
601
      //e.printStackTrace(System.err);
602
      throw new ConnectException(
603
          "Problem getting users in AuthLdap.getUsers:" + e);
604
    }
605

    
606
    return userinfo;
607
  }
608

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

    
621
    // Identify service provider to use
622
    Hashtable env = new Hashtable(11);
623
    env.put(Context.INITIAL_CONTEXT_FACTORY,
624
            "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 = {
635
          "uniqueMember"};
636

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

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

    
656
      // initialize users[]; fill users[]
657
      users = new String[uvec.size()];
658
      for (int i = 0; i < uvec.size(); i++) {
659
        users[i] = (String) uvec.elementAt(i);
660
      }
661

    
662
      // Close the context when we're done
663
      ctx.close();
664

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

    
673
    return users;
674
  }
675

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

    
688
  /**
689
   * Get the groups for a particular user from the authentication service
690
   *
691
   * @param user the user for authenticating against the service
692
   * @param password the password for authenticating against the service
693
   * @param foruser the user whose group list should be returned
694
   * @returns string array of the group names
695
   */
696
  public String[][] getGroups(String user, String password, 
697
    String foruser) throws ConnectException {
698
    
699
    logMetacat.debug("getGroups() called.");
700
    
701
    // create vectors to store group and dscription values returned from the
702
    // ldap servers
703
    Vector gvec = new Vector();
704
    Vector desc = new Vector();
705
    Attributes tempAttr = null;
706
    Attributes rsrAttr = null;
707
    
708
    // DURING getGroups(), DO WE NOT BIND USING userName AND userPassword??
709
    // NEED TO FIX THIS ...
710
    userName = user;
711
    userPassword = password;
712
    // Identify service provider to use
713
    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
714
    env.put(Context.REFERRAL, "throw");
715
    env.put(Context.PROVIDER_URL, ldapUrl);
716
    env.put("com.sun.jndi.ldap.connect.timeout", ldapConnectTimeLimit);
717
    
718
        
719
    // Iterate through the referrals, handling NamingExceptions in the 
720
    // outer catch statement, ReferralExceptions in the inner catch statement
721
    try { // outer try
722
       
723
      // Create the initial directory context
724
      DirContext ctx = new InitialDirContext(env);
725
      
726
      // Specify the attributes to match.
727
      // Groups are objects with attribute objectclass=groupofuniquenames.
728
      // and have attribute uniquemember: uid=foruser,ldapbase.
729
      SearchControls ctls = new SearchControls();
730
      // Specify the ids of the attributes to return
731
      String[] attrIDs = {"cn", "o", "description"};
732
      ctls.setReturningAttributes(attrIDs);
733
      // set the ldap search scope
734
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
735
      // set a 10 second time limit on searches to limit non-responding servers
736
      ctls.setTimeLimit(ldapSearchTimeLimit);
737
      // return at most 20000 entries
738
      ctls.setCountLimit(ldapSearchCountLimit);
739

    
740
      // build the ldap search filter that represents the "group" concept
741
      String filter = null;
742
      String gfilter = "(objectClass=groupOfUniqueNames)";
743
      if (null == foruser) {
744
        filter = gfilter;
745
      } else {
746
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
747
      }
748
      logMetacat.info("group filter is: " + filter);
749
      
750
      // now, search and iterate through the referrals
751
      for (boolean moreReferrals = true; moreReferrals;) {  
752
        try { // inner try
753
      
754
          NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
755

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

    
762
            if ( (tempAttr.get("description") + "").startsWith("description: ")) {
763
              desc.add( (tempAttr.get("description") + "").substring(13));
764
            }
765
            else {
766
              desc.add(tempAttr.get("description") + "");
767
            }
768
            
769
            // check for an absolute URL value or an answer value relative 
770
            // to the target context  
771
            if ( !sr.getName().startsWith("ldap") &&
772
                  sr.isRelative()) {
773
              logMetacat.debug("Search result entry is relative ...");
774
              gvec.add(sr.getName() + "," + ldapBase);
775
              logMetacat.info("group " + sr.getName() + "," +ldapBase + 
776
              " added to the group vector"); 
777
            } else {
778
              logMetacat.debug("Search result entry is absolute ...");
779
              
780
              // search the top level directory for referral objects and match
781
              // that of the search result's absolute URL.  This will let us
782
              // rebuild the group name from the search result, referral point
783
              // in the top directory tree, and ldapBase.
784
              
785
              // configure a new directory search first
786
              Hashtable envHash = new Hashtable(11);
787
              // Identify service provider to use
788
              envHash.put(Context.INITIAL_CONTEXT_FACTORY, 
789
                "com.sun.jndi.ldap.LdapCtxFactory");
790
              envHash.put(Context.REFERRAL, "ignore");
791
              envHash.put(Context.PROVIDER_URL, ldapUrl);
792
              envHash.put("com.sun.jndi.ldap.connect.timeout", 
793
                ldapConnectTimeLimit);
794
              
795
              try {
796
                // Create the initial directory context
797
                DirContext DirCtx = new InitialDirContext(envHash);
798

    
799
                SearchControls searchCtls = new SearchControls();
800
                // Specify the ids of the attributes to return
801
                String[] attrNames = {"o"};
802
                searchCtls.setReturningAttributes(attrNames);
803
                // set the ldap search scope - only look for top level referrals
804
                searchCtls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
805
                // set a time limit on searches to limit non-responding servers
806
                searchCtls.setTimeLimit(ldapSearchTimeLimit);
807
                // return the configured number of entries
808
                searchCtls.setCountLimit(ldapSearchCountLimit);
809
                
810
                // Specify the attributes to match.
811
                // build the ldap search filter to match referral entries that 
812
                // match the search result
813
                String rFilter = "(&(objectClass=referral)(ref=" + 
814
                currentReferralInfo.substring(0, 
815
                currentReferralInfo.indexOf("?")) + "))";
816
                logMetacat.debug("rFilter is: " + rFilter);
817
                
818
                NamingEnumeration rNamingEnum = 
819
                  DirCtx.search(ldapBase, rFilter, searchCtls);
820
                  
821
                while (rNamingEnum.hasMore()) {
822
                  SearchResult rsr = (SearchResult) rNamingEnum.next();
823
                  rsrAttr = rsr.getAttributes();
824
                  logMetacat.debug("referral search result is: " +
825
                    rsr.toString());
826
                    
827
                  // add the returned groups to the group vector.  Test the 
828
                  // syntax of the returned attributes - sometimes they are 
829
                  // preceded with the attribute id and a colon
830
                  if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
831
                    gvec.add( "cn=" + (tempAttr.get("cn") + "").substring(4) + 
832
                    "," + "o=" + (rsrAttr.get("o") + "").substring(3 ) + "," + 
833
                    ldapBase);
834
                    logMetacat.info("group " + 
835
                    (tempAttr.get("cn") + "").substring(4) + "," + 
836
                    "o=" + (rsrAttr.get("o") + "").substring(3) + "," + 
837
                    ldapBase + " added to the group vector");
838
                  } else {
839
                    gvec.add( "cn=" + tempAttr.get("cn") + "," + 
840
                    "o=" + rsrAttr.get("o") +
841
                    "," + ldapBase);
842
                    logMetacat.info("group " + 
843
                    "cn=" + tempAttr.get("cn") + "," + 
844
                    "o=" + rsrAttr.get("o") + "," + 
845
                    ldapBase + " added to the group vector");
846
                  }  
847
                }
848
                
849
              } catch (NamingException nameEx){
850
                logMetacat.debug("Caught naming exception: ");
851
                nameEx.printStackTrace(System.err);
852
              }
853
            }
854
          }// end while
855
          
856
          moreReferrals = false;
857
          
858
        } catch (ReferralException re) {
859
          
860
          logMetacat.info(
861
            "In AuthLdap.getGroups(), caught referral exception: " +
862
            re.getReferralInfo()
863
          );
864
          this.currentReferralInfo = (String) re.getReferralInfo();
865
          
866
          // set moreReferrals to true and set the referral context
867
          moreReferrals = true;
868
          ctx = (DirContext) re.getReferralContext();
869
           
870
        }// end inner try
871
      }// end for
872
      
873
      // close the context now that all initial and referral 
874
      // searches are processed
875
      ctx.close();
876
      
877
    } catch (NamingException e) {
878
      
879
      // naming exceptions get logged, groups are returned
880
      logMetacat.info("In AuthLdap.getGroups(), caught naming exception: ");
881
      e.printStackTrace(System.err);
882
      
883
    } finally {
884
      // once all referrals are followed, report and return the groups found
885
      logMetacat.warn("The user is in the following groups: " +
886
                               gvec.toString());
887
      //build and return the groups array
888
      String groups[][] = new String[gvec.size()][2];
889
      for (int i = 0; i < gvec.size(); i++) {
890
        groups[i][0] = (String) gvec.elementAt(i);
891
        groups[i][1] = (String) desc.elementAt(i);
892
      }
893
      return groups;
894
    }// end outer try
895
  }
896

    
897
  /**
898
   * Get attributes describing a user or group
899
   *
900
   * @param foruser the user for which the attribute list is requested
901
   * @returns HashMap a map of attribute name to a Vector of values
902
   */
903
  public HashMap getAttributes(String foruser) throws ConnectException {
904
    return getAttributes(null, null, foruser);
905
  }
906

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

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

    
929
    try {
930

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

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

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

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

    
962
    return attributes;
963
  }
964

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

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

    
983
    env.put(Context.REFERRAL, "ignore");
984
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
985

    
986
    try {
987

    
988
      // Create the initial directory context
989
      DirContext ctx = new InitialDirContext(env);
990

    
991
      // Specify the ids of the attributes to return
992
      String[] attrIDs = {
993
          "o", "ref"};
994
      SearchControls ctls = new SearchControls();
995
      ctls.setReturningAttributes(attrIDs);
996
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
997

    
998
      // Specify the attributes to match.
999
      // Subtrees from the main server are found as objects with attribute
1000
      // objectclass=organization or objectclass=referral to the subtree
1001
      // resided on other server.
1002
      String filter = "(|(objectclass=organization)(objectclass=referral))";
1003

    
1004
      // Search for objects in the current context
1005
      NamingEnumeration namingEnum = ctx.search("", filter, ctls);
1006

    
1007
      // Print the subtrees' <ldapURL, baseDN>
1008
      while (namingEnum.hasMore()) {
1009

    
1010
        SearchResult sr = (SearchResult) namingEnum.next();
1011

    
1012
        Attributes attrs = sr.getAttributes();
1013
        NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref" attrs
1014

    
1015
        if (enum1.hasMore()) {
1016
          Attribute attr = (Attribute) enum1.next();
1017
          String attrValue = (String) attr.get();
1018
          String attrName = (String) attr.getID();
1019

    
1020
          if (enum1.hasMore()) {
1021
            attr = (Attribute) enum1.next();
1022
            String refValue = (String) attr.get();
1023
            String refName = (String) attr.getID();
1024
            if (ldapBase.startsWith(refName + "=" + refValue)) {
1025
              trees.put(ldapBase,
1026
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
1027
            }
1028
            else {
1029
              // this is a referral - so organization name is appended in
1030
              // front of the ldapbase.... later it is stripped out
1031
              // in getPrincipals
1032
              trees.put("[" + refName + "=" + refValue + "]" +
1033
                        attrValue.substring(attrValue.lastIndexOf("/") + 1,
1034
                                            attrValue.length()),
1035
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
1036

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

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

    
1057
          }
1058
        }
1059
      }
1060

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

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

    
1072
    return trees;
1073
  }
1074

    
1075
  /**
1076
   * Get all groups and users from authentication scheme.
1077
   * The output is formatted in XML.
1078
   * @param user the user which requests the information
1079
   * @param password the user's password
1080
   */
1081
  public String getPrincipals(String user, String password) throws 
1082
    ConnectException {
1083
    StringBuffer out = new StringBuffer();
1084
   
1085
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
1086
    out.append("<principals>\n");
1087

    
1088
    /*
1089
     * get all subtrees first in the current dir context
1090
     * and then the Metacat users under them
1091
     */
1092
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
1093
                                     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
      }
1118
      else {
1119
        // else it is not referral
1120
        // hence orgName can be retrieved  by getting the string between
1121
        // 'o=' and ','
1122
        if (orgName != null && orgName.indexOf("o=") > -1) {
1123
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1124
          if (orgName.indexOf(",") > -1) {
1125
            orgName = orgName.substring(0, orgName.indexOf(","));
1126
          }
1127
        }
1128
      }
1129
      logMetacat.info("org name is  "+orgName);
1130
      out.append("  <authSystem URI=\"" +
1131
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
1132
                 "\">\n");
1133

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

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

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

    
1169
            out.append("      </user>\n");
1170
          }
1171
          out.append("    </group>\n");
1172
        }
1173
      }
1174
     
1175
      if (users != null)
1176
      {
1177
	      // for the users not belonging to any grou8p
1178
	      for (int j = 0; j < users.length; j++) {
1179
	          out.append("    <user>\n");
1180
	          out.append("      <username>" + users[j][0] + "</username>\n");
1181
	          out.append("      <name>" + users[j][1] + "</name>\n");
1182
	          out.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, 
1212
		    String rootServer, 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
   
1255
    /**
1256
	 * Test method for the class
1257
	 */
1258
	public static void main(String[] args) {
1259

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

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

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

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

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

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

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

    
1339
			// get all users
1340
			if (isValid) {
1341
				logMetacat.warn("\nGetting all users ....");
1342
				String[][] users = authservice.getUsers(user, password);
1343
				logMetacat.info("Users found: " + users.length);
1344

    
1345
			}
1346

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

    
1362
		} catch (ConnectException ce) {
1363
			logMetacat.error(ce.getMessage());
1364
		} catch (java.io.IOException ioe) {
1365
			logMetacat.error("I/O Error writing to file principals.txt: "
1366
					+ ioe.getMessage());
1367
		} catch (InstantiationException ie) {
1368
			logMetacat.error("Instantiation error writing to file principals.txt: "
1369
							+ ie.getMessage());
1370
		}
1371
	}
1372

    
1373
  /**
1374
   * This method will be called by start a thread.
1375
   * It can handle if a referral exception happend.
1376
   */
1377
}
(10-10/67)