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 2589 sgarg
        MetaCatUtil.logMetacat.info("Looking up DN for: " + identifier);
114 2121 sgarg
        identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
115 2589 sgarg
        MetaCatUtil.logMetacat.info("DN found: " + identifier);
116 2121 sgarg
        String decoded = URLDecoder.decode(identifier);
117 2589 sgarg
        MetaCatUtil.logMetacat.info("DN decoded: " + decoded);
118 2121 sgarg
        identifier = decoded;
119
        String refUrl = "";
120
        String refBase = "";
121
        if (identifier.startsWith("ldap")) {
122
          refUrl = identifier.substring(0,
123
                                        identifier.lastIndexOf("/") + 1);
124 2589 sgarg
          MetaCatUtil.logMetacat.info("Ref ldapUrl: " + refUrl);
125 2121 sgarg
          int position = identifier.indexOf(",");
126
          int position2 = identifier.indexOf(",", position + 1);
127
          refBase = identifier.substring(position2 + 1);
128 2589 sgarg
          MetaCatUtil.logMetacat.info("Ref ldapBase: " + refBase);
129 2121 sgarg
          identifier = identifier.substring(
130
              identifier.lastIndexOf("/") + 1);
131 2589 sgarg
          MetaCatUtil.logMetacat.info("Trying: " + identifier);
132 2121 sgarg
          authenticated = ldapAuthenticate(identifier, password,
133
                                           refUrl, refBase);
134 1004 tao
        }
135 2121 sgarg
        else {
136
          identifier = identifier + "," + ldapBase;
137 2589 sgarg
          MetaCatUtil.logMetacat.info("Trying: " + identifier);
138 2121 sgarg
          authenticated = ldapAuthenticate(identifier, password);
139
        }
140
        //authenticated = ldapAuthenticate(identifier, password);
141
      }
142 2058 sgarg
143 2121 sgarg
    }
144
    catch (NullPointerException e) {
145 2589 sgarg
      MetaCatUtil.logMetacat.info("NullPointerException b' password is null");
146
      MetaCatUtil.logMetacat.info("NullPointerException while authenticating in " +
147
                        "AuthLdap.authenticate: " + e);
148 740 bojilova
      throw new ConnectException(
149 2121 sgarg
          "NullPointerException while authenticating in " +
150
          "AuthLdap.authenticate: " + e);
151
    }
152
    catch (NamingException e) {
153 2589 sgarg
      MetaCatUtil.logMetacat.info("Naming exception while authenticating in " +
154
                        "AuthLdap.authenticate: " + e);
155 852 jones
      e.printStackTrace();
156 2121 sgarg
    }
157
    catch (Exception e) {
158 2589 sgarg
      MetaCatUtil.logMetacat.info(e.getMessage());
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 2589 sgarg
      MetaCatUtil.logMetacat.info("PROVIDER_URL set to: " + directoryUrl + searchBase);
200 2121 sgarg
      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 2589 sgarg
        MetaCatUtil.logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
216
                          (stopTime - startTime) / 1000 + " seconds.");
217 2121 sgarg
        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 2589 sgarg
        MetaCatUtil.logMetacat.info("An invalid DN was provided!");
232 2121 sgarg
      }
233
      catch (javax.naming.ReferralException re) {
234 2589 sgarg
        MetaCatUtil.logMetacat.info("referral during authentication");
235
        MetaCatUtil.logMetacat.info("Referral information: " + re.getReferralInfo());
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 2589 sgarg
          MetaCatUtil.logMetacat.info("Awake after 5 seconds.");
244 2121 sgarg
          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 2589 sgarg
      MetaCatUtil.logMetacat.info("User not found");
259 2121 sgarg
    }
260 867 berkley
    double totStopTime = System.currentTimeMillis();
261 2589 sgarg
    MetaCatUtil.logMetacat.info("total ldap authentication time: " +
262
                      (totStopTime - totStartTime) / 1000 + " seconds");
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 2589 sgarg
    MetaCatUtil.logMetacat.info("setting referrals to: " + referral);
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 2589 sgarg
      MetaCatUtil.logMetacat.info("First comp is: " + comp1);
304 2121 sgarg
      String comp2 = user.substring(position + 1,
305
                                    user.indexOf(",", position + 1));
306 2589 sgarg
      MetaCatUtil.logMetacat.info("Second comp is: " + comp2);
307 1005 jones
308 1998 jones
      //String filter = "(&(" + comp1 + "))";
309
      String filter = "(&(" + comp1 + ")(" + comp2 + "))";
310 2589 sgarg
      MetaCatUtil.logMetacat.info("Filter is: " + filter);
311
      MetaCatUtil.logMetacat.info("Provider URL is: " + ldapUrl + ldapBase);
312 802 bojilova
      NamingEnumeration answer;
313
      try {
314 2589 sgarg
        MetaCatUtil.logMetacat.info("Trying search 1: " + filter);
315 802 bojilova
        answer = ctx.search("", filter, ctls);
316 2589 sgarg
        MetaCatUtil.logMetacat.info("Search 1 complete");
317 1988 jones
        if (answer == null) {
318 2589 sgarg
          MetaCatUtil.logMetacat.info("Search 1 answer is null.");
319 1988 jones
        }
320 802 bojilova
        if (answer.hasMore()) {
321 2589 sgarg
          MetaCatUtil.logMetacat.info("Search 1 has answers.");
322 2121 sgarg
          SearchResult sr = (SearchResult) answer.next();
323 802 bojilova
          identifier = sr.getName();
324 2589 sgarg
          MetaCatUtil.logMetacat.info("Originally Found: " + identifier);
325 1005 jones
          return identifier;
326
        }
327 1988 jones
      }
