Project

General

Profile

1 503 bojilova
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An implementation of the AuthInterface interface that
4
 *             allows Metacat to use the LDAP protocol for
5
 *             directory services
6
 *  Copyright: 2000 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    Authors: Matt Jones
9
 *    Release: @release@
10
 *
11
 *   '$Author$'
12
 *     '$Date$'
13
 * '$Revision$'
14 669 jones
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28 503 bojilova
 */
29
30
package edu.ucsb.nceas.metacat;
31
32
import java.net.ConnectException;
33
import javax.naming.AuthenticationException;
34
import javax.naming.Context;
35 787 bojilova
import javax.naming.NamingEnumeration;
36
import javax.naming.NamingException;
37 873 jones
import javax.naming.SizeLimitExceededException;
38 802 bojilova
import javax.naming.directory.InvalidSearchFilterException;
39 503 bojilova
import javax.naming.directory.Attribute;
40
import javax.naming.directory.Attributes;
41 504 jones
import javax.naming.directory.DirContext;
42
import javax.naming.directory.InitialDirContext;
43
import javax.naming.directory.SearchResult;
44 723 bojilova
import javax.naming.directory.SearchControls;
45 868 berkley
import javax.naming.ReferralException;
46 3022 sgarg
import javax.naming.ldap.InitialLdapContext;
47
import javax.naming.ldap.LdapContext;
48
import javax.naming.ldap.StartTlsRequest;
49
import javax.naming.ldap.StartTlsResponse;
50
import javax.net.ssl.SSLSession;
51 2666 sgarg
52
import org.apache.log4j.Logger;
53
54 1988 jones
import java.net.URLDecoder;
55 503 bojilova
import java.util.Iterator;
56
import java.util.HashMap;
57
import java.util.Hashtable;
58 730 bojilova
import java.util.Enumeration;
59 503 bojilova
import java.util.Set;
60
import java.util.Vector;
61
62
/**
63
 * An implementation of the AuthInterface interface that
64
 * allows Metacat to use the LDAP protocol for directory services.
65 2058 sgarg
 * The LDAP authentication service is used to determine if a user
66 503 bojilova
 * is authenticated, and whether they are a member of a particular group.
67
 */
68 2121 sgarg
public class AuthLdap
69
    implements AuthInterface, Runnable {
70 787 bojilova
  private MetaCatUtil util = new MetaCatUtil();
71 728 bojilova
  private String ldapUrl;
72 787 bojilova
  private String ldapsUrl;
73 728 bojilova
  private String ldapBase;
74 865 jones
  private String referral;
75 991 tao
  private Context referralContext;
76 893 berkley
  Hashtable env = new Hashtable(11);
77
  private Context rContext;
78 934 tao
  private String userName;
79
  private String userPassword;
80 893 berkley
  ReferralException refExc;
81 503 bojilova
82 2666 sgarg
  private static Logger logMetacat = Logger.getLogger(AuthLdap.class);
83
84 2058 sgarg
  /**
85 728 bojilova
   * Construct an AuthLdap
86
   */
87
  public AuthLdap() {
88
    // Read LDAP URI for directory service information
89 787 bojilova
    this.ldapUrl = MetaCatUtil.getOption("ldapurl");
90
    this.ldapsUrl = MetaCatUtil.getOption("ldapsurl");
91
    this.ldapBase = MetaCatUtil.getOption("ldapbase");
92 865 jones
    this.referral = MetaCatUtil.getOption("referral");
93 728 bojilova
  }
94
95 503 bojilova
  /**
96
   * Determine if a user/password are valid according to the authentication
97
   * service.
98
   *
99
   * @param user the name of the principal to authenticate
100
   * @param password the password to use for authentication
101
   * @returns boolean true if authentication successful, false otherwise
102
   */
103 3022 sgarg
104 2121 sgarg
  public boolean authenticate(String user, String password) throws
105
      ConnectException {
106 730 bojilova
    String ldapUrl = this.ldapUrl;
107 787 bojilova
    String ldapsUrl = this.ldapsUrl;
108 730 bojilova
    String ldapBase = this.ldapBase;
109 503 bojilova
    boolean authenticated = false;
110 802 bojilova
    String identifier = user;
111 3022 sgarg
112 1004 tao
    //get uid here.
113 3022 sgarg
    String uid=user.substring(0, user.indexOf(","));
114
    user = user.substring(user.indexOf(","), user.length());
115 2058 sgarg
116 3022 sgarg
    logMetacat.debug("identifier: " + identifier);
117
    logMetacat.debug("uid: " + uid);
118
    logMetacat.debug("user: " + user);
119
120 503 bojilova
    try {
121 3022 sgarg
    	// Check the usename as passed in
122
        logMetacat.info("Calling ldapAuthenticate");
123
        logMetacat.info("with user as identifier: " + identifier);
124
125
        authenticated = ldapAuthenticate(identifier, password,
126
        		(new Boolean(MetaCatUtil.getOption("onlySecureLDAPConnection"))).booleanValue());
127
        // if not found, try looking up a valid DN then auth again
128
        if (!authenticated) {
129
        	logMetacat.info("Not Authenticated");
130
        	logMetacat.info("Looking up DN for: " + identifier);
131
        	identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
132
        	if(identifier == null){
133 3023 sgarg
        		logMetacat.info("No DN found from getIdentifyingName");
134 3022 sgarg
        		return authenticated;
135
        	}
136
137
           	logMetacat.info("DN found from getIdentifyingName: " + identifier);
138
        	String decoded = URLDecoder.decode(identifier);
139
        	logMetacat.info("DN decoded: " + decoded);
140
        	identifier = decoded;
141
        	String refUrl = "";
142
        	String refBase = "";
143
        	if (identifier.startsWith("ldap")) {
144
        		logMetacat.debug("identifier starts with ldap");
145
146
        		refUrl = identifier.substring(0, identifier.lastIndexOf("/") + 1);
147
        		int position = identifier.indexOf(",");
148
        		int position2 = identifier.indexOf(",", position + 1);
149 3023 sgarg
150 3022 sgarg
        		refBase = identifier.substring(position2 + 1);
151
        		identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
152 3023 sgarg
153 3022 sgarg
        		logMetacat.info("Calling ldapAuthenticate");
154
        		logMetacat.info("with user as identifier: " + identifier);
155
        		logMetacat.info("and refUrl as: " + refUrl);
156
        		logMetacat.info("and refBase as: " + refBase);
157
158
        		authenticated = ldapAuthenticate(identifier, password, refUrl, refBase,
159
                		(new Boolean(MetaCatUtil.getOption("onlySecureLDAPReferalsConnection")))
160
                			.booleanValue());
161
        	} else {
162
        		logMetacat.info("identifier doesnt start with ldap");
163 3023 sgarg
        		identifier = identifier + "," + ldapBase;
164
165 3022 sgarg
        		logMetacat.info("Calling ldapAuthenticate");
166
        		logMetacat.info("with user as identifier: " + identifier);
167 3023 sgarg
168 3022 sgarg
        		authenticated = ldapAuthenticate(identifier, password,
169
            		(new Boolean(MetaCatUtil.getOption("onlySecureLDAPConnection"))).booleanValue());
170
        	}
171 1004 tao
        }
172 2121 sgarg
    }
173
    catch (NullPointerException e) {
174 3022 sgarg
    	logMetacat.error("NullPointerException while authenticating in " +
175 2589 sgarg
                        "AuthLdap.authenticate: " + e);
176 3022 sgarg
    	e.printStackTrace();
177
178
    	throw new ConnectException(
179 2121 sgarg
          "NullPointerException while authenticating in " +
180
          "AuthLdap.authenticate: " + e);
181 3022 sgarg
    } catch (NamingException e) {
182
    	logMetacat.error("Naming exception while authenticating in " +
183 2589 sgarg
                        "AuthLdap.authenticate: " + e);
184 3022 sgarg
    	e.printStackTrace();
185
    } catch (Exception e) {
186
    	logMetacat.error(e.getMessage());
187 2121 sgarg
    }
188 3022 sgarg
189 503 bojilova
    return authenticated;
190
  }
191
192
  /**
193 852 jones
   * Connect to the LDAP directory and do the authentication using the
194
   * username and password as passed into the routine.
195
   *
196
   * @param identifier the distinguished name to check against LDAP
197
   * @param password the password for authentication
198
   */
199 3022 sgarg
  private boolean ldapAuthenticate(String identifier, String password,
200
		  boolean secureConnectionOnly) throws ConnectException, NamingException,
201
		  NullPointerException {
202 2121 sgarg
    return ldapAuthenticate(identifier, password,
203 3022 sgarg
                            this.ldapsUrl, this.ldapBase, secureConnectionOnly);
204 1005 jones
  }
205
206
  /**
207
   * Connect to the LDAP directory and do the authentication using the
208
   * username and password as passed into the routine.
209
   *
210
   * @param identifier the distinguished name to check against LDAP
211
   * @param password the password for authentication
212
   */
213 3022 sgarg
214
  private boolean ldapAuthenticate(String dn, String password, String rootServer,
215
		  String rootBase, boolean secureConnectionOnly){
216
217
	  boolean authenticated = false;
218
219
	  String server = "";
220
	  String userDN = "";
221
	  logMetacat.info("dn is: " + dn);
222 2058 sgarg
223 3022 sgarg
	  int position = dn.lastIndexOf("/");
224
      logMetacat.debug("position is: " + position);
225
	  if (position == -1) {
226
		  server = rootServer;
227
		  if(dn.indexOf(userDN) < 0){
228
			  userDN = dn + "," + rootBase;
229
		  } else {
230
			  userDN = dn;
231
		  }
232
		  logMetacat.info("userDN is: " + userDN);
233
234
       } else {
235
		  server = dn.substring(0, position+1);
236
		  userDN = dn.substring(position+1);
237
		  logMetacat.info("server is: " + server);
238
		  logMetacat.info("userDN is: " + userDN);
239
	   }
240
241
	   logMetacat.warn("Trying to authenticate: " + userDN);
242
	   logMetacat.warn("          Using server: " + server);
243
244
	   LdapContext ctx = null;
245
	   double startTime;
246
	   double stopTime;
247
	   try {
248
		   Hashtable env = new Hashtable();
249
		   env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
250
		   env.put(Context.PROVIDER_URL, server);
251
		   env.put(Context.REFERRAL, "throw");
252
253
		   try {
254
255
			   startTime = System.currentTimeMillis();
256
			   ctx = new InitialLdapContext(env, null);
257
258
			   // Start up TLS here so that we don't pass our jewels in cleartext
259
		       StartTlsResponse tls =
260
		              (StartTlsResponse)ctx.extendedOperation(new StartTlsRequest());
261
		       //tls.setHostnameVerifier(new SampleVerifier());
262
		       SSLSession sess = tls.negotiate();
263
264
		       ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
265
			   ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
266
			   ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
267
			   ctx.reconnect(null);
268
269
			   stopTime = System.currentTimeMillis();
270
			   logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
271
                       	(stopTime - startTime) / 1000 + " seconds.");
272
273
			   authenticated = true;
274
		   } catch (java.io.IOException ioe) {
275
			   logMetacat.warn("Caught IOException in login while negotiating TLS: "
276
	                                 + ioe.getMessage());
277
278
			   if(secureConnectionOnly){
279 3023 sgarg
280
				   return authenticated;
281
282 3022 sgarg
			   } else {
283 3023 sgarg
284
				   logMetacat.info("Trying to authenticate without TLS");
285 3022 sgarg
				   env.put(Context.SECURITY_AUTHENTICATION, "simple");
286
				   env.put(Context.SECURITY_PRINCIPAL, userDN);
287
				   env.put(Context.SECURITY_CREDENTIALS, password);
288
289
				   startTime = System.currentTimeMillis();
290
				   ctx = new InitialLdapContext(env, null);
291
				   stopTime = System.currentTimeMillis();
292
				   logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
293
	                       	(stopTime - startTime) / 1000 + " seconds.");
294
295
				   authenticated = true;
296
			   }
297
		   }
298
	   } catch (AuthenticationException ae) {
299
		   authenticated = false;
300
	   } catch (javax.naming.InvalidNameException ine) {
301
	        logMetacat.error("An invalid DN was provided!");
302
	   } catch (NamingException e) {
303
		   logMetacat.warn("Caught NamingException in login: " + e.getClass().getName());
304
		   logMetacat.info(e.toString() + "  " + e.getRootCause());
305 2666 sgarg
       }
