Project

General

Profile

1
/**
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: sgarg $'
12
 *     '$Date: 2004-04-14 18:41:45 -0700 (Wed, 14 Apr 2004) $'
13
 * '$Revision: 2130 $'
14
 *
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
 */
29

    
30
package edu.ucsb.nceas.metacat;
31

    
32
import java.net.ConnectException;
33
import javax.naming.AuthenticationException;
34
import javax.naming.Context;
35
import javax.naming.NamingEnumeration;
36
import javax.naming.NamingException;
37
import javax.naming.SizeLimitExceededException;
38
import javax.naming.InitialContext;
39
import javax.naming.directory.InvalidSearchFilterException;
40
import javax.naming.directory.Attribute;
41
import javax.naming.directory.Attributes;
42
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
import javax.naming.directory.SearchControls;
48
import javax.naming.ReferralException;
49
import javax.naming.ldap.*;
50
import java.net.URLDecoder;
51
import java.util.Iterator;
52
import java.util.HashMap;
53
import java.util.Hashtable;
54
import java.util.Enumeration;
55
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
 * The LDAP authentication service is used to determine if a user
62
 * is authenticated, and whether they are a member of a particular group.
63
 */
64
public class AuthLdap
65
    implements AuthInterface, Runnable {
66
  private MetaCatUtil util = new MetaCatUtil();
67
  private String ldapUrl;
68
  private String ldapsUrl;
69
  private String ldapBase;
70
  private String referral;
71
  private Context referralContext;
72
  Hashtable env = new Hashtable(11);
73
  private Context rContext;
74
  private String userName;
75
  private String userPassword;
76
  ReferralException refExc;
77
  //String uid=null;
78

    
79
  /**
80
   * Construct an AuthLdap
81
   */
82
  public AuthLdap() {
83
    // Read LDAP URI for directory service information
84
    this.ldapUrl = MetaCatUtil.getOption("ldapurl");
85
    this.ldapsUrl = MetaCatUtil.getOption("ldapsurl");
86
    this.ldapBase = MetaCatUtil.getOption("ldapbase");
87
    this.referral = MetaCatUtil.getOption("referral");
88
  }
89

    
90
  /**
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
  public boolean authenticate(String user, String password) throws
99
      ConnectException {
100
    String ldapUrl = this.ldapUrl;
101
    String ldapsUrl = this.ldapsUrl;
102
    String ldapBase = this.ldapBase;
103
    boolean authenticated = false;
104
    String identifier = user;
105
    //get uid here.
106
    //uid=user.substring(0, user.indexOf(","));
107

    
108
    try {
109
      // Check the usename as passed in
110
      authenticated = ldapAuthenticate(identifier, password);
111
      // if not found, try looking up a valid DN then auth again
112
      if (!authenticated) {
113
        MetaCatUtil.debugMessage("Looking up DN for: " + identifier, 35);
114
        identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
115
        MetaCatUtil.debugMessage("DN found: " + identifier, 35);
116
        String decoded = URLDecoder.decode(identifier);
117
        MetaCatUtil.debugMessage("DN decoded: " + decoded, 35);
118
        identifier = decoded;
119
        String refUrl = "";
120
        String refBase = "";
121
        if (identifier.startsWith("ldap")) {
122
          refUrl = identifier.substring(0,
123
                                        identifier.lastIndexOf("/") + 1);
124
          MetaCatUtil.debugMessage("Ref ldapUrl: " + refUrl, 35);
125
          int position = identifier.indexOf(",");
126
          int position2 = identifier.indexOf(",", position + 1);
127
          refBase = identifier.substring(position2 + 1);
128
          MetaCatUtil.debugMessage("Ref ldapBase: " + refBase, 35);
129
          identifier = identifier.substring(
130
              identifier.lastIndexOf("/") + 1);
131
          MetaCatUtil.debugMessage("Trying: " + identifier, 35);
132
          authenticated = ldapAuthenticate(identifier, password,
133
                                           refUrl, refBase);
134
        }
135
        else {
136
          identifier = identifier + "," + ldapBase;
137
          MetaCatUtil.debugMessage("Trying: " + identifier, 35);
138
          authenticated = ldapAuthenticate(identifier, password);
139
        }
140
        //authenticated = ldapAuthenticate(identifier, password);
141
      }
142

    
143
    }
144
    catch (NullPointerException e) {
145
      util.debugMessage("NullPointerException b' password is null", 30);
146
      util.debugMessage("NullPointerException while authenticating in " +
147
                        "AuthLdap.authenticate: " + e, 30);
148
      throw new ConnectException(
149
          "NullPointerException while authenticating in " +
150
          "AuthLdap.authenticate: " + e);
151
    }
152
    catch (NamingException e) {
153
      util.debugMessage("Naming exception while authenticating in " +
154
                        "AuthLdap.authenticate: " + e, 30);
155
      e.printStackTrace();
156
    }
157
    catch (Exception e) {
158
      util.debugMessage(e.getMessage(), 30);
159
    }
160
    return authenticated;
161
  }
162

    
163
  /**
164
   * 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
  private boolean ldapAuthenticate(String identifier, String password) throws
171
      ConnectException, NamingException, NullPointerException {
172
    return ldapAuthenticate(identifier, password,
173
                            this.ldapsUrl, this.ldapBase);
174
  }
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
                                   String directoryUrl, String searchBase) throws
185
      ConnectException, NamingException, NullPointerException {
186
    double totStartTime = System.currentTimeMillis();
187
    boolean authenticated = false;
188
    if (identifier != null && !password.equals("")) {
189

    
190
      //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
              "com.sun.jndi.ldap.LdapCtxFactory");
197
      env.put(Context.REFERRAL, "throw");
198
      env.put(Context.PROVIDER_URL, directoryUrl + searchBase);
199
      util.debugMessage("PROVIDER_URL set to: " + directoryUrl + searchBase, 35);
200
      if (!ldapsUrl.equals(ldapUrl)) {
201
        // ldap is set on default port 389
202
        // ldaps is set on second port - 636 by default
203
        //env.put(Context.SECURITY_PROTOCOL, "ssl");
204
      }
205
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
206
      env.put(Context.SECURITY_PRINCIPAL, identifier);
207
      env.put(Context.SECURITY_CREDENTIALS, password);
208
      // If our auth credentials are invalid, an exception will be thrown
209
      DirContext ctx = null;
210
      try {
211
        double startTime = System.currentTimeMillis();
212
        //Here to check the authorization
213
        ctx = new InitialDirContext(env);
214
        double stopTime = System.currentTimeMillis();
215
        util.debugMessage("Connection time thru " + ldapsUrl + " was: " +
216
                          (stopTime - startTime) / 1000 + " seconds.", 35);
217
        authenticated = true;
218
        //tls.close();
219
        ctx.close();
220
        this.ldapUrl = ldapUrl;
221
        this.ldapBase = ldapBase;
222
        //break;
223
      }
224
      catch (AuthenticationException ae) {
225
        authenticated = false;
226
        if (ctx != null) {
227
          ctx.close();
228
        }
229
      }
230
      catch (javax.naming.InvalidNameException ine) {
231
        util.debugMessage("An invalid DN was provided!", 30);
232
      }
233
      catch (javax.naming.ReferralException re) {
234
        util.debugMessage("referral during authentication", 30);
235
        util.debugMessage("Referral information: " + re.getReferralInfo(), 30);
236
        try {
237
          refExc = re;
238

    
239
          Thread t = new Thread(this);
240
          t.start();
241
          Thread.sleep(5000); //this is a manual override of ldap's
242
          //hideously long time out period.
243
          util.debugMessage("Awake after 5 seconds.", 35);
244
          if (referralContext == null) {
245
            t.interrupt();
246
            authenticated = false;
247
          }
248
          else {
249
            authenticated = true;
250
          }
251
        }
252
        catch (Exception e) {
253
          authenticated = false;
254
        }
255
      }
256
    }
257
    else {
258
      util.debugMessage("User not found", 30);
259
    }
260
    double totStopTime = System.currentTimeMillis();
261
    util.debugMessage("total ldap authentication time: " +
262
                      (totStopTime - totStartTime) / 1000 + " seconds", 35);
263
    return authenticated;
264
  }
265

    
266
  /**
267
   * 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
   * @returns String the identifying name for the user,
273
   *          or null if not found
274
   */
275
  private String getIdentifyingName(String user, String ldapUrl,
276
                                    String ldapBase) throws NamingException {
277
    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
    util.debugMessage("setting referrals to: " + referral, 35);
283
    env.put(Context.REFERRAL, referral);
284
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
285
    //    non-secure LDAP context; dn are publicly readable
286
    try {
287

    
288
      // 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
      // Search for the user id or name using the uid, then cn and sn
294
      //attributes
295
      // If we find a record, determine the dn for the record
296
      // The following blocks need to be refactored into a subroutine
297
      // they have a ridiculous amount of redundancy
298

    
299
      // 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
      MetaCatUtil.debugMessage("First comp is: " + comp1, 35);
304
      String comp2 = user.substring(position + 1,
305
                                    user.indexOf(",", position + 1));
306
      MetaCatUtil.debugMessage("Second comp is: " + comp2, 35);
307

    
308
      //String filter = "(&(" + comp1 + "))";
309
      String filter = "(&(" + comp1 + ")(" + comp2 + "))";
310
      MetaCatUtil.debugMessage("Filter is: " + filter, 35);
311
      MetaCatUtil.debugMessage("Provider URL is: " + ldapUrl + ldapBase, 35);
312
      NamingEnumeration answer;
313
      try {
314
        util.debugMessage("Trying search 1: " + filter, 35);
315
        answer = ctx.search("", filter, ctls);
316
        util.debugMessage("Search 1 complete", 35);
317
        if (answer == null) {
318
          util.debugMessage("Search 1 answer is null.", 35);
319
        }
320
        if (answer.hasMore()) {
321
          util.debugMessage("Search 1 has answers.", 35);
322
          SearchResult sr = (SearchResult) answer.next();
323
          identifier = sr.getName();
324
          util.debugMessage("Originally Found: " + identifier, 35);
325
          return identifier;
326
        }
327
      }
328
      catch (InvalidSearchFilterException e) {
329
        util.debugMessage("Invalid Filter exception thrown (if1)", 35);
330
      }
331

    
332
      // That failed, so check if it is just a username
333
      filter = "(" + user + ")";
334
      try {
335
        MetaCatUtil.debugMessage("Trying again: " + filter, 35);
336
        answer = ctx.search("", filter, ctls);
337
        if (answer.hasMore()) {
338
          SearchResult sr = (SearchResult) answer.next();
339
          identifier = sr.getName();
340
          if (!sr.isRelative()) {
341
            this.ldapUrl = identifier.substring(0,
342
                                                identifier.lastIndexOf("/") + 1);
343
            this.ldapBase = identifier.substring(identifier.indexOf(",") + 1);
344
            identifier = identifier.substring(identifier.lastIndexOf("/") + 1,
345
                                              identifier.indexOf(","));
346
          }
347
          util.debugMessage("Found: " + identifier, 35);
348
          return identifier;
349
        }
350
      }
351
      catch (InvalidSearchFilterException e) {}
352

    
353
      // Maybe its a user id (uid)
354
      filter = "(uid=" + user + ")";
355
      MetaCatUtil.debugMessage("Trying again: " + filter, 35);
356
      answer = ctx.search("", filter, ctls);
357
      if (answer.hasMore()) {
358
        SearchResult sr = (SearchResult) answer.next();
359
        identifier = sr.getName();
360
        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
                                            identifier.indexOf(","));
366
        }
367
        util.debugMessage("Found: " + identifier, 35);
368
      }
369
      else {
370

    
371
        // maybe its just a common name
372
        filter = "(cn=" + user + ")";
373
        MetaCatUtil.debugMessage("Trying again: " + filter, 35);
374
        NamingEnumeration answer2 = ctx.search("", filter, ctls);
375
        if (answer2.hasMore()) {
376
          SearchResult sr = (SearchResult) answer2.next();
377
          identifier = sr.getName();
378
          if (!sr.isRelative()) {
379
            this.ldapUrl = identifier.substring(0,
380
                                                identifier.lastIndexOf("/") + 1);
381
            this.ldapBase = identifier.substring(identifier.indexOf(",") + 1);
382
            identifier = identifier.substring(identifier.lastIndexOf("/") + 1,
383
                                              identifier.indexOf(","));
384
          }
385
          util.debugMessage("Found: " + identifier, 35);
386
        }
387
        else {
388

    
389
          // ok, last resort, is it a surname?
390
          filter = "(sn=" + user + ")";
391
          MetaCatUtil.debugMessage("Trying again: " + filter, 35);
392
          NamingEnumeration answer3 = ctx.search("", filter, ctls);
393
          if (answer3.hasMore()) {
394
            SearchResult sr = (SearchResult) answer3.next();
395
            identifier = sr.getName();
396
            if (!sr.isRelative()) {
397
              this.ldapUrl = identifier.substring(0,
398
                                                  identifier.lastIndexOf("/") +
399
                                                  1);
400
              this.ldapBase = identifier.substring(identifier.indexOf(",") + 1);
401
              identifier = identifier.substring(identifier.lastIndexOf("/") + 1,
402
                                                identifier.indexOf(","));
403
            }
404
            util.debugMessage("Found: " + identifier, 35);
405
          }
406
        }
407
      }
408
      // Close the context when we're done the initial search
409
      ctx.close();
410
    }