328 2121 sgarg
      catch (InvalidSearchFilterException e) {
329 2589 sgarg
        MetaCatUtil.logMetacat.info("Invalid Filter exception thrown (if1)");
330 2121 sgarg
      }
331 1005 jones
332
      // That failed, so check if it is just a username
333
      filter = "(" + user + ")";
334
      try {
335 2589 sgarg
        MetaCatUtil.logMetacat.info("Trying again: " + filter);
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 2589 sgarg
          MetaCatUtil.logMetacat.info("Found: " + identifier);
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 2589 sgarg
      MetaCatUtil.logMetacat.info("Trying again: " + filter);
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 2589 sgarg
        MetaCatUtil.logMetacat.info("Found: " + identifier);
368 2121 sgarg
      }
369
      else {
370 1005 jones
371
        // maybe its just a common name
372 730 bojilova
        filter = "(cn=" + user + ")";
373 2589 sgarg
        MetaCatUtil.logMetacat.info("Trying again: " + filter);
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 2589 sgarg
          MetaCatUtil.logMetacat.info("Found: " + identifier);
386 2121 sgarg
        }
387
        else {
388 1005 jones
389
          // ok, last resort, is it a surname?
390 730 bojilova
          filter = "(sn=" + user + ")";
391 2589 sgarg
          MetaCatUtil.logMetacat.info("Trying again: " + filter);
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 2589 sgarg
            MetaCatUtil.logMetacat.info("Found: " + identifier);
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 2589 sgarg
      MetaCatUtil.logMetacat.info("Naming exception while getting dn: " + e);
413 730 bojilova
      throw new NamingException(
414 2121 sgarg
          "Naming exception in AuthLdap.getIdentifyingName: " + e);
415 730 bojilova
    }
416 2589 sgarg
    MetaCatUtil.logMetacat.info("Returning found identifier as: " + identifier);
417 730 bojilova
    return identifier;
418
  }
419
420
  /**
421 503 bojilova
   * Get all users from the authentication service
422 871 jones
   *
423
   * @param user the user for authenticating against the service
424
   * @param password the password for authenticating against the service
425
   * @returns string array of all of the user names
426 503 bojilova
   */
427 2121 sgarg
  public String[][] getUsers(String user, String password) throws
428
      ConnectException {
429 2058 sgarg
    String[][] users = null;
430 723 bojilova
431
    // Identify service provider to use
432
    Hashtable env = new Hashtable(11);
433 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
434 723 bojilova
            "com.sun.jndi.ldap.LdapCtxFactory");
435 865 jones
    env.put(Context.REFERRAL, referral);
436 871 jones
    env.put(Context.PROVIDER_URL, ldapUrl);
437 2058 sgarg
438 723 bojilova
    try {
439
440 2121 sgarg
      // Create the initial directory context
441
      DirContext ctx = new InitialDirContext(env);
442 723 bojilova
443 2121 sgarg
      // Specify the attributes to match.
444
      // Users are objects that have the attribute objectclass=InetOrgPerson.
445
      SearchControls ctls = new SearchControls();
446
      String[] attrIDs = {
447 2130 sgarg
          "dn", "cn", "o", "ou", "mail"};
448 2121 sgarg
      ctls.setReturningAttributes(attrIDs);
449
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
450
      //ctls.setCountLimit(1000);
451
      String filter = "(objectClass=inetOrgPerson)";
452 2447 sgarg
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
453 2058 sgarg
454 2121 sgarg
      // Store the users in a vector
455
      Vector uvec = new Vector();
456
      Vector uname = new Vector();
457
      Vector uorg = new Vector();
458 2130 sgarg
      Vector uou = new Vector();
459 2121 sgarg
      Vector umail = new Vector();
460
      Attributes tempAttr = null;
461
      try {
462 2447 sgarg
        while (namingEnum.hasMore()) {
463
          SearchResult sr = (SearchResult) namingEnum.next();
464 2121 sgarg
          tempAttr = sr.getAttributes();
465 2058 sgarg
466 2121 sgarg
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
467
            uname.add( (tempAttr.get("cn") + "").substring(4));
468
          }
469
          else {
470
            uname.add(tempAttr.get("cn") + "");
471
          }
472 2058 sgarg
473 2121 sgarg
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
474
            uorg.add( (tempAttr.get("o") + "").substring(3));
475
          }
476
          else {
477
            uorg.add(tempAttr.get("o") + "");
478
          }
479 2116 sgarg
480 2130 sgarg
          if ( (tempAttr.get("ou") + "").startsWith("ou: ")) {
481
            uou.add( (tempAttr.get("ou") + "").substring(4));
482
          }
483
          else {
484
            uou.add(tempAttr.get("ou") + "");
485
          }
486
487 2121 sgarg
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
488
            umail.add( (tempAttr.get("mail") + "").substring(6));
489
          }
490
          else {
491
            umail.add(tempAttr.get("mail") + "");
492
          }
493 2058 sgarg
494 2121 sgarg
          uvec.add(sr.getName() + "," + ldapBase);
495 723 bojilova
        }
496 2121 sgarg
      }
