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: 2005-09-09 13:59:22 -0700 (Fri, 09 Sep 2005) $'
13
 * '$Revision: 2589 $'
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.logMetacat.info("Looking up DN for: " + identifier);
114
        identifier = getIdentifyingName(identifier, ldapUrl, ldapBase);
115
        MetaCatUtil.logMetacat.info("DN found: " + identifier);
116
        String decoded = URLDecoder.decode(identifier);
117
        MetaCatUtil.logMetacat.info("DN decoded: " + decoded);
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.logMetacat.info("Ref ldapUrl: " + refUrl);
125
          int position = identifier.indexOf(",");
126
          int position2 = identifier.indexOf(",", position + 1);
127
          refBase = identifier.substring(position2 + 1);
128
          MetaCatUtil.logMetacat.info("Ref ldapBase: " + refBase);
129
          identifier = identifier.substring(
130
              identifier.lastIndexOf("/") + 1);
131
          MetaCatUtil.logMetacat.info("Trying: " + identifier);
132
          authenticated = ldapAuthenticate(identifier, password,
133
                                           refUrl, refBase);
134
        }
135
        else {
136
          identifier = identifier + "," + ldapBase;
137
          MetaCatUtil.logMetacat.info("Trying: " + identifier);
138
          authenticated = ldapAuthenticate(identifier, password);
139
        }
140
        //authenticated = ldapAuthenticate(identifier, password);
141
      }
142

    
143
    }
144
    catch (NullPointerException e) {
145
      MetaCatUtil.logMetacat.info("NullPointerException b' password is null");
146
      MetaCatUtil.logMetacat.info("NullPointerException while authenticating in " +
147
                        "AuthLdap.authenticate: " + e);
148
      throw new ConnectException(
149
          "NullPointerException while authenticating in " +
150
          "AuthLdap.authenticate: " + e);
151
    }
152
    catch (NamingException e) {
153
      MetaCatUtil.logMetacat.info("Naming exception while authenticating in " +
154
                        "AuthLdap.authenticate: " + e);
155
      e.printStackTrace();
156
    }
157
    catch (Exception e) {
158
      MetaCatUtil.logMetacat.info(e.getMessage());
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
      MetaCatUtil.logMetacat.info("PROVIDER_URL set to: " + directoryUrl + searchBase);
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
        MetaCatUtil.logMetacat.info("Connection time thru " + ldapsUrl + " was: " +
216
                          (stopTime - startTime) / 1000 + " seconds.");
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
        MetaCatUtil.logMetacat.info("An invalid DN was provided!");
232
      }
233
      catch (javax.naming.ReferralException re) {
234
        MetaCatUtil.logMetacat.info("referral during authentication");
235
        MetaCatUtil.logMetacat.info("Referral information: " + re.getReferralInfo());
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
          MetaCatUtil.logMetacat.info("Awake after 5 seconds.");
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
      MetaCatUtil.logMetacat.info("User not found");
259
    }
260
    double totStopTime = System.currentTimeMillis();
261
    MetaCatUtil.logMetacat.info("total ldap authentication time: " +
262
                      (totStopTime - totStartTime) / 1000 + " seconds");
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
    MetaCatUtil.logMetacat.info("setting referrals to: " + referral);
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.logMetacat.info("First comp is: " + comp1);
304
      String comp2 = user.substring(position + 1,
305
                                    user.indexOf(",", position + 1));
306
      MetaCatUtil.logMetacat.info("Second comp is: " + comp2);
307

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

    
332
      // That failed, so check if it is just a username
333
      filter = "(" + user + ")";
334
      try {
335
        MetaCatUtil.logMetacat.info("Trying again: " + filter);
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
          MetaCatUtil.logMetacat.info("Found: " + identifier);
348
          return identifier;
349
        }
350
      }
351
      catch (InvalidSearchFilterException e) {}
352

    
353
      // Maybe its a user id (uid)
354
      filter = "(uid=" + user + ")";
355
      MetaCatUtil.logMetacat.info("Trying again: " + filter);
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
        MetaCatUtil.logMetacat.info("Found: " + identifier);