411
    catch (NamingException e) {
412
      util.debugMessage("Naming exception while getting dn: " + e, 35);
413
      throw new NamingException(
414
          "Naming exception in AuthLdap.getIdentifyingName: " + e);
415
    }
416
    MetaCatUtil.debugMessage("Returning found identifier as: " + identifier, 35);
417
    return identifier;
418
  }
419

    
420
  /**
421
   * Get all users from the authentication service
422
   *
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
   */
427
  public String[][] getUsers(String user, String password) throws
428
      ConnectException {
429
    String[][] users = null;
430

    
431
    // Identify service provider to use
432
    Hashtable env = new Hashtable(11);
433
    env.put(Context.INITIAL_CONTEXT_FACTORY,
434
            "com.sun.jndi.ldap.LdapCtxFactory");
435
    env.put(Context.REFERRAL, referral);
436
    env.put(Context.PROVIDER_URL, ldapUrl);
437

    
438
    try {
439

    
440
      // Create the initial directory context
441
      DirContext ctx = new InitialDirContext(env);
442

    
443
      // Specify the attributes to match.
444
      // Users are objects that have the attribute objectclass=InetOrgPerson.
445
      SearchControls ctls = new SearchControls();
446
      String[] attrIDs = {
447
          "dn", "cn", "o", "ou", "mail"};
448
      ctls.setReturningAttributes(attrIDs);
449
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
450
      //ctls.setCountLimit(1000);
451
      String filter = "(objectClass=inetOrgPerson)";
452
      NamingEnumeration enum = ctx.search(ldapBase, filter, ctls);
453

    
454
      // Store the users in a vector
455
      Vector uvec = new Vector();
456
      Vector uname = new Vector();
457
      Vector uorg = new Vector();
458
      Vector uou = new Vector();
459
      Vector umail = new Vector();
460
      Attributes tempAttr = null;
461
      try {
462
        while (enum.hasMore()) {
463
          SearchResult sr = (SearchResult) enum.next();
464
          tempAttr = sr.getAttributes();
465

    
466
          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

    
473
          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

    
480
          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
          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

    
494
          uvec.add(sr.getName() + "," + ldapBase);
495
        }
496
      }
497
      catch (SizeLimitExceededException slee) {
498
        util.debugMessage("LDAP Server size limit exceeded. " +
499
                          "Returning incomplete record set.", 35);
500
      }
501

    
502
      // initialize users[]; fill users[]
503
      users = new String[uvec.size()][5];
504
      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
        users[i][3] = (String) uorg.elementAt(i);
509
        users[i][4] = (String) umail.elementAt(i);
510
      }
511

    
512
      // Close the context when we're done
513
      ctx.close();
514

    
515
    }