497
      catch (SizeLimitExceededException slee) {
498 2589 sgarg
        MetaCatUtil.logMetacat.info("LDAP Server size limit exceeded. " +
499
                          "Returning incomplete record set.");
500 2121 sgarg
      }
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 2589 sgarg
      MetaCatUtil.logMetacat.info("Problem getting users in AuthLdap.getUsers:" + e);
518 1477 tao
      //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 2589 sgarg
        MetaCatUtil.logMetacat.info("LDAP Server size limit exceeded. " +
570
                          "Returning incomplete record set.");
571 2121 sgarg
      }
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 2589 sgarg
      MetaCatUtil.logMetacat.info("Problem getting users for a group in " +
585
                        "AuthLdap.getUsers:" + e);
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 2589 sgarg
      MetaCatUtil.logMetacat.info("searching for groups: " + filter);
649 2447 sgarg
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
650 991 tao
651 2121 sgarg
      // Print the groups
652 2589 sgarg
      MetaCatUtil.logMetacat.info("getting group results.");
653 2447 sgarg
      while (namingEnum.hasMore()) {
654
        SearchResult sr = (SearchResult) namingEnum.next();
655 2121 sgarg
        tempAttr = sr.getAttributes();
656 2058 sgarg
657 2121 sgarg
        if ( (tempAttr.get("description") + "").startsWith("description: ")) {
658
          desc.add( (tempAttr.get("description") + "").substring(13));
659 723 bojilova
        }
660 2121 sgarg
        else {
661
          desc.add(tempAttr.get("description") + "");
662
        }
663 991 tao
664 2121 sgarg
        gvec.add(sr.getName() + "," + ldapBase);
665 2589 sgarg
        MetaCatUtil.logMetacat.info("group " + sr.getName() +
666
                                 " added to Group vector");
667 2121 sgarg
      }
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 2589 sgarg
      MetaCatUtil.logMetacat.info("Starting thread...");
676 1000 berkley
      t.start();
677 2589 sgarg
      MetaCatUtil.logMetacat.info("sleeping for 5 seconds.");
678 2121 sgarg
      try {
679 1000 berkley
        Thread.sleep(5000);
680
      }
681 2121 sgarg
      catch (InterruptedException ie) {
682 2589 sgarg
        MetaCatUtil.logMetacat.info("main thread interrupted: " + ie.getMessage());
683 1000 berkley
      }
684
      //this is a manual override of jndi's hideously long time
685
      //out period.
686 2589 sgarg
      MetaCatUtil.logMetacat.info("Awake after 5 seconds.");
687 2121 sgarg
      if (referralContext == null) {
688 2589 sgarg
        MetaCatUtil.logMetacat.info("thread timed out...returning groups: " +
689
                          gvec.toString());
690 2116 sgarg
        String groups[][] = new String[gvec.size()][2];
691 2121 sgarg
        for (int i = 0; i < gvec.size(); i++) {
692
          groups[i][0] = (String) gvec.elementAt(i);
693
          groups[i][1] = (String) desc.elementAt(i);
694 991 tao
        }
695 1000 berkley
        t.interrupt();
696
        return groups;
697
      }
698 2121 sgarg
      DirContext dc = (DirContext) referralContext;
699
      String[] attrIDs = {
700
          "cn", "o", "description"};
701 1000 berkley
      // Specify the attributes to match.
702
      // Groups are objects with attribute objectclass=groupofuniquenames.
703
      // and have attribute uniquemember: uid=foruser,ldapbase.
704
      SearchControls ctls = new SearchControls();
705
      ctls.setReturningAttributes(attrIDs);
706
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
707 2058 sgarg
708 1000 berkley
      String filter = null;
709
      String gfilter = "(objectClass=groupOfUniqueNames)";
710
      if (null == foruser) {
711 2121 sgarg
        filter = gfilter;
712 1000 berkley
      }
713 2121 sgarg
      else {
714
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
715
      }
716 2058 sgarg
717 2121 sgarg
      try {
718 2447 sgarg
        NamingEnumeration namingEnum = dc.search(ldapBase, filter, ctls);
719 991 tao
        // Print the groups
720 2447 sgarg
        while (namingEnum.hasMore()) {
721
          SearchResult sr = (SearchResult) namingEnum.next();
722 2058 sgarg
          tempAttr = sr.getAttributes();
723
724 2121 sgarg
          if ( (tempAttr.get("description") + "").startsWith("description: ")) {
725 2058 sgarg
            desc.add( (tempAttr.get("description") + "").substring(13));
726
          }
727 2121 sgarg
          else {
728
            desc.add(tempAttr.get("description") + "");
729
          }
730 2058 sgarg
731 2121 sgarg
          gvec.add(sr.getName() + "," + ldapBase);
732 991 tao
        }
733 2058 sgarg
734 991 tao
        referralContext.close();
735
        dc.close();
736
      }
737 2121 sgarg
      catch (NamingException ne) {
738 2589 sgarg
        MetaCatUtil.logMetacat.info("Naming Exception in AuthLdap.getGroups" +
739
                                 ne.getExplanation() + ne.getMessage());
740 991 tao
      }
741 2121 sgarg
    }