368
      }
369
      else {
370

    
371
        // maybe its just a common name
372
        filter = "(cn=" + user + ")";
373
        MetaCatUtil.logMetacat.info("Trying again: " + filter);
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
          MetaCatUtil.logMetacat.info("Found: " + identifier);
386
        }
387
        else {
388

    
389
          // ok, last resort, is it a surname?
390
          filter = "(sn=" + user + ")";
391
          MetaCatUtil.logMetacat.info("Trying again: " + filter);
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
            MetaCatUtil.logMetacat.info("Found: " + identifier);
405
          }
406
        }
407
      }
408
      // Close the context when we're done the initial search
409
      ctx.close();
410
    }
411
    catch (NamingException e) {
412
      MetaCatUtil.logMetacat.info("Naming exception while getting dn: " + e);
413
      throw new NamingException(
414
          "Naming exception in AuthLdap.getIdentifyingName: " + e);
415
    }
416
    MetaCatUtil.logMetacat.info("Returning found identifier as: " + identifier);
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 namingEnum = 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 (namingEnum.hasMore()) {
463
          SearchResult sr = (SearchResult) namingEnum.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
        MetaCatUtil.logMetacat.info("LDAP Server size limit exceeded. " +
499
                          "Returning incomplete record set.");
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
      MetaCatUtil.logMetacat.info("Problem getting users in AuthLdap.getUsers:" + e);
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
        MetaCatUtil.logMetacat.info("LDAP Server size limit exceeded. " +
570
                          "Returning incomplete record set.");
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
      MetaCatUtil.logMetacat.info("Problem getting users for a group in " +
585
                        "AuthLdap.getUsers:" + e);
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.logMetacat.info("searching for groups: " + filter);
649
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
650

    
651
      // Print the groups
652
      MetaCatUtil.logMetacat.info("getting group results.");
653
      while (namingEnum.hasMore()) {
654
        SearchResult sr = (SearchResult) namingEnum.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.logMetacat.info("group " + sr.getName() +
666
                                 " added to Group vector");
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
      MetaCatUtil.logMetacat.info("Starting thread...");
676
      t.start();
677
      MetaCatUtil.logMetacat.info("sleeping for 5 seconds.");
678
      try {
679
        Thread.sleep(5000);
680
      }
681
      catch (InterruptedException ie) {
682
        MetaCatUtil.logMetacat.info("main thread interrupted: " + ie.getMessage());
683
      }
684
      //this is a manual override of jndi's hideously long time
685
      //out period.
686
      MetaCatUtil.logMetacat.info("Awake after 5 seconds.");
687
      if (referralContext == null) {
688
        MetaCatUtil.logMetacat.info("thread timed out...returning groups: " +
689
                          gvec.toString());
690
        String groups[][] = new String[gvec.size()][2];
691
        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
        }
695
        t.interrupt();
696
        return groups;
697
      }
698
      DirContext dc = (DirContext) referralContext;
699
      String[] attrIDs = {
700
          "cn", "o", "description"};
701
      // 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

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

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

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

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

    
734
        referralContext.close();
735
        dc.close();
736
      }
737
      catch (NamingException ne) {
738
        MetaCatUtil.logMetacat.info("Naming Exception in AuthLdap.getGroups" +
739
                                 ne.getExplanation() + ne.getMessage());
740
      }
741
    }
742
    catch (NamingException e) {
743
      e.printStackTrace(System.err);
744
      String groups[][] = new String[gvec.size()][2];
745
      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
      }
749
      return groups;
750
      /*throw new ConnectException(
751
             "Problem getting groups for a user in AuthLdap.getGroups:" + e);*/
752
    }
753

    
754
    MetaCatUtil.logMetacat.info("The user is in the following groups: " +
755
                             gvec.toString());
756
    String groups[][] = new String[gvec.size()][2];
757
    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
    }
761
    return groups;
762
  }
763

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

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

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

    
796
    try {
797

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

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

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

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

    
829
    return attributes;
830
  }
831

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

    
842
    // Identify service provider to use
843
    Hashtable env = new Hashtable(11);