516
    catch (NamingException e) {
517
      util.debugMessage("Problem getting users in AuthLdap.getUsers:" + e, 35);
518
      //e.printStackTrace(System.err);
519
      throw new ConnectException(
520
          "Problem getting users in AuthLdap.getUsers:" + e);
521
    }
522

    
523
    return users;
524
  }
525

    
526
  /**
527
   * Get the users for a particular group from the authentication service
528
   *
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
   */
534
  public String[] getUsers(String user, String password, String group) throws
535
      ConnectException {
536
    String[] users = null;
537

    
538
    // Identify service provider to use
539
    Hashtable env = new Hashtable(11);
540
    env.put(Context.INITIAL_CONTEXT_FACTORY,
541
            "com.sun.jndi.ldap.LdapCtxFactory");
542
    env.put(Context.REFERRAL, referral);
543
    env.put(Context.PROVIDER_URL, ldapUrl);
544

    
545
    try {
546

    
547
      // Create the initial directory context
548
      DirContext ctx = new InitialDirContext(env);
549

    
550
      // Specify the ids of the attributes to return
551
      String[] attrIDs = {
552
          "uniqueMember"};
553

    
554
      Attributes answer = ctx.getAttributes(group, attrIDs);
555

    
556
      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
        }
567
      }
568
      catch (SizeLimitExceededException slee) {
569
        util.debugMessage("LDAP Server size limit exceeded. " +
570
                          "Returning incomplete record set.", 35);
571
      }