742
    catch (NamingException e) {
743 868 berkley
      e.printStackTrace(System.err);
744 2116 sgarg
      String groups[][] = new String[gvec.size()][2];
745 2121 sgarg
      for (int i = 0; i < gvec.size(); i++) {
746
        groups[i][0] = (String) gvec.elementAt(i);
747
        groups[i][1] = (String) desc.elementAt(i);
748 1006 tao
      }
749
      return groups;
750 2121 sgarg
      /*throw new ConnectException(
751
             "Problem getting groups for a user in AuthLdap.getGroups:" + e);*/
752 2058 sgarg
    }
753
754 2589 sgarg
    MetaCatUtil.logMetacat.info("The user is in the following groups: " +
755
                             gvec.toString());
756 2116 sgarg
    String groups[][] = new String[gvec.size()][2];
757 2121 sgarg
    for (int i = 0; i < gvec.size(); i++) {
758
      groups[i][0] = (String) gvec.elementAt(i);
759
      groups[i][1] = (String) desc.elementAt(i);
760 1000 berkley
    }
761 723 bojilova
    return groups;
762 503 bojilova
  }
763
764
  /**
765
   * Get attributes describing a user or group
766
   *
767 871 jones
   * @param foruser the user for which the attribute list is requested
768 503 bojilova
   * @returns HashMap a map of attribute name to a Vector of values
769
   */
770 2121 sgarg
  public HashMap getAttributes(String foruser) throws ConnectException {
771 514 jones
    return getAttributes(null, null, foruser);
772 503 bojilova
  }
773
774
  /**
775
   * Get attributes describing a user or group
776
   *
777 871 jones
   * @param user the user for authenticating against the service
778 503 bojilova
   * @param password the password for authenticating against the service
779 871 jones
   * @param foruser the user whose attributes should be returned
780 503 bojilova
   * @returns HashMap a map of attribute name to a Vector of values
781
   */
782 2121 sgarg
  public HashMap getAttributes(String user, String password, String foruser) throws
783
      ConnectException {
784 503 bojilova
    HashMap attributes = new HashMap();
785 802 bojilova
    String ldapUrl = this.ldapUrl;
786
    String ldapBase = this.ldapBase;
787
    String userident = foruser;
788 2058 sgarg
789 503 bojilova
    // Identify service provider to use
790
    Hashtable env = new Hashtable(11);
791 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
792 2121 sgarg
            "com.sun.jndi.ldap.LdapCtxFactory");
793 865 jones
    env.put(Context.REFERRAL, referral);
794 871 jones
    env.put(Context.PROVIDER_URL, ldapUrl);
795 503 bojilova
796
    try {
797 2058 sgarg
798 503 bojilova
      // Create the initial directory context
799
      DirContext ctx = new InitialDirContext(env);
800 2058 sgarg
801
      // Ask for all attributes of the user
802 871 jones
      //Attributes attrs = ctx.getAttributes(userident);
803
      Attributes attrs = ctx.getAttributes(foruser);
804 2058 sgarg
805 503 bojilova
      // Print all of the attributes
806
      NamingEnumeration en = attrs.getAll();
807
      while (en.hasMore()) {
808 2121 sgarg
        Attribute att = (Attribute) en.next();
809 503 bojilova
        Vector values = new Vector();
810
        String attName = att.getID();
811
        NamingEnumeration attvalues = att.getAll();
812
        while (attvalues.hasMore()) {
813 2121 sgarg
          String value = (String) attvalues.next();
814 503 bojilova
          values.add(value);
815
        }
816
        attributes.put(attName, values);
817
      }
818 2058 sgarg
819 503 bojilova
      // Close the context when we're done
820
      ctx.close();
821 2121 sgarg
    }
822
    catch (NamingException e) {
823 2589 sgarg
      MetaCatUtil.logMetacat.info("Problem getting attributes in " +
824
                        "AuthLdap.getAttributes:" + e);
825 723 bojilova
      throw new ConnectException(
826 2121 sgarg
          "Problem getting attributes in AuthLdap.getAttributes:" + e);
827 503 bojilova
    }
828
829
    return attributes;
830
  }
831
832
  /**
833 730 bojilova
   * Get list of all subtrees holding Metacat's groups and users
834 2058 sgarg
   * starting from the Metacat LDAP root,
835 730 bojilova
   * i.e. ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
836 504 jones
   */
837 730 bojilova
  private Hashtable getSubtrees(String user, String password,
838 2121 sgarg
                                String ldapUrl, String ldapBase) throws
