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 }