572

    
573
      // 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

    
579
      // Close the context when we're done
580
      ctx.close();
581

    
582
    }
583
    catch (NamingException e) {
584
      util.debugMessage("Problem getting users for a group in " +
585
                        "AuthLdap.getUsers:" + e, 30);
586
      throw new ConnectException(
587
          "Problem getting users for a group in AuthLdap.getUsers:" + e);
588
    }
589

    
590
    return users;
591
  }
592

    
593
  /**
594
   * Get all groups from the authentication service
595
   *
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
   */
600
  public String[][] getGroups(String user, String password) throws
601
      ConnectException {
602
    return getGroups(user, password, null);
603
  }
604

    
605
  /**
606
   * Get the groups for a particular user from the authentication service
607
   *
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
   */
613
  public String[][] getGroups(String user, String password, String foruser) throws
614
      ConnectException {
615
    Vector gvec = new Vector();
616
    Vector desc = new Vector();
617
    Attributes tempAttr = null;
618

    
619
    //Pass the username and password to run() method
620
    userName = user;
621
    userPassword = password;
622
    // Identify service provider to use
623
    env.put(Context.INITIAL_CONTEXT_FACTORY,
624
            "com.sun.jndi.ldap.LdapCtxFactory");
625
    env.put(Context.REFERRAL, "throw");
626
    env.put(Context.PROVIDER_URL, ldapUrl);
627
    try {
628
      // 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

    
640
      String filter = null;
641
      String gfilter = "(objectClass=groupOfUniqueNames)";
642
      if (null == foruser) {
643
        filter = gfilter;
644
      }
645
      else {
646
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
647
      }
648
      MetaCatUtil.debugMessage("searching for groups: " + filter, 35);
649
      NamingEnumeration enum = ctx.search(ldapBase, filter, ctls);
650

    
651
      // Print the groups
652
      MetaCatUtil.debugMessage("getting group results.", 50);
653
      while (enum.hasMore()) {
654
        SearchResult sr = (SearchResult) enum.next();
655
        tempAttr = sr.getAttributes();
656

    
657
        if ( (tempAttr.get("description") + "").startsWith("description: ")) {
658
          desc.add( (tempAttr.get("description") + "").substring(13));
659
        }
660
        else {
661
          desc.add(tempAttr.get("description") + "");
662
        }
663

    
664
        gvec.add(sr.getName() + "," + ldapBase);
665
        MetaCatUtil.debugMessage("group " + sr.getName() +
666
                                 " added to Group vector", 35);
667
      }
668
      // Close the context when we're done
669
      ctx.close();
670

    
671
    }
672
    catch (ReferralException re) {
673
      refExc = re;
674
      Thread t = new Thread(new GetGroup());
675
      util.debugMessage("Starting thread...", 50);
676
      t.start();
677
      util.debugMessage("sleeping for 5 seconds.", 50);
678
      try {
679
        Thread.sleep(5000);
680
      }
681
      catch (InterruptedException ie) {
682
        MetaCatUtil.debugMessage("main thread interrupted: " + ie.getMessage(),
683
                                 30);
684
      }
685
      //this is a manual override of jndi's hideously long time
686
      //out period.
687
      util.debugMessage("Awake after 5 seconds.", 40);
688
      if (referralContext == null) {
689
        util.debugMessage("thread timed out...returning groups: " +
690
                          gvec.toString(), 35);
691
        String groups[][] = new String[gvec.size()][2];
692
        for (int i = 0; i < gvec.size(); i++) {
693
          groups[i][0] = (String) gvec.elementAt(i);
694
          groups[i][1] = (String) desc.elementAt(i);
695
        }
696
        t.interrupt();
697
        return groups;
698
      }
699
      DirContext dc = (DirContext) referralContext;
700
      String[] attrIDs = {
701
          "cn", "o", "description"};
702
      // Specify the attributes to match.
703
      // Groups are objects with attribute objectclass=groupofuniquenames.
704
      // and have attribute uniquemember: uid=foruser,ldapbase.
705
      SearchControls ctls = new SearchControls();
706
      ctls.setReturningAttributes(attrIDs);
707
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
708

    
709
      String filter = null;
710
      String gfilter = "(objectClass=groupOfUniqueNames)";
711
      if (null == foruser) {
712
        filter = gfilter;
713
      }
714
      else {
715
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
716
      }
717

    
718
      try {
719
        NamingEnumeration enum = dc.search(ldapBase, filter, ctls);
720
        // Print the groups
721
        while (enum.hasMore()) {
722
          SearchResult sr = (SearchResult) enum.next();
723
          tempAttr = sr.getAttributes();
724

    
725
          if ( (tempAttr.get("description") + "").startsWith("description: ")) {
726
            desc.add( (tempAttr.get("description") + "").substring(13));
727
          }
728
          else {
729
            desc.add(tempAttr.get("description") + "");
730
          }
731

    
732
          gvec.add(sr.getName() + "," + ldapBase);
733
        }
734

    
735
        referralContext.close();
736
        dc.close();
737
      }
738
      catch (NamingException ne) {
739
        MetaCatUtil.debugMessage("Naming Exception in AuthLdap.getGroups" +
740
                                 ne.getExplanation() + ne.getMessage(), 30);
741
      }
742
    }
743
    catch (NamingException e) {
744
      e.printStackTrace(System.err);
745
      String groups[][] = new String[gvec.size()][2];
746
      for (int i = 0; i < gvec.size(); i++) {
747
        groups[i][0] = (String) gvec.elementAt(i);
748
        groups[i][1] = (String) desc.elementAt(i);
749
      }
750
      return groups;
751
      /*throw new ConnectException(
752
             "Problem getting groups for a user in AuthLdap.getGroups:" + e);*/
753
    }
754

    
755
    MetaCatUtil.debugMessage("The user is in the following groups: " +
756
                             gvec.toString(), 35);
757
    String groups[][] = new String[gvec.size()][2];
758
    for (int i = 0; i < gvec.size(); i++) {
759
      groups[i][0] = (String) gvec.elementAt(i);
760
      groups[i][1] = (String) desc.elementAt(i);
761
    }
762
    return groups;
763
  }