844
    env.put(Context.INITIAL_CONTEXT_FACTORY,
845
            "com.sun.jndi.ldap.LdapCtxFactory");
846
    // 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
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
853

    
854
    try {
855

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

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

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

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

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

    
878
        SearchResult sr = (SearchResult) namingEnum.next();
879

    
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
          if (enum1.hasMore()) {
889
            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
              // 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
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
904

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

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

    
925
          }
926
        }
927
      }
928

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

    
932
    }
933
    catch (NamingException e) {
934
      MetaCatUtil.logMetacat.info("Problem getting subtrees in AuthLdap.getSubtrees:"
935
                        + e);
936
      throw new ConnectException(
937
          "Problem getting subtrees in AuthLdap.getSubtrees:" + e);
938
    }
939

    
940
    return trees;
941
  }
942

    
943
  /**
944
   * Get all groups and users from authentication scheme.
945
   * The output is formatted in XML.
946
   * @param user the user which requests the information
947
   * @param password the user's password
948
   */
949
  public String getPrincipals(String user, String password) throws
950
      ConnectException {
951
    StringBuffer out = new StringBuffer();
952
   
953
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
954
    out.append("<principals>\n");
955

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

    
963
    Enumeration keyEnum = subtrees.keys();
964
    while (keyEnum.hasMoreElements()) {
965
      this.ldapBase = (String) keyEnum.nextElement();
966
      this.ldapUrl = (String) subtrees.get(ldapBase);
967

    
968
      /*
969
       * code to get the organization name from ldapBase
970
       */
971
      String orgName = this.ldapBase;
972
      if (orgName.startsWith("[")) {
973
        // 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
      }
985
      else {
986
        // 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
      }
996

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

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

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

    
1018
            if (userIndex < 0) {
1019
              out.append("        <username>" + usersForGroup[j] +
1020
                         "</username>\n");
1021
            }
1022
            else {
1023
              out.append("        <username>" + users[userIndex][0] +
1024
                         "</username>\n");
1025
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1026
              out.append("        <organization>" + users[userIndex][2] +
1027
                         "</organization>\n");
1028
              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
            }
1034

    
1035
            out.append("      </user>\n");
1036
          }
1037
          out.append("    </group>\n");
1038
        }
1039
      }
1040

    
1041
      // for the users not belonging to any grou8p
1042
      for (int j = 0; j < users.length; j++) {
1043
          out.append("    <user>\n");
1044
          out.append("      <username>" + users[j][0] + "</username>\n");
1045
          out.append("      <name>" + users[j][1] + "</name>\n");
1046
          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
          out.append("    </user>\n");
1054
      }
1055

    
1056
      out.append("  </authSystem>\n");
1057
    }
1058
    out.append("</principals>");
1059
    return out.toString();
1060
  }
1061

    
1062
  /**
1063
   * Method for getting index of user DN in User info array
1064
   */
1065
  int searchUser(String user, String userGroup[][]) {
1066
    for (int j = 0; j < userGroup.length; j++) {
1067
      if (user.compareTo(userGroup[j][0]) == 0) {
1068
        return j;
1069
      }
1070
    }
1071
    return -1;
1072
  }
1073

    
1074
  /**
1075
   * Test method for the class
1076
   */
