Project

General

Profile

1 503 bojilova
/**
2
 *  '$RCSfile$'
3
 *    Purpose: An implementation of the AuthInterface interface that
4
 *             allows Metacat to use the LDAP protocol for
5
 *             directory services
6
 *  Copyright: 2000 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    Authors: Matt Jones
9
 *    Release: @release@
10
 *
11
 *   '$Author$'
12
 *     '$Date$'
13
 * '$Revision$'
14
 */
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 504 jones
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 503 bojilova
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 515 jones
public class AuthLdap implements AuthInterface {
44 503 bojilova
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 504 jones
    String distName = null;
61 503 bojilova
    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 504 jones
      // 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 503 bojilova
83 504 jones
        // 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 503 bojilova
    } 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 514 jones
  public String[] getUsers(String user, String password)
109
         throws ConnectException
110 503 bojilova
  {
111
    // NOT IMPLEMENTED YET
112
    return null;
113
  }
114
115
  /**
116
   * Get the users for a particular group from the authentication service
117
   */
118 514 jones
  public String[] getUsers(String user, String password, String group)
119
         throws ConnectException
120 503 bojilova
  {
121
    // NOT IMPLEMENTED YET
122
    return null;
123
  }
124
125
  /**
126
   * Get all groups from the authentication service
127
   */
128 514 jones
  public String[] getGroups(String user, String password)
129
         throws ConnectException
130 503 bojilova
  {
131
    // NOT IMPLEMENTED YET
132
    return null;
133
  }
134
135
  /**
136
   * Get the groups for a particular user from the authentication service
137
   */
138 514 jones
  public String[] getGroups(String user, String password, String foruser)
139
         throws ConnectException
140 503 bojilova
  {
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 514 jones
  public HashMap getAttributes(String foruser)
152 503 bojilova
         throws ConnectException
153
  {
154 514 jones
    return getAttributes(null, null, foruser);
155 503 bojilova
  }
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 514 jones
  public HashMap getAttributes(String user, String password, String foruser)
166 503 bojilova
         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 514 jones
    if ((user != null) && (password != null)) {
182
      String identifier = getIdentifyingName(user);
183 503 bojilova
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
184 504 jones
      env.put(Context.SECURITY_PRINCIPAL, identifier + "," + ldapBase);
185 503 bojilova
      env.put(Context.SECURITY_CREDENTIALS, password);
186
    }
187
188
    try {
189
190 504 jones
      // Find out the identifying attribute for the user
191 514 jones
      String userident = getIdentifyingName(foruser);
192 504 jones
193 503 bojilova
      // Create the initial directory context
194
      DirContext ctx = new InitialDirContext(env);
195
196 504 jones
      // Ask for all attributes of the user
197
      Attributes attrs = ctx.getAttributes(userident);
198 503 bojilova
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 504 jones
   * 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 503 bojilova
   * Test method for the class
295
   */
296
  public static void main(String[] args) {
297
298 504 jones
    // Provide a user, such as: "Matt Jones", or "jones"
299 503 bojilova
    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 514 jones
        HashMap userInfo = authservice.getAttributes(user, password, user);
316 503 bojilova
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 504 jones
            System.out.println(att + ": " + value);
326 503 bojilova
          }
327
        }
328
      }
329
330
    } catch (ConnectException ce) {
331
      System.err.println("Error connecting to LDAP server.");
332
    }
333
  }
334
}