306 934 tao
307 3022 sgarg
       return authenticated;
308 852 jones
  }
309
310 3022 sgarg
311 852 jones
  /**
312 730 bojilova
   * Get the identifying name for a given userid or name.  This is the name
313
   * that is used in conjunction withthe LDAP BaseDN to create a
314
   * distinguished name (dn) for the record
315
   *
316
   * @param user the user for which the identifying name is requested
317 2058 sgarg
   * @returns String the identifying name for the user,
318 730 bojilova
   *          or null if not found
319
   */
320 934 tao
  private String getIdentifyingName(String user, String ldapUrl,
321 3022 sgarg
          String ldapBase) throws NamingException {
322
323
      String identifier = null;
324
      Hashtable env = new Hashtable();
325
      env.put(Context.INITIAL_CONTEXT_FACTORY,
326
              "com.sun.jndi.ldap.LdapCtxFactory");
327
      env.put(Context.REFERRAL, "throw");
328
      env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
329 802 bojilova
      try {
330 3022 sgarg
    	  int position = user.indexOf(",");
331
          String uid = user.substring(user.indexOf("=") + 1, position);
332 3023 sgarg
          logMetacat.info("uid is: " + uid);
333 3022 sgarg
          String org = user.substring(user.indexOf("=", position + 1) + 1,
334
                                        user.indexOf(",", position + 1));
335 3023 sgarg
          logMetacat.info("org is: " + org);
336 3022 sgarg
337
          DirContext sctx = new InitialDirContext(env);
338
          SearchControls ctls = new SearchControls();
339
          ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
340
          String filter = "(&(uid=" + uid + ")(o=" + org + "))";
341 3023 sgarg
          logMetacat.warn("Searching for DNs with following filter: " + filter);
342 3022 sgarg
343
          for (boolean moreReferrals = true; moreReferrals;) {
344
              try {
345
                  // Perform the search
346
                  NamingEnumeration answer =
347
                      sctx.search("", filter, ctls);
348 1005 jones
349 3022 sgarg
                  // Return the answer
350
                  while (answer.hasMore()) {
351
                      SearchResult sr = (SearchResult)answer.next();
352
                      identifier = sr.getName();
353
                      return identifier;
354
                  }
355
                  // The search completes with no more referrals
356
                  moreReferrals = false;
357
              } catch (ReferralException e) {
358
            	  logMetacat.info("Got referral: " + e.getReferralInfo());
359 3023 sgarg
            	  // Point to the new context from the referral
360 3022 sgarg
                  if (moreReferrals) {
361
                      sctx = (DirContext) e.getReferralContext();
362
                  }
363
              }
364 730 bojilova
          }
365 3022 sgarg
      } catch (NamingException e) {
366
    	     logMetacat.error("Naming exception while getting dn: " + e);
367
    	      throw new NamingException(
368
    	          "Naming exception in AuthLdap.getIdentifyingName: " + e);
369
    	      }
370
      return identifier;
371 730 bojilova
  }
