Project

General

Profile

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