1 package org
.argeo
.cms
.internal
.auth
;
3 import java
.security
.Principal
;
4 import java
.util
.Arrays
;
5 import java
.util
.Collections
;
10 import javax
.naming
.InvalidNameException
;
11 import javax
.naming
.ldap
.LdapName
;
12 import javax
.security
.auth
.Subject
;
13 import javax
.security
.auth
.callback
.Callback
;
14 import javax
.security
.auth
.callback
.CallbackHandler
;
15 import javax
.security
.auth
.callback
.NameCallback
;
16 import javax
.security
.auth
.callback
.PasswordCallback
;
17 import javax
.security
.auth
.login
.CredentialNotFoundException
;
18 import javax
.security
.auth
.login
.LoginException
;
19 import javax
.security
.auth
.spi
.LoginModule
;
20 import javax
.security
.auth
.x500
.X500Principal
;
22 import org
.apache
.jackrabbit
.core
.security
.AnonymousPrincipal
;
23 import org
.apache
.jackrabbit
.core
.security
.SecurityConstants
;
24 import org
.apache
.jackrabbit
.core
.security
.principal
.AdminPrincipal
;
25 import org
.argeo
.cms
.CmsException
;
26 import org
.argeo
.cms
.KernelHeader
;
27 import org
.argeo
.cms
.internal
.kernel
.Activator
;
28 import org
.osgi
.framework
.BundleContext
;
29 import org
.osgi
.service
.useradmin
.Authorization
;
30 import org
.osgi
.service
.useradmin
.User
;
31 import org
.osgi
.service
.useradmin
.UserAdmin
;
33 public class UserAdminLoginModule
implements LoginModule
{
34 private Subject subject
;
35 private CallbackHandler callbackHandler
;
36 private boolean isAnonymous
= false;
38 private final static LdapName ROLE_KERNEL_NAME
, ROLE_ADMIN_NAME
,
39 ROLE_ANONYMOUS_NAME
, ROLE_USER_NAME
;
40 private final static List
<LdapName
> RESERVED_ROLES
;
41 private final static X500Principal ROLE_ANONYMOUS_PRINCIPAL
;
44 ROLE_KERNEL_NAME
= new LdapName(KernelHeader
.ROLE_KERNEL
);
45 ROLE_ADMIN_NAME
= new LdapName(KernelHeader
.ROLE_ADMIN
);
46 ROLE_USER_NAME
= new LdapName(KernelHeader
.ROLE_USER
);
47 ROLE_ANONYMOUS_NAME
= new LdapName(KernelHeader
.ROLE_ANONYMOUS
);
48 RESERVED_ROLES
= Collections
.unmodifiableList(Arrays
49 .asList(new LdapName
[] { ROLE_KERNEL_NAME
, ROLE_ADMIN_NAME
,
50 ROLE_ANONYMOUS_NAME
, ROLE_USER_NAME
,
51 new LdapName(KernelHeader
.ROLE_GROUP_ADMIN
),
52 new LdapName(KernelHeader
.ROLE_USER_ADMIN
) }));
53 ROLE_ANONYMOUS_PRINCIPAL
= new X500Principal(
54 ROLE_ANONYMOUS_NAME
.toString());
55 } catch (InvalidNameException e
) {
56 throw new Error("Cannot initialize login module class", e
);
60 private Authorization authorization
;
63 public void initialize(Subject subject
, CallbackHandler callbackHandler
,
64 Map
<String
, ?
> sharedState
, Map
<String
, ?
> options
) {
66 this.subject
= subject
;
67 this.callbackHandler
= callbackHandler
;
68 if (options
.containsKey("anonymous"))
69 isAnonymous
= Boolean
.parseBoolean(options
.get("anonymous")
71 // String ldifFile = options.get("ldifFile").toString();
72 // InputStream in = new URL(ldifFile).openStream();
73 // userAdmin = new LdifUserAdmin(in);
74 } catch (Exception e
) {
75 throw new CmsException("Cannot initialize login module", e
);
80 public boolean login() throws LoginException
{
81 // TODO use a callback in order to get the bundle context
82 BundleContext bc
= Activator
.getBundleContext();
83 UserAdmin userAdmin
= bc
.getService(bc
84 .getServiceReference(UserAdmin
.class));
88 // ask for username and password
89 NameCallback nameCallback
= new NameCallback("User");
90 PasswordCallback passwordCallback
= new PasswordCallback(
94 callbackHandler
.handle(new Callback
[] { nameCallback
,
96 } catch (Exception e
) {
97 throw new CmsException("Cannot handle callbacks", e
);
100 // create credentials
101 final String username
= nameCallback
.getName();
102 if (username
== null || username
.trim().equals(""))
103 throw new CredentialNotFoundException("No credentials provided");
105 char[] password
= {};
106 if (passwordCallback
.getPassword() != null)
107 password
= passwordCallback
.getPassword();
109 throw new CredentialNotFoundException("No credentials provided");
111 user
= userAdmin
.getUser(null, username
);
114 if (!user
.hasCredential(null, password
))
119 this.authorization
= userAdmin
.getAuthorization(user
);
124 public boolean commit() throws LoginException
{
125 if (authorization
!= null) {
126 Set
<Principal
> principals
= subject
.getPrincipals();
128 String authName
= authorization
.getName();
130 // determine user's principal
132 final Principal userPrincipal
;
133 if (authName
== null) {
134 name
= ROLE_ANONYMOUS_NAME
;
135 userPrincipal
= ROLE_ANONYMOUS_PRINCIPAL
;
136 principals
.add(userPrincipal
);
137 principals
.add(new AnonymousPrincipal());
139 name
= new LdapName(authName
);
141 userPrincipal
= new X500Principal(name
.toString());
142 principals
.add(userPrincipal
);
143 principals
.add(new ImpliedByPrincipal(ROLE_USER_NAME
,
147 // Add roles provided by authorization
148 for (String role
: authorization
.getRoles()) {
149 LdapName roleName
= new LdapName(role
);
150 if (roleName
.equals(name
)) {
153 checkImpliedPrincipalName(roleName
);
154 principals
.add(new ImpliedByPrincipal(roleName
155 .toString(), userPrincipal
));
156 if (roleName
.equals(ROLE_ADMIN_NAME
))
157 principals
.add(new AdminPrincipal(
158 SecurityConstants
.ADMIN_ID
));
163 } catch (InvalidNameException e
) {
164 throw new CmsException("Cannot commit", e
);
171 public boolean abort() throws LoginException
{
177 public boolean logout() throws LoginException
{
178 // TODO better deal with successive logout
181 // TODO make it less brutal
182 subject
.getPrincipals().removeAll(
183 subject
.getPrincipals(X500Principal
.class));
184 subject
.getPrincipals().removeAll(
185 subject
.getPrincipals(ImpliedByPrincipal
.class));
190 private void cleanUp() {
192 authorization
= null;
195 private void checkUserName(LdapName name
) {
196 if (RESERVED_ROLES
.contains(name
))
197 throw new CmsException(name
+ " is a reserved name");
200 private void checkImpliedPrincipalName(LdapName roleName
) {
201 if (ROLE_USER_NAME
.equals(roleName
)
202 || ROLE_ANONYMOUS_NAME
.equals(roleName
)
203 || ROLE_KERNEL_NAME
.equals(roleName
))
204 throw new CmsException(roleName
+ " cannot be listed as role");