372 3022 sgarg
373 730 bojilova
  /**
374 503 bojilova
   * Get all users from the authentication service
375 871 jones
   *
376
   * @param user the user for authenticating against the service
377
   * @param password the password for authenticating against the service
378
   * @returns string array of all of the user names
379 503 bojilova
   */
380 2121 sgarg
  public String[][] getUsers(String user, String password) throws
381
      ConnectException {
382 2058 sgarg
    String[][] users = null;
383 723 bojilova
384
    // Identify service provider to use
385
    Hashtable env = new Hashtable(11);
386 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
387 723 bojilova
            "com.sun.jndi.ldap.LdapCtxFactory");
388 865 jones
    env.put(Context.REFERRAL, referral);
389 871 jones
    env.put(Context.PROVIDER_URL, ldapUrl);
390 2058 sgarg
391 723 bojilova
    try {
392
393 2121 sgarg
      // Create the initial directory context
394
      DirContext ctx = new InitialDirContext(env);
395 723 bojilova
396 2121 sgarg
      // Specify the attributes to match.
397
      // Users are objects that have the attribute objectclass=InetOrgPerson.
398
      SearchControls ctls = new SearchControls();
399
      String[] attrIDs = {
400 2130 sgarg
          "dn", "cn", "o", "ou", "mail"};
401 2121 sgarg
      ctls.setReturningAttributes(attrIDs);
402
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
403
      //ctls.setCountLimit(1000);
404
      String filter = "(objectClass=inetOrgPerson)";
405 2447 sgarg
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
406 2058 sgarg
407 2121 sgarg
      // Store the users in a vector
408
      Vector uvec = new Vector();
409
      Vector uname = new Vector();
410
      Vector uorg = new Vector();
411 2130 sgarg
      Vector uou = new Vector();
412 2121 sgarg
      Vector umail = new Vector();
413
      Attributes tempAttr = null;
414
      try {
415 2447 sgarg
        while (namingEnum.hasMore()) {
416
          SearchResult sr = (SearchResult) namingEnum.next();
417 2121 sgarg
          tempAttr = sr.getAttributes();
418 2058 sgarg
419 2121 sgarg
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
420
            uname.add( (tempAttr.get("cn") + "").substring(4));
421
          }
422
          else {
423
            uname.add(tempAttr.get("cn") + "");
424
          }
425 2058 sgarg
426 2121 sgarg
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
427
            uorg.add( (tempAttr.get("o") + "").substring(3));
428
          }
429
          else {
430
            uorg.add(tempAttr.get("o") + "");
431
          }
432 2116 sgarg
433 2130 sgarg
          if ( (tempAttr.get("ou") + "").startsWith("ou: ")) {
434
            uou.add( (tempAttr.get("ou") + "").substring(4));
435
          }
436
          else {
437
            uou.add(tempAttr.get("ou") + "");
438
          }
439
440 2121 sgarg
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
441
            umail.add( (tempAttr.get("mail") + "").substring(6));
442
          }
443
          else {
444
            umail.add(tempAttr.get("mail") + "");
445
          }
446 2058 sgarg
447 2121 sgarg
          uvec.add(sr.getName() + "," + ldapBase);
448 723 bojilova
        }
449 2121 sgarg
      }
450
      catch (SizeLimitExceededException slee) {
451 2666 sgarg
        logMetacat.error("LDAP Server size limit exceeded. " +
452 2589 sgarg
                          "Returning incomplete record set.");
453 2121 sgarg
      }
454 723 bojilova
455 2121 sgarg
      // initialize users[]; fill users[]
456 2130 sgarg
      users = new String[uvec.size()][5];
457 2121 sgarg
      for (int i = 0; i < uvec.size(); i++) {
458
        users[i][0] = (String) uvec.elementAt(i);
459
        users[i][1] = (String) uname.elementAt(i);
460
        users[i][2] = (String) uorg.elementAt(i);
461 2130 sgarg
        users[i][3] = (String) uorg.elementAt(i);
462
        users[i][4] = (String) umail.elementAt(i);
463 2121 sgarg
      }
464 723 bojilova
465 2121 sgarg
      // Close the context when we're done
466
      ctx.close();
467 723 bojilova
468 2121 sgarg
    }
469
    catch (NamingException e) {
470 2666 sgarg
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
471 1477 tao
      //e.printStackTrace(System.err);
472 723 bojilova
      throw new ConnectException(
473 2121 sgarg
          "Problem getting users in AuthLdap.getUsers:" + e);
474 723 bojilova
    }
475
476
    return users;
477 503 bojilova
  }
478
479 2679 sgarg
480 503 bojilova
  /**
481 2679 sgarg
   * Get all users from the authentication service
482
   *
483
   * @param user the user for authenticating against the service
484
   * @param password the password for authenticating against the service
485
   * @returns string array of all of the user names
486
   */
487
  public String[] getUserInfo(String user, String password) throws
488
      ConnectException {
489
    String[] userinfo = new String[3];
490
491
    // Identify service provider to use
492
    Hashtable env = new Hashtable(11);
493
    env.put(Context.INITIAL_CONTEXT_FACTORY,
494
            "com.sun.jndi.ldap.LdapCtxFactory");
495
    env.put(Context.REFERRAL, referral);
496
    env.put(Context.PROVIDER_URL, ldapUrl);
497
498
    try {
499 2697 sgarg
500 2679 sgarg
      // Create the initial directory context
501
      DirContext ctx = new InitialDirContext(env);
502
      // Specify the attributes to match.
503
      // Users are objects that have the attribute objectclass=InetOrgPerson.
504
      SearchControls ctls = new SearchControls();
505
      String[] attrIDs = {
506
          "cn", "o", "mail"};
507
      ctls.setReturningAttributes(attrIDs);
508
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
509
      //ctls.setCountLimit(1000);
510 2697 sgarg
      // create the filter based on the uid
511
512
      String filter = null;
513
514
      if(user.indexOf("o=")>0){
515
    	  String tempStr = user.substring(user.indexOf("o="));
516
    	  filter = "(&(" + user.substring(0, user.indexOf(","))
517
			+ ")(" + tempStr.substring(0, tempStr.indexOf(","))
518
			+ "))";
519
      } else{
520
    	  filter = "(&(" + user.substring(0, user.indexOf(","))
521
			+ "))";
522
      }
523
   	  filter = "(&(" + user.substring(0, user.indexOf(","))
524
		+ "))";
525
526 2679 sgarg
      NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
527 2697 sgarg
528 2679 sgarg
      Attributes tempAttr = null;
529
      try {
530
        while (namingEnum.hasMore()) {
531
          SearchResult sr = (SearchResult) namingEnum.next();
532
          tempAttr = sr.getAttributes();
533
534
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
535
        	  userinfo[0] = (tempAttr.get("cn") + "").substring(4);
536
          }
537
          else {
538
        	  userinfo[0] = (tempAttr.get("cn") + "");
539
          }
540
541
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
542
        	  userinfo[1] = (tempAttr.get("o") + "").substring(3);
543
          }
544
          else {
545
        	  userinfo[1] = (tempAttr.get("o") + "");
546
          }
547
548
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
549
        	  userinfo[2] =  (tempAttr.get("mail") + "").substring(6);
550
          }
551
          else {
552
        	  userinfo[2] = (tempAttr.get("mail") + "");
553
          }
554
        }
