1 22 package org.jboss.web.tomcat.security; 23 24 import java.security.Principal ; 25 import java.security.cert.X509Certificate ; 26 import java.util.ArrayList ; 27 import java.util.Iterator ; 28 import java.util.Set ; 29 import java.util.HashSet ; 30 import java.io.IOException ; 31 import javax.naming.Context ; 32 import javax.naming.InitialContext ; 33 import javax.naming.NamingException ; 34 import javax.security.auth.Subject ; 35 import javax.servlet.http.HttpServletResponse ; 36 37 import org.apache.catalina.LifecycleException; 38 import org.apache.catalina.Realm; 39 import org.apache.catalina.deploy.SecurityConstraint; 40 import org.apache.catalina.deploy.LoginConfig; 41 import org.apache.catalina.connector.Request; 42 import org.apache.catalina.connector.Response; 43 import org.apache.catalina.realm.RealmBase; 44 import org.apache.catalina.realm.Constants; 45 import org.apache.catalina.realm.GenericPrincipal; 46 import org.jboss.logging.Logger; 47 import org.jboss.security.CertificatePrincipal; 48 import org.jboss.security.RealmMapping; 49 import org.jboss.security.SimplePrincipal; 50 import org.jboss.security.SubjectSecurityManager; 51 import org.jboss.security.auth.certs.SubjectDNMapping; 52 import org.jboss.security.auth.callback.CallbackHandlerPolicyContextHandler; 53 54 74 public class JBossSecurityMgrRealm extends RealmBase implements Realm 75 { 76 static Logger log = Logger.getLogger(JBossSecurityMgrRealm.class); 77 80 private CertificatePrincipal certMapping = new SubjectDNMapping(); 81 84 private boolean trace; 85 86 private AllRolesMode allRolesMode = AllRolesMode.AUTH_ONLY_MODE; 87 88 96 public void setCertificatePrincipal(String className) 97 { 98 try 99 { 100 ClassLoader loader = Thread.currentThread().getContextClassLoader(); 101 Class cpClass = loader.loadClass(className); 102 certMapping = (CertificatePrincipal) cpClass.newInstance(); 103 } 104 catch (Exception e) 105 { 106 log.error("Failed to load CertificatePrincipal: " + className, e); 107 certMapping = new SubjectDNMapping(); 108 } 109 } 110 111 private Context getSecurityContext() 112 { 113 Context securityCtx = null; 114 try 116 { 117 InitialContext iniCtx = new InitialContext (); 118 securityCtx = (Context ) iniCtx.lookup("java:comp/env/security"); 119 } 120 catch (NamingException e) 121 { 122 } 124 return securityCtx; 125 } 126 127 130 public void start() throws LifecycleException 131 { 132 if (super.started == true) 133 { 134 return; 135 } 136 super.start(); 137 trace = log.isTraceEnabled(); 138 } 139 140 143 public void stop() throws LifecycleException 144 { 145 if (super.started == false) 146 { 147 return; 148 } 149 super.stop(); 150 } 151 152 public boolean hasResourcePermission(Request request, Response response, 153 SecurityConstraint[] constraints, org.apache.catalina.Context context) 154 throws IOException 155 { 156 if (constraints == null || constraints.length == 0) 157 { 158 return (true); 159 } 160 161 boolean hasPermission = false; 162 LoginConfig config = context.getLoginConfig(); 165 if ((config != null) && 166 (Constants.FORM_METHOD.equals(config.getAuthMethod()))) 167 { 168 String requestURI = request.getRequestPathMB().toString(); 169 String loginPage = config.getLoginPage(); 170 if (loginPage.equals(requestURI)) 171 { 172 if( trace ) 173 log.trace("Allow access to login page " + loginPage); 174 return (true); 175 } 176 String errorPage = config.getErrorPage(); 177 if (errorPage.equals(requestURI)) 178 { 179 if( trace ) 180 log.trace("Allow access to error page " + errorPage); 181 return (true); 182 } 183 if (requestURI.endsWith(Constants.FORM_ACTION)) 184 { 185 if( trace ) 186 log.trace("Allow access to username/password submission"); 187 return (true); 188 } 189 } 190 191 Principal principal = request.getPrincipal(); 193 boolean denyfromall = false; 194 for (int i = 0; i < constraints.length; i++) 195 { 196 SecurityConstraint constraint = constraints[i]; 197 198 String roles[]; 199 if (constraint.getAllRoles()) 200 { 201 roles = request.getContext().findSecurityRoles(); 203 } 204 else 205 { 206 roles = constraint.findAuthRoles(); 207 } 208 209 if (roles == null) 210 { 211 roles = new String [0]; 212 } 213 214 if( trace ) 215 log.trace("Checking roles " + principal); 216 217 if (roles.length == 0 && !constraint.getAllRoles()) 218 { 219 if (constraint.getAuthConstraint()) 220 { 221 if( trace ) 222 log.trace("No roles"); 223 hasPermission = false; denyfromall = true; 225 } 226 else 227 { 228 if( trace ) 229 log.trace("Passing all access"); 230 return (true); 231 } 232 } 233 else if (principal == null) 234 { 235 if( trace ) 236 log.trace("No user authenticated, cannot grant access"); 237 hasPermission = false; 238 } 239 else if (!denyfromall) 240 { 241 for (int j = 0; j < roles.length; j++) 242 { 243 if (hasRole(principal, roles[j])) 244 { 245 hasPermission = true; 246 } 247 if( trace ) 248 log.trace("No role found: " + roles[j]); 249 } 250 } 251 } 252 253 if (allRolesMode != AllRolesMode.STRICT_MODE 254 && hasPermission == false 255 && principal != null) 256 { 257 if (trace) 258 { 259 log.trace("Checking for all roles mode: " + allRolesMode); 260 } 261 for (int i = 0; i < constraints.length; i++) 263 { 264 SecurityConstraint constraint = constraints[i]; 265 String roles[]; 266 if (constraint.getAllRoles()) 268 { 269 if (allRolesMode == AllRolesMode.AUTH_ONLY_MODE) 270 { 271 if (trace) 272 { 273 log.trace("Granting access for role-name=*, auth-only"); 274 } 275 hasPermission = true; 276 break; 277 } 278 279 roles = request.getContext().findSecurityRoles(); 281 if (roles.length == 0 && allRolesMode == AllRolesMode.STRICT_AUTH_ONLY_MODE) 282 { 283 if (trace) 284 { 285 log.trace("Granting access for role-name=*, strict auth-only"); 286 } 287 hasPermission = true; 288 break; 289 } 290 } 291 } 292 } 293 294 if (!hasPermission) 296 { 297 response.sendError 298 (HttpServletResponse.SC_FORBIDDEN, 299 sm.getString("realmBase.forbidden")); 300 } 301 return hasPermission; 302 } 303 304 311 public Principal authenticate(X509Certificate [] certs) 312 { 313 Principal principal = null; 314 Context securityCtx = getSecurityContext(); 315 if (securityCtx == null) 316 { 317 if (trace) 318 { 319 log.trace("No security context for authenticate(X509Certificate[])"); 320 } 321 return null; 322 } 323 324 try 325 { 326 SubjectSecurityManager securityMgr = (SubjectSecurityManager) securityCtx.lookup("securityMgr"); 328 Subject subject = new Subject (); 329 principal = certMapping.toPrinicipal(certs); 330 if (securityMgr.isValid(principal, certs, subject)) 331 { 332 if (trace) 333 { 334 log.trace("User: " + principal + " is authenticated"); 335 } 336 SecurityAssociationActions.setPrincipalInfo(principal, certs, subject); 337 RealmMapping realmMapping = (RealmMapping) securityCtx.lookup("realmMapping"); 339 Principal oldPrincipal = principal; 340 principal = realmMapping.getPrincipal(oldPrincipal); 341 if (trace) 342 { 343 log.trace("Mapped from input principal: " + oldPrincipal 344 + "to: " + principal); 345 } 346 principal = getCachingPrincpal(realmMapping, oldPrincipal, 348 principal, certs, subject); 349 } 350 else 351 { 352 if (trace) 353 { 354 log.trace("User: " + principal + " is NOT authenticated"); 355 } 356 principal = null; 357 } 358 } 359 catch (NamingException e) 360 { 361 log.error("Error during authenticate", e); 362 } 363 return principal; 364 } 365 366 382 public Principal authenticate(String username, String digest, String nonce, 383 String nc, String cnonce, String qop, String realm, String md5a2) 384 { 385 Principal principal = null; 386 Context securityCtx = getSecurityContext(); 387 if (securityCtx == null) 388 { 389 if (trace) 390 { 391 log.trace("No security context for authenticate(String, String)"); 392 } 393 return null; 394 } 395 396 Principal caller = (Principal ) SecurityAssociationValve.userPrincipal.get(); 397 if (caller == null && username == null && digest == null) 398 { 399 return null; 400 } 401 402 try 403 { 404 DigestCallbackHandler handler = new DigestCallbackHandler(username, nonce, 405 nc, cnonce, qop, realm, md5a2); 406 CallbackHandlerPolicyContextHandler.setCallbackHandler(handler); 407 408 SubjectSecurityManager securityMgr = (SubjectSecurityManager) securityCtx.lookup("securityMgr"); 410 principal = new SimplePrincipal(username); 411 Subject subject = new Subject (); 412 if (securityMgr.isValid(principal, digest, subject)) 413 { 414 log.trace("User: " + username + " is authenticated"); 415 SecurityAssociationActions.setPrincipalInfo(principal, digest, subject); 416 RealmMapping realmMapping = (RealmMapping) securityCtx.lookup("realmMapping"); 418 Principal oldPrincipal = principal; 419 principal = realmMapping.getPrincipal(oldPrincipal); 420 if (trace) 421 { 422 log.trace("Mapped from input principal: " + oldPrincipal 423 + "to: " + principal); 424 } 425 principal = getCachingPrincpal(realmMapping, oldPrincipal, 427 principal, digest, subject); 428 } 429 else 430 { 431 principal = null; 432 if (trace) 433 { 434 log.trace("User: " + username + " is NOT authenticated"); 435 } 436 } 437 } 438 catch (NamingException e) 439 { 440 principal = null; 441 log.error("Error during authenticate", e); 442 } 443 finally 444 { 445 CallbackHandlerPolicyContextHandler.setCallbackHandler(null); 446 } 447 if (trace) 448 { 449 log.trace("End authenticate, principal=" + principal); 450 } 451 return principal; 452 } 453 454 462 public Principal authenticate(String username, String credentials) 463 { 464 if (trace) 465 { 466 log.trace("Begin authenticate, username=" + username); 467 } 468 Principal principal = null; 469 Context securityCtx = getSecurityContext(); 470 if (securityCtx == null) 471 { 472 if (trace) 473 { 474 log.trace("No security context for authenticate(String, String)"); 475 } 476 return null; 477 } 478 479 Principal caller = (Principal ) SecurityAssociationValve.userPrincipal.get(); 480 if (caller == null && username == null && credentials == null) 481 { 482 return null; 483 } 484 485 try 486 { 487 SubjectSecurityManager securityMgr = (SubjectSecurityManager) securityCtx.lookup("securityMgr"); 489 principal = new SimplePrincipal(username); 490 Subject subject = new Subject (); 491 if (securityMgr.isValid(principal, credentials, subject)) 492 { 493 log.trace("User: " + username + " is authenticated"); 494 SecurityAssociationActions.setPrincipalInfo(principal, credentials, subject); 495 RealmMapping realmMapping = (RealmMapping) securityCtx.lookup("realmMapping"); 497 Principal oldPrincipal = principal; 498 principal = realmMapping.getPrincipal(oldPrincipal); 499 if (trace) 500 { 501 log.trace("Mapped from input principal: " + oldPrincipal 502 + "to: " + principal); 503 } 504 principal = getCachingPrincpal(realmMapping, oldPrincipal, 506 principal, credentials, subject); 507 } 508 else 509 { 510 principal = null; 511 if (trace) 512 { 513 log.trace("User: " + username + " is NOT authenticated"); 514 } 515 } 516 } 517 catch (NamingException e) 518 { 519 principal = null; 520 log.error("Error during authenticate", e); 521 } 522 if (trace) 523 { 524 log.trace("End authenticate, principal=" + principal); 525 } 526 return principal; 527 } 528 529 541 public boolean hasRole(Principal principal, String role) 542 { 543 return super.hasRole(principal, role); 544 569 } 570 571 579 public Principal authenticate(String username, byte[] credentials) 580 { 581 return authenticate(username, new String (credentials)); 582 } 583 584 588 protected String getName() 589 { 590 return getClass().getName(); 591 } 592 593 596 protected String getPassword(String username) 597 { 598 String password = null; 599 return password; 600 } 601 602 605 protected Principal getPrincipal(String username) 606 { 607 return new SimplePrincipal(username); 608 } 609 610 617 protected Set getPrincipalRoles(Principal principal) 618 { 619 if( (principal instanceof GenericPrincipal) == false ) 620 throw new IllegalStateException ("Expected GenericPrincipal, but saw: "+principal.getClass()); 621 GenericPrincipal gp = (GenericPrincipal) principal; 622 String [] roleNames = gp.getRoles(); 623 Set userRoles = new HashSet (); 624 if( roleNames != null ) 625 { 626 for(int n = 0; n < roleNames.length; n ++) 627 { 628 SimplePrincipal sp = new SimplePrincipal(roleNames[n]); 629 userRoles.add(sp); 630 } 631 } 632 return userRoles; 633 } 634 635 647 protected Principal getCachingPrincpal(RealmMapping realmMapping, 648 Principal authPrincipal, Principal callerPrincipal, Object credential, 649 Subject subject) 650 { 651 Set userRoles = realmMapping.getUserRoles(authPrincipal); 653 ArrayList roles = new ArrayList (); 654 if (userRoles != null) 655 { 656 Iterator iterator = userRoles.iterator(); 657 while (iterator.hasNext()) 658 { 659 Principal role = (Principal ) iterator.next(); 660 roles.add(role.getName()); 661 } 662 } 663 JBossGenericPrincipal gp = new JBossGenericPrincipal(this, subject, 664 authPrincipal, callerPrincipal, credential, roles, userRoles); 665 return gp; 666 } 667 } 668 | Popular Tags |