Coverage report

  %line %branch
org.apache.turbine.services.security.ldap.LDAPUserManager
0% 
0% 

 1  
 package org.apache.turbine.services.security.ldap;
 2  
 
 3  
 /*
 4  
  * Copyright 2001-2005 The Apache Software Foundation.
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License")
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  *     http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import java.util.List;
 20  
 import java.util.Hashtable;
 21  
 import java.util.Vector;
 22  
 
 23  
 import javax.naming.AuthenticationException;
 24  
 import javax.naming.Context;
 25  
 import javax.naming.NamingEnumeration;
 26  
 import javax.naming.NamingException;
 27  
 import javax.naming.directory.Attributes;
 28  
 import javax.naming.directory.DirContext;
 29  
 import javax.naming.directory.SearchControls;
 30  
 import javax.naming.directory.SearchResult;
 31  
 
 32  
 import org.apache.commons.configuration.Configuration;
 33  
 
 34  
 import org.apache.torque.util.Criteria;
 35  
 
 36  
 import org.apache.turbine.om.security.User;
 37  
 import org.apache.turbine.services.security.TurbineSecurity;
 38  
 import org.apache.turbine.services.security.UserManager;
 39  
 import org.apache.turbine.util.security.DataBackendException;
 40  
 import org.apache.turbine.util.security.EntityExistsException;
 41  
 import org.apache.turbine.util.security.PasswordMismatchException;
 42  
 import org.apache.turbine.util.security.UnknownEntityException;
 43  
 
 44  
 /**
 45  
  * A UserManager performs {@link org.apache.turbine.om.security.User}
 46  
  * object related tasks on behalf of the
 47  
  * {@link org.apache.turbine.services.security.SecurityService}.
 48  
  *
 49  
  * This implementation uses ldap for retrieving user data. It
 50  
  * expects that the User interface implementation will be castable to
 51  
  * {@link org.apache.turbine.om.BaseObject}.
 52  
  *
 53  
  * @author <a href="mailto:jon@collab.net">Jon S. Stevens</a>
 54  
  * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
 55  
  * @author <a href="mailto:frank.kim@clearink.com">Frank Y. Kim</a>
 56  
  * @author <a href="mailto:cberry@gluecode.com">Craig D. Berry</a>
 57  
  * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
 58  
  * @author <a href="mailto:tadewunmi@gluecode.com">Tracy M. Adewunmi</a>
 59  
  * @author <a href="mailto:lflournoy@gluecode.com">Leonard J. Flournoy</a>
 60  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
 61  
  * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 62  
  * @author <a href="mailto:hhernandez@itweb.com.mx">Humberto Hernandez</a>
 63  
  * @version $Id: LDAPUserManager.java 264148 2005-08-29 14:21:04Z henning $
 64  
  */
 65  0
 public class LDAPUserManager implements UserManager
 66  
 {
 67  
     /**
 68  
      * Initializes the UserManager
 69  
      *
 70  
      * @param conf A Configuration object to init this Manager
 71  
      */
 72  
     public void init(Configuration conf)
 73  
     {
 74  
         // GNDN
 75  0
     }
 76  
 
 77  
     /**
 78  
      * Check wether a specified user's account exists.
 79  
      *
 80  
      * The login name is used for looking up the account.
 81  
      *
 82  
      * @param user The user to be checked.
 83  
      * @return true if the specified account exists
 84  
      * @throws DataBackendException Error accessing the data backend.
 85  
      */
 86  
     public boolean accountExists(User user) throws DataBackendException
 87  
     {
 88  0
         return accountExists(user.getName());
 89  
     }
 90  
 
 91  
     /**
 92  
      *
 93  
      * Check wether a specified user's account exists.
 94  
      * The login name is used for looking up the account.
 95  
      *
 96  
      * @param username The name of the user to be checked.
 97  
      * @return true if the specified account exists
 98  
      * @throws DataBackendException Error accessing the data backend.
 99  
      */
 100  
     public boolean accountExists(String username)
 101  
             throws DataBackendException
 102  
     {
 103  
         try
 104  
         {
 105  0
             User ldapUser = retrieve(username);
 106  
         }
 107  0
         catch (UnknownEntityException ex)
 108  
         {
 109  0
             return false;
 110  0
         }
 111  
 
 112  0
         return true;
 113  
     }
 114  
 
 115  
     /**
 116  
      * Retrieve a user from persistent storage using username as the
 117  
      * key.
 118  
      *
 119  
      * @param username the name of the user.
 120  
      * @return an User object.
 121  
      * @exception UnknownEntityException if the user's account does not
 122  
      *            exist in the database.
 123  
      * @exception DataBackendException Error accessing the data backend.
 124  
      */
 125  
     public User retrieve(String username)
 126  
             throws UnknownEntityException, DataBackendException
 127  
     {
 128  
         try
 129  
         {
 130  0
             DirContext ctx = bindAsAdmin();
 131  
 
 132  
             /*
 133  
              * Define the search.
 134  
              */
 135  0
             String userBaseSearch = LDAPSecurityConstants.getBaseSearch();
 136  0
             String filter = LDAPSecurityConstants.getNameAttribute();
 137  
 
 138  0
             filter = "(" + filter + "=" + username + ")";
 139  
 
 140  
             /*
 141  
              * Create the default search controls.
 142  
              */
 143  0
             SearchControls ctls = new SearchControls();
 144  
 
 145  0
             NamingEnumeration answer =
 146  
                     ctx.search(userBaseSearch, filter, ctls);
 147  
 
 148  0
             if (answer.hasMore())
 149  
             {
 150  0
                 SearchResult sr = (SearchResult) answer.next();
 151  0
                 Attributes attribs = sr.getAttributes();
 152  0
                 LDAPUser ldapUser = createLDAPUser();
 153  
 
 154  0
                 ldapUser.setLDAPAttributes(attribs);
 155  0
                 ldapUser.setTemp("turbine.user", ldapUser);
 156  
 
 157  0
                 return ldapUser;
 158  
             }
 159  
             else
 160  
             {
 161  0
                 throw new UnknownEntityException("The given user: "
 162  
                         + username + "\n does not exist.");
 163  
             }
 164  
         }
 165  0
         catch (NamingException ex)
 166  
         {
 167  0
             throw new DataBackendException(
 168  
                     "The LDAP server specified is unavailable", ex);
 169  
         }
 170  
     }
 171  
 
 172  
     /**
 173  
      * Retrieve a user from persistent storage using the primary key
 174  
      *
 175  
      * @param key The primary key object
 176  
      * @return an User object.
 177  
      * @throws UnknownEntityException if the user's record does not
 178  
      *         exist in the database.
 179  
      * @throws DataBackendException if there is a problem accessing the
 180  
      *         storage.
 181  
      */
 182  
     public User retrieveById(Object key)
 183  
             throws UnknownEntityException, DataBackendException
 184  
     {
 185  
         try
 186  
         {
 187  0
             DirContext ctx = bindAsAdmin();
 188  
 
 189  
             /*
 190  
              * Define the search.
 191  
              */
 192  0
             StringBuffer userBaseSearch = new StringBuffer();
 193  0
             userBaseSearch.append(LDAPSecurityConstants.getUserIdAttribute());
 194  0
             userBaseSearch.append("=");
 195  0
             userBaseSearch.append(String.valueOf(key));
 196  0
             userBaseSearch.append(",");
 197  0
             userBaseSearch.append(LDAPSecurityConstants.getBaseSearch());
 198  
 
 199  
             /*
 200  
              * Create the default search controls.
 201  
              */
 202  0
             NamingEnumeration answer =
 203  
                     ctx.search(userBaseSearch.toString(), (Attributes)null);
 204  
 
 205  0
             if (answer.hasMore())
 206  
             {
 207  0
                 SearchResult sr = (SearchResult) answer.next();
 208  0
                 Attributes attribs = sr.getAttributes();
 209  0
                 LDAPUser ldapUser = createLDAPUser();
 210  
 
 211  0
                 ldapUser.setLDAPAttributes(attribs);
 212  0
                 ldapUser.setTemp("turbine.user", ldapUser);
 213  
 
 214  0
                 return ldapUser;
 215  
             }
 216  
             else
 217  
             {
 218  0
                 throw new UnknownEntityException("No user exists for the key: "
 219  
                         + String.valueOf(key) + "\n");
 220  
             }
 221  
         }
 222  0
         catch (NamingException ex)
 223  
         {
 224  0
             throw new DataBackendException(
 225  
                     "The LDAP server specified is unavailable", ex);
 226  
         }
 227  
     }
 228  
 
 229  
     /**
 230  
      * This is currently not implemented to behave as expected.  It
 231  
      * ignores the Criteria argument and returns all the users.
 232  
      *
 233  
      * Retrieve a set of users that meet the specified criteria.
 234  
      *
 235  
      * As the keys for the criteria, you should use the constants that
 236  
      * are defined in {@link User} interface, plus the the names
 237  
      * of the custom attributes you added to your user representation
 238  
      * in the data storage. Use verbatim names of the attributes -
 239  
      * without table name prefix in case of DB implementation.
 240  
      *
 241  
      * @param criteria The criteria of selection.
 242  
      * @return a List of users meeting the criteria.
 243  
      * @throws DataBackendException Error accessing the data backend.
 244  
      * @deprecated Use <a href="#retrieveList">retrieveList</a> instead.
 245  
      */
 246  
     public User[] retrieve(Criteria criteria)
 247  
             throws DataBackendException
 248  
     {
 249  0
         return (User []) retrieveList(criteria).toArray(new User[0]);
 250  
     }
 251  
 
 252  
     /**
 253  
      * Retrieve a list of users that meet the specified criteria.
 254  
      *
 255  
      * As the keys for the criteria, you should use the constants that
 256  
      * are defined in {@link User} interface, plus the names
 257  
      * of the custom attributes you added to your user representation
 258  
      * in the data storage. Use verbatim names of the attributes -
 259  
      * without table name prefix in case of Torque implementation.
 260  
      *
 261  
      * @param criteria The criteria of selection.
 262  
      * @return a List of users meeting the criteria.
 263  
      * @throws DataBackendException if there is a problem accessing the
 264  
      *         storage.
 265  
      */
 266  
     public List retrieveList(Criteria criteria)
 267  
             throws DataBackendException
 268  
     {
 269  0
         List users = new Vector(0);
 270  
 
 271  
         try
 272  
         {
 273  0
             DirContext ctx = bindAsAdmin();
 274  
 
 275  0
             String userBaseSearch = LDAPSecurityConstants.getBaseSearch();
 276  0
             String filter = LDAPSecurityConstants.getNameAttribute();
 277  
 
 278  0
             filter = "(" + filter + "=*)";
 279  
 
 280  
             /*
 281  
              * Create the default search controls.
 282  
              */
 283  0
             SearchControls ctls = new SearchControls();
 284  
 
 285  0
             NamingEnumeration answer =
 286  
                     ctx.search(userBaseSearch, filter, ctls);
 287  
 
 288  0
             while (answer.hasMore())
 289  
             {
 290  0
                 SearchResult sr = (SearchResult) answer.next();
 291  0
                 Attributes attribs = sr.getAttributes();
 292  0
                 LDAPUser ldapUser = createLDAPUser();
 293  
 
 294  0
                 ldapUser.setLDAPAttributes(attribs);
 295  0
                 ldapUser.setTemp("turbine.user", ldapUser);
 296  0
                 users.add(ldapUser);
 297  
             }
 298  
         }
 299  0
         catch (NamingException ex)
 300  
         {
 301  0
             throw new DataBackendException(
 302  
                     "The LDAP server specified is unavailable", ex);
 303  0
         }
 304  0
         return users;
 305  
     }
 306  
 
 307  
     /**
 308  
      * Retrieve a user from persistent storage using username as the
 309  
      * key, and authenticate the user. The implementation may chose
 310  
      * to authenticate to the server as the user whose data is being
 311  
      * retrieved.
 312  
      *
 313  
      * @param username the name of the user.
 314  
      * @param password the user supplied password.
 315  
      * @return an User object.
 316  
      * @exception PasswordMismatchException if the supplied password was
 317  
      *            incorrect.
 318  
      * @exception UnknownEntityException if the user's account does not
 319  
      *            exist in the database.
 320  
      * @exception DataBackendException Error accessing the data backend.
 321  
      */
 322  
     public User retrieve(String username, String password)
 323  
             throws PasswordMismatchException,
 324  
             UnknownEntityException, DataBackendException
 325  
     {
 326  0
         User user = retrieve(username);
 327  
 
 328  0
         authenticate(user, password);
 329  0
         return user;
 330  
     }
 331  
 
 332  
     /**
 333  
      * Save a User object to persistent storage. User's account is
 334  
      * required to exist in the storage.
 335  
      *
 336  
      * @param user an User object to store.
 337  
      * @throws UnknownEntityException if the user's account does not
 338  
      *            exist in the database.
 339  
      * @throws DataBackendException if there is an LDAP error
 340  
      *
 341  
      */
 342  
     public void store(User user)
 343  
             throws UnknownEntityException, DataBackendException
 344  
     {
 345  0
         if (!accountExists(user))
 346  
         {
 347  0
             throw new UnknownEntityException("The account '"
 348  
                     + user.getName() + "' does not exist");
 349  
         }
 350  
 
 351  
         try
 352  
         {
 353  0
             LDAPUser ldapUser = (LDAPUser) user;
 354  0
             Attributes attrs = ldapUser.getLDAPAttributes();
 355  0
             String name = ldapUser.getDN();
 356  
 
 357  0
             DirContext ctx = bindAsAdmin();
 358  
 
 359  0
             ctx.modifyAttributes(name, DirContext.REPLACE_ATTRIBUTE, attrs);
 360  
         }
 361  0
         catch (NamingException ex)
 362  
         {
 363  0
             throw new DataBackendException("NamingException caught", ex);
 364  0
         }
 365  0
     }
 366  
 
 367  
     /**
 368  
      * This method is not yet implemented.
 369  
      * Saves User data when the session is unbound. The user account is required
 370  
      * to exist in the storage.
 371  
      *
 372  
      * LastLogin, AccessCounter, persistent pull tools, and any data stored
 373  
      * in the permData hashtable that is not mapped to a column will be saved.
 374  
      *
 375  
      * @exception UnknownEntityException if the user's account does not
 376  
      *            exist in the database.
 377  
      * @exception DataBackendException if there is a problem accessing the
 378  
      *            storage.
 379  
      */
 380  
     public void saveOnSessionUnbind(User user)
 381  
             throws UnknownEntityException, DataBackendException
 382  
     {
 383  0
         if (!accountExists(user))
 384  
         {
 385  0
             throw new UnknownEntityException("The account '" +
 386  
                     user.getName() + "' does not exist");
 387  
         }
 388  0
     }
 389  
 
 390  
     /**
 391  
      * Authenticate a User with the specified password. If authentication
 392  
      * is successful the method returns nothing. If there are any problems,
 393  
      * exception was thrown.
 394  
      *
 395  
      * @param user a User object to authenticate.
 396  
      * @param password the user supplied password.
 397  
      * @exception PasswordMismatchException if the supplied password was
 398  
      *            incorrect.
 399  
      * @exception UnknownEntityException if the user's account does not
 400  
      *            exist in the database.
 401  
      * @exception DataBackendException Error accessing the data backend.
 402  
      */
 403  
     public void authenticate(User user, String password)
 404  
             throws PasswordMismatchException,
 405  
             UnknownEntityException,
 406  
             DataBackendException
 407  
     {
 408  0
         LDAPUser ldapUser = (LDAPUser) user;
 409  
 
 410  
         try
 411  
         {
 412  0
             bind(ldapUser.getDN(), password);
 413  
         }
 414  0
         catch (AuthenticationException ex)
 415  
         {
 416  0
             throw new PasswordMismatchException(
 417  
                     "The given password for: "
 418  
                     + ldapUser.getDN() + " is invalid\n");
 419  
         }
 420  0
         catch (NamingException ex)
 421  
         {
 422  0
             throw new DataBackendException(
 423  
                     "NamingException caught:", ex);
 424  0
         }
 425  0
     }
 426  
 
 427  
     /**
 428  
      * This method is not yet implemented
 429  
      * Change the password for an User.
 430  
      *
 431  
      * @param user an User to change password for.
 432  
      * @param newPass the new password.
 433  
      * @param oldPass the old password.
 434  
      * @exception PasswordMismatchException if the supplied password was
 435  
      *            incorrect.
 436  
      * @exception UnknownEntityException if the user's account does not
 437  
      *            exist in the database.
 438  
      * @exception DataBackendException Error accessing the data backend.
 439  
      */
 440  
     public void changePassword(User user, String oldPass, String newPass)
 441  
             throws PasswordMismatchException,
 442  
             UnknownEntityException, DataBackendException
 443  
     {
 444  0
         throw new DataBackendException(
 445  
                 "The method changePassword has no implementation.");
 446  
     }
 447  
 
 448  
     /**
 449  
      * This method is not yet implemented
 450  
      * Forcibly sets new password for an User.
 451  
      *
 452  
      * This is supposed to be used by the administrator to change the forgotten
 453  
      * or compromised passwords. Certain implementatations of this feature
 454  
      * would require adminstrative level access to the authenticating
 455  
      * server / program.
 456  
      *
 457  
      * @param user an User to change password for.
 458  
      * @param password the new password.
 459  
      * @exception UnknownEntityException if the user's record does not
 460  
      *            exist in the database.
 461  
      * @exception DataBackendException Error accessing the data backend.
 462  
      */
 463  
     public void forcePassword(User user, String password)
 464  
             throws UnknownEntityException, DataBackendException
 465  
     {
 466  0
         throw new DataBackendException(
 467  
                 "The method forcePassword has no implementation.");
 468  
     }
 469  
 
 470  
     /**
 471  
      * Creates new user account with specified attributes.
 472  
      *
 473  
      * @param user the object describing account to be created.
 474  
      * @param initialPassword Not used yet.
 475  
      * @throws DataBackendException Error accessing the data backend.
 476  
      * @throws EntityExistsException if the user account already exists.
 477  
      */
 478  
     public void createAccount(User user, String initialPassword)
 479  
             throws EntityExistsException, DataBackendException
 480  
     {
 481  0
         if (accountExists(user))
 482  
         {
 483  0
             throw new EntityExistsException("The account '"
 484  
                     + user.getName() + "' already exist");
 485  
         }
 486  
 
 487  
         try
 488  
         {
 489  0
             LDAPUser ldapUser = (LDAPUser) user;
 490  0
             Attributes attrs = ldapUser.getLDAPAttributes();
 491  0
             String name = ldapUser.getDN();
 492  
 
 493  0
             DirContext ctx = bindAsAdmin();
 494  
 
 495  0
             ctx.bind(name, null, attrs);
 496  
         }
 497  0
         catch (NamingException ex)
 498  
         {
 499  0
             throw new DataBackendException("NamingException caught", ex);
 500  0
         }
 501  0
     }
 502  
 
 503  
     /**
 504  
      * Removes an user account from the system.
 505  
      *
 506  
      * @param user the object describing the account to be removed.
 507  
      * @throws DataBackendException Error accessing the data backend.
 508  
      * @throws UnknownEntityException if the user account is not present.
 509  
      */
 510  
     public void removeAccount(User user)
 511  
             throws UnknownEntityException, DataBackendException
 512  
     {
 513  0
         if (!accountExists(user))
 514  
         {
 515  0
             throw new UnknownEntityException("The account '"
 516  
                     + user.getName() + "' does not exist");
 517  
         }
 518  
 
 519  
         try
 520  
         {
 521  0
             LDAPUser ldapUser = (LDAPUser) user;
 522  0
             String name = ldapUser.getDN();
 523  
 
 524  0
             DirContext ctx = bindAsAdmin();
 525  
 
 526  0
             ctx.unbind(name);
 527  
         }
 528  0
         catch (NamingException ex)
 529  
         {
 530  0
             throw new DataBackendException("NamingException caught", ex);
 531  0
         }
 532  0
     }
 533  
 
 534  
     /**
 535  
      * Bind as the admin user.
 536  
      *
 537  
      * @throws NamingException when an error occurs with the named server.
 538  
      * @return a new DirContext.
 539  
      */
 540  
     public static DirContext bindAsAdmin()
 541  
             throws NamingException
 542  
     {
 543  0
         String adminUser = LDAPSecurityConstants.getAdminUsername();
 544  0
         String adminPassword = LDAPSecurityConstants.getAdminPassword();
 545  
 
 546  0
         return bind(adminUser, adminPassword);
 547  
     }
 548  
 
 549  
     /**
 550  
      * Creates an initial context.
 551  
      *
 552  
      * @param username admin username supplied in TRP.
 553  
      * @param password admin password supplied in TRP
 554  
      * @throws NamingException when an error occurs with the named server.
 555  
      * @return a new DirContext.
 556  
      */
 557  
     public static DirContext bind(String username, String password)
 558  
             throws NamingException
 559  
     {
 560  0
         String host = LDAPSecurityConstants.getLDAPHost();
 561  0
         String port = LDAPSecurityConstants.getLDAPPort();
 562  0
         String providerURL = "ldap://" + host + ":" + port;
 563  0
         String ldapProvider = LDAPSecurityConstants.getLDAPProvider();
 564  0
         String authentication = LDAPSecurityConstants.getLDAPAuthentication();
 565  
 
 566  
         /*
 567  
          * creating an initial context using Sun's client
 568  
          * LDAP Provider.
 569  
          */
 570  0
         Hashtable env = new Hashtable();
 571  
 
 572  0
         env.put(Context.INITIAL_CONTEXT_FACTORY, ldapProvider);
 573  0
         env.put(Context.PROVIDER_URL, providerURL);
 574  0
         env.put(Context.SECURITY_AUTHENTICATION, authentication);
 575  0
         env.put(Context.SECURITY_PRINCIPAL, username);
 576  0
         env.put(Context.SECURITY_CREDENTIALS, password);
 577  
 
 578  0
         DirContext ctx = new javax.naming.directory.InitialDirContext(env);
 579  
 
 580  0
         return ctx;
 581  
     }
 582  
 
 583  
     /**
 584  
      * Create a new instance of the LDAP User according to the value
 585  
      * configured in TurbineResources.properties.
 586  
      * @return a new instance of the LDAP User.
 587  
      * @throws DataBackendException if there is an error creating the
 588  
      */
 589  
     private LDAPUser createLDAPUser()
 590  
             throws DataBackendException
 591  
     {
 592  
         try
 593  
         {
 594  0
             return (LDAPUser) TurbineSecurity.getUserInstance();
 595  
         }
 596  0
         catch (ClassCastException ex)
 597  
         {
 598  0
             throw new DataBackendException("ClassCastException:", ex);
 599  
         }
 600  0
         catch (UnknownEntityException ex)
 601  
         {
 602  0
             throw new DataBackendException("UnknownEntityException:", ex);
 603  
         }
 604  
     }
 605  
 
 606  
 }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.