555
      }
556
      catch (SizeLimitExceededException slee) {
557
        logMetacat.error("LDAP Server size limit exceeded. " +
558
                          "Returning incomplete record set.");
559
      }
560
561
      // Close the context when we're done
562
      ctx.close();
563
564
    }
565
    catch (NamingException e) {
566
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
567
      //e.printStackTrace(System.err);
568
      throw new ConnectException(
569
          "Problem getting users in AuthLdap.getUsers:" + e);
570
    }
571
572
    return userinfo;
573
  }
574
575
  /**
576 503 bojilova
   * Get the users for a particular group from the authentication service
577 871 jones
   *
578
   * @param user the user for authenticating against the service
579
   * @param password the password for authenticating against the service
580
   * @param group the group whose user list should be returned
581
   * @returns string array of the user names belonging to the group
582 503 bojilova
   */
583 2121 sgarg
  public String[] getUsers(String user, String password, String group) throws
584
      ConnectException {
585 723 bojilova
    String[] users = null;
586
587
    // Identify service provider to use
588
    Hashtable env = new Hashtable(11);
589 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
590 723 bojilova
            "com.sun.jndi.ldap.LdapCtxFactory");
591 865 jones
    env.put(Context.REFERRAL, referral);
592 871 jones
    env.put(Context.PROVIDER_URL, ldapUrl);
593 723 bojilova
594
    try {
595
596 2121 sgarg
      // Create the initial directory context
597
      DirContext ctx = new InitialDirContext(env);
598 723 bojilova
599 2121 sgarg
      // Specify the ids of the attributes to return
600
      String[] attrIDs = {
601
          "uniqueMember"};
602 723 bojilova
603 2121 sgarg
      Attributes answer = ctx.getAttributes(group, attrIDs);
604 723 bojilova
605 2121 sgarg
      Vector uvec = new Vector();
606
      try {
607
        for (NamingEnumeration ae = answer.getAll(); ae.hasMore(); ) {
608
          Attribute attr = (Attribute) ae.next();
609
          for (NamingEnumeration e = attr.getAll();
610
               e.hasMore();
611
               uvec.add(e.next())
612
               ) {
613
            ;
614
          }
615 723 bojilova
        }
616 2121 sgarg
      }
617
      catch (SizeLimitExceededException slee) {
618 2666 sgarg
        logMetacat.error("LDAP Server size limit exceeded. " +
619 2589 sgarg
                          "Returning incomplete record set.");
620 2121 sgarg
      }
621 723 bojilova
622 2121 sgarg
      // initialize users[]; fill users[]
623
      users = new String[uvec.size()];
624
      for (int i = 0; i < uvec.size(); i++) {
625
        users[i] = (String) uvec.elementAt(i);
626
      }
627 723 bojilova
628 2121 sgarg
      // Close the context when we're done
629
      ctx.close();
630 723 bojilova
631 2121 sgarg
    }
632
    catch (NamingException e) {
633 2666 sgarg
      logMetacat.error("Problem getting users for a group in " +
634 2589 sgarg
                        "AuthLdap.getUsers:" + e);
635 723 bojilova
      throw new ConnectException(
636 2121 sgarg
          "Problem getting users for a group in AuthLdap.getUsers:" + e);
637 723 bojilova
    }
638
639
    return users;
640 503 bojilova
  }
641
642
  /**
643
   * Get all groups from the authentication service
644 871 jones
   *
645
   * @param user the user for authenticating against the service
646
   * @param password the password for authenticating against the service
647
   * @returns string array of the group names
648 503 bojilova
   */
649 2121 sgarg
  public String[][] getGroups(String user, String password) throws
650
      ConnectException {
651
    return getGroups(user, password, null);
652 503 bojilova
  }
653
654
  /**
655
   * Get the groups for a particular user from the authentication service
656 871 jones
   *
657
   * @param user the user for authenticating against the service
658
   * @param password the password for authenticating against the service
659
   * @param foruser the user whose group list should be returned
660
   * @returns string array of the group names
661 503 bojilova
   */
662 2121 sgarg
  public String[][] getGroups(String user, String password, String foruser) throws
663
      ConnectException {
664 2116 sgarg
    Vector gvec = new Vector();
665 2058 sgarg
    Vector desc = new Vector();
666
    Attributes tempAttr = null;
667
668 976 tao
    //Pass the username and password to run() method
669 2121 sgarg
    userName = user;
670
    userPassword = password;
671 723 bojilova
    // Identify service provider to use
672 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
673 723 bojilova
            "com.sun.jndi.ldap.LdapCtxFactory");
674 888 berkley
    env.put(Context.REFERRAL, "throw");
675 871 jones
    env.put(Context.PROVIDER_URL, ldapUrl);
676 723 bojilova
    try {
677 2121 sgarg
      // Create the initial directory context
678
      DirContext ctx = new InitialDirContext(env);
679
      // Specify the ids of the attributes to return
680
      String[] attrIDs = {
681
          "cn", "o", "description"};
682
      // Specify the attributes to match.
683
      // Groups are objects with attribute objectclass=groupofuniquenames.
684
      // and have attribute uniquemember: uid=foruser,ldapbase.
685
      SearchControls ctls = new SearchControls();
686
      ctls.setReturningAttributes(attrIDs);
687
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
688 2058 sgarg
689 2121 sgarg
      String filter = null;
690
      String gfilter = "(objectClass=groupOfUniqueNames)";
691
      if (null == foruser) {
692
        filter = gfilter;
693
      }
694
      else {
695
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
696
      }
697 2666 sgarg
      logMetacat.info("searching for groups: " + filter);
698 2447 sgarg
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
699 991 tao
700 2121 sgarg
      // Print the groups
701 2666 sgarg
      logMetacat.info("getting group results.");
702 2447 sgarg
      while (namingEnum.hasMore()) {
703
        SearchResult sr = (SearchResult) namingEnum.next();
704 2121 sgarg
        tempAttr = sr.getAttributes();
705 2058 sgarg
706 2121 sgarg
        if ( (tempAttr.get("description") + "").startsWith("description: ")) {
707
          desc.add( (tempAttr.get("description") + "").substring(13));
708 723 bojilova
        }
709 2121 sgarg
        else {
710
          desc.add(tempAttr.get("description") + "");
711
        }
712 991 tao
713 2121 sgarg
        gvec.add(sr.getName() + "," + ldapBase);
714 2666 sgarg
        logMetacat.info("group " + sr.getName() +
715 2589 sgarg
                                 " added to Group vector");
716 2121 sgarg
      }
717
      // Close the context when we're done
718
      ctx.close();
719
720 2058 sgarg
    }