1077
  public static void main(String[] args) {
1078

    
1079
    // Provide a user, such as: "Matt Jones", or "jones"
1080
    String user = args[0];
1081
    String password = args[1];
1082

    
1083
    MetaCatUtil.logMetacat.warn("Creating session...");
1084
    AuthLdap authservice = new AuthLdap();
1085
    MetaCatUtil.logMetacat.warn("Session exists...");
1086

    
1087
    boolean isValid = false;
1088
    try {
1089
      MetaCatUtil.logMetacat.warn("Authenticating...");
1090
      isValid = authservice.authenticate(user, password);
1091
      if (isValid) {
1092
        MetaCatUtil.logMetacat.warn("Authentication successful for: " + user);
1093
      }
1094
      else {
1095
        MetaCatUtil.logMetacat.warn("Authentication failed for: " + user);
1096
      }
1097

    
1098
      // Get attributes for the user
1099
      if (isValid) {
1100
        MetaCatUtil.logMetacat.warn("\nGetting attributes for user....");
1101
        HashMap userInfo = authservice.getAttributes(user, password, user);
1102
        // Print all of the attributes
1103
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1104
        while (attList.hasNext()) {
1105
          String att = (String) attList.next();
1106
          Vector values = (Vector) userInfo.get(att);
1107
          Iterator attvalues = values.iterator();
1108
          while (attvalues.hasNext()) {
1109
            String value = (String) attvalues.next();
1110
            MetaCatUtil.logMetacat.warn(att + ": " + value);
1111
          }
1112
        }
1113
      }
1114

    
1115
      // get the groups
1116
      if (isValid) {
1117
        MetaCatUtil.logMetacat.warn("\nGetting all groups....");
1118
        String[][] groups = authservice.getGroups(user, password);
1119
        MetaCatUtil.logMetacat.warn("Groups found: " + groups.length);
1120
        for (int i = 0; i < groups.length; i++) {
1121
          MetaCatUtil.logMetacat.warn("Group " + i + ": " + groups[i][0]);
1122
        }
1123
      }
1124

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

    
1137
      // get the users for a group
1138
      if (isValid) {
1139
        MetaCatUtil.logMetacat.warn("\nGetting users for group....");
1140
        MetaCatUtil.logMetacat.warn("Group: " + savedGroup);
1141
        String[] users = authservice.getUsers(user, password, savedGroup);
1142
        MetaCatUtil.logMetacat.warn("Users found: " + users.length);
1143
        for (int i = 0; i < users.length; i++) {
1144
          MetaCatUtil.logMetacat.warn("User " + i + ": " + users[i]);
1145
        }
1146
      }
1147

    
1148
      // get all users
1149
      if (isValid) {
1150
        MetaCatUtil.logMetacat.warn("\nGetting all users ....");
1151
        String[][] users = authservice.getUsers(user, password);
1152
        MetaCatUtil.logMetacat.warn("Users found: " + users.length);
1153

    
1154
      }
1155

    
1156
      // get the whole list groups and users in XML format
1157
      if (isValid) {
1158
        MetaCatUtil.logMetacat.warn("\nTrying principals....");
1159
        authservice = new AuthLdap();
1160
        String out = authservice.getPrincipals(user, password);
1161
        java.io.File f = new java.io.File("principals.xml");
1162
        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
        MetaCatUtil.logMetacat.warn("\nFinished getting principals.");
1169
      }
1170

    
1171
    }
1172
    catch (ConnectException ce) {
1173
      MetaCatUtil.logMetacat.info(ce.getMessage());
1174
    }
1175
    catch (java.io.IOException ioe) {
1176
      MetaCatUtil.logMetacat.info("I/O Error writing to file principals.txt");
1177
    }
1178
  }
1179

    
1180
  /**
1181
   * This method will be called by start a thread.
1182
   * It can handle if a referral exception happend.
1183
   */