764

    
765
  /**
766
   * Get attributes describing a user or group
767
   *
768
   * @param foruser the user for which the attribute list is requested
769
   * @returns HashMap a map of attribute name to a Vector of values
770
   */
771
  public HashMap getAttributes(String foruser) throws ConnectException {
772
    return getAttributes(null, null, foruser);
773
  }
774

    
775
  /**
776
   * Get attributes describing a user or group
777
   *
778
   * @param user the user for authenticating against the service
779
   * @param password the password for authenticating against the service
780
   * @param foruser the user whose attributes should be returned
781
   * @returns HashMap a map of attribute name to a Vector of values
782
   */
783
  public HashMap getAttributes(String user, String password, String foruser) throws
784
      ConnectException {
785
    HashMap attributes = new HashMap();
786
    String ldapUrl = this.ldapUrl;
787
    String ldapBase = this.ldapBase;
788
    String userident = foruser;
789

    
790
    // Identify service provider to use
791
    Hashtable env = new Hashtable(11);
792
    env.put(Context.INITIAL_CONTEXT_FACTORY,
793
            "com.sun.jndi.ldap.LdapCtxFactory");
794
    env.put(Context.REFERRAL, referral);
795
    env.put(Context.PROVIDER_URL, ldapUrl);
796

    
797
    try {
798

    
799
      // Create the initial directory context
800
      DirContext ctx = new InitialDirContext(env);
801

    
802
      // Ask for all attributes of the user
803
      //Attributes attrs = ctx.getAttributes(userident);
804
      Attributes attrs = ctx.getAttributes(foruser);
805

    
806
      // Print all of the attributes
807
      NamingEnumeration en = attrs.getAll();
808
      while (en.hasMore()) {
809
        Attribute att = (Attribute) en.next();
810
        Vector values = new Vector();
811
        String attName = att.getID();
812
        NamingEnumeration attvalues = att.getAll();
813
        while (attvalues.hasMore()) {
814
          String value = (String) attvalues.next();
815
          values.add(value);
816
        }
817
        attributes.put(attName, values);
818
      }
819

    
820
      // Close the context when we're done
821
      ctx.close();
822
    }
823
    catch (NamingException e) {
824
      util.debugMessage("Problem getting attributes in " +
825
                        "AuthLdap.getAttributes:" + e, 35);
826
      throw new ConnectException(
827
          "Problem getting attributes in AuthLdap.getAttributes:" + e);
828
    }
829

    
830
    return attributes;
831
  }
832

    
833
  /**
834
   * Get list of all subtrees holding Metacat's groups and users
835
   * starting from the Metacat LDAP root,
836
   * i.e. ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
837
   */
838
  private Hashtable getSubtrees(String user, String password,
839
                                String ldapUrl, String ldapBase) throws