721 2121 sgarg
    catch (ReferralException re) {
722 1000 berkley
      refExc = re;
723
      Thread t = new Thread(new GetGroup());
724 2666 sgarg
      logMetacat.info("Starting thread...");
725 1000 berkley
      t.start();
726 2666 sgarg
      logMetacat.info("sleeping for 5 seconds.");
727 2121 sgarg
      try {
728 1000 berkley
        Thread.sleep(5000);
729
      }
730 2121 sgarg
      catch (InterruptedException ie) {
731 2666 sgarg
        logMetacat.error("main thread interrupted: " + ie.getMessage());
732 1000 berkley
      }
733
      //this is a manual override of jndi's hideously long time
734
      //out period.
735 2666 sgarg
      logMetacat.info("Awake after 5 seconds.");
736 2121 sgarg
      if (referralContext == null) {
737 2666 sgarg
        logMetacat.info("thread timed out...returning groups: " +
738 2589 sgarg
                          gvec.toString());
739 2116 sgarg
        String groups[][] = new String[gvec.size()][2];
740 2121 sgarg
        for (int i = 0; i < gvec.size(); i++) {
741
          groups[i][0] = (String) gvec.elementAt(i);
742
          groups[i][1] = (String) desc.elementAt(i);
743 991 tao
        }
744 1000 berkley
        t.interrupt();
745
        return groups;
746
      }
747 2121 sgarg
      DirContext dc = (DirContext) referralContext;
748
      String[] attrIDs = {
749
          "cn", "o", "description"};
750 1000 berkley
      // Specify the attributes to match.
751
      // Groups are objects with attribute objectclass=groupofuniquenames.
752
      // and have attribute uniquemember: uid=foruser,ldapbase.
753
      SearchControls ctls = new SearchControls();
754
      ctls.setReturningAttributes(attrIDs);
755
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
756 2058 sgarg
757 1000 berkley
      String filter = null;
758
      String gfilter = "(objectClass=groupOfUniqueNames)";
759
      if (null == foruser) {
760 2121 sgarg
        filter = gfilter;
761 1000 berkley
      }
762 2121 sgarg
      else {
763
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
764
      }
765 2058 sgarg
766 2121 sgarg
      try {
767 2447 sgarg
        NamingEnumeration namingEnum = dc.search(ldapBase, filter, ctls);
768 991 tao
        // Print the groups
769 2447 sgarg
        while (namingEnum.hasMore()) {
770
          SearchResult sr = (SearchResult) namingEnum.next();
771 2058 sgarg
          tempAttr = sr.getAttributes();
772
773 2121 sgarg
          if ( (tempAttr.get("description") + "").startsWith("description: ")) {
774 2058 sgarg
            desc.add( (tempAttr.get("description") + "").substring(13));
775
          }
776 2121 sgarg
          else {
777
            desc.add(tempAttr.get("description") + "");
778
          }
779 2058 sgarg
780 2121 sgarg
          gvec.add(sr.getName() + "," + ldapBase);
781 991 tao
        }
782 2058 sgarg
783 991 tao
        referralContext.close();
784
        dc.close();
785
      }
786 2121 sgarg
      catch (NamingException ne) {
787 3022 sgarg
        logMetacat.info("Naming Exception in AuthLdap.getGroups for referals" +
788 2589 sgarg
                                 ne.getExplanation() + ne.getMessage());
789 991 tao
      }
790 2121 sgarg
    }
791
    catch (NamingException e) {
792 868 berkley
      e.printStackTrace(System.err);
793 2116 sgarg
      String groups[][] = new String[gvec.size()][2];
794 2121 sgarg
      for (int i = 0; i < gvec.size(); i++) {
795
        groups[i][0] = (String) gvec.elementAt(i);
796
        groups[i][1] = (String) desc.elementAt(i);
797 1006 tao
      }
798
      return groups;
799 2121 sgarg
      /*throw new ConnectException(
800
             "Problem getting groups for a user in AuthLdap.getGroups:" + e);*/
801 2058 sgarg
    }
802
803 2666 sgarg
    logMetacat.warn("The user is in the following groups: " +
804 2589 sgarg
                             gvec.toString());
805 2116 sgarg
    String groups[][] = new String[gvec.size()][2];
806 2121 sgarg
    for (int i = 0; i < gvec.size(); i++) {
807
      groups[i][0] = (String) gvec.elementAt(i);
808
      groups[i][1] = (String) desc.elementAt(i);
809 1000 berkley
    }
810 723 bojilova
    return groups;
811 503 bojilova
  }
812
813
  /**
814
   * Get attributes describing a user or group
815
   *
816 871 jones
   * @param foruser the user for which the attribute list is requested
817 503 bojilova
   * @returns HashMap a map of attribute name to a Vector of values
818
   */
819 2121 sgarg
  public HashMap getAttributes(String foruser) throws ConnectException {
820 514 jones
    return getAttributes(null, null, foruser);
821 503 bojilova
  }
822
823
  /**
824
   * Get attributes describing a user or group
825
   *
826 871 jones
   * @param user the user for authenticating against the service
827 503 bojilova
   * @param password the password for authenticating against the service
828 871 jones
   * @param foruser the user whose attributes should be returned
829 503 bojilova
   * @returns HashMap a map of attribute name to a Vector of values
830
   */
831 2121 sgarg
  public HashMap getAttributes(String user, String password, String foruser) throws
832
      ConnectException {
833 503 bojilova
    HashMap attributes = new HashMap();
834 802 bojilova
    String ldapUrl = this.ldapUrl;
835
    String ldapBase = this.ldapBase;
836
    String userident = foruser;
837 2058 sgarg
838 503 bojilova
    // Identify service provider to use
839
    Hashtable env = new Hashtable(11);
840 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
841 2121 sgarg
            "com.sun.jndi.ldap.LdapCtxFactory");
842 865 jones
    env.put(Context.REFERRAL, referral);
843 871 jones
    env.put(Context.PROVIDER_URL, ldapUrl);
844 503 bojilova
845
    try {
846 2058 sgarg
847 503 bojilova
      // Create the initial directory context
848
      DirContext ctx = new InitialDirContext(env);
849 2058 sgarg
850
      // Ask for all attributes of the user
851 871 jones
      //Attributes attrs = ctx.getAttributes(userident);
852
      Attributes attrs = ctx.getAttributes(foruser);
853 2058 sgarg
854 503 bojilova
      // Print all of the attributes
855
      NamingEnumeration en = attrs.getAll();
856
      while (en.hasMore()) {
857 2121 sgarg
        Attribute att = (Attribute) en.next();
858 503 bojilova
        Vector values = new Vector();
859
        String attName = att.getID();
860
        NamingEnumeration attvalues = att.getAll();
861
        while (attvalues.hasMore()) {
862 2121 sgarg
          String value = (String) attvalues.next();
863 503 bojilova
          values.add(value);
864
        }
865
        attributes.put(attName, values);
866
      }
867 2058 sgarg
868 503 bojilova
      // Close the context when we're done
869
      ctx.close();
870 2121 sgarg
    }
871
    catch (NamingException e) {
872 2666 sgarg
      logMetacat.error("Problem getting attributes in " +
873 2589 sgarg
                        "AuthLdap.getAttributes:" + e);
874 723 bojilova
      throw new ConnectException(
875 2121 sgarg
          "Problem getting attributes in AuthLdap.getAttributes:" + e);
876 503 bojilova
    }
877
878
    return attributes;
879
  }
880
881
  /**
882 730 bojilova
   * Get list of all subtrees holding Metacat's groups and users
883 2058 sgarg
   * starting from the Metacat LDAP root,
884 730 bojilova
   * i.e. ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
885 504 jones
   */