839
      ConnectException {
840 730 bojilova
    Hashtable trees = new Hashtable();
841 504 jones
842
    // Identify service provider to use
843
    Hashtable env = new Hashtable(11);
844 2058 sgarg
    env.put(Context.INITIAL_CONTEXT_FACTORY,
845 504 jones
            "com.sun.jndi.ldap.LdapCtxFactory");
846 2129 sgarg
    // env.put(Context.REFERRAL, referral);
847
    // Using 'ignore' here instead of 'follow' as 'ignore' seems
848
    // to do the job better. 'follow' was not bringing up the UCNRS
849
    // and PISCO tree whereas 'ignore' brings up the tree.
850
851
    env.put(Context.REFERRAL, "ignore");
852 504 jones
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
853
854
    try {
855
856 2121 sgarg
      // Create the initial directory context
857
      DirContext ctx = new InitialDirContext(env);
858 730 bojilova
859 2121 sgarg
      // Specify the ids of the attributes to return
860
      String[] attrIDs = {
861
          "o", "ref"};
862
      SearchControls ctls = new SearchControls();
863
      ctls.setReturningAttributes(attrIDs);
864
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
865 2058 sgarg
866 2121 sgarg
      // Specify the attributes to match.
867
      // Subtrees from the main server are found as objects with attribute
868
      // objectclass=organization or objectclass=referral to the subtree
869
      // resided on other server.
870
      String filter = "(|(objectclass=organization)(objectclass=referral))";
871 730 bojilova
872 2121 sgarg
      // Search for objects in the current context
873 2447 sgarg
      NamingEnumeration namingEnum = ctx.search("", filter, ctls);
874 730 bojilova
875 2121 sgarg
      // Print the subtrees' <ldapURL, baseDN>
876 2447 sgarg
      while (namingEnum.hasMore()) {
877 2121 sgarg
878 2447 sgarg
        SearchResult sr = (SearchResult) namingEnum.next();
879 2121 sgarg
880
        Attributes attrs = sr.getAttributes();
881
        NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref" attrs
882
883
        if (enum1.hasMore()) {
884
          Attribute attr = (Attribute) enum1.next();
885
          String attrValue = (String) attr.get();
886
          String attrName = (String) attr.getID();
887
888 730 bojilova
          if (enum1.hasMore()) {
889 2121 sgarg
            attr = (Attribute) enum1.next();
890
            String refValue = (String) attr.get();
891
            String refName = (String) attr.getID();
892
            if (ldapBase.startsWith(refName + "=" + refValue)) {
893
              trees.put(ldapBase,
894
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
895
            }
896
            else {
897 2129 sgarg
              // this is a referral - so organization name is appended in
898
              // front of the ldapbase.... later it is stripped out
899
              // in getPrincipals
900
              trees.put("[" + refName + "=" + refValue + "]" +
901
                        attrValue.substring(attrValue.lastIndexOf("/") + 1,
902
                                            attrValue.length()),
903 2121 sgarg
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
904 2129 sgarg
905
              // trees.put(refName + "=" + refValue + "," + ldapBase,
906
              //           attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
907 2121 sgarg
            }
908 2058 sgarg
909 2121 sgarg
          }
910
          else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
911
            trees.put(ldapBase, ldapUrl);
912
          }
913
          else {
914 2129 sgarg
            if (sr.isRelative()) {
915 2121 sgarg
              trees.put(attrName + "=" + attrValue + "," + ldapBase, ldapUrl);
916 2130 sgarg
            }
917
            else {
918 2121 sgarg
              String referenceURL = sr.getName();
919 2129 sgarg
              referenceURL = referenceURL.substring(0,
920
                  referenceURL.lastIndexOf("/") + 1);
921
              trees.put(attrName + "=" + attrValue + "," + ldapBase,
922
                        referenceURL);
923 730 bojilova
            }
924 2121 sgarg
925 504 jones
          }
926
        }
927 2121 sgarg
      }
928 730 bojilova
929 2121 sgarg
      // Close the context when we're done
930
      ctx.close();
931 730 bojilova
932 2121 sgarg
    }
933
    catch (NamingException e) {
934 2589 sgarg
      MetaCatUtil.logMetacat.info("Problem getting subtrees in AuthLdap.getSubtrees:"
935
                        + e);
936 730 bojilova
      throw new ConnectException(
937 2121 sgarg
          "Problem getting subtrees in AuthLdap.getSubtrees:" + e);
938 504 jones
    }
939
940 730 bojilova
    return trees;
941 504 jones
  }
942
943
  /**
944 730 bojilova
   * Get all groups and users from authentication scheme.
945 725 bojilova
   * The output is formatted in XML.
946 730 bojilova
   * @param user the user which requests the information
947
   * @param password the user's password
948 725 bojilova
   */
949 2121 sgarg
  public String getPrincipals(String user, String password) throws
950
      ConnectException {
951 725 bojilova
    StringBuffer out = new StringBuffer();
952 2559 sgarg
953 2058 sgarg
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
954 730 bojilova
    out.append("<principals>\n");
955 2058 sgarg
956 730 bojilova
    /*
957 2058 sgarg
     * get all subtrees first in the current dir context
958 730 bojilova
     * and then the Metacat users under them
959
     */
960 2121 sgarg
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
961
                                     this.ldapBase);
962 2058 sgarg
963 2447 sgarg
    Enumeration keyEnum = subtrees.keys();
964
    while (keyEnum.hasMoreElements()) {
965
      this.ldapBase = (String) keyEnum.nextElement();
966 2121 sgarg
      this.ldapUrl = (String) subtrees.get(ldapBase);
967 2058 sgarg
968 2129 sgarg
      /*
969
       * code to get the organization name from ldapBase
970
       */
971 2116 sgarg
      String orgName = this.ldapBase;
972 2130 sgarg
      if (orgName.startsWith("[")) {
973 2129 sgarg
        // if orgName starts with [ then it is a referral URL...
974
        // (see code in getSubtress)
975
        // hence orgName can be retrieved  by getting the string between
976
        // 'o=' and ']'
977
        // also the string between [ and ] needs to be striped out from
978
        // this.ldapBase
979
        this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
980
        if (orgName != null && orgName.indexOf("o=") > -1) {
981
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
982
          orgName = orgName.substring(0, orgName.indexOf("]"));
983
        }
984 2130 sgarg
      }
985
      else {
986 2129 sgarg
        // else it is not referral
987
        // hence orgName can be retrieved  by getting the string between
988
        // 'o=' and ','
989
        if (orgName != null && orgName.indexOf("o=") > -1) {
990
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
991
          if (orgName.indexOf(",") > -1) {
992
            orgName = orgName.substring(0, orgName.indexOf(","));
993
          }
994
        }
995 2121 sgarg
      }
996
997 2058 sgarg
      out.append("  <authSystem URI=\"" +
998 2121 sgarg
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
999
                 "\">\n");
1000 730 bojilova
1001
      // get all groups for directory context
1002 2058 sgarg
      String[][] groups = getGroups(user, password);
1003
      String[][] users = getUsers(user, password);
1004
      int userIndex = 0;
1005 730 bojilova
1006
      // for the groups and users that belong to them
1007 2121 sgarg
      if (groups != null && groups.length > 0) {
1008
        for (int i = 0; i < groups.length; i++) {
1009 730 bojilova
          out.append("    <group>\n");
1010 2058 sgarg
          out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1011
          out.append("      <description>" + groups[i][1] + "</description>\n");
1012 2121 sgarg
          String[] usersForGroup = getUsers(user, password, groups[i][0]);
1013
          for (int j = 0; j < usersForGroup.length; j++) {
1014 2559 sgarg
1015 2058 sgarg
            userIndex = searchUser(usersForGroup[j], users);
1016 730 bojilova
            out.append("      <user>\n");
1017 2058 sgarg
1018 2121 sgarg
            if (userIndex < 0) {
1019 2095 sgarg
              out.append("        <username>" + usersForGroup[j] +
1020
                         "</username>\n");
1021 2121 sgarg
            }
1022
            else {
1023 2130 sgarg
              out.append("        <username>" + users[userIndex][0] +
1024 2121 sgarg
                         "</username>\n");
1025 2130 sgarg
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1026
              out.append("        <organization>" + users[userIndex][2] +
1027 2121 sgarg
                         "</organization>\n");
1028 2130 sgarg
              if (users[userIndex][3].compareTo("null") != 0) {
1029
                out.append("      <organizationUnitName>" + users[userIndex][3] +
1030
                           "</organizationUnitName>\n");
1031
              }
1032
              out.append("        <email>" + users[userIndex][4] + "</email>\n");
1033 2058 sgarg
            }
1034
1035 730 bojilova
            out.append("      </user>\n");
1036
          }
1037
          out.append("    </group>\n");
1038
        }
1039
      }
1040 2058 sgarg
1041 2130 sgarg
      // for the users not belonging to any grou8p
1042 2121 sgarg
      for (int j = 0; j < users.length; j++) {
1043 725 bojilova
          out.append("    <user>\n");
1044 2058 sgarg
          out.append("      <username>" + users[j][0] + "</username>\n");
1045
          out.append("      <name>" + users[j][1] + "</name>\n");
1046 2130 sgarg
          out.append("      <organization>" + users[j][2] +
1047
                     "</organization>\n");
1048
          if (users[j][3].compareTo("null") != 0) {
1049
            out.append("      <organizationUnitName>" + users[j][3] +
1050
                       "</organizationUnitName>\n");
1051
          }
1052
          out.append("      <email>" + users[j][4] + "</email>\n");
1053 725 bojilova
          out.append("    </user>\n");
1054
      }
1055 2058 sgarg
1056 730 bojilova
      out.append("  </authSystem>\n");
1057 725 bojilova
    }
1058
    out.append("</principals>");
1059
    return out.toString();
1060
  }
