1 16 package org.mortbay.http; 17 18 import java.io.IOException ; 19 import java.io.Serializable ; 20 import java.security.Principal ; 21 import java.util.Collections ; 22 import java.util.List ; 23 24 import org.apache.commons.logging.Log; 25 import org.mortbay.log.LogFactory; 26 import org.mortbay.jetty.servlet.FormAuthenticator; 27 import org.mortbay.util.LazyList; 28 29 30 35 public class SecurityConstraint implements Cloneable , Serializable 36 { 37 private static Log log= LogFactory.getLog(SecurityConstraint.class); 38 39 40 public final static String __BASIC_AUTH= "BASIC"; 41 public final static String __FORM_AUTH= "FORM"; 42 public final static String __DIGEST_AUTH= "DIGEST"; 43 public final static String __CERT_AUTH= "CLIENT_CERT"; 44 public final static String __CERT_AUTH2= "CLIENT-CERT"; 45 46 47 public final static int DC_UNSET= -1, DC_NONE= 0, DC_INTEGRAL= 1, DC_CONFIDENTIAL= 2; 48 49 50 public final static String NONE= "NONE"; 51 public final static String ANY_ROLE= "*"; 52 53 54 55 56 64 public static class Nobody implements Principal 65 66 { 67 public String getName() 68 { 69 return "Nobody"; 70 } 71 } 72 public final static Nobody __NOBODY= new Nobody(); 73 74 75 private String _name; 76 private Object _methods; 77 private Object _roles; 78 private int _dataConstraint= DC_UNSET; 79 private boolean _anyRole= false; 80 private boolean _authenticate= false; 81 82 private transient List _umMethods; 83 private transient List _umRoles; 84 85 86 88 public SecurityConstraint() 89 {} 90 91 92 96 public SecurityConstraint(String name, String role) 97 { 98 setName(name); 99 addRole(role); 100 } 101 102 103 106 public void setName(String name) 107 { 108 _name= name; 109 } 110 111 112 115 public synchronized void addMethod(String method) 116 { 117 _methods= LazyList.add(_methods, method); 118 } 119 120 121 public List getMethods() 122 { 123 if (_umMethods == null && _methods != null) 124 _umMethods= Collections.unmodifiableList(LazyList.getList(_methods)); 125 return _umMethods; 126 } 127 128 129 134 public boolean forMethod(String method) 135 { 136 if (_methods == null) 137 return true; 138 for (int i= 0; i < LazyList.size(_methods); i++) 139 if (LazyList.get(_methods, i).equals(method)) 140 return true; 141 return false; 142 } 143 144 145 151 public synchronized void addRole(String role) 152 { 153 _authenticate= true; 154 if (ANY_ROLE.equals(role)) 155 { 156 _roles= null; 157 _umRoles= null; 158 _anyRole= true; 159 } 160 else if (!_anyRole) 161 _roles= LazyList.add(_roles, role); 162 } 163 164 165 168 public boolean isAnyRole() 169 { 170 return _anyRole; 171 } 172 173 174 177 public List getRoles() 178 { 179 if (_umRoles == null && _roles != null) 180 _umRoles= Collections.unmodifiableList(LazyList.getList(_roles)); 181 return _umRoles; 182 } 183 184 185 189 public boolean hasRole(String role) 190 { 191 return LazyList.contains(_roles, role); 192 } 193 194 195 198 public void setAuthenticate(boolean authenticate) 199 { 200 _authenticate= authenticate; 201 } 202 203 204 207 public boolean getAuthenticate() 208 { 209 return _authenticate; 210 } 211 212 213 216 public boolean isForbidden() 217 { 218 return _authenticate && !_anyRole && LazyList.size(_roles) == 0; 219 } 220 221 222 225 public void setDataConstraint(int c) 226 { 227 if (c < 0 || c > DC_CONFIDENTIAL) 228 throw new IllegalArgumentException ("Constraint out of range"); 229 _dataConstraint= c; 230 } 231 232 233 236 public int getDataConstraint() 237 { 238 return _dataConstraint; 239 } 240 241 242 245 public boolean hasDataConstraint() 246 { 247 return _dataConstraint >= DC_NONE; 248 } 249 250 251 public Object clone() 252 throws CloneNotSupportedException 253 { 254 SecurityConstraint sc = (SecurityConstraint) super.clone(); 255 sc._umMethods=null; 256 sc._umRoles=null; 257 return sc; 258 } 259 260 261 public String toString() 262 { 263 return "SC{" 264 + _name 265 + "," 266 + _methods 267 + "," 268 + (_anyRole ? "*" : (_roles == null ? "-" : _roles.toString())) 269 + "," 270 + (_dataConstraint == DC_NONE 271 ? "NONE}" 272 : (_dataConstraint == DC_INTEGRAL ? "INTEGRAL}" : "CONFIDENTIAL}")); 273 } 274 275 276 287 public static boolean check( 288 List constraints, 289 Authenticator authenticator, 290 UserRealm realm, 291 String pathInContext, 292 HttpRequest request, 293 HttpResponse response) 294 throws HttpException, IOException 295 { 296 int dataConstraint= DC_NONE; 298 Object roles= null; 299 boolean unauthenticated= false; 300 boolean forbidden= false; 301 302 for (int c= 0; c < constraints.size(); c++) 303 { 304 SecurityConstraint sc= (SecurityConstraint)constraints.get(c); 305 306 if (!sc.forMethod(request.getMethod())) 308 continue; 309 310 if (dataConstraint > DC_UNSET && sc.hasDataConstraint()) 312 { 313 if (sc.getDataConstraint() > dataConstraint) 314 dataConstraint= sc.getDataConstraint(); 315 } 316 else 317 dataConstraint= DC_UNSET; 319 if (!unauthenticated && !forbidden) 321 { 322 if (sc.getAuthenticate()) 323 { 324 if (sc.isAnyRole()) 325 { 326 roles= ANY_ROLE; 327 } 328 else 329 { 330 List scr= sc.getRoles(); 331 if (scr == null || scr.size() == 0) 332 { 333 forbidden= true; 334 break; 335 } 336 else 337 { 338 if (roles != ANY_ROLE) 339 { 340 roles= LazyList.addCollection(roles, scr); 341 } 342 } 343 } 344 } 345 else 346 unauthenticated= true; 347 } 348 } 349 350 if (forbidden && 352 (!(authenticator instanceof FormAuthenticator) || 353 !((FormAuthenticator)authenticator).isLoginOrErrorPage(pathInContext))) 354 { 355 HttpContext.sendContextError(response,HttpResponse.__403_Forbidden,null); 356 return false; 357 } 358 359 if (dataConstraint > DC_NONE) 361 { 362 HttpConnection connection= request.getHttpConnection(); 363 HttpListener listener= connection.getListener(); 364 365 switch (dataConstraint) 366 { 367 case SecurityConstraint.DC_INTEGRAL : 368 if (listener.isIntegral(connection)) 369 break; 370 371 if (listener.getIntegralPort() > 0) 372 { 373 String url= 374 listener.getIntegralScheme() 375 + "://" 376 + request.getHost() 377 + ":" 378 + listener.getIntegralPort() 379 + request.getPath(); 380 if (request.getQuery() != null) 381 url += "?" + request.getQuery(); 382 response.setContentLength(0); 383 response.sendRedirect(url); 384 } 385 else 386 HttpContext.sendContextError(response,HttpResponse.__403_Forbidden,null); 387 return false; 388 389 case SecurityConstraint.DC_CONFIDENTIAL : 390 if (listener.isConfidential(connection)) 391 break; 392 393 if (listener.getConfidentialPort() > 0) 394 { 395 String url= 396 listener.getConfidentialScheme() 397 + "://" 398 + request.getHost() 399 + ":" 400 + listener.getConfidentialPort() 401 + request.getPath(); 402 if (request.getQuery() != null) 403 url += "?" + request.getQuery(); 404 405 response.setContentLength(0); 406 response.sendRedirect(url); 407 } 408 else 409 HttpContext.sendContextError(response,HttpResponse.__403_Forbidden,null); 410 return false; 411 412 default : 413 HttpContext.sendContextError(response,HttpResponse.__403_Forbidden,null); 414 return false; 415 } 416 } 417 418 if (!unauthenticated && roles != null) 420 { 421 if (realm == null) 422 { 423 HttpContext.sendContextError(response,HttpResponse.__500_Internal_Server_Error,"Configuration error"); 424 return false; 425 } 426 427 Principal user= null; 428 429 if (request.getAuthType() != null && request.getAuthUser() != null) 431 { 432 user= request.getUserPrincipal(); 434 if (user == null) 435 user= realm.authenticate(request.getAuthUser(), null, request); 436 if (user == null && authenticator != null) 437 user= authenticator.authenticate(realm, pathInContext, request, response); 438 } 439 else if (authenticator != null) 440 { 441 user= authenticator.authenticate(realm, pathInContext, request, response); 443 } 444 else 445 { 446 log.warn("Mis-configured Authenticator for " + request.getPath()); 448 HttpContext.sendContextError(response,HttpResponse.__500_Internal_Server_Error,"Configuration error"); 449 } 450 451 if (user == null) 453 return false; else if (user == __NOBODY) 455 return true; 457 if (roles != ANY_ROLE) 458 { 459 boolean inRole= false; 460 for (int r= LazyList.size(roles); r-- > 0;) 461 { 462 if (realm.isUserInRole(user, (String )LazyList.get(roles, r))) 463 { 464 inRole= true; 465 break; 466 } 467 } 468 469 if (!inRole) 470 { 471 log.warn("AUTH FAILURE: role for " + user.getName()); 472 if ("BASIC".equalsIgnoreCase(authenticator.getAuthMethod())) 473 ((BasicAuthenticator)authenticator).sendChallenge(realm, response); 474 else 475 HttpContext.sendContextError(response,HttpResponse.__403_Forbidden,"User not in required role"); 476 return false; } 478 } 479 } 480 else 481 { 482 request.setUserPrincipal(HttpRequest.__NOT_CHECKED); 483 } 484 485 return true; 486 } 487 488 } 489 | Popular Tags |