886 730 bojilova
  private Hashtable getSubtrees(String user, String password,
887 2121 sgarg
                                String ldapUrl, String ldapBase) throws
888
      ConnectException {
889 730 bojilova
    Hashtable trees = new Hashtable();
890 504 jones
891
    // Identify service provider to use
892
    Hashtable env = new Hashtable(11);
893 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
894 504 jones
            "com.sun.jndi.ldap.LdapCtxFactory");
895 2129 sgarg
    // env.put(Context.REFERRAL, referral);
896
    // Using 'ignore' here instead of 'follow' as 'ignore' seems
897
    // to do the job better. 'follow' was not bringing up the UCNRS
898
    // and PISCO tree whereas 'ignore' brings up the tree.
899
900
    env.put(Context.REFERRAL, "ignore");
901 504 jones
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
902
903
    try {
904
905 2121 sgarg
      // Create the initial directory context
906
      DirContext ctx = new InitialDirContext(env);
907 730 bojilova
908 2121 sgarg
      // Specify the ids of the attributes to return
909
      String[] attrIDs = {
910
          "o", "ref"};
911
      SearchControls ctls = new SearchControls();
912
      ctls.setReturningAttributes(attrIDs);
913
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
914 2058 sgarg
915 2121 sgarg
      // Specify the attributes to match.
916
      // Subtrees from the main server are found as objects with attribute
917
      // objectclass=organization or objectclass=referral to the subtree
918
      // resided on other server.
919
      String filter = "(|(objectclass=organization)(objectclass=referral))";
920 730 bojilova
921 2121 sgarg
      // Search for objects in the current context
922 2447 sgarg
      NamingEnumeration namingEnum = ctx.search("", filter, ctls);
923 730 bojilova
924 2121 sgarg
      // Print the subtrees' <ldapURL, baseDN>
925 2447 sgarg
      while (namingEnum.hasMore()) {
926 2121 sgarg
927 2447 sgarg
        SearchResult sr = (SearchResult) namingEnum.next();
928 2121 sgarg
929
        Attributes attrs = sr.getAttributes();
930
        NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref" attrs
931
932
        if (enum1.hasMore()) {
933
          Attribute attr = (Attribute) enum1.next();
934
          String attrValue = (String) attr.get();
935
          String attrName = (String) attr.getID();
936
937 730 bojilova
          if (enum1.hasMore()) {
938 2121 sgarg
            attr = (Attribute) enum1.next();
939
            String refValue = (String) attr.get();
940
            String refName = (String) attr.getID();
941
            if (ldapBase.startsWith(refName + "=" + refValue)) {
942
              trees.put(ldapBase,
943
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
944
            }
945
            else {
946 2129 sgarg
              // this is a referral - so organization name is appended in
947
              // front of the ldapbase.... later it is stripped out
948
              // in getPrincipals
949
              trees.put("[" + refName + "=" + refValue + "]" +
950
                        attrValue.substring(attrValue.lastIndexOf("/") + 1,
951
                                            attrValue.length()),
952 2121 sgarg
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
953 2129 sgarg
954
              // trees.put(refName + "=" + refValue + "," + ldapBase,
955
              //           attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
956 2121 sgarg
            }
957 2058 sgarg
958 2121 sgarg
          }
959
          else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
960
            trees.put(ldapBase, ldapUrl);
961
          }
962
          else {
963 2129 sgarg
            if (sr.isRelative()) {
964 2121 sgarg
              trees.put(attrName + "=" + attrValue + "," + ldapBase, ldapUrl);
965 2130 sgarg
            }
966
            else {
967 2121 sgarg
              String referenceURL = sr.getName();
968 2129 sgarg
              referenceURL = referenceURL.substring(0,
969
                  referenceURL.lastIndexOf("/") + 1);
970
              trees.put(attrName + "=" + attrValue + "," + ldapBase,
971
                        referenceURL);
972 730 bojilova
            }
973 2121 sgarg
974 504 jones
          }
975
        }
976 2121 sgarg
      }
977 730 bojilova
978 2121 sgarg
      // Close the context when we're done
979
      ctx.close();
980 730 bojilova
981 2121 sgarg
    }
982
    catch (NamingException e) {
983 2666 sgarg
      logMetacat.error("Problem getting subtrees in AuthLdap.getSubtrees:"
984 2589 sgarg
                        + e);
985 730 bojilova
      throw new ConnectException(
986 2121 sgarg
          "Problem getting subtrees in AuthLdap.getSubtrees:" + e);
987 504 jones
    }
988
989 730 bojilova
    return trees;
990 504 jones
  }
991
992
  /**
993 730 bojilova
   * Get all groups and users from authentication scheme.
994 725 bojilova
   * The output is formatted in XML.
995 730 bojilova
   * @param user the user which requests the information
996
   * @param password the user's password
997 725 bojilova
   */
998 2121 sgarg
  public String getPrincipals(String user, String password) throws
999
      ConnectException {
1000 725 bojilova
    StringBuffer out = new StringBuffer();
1001 2559 sgarg
1002 2058 sgarg
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
1003 730 bojilova
    out.append("<principals>\n");
1004 2058 sgarg
1005 730 bojilova
    /*
1006 2058 sgarg
     * get all subtrees first in the current dir context
1007 730 bojilova
     * and then the Metacat users under them
1008
     */
1009 2121 sgarg
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
1010
                                     this.ldapBase);
1011 2058 sgarg
1012 2447 sgarg
    Enumeration keyEnum = subtrees.keys();