1061
1062
  /**
1063 2058 sgarg
   * Method for getting index of user DN in User info array
1064
   */
1065 2121 sgarg
  int searchUser(String user, String userGroup[][]) {
1066
    for (int j = 0; j < userGroup.length; j++) {
1067
      if (user.compareTo(userGroup[j][0]) == 0) {
1068 2058 sgarg
        return j;
1069
      }
1070
    }
1071
    return -1;
1072
  }
1073
1074
  /**
1075 503 bojilova
   * Test method for the class
1076
   */
1077
  public static void main(String[] args) {
1078
1079 504 jones
    // Provide a user, such as: "Matt Jones", or "jones"
1080 503 bojilova
    String user = args[0];
1081
    String password = args[1];
1082
1083 2589 sgarg
    MetaCatUtil.logMetacat.warn("Creating session...");
1084 503 bojilova
    AuthLdap authservice = new AuthLdap();
1085 2589 sgarg
    MetaCatUtil.logMetacat.warn("Session exists...");
1086 2058 sgarg
1087 503 bojilova
    boolean isValid = false;
1088
    try {
1089 2589 sgarg
      MetaCatUtil.logMetacat.warn("Authenticating...");
1090 503 bojilova
      isValid = authservice.authenticate(user, password);
1091
      if (isValid) {
1092 2589 sgarg
        MetaCatUtil.logMetacat.warn("Authentication successful for: " + user);
1093 2121 sgarg
      }
1094
      else {
1095 2589 sgarg
        MetaCatUtil.logMetacat.warn("Authentication failed for: " + user);
1096 503 bojilova
      }
1097 725 bojilova
1098 871 jones
      // Get attributes for the user
1099 503 bojilova
      if (isValid) {
1100 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nGetting attributes for user....");
1101 991 tao
        HashMap userInfo = authservice.getAttributes(user, password, user);
1102 503 bojilova
        // Print all of the attributes
1103 2121 sgarg
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1104 503 bojilova
        while (attList.hasNext()) {
1105 2121 sgarg
          String att = (String) attList.next();
1106
          Vector values = (Vector) userInfo.get(att);
1107 503 bojilova
          Iterator attvalues = values.iterator();
1108
          while (attvalues.hasNext()) {
1109 2121 sgarg
            String value = (String) attvalues.next();
1110 2589 sgarg
            MetaCatUtil.logMetacat.warn(att + ": " + value);
1111 503 bojilova
          }
1112
        }
1113 871 jones
      }
1114 723 bojilova
1115 871 jones
      // get the groups
1116
      if (isValid) {
1117 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nGetting all groups....");
1118 2058 sgarg
        String[][] groups = authservice.getGroups(user, password);
1119 2589 sgarg
        MetaCatUtil.logMetacat.warn("Groups found: " + groups.length);
1120 2121 sgarg
        for (int i = 0; i < groups.length; i++) {
1121 2589 sgarg
          MetaCatUtil.logMetacat.warn("Group " + i + ": " + groups[i][0]);
1122 871 jones
        }
1123 503 bojilova
      }
1124 725 bojilova
1125 871 jones
      // get the groups for the user
1126
      String savedGroup = null;
1127
      if (isValid) {
1128 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nGetting groups for user....");
1129 2058 sgarg
        String[][] groups = authservice.getGroups(user, password, user);
1130 2589 sgarg
        MetaCatUtil.logMetacat.warn("Groups found: " + groups.length);
1131 2121 sgarg
        for (int i = 0; i < groups.length; i++) {
1132 2589 sgarg
          MetaCatUtil.logMetacat.warn("Group " + i + ": " + groups[i][0]);
1133 2121 sgarg
          savedGroup = groups[i][0];
1134 871 jones
        }
1135
      }
1136
1137
      // get the users for a group
1138
      if (isValid) {
1139 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nGetting users for group....");
1140
        MetaCatUtil.logMetacat.warn("Group: " + savedGroup);
1141 871 jones
        String[] users = authservice.getUsers(user, password, savedGroup);
1142 2589 sgarg
        MetaCatUtil.logMetacat.warn("Users found: " + users.length);
1143 2121 sgarg
        for (int i = 0; i < users.length; i++) {
1144 2589 sgarg
          MetaCatUtil.logMetacat.warn("User " + i + ": " + users[i]);
1145 871 jones
        }
1146
      }
1147
1148
      // get all users
1149
      if (isValid) {
1150 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nGetting all users ....");
1151 2058 sgarg
        String[][] users = authservice.getUsers(user, password);
1152 2589 sgarg
        MetaCatUtil.logMetacat.warn("Users found: " + users.length);
1153 2058 sgarg
1154 871 jones
      }
1155 873 jones
1156 726 bojilova
      // get the whole list groups and users in XML format
1157 725 bojilova
      if (isValid) {
1158 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nTrying principals....");
1159 730 bojilova
        authservice = new AuthLdap();
1160 725 bojilova
        String out = authservice.getPrincipals(user, password);
1161 802 bojilova
        java.io.File f = new java.io.File("principals.xml");
1162 725 bojilova
        java.io.FileWriter fw = new java.io.FileWriter(f);
1163
        java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1164
        buff.write(out);
1165
        buff.flush();
1166
        buff.close();
1167
        fw.close();
1168 2589 sgarg
        MetaCatUtil.logMetacat.warn("\nFinished getting principals.");
1169 725 bojilova
      }
1170 873 jones
1171 2121 sgarg
    }
1172
    catch (ConnectException ce) {
1173 2589 sgarg
      MetaCatUtil.logMetacat.info(ce.getMessage());
1174 2121 sgarg
    }
1175
    catch (java.io.IOException ioe) {
1176 2589 sgarg
      MetaCatUtil.logMetacat.info("I/O Error writing to file principals.txt");
1177 503 bojilova
    }
1178
  }
