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