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.security.MgnlUser;
37 import info.magnolia.cms.security.MgnlUserManager;
38 import info.magnolia.cms.security.SecuritySupport;
39 import info.magnolia.cms.security.User;
40 import info.magnolia.cms.security.UserManager;
41 import info.magnolia.jaas.sp.AbstractLoginModule;
42 import info.magnolia.jaas.sp.UserAwareLoginModule;
43
44 import java.io.Serializable;
45 import java.util.Calendar;
46 import java.util.GregorianCalendar;
47 import java.util.TimeZone;
48
49 import javax.security.auth.login.AccountLockedException;
50 import javax.security.auth.login.AccountNotFoundException;
51 import javax.security.auth.login.FailedLoginException;
52 import javax.security.auth.login.LoginException;
53
54 import org.apache.commons.lang.StringUtils;
55 import org.apache.jackrabbit.value.ValueFactoryImpl;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59
60
61
62
63 public class JCRAuthenticationModule extends AbstractLoginModule implements UserAwareLoginModule, Serializable {
64
65 private static final Logger log = LoggerFactory.getLogger(JCRAuthenticationModule.class);
66 protected User user;
67
68
69
70
71 public int getMaxAttempts() {
72 String realm;
73 if (this.user instanceof MgnlUser) {
74 realm = ((MgnlUser) user).getRealm();
75
76 } else {
77 return 0;
78 }
79 MgnlUserManager manager = (MgnlUserManager) SecuritySupport.Factory.getInstance().getUserManager(realm);
80 return manager.getMaxFailedLoginAttempts();
81 }
82
83
84
85
86 public long getTimeLock(){
87 String realm;
88 if (this.user instanceof MgnlUser) {
89 realm = ((MgnlUser) user).getRealm();
90 } else {
91
92 return 0;
93 }
94 MgnlUserManager manager = (MgnlUserManager) SecuritySupport.Factory.getInstance().getUserManager(realm);
95 return manager.getLockTimePeriod();
96 }
97
98
99
100
101
102
103
104 @Override
105 public void validateUser() throws LoginException {
106 initUser();
107
108 if (this.user == null) {
109 throw new AccountNotFoundException("User account " + this.name + " not found.");
110 }
111
112 if (!this.user.isEnabled()) {
113 throw new AccountLockedException("User account " + this.name + " is locked.");
114 }
115
116 matchPassword();
117
118 if (!UserManager.ANONYMOUS_USER.equals(user.getName())) {
119
120 getUserManager().updateLastAccessTimestamp(user);
121 }
122 }
123
124 private UserManager getUserManager() {
125
126 log.debug("getting user manager for realm " + realm.getName());
127 return SecuritySupport.Factory.getInstance().getUserManager(realm.getName());
128 }
129
130
131
132 protected void initUser() throws LoginException {
133 log.debug("initializing user {}", name);
134
135 long start = System.currentTimeMillis();
136 this.user = getUserManager().getUser(name);
137 log.debug("initialized user {} in {}ms", name, (System.currentTimeMillis() - start));
138 }
139
140 protected void matchPassword() throws LoginException {
141 if(getMaxAttempts() > 0 && !UserManager.ANONYMOUS_USER.equals(user.getName()) && getTimeLock() > 0){
142
143 Calendar currentTime = new GregorianCalendar(TimeZone.getDefault());
144 Calendar lockTime = new GregorianCalendar(TimeZone.getDefault());
145 MgnlUser mgnlUser = (MgnlUser) user;
146 if(mgnlUser.getReleaseTime() != null){
147 lockTime.clear();
148 lockTime.setTime(mgnlUser.getReleaseTime().getTime());
149 }
150 if(lockTime.after(currentTime) && mgnlUser.getReleaseTime() != null){
151 throw new LoginException("User account " + this.name + " is locked until " + mgnlUser.getReleaseTime().getTime() + ".");
152 }
153 }
154 String serverPassword = user.getPassword();
155
156 if (StringUtils.isEmpty(serverPassword)) {
157 throw new FailedLoginException("we do not allow users with no password");
158 }
159
160 if (!StringUtils.equals(serverPassword, new String(this.pswd))) {
161 if (getMaxAttempts() > 0 && !UserManager.ANONYMOUS_USER.equals(user.getName())){
162
163 UserManager userManager = getUserManager();
164 MgnlUser mgnlUser = (MgnlUser) user;
165 userManager.setProperty(mgnlUser, "failedLoginAttempts", ValueFactoryImpl.getInstance().createValue((mgnlUser.getFailedLoginAttempts() + 1)));
166
167
168 if (mgnlUser.getFailedLoginAttempts() >= getMaxAttempts() && getTimeLock() <= 0){
169 userManager.setProperty(mgnlUser, "enabled", ValueFactoryImpl.getInstance().createValue(false));
170 userManager.setProperty(mgnlUser, "failedLoginAttempts", ValueFactoryImpl.getInstance().createValue(0));
171 log.warn("Account " + this.name + " was locked due to high number of failed login attempts.");
172
173
174 }else if (mgnlUser.getFailedLoginAttempts() >= getMaxAttempts() && getTimeLock() > 0){
175 userManager.setProperty(mgnlUser, "failedLoginAttempts", ValueFactoryImpl.getInstance().createValue(0));
176 Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
177 calendar.add(Calendar.MINUTE, (int)getTimeLock());
178 userManager.setProperty(mgnlUser, "releaseTime", ValueFactoryImpl.getInstance().createValue(calendar));
179 log.warn("Account " + this.name + " was locked for " + getTimeLock() + " minute(s) due to high number of failed login attempts.");
180 }
181 throw new FailedLoginException("passwords do not match");
182 }
183 if(user instanceof MgnlUser){
184 MgnlUser mgnlUser = (MgnlUser) user;
185 UserManager userManager = getUserManager();
186 if (getMaxAttempts() > 0 && !UserManager.ANONYMOUS_USER.equals(mgnlUser.getName()) && mgnlUser.getFailedLoginAttempts() > 0){
187 userManager.setProperty(mgnlUser, "failedLoginAttempts", ValueFactoryImpl.getInstance().createValue(0));
188 }
189 }
190 }
191 }
192
193
194
195
196 @Override
197 public void setEntity() {
198
199 this.subject.getPrincipals().add(this.user);
200 this.subject.getPrincipals().add(this.realm);
201
202 collectGroupNames();
203 collectRoleNames();
204 }
205
206
207
208
209 @Override
210 public void setACL() {
211 }
212
213
214
215
216 public void collectRoleNames() {
217 for (String role : this.user.getAllRoles()) {
218 addRoleName(role);
219 }
220 }
221
222
223
224
225 public void collectGroupNames() {
226 for (String group : this.user.getAllGroups()) {
227 addGroupName(group);
228 }
229 }
230
231 @Override
232 public User getUser() {
233 return user;
234 }
235 }