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-10-20 11:26:46 -0700 (Thu, 20 Oct 2005) $'
13
 * '$Revision: 2679 $'
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

    
51
import org.apache.log4j.Logger;
52

    
53
import java.net.URLDecoder;
54
import java.util.Iterator;
55
import java.util.HashMap;
56
import java.util.Hashtable;
57
import java.util.Enumeration;
58
import java.util.Set;
59
import java.util.Vector;
60

    
61
/**
62
 * An implementation of the AuthInterface interface that
63
 * allows Metacat to use the LDAP protocol for directory services.
64
 * The LDAP authentication service is used to determine if a user
65
 * is authenticated, and whether they are a member of a particular group.
66
 */
67
public class AuthLdap
68
    implements AuthInterface, Runnable {
69
  private MetaCatUtil util = new MetaCatUtil();
70
  private String ldapUrl;
71
  private String ldapsUrl;
72
  private String ldapBase;
73
  private String referral;
74
  private Context referralContext;
75
  Hashtable env = new Hashtable(11);
76
  private Context rContext;
77
  private String userName;
78
  private String userPassword;
79
  ReferralException refExc;
80

    
81
  private static Logger logMetacat = Logger.getLogger(AuthLdap.class);
82
  
83
  /**
84
   * Construct an AuthLdap
85
   */
86
  public AuthLdap() {
87
    // Read LDAP URI for directory service information
88
    this.ldapUrl = MetaCatUtil.getOption("ldapurl");
89
    this.ldapsUrl = MetaCatUtil.getOption("ldapsurl");
90
    this.ldapBase = MetaCatUtil.getOption("ldapbase");
91
    this.referral = MetaCatUtil.getOption("referral");
92
  }
93

    
94
  /**
95
   * Determine if a user/password are valid according to the authentication
96
   * service.
97
   *
98
   * @param user the name of the principal to authenticate
99
   * @param password the password to use for authentication
100
   * @returns boolean true if authentication successful, false otherwise
101
   */
102
  public boolean authenticate(String user, String password) throws
103
      ConnectException {
104
    String ldapUrl = this.ldapUrl;
105
    String ldapsUrl = this.ldapsUrl;
106
    String ldapBase = this.ldapBase;
107
    boolean authenticated = false;
108
    String identifier = user;
109
    //get uid here.
110
    //uid=user.substring(0, user.indexOf(","));
111

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

    
147
    }
148
    catch (NullPointerException e) {
149
      logMetacat.error("NullPointerException b' password is null");
150
      logMetacat.error("NullPointerException while authenticating in " +
151
                        "AuthLdap.authenticate: " + e);
152
      throw new ConnectException(
153
          "NullPointerException while authenticating in " +
154
          "AuthLdap.authenticate: " + e);
155
    }
156
    catch (NamingException e) {
157
      logMetacat.error("Naming exception while authenticating in " +
158
                        "AuthLdap.authenticate: " + e);
159
      e.printStackTrace();
160
    }
161
    catch (Exception e) {
162
      logMetacat.error(e.getMessage());
163
    }
164
    return authenticated;
165
  }
166

    
167
  /**
168
   * Connect to the LDAP directory and do the authentication using the
169
   * username and password as passed into the routine.
170
   *
171
   * @param identifier the distinguished name to check against LDAP
172
   * @param password the password for authentication
173
   */
174
  private boolean ldapAuthenticate(String identifier, String password) throws
175
      ConnectException, NamingException, NullPointerException {
176
    return ldapAuthenticate(identifier, password,
177
                            this.ldapsUrl, this.ldapBase);
178
  }
179

    
180
  /**
181
   * Connect to the LDAP directory and do the authentication using the
182
   * username and password as passed into the routine.
183
   *
184
   * @param identifier the distinguished name to check against LDAP
185
   * @param password the password for authentication
186
   */
187
  private boolean ldapAuthenticate(String identifier, String password,
188
                                   String directoryUrl, String searchBase) throws