1179 2058 sgarg
1180 934 tao
  /**
1181
   * This method will be called by start a thread.
1182
   * It can handle if a referral exception happend.
1183 2058 sgarg
   */
1184 2121 sgarg
  public void run() {
1185 893 berkley
    referralContext = null;
1186 2121 sgarg
    DirContext refDirContext = null;
1187
    boolean moreReferrals = true;
1188
    String referralInfo = null;
1189 934 tao
    //set a while loop is because we don't know if a referral excption contains
1190
    //another referral exception
1191 2121 sgarg
    while (moreReferrals) {
1192
      try {
1193 934 tao
        //revise environment variable
1194 2121 sgarg
        referralInfo = (String) refExc.getReferralInfo();
1195 2589 sgarg
        MetaCatUtil.logMetacat.info("Processing referral (pr0): ");
1196
        MetaCatUtil.logMetacat.info("PROVIDER_URL set to (pr1): " + referralInfo);
1197 1988 jones
        //env.put(Context.PROVIDER_URL,referralInfo);
1198
        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1199
        //env.put(Context.SECURITY_PRINCIPAL, userName);
1200
        //env.put(Context.SECURITY_CREDENTIALS, userPassword);
1201
        //env.put(Context.REFERRAL, "throw");
1202 2589 sgarg
        //MetaCatUtil.logMetacat.info("Processing referral (pr1.info): " + userName,35);
1203
        //MetaCatUtil.logMetacat.info("Processing referral (pr2)",35);
1204 1988 jones
        //rContext = refExc.getReferralContext(env);
1205
        rContext = refExc.getReferralContext();
1206 2589 sgarg
        MetaCatUtil.logMetacat.info("Processing referral (pr3)");
1207 934 tao
        //casting the context to dircontext and it will create a
1208
        //autherntication or naming exception if DN and password is incorrect
1209 2121 sgarg
        referralContext = rContext;
1210
        refDirContext = (DirContext) rContext;
1211 991 tao
        refDirContext.close();
1212 934 tao
        //get context and jump out the while loop
1213 2121 sgarg
        moreReferrals = false;
1214 2589 sgarg
        MetaCatUtil.logMetacat.info("Processing referral (pr4)");
1215 2121 sgarg
      } //try
1216 991 tao
      //if referral have another referral excption
1217 2121 sgarg
      catch (ReferralException re) {
1218 2589 sgarg
        MetaCatUtil.logMetacat.info("GOT referral exception (re1): " + re.getMessage());
1219
        MetaCatUtil.logMetacat.info("RE details (re2): " + re.toString(true));
1220 934 tao
        //keep running in while loop
1221 2121 sgarg
        moreReferrals = true;
1222 934 tao
        //assign refExc to new referral exception re
1223 2121 sgarg
        refExc = re;
1224 934 tao
      }
1225 991 tao
      //catch a authentication exception
1226 2121 sgarg
      catch (AuthenticationException ae) {
1227 2589 sgarg
        MetaCatUtil.logMetacat.warn("Error running referral handler thread (ae1): " +
1228
                          ae.getMessage());
1229 934 tao
        //check if has another referral
1230 2121 sgarg
        moreReferrals = refExc.skipReferral();
1231 934 tao
        //don't get the context
1232
        referralContext = null;
1233
      }
1234 991 tao
      //catch a naming exception
1235 2121 sgarg
      catch (NamingException ne) {
1236 2589 sgarg
        MetaCatUtil.logMetacat.warn("Error running referral handler thread (ne1): " +
1237
                          ne.getMessage());
1238 934 tao
        //check if has another referral
1239 2121 sgarg
        moreReferrals = refExc.skipReferral();
1240 934 tao
        //don't get context
1241 2058 sgarg
        referralContext = null;
1242 934 tao
      }
1243 2121 sgarg
    } //while
1244
  } //run()
