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: 2001-01-18 11:52:00 -0800 (Thu, 18 Jan 2001) $'
13
 * '$Revision: 669 $'
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: " + 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
  public String[] getUsers(String user, String password) 
123
         throws ConnectException
124
  {
125
    // NOT IMPLEMENTED YET
126
    return null;
127
  }
128

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

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

    
149
  /**
150
   * Get the groups for a particular user from the authentication service
151
   */
152
  public String[] getGroups(String user, String password, String foruser) 
153
         throws ConnectException
154
  {
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
  public HashMap getAttributes(String foruser) 
166
         throws ConnectException
167
  {
168
    return getAttributes(null, null, foruser);
169
  }
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
  public HashMap getAttributes(String user, String password, String foruser) 
180
         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
    if ((user != null) && (password != null)) {
196
      String identifier = getIdentifyingName(user);
197
      env.put(Context.SECURITY_AUTHENTICATION, "simple");
198
      env.put(Context.SECURITY_PRINCIPAL, identifier + "," + ldapBase);
199
      env.put(Context.SECURITY_CREDENTIALS, password);
200
    }
201
 
202
    try {
203
  
204
      // Find out the identifying attribute for the user
205
      String userident = getIdentifyingName(foruser);
206

    
207
      // Create the initial directory context
208
      DirContext ctx = new InitialDirContext(env);
209
        
210
      // Ask for all attributes of the user 
211
      Attributes attrs = ctx.getAttributes(userident);
212
  
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
   * 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
   * Test method for the class
309
   */
310
  public static void main(String[] args) {
311

    
312
    // Provide a user, such as: "Matt Jones", or "jones"
313
    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
        HashMap userInfo = authservice.getAttributes(user, password, user);
330

    
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
            System.out.println(att + ": " + value);
340
          }
341
        }
342
      }
343

    
344
    } catch (ConnectException ce) {
345
      System.err.println("Error connecting to LDAP server.");
346
    }
347
  }
348
}
(6-6/43)