189
      ConnectException, NamingException, NullPointerException {
190
    double totStartTime = System.currentTimeMillis();
191
    boolean authenticated = false;
192
    if (identifier != null && !password.equals("")) {
193

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

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

    
270
  /**
271
   * Get the identifying name for a given userid or name.  This is the name
272
   * that is used in conjunction withthe LDAP BaseDN to create a
273
   * distinguished name (dn) for the record
274
   *
275
   * @param user the user for which the identifying name is requested
276
   * @returns String the identifying name for the user,
277
   *          or null if not found
278
   */
279
  private String getIdentifyingName(String user, String ldapUrl,
280
                                    String ldapBase) throws NamingException {
281
    String identifier = null;
282
    // Identify service provider to use
283
    Hashtable env = new Hashtable(11);
284
    env.put(Context.INITIAL_CONTEXT_FACTORY,
285
            "com.sun.jndi.ldap.LdapCtxFactory");
286
    logMetacat.info("setting referrals to: " + referral);
287
    env.put(Context.REFERRAL, referral);
288
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
289
    //    non-secure LDAP context; dn are publicly readable
290
    try {
291

    
292
      // Bind to the LDAP server, in order to search for the right
293
      // distinguished name (dn) based on userid (uid) or common name (cn)
294
      DirContext ctx = new InitialDirContext(env);
295
      SearchControls ctls = new SearchControls();
296
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
297
      // Search for the user id or name using the uid, then cn and sn
298
      //attributes
299
      // If we find a record, determine the dn for the record
300
      // The following blocks need to be refactored into a subroutine
301
      // they have a ridiculous amount of redundancy
302

    
303
      // Parse out the uid and org components and look up the real DN
304
      // This assumes a dn like "uid=x,o=y,dc=someinst,dc=org"
305
      int position = user.indexOf(",");
306
      String comp1 = user.substring(0, position);
307
      logMetacat.info("First comp is: " + comp1);
308
      String comp2 = user.substring(position + 1,
309
                                    user.indexOf(",", position + 1));
310
      logMetacat.info("Second comp is: " + comp2);
311

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

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

    
357
      // Maybe its a user id (uid)
358
      filter = "(uid=" + user + ")";
359
      logMetacat.info("Trying again: " + filter);
360
      answer = ctx.search("", filter, ctls);
361
      if (answer.hasMore()) {
362
        SearchResult sr = (SearchResult) answer.next();
363
        identifier = sr.getName();
364
        if (!sr.isRelative()) {
365
          this.ldapUrl = identifier.substring(0,
366
                                              identifier.lastIndexOf("/") + 1);
367
          this.ldapBase = identifier.substring(identifier.indexOf(",") + 1);
368
          identifier = identifier.substring(identifier.lastIndexOf("/") + 1,
369
                                            identifier.indexOf(","));
370
        }
371
        logMetacat.info("Found: " + identifier);
372
      }
373
      else {
374

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

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

    
424
  /**
425
   * Get all users from the authentication service
426
   *
427
   * @param user the user for authenticating against the service
428
   * @param password the password for authenticating against the service
429
   * @returns string array of all of the user names
430
   */
431
  public String[][] getUsers(String user, String password) throws
432
      ConnectException {
433
    String[][] users = null;
434

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

    
442
    try {
443

    
444
      // Create the initial directory context
445
      DirContext ctx = new InitialDirContext(env);
446

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

    
458
      // Store the users in a vector
459
      Vector uvec = new Vector();
460
      Vector uname = new Vector();
461
      Vector uorg = new Vector();
462
      Vector uou = new Vector();
463
      Vector umail = new Vector();
464
      Attributes tempAttr = null;
465
      try {
466
        while (namingEnum.hasMore()) {
467
          SearchResult sr = (SearchResult) namingEnum.next();
468
          tempAttr = sr.getAttributes();
469

    
470
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
471
            uname.add( (tempAttr.get("cn") + "").substring(4));
472
          }
473
          else {
474
            uname.add(tempAttr.get("cn") + "");
475
          }
476

    
477
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
478
            uorg.add( (tempAttr.get("o") + "").substring(3));
479
          }
480
          else {
481
            uorg.add(tempAttr.get("o") + "");
482
          }
483

    
484
          if ( (tempAttr.get("ou") + "").startsWith("ou: ")) {
485
            uou.add( (tempAttr.get("ou") + "").substring(4));
486
          }
487
          else {
488
            uou.add(tempAttr.get("ou") + "");
489
          }
490

    
491
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
492
            umail.add( (tempAttr.get("mail") + "").substring(6));
493
          }
494
          else {
495
            umail.add(tempAttr.get("mail") + "");
496
          }
497

    
498
          uvec.add(sr.getName() + "," + ldapBase);
499
        }
500
      }
501
      catch (SizeLimitExceededException slee) {
502
        logMetacat.error("LDAP Server size limit exceeded. " +
503
                          "Returning incomplete record set.");
504
      }
505

    
506
      // initialize users[]; fill users[]
507
      users = new String[uvec.size()][5];
508
      for (int i = 0; i < uvec.size(); i++) {
509
        users[i][0] = (String) uvec.elementAt(i);
510
        users[i][1] = (String) uname.elementAt(i);
511
        users[i][2] = (String) uorg.elementAt(i);
512
        users[i][3] = (String) uorg.elementAt(i);
513
        users[i][4] = (String) umail.elementAt(i);
514
      }
515

    
516
      // Close the context when we're done
517
      ctx.close();
518

    
519
    }
520
    catch (NamingException e) {
521
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
522
      //e.printStackTrace(System.err);
523
      throw new ConnectException(
524
          "Problem getting users in AuthLdap.getUsers:" + e);
525
    }
526

    
527
    return users;
528
  }
529

    
530
  
531
  /**
532
   * Get all users from the authentication service
533
   *
534
   * @param user the user for authenticating against the service
535
   * @param password the password for authenticating against the service
536
   * @returns string array of all of the user names
537
   */
538
  public String[] getUserInfo(String user, String password) throws
539
      ConnectException {
540
    String[] userinfo = new String[3];
541

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

    
549
    try {
550

    
551
      // Create the initial directory context
552
      DirContext ctx = new InitialDirContext(env);
553
      // Specify the attributes to match.
554
      // Users are objects that have the attribute objectclass=InetOrgPerson.
555
      SearchControls ctls = new SearchControls();
556
      String[] attrIDs = {
557
          "cn", "o", "mail"};
558
      ctls.setReturningAttributes(attrIDs);
559
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
560
      //ctls.setCountLimit(1000);
561
      String filter = "objectclass=InetOrgPerson";
562
      NamingEnumeration namingEnum = ctx.search(user, filter, ctls);
563

    
564
      Attributes tempAttr = null;
565
      try {
566
        while (namingEnum.hasMore()) {
567
          SearchResult sr = (SearchResult) namingEnum.next();
568
          tempAttr = sr.getAttributes();
569

    
570
          if ( (tempAttr.get("cn") + "").startsWith("cn: ")) {
571
        	  userinfo[0] = (tempAttr.get("cn") + "").substring(4);
572
          }
573
          else {
574
        	  userinfo[0] = (tempAttr.get("cn") + "");
575
          }
576

    
577
          if ( (tempAttr.get("o") + "").startsWith("o: ")) {
578
        	  userinfo[1] = (tempAttr.get("o") + "").substring(3);
579
          }
580
          else {
581
        	  userinfo[1] = (tempAttr.get("o") + "");
582
          }
583

    
584
          if ( (tempAttr.get("mail") + "").startsWith("mail: ")) {
585
        	  userinfo[2] =  (tempAttr.get("mail") + "").substring(6);
586
          }
587
          else {
588
        	  userinfo[2] = (tempAttr.get("mail") + "");
589
          }
590
        }
591
      }
592
      catch (SizeLimitExceededException slee) {
593
        logMetacat.error("LDAP Server size limit exceeded. " +
594
                          "Returning incomplete record set.");
595
      }
596

    
597
      // Close the context when we're done
598
      ctx.close();
599

    
600
    }
601
    catch (NamingException e) {
602
      logMetacat.error("Problem getting users in AuthLdap.getUsers:" + e);
603
      //e.printStackTrace(System.err);
604
      throw new ConnectException(
605
          "Problem getting users in AuthLdap.getUsers:" + e);
606
    }
607

    
608
    return userinfo;
609
  }
610

    
611
  /**
612
   * Get the users for a particular group from the authentication service
613
   *
614
   * @param user the user for authenticating against the service
615
   * @param password the password for authenticating against the service
616
   * @param group the group whose user list should be returned
617
   * @returns string array of the user names belonging to the group
618
   */
619
  public String[] getUsers(String user, String password, String group) throws
620
      ConnectException {
621
    String[] users = null;
622

    
623
    // Identify service provider to use
624
    Hashtable env = new Hashtable(11);
625
    env.put(Context.INITIAL_CONTEXT_FACTORY,
626
            "com.sun.jndi.ldap.LdapCtxFactory");
627
    env.put(Context.REFERRAL, referral);
628
    env.put(Context.PROVIDER_URL, ldapUrl);
629

    
630
    try {
631

    
632
      // Create the initial directory context
633
      DirContext ctx = new InitialDirContext(env);
634

    
635
      // Specify the ids of the attributes to return
636
      String[] attrIDs = {
637
          "uniqueMember"};
638

    
639
      Attributes answer = ctx.getAttributes(group, attrIDs);
640

    
641
      Vector uvec = new Vector();
642
      try {
643
        for (NamingEnumeration ae = answer.getAll(); ae.hasMore(); ) {
644
          Attribute attr = (Attribute) ae.next();
645
          for (NamingEnumeration e = attr.getAll();
646
               e.hasMore();
647
               uvec.add(e.next())
648
               ) {
649
            ;
650
          }
651
        }
652
      }
653
      catch (SizeLimitExceededException slee) {
654
        logMetacat.error("LDAP Server size limit exceeded. " +
655
                          "Returning incomplete record set.");
656
      }
657

    
658
      // initialize users[]; fill users[]
659
      users = new String[uvec.size()];
660
      for (int i = 0; i < uvec.size(); i++) {
661
        users[i] = (String) uvec.elementAt(i);
662
      }
663

    
664
      // Close the context when we're done
665
      ctx.close();
666

    
667
    }
668
    catch (NamingException e) {
669
      logMetacat.error("Problem getting users for a group in " +
670
                        "AuthLdap.getUsers:" + e);
671
      throw new ConnectException(
672
          "Problem getting users for a group in AuthLdap.getUsers:" + e);
673
    }
674

    
675
    return users;
676
  }
677

    
678
  /**
679
   * Get all groups from the authentication service
680
   *
681
   * @param user the user for authenticating against the service
682
   * @param password the password for authenticating against the service
683
   * @returns string array of the group names
684
   */
685
  public String[][] getGroups(String user, String password) throws
686
      ConnectException {
687
    return getGroups(user, password, null);
688
  }
689

    
690
  /**
691
   * Get the groups for a particular user from the authentication service
692
   *
693
   * @param user the user for authenticating against the service
694
   * @param password the password for authenticating against the service
695
   * @param foruser the user whose group list should be returned
696
   * @returns string array of the group names
697
   */
698
  public String[][] getGroups(String user, String password, String foruser) throws
699
      ConnectException {
700
    Vector gvec = new Vector();
701
    Vector desc = new Vector();
702
    Attributes tempAttr = null;
703

    
704
    //Pass the username and password to run() method
705
    userName = user;
706
    userPassword = password;
707
    // Identify service provider to use
708
    env.put(Context.INITIAL_CONTEXT_FACTORY,
709
            "com.sun.jndi.ldap.LdapCtxFactory");
710
    env.put(Context.REFERRAL, "throw");
711
    env.put(Context.PROVIDER_URL, ldapUrl);
712
    try {
713
      // Create the initial directory context
714
      DirContext ctx = new InitialDirContext(env);
715
      // Specify the ids of the attributes to return
716
      String[] attrIDs = {
717
          "cn", "o", "description"};
718
      // Specify the attributes to match.
719
      // Groups are objects with attribute objectclass=groupofuniquenames.
720
      // and have attribute uniquemember: uid=foruser,ldapbase.
721
      SearchControls ctls = new SearchControls();
722
      ctls.setReturningAttributes(attrIDs);
723
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
724

    
725
      String filter = null;
726
      String gfilter = "(objectClass=groupOfUniqueNames)";
727
      if (null == foruser) {
728
        filter = gfilter;
729
      }
730
      else {
731
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
732
      }
733
      logMetacat.info("searching for groups: " + filter);
734
      NamingEnumeration namingEnum = ctx.search(ldapBase, filter, ctls);
735

    
736
      // Print the groups
737
      logMetacat.info("getting group results.");
738
      while (namingEnum.hasMore()) {
739
        SearchResult sr = (SearchResult) namingEnum.next();
740
        tempAttr = sr.getAttributes();
741

    
742
        if ( (tempAttr.get("description") + "").startsWith("description: ")) {
743
          desc.add( (tempAttr.get("description") + "").substring(13));
744
        }
745
        else {
746
          desc.add(tempAttr.get("description") + "");
747
        }
748

    
749
        gvec.add(sr.getName() + "," + ldapBase);
750
        logMetacat.info("group " + sr.getName() +
751
                                 " added to Group vector");
752
      }
753
      // Close the context when we're done
754
      ctx.close();
755

    
756
    }
757
    catch (ReferralException re) {
758
      refExc = re;
759
      Thread t = new Thread(new GetGroup());
760
      logMetacat.info("Starting thread...");
761
      t.start();
762
      logMetacat.info("sleeping for 5 seconds.");
763
      try {
764
        Thread.sleep(5000);
765
      }
766
      catch (InterruptedException ie) {
767
        logMetacat.error("main thread interrupted: " + ie.getMessage());
768
      }
769
      //this is a manual override of jndi's hideously long time
770
      //out period.
771
      logMetacat.info("Awake after 5 seconds.");
772
      if (referralContext == null) {
773
        logMetacat.info("thread timed out...returning groups: " +
774
                          gvec.toString());
775
        String groups[][] = new String[gvec.size()][2];
776
        for (int i = 0; i < gvec.size(); i++) {
777
          groups[i][0] = (String) gvec.elementAt(i);
778
          groups[i][1] = (String) desc.elementAt(i);
779
        }
780
        t.interrupt();
781
        return groups;
782
      }
783
      DirContext dc = (DirContext) referralContext;
784
      String[] attrIDs = {
785
          "cn", "o", "description"};
786
      // Specify the attributes to match.
787
      // Groups are objects with attribute objectclass=groupofuniquenames.
788
      // and have attribute uniquemember: uid=foruser,ldapbase.
789
      SearchControls ctls = new SearchControls();
790
      ctls.setReturningAttributes(attrIDs);
791
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
792

    
793
      String filter = null;
794
      String gfilter = "(objectClass=groupOfUniqueNames)";
795
      if (null == foruser) {
796
        filter = gfilter;
797
      }
798
      else {
799
        filter = "(& " + gfilter + "(uniqueMember=" + foruser + "))";
800
      }
801

    
802
      try {
803
        NamingEnumeration namingEnum = dc.search(ldapBase, filter, ctls);
804
        // Print the groups
805
        while (namingEnum.hasMore()) {
806
          SearchResult sr = (SearchResult) namingEnum.next();
807
          tempAttr = sr.getAttributes();
808

    
809
          if ( (tempAttr.get("description") + "").startsWith("description: ")) {
810
            desc.add( (tempAttr.get("description") + "").substring(13));
811
          }
812
          else {
813
            desc.add(tempAttr.get("description") + "");
814
          }
815

    
816
          gvec.add(sr.getName() + "," + ldapBase);
817
        }
818

    
819
        referralContext.close();
820
        dc.close();
821
      }
822
      catch (NamingException ne) {
823
        logMetacat.warn("Naming Exception in AuthLdap.getGroups" +
824
                                 ne.getExplanation() + ne.getMessage());
825
      }
826
    }
827
    catch (NamingException e) {
828
      e.printStackTrace(System.err);
829
      String groups[][] = new String[gvec.size()][2];
830
      for (int i = 0; i < gvec.size(); i++) {
831
        groups[i][0] = (String) gvec.elementAt(i);
832
        groups[i][1] = (String) desc.elementAt(i);
833
      }
834
      return groups;
835
      /*throw new ConnectException(
836
             "Problem getting groups for a user in AuthLdap.getGroups:" + e);*/
837
    }
838

    
839
    logMetacat.warn("The user is in the following groups: " +
840
                             gvec.toString());
841
    String groups[][] = new String[gvec.size()][2];
842
    for (int i = 0; i < gvec.size(); i++) {
843
      groups[i][0] = (String) gvec.elementAt(i);
844
      groups[i][1] = (String) desc.elementAt(i);
845
    }
846
    return groups;
847
  }
848

    
849
  /**
850
   * Get attributes describing a user or group
851
   *
852
   * @param foruser the user for which the attribute list is requested
853
   * @returns HashMap a map of attribute name to a Vector of values
854
   */
855
  public HashMap getAttributes(String foruser) throws ConnectException {
856
    return getAttributes(null, null, foruser);
857
  }
858

    
859
  /**
860
   * Get attributes describing a user or group
861
   *
862
   * @param user the user for authenticating against the service
863
   * @param password the password for authenticating against the service
864
   * @param foruser the user whose attributes should be returned
865
   * @returns HashMap a map of attribute name to a Vector of values
866
   */
867
  public HashMap getAttributes(String user, String password, String foruser) throws
868
      ConnectException {
869
    HashMap attributes = new HashMap();
870
    String ldapUrl = this.ldapUrl;
871
    String ldapBase = this.ldapBase;
872
    String userident = foruser;
873

    
874
    // Identify service provider to use
875
    Hashtable env = new Hashtable(11);
876
    env.put(Context.INITIAL_CONTEXT_FACTORY,
877
            "com.sun.jndi.ldap.LdapCtxFactory");
878
    env.put(Context.REFERRAL, referral);
879
    env.put(Context.PROVIDER_URL, ldapUrl);
880

    
881
    try {
882

    
883
      // Create the initial directory context
884
      DirContext ctx = new InitialDirContext(env);
885

    
886
      // Ask for all attributes of the user
887
      //Attributes attrs = ctx.getAttributes(userident);
888
      Attributes attrs = ctx.getAttributes(foruser);
889

    
890
      // Print all of the attributes
891
      NamingEnumeration en = attrs.getAll();
892
      while (en.hasMore()) {
893
        Attribute att = (Attribute) en.next();
894
        Vector values = new Vector();
895
        String attName = att.getID();
896
        NamingEnumeration attvalues = att.getAll();
897
        while (attvalues.hasMore()) {
898
          String value = (String) attvalues.next();
899
          values.add(value);
900
        }
901
        attributes.put(attName, values);
902
      }
903

    
904
      // Close the context when we're done
905
      ctx.close();
906
    }
907
    catch (NamingException e) {
908
      logMetacat.error("Problem getting attributes in " +
909
                        "AuthLdap.getAttributes:" + e);
910
      throw new ConnectException(
911
          "Problem getting attributes in AuthLdap.getAttributes:" + e);
912
    }
913

    
914
    return attributes;
915
  }
916

    
917
  /**
918
   * Get list of all subtrees holding Metacat's groups and users
919
   * starting from the Metacat LDAP root,
920
   * i.e. ldap://dev.nceas.ucsb.edu/dc=ecoinformatics,dc=org
921
   */
922
  private Hashtable getSubtrees(String user, String password,
923
                                String ldapUrl, String ldapBase) throws
924
      ConnectException {
925
    Hashtable trees = new Hashtable();
926

    
927
    // Identify service provider to use
928
    Hashtable env = new Hashtable(11);
929
    env.put(Context.INITIAL_CONTEXT_FACTORY,
930
            "com.sun.jndi.ldap.LdapCtxFactory");
931
    // env.put(Context.REFERRAL, referral);
932
    // Using 'ignore' here instead of 'follow' as 'ignore' seems
933
    // to do the job better. 'follow' was not bringing up the UCNRS
934
    // and PISCO tree whereas 'ignore' brings up the tree.
935

    
936
    env.put(Context.REFERRAL, "ignore");
937
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
938

    
939
    try {
940

    
941
      // Create the initial directory context
942
      DirContext ctx = new InitialDirContext(env);
943

    
944
      // Specify the ids of the attributes to return
945
      String[] attrIDs = {
946
          "o", "ref"};
947
      SearchControls ctls = new SearchControls();
948
      ctls.setReturningAttributes(attrIDs);
949
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
950

    
951
      // Specify the attributes to match.
952
      // Subtrees from the main server are found as objects with attribute
953
      // objectclass=organization or objectclass=referral to the subtree
954
      // resided on other server.
955
      String filter = "(|(objectclass=organization)(objectclass=referral))";
956

    
957
      // Search for objects in the current context
958
      NamingEnumeration namingEnum = ctx.search("", filter, ctls);
959

    
960
      // Print the subtrees' <ldapURL, baseDN>
961
      while (namingEnum.hasMore()) {
962

    
963
        SearchResult sr = (SearchResult) namingEnum.next();
964

    
965
        Attributes attrs = sr.getAttributes();
966
        NamingEnumeration enum1 = attrs.getAll(); // "dc" and "ref" attrs
967

    
968
        if (enum1.hasMore()) {
969
          Attribute attr = (Attribute) enum1.next();
970
          String attrValue = (String) attr.get();
971
          String attrName = (String) attr.getID();
972

    
973
          if (enum1.hasMore()) {
974
            attr = (Attribute) enum1.next();
975
            String refValue = (String) attr.get();
976
            String refName = (String) attr.getID();
977
            if (ldapBase.startsWith(refName + "=" + refValue)) {
978
              trees.put(ldapBase,
979
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
980
            }
981
            else {
982
              // this is a referral - so organization name is appended in
983
              // front of the ldapbase.... later it is stripped out
984
              // in getPrincipals
985
              trees.put("[" + refName + "=" + refValue + "]" +
986
                        attrValue.substring(attrValue.lastIndexOf("/") + 1,
987
                                            attrValue.length()),
988
                        attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
989

    
990
              // trees.put(refName + "=" + refValue + "," + ldapBase,
991
              //           attrValue.substring(0, attrValue.lastIndexOf("/") + 1));
992
            }
993

    
994
          }
995
          else if (ldapBase.startsWith(attrName + "=" + attrValue)) {
996
            trees.put(ldapBase, ldapUrl);
997
          }
998
          else {
999
            if (sr.isRelative()) {
1000
              trees.put(attrName + "=" + attrValue + "," + ldapBase, ldapUrl);
1001
            }
1002
            else {
1003
              String referenceURL = sr.getName();
1004
              referenceURL = referenceURL.substring(0,
1005
                  referenceURL.lastIndexOf("/") + 1);
1006
              trees.put(attrName + "=" + attrValue + "," + ldapBase,
1007
                        referenceURL);
1008
            }
1009

    
1010
          }
1011
        }
1012
      }
1013

    
1014
      // Close the context when we're done
1015
      ctx.close();
1016

    
1017
    }
1018
    catch (NamingException e) {
1019
      logMetacat.error("Problem getting subtrees in AuthLdap.getSubtrees:"
1020
                        + e);
1021
      throw new ConnectException(
1022
          "Problem getting subtrees in AuthLdap.getSubtrees:" + e);
1023
    }
1024

    
1025
    return trees;
1026
  }
1027

    
1028
  /**
1029
   * Get all groups and users from authentication scheme.
1030
   * The output is formatted in XML.
1031
   * @param user the user which requests the information
1032
   * @param password the user's password
1033
   */
1034
  public String getPrincipals(String user, String password) throws
1035
      ConnectException {
1036
    StringBuffer out = new StringBuffer();
1037
   
1038
    out.append("<?xml version=\"1.0\" encoding=\"US-ASCII\"?>\n");
1039
    out.append("<principals>\n");
1040

    
1041
    /*
1042
     * get all subtrees first in the current dir context
1043
     * and then the Metacat users under them
1044
     */
1045
    Hashtable subtrees = getSubtrees(user, password, this.ldapUrl,
1046
                                     this.ldapBase);
1047

    
1048
    Enumeration keyEnum = subtrees.keys();
1049
    while (keyEnum.hasMoreElements()) {
1050
      this.ldapBase = (String) keyEnum.nextElement();
1051
      this.ldapUrl = (String) subtrees.get(ldapBase);
1052

    
1053
      /*
1054
       * code to get the organization name from ldapBase
1055
       */
1056
      String orgName = this.ldapBase;
1057
      if (orgName.startsWith("[")) {
1058
        // if orgName starts with [ then it is a referral URL...
1059
        // (see code in getSubtress)
1060
        // hence orgName can be retrieved  by getting the string between
1061
        // 'o=' and ']'
1062
        // also the string between [ and ] needs to be striped out from
1063
        // this.ldapBase
1064
        this.ldapBase = orgName.substring(orgName.indexOf("]") + 1);
1065
        if (orgName != null && orgName.indexOf("o=") > -1) {
1066
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1067
          orgName = orgName.substring(0, orgName.indexOf("]"));
1068
        }
1069
      }
1070
      else {
1071
        // else it is not referral
1072
        // hence orgName can be retrieved  by getting the string between
1073
        // 'o=' and ','
1074
        if (orgName != null && orgName.indexOf("o=") > -1) {
1075
          orgName = orgName.substring(orgName.indexOf("o=") + 2);
1076
          if (orgName.indexOf(",") > -1) {
1077
            orgName = orgName.substring(0, orgName.indexOf(","));
1078
          }
1079
        }
1080
      }
1081

    
1082
      out.append("  <authSystem URI=\"" +
1083
                 this.ldapUrl + this.ldapBase + "\" organization=\"" + orgName +
1084
                 "\">\n");
1085

    
1086
      // get all groups for directory context
1087
      String[][] groups = getGroups(user, password);
1088
      String[][] users = getUsers(user, password);
1089
      int userIndex = 0;
1090

    
1091
      // for the groups and users that belong to them
1092
      if (groups != null && groups.length > 0) {
1093
        for (int i = 0; i < groups.length; i++) {
1094
          out.append("    <group>\n");
1095
          out.append("      <groupname>" + groups[i][0] + "</groupname>\n");
1096
          out.append("      <description>" + groups[i][1] + "</description>\n");
1097
          String[] usersForGroup = getUsers(user, password, groups[i][0]);
1098
          for (int j = 0; j < usersForGroup.length; j++) {
1099
            
1100
            userIndex = searchUser(usersForGroup[j], users);
1101
            out.append("      <user>\n");
1102

    
1103
            if (userIndex < 0) {
1104
              out.append("        <username>" + usersForGroup[j] +
1105
                         "</username>\n");
1106
            }
1107
            else {
1108
              out.append("        <username>" + users[userIndex][0] +
1109
                         "</username>\n");
1110
              out.append("        <name>" + users[userIndex][1] + "</name>\n");
1111
              out.append("        <organization>" + users[userIndex][2] +
1112
                         "</organization>\n");
1113
              if (users[userIndex][3].compareTo("null") != 0) {
1114
                out.append("      <organizationUnitName>" + users[userIndex][3] +
1115
                           "</organizationUnitName>\n");
1116
              }
1117
              out.append("        <email>" + users[userIndex][4] + "</email>\n");
1118
            }
1119

    
1120
            out.append("      </user>\n");
1121
          }
1122
          out.append("    </group>\n");
1123
        }
1124
      }
1125

    
1126
      // for the users not belonging to any grou8p
1127
      for (int j = 0; j < users.length; j++) {
1128
          out.append("    <user>\n");
1129
          out.append("      <username>" + users[j][0] + "</username>\n");
1130
          out.append("      <name>" + users[j][1] + "</name>\n");
1131
          out.append("      <organization>" + users[j][2] +
1132
                     "</organization>\n");
1133
          if (users[j][3].compareTo("null") != 0) {
1134
            out.append("      <organizationUnitName>" + users[j][3] +
1135
                       "</organizationUnitName>\n");
1136
          }
1137
          out.append("      <email>" + users[j][4] + "</email>\n");
1138
          out.append("    </user>\n");
1139
      }
1140

    
1141
      out.append("  </authSystem>\n");
1142
    }
1143
    out.append("</principals>");
1144
    return out.toString();
1145
  }
1146

    
1147
  /**
1148
   * Method for getting index of user DN in User info array
1149
   */
1150
  int searchUser(String user, String userGroup[][]) {
1151
    for (int j = 0; j < userGroup.length; j++) {
1152
      if (user.compareTo(userGroup[j][0]) == 0) {
1153
        return j;
1154
      }
1155
    }
1156
    return -1;
1157
  }
1158

    
1159
  /**
1160
   * Test method for the class
1161
   */
1162
  public static void main(String[] args) {
1163

    
1164
    // Provide a user, such as: "Matt Jones", or "jones"
1165
    String user = args[0];
1166
    String password = args[1];
1167

    
1168
    logMetacat.warn("Creating session...");
1169
    AuthLdap authservice = new AuthLdap();
1170
    logMetacat.warn("Session exists...");
1171

    
1172
    boolean isValid = false;
1173
    try {
1174
      logMetacat.warn("Authenticating...");
1175
      isValid = authservice.authenticate(user, password);
1176
      if (isValid) {
1177
    	  logMetacat.warn("Authentication successful for: " + user);
1178
      }
1179
      else {
1180
        logMetacat.warn("Authentication failed for: " + user);
1181
      }
1182

    
1183
      // Get attributes for the user
1184
      if (isValid) {
1185
        logMetacat.info("\nGetting attributes for user....");
1186
        HashMap userInfo = authservice.getAttributes(user, password, user);
1187
        // Print all of the attributes
1188
        Iterator attList = (Iterator) ( ( (Set) userInfo.keySet()).iterator());
1189
        while (attList.hasNext()) {
1190
          String att = (String) attList.next();
1191
          Vector values = (Vector) userInfo.get(att);
1192
          Iterator attvalues = values.iterator();
1193
          while (attvalues.hasNext()) {
1194
            String value = (String) attvalues.next();
1195
            logMetacat.warn(att + ": " + value);
1196
          }
1197
        }
1198
      }
1199

    
1200
      // get the groups
1201
      if (isValid) {
1202
        logMetacat.warn("\nGetting all groups....");
1203
        String[][] groups = authservice.getGroups(user, password);
1204
        logMetacat.info("Groups found: " + groups.length);
1205
        for (int i = 0; i < groups.length; i++) {
1206
          logMetacat.info("Group " + i + ": " + groups[i][0]);
1207
        }
1208
      }
1209

    
1210
      // get the groups for the user
1211
      String savedGroup = null;
1212
      if (isValid) {
1213
        logMetacat.warn("\nGetting groups for user....");
1214
        String[][] groups = authservice.getGroups(user, password, user);
1215
        logMetacat.info("Groups found: " + groups.length);
1216
        for (int i = 0; i < groups.length; i++) {
1217
          logMetacat.info("Group " + i + ": " + groups[i][0]);
1218
          savedGroup = groups[i][0];
1219
        }
1220
      }
1221

    
1222
      // get the users for a group
1223
      if (isValid) {
1224
        logMetacat.warn("\nGetting users for group....");
1225
        logMetacat.info("Group: " + savedGroup);
1226
        String[] users = authservice.getUsers(user, password, savedGroup);
1227
        logMetacat.info("Users found: " + users.length);
1228
        for (int i = 0; i < users.length; i++) {
1229
          logMetacat.warn("User " + i + ": " + users[i]);
1230
        }
1231
      }
1232

    
1233
      // get all users
1234
      if (isValid) {
1235
        logMetacat.warn("\nGetting all users ....");
1236
        String[][] users = authservice.getUsers(user, password);
1237
        logMetacat.info("Users found: " + users.length);
1238

    
1239
      }
1240

    
1241
      // get the whole list groups and users in XML format
1242
      if (isValid) {
1243
        logMetacat.warn("\nTrying principals....");
1244
        authservice = new AuthLdap();
1245
        String out = authservice.getPrincipals(user, password);
1246
        java.io.File f = new java.io.File("principals.xml");
1247
        java.io.FileWriter fw = new java.io.FileWriter(f);
1248
        java.io.BufferedWriter buff = new java.io.BufferedWriter(fw);
1249
        buff.write(out);
1250
        buff.flush();
1251
        buff.close();
1252
        fw.close();
1253
        logMetacat.warn("\nFinished getting principals.");
1254
      }
1255

    
1256
    }
1257
    catch (ConnectException ce) {
1258
      logMetacat.error(ce.getMessage());
1259
    }
1260
    catch (java.io.IOException ioe) {
1261
      logMetacat.error("I/O Error writing to file principals.txt");
1262
    }
1263
  }
1264

    
1265
  /**
1266
   * This method will be called by start a thread.
1267
   * It can handle if a referral exception happend.
1268
   */
1269
  public void run() {
1270
    referralContext = null;
1271
    DirContext refDirContext = null;
1272
    boolean moreReferrals = true;
1273
    String referralInfo = null;
1274
    //set a while loop is because we don't know if a referral excption contains
1275
    //another referral exception
1276
    while (moreReferrals) {
1277
      try {
1278
        //revise environment variable
1279
        referralInfo = (String) refExc.getReferralInfo();
1280
        logMetacat.info("Processing referral (pr0): ");
1281
        logMetacat.info("PROVIDER_URL set to (pr1): " + referralInfo);
1282
        //env.put(Context.PROVIDER_URL,referralInfo);
1283
        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
1284
        //env.put(Context.SECURITY_PRINCIPAL, userName);
1285
        //env.put(Context.SECURITY_CREDENTIALS, userPassword);
1286
        //env.put(Context.REFERRAL, "throw");
1287
        //logMetacat.info("Processing referral (pr1.info): " + userName,35);
1288
        //logMetacat.info("Processing referral (pr2)",35);
1289
        //rContext = refExc.getReferralContext(env);
1290
        rContext = refExc.getReferralContext();
1291
        logMetacat.info("Processing referral (pr3)");
1292
        //casting the context to dircontext and it will create a
1293
        //autherntication or naming exception if DN and password is incorrect
1294
        referralContext = rContext;
1295
        refDirContext = (DirContext) rContext;
1296
        refDirContext.close();
1297
        //get context and jump out the while loop
1298
        moreReferrals = false;
1299
        logMetacat.info("Processing referral (pr4)");
1300
      } //try
1301
      //if referral have another referral excption
1302
      catch (ReferralException re) {
1303
        logMetacat.warn("GOT referral exception (re1): " + re.getMessage());
1304
        logMetacat.warn("RE details (re2): " + re.toString(true));
1305
        //keep running in while loop
1306
        moreReferrals = true;
1307
        //assign refExc to new referral exception re
1308
        refExc = re;
1309
      }
1310
      //catch a authentication exception
1311
      catch (AuthenticationException ae) {
1312
        logMetacat.error("Error running referral handler thread (ae1): " +
1313
                          ae.getMessage());
1314
        //check if has another referral
1315
        moreReferrals = refExc.skipReferral();
1316
        //don't get the context
1317
        referralContext = null;
1318
      }
1319
      //catch a naming exception
1320
      catch (NamingException ne) {
1321
        logMetacat.error("Error running referral handler thread (ne1): " +
1322
                          ne.getMessage());
1323
        //check if has another referral
1324
        moreReferrals = refExc.skipReferral();
1325
        //don't get context
1326
        referralContext = null;
1327
      }
1328
    } //while
1329
  } //run()
1330

    
1331
  private class GetGroup
1332
      implements Runnable {
1333
    public void run() {
1334
      referralContext = null;
1335
      logMetacat.info("getting groups context");
1336
      DirContext refDirContext = null;
1337
      boolean moreReferrals = true;
1338
      //set a while loop is because we don't know if a referral excption
1339
      //contains another referral exception
1340
      while (moreReferrals) {
1341
        try {
1342
          //revise environment variable
1343
          String refInfo = null;
1344
          refInfo = (String) refExc.getReferralInfo();
1345
          if (refInfo != null) {
1346
            logMetacat.info("Referral in thread to: " +
1347
                                     refInfo.toString());
1348
          }
1349
          else {
1350
            logMetacat.info("getting refInfo Manually");
1351
            refInfo = (String) refExc.getReferralContext().getEnvironment().
1352
                get(Context.PROVIDER_URL);
1353
          }
1354
          logMetacat.info("refInfo: " + refInfo);
1355

    
1356
          env.put(Context.INITIAL_CONTEXT_FACTORY,
1357
                  "com.sun.jndi.ldap.LdapCtxFactory");
1358
          env.put(Context.REFERRAL, "throw");
1359
          env.put(Context.PROVIDER_URL, refInfo);
1360

    
1361
          logMetacat.info("creating referralContext");
1362
          referralContext = new InitialDirContext(env);
1363
          logMetacat.info("referralContext created");
1364
          //get context and jump out the while loop
1365
          moreReferrals = false;
1366
        } //try
1367
        catch (ReferralException re) {
1368
          //keep running in while loop
1369
          moreReferrals = true;
1370
          //assign refExc to new referral exception re
1371
          refExc = re;
1372
        }
1373
        catch (AuthenticationException ae) {
1374
          logMetacat.error("Error running referral handler thread (ae2): " +
1375
                            ae.getMessage());
1376
          //check if has another referral
1377
          moreReferrals = refExc.skipReferral();
1378
          //don't get the context
1379
          referralContext = null;
1380
        }
1381
        catch (NamingException ne) {
1382
          logMetacat.error("Error running referral handler thread (ne2): " +
1383
                            ne.getMessage());
1384
          //check if has another referral
1385
          moreReferrals = refExc.skipReferral();
1386
          //don't get context
1387
          referralContext = null;
1388
        }
1389
      } //while
1390
    } //run()
1391
  }
1392
}
(12-12/63)