1013
    while (keyEnum.hasMoreElements()) {
1014
      this.ldapBase = (String) keyEnum.nextElement();
1015 2121 sgarg
      this.ldapUrl = (String) subtrees.get(ldapBase);
1016 2058 sgarg
1017 2129 sgarg
      /*
1018
       * code to get the organization name from ldapBase
1019
       */
1020 2116 sgarg
      String orgName = this.ldapBase;
1021 2130 sgarg
      if (orgName.startsWith("[")) {
1022 2129 sgarg
        // if orgName starts with [ then it is a referral URL...
1023
        // (see code in getSubtress)
1024
        // hence orgName can be retrieved  by getting the string between
1025
        // 'o=' and ']'
1026
        // also the string between [ and ] needs to be striped out from
1027
        // this.ldapBase
1028
        this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1029
        if (orgName != null && orgName.indexOf("o=") > -1) {
1030
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1031
          orgName = orgName.substring(0, orgName.indexOf("]"));
1032
        }
1033 2130 sgarg
      }
1034
      else {
1035 2129 sgarg
        // else it is not referral
1036
        // hence orgName can be retrieved  by getting the string between
1037
        // 'o=' and ','
1038
        if (orgName != null && orgName.indexOf("o=") > -1) {
1039
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1040
          if (orgName.indexOf(",") > -1) {
1041
            orgName = orgName.substring(0, orgName.indexOf(","));
1042
          }
1043
        }
1044 2121 sgarg
      }
1045
1046 2058 sgarg
      out.append("  <authSystem URI=\"" +
1047 2121 sgarg
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
1048
                 "\">\n");
1049 730 bojilova
1050
      // get all groups for directory context
1051 2058 sgarg
      String[][] groups = getGroups(user, password);
1052
      String[][] users = getUsers(user, password);
1053
      int userIndex = 0;
1054 730 bojilova
1055
      // for the groups and users that belong to them
1056 2121 sgarg
      if (groups != null && groups.length > 0) {
1057
        for (int i = 0; i < groups.length; i++) {
1058 730 bojilova
          out.append("    <group>\n");
1059 2058 sgarg
          out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1060
          out.append("      <description>" + groups[i][1] + "</description>\n");
1061 2121 sgarg
          String[] usersForGroup = getUsers(user, password, groups[i][0]);
1062
          for (int j = 0; j < usersForGroup.length; j++) {
1063 2559 sgarg
1064 2058 sgarg
            userIndex = searchUser(usersForGroup[j], users);
1065 730 bojilova
            out.append("      <user>\n");
1066 2058 sgarg
1067 2121 sgarg
            if (userIndex < 0) {
1068 2095 sgarg
              out.append("        <username>" + usersForGroup[j] +
1069
                         "</username>\n");
1070 2121 sgarg
            }
1071
            else {
1072 2130 sgarg
              out.append("        <username>" + users[userIndex][0] +
1073 2121 sgarg
                         "</username>\n");
1074 2130 sgarg
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1075
              out.append("        <organization>" + users[userIndex][2] +
1076 2121 sgarg
                         "</organization>\n");
1077 2130 sgarg
              if (users[userIndex][3].compareTo("null") != 0) {
1078
                out.append("      <organizationUnitName>" + users[userIndex][3] +
1079
                           "</organizationUnitName>\n");
1080
              }
1081
              out.append("        <email>" + users[userIndex][4] + "</email>\n");
1082 2058 sgarg
            }
1083
1084 730 bojilova
            out.append("      </user>\n");
1085
          }
1086
          out.append("    </group>\n");
1087
        }
1088
      }
1089 2058 sgarg
1090 2130 sgarg
      // for the users not belonging to any grou8p
1091 2121 sgarg
      for (int j = 0; j < users.length; j++) {
1092 725 bojilova
          out.append("    <user>\n");
1093 2058 sgarg
          out.append("      <username>" + users[j][0] + "</username>\n");
1094
          out.append("      <name>" + users[j][1] + "</name>\n");
1095 2130 sgarg
          out.append("      <organization>" + users[j][2] +
1096
                     "</organization>\n");
1097
          if (users[j][3].compareTo("null") != 0) {
1098
            out.append("      <organizationUnitName>" + users[j][3] +
1099
                       "</organizationUnitName>\n");
1100
          }
1101
          out.append("      <email>" + users[j][4] + "</email>\n");
1102 725 bojilova
          out.append("    </user>\n");
1103
      }
1104 2058 sgarg
1105 730 bojilova
      out.append("  </authSystem>\n");
1106 725 bojilova
    }
1107
    out.append("</principals>");
1108
    return out.toString();
1109
  }
1110
1111
  /**
1112 2058 sgarg
   * Method for getting index of user DN in User info array
1113
   */
1114 2121 sgarg
  int searchUser(String user, String userGroup[][]) {
1115
    for (int j = 0; j < userGroup.length; j++) {
1116
      if (user.compareTo(userGroup[j][0]) == 0) {
1117 2058 sgarg
        return j;
1118
      }
1119
    }
1120
    return -1;
1121
  }
1122
1123
  /**
1124 503 bojilova
   * Test method for the class
1125
   */
1126
  public static void main(String[] args) {
1127
1128 504 jones
    // Provide a user, such as: "Matt Jones", or "jones"
1129 503 bojilova
    String user = args[0];
1130
    String password = args[1];
1131
1132 2666 sgarg
    logMetacat.warn("Creating session...");
1133 503 bojilova
    AuthLdap authservice = new AuthLdap();
1134 2666 sgarg
    logMetacat.warn("Session exists...");
1135 2058 sgarg
1136 503 bojilova
    boolean isValid = false;
1137
    try {
1138 2666 sgarg
      logMetacat.warn("Authenticating...");
1139 503 bojilova
      isValid = authservice.authenticate(user, password);
1140
      if (isValid) {
1141 2666 sgarg
    	  logMetacat.warn("Authentication successful for: " + user);
1142 2121 sgarg
      }
1143
      else {
1144 2666 sgarg
        logMetacat.warn("Authentication failed for: " + user);
1145 503 bojilova
      }
1146 725 bojilova
1147 871 jones
      // Get attributes for the user
1148 503 bojilova
      if (isValid) {
1149 2666 sgarg
        logMetacat.info("\nGetting attributes for user....");
1150 991 tao
        HashMap userInfo = authservice.getAttributes(user, password, user);
1151 503 bojilova
        // Print all of the attributes
1152 2121 sgarg
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1153 503 bojilova
        while (attList.hasNext()) {
1154 2121 sgarg
          String att = (String) attList.next();
1155
          Vector values = (Vector) userInfo.get(att);
1156 503 bojilova
          Iterator attvalues = values.iterator();
1157
          while (attvalues.hasNext()) {
1158 2121 sgarg
            String value = (String) attvalues.next();
1159 2666 sgarg
            logMetacat.warn(att + ": " + value);
1160 503 bojilova
          }
1161
        }
1162 871 jones
      }
1163 723 bojilova
1164 871 jones
      // get the groups
1165
      if (isValid) {
1166 2666 sgarg
        logMetacat.warn("\nGetting all groups....");
1167 2058 sgarg
        String[][] groups = authservice.getGroups(user, password);
1168 2666 sgarg
        logMetacat.info("Groups found: " + groups.length);
1169 2121 sgarg
        for (int i = 0; i < groups.length; i++) {
1170 2666 sgarg
          logMetacat.info("Group " + i + ": " + groups[i][0]);
1171 871 jones
        }
1172 503 bojilova
      }
1173 725 bojilova
1174 871 jones
      // get the groups for the user
1175
      String savedGroup = null;
1176
      if (isValid) {
1177 2666 sgarg
        logMetacat.warn("\nGetting groups for user....");
1178 2058 sgarg
        String[][] groups = authservice.getGroups(user, password, user);
1179 2666 sgarg
        logMetacat.info("Groups found: " + groups.length);
1180 2121 sgarg
        for (int i = 0; i < groups.length; i++) {
1181 2666 sgarg
          logMetacat.info("Group " + i + ": " + groups[i][0]);
1182 2121 sgarg
          savedGroup = groups[i][0];
1183 871 jones
        }
1184
      }
1185
1186
      // get the users for a group
1187
      if (isValid) {
1188 2666 sgarg
        logMetacat.warn("\nGetting users for group....");
1189
        logMetacat.info("Group: " + savedGroup);
1190 871 jones
        String[] users = authservice.getUsers(user, password, savedGroup);
1191 2666 sgarg
        logMetacat.info("Users found: " + users.length);
1192 2121 sgarg
        for (int i = 0; i < users.length; i++) {
1193 2666 sgarg
          logMetacat.warn("User " + i + ": " + users[i]);
1194 871 jones
        }
1195
      }
1196
1197
      // get all users
1198
      if (isValid) {
1199 2666 sgarg
        logMetacat.warn("\nGetting all users ....");
1200 2058 sgarg
        String[][] users = authservice.getUsers(user, password);
1201 2666 sgarg
        logMetacat.info("Users found: " + users.length);
1202 2058 sgarg
1203 871 jones
      }
1204 873 jones
1205 726 bojilova
      // get the whole list groups and users in XML format
1206 725 bojilova
      if (isValid) {
1207 2666 sgarg
        logMetacat.warn("\nTrying principals....");
1208 730 bojilova
        authservice = new AuthLdap();
1209 725 bojilova
        String out = authservice.getPrincipals(user, password);
1210 802 bojilova
        java.io.File f = new java.io.File("principals.xml");
1211 725 bojilova
        java.io.FileWriter fw = new java.io.FileWriter(f);
1212
        java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1213
        buff.write(out);
1214
        buff.flush();
1215
        buff.close();
1216
        fw.close();
1217 2666 sgarg
        logMetacat.warn("\nFinished getting principals.");
1218 725 bojilova
      }
1219 873 jones
1220 2121 sgarg
    }
1221
    catch (ConnectException ce) {
1222 2666 sgarg
      logMetacat.error(ce.getMessage());
1223 2121 sgarg
    }
1224
    catch (java.io.IOException ioe) {
1225 2666 sgarg
      logMetacat.error("I/O Error writing to file principals.txt");
1226 503 bojilova
    }
1227
  }
