1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.jaas.sp.jcr;
35
36 import info.magnolia.cms.beans.config.ContentRepository;
37 import info.magnolia.cms.security.PrincipalUtil;
38 import info.magnolia.cms.security.User;
39 import info.magnolia.cms.security.UserManager;
40 import info.magnolia.context.Context;
41 import info.magnolia.context.MgnlContext;
42 import info.magnolia.init.MagnoliaConfigurationProperties;
43 import info.magnolia.objectfactory.Components;
44
45 import java.io.IOException;
46 import java.io.Serializable;
47 import java.util.Arrays;
48 import java.util.Map;
49
50 import javax.security.auth.Subject;
51 import javax.security.auth.callback.Callback;
52 import javax.security.auth.callback.CallbackHandler;
53 import javax.security.auth.callback.NameCallback;
54 import javax.security.auth.callback.PasswordCallback;
55 import javax.security.auth.callback.UnsupportedCallbackException;
56 import javax.security.auth.login.FailedLoginException;
57 import javax.security.auth.login.LoginException;
58 import javax.security.auth.spi.LoginModule;
59
60 import org.apache.jackrabbit.core.security.UserPrincipal;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64
65
66
67
68
69
70 public class JackrabbitAuthenticationModule implements LoginModule, Serializable {
71
72 private static final Logger log = LoggerFactory.getLogger(JackrabbitAuthenticationModule.class);
73
74 private Subject subject;
75 private CallbackHandler callbackHandler;
76 private String name;
77
78 @Override
79 public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options) {
80 this.subject = subject;
81 this.callbackHandler = callbackHandler;
82 }
83
84 @Override
85 public boolean login() throws LoginException {
86
87 if (this.callbackHandler == null) {
88 throw new LoginException("Error: no CallbackHandler available");
89 }
90
91 Callback[] callbacks = new Callback[2];
92 callbacks[0] = new NameCallback("name");
93 callbacks[1] = new PasswordCallback("pswd", false);
94
95 char[] password;
96 try {
97 this.callbackHandler.handle(callbacks);
98 this.name = ((NameCallback) callbacks[0]).getName();
99 password = ((PasswordCallback) callbacks[1]).getPassword();
100 } catch (IOException ioe) {
101 throw new LoginException(ioe.toString());
102 } catch (UnsupportedCallbackException ce) {
103 throw new LoginException(ce.getCallback().toString() + " not available");
104 }
105
106
107
108
109
110
111 if (getAdminUser().equals(this.name)) {
112 if (!Arrays.equals(password, getAdminPassword().toCharArray())) {
113 throw new FailedLoginException();
114 }
115 compileAdminPrincipals();
116 return true;
117 }
118
119 Context context = MgnlContext.hasInstance() ? MgnlContext.getInstance() : null;
120 if (context == null) {
121 throw new FailedLoginException("Cannot login, magnolia context is not set");
122 }
123
124 Subject magnoliaSubject = context.getSubject();
125 if (magnoliaSubject == null) {
126 throw new FailedLoginException("Cannot login, invalid setup or deserialization error");
127 }
128
129 if (isSuperuser(magnoliaSubject)) {
130 compileAdminPrincipals();
131 return true;
132 }
133
134 compileUserPrincipals(magnoliaSubject);
135 return true;
136 }
137
138 @Override
139 public boolean commit() throws LoginException {
140 return true;
141 }
142
143 @Override
144 public boolean abort() throws LoginException {
145 return false;
146 }
147
148 @Override
149 public boolean logout() throws LoginException {
150 callbackHandler = null;
151 name = null;
152 return true;
153 }
154
155 private void compileUserPrincipals(Subject magnoliaSubject) {
156 subject.getPrincipals().addAll(magnoliaSubject.getPrincipals());
157 subject.getPrincipals().add(new UserPrincipal(name));
158 }
159
160 private void compileAdminPrincipals() {
161 this.subject.getPrincipals().add(new MagnoliaJRAdminPrincipal(getAdminUser()));
162 }
163
164 protected String getAdminUser() {
165 String user = ContentRepository.REPOSITORY_USER;
166 if (user == null) {
167 MagnoliaConfigurationProperties mcp = Components.getSingleton(MagnoliaConfigurationProperties.class);
168 user = mcp.getProperty("magnolia.connection.jcr.userId");
169 }
170 if (user == null) {
171 user = System.getProperty("magnolia.connection.jcr.userId");
172 }
173 return user;
174 }
175
176 protected String getAdminPassword() {
177 String user = ContentRepository.REPOSITORY_PSWD;
178 if (user == null) {
179 MagnoliaConfigurationProperties mcp = Components.getSingleton(MagnoliaConfigurationProperties.class);
180 user = mcp.getProperty("magnolia.connection.jcr.password");
181 }
182 if (user == null) {
183 user = System.getProperty("magnolia.connection.jcr.password");
184 }
185 return user;
186 }
187
188
189
190
191 private boolean isSuperuser(Subject magnoliaSubject) {
192 User user = PrincipalUtil.findPrincipal(magnoliaSubject, User.class);
193 return user != null && UserManager.SYSTEM_USER.equals(user.getName());
194 }
195 }