1 package org
.argeo
.cms
.auth
;
3 import java
.io
.IOException
;
4 import java
.security
.PrivilegedAction
;
5 import java
.util
.ArrayList
;
6 import java
.util
.Arrays
;
8 import java
.util
.Locale
;
12 import javax
.naming
.ldap
.LdapName
;
13 import javax
.security
.auth
.Subject
;
14 import javax
.security
.auth
.callback
.Callback
;
15 import javax
.security
.auth
.callback
.CallbackHandler
;
16 import javax
.security
.auth
.callback
.LanguageCallback
;
17 import javax
.security
.auth
.callback
.NameCallback
;
18 import javax
.security
.auth
.callback
.PasswordCallback
;
19 import javax
.security
.auth
.callback
.UnsupportedCallbackException
;
20 import javax
.security
.auth
.kerberos
.KerberosPrincipal
;
21 import javax
.security
.auth
.login
.CredentialNotFoundException
;
22 import javax
.security
.auth
.login
.FailedLoginException
;
23 import javax
.security
.auth
.login
.LoginException
;
24 import javax
.security
.auth
.spi
.LoginModule
;
25 import javax
.servlet
.http
.HttpServletRequest
;
27 import org
.apache
.commons
.logging
.Log
;
28 import org
.apache
.commons
.logging
.LogFactory
;
29 import org
.argeo
.cms
.CmsException
;
30 import org
.argeo
.eclipse
.ui
.specific
.UiContext
;
31 import org
.argeo
.naming
.LdapAttrs
;
32 import org
.argeo
.osgi
.useradmin
.IpaUtils
;
33 import org
.osgi
.framework
.BundleContext
;
34 import org
.osgi
.framework
.FrameworkUtil
;
35 import org
.osgi
.service
.useradmin
.Authorization
;
36 import org
.osgi
.service
.useradmin
.User
;
37 import org
.osgi
.service
.useradmin
.UserAdmin
;
39 public class UserAdminLoginModule
implements LoginModule
{
40 private final static Log log
= LogFactory
.getLog(UserAdminLoginModule
.class);
42 private Subject subject
;
43 private CallbackHandler callbackHandler
;
44 private Map
<String
, Object
> sharedState
= null;
46 // private boolean isAnonymous = false;
47 private List
<String
> indexedUserProperties
= Arrays
48 .asList(new String
[] { LdapAttrs
.uid
.name(), LdapAttrs
.mail
.name(), LdapAttrs
.cn
.name() });
51 private BundleContext bc
;
52 // private Authorization authorization;
53 private User authenticatedUser
= null;
55 @SuppressWarnings("unchecked")
57 public void initialize(Subject subject
, CallbackHandler callbackHandler
, Map
<String
, ?
> sharedState
,
58 Map
<String
, ?
> options
) {
59 this.subject
= subject
;
61 bc
= FrameworkUtil
.getBundle(UserAdminLoginModule
.class).getBundleContext();
63 // this.subject = subject;
64 this.callbackHandler
= callbackHandler
;
65 this.sharedState
= (Map
<String
, Object
>) sharedState
;
66 // if (options.containsKey("anonymous"))
68 // Boolean.parseBoolean(options.get("anonymous").toString());
69 } catch (Exception e
) {
70 throw new CmsException("Cannot initialize login module", e
);
75 public boolean login() throws LoginException
{
76 Authorization sharedAuth
= (Authorization
) sharedState
.get(CmsAuthUtils
.SHARED_STATE_AUTHORIZATION
);
77 if (sharedAuth
!= null) {
78 if (callbackHandler
== null && sharedAuth
.getName() != null)
79 throw new LoginException("Shared authorization should be anonymous");
82 UserAdmin userAdmin
= bc
.getService(bc
.getServiceReference(UserAdmin
.class));
83 if (callbackHandler
== null) {// anonymous
84 // authorization = userAdmin.getAuthorization(null);
85 // sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION,
90 final String username
;
91 final char[] password
;
92 if (sharedState
.containsKey(CmsAuthUtils
.SHARED_STATE_NAME
)
93 && sharedState
.containsKey(CmsAuthUtils
.SHARED_STATE_PWD
)) {
94 username
= (String
) sharedState
.get(CmsAuthUtils
.SHARED_STATE_NAME
);
95 password
= (char[]) sharedState
.get(CmsAuthUtils
.SHARED_STATE_PWD
);
97 // // NB: raw user name is used
98 // AuthenticatingUser authenticatingUser = new
99 // AuthenticatingUser(username, password);
100 // authorization = userAdmin.getAuthorization(authenticatingUser);
102 // ask for username and password
103 NameCallback nameCallback
= new NameCallback("User");
104 PasswordCallback passwordCallback
= new PasswordCallback("Password", false);
105 LanguageCallback langCallback
= new LanguageCallback();
107 callbackHandler
.handle(new Callback
[] { nameCallback
, passwordCallback
, langCallback
});
108 } catch (IOException e
) {
109 throw new LoginException("Cannot handle callback: " + e
.getMessage());
110 } catch (UnsupportedCallbackException e
) {
115 Locale locale
= langCallback
.getLocale();
117 locale
= Locale
.getDefault();
118 UiContext
.setLocale(locale
);
120 username
= nameCallback
.getName();
121 if (username
== null || username
.trim().equals("")) {
122 // authorization = userAdmin.getAuthorization(null);
123 throw new CredentialNotFoundException("No credentials provided");
125 if (passwordCallback
.getPassword() != null)
126 password
= passwordCallback
.getPassword();
128 throw new CredentialNotFoundException("No credentials provided");
129 // FIXME move Argeo specific convention from user admin to here
132 // User user = userAdmin.getUser(null, username);
133 User user
= searchForUser(userAdmin
, username
);
135 return true;// expect Kerberos
136 // throw new FailedLoginException("Invalid credentials");
137 if (!user
.hasCredential(null, password
))
138 throw new FailedLoginException("Invalid credentials");
139 authenticatedUser
= user
;
142 // authorization = userAdmin.getAuthorization(user);
143 // assert authorization != null;
145 // sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION,
151 public boolean commit() throws LoginException
{
152 // if (authorization == null) {
154 // // throw new LoginException("Authorization should not be null");
156 // CmsAuthUtils.addAuthentication(subject, authorization);
159 UserAdmin userAdmin
= bc
.getService(bc
.getServiceReference(UserAdmin
.class));
160 Authorization authorization
;
161 if (callbackHandler
== null) {// anonymous
162 authorization
= userAdmin
.getAuthorization(null);
164 User authenticatingUser
;
165 Set
<KerberosPrincipal
> kerberosPrincipals
= subject
.getPrincipals(KerberosPrincipal
.class);
166 if (kerberosPrincipals
.isEmpty()) {
167 if (authenticatedUser
== null) {
168 if(log
.isTraceEnabled())
169 log
.trace("Neither kerberos nor user admin login succeeded. Login failed.");
172 authenticatingUser
= authenticatedUser
;
175 KerberosPrincipal kerberosPrincipal
= kerberosPrincipals
.iterator().next();
176 LdapName dn
= IpaUtils
.kerberosToDn(kerberosPrincipal
.getName());
177 authenticatingUser
= new AuthenticatingUser(dn
);
178 if (authenticatedUser
!= null && !authenticatingUser
.getName().equals(authenticatedUser
.getName()))
179 throw new LoginException("Kerberos login " + authenticatingUser
.getName()
180 + " is inconsistent with user admin login " + authenticatedUser
.getName());
182 authorization
= Subject
.doAs(subject
, new PrivilegedAction
<Authorization
>() {
185 public Authorization
run() {
186 Authorization authorization
= userAdmin
.getAuthorization(authenticatingUser
);
187 return authorization
;
191 if (authorization
== null)
192 throw new LoginException("User admin found no authorization for authenticated user "+authenticatingUser
.getName());
194 // Log and monitor new login
195 CmsAuthUtils
.addAuthorization(subject
, authorization
, (HttpServletRequest
) sharedState
.get(CmsAuthUtils
.SHARED_STATE_HTTP_REQUEST
));
196 // HttpServletRequest request = (HttpServletRequest) sharedState.get(CmsAuthUtils.SHARED_STATE_HTTP_REQUEST);
197 // if (request != null) {
198 // CmsAuthUtils.registerSessionAuthorization(bc, request, subject, authorization);
200 if (log
.isDebugEnabled())
201 log
.debug("Logged in to CMS: " + subject
);
206 public boolean abort() throws LoginException
{
207 // authorization = null;
212 public boolean logout() throws LoginException
{
213 if (log
.isDebugEnabled())
214 log
.debug("Logging out from CMS... " + subject
);
215 CmsAuthUtils
.cleanUp(subject
);
219 protected User
searchForUser(UserAdmin userAdmin
, String providedUsername
) {
221 // TODO check value null or empty
222 List
<User
> collectedUsers
= new ArrayList
<User
>();
226 user
= (User
) userAdmin
.getRole(providedUsername
);
228 collectedUsers
.add(user
);
229 } catch (Exception e
) {
233 for (String attr
: indexedUserProperties
) {
234 user
= userAdmin
.getUser(attr
, providedUsername
);
236 collectedUsers
.add(user
);
238 if (collectedUsers
.size() == 1)
239 return collectedUsers
.get(0);
240 else if (collectedUsers
.size() > 1)
241 log
.warn(collectedUsers
.size() + " users for provided username" + providedUsername
);
243 } catch (Exception e
) {
244 if (log
.isTraceEnabled())
245 log
.warn("Cannot search for user " + providedUsername
, e
);