1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.security;
15
16 import java.io.IOException;
17 import java.util.HashSet;
18 import java.util.Map;
19 import java.util.Set;
20
21 import org.eclipse.jetty.http.PathMap;
22 import org.eclipse.jetty.http.security.Constraint;
23 import org.eclipse.jetty.server.Connector;
24 import org.eclipse.jetty.server.HttpConnection;
25 import org.eclipse.jetty.server.Request;
26 import org.eclipse.jetty.server.Response;
27 import org.eclipse.jetty.server.UserIdentity;
28 import org.eclipse.jetty.util.StringMap;
29
30
31
32
33
34
35
36
37 public class ConstraintSecurityHandler extends SecurityHandler implements ConstraintAware
38 {
39 private ConstraintMapping[] _constraintMappings;
40 private Set<String> _roles;
41 private PathMap _constraintMap = new PathMap();
42 private boolean _strict = true;
43
44
45
46
47
48
49 public boolean isStrict()
50 {
51 return _strict;
52 }
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public void setStrict(boolean strict)
69 {
70 _strict = strict;
71 }
72
73
74
75
76
77 public ConstraintMapping[] getConstraintMappings()
78 {
79 return _constraintMappings;
80 }
81
82
83 public Set<String> getRoles()
84 {
85 return _roles;
86 }
87
88
89
90
91
92
93
94
95
96
97 public void setConstraintMappings(ConstraintMapping[] constraintMappings)
98 {
99 setConstraintMappings(constraintMappings,null);
100 }
101
102
103
104
105
106
107
108
109
110
111 public void setConstraintMappings(ConstraintMapping[] constraintMappings, Set<String> roles)
112 {
113 if (isStarted())
114 throw new IllegalStateException("Started");
115 _constraintMappings = constraintMappings;
116
117 if (roles==null)
118 {
119 roles = new HashSet<String>();
120 for (ConstraintMapping cm : constraintMappings)
121 {
122 String[] cmr = cm.getConstraint().getRoles();
123 if (cmr!=null)
124 {
125 for (String r : cmr)
126 if (!"*".equals(r))
127 roles.add(r);
128 }
129 }
130 }
131
132 this._roles = roles;
133
134 }
135
136
137
138
139
140 @Override
141 protected void doStart() throws Exception
142 {
143 _constraintMap.clear();
144 if (_constraintMappings!=null)
145 {
146 for (ConstraintMapping mapping : _constraintMappings)
147 {
148 Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.get(mapping.getPathSpec());
149 if (mappings == null)
150 {
151 mappings = new StringMap();
152 _constraintMap.put(mapping.getPathSpec(),mappings);
153 }
154 RoleInfo allMethodsRoleInfo = mappings.get(null);
155 if (allMethodsRoleInfo != null && allMethodsRoleInfo.isForbidden())
156 {
157 continue;
158 }
159 String httpMethod = mapping.getMethod();
160 RoleInfo roleInfo = mappings.get(httpMethod);
161 if (roleInfo == null)
162 {
163 roleInfo = new RoleInfo();
164 mappings.put(httpMethod,roleInfo);
165 if (allMethodsRoleInfo != null)
166 {
167 roleInfo.combine(allMethodsRoleInfo);
168 }
169 }
170 if (roleInfo.isForbidden())
171 {
172 continue;
173 }
174 Constraint constraint = mapping.getConstraint();
175 boolean forbidden = constraint.isForbidden();
176 roleInfo.setForbidden(forbidden);
177 if (forbidden)
178 {
179 if (httpMethod == null)
180 {
181 mappings.clear();
182 mappings.put(null,roleInfo);
183 }
184 }
185 else
186 {
187 UserDataConstraint userDataConstraint = UserDataConstraint.get(constraint.getDataConstraint());
188 roleInfo.setUserDataConstraint(userDataConstraint);
189
190 boolean checked = constraint.getAuthenticate();
191 roleInfo.setChecked(checked);
192 if (roleInfo.isChecked())
193 {
194 if (constraint.isAnyRole())
195 {
196 if (_strict)
197 {
198
199 for (String role : _roles)
200 roleInfo.addRole(role);
201 }
202 else
203
204 roleInfo.setAnyRole(true);
205 }
206 else
207 {
208 String[] newRoles = constraint.getRoles();
209 for (String role : newRoles)
210 {
211 if (_strict &&!_roles.contains(role))
212 throw new IllegalArgumentException("Attempt to use undeclared role: " + role + ", known roles: " + _roles);
213 roleInfo.addRole(role);
214 }
215 }
216 }
217 if (httpMethod == null)
218 {
219 for (Map.Entry<String, RoleInfo> entry : mappings.entrySet())
220 {
221 if (entry.getKey() != null)
222 {
223 RoleInfo specific = entry.getValue();
224 specific.combine(roleInfo);
225 }
226 }
227 }
228 }
229 }
230 }
231 super.doStart();
232 }
233
234 protected Object prepareConstraintInfo(String pathInContext, Request request)
235 {
236 Map<String, RoleInfo> mappings = (Map<String, RoleInfo>)_constraintMap.match(pathInContext);
237
238 if (mappings != null)
239 {
240 String httpMethod = request.getMethod();
241 RoleInfo roleInfo = mappings.get(httpMethod);
242 if (roleInfo == null)
243 roleInfo = mappings.get(null);
244 return roleInfo;
245 }
246
247 return null;
248 }
249
250 protected boolean checkUserDataPermissions(String pathInContext, Request request, Response response, Object constraintInfo) throws IOException
251 {
252 if (constraintInfo == null)
253 return true;
254
255 RoleInfo roleInfo = (RoleInfo)constraintInfo;
256 if (roleInfo.isForbidden())
257 return false;
258
259
260 UserDataConstraint dataConstraint = roleInfo.getUserDataConstraint();
261 if (dataConstraint == null || dataConstraint == UserDataConstraint.None)
262 {
263 return true;
264 }
265 HttpConnection connection = HttpConnection.getCurrentConnection();
266 Connector connector = connection.getConnector();
267
268 if (dataConstraint == UserDataConstraint.Integral)
269 {
270 if (connector.isIntegral(request))
271 return true;
272 if (connector.getConfidentialPort() > 0)
273 {
274 String url = connector.getIntegralScheme() + "://" + request.getServerName() + ":" + connector.getIntegralPort() + request.getRequestURI();
275 if (request.getQueryString() != null)
276 url += "?" + request.getQueryString();
277 response.setContentLength(0);
278 response.sendRedirect(url);
279 }
280 else
281 response.sendError(Response.SC_FORBIDDEN,"!Integral");
282
283 request.setHandled(true);
284 return false;
285 }
286 else if (dataConstraint == UserDataConstraint.Confidential)
287 {
288 if (connector.isConfidential(request))
289 return true;
290
291 if (connector.getConfidentialPort() > 0)
292 {
293 String url = connector.getConfidentialScheme() + "://" + request.getServerName() + ":" + connector.getConfidentialPort()
294 + request.getRequestURI();
295 if (request.getQueryString() != null)
296 url += "?" + request.getQueryString();
297
298 response.setContentLength(0);
299 response.sendRedirect(url);
300 }
301 else
302 response.sendError(Response.SC_FORBIDDEN,"!Confidential");
303
304 request.setHandled(true);
305 return false;
306 }
307 else
308 {
309 throw new IllegalArgumentException("Invalid dataConstraint value: " + dataConstraint);
310 }
311
312 }
313
314 protected boolean isAuthMandatory(Request baseRequest, Response base_response, Object constraintInfo)
315 {
316 if (constraintInfo == null)
317 {
318 return false;
319 }
320 return ((RoleInfo)constraintInfo).isChecked();
321 }
322
323 protected boolean checkWebResourcePermissions(String pathInContext, Request request, Response response, Object constraintInfo, UserIdentity userIdentity)
324 throws IOException
325 {
326 if (constraintInfo == null)
327 {
328 return true;
329 }
330 RoleInfo roleInfo = (RoleInfo)constraintInfo;
331
332 if (!roleInfo.isChecked())
333 {
334 return true;
335 }
336
337 if (roleInfo.isAnyRole() && request.getAuthType()!=null)
338 return true;
339
340 String[] roles = roleInfo.getRoles();
341 for (String role : roles)
342 {
343 if (userIdentity.isUserInRole(role, null))
344 return true;
345 }
346 return false;
347 }
348
349
350 protected void dump(StringBuilder b,String indent)
351 {
352 super.dump(b,indent);
353 b.append(indent).append(" +=roles=").append(_roles).append('\n');
354
355 for (Object path : _constraintMap.keySet())
356 {
357 Object constraint = _constraintMap.get(path);
358 b.append(indent).append(" +=").append(path).append('=').append(constraint).append('\n');
359 }
360 }
361 }