Project

General

Profile

« Previous | Next » 

Revision 504

Added by Matt Jones over 23 years ago

Fixed the LDAP authentication adapter (AuthLdap.java) so that it now looks up
the distinguished name for a user before attempting to do authentication.
This is because the user's distinguished name can sometimes be based on
their uid attribute, but sometimes be based on their cn (common name)
attribute, or some other attribute. In order to authenticate, we must
be able construct the distinguished name, so we have to look up the
identifying attribute before trying to authenticate. Basically, this
lets us authenticate agains both of the following records:

dn: uid=jones,o=NCEAS,c=US

and

dn: cn=Matt Jones,o=NCEAS,c=US

Effectively, this means that the user can type in their user id (uid),
common name (cn), or surname (sn) and we'll still be able to authenticate them.
BugID: 138

View differences:

AuthLdap.java
19 19

  
20 20
import javax.naming.AuthenticationException;
21 21
import javax.naming.Context;
22
import javax.naming.directory.InitialDirContext;
23
import javax.naming.directory.DirContext;
24 22
import javax.naming.directory.Attribute;
25 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;
26 29
import javax.naming.NamingEnumeration;
27 30
import javax.naming.NamingException;
28 31
import java.util.Iterator;
......
54 57
    String ldapUrl = util.getOption("ldapurl");
55 58
    String ldapBase = util.getOption("ldapbase");
56 59

  
60
    String distName = null;
57 61
    boolean authenticated = false;
58 62

  
59 63
    // Identify service provider to use
......
62 66
            "com.sun.jndi.ldap.LdapCtxFactory");
63 67
    env.put(Context.PROVIDER_URL, ldapUrl + ldapBase);
64 68

  
65
    // Authentication information
66
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
67
    env.put(Context.SECURITY_PRINCIPAL, user + "," + ldapBase);
68
    env.put(Context.SECURITY_CREDENTIALS, password);
69

  
70 69
    try {
71 70

  
72
      // Bind to the LDAP server
73
      // If our auth credentials are invalid, an exception will be thrown
74
      DirContext ctx = new InitialDirContext(env);
75
      authenticated = true;
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);
76 82

  
77
      // Close the context when we're done
78
      ctx.close();
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

  
79 92
    } catch (AuthenticationException ae) {
80 93
      util.debugMessage("Error authenticating: " + ae);
81 94
      // NEED TO THROW THE RIGHT EXCEPTION HERE
......
162 175

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

  
172 189
      // Create the initial directory context
173 190
      DirContext ctx = new InitialDirContext(env);
174 191
        
175
      // Ask for all attributes of the object 
176
      Attributes attrs = ctx.getAttributes(user);
192
      // Ask for all attributes of the user 
193
      Attributes attrs = ctx.getAttributes(userident);
177 194
  
178 195
      // Print all of the attributes
179 196
      NamingEnumeration en = attrs.getAll();
......
200 217
  }
201 218

  
202 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
  /**
203 290
   * Test method for the class
204 291
   */
205 292
  public static void main(String[] args) {
206 293

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

  
......
221 308
      }
222 309

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

  
226 313
        // Print all of the attributes
227 314
        Iterator attList = (Iterator)(((Set)userInfo.keySet()).iterator());
228 315
        while (attList.hasNext()) {
229 316
          String att = (String)attList.next();
230 317
          Vector values = (Vector)userInfo.get(att);
231
          System.out.println(att + ": " );
232 318
          Iterator attvalues = values.iterator();
233 319
          while (attvalues.hasNext()) {
234 320
            String value = (String)attvalues.next();
235
            System.out.println("  value: " + value);
321
            System.out.println(att + ": " + value);
236 322
          }
237 323
        }
238 324
      }

Also available in: Unified diff