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
      NamingEnumeration enum = 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
        while (enum.hasMore()) {
463
          SearchResult sr = (SearchResult) enum.next();
464
          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
      NamingEnumeration enum = ctx.search(ldapBase, filter, ctls);
650 991 tao
651 2121 sgarg
      // Print the groups
652
      MetaCatUtil.debugMessage("getting group results.", 50);
653
      while (enum.hasMore()) {
654
        SearchResult sr = (SearchResult) enum.next();
655
        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 991 tao
        NamingEnumeration enum = dc.search(ldapBase, filter, ctls);
720
        // Print the groups
721
        while (enum.hasMore()) {
722 2121 sgarg
          SearchResult sr = (SearchResult) enum.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
      NamingEnumeration enum = ctx.search("", filter, ctls);
875 730 bojilova
876 2121 sgarg
      // Print the subtrees' <ldapURL, baseDN>
877
      while (enum.hasMore()) {
878
879
        SearchResult sr = (SearchResult) enum.next();
880
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 726 bojilova
    Vector usersIn = new Vector();
954 2058 sgarg
955
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
956 730 bojilova
    out.append("<principals>\n");
957 2058 sgarg
958 730 bojilova
    /*
959 2058 sgarg
     * get all subtrees first in the current dir context
960 730 bojilova
     * and then the Metacat users under them
961
     */
962 2121 sgarg
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
963
                                     this.ldapBase);
964 2058 sgarg
965 730 bojilova
    Enumeration enum = subtrees.keys();
966 2121 sgarg
    while (enum.hasMoreElements()) {
967
      this.ldapBase = (String) enum.nextElement();
968
      this.ldapUrl = (String) subtrees.get(ldapBase);
969 2058 sgarg
970 2129 sgarg
      /*
971
       * code to get the organization name from ldapBase
972
       */
973 2116 sgarg
      String orgName = this.ldapBase;
974 2130 sgarg
      if (orgName.startsWith("[")) {
975 2129 sgarg
        // if orgName starts with [ then it is a referral URL...
976
        // (see code in getSubtress)
977
        // hence orgName can be retrieved  by getting the string between
978
        // 'o=' and ']'
979
        // also the string between [ and ] needs to be striped out from
980
        // this.ldapBase
981
        this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
982
        if (orgName != null && orgName.indexOf("o=") > -1) {
983
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
984
          orgName = orgName.substring(0, orgName.indexOf("]"));
985
        }
986 2130 sgarg
      }
987
      else {
988 2129 sgarg
        // else it is not referral
989
        // hence orgName can be retrieved  by getting the string between
990
        // 'o=' and ','
991
        if (orgName != null && orgName.indexOf("o=") > -1) {
992
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
993
          if (orgName.indexOf(",") > -1) {
994
            orgName = orgName.substring(0, orgName.indexOf(","));
995
          }
996
        }
997 2121 sgarg
      }
998
999 2058 sgarg
      out.append("  <authSystem URI=\"" +
1000 2121 sgarg
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
1001
                 "\">\n");
1002 730 bojilova
1003
      // get all groups for directory context
1004 2058 sgarg
      String[][] groups = getGroups(user, password);
1005
      String[][] users = getUsers(user, password);
1006
      int userIndex = 0;
1007 730 bojilova
1008
      // for the groups and users that belong to them
1009 2121 sgarg
      if (groups != null && groups.length > 0) {
1010
        for (int i = 0; i < groups.length; i++) {
1011 730 bojilova
          out.append("    <group>\n");
1012 2058 sgarg
          out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1013
          out.append("      <description>" + groups[i][1] + "</description>\n");
1014 2121 sgarg
          String[] usersForGroup = getUsers(user, password, groups[i][0]);
1015
          for (int j = 0; j < usersForGroup.length; j++) {
1016 730 bojilova
            usersIn.addElement(usersForGroup[j]);
1017 2058 sgarg
1018
            userIndex = searchUser(usersForGroup[j], users);
1019 730 bojilova
            out.append("      <user>\n");
1020 2058 sgarg
1021 2121 sgarg
            if (userIndex < 0) {
1022 2095 sgarg
              out.append("        <username>" + usersForGroup[j] +
1023
                         "</username>\n");
1024 2121 sgarg
            }
1025
            else {
1026 2130 sgarg
              out.append("        <username>" + users[userIndex][0] +
1027 2121 sgarg
                         "</username>\n");
1028 2130 sgarg
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1029
              out.append("        <organization>" + users[userIndex][2] +
1030 2121 sgarg
                         "</organization>\n");
1031 2130 sgarg
              if (users[userIndex][3].compareTo("null") != 0) {
1032
                out.append("      <organizationUnitName>" + users[userIndex][3] +
1033
                           "</organizationUnitName>\n");
1034
              }
1035
              out.append("        <email>" + users[userIndex][4] + "</email>\n");
1036 2058 sgarg
            }
1037
1038 730 bojilova
            out.append("      </user>\n");
1039
          }
1040
          out.append("    </group>\n");
1041
        }
1042
      }
1043 2058 sgarg
1044 2130 sgarg
      // for the users not belonging to any grou8p
1045 2121 sgarg
      for (int j = 0; j < users.length; j++) {
1046
        if (!usersIn.contains(users[j][0])) {
1047 725 bojilova
          out.append("    <user>\n");
1048 2058 sgarg
          out.append("      <username>" + users[j][0] + "</username>\n");
1049
          out.append("      <name>" + users[j][1] + "</name>\n");
1050 2130 sgarg
          out.append("      <organization>" + users[j][2] +
1051
                     "</organization>\n");
1052
          if (users[j][3].compareTo("null") != 0) {
1053
            out.append("      <organizationUnitName>" + users[j][3] +
1054
                       "</organizationUnitName>\n");
1055
          }
1056
          out.append("      <email>" + users[j][4] + "</email>\n");
1057 725 bojilova
          out.append("    </user>\n");
1058
        }
1059
      }
1060 2058 sgarg
1061 730 bojilova
      out.append("  </authSystem>\n");
1062 2121 sgarg
      if (!usersIn.isEmpty()) {
1063 730 bojilova
        usersIn.removeAllElements();
1064
        usersIn.trimToSize();
1065 725 bojilova
      }
1066 2058 sgarg
1067 725 bojilova
    }
1068
    out.append("</principals>");
1069
    return out.toString();
1070
  }
1071
1072
  /**
1073 2058 sgarg
   * Method for getting index of user DN in User info array
1074
   */
1075 2121 sgarg
  int searchUser(String user, String userGroup[][]) {
1076
    for (int j = 0; j < userGroup.length; j++) {
1077
      if (user.compareTo(userGroup[j][0]) == 0) {
1078 2058 sgarg
        return j;
1079
      }
1080
    }
1081
    return -1;
1082
  }
1083
1084
  /**
1085 503 bojilova
   * Test method for the class
1086
   */
1087
  public static void main(String[] args) {
1088
1089 504 jones
    // Provide a user, such as: "Matt Jones", or "jones"
1090 503 bojilova
    String user = args[0];
1091
    String password = args[1];
1092
1093 1477 tao
    MetaCatUtil.debugMessage("Creating session...", 20);
1094 503 bojilova
    AuthLdap authservice = new AuthLdap();
1095 1477 tao
    MetaCatUtil.debugMessage("Session exists...", 20);
1096 2058 sgarg
1097 503 bojilova
    boolean isValid = false;
1098
    try {
1099 1477 tao
      MetaCatUtil.debugMessage("Authenticating...", 20);
1100 503 bojilova
      isValid = authservice.authenticate(user, password);
1101
      if (isValid) {
1102 2121 sgarg
        MetaCatUtil.debugMessage("Authentication successful for: " + user, 20);
1103
      }
1104
      else {
1105 1477 tao
        MetaCatUtil.debugMessage("Authentication failed for: " + user, 20);
1106 503 bojilova
      }
1107 725 bojilova
1108 871 jones
      // Get attributes for the user
1109 503 bojilova
      if (isValid) {
1110 1477 tao
        MetaCatUtil.debugMessage("\nGetting attributes for user....", 20);
1111 991 tao
        HashMap userInfo = authservice.getAttributes(user, password, user);
1112 503 bojilova
        // Print all of the attributes
1113 2121 sgarg
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1114 503 bojilova
        while (attList.hasNext()) {
1115 2121 sgarg
          String att = (String) attList.next();
1116
          Vector values = (Vector) userInfo.get(att);
1117 503 bojilova
          Iterator attvalues = values.iterator();
1118
          while (attvalues.hasNext()) {
1119 2121 sgarg
            String value = (String) attvalues.next();
1120 1477 tao
            MetaCatUtil.debugMessage(att + ": " + value, 20);
1121 503 bojilova
          }
1122
        }
1123 871 jones
      }
1124 723 bojilova
1125 871 jones
      // get the groups
1126
      if (isValid) {
1127 1477 tao
        MetaCatUtil.debugMessage("\nGetting all groups....", 20);
1128 2058 sgarg
        String[][] groups = authservice.getGroups(user, password);
1129 1477 tao
        MetaCatUtil.debugMessage("Groups found: " + groups.length, 20);
1130 2121 sgarg
        for (int i = 0; i < groups.length; i++) {
1131
          MetaCatUtil.debugMessage("Group " + i + ": " + groups[i][0], 20);
1132 871 jones
        }
1133 503 bojilova
      }
1134 725 bojilova
1135 871 jones
      // get the groups for the user
1136
      String savedGroup = null;
1137
      if (isValid) {
1138 1477 tao
        MetaCatUtil.debugMessage("\nGetting groups for user....", 20);
1139 2058 sgarg
        String[][] groups = authservice.getGroups(user, password, user);
1140 1477 tao
        MetaCatUtil.debugMessage("Groups found: " + groups.length, 20);
1141 2121 sgarg
        for (int i = 0; i < groups.length; i++) {
1142
          MetaCatUtil.debugMessage("Group " + i + ": " + groups[i][0], 20);
1143
          savedGroup = groups[i][0];
1144 871 jones
        }
1145
      }
1146
1147
      // get the users for a group
1148
      if (isValid) {
1149 1477 tao
        MetaCatUtil.debugMessage("\nGetting users for group....", 20);
1150
        MetaCatUtil.debugMessage("Group: " + savedGroup, 20);
1151 871 jones
        String[] users = authservice.getUsers(user, password, savedGroup);
1152 1477 tao
        MetaCatUtil.debugMessage("Users found: " + users.length, 20);
1153 2121 sgarg
        for (int i = 0; i < users.length; i++) {
1154
          MetaCatUtil.debugMessage("User " + i + ": " + users[i], 20);
1155 871 jones
        }
1156
      }
1157
1158
      // get all users
1159
      if (isValid) {
1160 1494 tao
        MetaCatUtil.debugMessage("\nGetting all users ....", 20);
1161 2058 sgarg
        String[][] users = authservice.getUsers(user, password);
1162 1494 tao
        MetaCatUtil.debugMessage("Users found: " + users.length, 20);
1163 2058 sgarg
1164 871 jones
      }
1165 873 jones
1166 726 bojilova
      // get the whole list groups and users in XML format
1167 725 bojilova
      if (isValid) {
1168 1494 tao
        MetaCatUtil.debugMessage("\nTrying principals....", 20);
1169 730 bojilova
        authservice = new AuthLdap();
1170 725 bojilova
        String out = authservice.getPrincipals(user, password);
1171 802 bojilova
        java.io.File f = new java.io.File("principals.xml");
1172 725 bojilova
        java.io.FileWriter fw = new java.io.FileWriter(f);
1173
        java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1174
        buff.write(out);
1175
        buff.flush();
1176
        buff.close();
1177
        fw.close();
1178 1494 tao
        MetaCatUtil.debugMessage("\nFinished getting principals.", 20);
1179 725 bojilova
      }
1180 873 jones
1181 2121 sgarg
    }
1182
    catch (ConnectException ce) {
1183 1494 tao
      MetaCatUtil.debugMessage(ce.getMessage(), 30);
1184 2121 sgarg
    }
1185
    catch (java.io.IOException ioe) {
1186 1494 tao
      MetaCatUtil.debugMessage("I/O Error writing to file principals.txt", 20);
1187 503 bojilova
    }
1188
  }
1189 2058 sgarg
1190 934 tao
  /**
1191
   * This method will be called by start a thread.
1192
   * It can handle if a referral exception happend.
1193 2058 sgarg
   */
1194 2121 sgarg
  public void run() {
1195 893 berkley
    referralContext = null;
1196 2121 sgarg
    DirContext refDirContext = null;
1197
    boolean moreReferrals = true;
1198
    String referralInfo = null;
1199 934 tao
    //set a while loop is because we don't know if a referral excption contains
1200
    //another referral exception
1201 2121 sgarg
    while (moreReferrals) {
1202
      try {
1203 934 tao
        //revise environment variable
1204 2121 sgarg
        referralInfo = (String) refExc.getReferralInfo();
1205 1988 jones
        util.debugMessage("Processing referral (pr0): ", 35);
1206
        util.debugMessage("PROVIDER_URL set to (pr1): " + referralInfo, 35);
1207
        //env.put(Context.PROVIDER_URL,referralInfo);
1208
        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1209
        //env.put(Context.SECURITY_PRINCIPAL, userName);
1210
        //env.put(Context.SECURITY_CREDENTIALS, userPassword);
1211
        //env.put(Context.REFERRAL, "throw");
1212
        //util.debugMessage("Processing referral (pr1.info): " + userName,35);
1213
        //util.debugMessage("Processing referral (pr2)",35);
1214
        //rContext = refExc.getReferralContext(env);
1215
        rContext = refExc.getReferralContext();
1216 2121 sgarg
        util.debugMessage("Processing referral (pr3)", 35);
1217 934 tao
        //casting the context to dircontext and it will create a
1218
        //autherntication or naming exception if DN and password is incorrect
1219 2121 sgarg
        referralContext = rContext;
1220
        refDirContext = (DirContext) rContext;
1221 991 tao
        refDirContext.close();
1222 934 tao
        //get context and jump out the while loop
1223 2121 sgarg
        moreReferrals = false;
1224
        util.debugMessage("Processing referral (pr4)", 35);
1225
      } //try
1226 991 tao
      //if referral have another referral excption
1227 2121 sgarg
      catch (ReferralException re) {
1228
        util.debugMessage("GOT referral exception (re1): " + re.getMessage(),
1229
                          35);
1230
        util.debugMessage("RE details (re2): " + re.toString(true), 35);
1231 934 tao
        //keep running in while loop
1232 2121 sgarg
        moreReferrals = true;
1233 934 tao
        //assign refExc to new referral exception re
1234 2121 sgarg
        refExc = re;
1235 934 tao
      }
1236 991 tao
      //catch a authentication exception
1237 2121 sgarg
      catch (AuthenticationException ae) {
1238 2058 sgarg
        util.debugMessage("Error running referral handler thread (ae1): " +
1239 1494 tao
                          ae.getMessage(), 20);
1240 934 tao
        //check if has another referral
1241 2121 sgarg
        moreReferrals = refExc.skipReferral();
1242 934 tao
        //don't get the context
1243
        referralContext = null;
1244
      }
1245 991 tao
      //catch a naming exception
1246 2121 sgarg
      catch (NamingException ne) {
1247 2058 sgarg
        util.debugMessage("Error running referral handler thread (ne1): " +
1248 1494 tao
                          ne.getMessage(), 20);
1249 934 tao
        //check if has another referral
1250 2121 sgarg
        moreReferrals = refExc.skipReferral();
1251 934 tao
        //don't get context
1252 2058 sgarg
        referralContext = null;
1253 934 tao
      }
1254 2121 sgarg
    } //while
1255
  } //run()
1256 2058 sgarg
1257 2121 sgarg
  private class GetGroup
1258
      implements Runnable {
1259
    public void run() {
1260 991 tao
      referralContext = null;
1261 1494 tao
      MetaCatUtil.debugMessage("getting groups context", 50);
1262 2121 sgarg
      DirContext refDirContext = null;
1263
      boolean moreReferrals = true;
1264 2058 sgarg
      //set a while loop is because we don't know if a referral excption
1265 991 tao
      //contains another referral exception
1266 2121 sgarg
      while (moreReferrals) {
1267
        try {
1268 991 tao
          //revise environment variable
1269
          String refInfo = null;
1270 2121 sgarg
          refInfo = (String) refExc.getReferralInfo();
1271
          if (refInfo != null) {
1272 2058 sgarg
            MetaCatUtil.debugMessage("Referral in thread to: " +
1273 2121 sgarg
                                     refInfo.toString(), 40);
1274 991 tao
          }
1275 2121 sgarg
          else {
1276 1494 tao
            MetaCatUtil.debugMessage("getting refInfo Manually", 50);
1277 2121 sgarg
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1278
                get(Context.PROVIDER_URL);
1279 991 tao
          }
1280 1494 tao
          MetaCatUtil.debugMessage("refInfo: " + refInfo, 40);
1281 2058 sgarg
1282
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1283 2121 sgarg
                  "com.sun.jndi.ldap.LdapCtxFactory");
1284 991 tao
          env.put(Context.REFERRAL, "throw");
1285
          env.put(Context.PROVIDER_URL, refInfo);
1286 2058 sgarg
1287 1494 tao
          MetaCatUtil.debugMessage("creating referralContext", 40);
1288 991 tao
          referralContext = new InitialDirContext(env);
1289 1494 tao
          MetaCatUtil.debugMessage("referralContext created", 40);
1290 991 tao
          //get context and jump out the while loop
1291 2121 sgarg
          moreReferrals = false;
1292
        } //try
1293
        catch (ReferralException re) {
1294 991 tao
          //keep running in while loop
1295 2121 sgarg
          moreReferrals = true;
1296 991 tao
          //assign refExc to new referral exception re
1297 2121 sgarg
          refExc = re;
1298 991 tao
        }
1299 2121 sgarg
        catch (AuthenticationException ae) {
1300 2058 sgarg
          util.debugMessage("Error running referral handler thread (ae2): " +
1301 2121 sgarg
                            ae.getMessage(), 50);
1302 991 tao
          //check if has another referral
1303 2121 sgarg
          moreReferrals = refExc.skipReferral();
1304 991 tao
          //don't get the context
1305
          referralContext = null;
1306
        }
1307 2121 sgarg
        catch (NamingException ne) {
1308 2058 sgarg
          util.debugMessage("Error running referral handler thread (ne2): " +
1309 2121 sgarg
                            ne.getMessage(), 50);
1310 991 tao
          //check if has another referral
1311 2121 sgarg
          moreReferrals = refExc.skipReferral();
1312 991 tao
          //don't get context
1313 2058 sgarg
          referralContext = null;
1314 991 tao
        }
1315 2121 sgarg
      } //while
1316
    } //run()
1317
  }
1318 503 bojilova
}