840
      ConnectException {
841
    Hashtable trees = new Hashtable();
842

    
843
    // Identify service provider to use
844
    Hashtable env = new Hashtable(11);
845
    env.put(Context.INITIAL_CONTEXT_FACTORY,
846
            "com.sun.jndi.ldap.LdapCtxFactory");
847
    // env.put(Context.REFERRAL, referral);
848
    // Using 'ignore' here instead of 'follow' as 'ignore' seems
849
    // to do the job better. 'follow' was not bringing up the UCNRS
850
    // and PISCO tree whereas 'ignore' brings up the tree.
851

    
852
    env.put(Context.REFERRAL, "ignore");
853
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
854

    
855
    try {
856

    
857
      // Create the initial directory context
858
      DirContext ctx = new InitialDirContext(env);
859

    
860
      // Specify the ids of the attributes to return
861
      String[] attrIDs = {
862
          "o", "ref"};
863
      SearchControls ctls = new SearchControls();
864
      ctls.setReturningAttributes(attrIDs);
865
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
866

    
867
      // Specify the attributes to match.
868
      // Subtrees from the main server are found as objects with attribute
869
      // objectclass=organization or objectclass=referral to the subtree
870
      // resided on other server.
871
      String filter = "(|(objectclass=organization)(objectclass=referral))";
872

    
873
      // Search for objects in the current context
874
      NamingEnumeration enum = ctx.search("", filter, ctls);
875

    
876
      // Print the subtrees' <ldapURL, baseDN>
877
      while (enum.hasMore()) {
878

    
879
        SearchResult sr = (SearchResult) enum.next();
880

    
881
        Attributes attrs = sr.getAttributes();
882
        NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref" attrs
883

    
884
        if (enum1.hasMore()) {
885
          Attribute attr = (Attribute) enum1.next();
886
          String attrValue = (String) attr.get();
887
          String attrName = (String) attr.getID();
888

    
889
          if (enum1.hasMore()) {
890
            attr = (Attribute) enum1.next();
891
            String refValue = (String) attr.get();
892
            String refName = (String) attr.getID();
893
            if (ldapBase.startsWith(refName + "=" + refValue)) {
894
              trees.put(ldapBase,
895
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
896
            }
897
            else {
898
              // this is a referral - so organization name is appended in
899
              // front of the ldapbase.... later it is stripped out
900
              // in getPrincipals
901
              trees.put("[" + refName + "=" + refValue + "]" +
902
                        attrValue.substring(attrValue.lastIndexOf("/") + 1,
903
                                            attrValue.length()),
904
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
905

    
906
              // trees.put(refName + "=" + refValue + "," + ldapBase,
907
              //           attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
908
            }
909

    
910
          }
911
          else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
912
            trees.put(ldapBase, ldapUrl);
913
          }
914
          else {
915
            if (sr.isRelative()) {
916
              trees.put(attrName + "=" + attrValue + "," + ldapBase, ldapUrl);
917
            }
918
            else {
919
              String referenceURL = sr.getName();
920
              referenceURL = referenceURL.substring(0,
921
                  referenceURL.lastIndexOf("/") + 1);
922
              trees.put(attrName + "=" + attrValue + "," + ldapBase,
923
                        referenceURL);
924
            }
925

    
926
          }
927
        }
928
      }
929

    
930
      // Close the context when we're done
931
      ctx.close();
932

    
933
    }
934
    catch (NamingException e) {
935
      util.debugMessage("Problem getting subtrees in AuthLdap.getSubtrees:"
936
                        + e, 30);
937
      throw new ConnectException(
938
          "Problem getting subtrees in AuthLdap.getSubtrees:" + e);
939
    }
940

    
941
    return trees;
942
  }
943

    
944
  /**
945
   * Get all groups and users from authentication scheme.
946
   * The output is formatted in XML.
947
   * @param user the user which requests the information
948
   * @param password the user's password
949
   */
950
  public String getPrincipals(String user, String password) throws
951
      ConnectException {
952
    StringBuffer out = new StringBuffer();
953
    Vector usersIn = new Vector();
954

    
955
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
956
    out.append("<principals>\n");
957

    
958
    /*
959
     * get all subtrees first in the current dir context
960
     * and then the Metacat users under them
961
     */
962
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
963
                                     this.ldapBase);
964

    
965
    Enumeration enum = subtrees.keys();
966
    while (enum.hasMoreElements()) {
967
      this.ldapBase = (String) enum.nextElement();
968
      this.ldapUrl = (String) subtrees.get(ldapBase);
969

    
970
      /*
971
       * code to get the organization name from ldapBase
972
       */
973
      String orgName = this.ldapBase;
974
      if (orgName.startsWith("[")) {
975
        // if orgName starts with [ then it is a referral URL...
976
        // (see code in getSubtress)
977
        // hence orgName can be retrieved  by getting the string between
978
        // 'o=' and ']'
979
        // also the string between [ and ] needs to be striped out from
980
        // this.ldapBase
981
        this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
982
        if (orgName != null && orgName.indexOf("o=") > -1) {
983
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
984
          orgName = orgName.substring(0, orgName.indexOf("]"));
985
        }
986
      }
987
      else {
988
        // else it is not referral
989
        // hence orgName can be retrieved  by getting the string between
990
        // 'o=' and ','
991
        if (orgName != null && orgName.indexOf("o=") > -1) {
992
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
993
          if (orgName.indexOf(",") > -1) {
994
            orgName = orgName.substring(0, orgName.indexOf(","));
995
          }
996
        }
997
      }
998

    
999
      out.append("  <authSystem URI=\"" +
1000
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
1001
                 "\">\n");
1002

    
1003
      // get all groups for directory context
1004
      String[][] groups = getGroups(user, password);
1005
      String[][] users = getUsers(user, password);
1006
      int userIndex = 0;
1007

    
1008
      // for the groups and users that belong to them
1009
      if (groups != null && groups.length > 0) {
1010
        for (int i = 0; i < groups.length; i++) {
1011
          out.append("    <group>\n");
1012
          out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1013
          out.append("      <description>" + groups[i][1] + "</description>\n");
1014
          String[] usersForGroup = getUsers(user, password, groups[i][0]);
1015
          for (int j = 0; j < usersForGroup.length; j++) {
1016
            usersIn.addElement(usersForGroup[j]);
1017

    
1018
            userIndex = searchUser(usersForGroup[j], users);
1019
            out.append("      <user>\n");
1020

    
1021
            if (userIndex < 0) {
1022
              out.append("        <username>" + usersForGroup[j] +
1023
                         "</username>\n");
1024
            }
1025
            else {
1026
              out.append("        <username>" + users[userIndex][0] +
1027
                         "</username>\n");
1028
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1029
              out.append("        <organization>" + users[userIndex][2] +
1030
                         "</organization>\n");
1031
              if (users[userIndex][3].compareTo("null") != 0) {
1032
                out.append("      <organizationUnitName>" + users[userIndex][3] +
1033
                           "</organizationUnitName>\n");
1034
              }
1035
              out.append("        <email>" + users[userIndex][4] + "</email>\n");
1036
            }
1037

    
1038
            out.append("      </user>\n");
1039
          }
1040
          out.append("    </group>\n");
1041
        }
1042
      }
1043

    
1044
      // for the users not belonging to any grou8p
1045
      for (int j = 0; j < users.length; j++) {
1046
        if (!usersIn.contains(users[j][0])) {
1047
          out.append("    <user>\n");
1048
          out.append("      <username>" + users[j][0] + "</username>\n");
1049
          out.append("      <name>" + users[j][1] + "</name>\n");
1050
          out.append("      <organization>" + users[j][2] +
1051
                     "</organization>\n");
1052
          if (users[j][3].compareTo("null") != 0) {
1053
            out.append("      <organizationUnitName>" + users[j][3] +
1054
                       "</organizationUnitName>\n");
1055
          }
1056
          out.append("      <email>" + users[j][4] + "</email>\n");
1057
          out.append("    </user>\n");
1058
        }
1059
      }
1060

    
1061
      out.append("  </authSystem>\n");
1062
      if (!usersIn.isEmpty()) {
1063
        usersIn.removeAllElements();
1064
        usersIn.trimToSize();
1065
      }
1066

    
1067
    }
1068
    out.append("</principals>");
1069
    return out.toString();
1070
  }
