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-24 13:52:51 -0700 (Thu, 24 Jul 2008) $'
12
 * '$Revision: 4159 $'
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
			// TODO MCD this may need to remain always at NCEAS value
100
			this.ldapBase = PropertyService.getProperty("organization.base.NCEAS");
101
			this.referral = PropertyService.getProperty("ldap.referral");
102
			this.ldapConnectTimeLimit = PropertyService
103
					.getProperty("ldap.connectTimeLimit");
104
			this.ldapSearchTimeLimit = Integer.parseInt(PropertyService
105
					.getProperty("ldap.searchTimeLimit"));
106
			this.ldapSearchCountLimit = Integer.parseInt(PropertyService
107
					.getProperty("ldap.searchCountLimit"));
108
		} catch (PropertyNotFoundException pnfe) {
109
			throw new InstantiationException(
110
					"Could not instantiate AuthLdap.  Property not found: "
111
							+ pnfe.getMessage());
112
		} catch (NumberFormatException nfe) {
113
			throw new InstantiationException(
114
					"Could not instantiate AuthLdap.  Bad number format when converting properties: "
115
							+ nfe.getMessage());
116
		}
117

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

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

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

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

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

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

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

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

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

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

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

    
340
       return authenticated;
341
  }
342

    
343

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

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

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

    
425
    try {
426

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

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

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

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

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

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

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

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

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

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

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

    
511
    return users;
512
  }
513

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

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

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

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

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

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

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

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

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

    
607
    return userinfo;
608
  }
609

    
610
  /**
611
   * Get the users for a particular group from the authentication service
612
   *
613
   * @param user the user for authenticating against the service
614
   * @param password the password for authenticating against the service
615
   * @param group 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) throws 
619
    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,
625
            "com.sun.jndi.ldap.LdapCtxFactory");
626
    env.put(Context.REFERRAL, referral);
627
    env.put(Context.PROVIDER_URL, ldapUrl);
628

    
629
    try {
630

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

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

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

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

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

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

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

    
674
    return users;
675
  }
676

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

    
689
  /**
690
   * Get the groups for a particular user from the authentication service
691
   *
692
   * @param user the user for authenticating against the service
693
   * @param password the password for authenticating against the service
694
   * @param foruser 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, 
698
    String foruser) throws ConnectException {
699
    
700
    logMetacat.debug("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
        
720
    // Iterate through the referrals, handling NamingExceptions in the 
721
    // outer catch statement, ReferralExceptions in the inner catch 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 servers
737
      ctls.setTimeLimit(ldapSearchTimeLimit);
738
      // return at most 20000 entries
739
      ctls.setCountLimit(ldapSearchCountLimit);
740

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

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

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

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

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

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

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

    
930
    try {
931

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

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

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

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

    
963
    return attributes;
964
  }
965

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

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

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

    
987
    try {
988

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

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

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

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

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

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

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

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

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

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

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

    
1058
          }
1059
        }
1060
      }
1061

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

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

    
1073
    return trees;
1074
  }
1075

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

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

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

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

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

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

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

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

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

    
1212
  public void testCredentials(String dn, String password, 
1213
		    String rootServer, String rootBase ) throws NamingException {
1214
	  
1215
	  String server = "";
1216
	  String userDN = "";
1217
	  logMetacat.debug("dn is: " + dn);
1218

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

    
1230
       } else {
1231
		  server = dn.substring(0, position+1);
1232
		  userDN = dn.substring(position+1);
1233
		  logMetacat.debug("server is: " + server);
1234
		  logMetacat.debug("userDN is: " + userDN);
1235
	   }
1236
		          
1237
	   logMetacat.debug("Trying to authenticate: " + userDN);
1238
	   logMetacat.debug("          Using server: " + server);
1239

    
1240
///*	   try { 
1241
			LdapContext ctx = null;
1242
			   
1243
			env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1244
	        env.put(Context.REFERRAL, "follow");
1245
			env.put(Context.SECURITY_AUTHENTICATION, "simple");
1246
			env.put(Context.SECURITY_PRINCIPAL, userDN);
1247
			env.put(Context.SECURITY_CREDENTIALS, password);
1248
			env.put(Context.PROVIDER_URL, rootServer);
1249

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

    
1252

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

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

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

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

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

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

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

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

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

    
1346
			}
1347

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

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

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