1228 2058 sgarg
1229 934 tao
  /**
1230
   * This method will be called by start a thread.
1231
   * It can handle if a referral exception happend.
1232 2058 sgarg
   */
1233 2121 sgarg
  public void run() {
1234 893 berkley
    referralContext = null;
1235 2121 sgarg
    DirContext refDirContext = null;
1236
    boolean moreReferrals = true;
1237
    String referralInfo = null;
1238 934 tao
    //set a while loop is because we don't know if a referral excption contains
1239
    //another referral exception
1240 2121 sgarg
    while (moreReferrals) {
1241
      try {
1242 934 tao
        //revise environment variable
1243 2121 sgarg
        referralInfo = (String) refExc.getReferralInfo();
1244 2666 sgarg
        logMetacat.info("Processing referral (pr0): ");
1245
        logMetacat.info("PROVIDER_URL set to (pr1): " + referralInfo);
1246 1988 jones
        //env.put(Context.PROVIDER_URL,referralInfo);
1247
        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1248
        //env.put(Context.SECURITY_PRINCIPAL, userName);
1249
        //env.put(Context.SECURITY_CREDENTIALS, userPassword);
1250
        //env.put(Context.REFERRAL, "throw");
1251 2666 sgarg
        //logMetacat.info("Processing referral (pr1.info): " + userName,35);
1252
        //logMetacat.info("Processing referral (pr2)",35);
1253 1988 jones
        //rContext = refExc.getReferralContext(env);
1254
        rContext = refExc.getReferralContext();
1255 2666 sgarg
        logMetacat.info("Processing referral (pr3)");
1256 934 tao
        //casting the context to dircontext and it will create a
1257
        //autherntication or naming exception if DN and password is incorrect
1258 2121 sgarg
        referralContext = rContext;
1259
        refDirContext = (DirContext) rContext;
1260 991 tao
        refDirContext.close();
1261 934 tao
        //get context and jump out the while loop
1262 2121 sgarg
        moreReferrals = false;
1263 2666 sgarg
        logMetacat.info("Processing referral (pr4)");
1264 2121 sgarg
      } //try
1265 991 tao
      //if referral have another referral excption
1266 2121 sgarg
      catch (ReferralException re) {
1267 2666 sgarg
        logMetacat.warn("GOT referral exception (re1): " + re.getMessage());
1268
        logMetacat.warn("RE details (re2): " + re.toString(true));
1269 934 tao
        //keep running in while loop
1270 2121 sgarg
        moreReferrals = true;
1271 934 tao
        //assign refExc to new referral exception re
1272 2121 sgarg
        refExc = re;
1273 934 tao
      }
1274 991 tao
      //catch a authentication exception
1275 2121 sgarg
      catch (AuthenticationException ae) {
1276 2666 sgarg
        logMetacat.error("Error running referral handler thread (ae1): " +
1277 2589 sgarg
                          ae.getMessage());
1278 934 tao
        //check if has another referral
1279 2121 sgarg
        moreReferrals = refExc.skipReferral();
1280 934 tao
        //don't get the context
1281
        referralContext = null;
1282
      }
1283 991 tao
      //catch a naming exception
1284 2121 sgarg
      catch (NamingException ne) {
1285 2666 sgarg
        logMetacat.error("Error running referral handler thread (ne1): " +
1286 2589 sgarg
                          ne.getMessage());
1287 934 tao
        //check if has another referral
1288 2121 sgarg
        moreReferrals = refExc.skipReferral();
1289 934 tao
        //don't get context
1290 2058 sgarg
        referralContext = null;
1291 934 tao
      }
1292 2121 sgarg
    } //while
1293
  } //run()
1294 2058 sgarg
1295 2121 sgarg
  private class GetGroup
1296
      implements Runnable {
1297
    public void run() {
1298 991 tao
      referralContext = null;
1299 2666 sgarg
      logMetacat.info("getting groups context");
1300 2121 sgarg
      DirContext refDirContext = null;
1301
      boolean moreReferrals = true;
1302 2058 sgarg
      //set a while loop is because we don't know if a referral excption
1303 991 tao
      //contains another referral exception
1304 2121 sgarg
      while (moreReferrals) {
1305
        try {
1306 991 tao
          //revise environment variable
1307
          String refInfo = null;
1308 2121 sgarg
          refInfo = (String) refExc.getReferralInfo();
1309
          if (refInfo != null) {
1310 2666 sgarg
            logMetacat.info("Referral in thread to: " +
1311 2589 sgarg
                                     refInfo.toString());
1312 991 tao
          }
1313 2121 sgarg
          else {
1314 2666 sgarg
            logMetacat.info("getting refInfo Manually");
1315 2121 sgarg
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1316
                get(Context.PROVIDER_URL);
1317 991 tao
          }
1318 2666 sgarg
          logMetacat.info("refInfo: " + refInfo);
1319 2058 sgarg
1320
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1321 2121 sgarg
                  "com.sun.jndi.ldap.LdapCtxFactory");
1322 991 tao
          env.put(Context.REFERRAL, "throw");
1323
          env.put(Context.PROVIDER_URL, refInfo);
1324 2058 sgarg
1325 2666 sgarg
          logMetacat.info("creating referralContext");
1326 991 tao
          referralContext = new InitialDirContext(env);
1327 2666 sgarg
          logMetacat.info("referralContext created");
1328 991 tao
          //get context and jump out the while loop
1329 2121 sgarg
          moreReferrals = false;
1330
        } //try
1331
        catch (ReferralException re) {
1332 991 tao
          //keep running in while loop
1333 2121 sgarg
          moreReferrals = true;
1334 991 tao
          //assign refExc to new referral exception re
1335 2121 sgarg
          refExc = re;
1336 991 tao
        }
1337 2121 sgarg
        catch (AuthenticationException ae) {
1338 2666 sgarg
          logMetacat.error("Error running referral handler thread (ae2): " +
1339 2589 sgarg
                            ae.getMessage());
1340 991 tao
          //check if has another referral
1341 2121 sgarg
          moreReferrals = refExc.skipReferral();
1342 991 tao
          //don't get the context
1343
          referralContext = null;
1344
        }
1345 2121 sgarg
        catch (NamingException ne) {
1346 2666 sgarg
          logMetacat.error("Error running referral handler thread (ne2): " +
1347 2589 sgarg
                            ne.getMessage());
1348 991 tao
          //check if has another referral
1349 2121 sgarg
          moreReferrals = refExc.skipReferral();
1350 991 tao
          //don't get context
1351 2058 sgarg
          referralContext = null;
1352 991 tao
        }
1353 2121 sgarg
      } //while
1354
    } //run()
1355
  }
1356 503 bojilova
}