1071

    
1072
  /**
1073
   * Method for getting index of user DN in User info array
1074
   */
1075
  int searchUser(String user, String userGroup[][]) {
1076
    for (int j = 0; j < userGroup.length; j++) {
1077
      if (user.compareTo(userGroup[j][0]) == 0) {
1078
        return j;
1079
      }
1080
    }
1081
    return -1;
1082
  }
1083

    
1084
  /**
1085
   * Test method for the class
1086
   */
1087
  public static void main(String[] args) {
1088

    
1089
    // Provide a user, such as: "Matt Jones", or "jones"
1090
    String user = args[0];
1091
    String password = args[1];
1092

    
1093
    MetaCatUtil.debugMessage("Creating session...", 20);
1094
    AuthLdap authservice = new AuthLdap();
1095
    MetaCatUtil.debugMessage("Session exists...", 20);
1096

    
1097
    boolean isValid = false;
1098
    try {
1099
      MetaCatUtil.debugMessage("Authenticating...", 20);
1100
      isValid = authservice.authenticate(user, password);
1101
      if (isValid) {
1102
        MetaCatUtil.debugMessage("Authentication successful for: " + user, 20);
1103
      }
1104
      else {
1105
        MetaCatUtil.debugMessage("Authentication failed for: " + user, 20);
1106
      }
1107

    
1108
      // Get attributes for the user
1109
      if (isValid) {
1110
        MetaCatUtil.debugMessage("\nGetting attributes for user....", 20);
1111
        HashMap userInfo = authservice.getAttributes(user, password, user);
1112
        // Print all of the attributes
1113
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1114
        while (attList.hasNext()) {
1115
          String att = (String) attList.next();
1116
          Vector values = (Vector) userInfo.get(att);
1117
          Iterator attvalues = values.iterator();
1118
          while (attvalues.hasNext()) {
1119
            String value = (String) attvalues.next();
1120
            MetaCatUtil.debugMessage(att + ": " + value, 20);
1121
          }
1122
        }
1123
      }
1124

    
1125
      // get the groups
1126
      if (isValid) {
1127
        MetaCatUtil.debugMessage("\nGetting all groups....", 20);
1128
        String[][] groups = authservice.getGroups(user, password);
1129
        MetaCatUtil.debugMessage("Groups found: " + groups.length, 20);
1130
        for (int i = 0; i < groups.length; i++) {
1131
          MetaCatUtil.debugMessage("Group " + i + ": " + groups[i][0], 20);
1132
        }
1133
      }
1134

    
1135
      // get the groups for the user
1136
      String savedGroup = null;
1137
      if (isValid) {
1138
        MetaCatUtil.debugMessage("\nGetting groups for user....", 20);
1139
        String[][] groups = authservice.getGroups(user, password, user);
1140
        MetaCatUtil.debugMessage("Groups found: " + groups.length, 20);
1141
        for (int i = 0; i < groups.length; i++) {
1142
          MetaCatUtil.debugMessage("Group " + i + ": " + groups[i][0], 20);
1143
          savedGroup = groups[i][0];
1144
        }
1145
      }
1146

    
1147
      // get the users for a group
1148
      if (isValid) {
1149
        MetaCatUtil.debugMessage("\nGetting users for group....", 20);
1150
        MetaCatUtil.debugMessage("Group: " + savedGroup, 20);
1151
        String[] users = authservice.getUsers(user, password, savedGroup);
1152
        MetaCatUtil.debugMessage("Users found: " + users.length, 20);
1153
        for (int i = 0; i < users.length; i++) {
1154
          MetaCatUtil.debugMessage("User " + i + ": " + users[i], 20);
1155
        }
1156
      }
1157

    
1158
      // get all users
1159
      if (isValid) {
1160
        MetaCatUtil.debugMessage("\nGetting all users ....", 20);
1161
        String[][] users = authservice.getUsers(user, password);
1162
        MetaCatUtil.debugMessage("Users found: " + users.length, 20);
1163

    
1164
      }
1165

    
1166
      // get the whole list groups and users in XML format
1167
      if (isValid) {
1168
        MetaCatUtil.debugMessage("\nTrying principals....", 20);
1169
        authservice = new AuthLdap();
1170
        String out = authservice.getPrincipals(user, password);
1171
        java.io.File f = new java.io.File("principals.xml");
1172
        java.io.FileWriter fw = new java.io.FileWriter(f);
1173
        java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1174
        buff.write(out);
1175
        buff.flush();
1176
        buff.close();
1177
        fw.close();
1178
        MetaCatUtil.debugMessage("\nFinished getting principals.", 20);
1179
      }
1180

    
1181
    }
1182
    catch (ConnectException ce) {
1183
      MetaCatUtil.debugMessage(ce.getMessage(), 30);
1184
    }
1185
    catch (java.io.IOException ioe) {
1186
      MetaCatUtil.debugMessage("I/O Error writing to file principals.txt", 20);
1187
    }
1188
  }
