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: jones $'
12
 *     '$Date: 2000-11-07 20:22:10 -0800 (Tue, 07 Nov 2000) $'
13
 * '$Revision: 515 $'
14
 */
15

    
16
package edu.ucsb.nceas.metacat;
17

    
18
import java.net.ConnectException;
19

    
20
import javax.naming.AuthenticationException;
21
import javax.naming.Context;
22
import javax.naming.directory.Attribute;
23
import javax.naming.directory.Attributes;
24
import javax.naming.directory.BasicAttribute;
25
import javax.naming.directory.BasicAttributes;
26
import javax.naming.directory.DirContext;
27
import javax.naming.directory.InitialDirContext;
28
import javax.naming.directory.SearchResult;
29
import javax.naming.NamingEnumeration;
30
import javax.naming.NamingException;
31
import java.util.Iterator;
32
import java.util.HashMap;
33
import java.util.Hashtable;
34
import java.util.Set;
35
import java.util.Vector;
36

    
37
/**
38
 * An implementation of the AuthInterface interface that
39
 * allows Metacat to use the LDAP protocol for directory services.
40
 * The LDAP authentication service is used to determine if a user 
41
 * is authenticated, and whether they are a member of a particular group.
42
 */
43
public class AuthLdap implements AuthInterface {
44

    
45
  /**
46
   * Determine if a user/password are valid according to the authentication
47
   * service.
48
   *
49
   * @param user the name of the principal to authenticate
50
   * @param password the password to use for authentication
51
   * @returns boolean true if authentication successful, false otherwise
52
   */
53
  public boolean authenticate(String user, String password)
54
                    throws ConnectException
55
  {
56
    MetaCatUtil util = new MetaCatUtil();
57
    String ldapUrl = util.getOption("ldapurl");
58
    String ldapBase = util.getOption("ldapbase");
59

    
60
    String distName = null;
61
    boolean authenticated = false;
62

    
63
    // Identify service provider to use
64
    Hashtable env = new Hashtable(11);
65
    env.put(Context.INITIAL_CONTEXT_FACTORY, 
66
            "com.sun.jndi.ldap.LdapCtxFactory");
67
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
68

    
69
    try {
70

    
71
      // Get the dn for this uid or cn 
72
      String identifier = getIdentifyingName(user);
73
      if (identifier != null) {
74
        distName = identifier + "," + ldapBase;
75
        // Now that we have the dn, we can authenticate, so
76
        // authenticate this time when opening the DirContext
77
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
78
        env.put(Context.SECURITY_PRINCIPAL, distName);
79
        env.put(Context.SECURITY_CREDENTIALS, password);
80
        // If our auth credentials are invalid, an exception will be thrown
81
        DirContext ctx = new InitialDirContext(env);
82

    
83
        // If no exception is thrown then authentication succeeded
84
        authenticated = true;
85

    
86
        // Close the context when we're done
87
        ctx.close();
88
      } else {
89
        util.debugMessage("User not found!");
90
      }
91

    
92
    } catch (AuthenticationException ae) {
93
      util.debugMessage("Error authenticating: " + ae);
94
      // NEED TO THROW THE RIGHT EXCEPTION HERE
95
      return false;
96
    } catch (NamingException e) {
97
      util.debugMessage("Naming exception while authenticating: " + e);
98
      // NEED TO THROW THE RIGHT EXCEPTION HERE
99
      return false;
100
    }
101

    
102
    return authenticated;
103
  }
104

    
105
  /**
106
   * Get all users from the authentication service
107
   */
108
  public String[] getUsers(String user, String password) 
109
         throws ConnectException
110
  {
111
    // NOT IMPLEMENTED YET
112
    return null;
113
  }
114

    
115
  /**
116
   * Get the users for a particular group from the authentication service
117
   */
118
  public String[] getUsers(String user, String password, String group) 
119
         throws ConnectException
120
  {
121
    // NOT IMPLEMENTED YET
122
    return null;
123
  }
124

    
125
  /**
126
   * Get all groups from the authentication service
127
   */
128
  public String[] getGroups(String user, String password) 
129
         throws ConnectException
130
  {
131
    // NOT IMPLEMENTED YET
132
    return null;
133
  }
134

    
135
  /**
136
   * Get the groups for a particular user from the authentication service
137
   */
138
  public String[] getGroups(String user, String password, String foruser) 
139
         throws ConnectException
140
  {
141
    // NOT IMPLEMENTED YET
142
    return null;
143
  }
144

    
145
  /**
146
   * Get attributes describing a user or group
147
   *
148
   * @param user the user for which the attribute list is requested
149
   * @returns HashMap a map of attribute name to a Vector of values
150
   */
151
  public HashMap getAttributes(String foruser) 
152
         throws ConnectException
153
  {
154
    return getAttributes(null, null, foruser);
155
  }
156

    
157
  /**
158
   * Get attributes describing a user or group
159
   *
160
   * @param user the user for which the attribute list is requested
161
   * @param authuser the user for authenticating against the service
162
   * @param password the password for authenticating against the service
163
   * @returns HashMap a map of attribute name to a Vector of values
164
   */
165
  public HashMap getAttributes(String user, String password, String foruser) 
166
         throws ConnectException
167
  {
168
    MetaCatUtil util = new MetaCatUtil();
169
    String ldapUrl = util.getOption("ldapurl");
170
    String ldapBase = util.getOption("ldapbase");
171

    
172
    HashMap attributes = new HashMap();
173

    
174
    // Identify service provider to use
175
    Hashtable env = new Hashtable(11);
176
    env.put(Context.INITIAL_CONTEXT_FACTORY, 
177
        "com.sun.jndi.ldap.LdapCtxFactory");
178
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
179

    
180
    // Authentication information
181
    if ((user != null) && (password != null)) {
182
      String identifier = getIdentifyingName(user);
183
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
184
      env.put(Context.SECURITY_PRINCIPAL, identifier + "," + ldapBase);
185
      env.put(Context.SECURITY_CREDENTIALS, password);
186
    }
187
 
188
    try {
189
  
190
      // Find out the identifying attribute for the user
191
      String userident = getIdentifyingName(foruser);
192

    
193
      // Create the initial directory context
194
      DirContext ctx = new InitialDirContext(env);
195
        
196
      // Ask for all attributes of the user 
197
      Attributes attrs = ctx.getAttributes(userident);
198
  
199
      // Print all of the attributes
200
      NamingEnumeration en = attrs.getAll();
201
      while (en.hasMore()) {
202
        Attribute att = (Attribute)en.next();
203
        Vector values = new Vector();
204
        String attName = att.getID();
205
        NamingEnumeration attvalues = att.getAll();
206
        while (attvalues.hasMore()) {
207
          String value = (String)attvalues.next();
208
          values.add(value);
209
        }
210
        attributes.put(attName, values);
211
      }
212
  
213
      // Close the context when we're done
214
      ctx.close();
215
    } catch (NamingException e) {
216
      System.err.println("Problem getting attributes: " + e);
217
      // NEED TO THROW THE RIGHT EXCEPTION HERE
218
    }
219

    
220
    return attributes;
221
  }
222

    
223
  /**
224
   * Get the identifying name for a given userid or name.  This is the name
225
   * that is used in conjunction withthe LDAP BaseDN to create a
226
   * distinguished name (dn) for the record
227
   *
228
   * @param user the user for which the identifying name is requested
229
   * @returns String the identifying name for the user, 
230
   *          or null if not found
231
   */
232
  private String getIdentifyingName(String user) 
233
         throws ConnectException
234
  {
235
    MetaCatUtil util = new MetaCatUtil();
236
    String ldapUrl = util.getOption("ldapurl");
237
    String ldapBase = util.getOption("ldapbase");
238

    
239
    String identifier = null;
240

    
241
    // Identify service provider to use
242
    Hashtable env = new Hashtable(11);
243
    env.put(Context.INITIAL_CONTEXT_FACTORY,
244
            "com.sun.jndi.ldap.LdapCtxFactory");
245
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
246

    
247
    try {
248

    
249
      // Bind to the LDAP server, in order to search for the right
250
      // distinguished name (dn) based on userid (uid) or common name (cn)
251
      DirContext ctx = new InitialDirContext(env);
252

    
253
      // Search for the user id or name using the uid, then cn and sn attributes
254
      // If we find a record, determine the dn for the record
255
      util.debugMessage("\nStarting search phase...\n");
256
      Attributes matchAttrs = new BasicAttributes(true);
257
      matchAttrs.put(new BasicAttribute("uid", user));
258
      NamingEnumeration answer = ctx.search("", matchAttrs);
259
      if (answer.hasMore()) {
260
        SearchResult sr = (SearchResult)answer.next();
261
        identifier = sr.getName();
262
        util.debugMessage("Found: " + identifier);
263
      } else {
264
        Attributes matchAttrs2 = new BasicAttributes(true);
265
        matchAttrs2.put(new BasicAttribute("cn", user));
266
        NamingEnumeration answer2 = ctx.search("", matchAttrs2);
267
        if (answer2.hasMore()) {
268
          SearchResult sr = (SearchResult)answer2.next();
269
          identifier = sr.getName();
270
          util.debugMessage("Found: " + identifier);
271
        } else {
272
          Attributes matchAttrs3 = new BasicAttributes(true);
273
          matchAttrs3.put(new BasicAttribute("sn", user));
274
          NamingEnumeration answer3 = ctx.search("", matchAttrs3);
275
          if (answer3.hasMore()) {
276
            SearchResult sr = (SearchResult)answer3.next();
277
            identifier = sr.getName();
278
            util.debugMessage("Found: " + identifier);
279
          }
280
        }
281
      }
282
      // Close the context when we're done the initial search
283
      ctx.close();
284
    } catch (NamingException e) {
285
      util.debugMessage("Naming exception while getting dn: " + e);
286
      // NEED TO THROW THE RIGHT EXCEPTION HERE
287
      return null;
288
    }
289

    
290
    return identifier;
291
  }
292

    
293
  /**
294
   * Test method for the class
295
   */
296
  public static void main(String[] args) {
297

    
298
    // Provide a user, such as: "Matt Jones", or "jones"
299
    String user = args[0];
300
    String password = args[1];
301

    
302
    AuthLdap authservice = new AuthLdap();
303

    
304
    boolean isValid = false;
305
    try {
306
      isValid = authservice.authenticate(user, password);
307
      if (isValid) {
308
        System.out.println("Authentication successful for: " + user );
309
        System.out.println(" ");
310
      } else {
311
        System.out.println("Authentication failed for: " + user);
312
      }
313

    
314
      if (isValid) {
315
        HashMap userInfo = authservice.getAttributes(user, password, user);
316

    
317
        // Print all of the attributes
318
        Iterator attList = (Iterator)(((Set)userInfo.keySet()).iterator());
319
        while (attList.hasNext()) {
320
          String att = (String)attList.next();
321
          Vector values = (Vector)userInfo.get(att);
322
          Iterator attvalues = values.iterator();
323
          while (attvalues.hasNext()) {
324
            String value = (String)attvalues.next();
325
            System.out.println(att + ": " + value);
326
          }
327
        }
328
      }
329

    
330
    } catch (ConnectException ce) {
331
      System.err.println("Error connecting to LDAP server.");
332
    }
333
  }
334
}
(5-5/38)