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