1189

    
1190
  /**
1191
   * This method will be called by start a thread.
1192
   * It can handle if a referral exception happend.
1193
   */
1194
  public void run() {
1195
    referralContext = null;
1196
    DirContext refDirContext = null;
1197
    boolean moreReferrals = true;
1198
    String referralInfo = null;
1199
    //set a while loop is because we don't know if a referral excption contains
1200
    //another referral exception
1201
    while (moreReferrals) {
1202
      try {
1203
        //revise environment variable
1204
        referralInfo = (String) refExc.getReferralInfo();
1205
        util.debugMessage("Processing referral (pr0): ", 35);
1206
        util.debugMessage("PROVIDER_URL set to (pr1): " + referralInfo, 35);
1207
        //env.put(Context.PROVIDER_URL,referralInfo);
1208
        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1209
        //env.put(Context.SECURITY_PRINCIPAL, userName);
1210
        //env.put(Context.SECURITY_CREDENTIALS, userPassword);
1211
        //env.put(Context.REFERRAL, "throw");
1212
        //util.debugMessage("Processing referral (pr1.info): " + userName,35);
1213
        //util.debugMessage("Processing referral (pr2)",35);
1214
        //rContext = refExc.getReferralContext(env);
1215
        rContext = refExc.getReferralContext();
1216
        util.debugMessage("Processing referral (pr3)", 35);
1217
        //casting the context to dircontext and it will create a
1218
        //autherntication or naming exception if DN and password is incorrect
1219
        referralContext = rContext;
1220
        refDirContext = (DirContext) rContext;
1221
        refDirContext.close();
1222
        //get context and jump out the while loop
1223
        moreReferrals = false;
1224
        util.debugMessage("Processing referral (pr4)", 35);
1225
      } //try
1226
      //if referral have another referral excption
1227
      catch (ReferralException re) {
1228
        util.debugMessage("GOT referral exception (re1): " + re.getMessage(),
1229
                          35);
1230
        util.debugMessage("RE details (re2): " + re.toString(true), 35);
1231
        //keep running in while loop
1232
        moreReferrals = true;
1233
        //assign refExc to new referral exception re
1234
        refExc = re;
1235
      }
1236
      //catch a authentication exception
1237
      catch (AuthenticationException ae) {
1238
        util.debugMessage("Error running referral handler thread (ae1): " +
1239
                          ae.getMessage(), 20);
1240
        //check if has another referral
1241
        moreReferrals = refExc.skipReferral();
1242
        //don't get the context
1243
        referralContext = null;
1244
      }
1245
      //catch a naming exception
1246
      catch (NamingException ne) {
1247
        util.debugMessage("Error running referral handler thread (ne1): " +
1248
                          ne.getMessage(), 20);
1249
        //check if has another referral
1250
        moreReferrals = refExc.skipReferral();
1251
        //don't get context
1252
        referralContext = null;
1253
      }
1254
    } //while
1255
  } //run()
1256

    
1257
  private class GetGroup
1258
      implements Runnable {
1259
    public void run() {
1260
      referralContext = null;
1261
      MetaCatUtil.debugMessage("getting groups context", 50);
1262
      DirContext refDirContext = null;
1263
      boolean moreReferrals = true;
1264
      //set a while loop is because we don't know if a referral excption
1265
      //contains another referral exception
1266
      while (moreReferrals) {
1267
        try {
1268
          //revise environment variable
1269
          String refInfo = null;
1270
          refInfo = (String) refExc.getReferralInfo();
1271
          if (refInfo != null) {
1272
            MetaCatUtil.debugMessage("Referral in thread to: " +
1273
                                     refInfo.toString(), 40);
1274
          }
1275
          else {
1276
            MetaCatUtil.debugMessage("getting refInfo Manually", 50);
1277
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1278
                get(Context.PROVIDER_URL);
1279
          }
1280
          MetaCatUtil.debugMessage("refInfo: " + refInfo, 40);
1281

    
1282
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1283
                  "com.sun.jndi.ldap.LdapCtxFactory");
1284
          env.put(Context.REFERRAL, "throw");
1285
          env.put(Context.PROVIDER_URL, refInfo);
1286

    
1287
          MetaCatUtil.debugMessage("creating referralContext", 40);
1288
          referralContext = new InitialDirContext(env);
1289
          MetaCatUtil.debugMessage("referralContext created", 40);
1290
          //get context and jump out the while loop
1291
          moreReferrals = false;
1292
        } //try
1293
        catch (ReferralException re) {
1294
          //keep running in while loop
1295
          moreReferrals = true;
1296
          //assign refExc to new referral exception re
1297
          refExc = re;
1298
        }
1299
        catch (AuthenticationException ae) {
1300
          util.debugMessage("Error running referral handler thread (ae2): " +
1301
                            ae.getMessage(), 50);
1302
          //check if has another referral
1303
          moreReferrals = refExc.skipReferral();
1304
          //don't get the context
1305
          referralContext = null;
1306
        }
1307
        catch (NamingException ne) {
1308
          util.debugMessage("Error running referral handler thread (ne2): " +
1309
                            ne.getMessage(), 50);
1310
          //check if has another referral
1311
          moreReferrals = refExc.skipReferral();
1312
          //don't get context
1313
          referralContext = null;
1314
        }
1315
      } //while
1316
    } //run()
1317
  }
1318
}
(12-12/61)