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 669 jones
 *
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 503 bojilova
 */
29
30
package edu.ucsb.nceas.metacat;
31
32
import java.net.ConnectException;
33
34
import javax.naming.AuthenticationException;
35
import javax.naming.Context;
36
import javax.naming.directory.Attribute;
37
import javax.naming.directory.Attributes;
38 504 jones
import javax.naming.directory.BasicAttribute;
39
import javax.naming.directory.BasicAttributes;
40
import javax.naming.directory.DirContext;
41
import javax.naming.directory.InitialDirContext;
42
import javax.naming.directory.SearchResult;
43 503 bojilova
import javax.naming.NamingEnumeration;
44
import javax.naming.NamingException;
45
import java.util.Iterator;
46
import java.util.HashMap;
47
import java.util.Hashtable;
48
import java.util.Set;
49
import java.util.Vector;
50
51
/**
52
 * An implementation of the AuthInterface interface that
53
 * allows Metacat to use the LDAP protocol for directory services.
54
 * The LDAP authentication service is used to determine if a user
55
 * is authenticated, and whether they are a member of a particular group.
56
 */
57 515 jones
public class AuthLdap implements AuthInterface {
58 503 bojilova
59
  /**
60
   * Determine if a user/password are valid according to the authentication
61
   * service.
62
   *
63
   * @param user the name of the principal to authenticate
64
   * @param password the password to use for authentication
65
   * @returns boolean true if authentication successful, false otherwise
66
   */
67
  public boolean authenticate(String user, String password)
68
                    throws ConnectException
69
  {
70
    MetaCatUtil util = new MetaCatUtil();
71
    String ldapUrl = util.getOption("ldapurl");
72
    String ldapBase = util.getOption("ldapbase");
73
74 504 jones
    String distName = null;
75 503 bojilova
    boolean authenticated = false;
76
77
    // Identify service provider to use
78
    Hashtable env = new Hashtable(11);
79
    env.put(Context.INITIAL_CONTEXT_FACTORY,
80
            "com.sun.jndi.ldap.LdapCtxFactory");
81
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
82
83
    try {
84
85 504 jones
      // Get the dn for this uid or cn
86
      String identifier = getIdentifyingName(user);
87
      if (identifier != null) {
88
        distName = identifier + "," + ldapBase;
89
        // Now that we have the dn, we can authenticate, so
90
        // authenticate this time when opening the DirContext
91
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
92
        env.put(Context.SECURITY_PRINCIPAL, distName);
93
        env.put(Context.SECURITY_CREDENTIALS, password);
94
        // If our auth credentials are invalid, an exception will be thrown
95
        DirContext ctx = new InitialDirContext(env);
96 503 bojilova
97 504 jones
        // If no exception is thrown then authentication succeeded
98
        authenticated = true;
99
100
        // Close the context when we're done
101
        ctx.close();
102
      } else {
103
        util.debugMessage("User not found!");
104
      }
105
106 503 bojilova
    } catch (AuthenticationException ae) {
107
      util.debugMessage("Error authenticating: " + ae);
108
      // NEED TO THROW THE RIGHT EXCEPTION HERE
109
      return false;
110
    } catch (NamingException e) {
111
      util.debugMessage("Naming exception while authenticating: " + e);
112
      // NEED TO THROW THE RIGHT EXCEPTION HERE
113
      return false;
114
    }
115
116
    return authenticated;
117
  }
118
119
  /**
120
   * Get all users from the authentication service
121
   */
122 514 jones
  public String[] getUsers(String user, String password)
123
         throws ConnectException
124 503 bojilova
  {
125
    // NOT IMPLEMENTED YET
126
    return null;
127
  }
128
129
  /**
130
   * Get the users for a particular group from the authentication service
131
   */
132 514 jones
  public String[] getUsers(String user, String password, String group)
133
         throws ConnectException
134 503 bojilova
  {
135
    // NOT IMPLEMENTED YET
136
    return null;
137
  }
138
139
  /**
140
   * Get all groups from the authentication service
141
   */
142 514 jones
  public String[] getGroups(String user, String password)
143
         throws ConnectException
144 503 bojilova
  {
145
    // NOT IMPLEMENTED YET
146
    return null;
147
  }
148
149
  /**
150
   * Get the groups for a particular user from the authentication service
151
   */
152 514 jones
  public String[] getGroups(String user, String password, String foruser)
153
         throws ConnectException
154 503 bojilova
  {
155
    // NOT IMPLEMENTED YET
156
    return null;
157
  }
158
159
  /**
160
   * Get attributes describing a user or group
161
   *
162
   * @param user the user for which the attribute list is requested
163
   * @returns HashMap a map of attribute name to a Vector of values
164
   */
165 514 jones
  public HashMap getAttributes(String foruser)
166 503 bojilova
         throws ConnectException
167
  {
168 514 jones
    return getAttributes(null, null, foruser);
169 503 bojilova
  }
170
171
  /**
172
   * Get attributes describing a user or group
173
   *
174
   * @param user the user for which the attribute list is requested
175
   * @param authuser the user for authenticating against the service
176
   * @param password the password for authenticating against the service
177
   * @returns HashMap a map of attribute name to a Vector of values
178
   */
179 514 jones
  public HashMap getAttributes(String user, String password, String foruser)
180 503 bojilova
         throws ConnectException
181
  {
182
    MetaCatUtil util = new MetaCatUtil();
183
    String ldapUrl = util.getOption("ldapurl");
184
    String ldapBase = util.getOption("ldapbase");
185
186
    HashMap attributes = new HashMap();
187
188
    // Identify service provider to use
189
    Hashtable env = new Hashtable(11);
190
    env.put(Context.INITIAL_CONTEXT_FACTORY,
191
        "com.sun.jndi.ldap.LdapCtxFactory");
192
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
193
194
    // Authentication information
195 514 jones
    if ((user != null) && (password != null)) {
196
      String identifier = getIdentifyingName(user);
197 503 bojilova
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
198 504 jones
      env.put(Context.SECURITY_PRINCIPAL, identifier + "," + ldapBase);
199 503 bojilova
      env.put(Context.SECURITY_CREDENTIALS, password);
200
    }
201
202
    try {
203
204 504 jones
      // Find out the identifying attribute for the user
205 514 jones
      String userident = getIdentifyingName(foruser);
206 504 jones
207 503 bojilova
      // Create the initial directory context
208
      DirContext ctx = new InitialDirContext(env);
209
210 504 jones
      // Ask for all attributes of the user
211
      Attributes attrs = ctx.getAttributes(userident);
212 503 bojilova
213
      // Print all of the attributes
214
      NamingEnumeration en = attrs.getAll();
215
      while (en.hasMore()) {
216
        Attribute att = (Attribute)en.next();
217
        Vector values = new Vector();
218
        String attName = att.getID();
219
        NamingEnumeration attvalues = att.getAll();
220
        while (attvalues.hasMore()) {
221
          String value = (String)attvalues.next();
222
          values.add(value);
223
        }
224
        attributes.put(attName, values);
225
      }
226
227
      // Close the context when we're done
228
      ctx.close();
229
    } catch (NamingException e) {
230
      System.err.println("Problem getting attributes: " + e);
231
      // NEED TO THROW THE RIGHT EXCEPTION HERE
232
    }
233
234
    return attributes;
235
  }
236
237
  /**
238 504 jones
   * Get the identifying name for a given userid or name.  This is the name
239
   * that is used in conjunction withthe LDAP BaseDN to create a
240
   * distinguished name (dn) for the record
241
   *
242
   * @param user the user for which the identifying name is requested
243
   * @returns String the identifying name for the user,
244
   *          or null if not found
245
   */
246
  private String getIdentifyingName(String user)
247
         throws ConnectException
248
  {
249
    MetaCatUtil util = new MetaCatUtil();
250
    String ldapUrl = util.getOption("ldapurl");
251
    String ldapBase = util.getOption("ldapbase");
252
253
    String identifier = null;
254
255
    // Identify service provider to use
256
    Hashtable env = new Hashtable(11);
257
    env.put(Context.INITIAL_CONTEXT_FACTORY,
258
            "com.sun.jndi.ldap.LdapCtxFactory");
259
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
260
261
    try {
262
263
      // Bind to the LDAP server, in order to search for the right
264
      // distinguished name (dn) based on userid (uid) or common name (cn)
265
      DirContext ctx = new InitialDirContext(env);
266
267
      // Search for the user id or name using the uid, then cn and sn attributes
268
      // If we find a record, determine the dn for the record
269
      util.debugMessage("\nStarting search phase...\n");
270
      Attributes matchAttrs = new BasicAttributes(true);
271
      matchAttrs.put(new BasicAttribute("uid", user));
272
      NamingEnumeration answer = ctx.search("", matchAttrs);
273
      if (answer.hasMore()) {
274
        SearchResult sr = (SearchResult)answer.next();
275
        identifier = sr.getName();
276
        util.debugMessage("Found: " + identifier);
277
      } else {
278
        Attributes matchAttrs2 = new BasicAttributes(true);
279
        matchAttrs2.put(new BasicAttribute("cn", user));
280
        NamingEnumeration answer2 = ctx.search("", matchAttrs2);
281
        if (answer2.hasMore()) {
282
          SearchResult sr = (SearchResult)answer2.next();
283
          identifier = sr.getName();
284
          util.debugMessage("Found: " + identifier);
285
        } else {
286
          Attributes matchAttrs3 = new BasicAttributes(true);
287
          matchAttrs3.put(new BasicAttribute("sn", user));
288
          NamingEnumeration answer3 = ctx.search("", matchAttrs3);
289
          if (answer3.hasMore()) {
290
            SearchResult sr = (SearchResult)answer3.next();
291
            identifier = sr.getName();
292
            util.debugMessage("Found: " + identifier);
293
          }
294
        }
295
      }
296
      // Close the context when we're done the initial search
297
      ctx.close();
298
    } catch (NamingException e) {
299
      util.debugMessage("Naming exception while getting dn: " + e);
300
      // NEED TO THROW THE RIGHT EXCEPTION HERE
301
      return null;
302
    }
303
304
    return identifier;
305
  }
306
307
  /**
308 503 bojilova
   * Test method for the class
309
   */
310
  public static void main(String[] args) {
311
312 504 jones
    // Provide a user, such as: "Matt Jones", or "jones"
313 503 bojilova
    String user = args[0];
314
    String password = args[1];
315
316
    AuthLdap authservice = new AuthLdap();
317
318
    boolean isValid = false;
319
    try {
320
      isValid = authservice.authenticate(user, password);
321
      if (isValid) {
322
        System.out.println("Authentication successful for: " + user );
323
        System.out.println(" ");
324
      } else {
325
        System.out.println("Authentication failed for: " + user);
326
      }
327
328
      if (isValid) {
329 514 jones
        HashMap userInfo = authservice.getAttributes(user, password, user);
330 503 bojilova
331
        // Print all of the attributes
332
        Iterator attList = (Iterator)(((Set)userInfo.keySet()).iterator());
333
        while (attList.hasNext()) {
334
          String att = (String)attList.next();
335
          Vector values = (Vector)userInfo.get(att);
336
          Iterator attvalues = values.iterator();
337
          while (attvalues.hasNext()) {
338
            String value = (String)attvalues.next();
339 504 jones
            System.out.println(att + ": " + value);
340 503 bojilova
          }
341
        }
342
      }
343
344
    } catch (ConnectException ce) {
345
      System.err.println("Error connecting to LDAP server.");
346
    }
347
  }
348
}