1184
  public void run() {
1185
    referralContext = null;
1186
    DirContext refDirContext = null;
1187
    boolean moreReferrals = true;
1188
    String referralInfo = null;
1189
    //set a while loop is because we don't know if a referral excption contains
1190
    //another referral exception
1191
    while (moreReferrals) {
1192
      try {
1193
        //revise environment variable
1194
        referralInfo = (String) refExc.getReferralInfo();
1195
        MetaCatUtil.logMetacat.info("Processing referral (pr0): ");
1196
        MetaCatUtil.logMetacat.info("PROVIDER_URL set to (pr1): " + referralInfo);
1197
        //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
        //MetaCatUtil.logMetacat.info("Processing referral (pr1.info): " + userName,35);
1203
        //MetaCatUtil.logMetacat.info("Processing referral (pr2)",35);
1204
        //rContext = refExc.getReferralContext(env);
1205
        rContext = refExc.getReferralContext();
1206
        MetaCatUtil.logMetacat.info("Processing referral (pr3)");
1207
        //casting the context to dircontext and it will create a
1208
        //autherntication or naming exception if DN and password is incorrect
1209
        referralContext = rContext;
1210
        refDirContext = (DirContext) rContext;
1211
        refDirContext.close();
1212
        //get context and jump out the while loop
1213
        moreReferrals = false;
1214
        MetaCatUtil.logMetacat.info("Processing referral (pr4)");
1215
      } //try
1216
      //if referral have another referral excption
1217
      catch (ReferralException re) {
1218
        MetaCatUtil.logMetacat.info("GOT referral exception (re1): " + re.getMessage());
1219
        MetaCatUtil.logMetacat.info("RE details (re2): " + re.toString(true));
1220
        //keep running in while loop
1221
        moreReferrals = true;
1222
        //assign refExc to new referral exception re
1223
        refExc = re;
1224
      }
1225
      //catch a authentication exception
1226
      catch (AuthenticationException ae) {
1227
        MetaCatUtil.logMetacat.warn("Error running referral handler thread (ae1): " +
1228
                          ae.getMessage());
1229
        //check if has another referral
1230
        moreReferrals = refExc.skipReferral();
1231
        //don't get the context
1232
        referralContext = null;
1233
      }
1234
      //catch a naming exception
1235
      catch (NamingException ne) {
1236
        MetaCatUtil.logMetacat.warn("Error running referral handler thread (ne1): " +
1237
                          ne.getMessage());
1238
        //check if has another referral
1239
        moreReferrals = refExc.skipReferral();
1240
        //don't get context
1241
        referralContext = null;
1242
      }
1243
    } //while
1244
  } //run()
1245

    
1246
  private class GetGroup
1247
      implements Runnable {
1248
    public void run() {
1249
      referralContext = null;
1250
      MetaCatUtil.logMetacat.info("getting groups context");
1251
      DirContext refDirContext = null;
1252
      boolean moreReferrals = true;
1253
      //set a while loop is because we don't know if a referral excption
1254
      //contains another referral exception
1255
      while (moreReferrals) {
1256
        try {
1257
          //revise environment variable
1258
          String refInfo = null;
1259
          refInfo = (String) refExc.getReferralInfo();
1260
          if (refInfo != null) {
1261
            MetaCatUtil.logMetacat.info("Referral in thread to: " +
1262
                                     refInfo.toString());
1263
          }
1264
          else {
1265
            MetaCatUtil.logMetacat.info("getting refInfo Manually");
1266
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1267
                get(Context.PROVIDER_URL);
1268
          }
1269
          MetaCatUtil.logMetacat.info("refInfo: " + refInfo);
1270

    
1271
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1272
                  "com.sun.jndi.ldap.LdapCtxFactory");
1273
          env.put(Context.REFERRAL, "throw");
1274
          env.put(Context.PROVIDER_URL, refInfo);
1275

    
1276
          MetaCatUtil.logMetacat.info("creating referralContext");
1277
          referralContext = new InitialDirContext(env);
1278
          MetaCatUtil.logMetacat.info("referralContext created");
1279
          //get context and jump out the while loop
1280
          moreReferrals = false;
1281
        } //try
1282
        catch (ReferralException re) {
1283
          //keep running in while loop
1284
          moreReferrals = true;
1285
          //assign refExc to new referral exception re
1286
          refExc = re;
1287
        }
1288
        catch (AuthenticationException ae) {
1289
          MetaCatUtil.logMetacat.info("Error running referral handler thread (ae2): " +
1290
                            ae.getMessage());
1291
          //check if has another referral
1292
          moreReferrals = refExc.skipReferral();
1293
          //don't get the context
1294
          referralContext = null;
1295
        }
1296
        catch (NamingException ne) {
1297
          MetaCatUtil.logMetacat.info("Error running referral handler thread (ne2): " +
1298
                            ne.getMessage());
1299
          //check if has another referral
1300
          moreReferrals = refExc.skipReferral();
1301
          //don't get context
1302
          referralContext = null;
1303
        }
1304
      } //while
1305
    } //run()
1306
  }
1307
}
(12-12/63)