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