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: berkley $'
12
 *     '$Date: 2001-01-18 15:15:21 -0800 (Thu, 18 Jan 2001) $'
13
 * '$Revision: 675 $'
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

    
34
import javax.naming.AuthenticationException;
35
import javax.naming.Context;
36
import javax.naming.directory.Attribute;
37
import javax.naming.directory.Attributes;
38
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
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
public class AuthLdap implements AuthInterface {
58

    
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
    String distName = null;
75
    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
      // 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

    
97
        // 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
    } catch (AuthenticationException ae) {
107
      util.debugMessage("Error authenticating in AuthLdap.authenticate: " + ae);
108
      // NEED TO THROW THE RIGHT EXCEPTION HERE
109
      return false;
110
    } catch (NamingException e) {
111
      util.debugMessage("Naming exception while authenticating in " + 
112
                        "AuthLdap.authenticate: " + e);
113
      // NEED TO THROW THE RIGHT EXCEPTION HERE
114
      return false;
115
    }
116

    
117
    return authenticated;
118
  }
119

    
120
  /**
121
   * Get all users from the authentication service
122
   */
123
  public String[] getUsers(String user, String password) 
124
         throws ConnectException
125
  {
126
    // NOT IMPLEMENTED YET
127
    return null;
128
  }
129

    
130
  /**
131
   * Get the users for a particular group from the authentication service
132
   */
133
  public String[] getUsers(String user, String password, String group) 
134
         throws ConnectException
135
  {
136
    // NOT IMPLEMENTED YET
137
    return null;
138
  }
139

    
140
  /**
141
   * Get all groups from the authentication service
142
   */
143
  public String[] getGroups(String user, String password) 
144
         throws ConnectException
145
  {
146
    // NOT IMPLEMENTED YET
147
    return null;
148
  }
149

    
150
  /**
151
   * Get the groups for a particular user from the authentication service
152
   */
153
  public String[] getGroups(String user, String password, String foruser) 
154
         throws ConnectException
155
  {
156
    // NOT IMPLEMENTED YET
157
    return null;
158
  }
159

    
160
  /**
161
   * Get attributes describing a user or group
162
   *
163
   * @param user the user for which the attribute list is requested
164
   * @returns HashMap a map of attribute name to a Vector of values
165
   */
166
  public HashMap getAttributes(String foruser) 
167
         throws ConnectException
168
  {
169
    return getAttributes(null, null, foruser);
170
  }
171

    
172
  /**
173
   * Get attributes describing a user or group
174
   *
175
   * @param user the user for which the attribute list is requested
176
   * @param authuser the user for authenticating against the service
177
   * @param password the password for authenticating against the service
178
   * @returns HashMap a map of attribute name to a Vector of values
179
   */
180
  public HashMap getAttributes(String user, String password, String foruser) 
181
         throws ConnectException
182
  {
183
    MetaCatUtil util = new MetaCatUtil();
184
    String ldapUrl = util.getOption("ldapurl");
185
    String ldapBase = util.getOption("ldapbase");
186

    
187
    HashMap attributes = new HashMap();
188

    
189
    // Identify service provider to use
190
    Hashtable env = new Hashtable(11);
191
    env.put(Context.INITIAL_CONTEXT_FACTORY, 
192
        "com.sun.jndi.ldap.LdapCtxFactory");
193
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
194

    
195
    // Authentication information
196
    if ((user != null) && (password != null)) {
197
      String identifier = getIdentifyingName(user);
198
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
199
      env.put(Context.SECURITY_PRINCIPAL, identifier + "," + ldapBase);
200
      env.put(Context.SECURITY_CREDENTIALS, password);
201
    }
202
 
203
    try {
204
  
205
      // Find out the identifying attribute for the user
206
      String userident = getIdentifyingName(foruser);
207

    
208
      // Create the initial directory context
209
      DirContext ctx = new InitialDirContext(env);
210
        
211
      // Ask for all attributes of the user 
212
      Attributes attrs = ctx.getAttributes(userident);
213
  
214
      // Print all of the attributes
215
      NamingEnumeration en = attrs.getAll();
216
      while (en.hasMore()) {
217
        Attribute att = (Attribute)en.next();
218
        Vector values = new Vector();
219
        String attName = att.getID();
220
        NamingEnumeration attvalues = att.getAll();
221
        while (attvalues.hasMore()) {
222
          String value = (String)attvalues.next();
223
          values.add(value);
224
        }
225
        attributes.put(attName, values);
226
      }
227
  
228
      // Close the context when we're done
229
      ctx.close();
230
    } catch (NamingException e) {
231
      System.err.println("Problem getting attributes in AuthLdap.getAttributes:" 
232
                          + e);
233
      // NEED TO THROW THE RIGHT EXCEPTION HERE
234
    }
235

    
236
    return attributes;
237
  }
