1   /*
2    * Copyright 2003 - 2013 The eFaps Team
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   *
16   * Revision:        $Rev$
17   * Last Changed:    $Date$
18   * Last Changed By: $Author$
19   */
20  
21  package org.efaps.jaas;
22  
23  import javax.security.auth.callback.Callback;
24  import javax.security.auth.callback.CallbackHandler;
25  import javax.security.auth.callback.NameCallback;
26  import javax.security.auth.callback.PasswordCallback;
27  import javax.security.auth.callback.TextOutputCallback;
28  import javax.security.auth.callback.UnsupportedCallbackException;
29  import javax.security.auth.login.LoginContext;
30  import javax.security.auth.login.LoginException;
31  
32  import org.slf4j.Logger;
33  import org.slf4j.LoggerFactory;
34  
35  /**
36   * This is class is used to handle the interface between JAAS and eFaps that
37   * enables a User to change his Password <br>
38   * To be able to change the Passwordx the name and password of the user method
39   * {@link #checkLogin} could be used to test if the user is allowed to login.
40   * The method returns then the related person to the given name and password (if
41   * found) or <i>null</i> (if not found)
42   *
43   * @author The eFaps Team
44   * @version $Id$
45   */
46  public class SetPasswordHandler
47  {
48      /**
49       * Logging instance used to give logging information of this class.
50       */
51      private static Logger LOG = LoggerFactory.getLogger(SetPasswordHandler.class);
52  
53      /**
54       * The name of the application used to create a new login context. The
55       * default value is <code>eFaps</code>.
56       */
57      private String application = "eFaps";
58  
59      /**
60       * Constructor to initialize the setpassword handler. If <i>null</i> is
61       * given to the application name, the default value defined in
62       * {@link #application} is used.
63       *
64       * @param _application  application name of the JAAS configuration
65       */
66      public SetPasswordHandler(final String _application)
67      {
68          if (_application != null) {
69              this.application = _application;
70          }
71      }
72  
73      /**
74       * Set the password.
75       * @param _name         Username
76       * @param _newpasswd    new passowrd
77       * @param _oldpasswd    old passowrd
78       * @return true if successful
79       * @throws LoginException on error
80       */
81      public boolean setPassword(final String _name,
82                                 final String _newpasswd,
83                                 final String _oldpasswd)
84          throws LoginException
85      {
86          boolean ret = false;
87  
88          final LoginContext login = new LoginContext(
89                  this.application,
90                  new SetPasswordCallbackHandler(ActionCallback.Mode.SET_PASSWORD, _name, _newpasswd, _oldpasswd));
91          login.login();
92          ret = true;
93          return ret;
94      }
95  
96      /**
97       * Callbackhandler.
98       */
99      protected class SetPasswordCallbackHandler
100         implements CallbackHandler
101     {
102         /**
103          * The user name to test is stored in this instance variable.
104          */
105         private final String name;
106 
107         /**
108          * The new password used from the user is stored in this instance variable.
109          */
110         private final String newpassword;
111 
112         /**
113          * The action mode for which the login must be made is stored in this
114          * instance variable (e.g. login, information about all persons, etc.)
115          */
116         private final ActionCallback.Mode mode;
117 
118         /**
119          * The old password used from the user is stored in this instance variable.
120          */
121         private final String oldpassword;
122 
123         /**
124          * Constructor initializing the action, name and password in this call back
125          * handler.
126          *
127          * @param _mode         defines mode for which the login is made
128          * @param _name         name of the login user
129          * @param _newpasswd    new password for the user
130          * @param _oldpasswd    old password
131          *                password of the login user
132          * @see #action
133          * @see #name
134          * @see #newpassword
135          */
136         protected SetPasswordCallbackHandler(final ActionCallback.Mode _mode,
137                                              final String _name,
138                                              final String _newpasswd,
139                                              final String _oldpasswd)
140         {
141             this.mode = _mode;
142             this.name = _name;
143             this.oldpassword = _oldpasswd;
144             this.newpassword = _newpasswd;
145         }
146 
147         /**
148          * hanlde the callbacks.
149          * @param _callbacks callbacks to be handled
150          * @throws UnsupportedCallbackException on error
151          */
152         public void handle(final Callback[] _callbacks)
153             throws UnsupportedCallbackException
154         {
155             for (int i = 0; i < _callbacks.length; i++) {
156                 if (_callbacks[i] instanceof ActionCallback) {
157                     final ActionCallback ac = (ActionCallback) _callbacks[i];
158                     ac.setMode(this.mode);
159                 } else if (_callbacks[i] instanceof NameCallback) {
160                     final NameCallback nc = (NameCallback) _callbacks[i];
161                     nc.setName(this.name);
162                 } else if (_callbacks[i] instanceof PasswordCallback) {
163                     final PasswordCallback pc = (PasswordCallback) _callbacks[i];
164                     if ("Password".equals(pc.getPrompt()) && this.oldpassword != null) {
165                         pc.setPassword(this.oldpassword.toCharArray());
166                     }
167                     if ("newPassword".equals(pc.getPrompt()) && this.newpassword != null) {
168                         pc.setPassword(this.newpassword.toCharArray());
169                     }
170                 } else if (_callbacks[i] instanceof TextOutputCallback) {
171                     SetPasswordHandler.LOG.debug("ignored handler: " + _callbacks[i]);
172                     // do nothing, TextOutputCallBack's are ignored!
173                 } else {
174                     throw new UnsupportedCallbackException(_callbacks[i], "Unrecognized Callback");
175                 }
176             }
177         }
178     }
179 }