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