238

    
239
  /**
240
   * Get the identifying name for a given userid or name.  This is the name
241
   * that is used in conjunction withthe LDAP BaseDN to create a
242
   * distinguished name (dn) for the record
243
   *
244
   * @param user the user for which the identifying name is requested
245
   * @returns String the identifying name for the user, 
246
   *          or null if not found
247
   */
248
  private String getIdentifyingName(String user) 
249
         throws ConnectException
250
  {
251
    MetaCatUtil util = new MetaCatUtil();
252
    String ldapUrl = util.getOption("ldapurl");
253
    String ldapBase = util.getOption("ldapbase");
254

    
255
    String identifier = null;
256

    
257
    // Identify service provider to use
258
    Hashtable env = new Hashtable(11);
259
    env.put(Context.INITIAL_CONTEXT_FACTORY,
260
            "com.sun.jndi.ldap.LdapCtxFactory");
261
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
262

    
263
    try {
264

    
265
      // Bind to the LDAP server, in order to search for the right
266
      // distinguished name (dn) based on userid (uid) or common name (cn)
267
      DirContext ctx = new InitialDirContext(env);
268

    
269
      // Search for the user id or name using the uid, then cn and sn attributes
270
      // If we find a record, determine the dn for the record
271
      util.debugMessage("\nStarting search phase...\n");
272
      Attributes matchAttrs = new BasicAttributes(true);
273
      matchAttrs.put(new BasicAttribute("uid", user));
274
      NamingEnumeration answer = ctx.search("", matchAttrs);
275
      if (answer.hasMore()) {
276
        SearchResult sr = (SearchResult)answer.next();
277
        identifier = sr.getName();
278
        util.debugMessage("Found: " + identifier);
279
      } else {
280
        Attributes matchAttrs2 = new BasicAttributes(true);
281
        matchAttrs2.put(new BasicAttribute("cn", user));
282
        NamingEnumeration answer2 = ctx.search("", matchAttrs2);
283
        if (answer2.hasMore()) {
284
          SearchResult sr = (SearchResult)answer2.next();
285
          identifier = sr.getName();
286
          util.debugMessage("Found: " + identifier);
287
        } else {
288
          Attributes matchAttrs3 = new BasicAttributes(true);
289
          matchAttrs3.put(new BasicAttribute("sn", user));
290
          NamingEnumeration answer3 = ctx.search("", matchAttrs3);
291
          if (answer3.hasMore()) {
292
            SearchResult sr = (SearchResult)answer3.next();
293
            identifier = sr.getName();
294
            util.debugMessage("Found: " + identifier);
295
          }
296
        }
297
      }
298
      // Close the context when we're done the initial search
299
      ctx.close();
300
    } catch (NamingException e) {
301
      util.debugMessage("Naming exception while getting dn: " + e);
302
      System.out.println("Naming exception in AuthLdap.getIdentifyingName");
303
      // NEED TO THROW THE RIGHT EXCEPTION HERE
304
      return null;
305
    }
306

    
307
    return identifier;
308
  }
309

    
310
  /**
311
   * Test method for the class
312
   */
313
  public static void main(String[] args) {
314

    
315
    // Provide a user, such as: "Matt Jones", or "jones"
316
    String user = args[0];
317
    String password = args[1];
318

    
319
    AuthLdap authservice = new AuthLdap();
320

    
321
    boolean isValid = false;
322
    try {
323
      isValid = authservice.authenticate(user, password);
324
      if (isValid) {
325
        System.out.println("Authentication successful for: " + user );
326
        System.out.println(" ");
327
      } else {
328
        System.out.println("Authentication failed for: " + user);
329
      }
330

    
331
      if (isValid) {
332
        HashMap userInfo = authservice.getAttributes(user, password, user);
333

    
334
        // Print all of the attributes
335
        Iterator attList = (Iterator)(((Set)userInfo.keySet()).iterator());
336
        while (attList.hasNext()) {
337
          String att = (String)attList.next();
338
          Vector values = (Vector)userInfo.get(att);
339
          Iterator attvalues = values.iterator();
340
          while (attvalues.hasNext()) {
341
            String value = (String)attvalues.next();
342
            System.out.println(att + ": " + value);
343
          }
344
        }
345
      }
346

    
347
    } catch (ConnectException ce) {
348
      System.err.println("Error connecting to LDAP server in authldap.main");
349
    }
350
  }
351
}
(6-6/43)