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-10-26 14:38:10 -0700 (Thu, 26 Oct 2000) $'
13
 * '$Revision: 504 $'
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
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() throws ConnectException
109
  {
110
    // NOT IMPLEMENTED YET
111
    return null;
112
  }
113

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

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

    
132
  /**
133
   * Get the groups for a particular user from the authentication service
134
   */
135
  public String[] getGroups(String user) throws ConnectException
136
  {
137
    // NOT IMPLEMENTED YET
138
    return null;
139
  }
140

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

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

    
168
    HashMap attributes = new HashMap();
169

    
170
    // Identify service provider to use
171
    Hashtable env = new Hashtable(11);
172
    env.put(Context.INITIAL_CONTEXT_FACTORY, 
173
        "com.sun.jndi.ldap.LdapCtxFactory");
174
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
175

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

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

    
216
    return attributes;
217
  }
218

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

    
235
    String identifier = null;
236

    
237
    // Identify service provider to use
238
    Hashtable env = new Hashtable(11);
239
    env.put(Context.INITIAL_CONTEXT_FACTORY,
240
            "com.sun.jndi.ldap.LdapCtxFactory");
241
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
242

    
243
    try {
244

    
245
      // Bind to the LDAP server, in order to search for the right
246
      // distinguished name (dn) based on userid (uid) or common name (cn)
247
      DirContext ctx = new InitialDirContext(env);
248

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

    
286
    return identifier;
287
  }
288

    
289
  /**
290
   * Test method for the class
291
   */
292
  public static void main(String[] args) {
293

    
294
    // Provide a user, such as: "Matt Jones", or "jones"
295
    String user = args[0];
296
    String password = args[1];
297

    
298
    AuthLdap authservice = new AuthLdap();
299

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

    
310
      if (isValid) {
311
        HashMap userInfo = authservice.getAttributes(user, user, password);
312

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

    
326
    } catch (ConnectException ce) {
327
      System.err.println("Error connecting to LDAP server.");
328
    }
329
  }
330
}
(5-5/33)