1245 2058 sgarg
1246 2121 sgarg
  private class GetGroup
1247
      implements Runnable {
1248
    public void run() {
1249 991 tao
      referralContext = null;
1250 2589 sgarg
      MetaCatUtil.logMetacat.info("getting groups context");
1251 2121 sgarg
      DirContext refDirContext = null;
1252
      boolean moreReferrals = true;
1253 2058 sgarg
      //set a while loop is because we don't know if a referral excption
1254 991 tao
      //contains another referral exception
1255 2121 sgarg
      while (moreReferrals) {
1256
        try {
1257 991 tao
          //revise environment variable
1258
          String refInfo = null;
1259 2121 sgarg
          refInfo = (String) refExc.getReferralInfo();
1260
          if (refInfo != null) {
1261 2589 sgarg
            MetaCatUtil.logMetacat.info("Referral in thread to: " +
1262
                                     refInfo.toString());
1263 991 tao
          }
1264 2121 sgarg
          else {
1265 2589 sgarg
            MetaCatUtil.logMetacat.info("getting refInfo Manually");
1266 2121 sgarg
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1267
                get(Context.PROVIDER_URL);
1268 991 tao
          }
1269 2589 sgarg
          MetaCatUtil.logMetacat.info("refInfo: " + refInfo);
1270 2058 sgarg
1271
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1272 2121 sgarg
                  "com.sun.jndi.ldap.LdapCtxFactory");
1273 991 tao
          env.put(Context.REFERRAL, "throw");
1274
          env.put(Context.PROVIDER_URL, refInfo);
1275 2058 sgarg
1276 2589 sgarg
          MetaCatUtil.logMetacat.info("creating referralContext");
1277 991 tao
          referralContext = new InitialDirContext(env);
1278 2589 sgarg
          MetaCatUtil.logMetacat.info("referralContext created");
1279 991 tao
          //get context and jump out the while loop
1280 2121 sgarg
          moreReferrals = false;
1281
        } //try
1282
        catch (ReferralException re) {
1283 991 tao
          //keep running in while loop
1284 2121 sgarg
          moreReferrals = true;
1285 991 tao
          //assign refExc to new referral exception re
1286 2121 sgarg
          refExc = re;
1287 991 tao
        }
1288 2121 sgarg
        catch (AuthenticationException ae) {
1289 2589 sgarg
          MetaCatUtil.logMetacat.info("Error running referral handler thread (ae2): " +
1290
                            ae.getMessage());
1291 991 tao
          //check if has another referral
1292 2121 sgarg
          moreReferrals = refExc.skipReferral();
1293 991 tao
          //don't get the context
1294
          referralContext = null;
1295
        }
1296 2121 sgarg
        catch (NamingException ne) {
1297 2589 sgarg
          MetaCatUtil.logMetacat.info("Error running referral handler thread (ne2): " +
1298
                            ne.getMessage());
1299 991 tao
          //check if has another referral
1300 2121 sgarg
          moreReferrals = refExc.skipReferral();
1301 991 tao
          //don't get context
1302 2058 sgarg
          referralContext = null;
1303 991 tao
        }
1304 2121 sgarg
      } //while
1305
    } //run()
1306
  }
1307 503 bojilova
}