jdk/src/jdk.security.auth/share/classes/com/sun/security/auth/module/JndiLoginModule.java
changeset 30044 bab15bbe2ca3
parent 25859 3317bb8137f4
child 31538 0981099a3e54
equal deleted inserted replaced
30043:b0dd05ec3db1 30044:bab15bbe2ca3
    42 import com.sun.security.auth.UnixNumericUserPrincipal;
    42 import com.sun.security.auth.UnixNumericUserPrincipal;
    43 import com.sun.security.auth.UnixNumericGroupPrincipal;
    43 import com.sun.security.auth.UnixNumericGroupPrincipal;
    44 
    44 
    45 
    45 
    46 /**
    46 /**
    47  * <p> The module prompts for a username and password
    47  * The module prompts for a username and password
    48  * and then verifies the password against the password stored in
    48  * and then verifies the password against the password stored in
    49  * a directory service configured under JNDI.
    49  * a directory service configured under JNDI.
    50  *
    50  *
    51  * <p> This <code>LoginModule</code> interoperates with
    51  * <p> This {@code LoginModule} interoperates with
    52  * any conformant JNDI service provider.  To direct this
    52  * any conformant JNDI service provider.  To direct this
    53  * <code>LoginModule</code> to use a specific JNDI service provider,
    53  * {@code LoginModule} to use a specific JNDI service provider,
    54  * two options must be specified in the login <code>Configuration</code>
    54  * two options must be specified in the login {@code Configuration}
    55  * for this <code>LoginModule</code>.
    55  * for this {@code LoginModule}.
    56  * <pre>
    56  * <pre>
    57  *      user.provider.url=<b>name_service_url</b>
    57  *      user.provider.url=<b>name_service_url</b>
    58  *      group.provider.url=<b>name_service_url</b>
    58  *      group.provider.url=<b>name_service_url</b>
    59  * </pre>
    59  * </pre>
    60  *
    60  *
    61  * <b>name_service_url</b> specifies
    61  * <b>name_service_url</b> specifies
    62  * the directory service and path where this <code>LoginModule</code>
    62  * the directory service and path where this {@code LoginModule}
    63  * can access the relevant user and group information.  Because this
    63  * can access the relevant user and group information.  Because this
    64  * <code>LoginModule</code> only performs one-level searches to
    64  * {@code LoginModule} only performs one-level searches to
    65  * find the relevant user information, the <code>URL</code>
    65  * find the relevant user information, the {@code URL}
    66  * must point to a directory one level above where the user and group
    66  * must point to a directory one level above where the user and group
    67  * information is stored in the directory service.
    67  * information is stored in the directory service.
    68  * For example, to instruct this <code>LoginModule</code>
    68  * For example, to instruct this {@code LoginModule}
    69  * to contact a NIS server, the following URLs must be specified:
    69  * to contact a NIS server, the following URLs must be specified:
    70  * <pre>
    70  * <pre>
    71  *    user.provider.url="nis://<b>NISServerHostName</b>/<b>NISDomain</b>/user"
    71  *    user.provider.url="nis://<b>NISServerHostName</b>/<b>NISDomain</b>/user"
    72  *    group.provider.url="nis://<b>NISServerHostName</b>/<b>NISDomain</b>/system/group"
    72  *    group.provider.url="nis://<b>NISServerHostName</b>/<b>NISDomain</b>/system/group"
    73  * </pre>
    73  * </pre>
    88  * (for example, <i>ou=People,o=Sun,c=US</i> and <i>ou=Groups,o=Sun,c=US</i>
    88  * (for example, <i>ou=People,o=Sun,c=US</i> and <i>ou=Groups,o=Sun,c=US</i>
    89  * for user and group information, respectively).
    89  * for user and group information, respectively).
    90  *
    90  *
    91  * <p> The format in which the user's information must be stored in
    91  * <p> The format in which the user's information must be stored in
    92  * the directory service is specified in RFC 2307.  Specifically,
    92  * the directory service is specified in RFC 2307.  Specifically,
    93  * this <code>LoginModule</code> will search for the user's entry in the
    93  * this {@code LoginModule} will search for the user's entry in the
    94  * directory service using the user's <i>uid</i> attribute,
    94  * directory service using the user's <i>uid</i> attribute,
    95  * where <i>uid=<b>username</b></i>.  If the search succeeds,
    95  * where <i>uid=<b>username</b></i>.  If the search succeeds,
    96  * this <code>LoginModule</code> will then
    96  * this {@code LoginModule} will then
    97  * obtain the user's encrypted password from the retrieved entry
    97  * obtain the user's encrypted password from the retrieved entry
    98  * using the <i>userPassword</i> attribute.
    98  * using the <i>userPassword</i> attribute.
    99  * This <code>LoginModule</code> assumes that the password is stored
    99  * This {@code LoginModule} assumes that the password is stored
   100  * as a byte array, which when converted to a <code>String</code>,
   100  * as a byte array, which when converted to a {@code String},
   101  * has the following format:
   101  * has the following format:
   102  * <pre>
   102  * <pre>
   103  *      "{crypt}<b>encrypted_password</b>"
   103  *      "{crypt}<b>encrypted_password</b>"
   104  * </pre>
   104  * </pre>
   105  *
   105  *
   106  * The LDAP directory server must be configured
   106  * The LDAP directory server must be configured
   107  * to permit read access to the userPassword attribute.
   107  * to permit read access to the userPassword attribute.
   108  * If the user entered a valid username and password,
   108  * If the user entered a valid username and password,
   109  * this <code>LoginModule</code> associates a
   109  * this {@code LoginModule} associates a
   110  * <code>UnixPrincipal</code>, <code>UnixNumericUserPrincipal</code>,
   110  * {@code UnixPrincipal}, {@code UnixNumericUserPrincipal},
   111  * and the relevant UnixNumericGroupPrincipals with the
   111  * and the relevant UnixNumericGroupPrincipals with the
   112  * <code>Subject</code>.
   112  * {@code Subject}.
   113  *
   113  *
   114  * <p> This LoginModule also recognizes the following <code>Configuration</code>
   114  * <p> This LoginModule also recognizes the following {@code Configuration}
   115  * options:
   115  * options:
   116  * <pre>
   116  * <pre>
   117  *    debug          if, true, debug messages are output to System.out.
   117  *    debug          if, true, debug messages are output to System.out.
   118  *
   118  *
   119  *    useFirstPass   if, true, this LoginModule retrieves the
   119  *    useFirstPass   if, true, this LoginModule retrieves the
   142  *                   "javax.security.auth.login.password" as the respective
   142  *                   "javax.security.auth.login.password" as the respective
   143  *                   keys.  This is not performed if existing values already
   143  *                   keys.  This is not performed if existing values already
   144  *                   exist for the username and password in the shared state,
   144  *                   exist for the username and password in the shared state,
   145  *                   or if authentication fails.
   145  *                   or if authentication fails.
   146  *
   146  *
   147  *    clearPass     if, true, this <code>LoginModule</code> clears the
   147  *    clearPass     if, true, this {@code LoginModule} clears the
   148  *                  username and password stored in the module's shared state
   148  *                  username and password stored in the module's shared state
   149  *                  after both phases of authentication (login and commit)
   149  *                  after both phases of authentication (login and commit)
   150  *                  have completed.
   150  *                  have completed.
   151  * </pre>
   151  * </pre>
   152  *
   152  *
   206     private static final String GROUP_ID = "gidNumber";
   206     private static final String GROUP_ID = "gidNumber";
   207     private static final String NAME = "javax.security.auth.login.name";
   207     private static final String NAME = "javax.security.auth.login.name";
   208     private static final String PWD = "javax.security.auth.login.password";
   208     private static final String PWD = "javax.security.auth.login.password";
   209 
   209 
   210     /**
   210     /**
   211      * Initialize this <code>LoginModule</code>.
   211      * Initialize this {@code LoginModule}.
   212      *
   212      *
   213      * <p>
   213      * @param subject the {@code Subject} to be authenticated.
   214      *
   214      *
   215      * @param subject the <code>Subject</code> to be authenticated. <p>
   215      * @param callbackHandler a {@code CallbackHandler} for communicating
   216      *
       
   217      * @param callbackHandler a <code>CallbackHandler</code> for communicating
       
   218      *                  with the end user (prompting for usernames and
   216      *                  with the end user (prompting for usernames and
   219      *                  passwords, for example). <p>
   217      *                  passwords, for example).
   220      *
   218      *
   221      * @param sharedState shared <code>LoginModule</code> state. <p>
   219      * @param sharedState shared {@code LoginModule} state.
   222      *
   220      *
   223      * @param options options specified in the login
   221      * @param options options specified in the login
   224      *                  <code>Configuration</code> for this particular
   222      *                  {@code Configuration} for this particular
   225      *                  <code>LoginModule</code>.
   223      *                  {@code LoginModule}.
   226      */
   224      */
   227     // Unchecked warning from (Map<String, Object>)sharedState is safe
   225     // Unchecked warning from (Map<String, Object>)sharedState is safe
   228     // since javax.security.auth.login.LoginContext passes a raw HashMap.
   226     // since javax.security.auth.login.LoginContext passes a raw HashMap.
   229     // Unchecked warnings from options.get(String) are safe since we are
   227     // Unchecked warnings from options.get(String) are safe since we are
   230     // passing known keys.
   228     // passing known keys.
   253         clearPass =
   251         clearPass =
   254                 "true".equalsIgnoreCase((String)options.get("clearPass"));
   252                 "true".equalsIgnoreCase((String)options.get("clearPass"));
   255     }
   253     }
   256 
   254 
   257     /**
   255     /**
   258      * <p> Prompt for username and password.
   256      * Prompt for username and password.
   259      * Verify the password against the relevant name service.
   257      * Verify the password against the relevant name service.
   260      *
   258      *
   261      * <p>
   259      * @return true always, since this {@code LoginModule}
   262      *
       
   263      * @return true always, since this <code>LoginModule</code>
       
   264      *          should not be ignored.
   260      *          should not be ignored.
   265      *
   261      *
   266      * @exception FailedLoginException if the authentication fails. <p>
   262      * @exception FailedLoginException if the authentication fails.
   267      *
   263      *
   268      * @exception LoginException if this <code>LoginModule</code>
   264      * @exception LoginException if this {@code LoginModule}
   269      *          is unable to perform the authentication.
   265      *          is unable to perform the authentication.
   270      */
   266      */
   271     public boolean login() throws LoginException {
   267     public boolean login() throws LoginException {
   272 
   268 
   273         if (userProvider == null) {
   269         if (userProvider == null) {
   365      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
   361      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
   366      * succeeded).
   362      * succeeded).
   367      *
   363      *
   368      * <p> If this LoginModule's own authentication attempt
   364      * <p> If this LoginModule's own authentication attempt
   369      * succeeded (checked by retrieving the private state saved by the
   365      * succeeded (checked by retrieving the private state saved by the
   370      * <code>login</code> method), then this method associates a
   366      * {@code login} method), then this method associates a
   371      * <code>UnixPrincipal</code>
   367      * {@code UnixPrincipal}
   372      * with the <code>Subject</code> located in the
   368      * with the {@code Subject} located in the
   373      * <code>LoginModule</code>.  If this LoginModule's own
   369      * {@code LoginModule}.  If this LoginModule's own
   374      * authentication attempted failed, then this method removes
   370      * authentication attempted failed, then this method removes
   375      * any state that was originally saved.
   371      * any state that was originally saved.
   376      *
       
   377      * <p>
       
   378      *
   372      *
   379      * @exception LoginException if the commit fails
   373      * @exception LoginException if the commit fails
   380      *
   374      *
   381      * @return true if this LoginModule's own login and commit
   375      * @return true if this LoginModule's own login and commit
   382      *          attempts succeeded, or false otherwise.
   376      *          attempts succeeded, or false otherwise.
   416         commitSucceeded = true;
   410         commitSucceeded = true;
   417         return true;
   411         return true;
   418     }
   412     }
   419 
   413 
   420     /**
   414     /**
   421      * <p> This method is called if the LoginContext's
   415      * This method is called if the LoginContext's
   422      * overall authentication failed.
   416      * overall authentication failed.
   423      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
   417      * (the relevant REQUIRED, REQUISITE, SUFFICIENT and OPTIONAL LoginModules
   424      * did not succeed).
   418      * did not succeed).
   425      *
   419      *
   426      * <p> If this LoginModule's own authentication attempt
   420      * <p> If this LoginModule's own authentication attempt
   427      * succeeded (checked by retrieving the private state saved by the
   421      * succeeded (checked by retrieving the private state saved by the
   428      * <code>login</code> and <code>commit</code> methods),
   422      * {@code login} and {@code commit} methods),
   429      * then this method cleans up any state that was originally saved.
   423      * then this method cleans up any state that was originally saved.
   430      *
       
   431      * <p>
       
   432      *
   424      *
   433      * @exception LoginException if the abort fails.
   425      * @exception LoginException if the abort fails.
   434      *
   426      *
   435      * @return false if this LoginModule's own login and/or commit attempts
   427      * @return false if this LoginModule's own login and/or commit attempts
   436      *          failed, and true otherwise.
   428      *          failed, and true otherwise.
   462 
   454 
   463     /**
   455     /**
   464      * Logout a user.
   456      * Logout a user.
   465      *
   457      *
   466      * <p> This method removes the Principals
   458      * <p> This method removes the Principals
   467      * that were added by the <code>commit</code> method.
   459      * that were added by the {@code commit} method.
   468      *
       
   469      * <p>
       
   470      *
   460      *
   471      * @exception LoginException if the logout fails.
   461      * @exception LoginException if the logout fails.
   472      *
   462      *
   473      * @return true in all cases since this <code>LoginModule</code>
   463      * @return true in all cases since this {@code LoginModule}
   474      *          should not be ignored.
   464      *          should not be ignored.
   475      */
   465      */
   476     public boolean logout() throws LoginException {
   466     public boolean logout() throws LoginException {
   477         if (subject.isReadOnly()) {
   467         if (subject.isReadOnly()) {
   478             cleanState();
   468             cleanState();
   503         return true;
   493         return true;
   504     }
   494     }
   505 
   495 
   506     /**
   496     /**
   507      * Attempt authentication
   497      * Attempt authentication
   508      *
       
   509      * <p>
       
   510      *
   498      *
   511      * @param getPasswdFromSharedState boolean that tells this method whether
   499      * @param getPasswdFromSharedState boolean that tells this method whether
   512      *          to retrieve the password from the sharedState.
   500      *          to retrieve the password from the sharedState.
   513      */
   501      */
   514     private void attemptAuthentication(boolean getPasswdFromSharedState)
   502     private void attemptAuthentication(boolean getPasswdFromSharedState)
   672      *
   660      *
   673      * <p> Also note that this method will set the username and password
   661      * <p> Also note that this method will set the username and password
   674      * values in the shared state in case subsequent LoginModules
   662      * values in the shared state in case subsequent LoginModules
   675      * want to use them via use/tryFirstPass.
   663      * want to use them via use/tryFirstPass.
   676      *
   664      *
   677      * <p>
       
   678      *
       
   679      * @param getPasswdFromSharedState boolean that tells this method whether
   665      * @param getPasswdFromSharedState boolean that tells this method whether
   680      *          to retrieve the password from the sharedState.
   666      *          to retrieve the password from the sharedState.
   681      */
   667      */
   682     private void getUsernamePassword(boolean getPasswdFromSharedState)
   668     private void getUsernamePassword(boolean getPasswdFromSharedState)
   683     throws LoginException {
   669     throws LoginException {