]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/auth/NodeUserLoginModule.java
[maven-release-plugin] prepare for next development iteration
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / auth / NodeUserLoginModule.java
1 package org.argeo.cms.auth;
2
3 import java.security.Principal;
4 import java.util.Arrays;
5 import java.util.Collections;
6 import java.util.Iterator;
7 import java.util.List;
8 import java.util.Map;
9 import java.util.Set;
10
11 import javax.naming.InvalidNameException;
12 import javax.naming.ldap.LdapName;
13 import javax.security.auth.Subject;
14 import javax.security.auth.callback.CallbackHandler;
15 import javax.security.auth.login.FailedLoginException;
16 import javax.security.auth.login.LoginException;
17 import javax.security.auth.spi.LoginModule;
18 import javax.security.auth.x500.X500Principal;
19
20 import org.apache.jackrabbit.core.security.AnonymousPrincipal;
21 import org.apache.jackrabbit.core.security.SecurityConstants;
22 import org.apache.jackrabbit.core.security.principal.AdminPrincipal;
23 import org.argeo.cms.CmsException;
24 import org.argeo.cms.internal.auth.ImpliedByPrincipal;
25 import org.osgi.service.useradmin.Authorization;
26
27 public class NodeUserLoginModule implements LoginModule {
28 private Subject subject;
29
30 private final static LdapName ROLE_KERNEL_NAME, ROLE_ADMIN_NAME,
31 ROLE_ANONYMOUS_NAME, ROLE_USER_NAME;
32 private final static List<LdapName> RESERVED_ROLES;
33 private final static X500Principal ROLE_ANONYMOUS_PRINCIPAL;
34 static {
35 try {
36 ROLE_KERNEL_NAME = new LdapName(AuthConstants.ROLE_KERNEL);
37 ROLE_ADMIN_NAME = new LdapName(AuthConstants.ROLE_ADMIN);
38 ROLE_USER_NAME = new LdapName(AuthConstants.ROLE_USER);
39 ROLE_ANONYMOUS_NAME = new LdapName(AuthConstants.ROLE_ANONYMOUS);
40 RESERVED_ROLES = Collections.unmodifiableList(Arrays
41 .asList(new LdapName[] { ROLE_KERNEL_NAME, ROLE_ADMIN_NAME,
42 ROLE_ANONYMOUS_NAME, ROLE_USER_NAME,
43 new LdapName(AuthConstants.ROLE_GROUP_ADMIN),
44 new LdapName(AuthConstants.ROLE_USER_ADMIN) }));
45 ROLE_ANONYMOUS_PRINCIPAL = new X500Principal(
46 ROLE_ANONYMOUS_NAME.toString());
47 } catch (InvalidNameException e) {
48 throw new Error("Cannot initialize login module class", e);
49 }
50 }
51
52 private Authorization authorization;
53
54 @Override
55 public void initialize(Subject subject, CallbackHandler callbackHandler,
56 Map<String, ?> sharedState, Map<String, ?> options) {
57 this.subject = subject;
58 }
59
60 @Override
61 public boolean login() throws LoginException {
62 Iterator<Authorization> auth = subject.getPrivateCredentials(
63 Authorization.class).iterator();
64 if (!auth.hasNext())
65 throw new FailedLoginException("No authorization available");
66 authorization = auth.next();
67 return true;
68 }
69
70 @Override
71 public boolean commit() throws LoginException {
72 if (authorization == null)
73 throw new LoginException("Authorization should not be null");
74 Set<Principal> principals = subject.getPrincipals();
75 try {
76 String authName = authorization.getName();
77
78 // determine user's principal
79 final LdapName name;
80 final Principal userPrincipal;
81 if (authName == null) {
82 name = ROLE_ANONYMOUS_NAME;
83 userPrincipal = ROLE_ANONYMOUS_PRINCIPAL;
84 principals.add(userPrincipal);
85 principals.add(new AnonymousPrincipal());
86 } else {
87 name = new LdapName(authName);
88 checkUserName(name);
89 userPrincipal = new X500Principal(name.toString());
90 principals.add(userPrincipal);
91 principals.add(new ImpliedByPrincipal(ROLE_USER_NAME,
92 userPrincipal));
93 }
94
95 // Add roles provided by authorization
96 for (String role : authorization.getRoles()) {
97 LdapName roleName = new LdapName(role);
98 if (roleName.equals(name)) {
99 // skip
100 } else {
101 checkImpliedPrincipalName(roleName);
102 principals.add(new ImpliedByPrincipal(roleName.toString(),
103 userPrincipal));
104 if (roleName.equals(ROLE_ADMIN_NAME))
105 principals.add(new AdminPrincipal(
106 SecurityConstants.ADMIN_ID));
107 }
108 }
109
110 return true;
111 } catch (InvalidNameException e) {
112 throw new CmsException("Cannot commit", e);
113 }
114 }
115
116 @Override
117 public boolean abort() throws LoginException {
118 cleanUp();
119 return true;
120 }
121
122 @Override
123 public boolean logout() throws LoginException {
124 if (subject == null)
125 throw new LoginException("Subject should not be null");
126 // Argeo
127 subject.getPrincipals().removeAll(
128 subject.getPrincipals(X500Principal.class));
129 subject.getPrincipals().removeAll(
130 subject.getPrincipals(ImpliedByPrincipal.class));
131 // Jackrabbit
132 subject.getPrincipals().removeAll(
133 subject.getPrincipals(AdminPrincipal.class));
134 subject.getPrincipals().removeAll(
135 subject.getPrincipals(AnonymousPrincipal.class));
136 cleanUp();
137 return true;
138 }
139
140 private void cleanUp() {
141 subject = null;
142 authorization = null;
143 }
144
145 private void checkUserName(LdapName name) {
146 if (RESERVED_ROLES.contains(name))
147 throw new CmsException(name + " is a reserved name");
148 }
149
150 private void checkImpliedPrincipalName(LdapName roleName) {
151 if (ROLE_USER_NAME.equals(roleName)
152 || ROLE_ANONYMOUS_NAME.equals(roleName)
153 || ROLE_KERNEL_NAME.equals(roleName))
154 throw new CmsException(roleName + " cannot be listed as role");
155 }
156 }