001/* 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: PolicyEvaluator.java,v 1.19 2010/01/14 23:18:35 dillidorai Exp $ 026 * 027 * Portions Copyrighted 2011-2015 ForgeRock AS. 028 */ 029 030package com.sun.identity.policy; 031 032import static org.forgerock.openam.utils.CollectionUtils.asSet; 033 034import javax.security.auth.Subject; 035import java.security.AccessController; 036import java.security.Principal; 037import java.util.Collections; 038import java.util.Enumeration; 039import java.util.HashMap; 040import java.util.HashSet; 041import java.util.Iterator; 042import java.util.List; 043import java.util.Map; 044import java.util.Set; 045 046import com.iplanet.am.sdk.AMCommonUtils; 047import com.iplanet.am.sdk.AMException; 048import com.iplanet.am.sdk.AMStoreConnection; 049import com.iplanet.am.sdk.AMUser; 050import com.iplanet.am.util.Cache; 051import com.iplanet.am.util.SystemProperties; 052import com.iplanet.sso.SSOException; 053import com.iplanet.sso.SSOToken; 054import com.iplanet.sso.SSOTokenListener; 055import com.sun.identity.entitlement.Application; 056import com.sun.identity.entitlement.ApplicationManager; 057import com.sun.identity.entitlement.Entitlement; 058import com.sun.identity.entitlement.EntitlementException; 059import com.sun.identity.entitlement.Evaluator; 060import com.sun.identity.entitlement.opensso.SubjectUtils; 061import com.sun.identity.monitoring.Agent; 062import com.sun.identity.monitoring.MonitoringUtil; 063import com.sun.identity.monitoring.SsoServerPolicySvcImpl; 064import com.sun.identity.policy.interfaces.Condition; 065import com.sun.identity.policy.interfaces.PolicyListener; 066import com.sun.identity.security.AdminTokenAction; 067import com.sun.identity.shared.debug.Debug; 068import com.sun.identity.shared.stats.Stats; 069import com.sun.identity.sm.AttributeSchema; 070import com.sun.identity.sm.DNMapper; 071import com.sun.identity.sm.ServiceManager; 072import org.forgerock.openam.entitlement.PolicyConstants; 073import org.forgerock.openam.ldap.LDAPUtils; 074 075/** 076 * The class <code>PolicyEvaluator</code> evaluates policies 077 * and provides policy decisions. 078 * @supported.api 079 * @deprecated since 12.0.0 080 */ 081@Deprecated 082public class PolicyEvaluator { 083 084 /** 085 * Constant used to identity all the resources of a service type. 086 * The resources include the sub resources of all resource prefixes of 087 * resource type 088 * 089 * @supported.api 090 */ 091 public static final String ALL_RESOURCES 092 = "---ALL_RESOURCES---"; 093 094 public static final String ADVICING_ORGANIZATION 095 = "AdvicingOrganization"; 096 097 /** 098 * Constant used to identity empty resource 099 * 100 * @supported.api 101 */ 102 public static final String EMPTY_RESOURCE_NAME = ""; 103 104 /** 105 * Constant used for key to pass the requested resource name canonicalized 106 * in the env map, so that Condition(s)/ResponseProvider(s) could use 107 * the requested resource name, if necessary 108 */ 109 public static final String SUN_AM_REQUESTED_RESOURCE 110 = "sun.am.requestedResource"; 111 112 /** 113 * Constant used for key to pass the requested resource name uncanonicalized 114 * in the env map, so that Condition(s)/ResponseProvider(s) could use 115 * the requested resource name, if necessary 116 */ 117 public static final String SUN_AM_ORIGINAL_REQUESTED_RESOURCE 118 = "sun.am.requestedOriginalResource"; 119 120 /** 121 * Constant used for key to pass the requested actions names 122 * in the env map, so that Condition(s)/ResponseProvider(s) could use 123 * the requested actions names, if necessary 124 */ 125 public static final String SUN_AM_REQUESTED_ACTIONS 126 = "sun.am.requestedActions"; 127 128 /** 129 * Constant used for key to pass the realm DN in the env map, so that Condition(s) 130 * can look up the relevant <code>PolicyConfig</code> config map, if necessary. 131 * <code>LDAPFilterCondition</code> needs to use PolicyConfig config map. 132 */ 133 public static final String REALM_DN = "am.policy.realmDN"; 134 135 public static final String RESULTS_CACHE_SESSION_CAP 136 = "com.sun.identity.policy.resultsCacheSessionCap"; 137 138 public static int DEFAULT_RESULTS_CACHE_SESSION_CAP = 1000; 139 140 public static int resultsCacheSessionCap = DEFAULT_RESULTS_CACHE_SESSION_CAP; 141 142 public static final String RESULTS_CACHE_RESOURCE_CAP 143 = "com.sun.identity.policy.resultsCacheResourceCap"; 144 145 public static int DEFAULT_RESULTS_CACHE_RESOURCE_CAP = 100; 146 147 public static int resultsCacheResourceCap = DEFAULT_RESULTS_CACHE_RESOURCE_CAP; 148 149 private static final Debug DEBUG = PolicyManager.debug; 150 private static final boolean USE_POLICY_CACHE = true; 151 private static final boolean INCLUDE_SUPER_RESOURCE_POLCIES = true; 152 private static final long DEFAULT_USER_NSROLE_CACHE_TTL = 600000; 153 154 private String orgName; 155 private String realm; 156 private String serviceTypeName; 157 private String applicationName; 158 private ServiceType serviceType; 159 private PolicyCache policyCache; 160 private PolicyManager policyManager; 161 private ResourceIndexManager resourceIndexManager; 162 163 private HashMap booleanActionNameTrueValues; //cache 164 private HashMap booleanActionNameFalseValues; //cache 165 private Set actionNames; //all action names valid for the serviceType 166 private Set orgNames = new HashSet(); // to pass org name in envParameters 167 // used to pass service type name in envParameters 168 private Set serviceTypeNames = new HashSet(); 169 // listener for policy decision cache 170 private PolicyDecisionCacheListener listener = null; 171 172 /* 173 * Cache to keep the policy evaluation results 174 * Cache structure layout: 175 * 176 * cache ----> Servicename1 177 * ----> servicename2 178 * ... 179 * ----> servicenameN 180 * 181 * servicenameI ----> Resourcename1 182 * ----> Resourcename2 183 * ... 184 * ----> ResourcenameN 185 * 186 * resourcenameI ----> userssotokenidstring1 187 * ----> userssotokenidstring2 188 * ... 189 * ----> userssotokenidstringN 190 * 191 * userssotokenidstringI ----> requestscope1 192 * ----> requestscope2 193 * 194 * requestscope1 ----> resourceresult1 195 * requestscope2 ----> resourceresult2 196 */ 197 static Map policyResultsCache = new HashMap(); 198 199 /* 200 * The sso token listener registry for policy decision cache. 201 * To avoid adding multiple sso token listeners for the same 202 * token, we use this registry to make sure the listener is 203 * registered only once for each token. It will be unregistered 204 * if token is expired. 205 * 206 * Key is tokenId and value is policySSOTokenListener 207 * ssoTokenIDString : PolicySSOTokenListener 208 * 209 * Used to clean up cache on ssoToken notifications 210 */ 211 public static Map ssoListenerRegistry = 212 Collections.synchronizedMap(new HashMap()); 213 214 /* 215 * The policy change listener registry for policy decision cache. 216 * To avoid adding multiple listeners for the same service, we 217 * use this registry to make sure the listener is registered only 218 * once for each service. 219 * 220 * Key is serviceTypeName and value is <code>PolicyDecisionCacheListener 221 * </code> 222 * serviceTypeName : PolicyDecisionCacheListener for service type 223 * 224 * Used to clean up the decision cache on policy change notification 225 */ 226 private static Map<String, PolicyDecisionCacheListener> policyListenerRegistry = 227 Collections.synchronizedMap(new HashMap<String, PolicyDecisionCacheListener>()); 228 229 /** 230 * The user <code>nsRole</code> attribute cache. 231 * AMSDK cache stops caching a user's nsRole attribute in 6.2 232 * due to notification issue. Adding this cache in policy to 233 * avoid performance impact caused by the AMSDK change. This 234 * cache uses a user's token as the key to map to the user's 235 * <code>nsRole</code> attribute values. 236 * 237 * Key is tokenId and value is set of role DN(s) 238 * ssoTokenIDString : set of role DN(s) 239 */ 240 static Map userNSRoleCache = 241 Collections.synchronizedMap(new HashMap()); 242 243 // TTL value for entries in the user's nsRole attribute values. 244 private static long userNSRoleCacheTTL = 0; 245 246 /** 247 * listener object to be used in cleaning up the 248 * userNSRoleCache, subjectEvaluationCache , user role 249 * cache in LDAPRoles and policyResultsCache 250 * upon user token expiration. 251 */ 252 public static SSOTokenListener ssoListener = 253 new PolicySSOTokenListener(); 254 255 /* 256 * Cache for sub resources keyed by resource name 257 * The structure is a Map of 258 * serviceType(String) : resourceNamesCache(Cache) 259 * Key for resourceNamesCache is a root resource name and value is 260 * a <code>Set</code> of sub resource names for the root resource name 261 * 262 * serviceType: resourceName : resourceNames 263 */ 264 private static Map resourceNamesMap = new HashMap(); 265 266 /** 267 * Constant key for passing organization name in the environment map during 268 * policy evaluation. The value for the key would be a <code>Set</code> 269 * with one element of type String. The string is the name of the 270 * organization the policy evaluator has been instantiated for. 271 */ 272 static final String ORGANIZATION_NAME = "organizationName"; 273 274 /** 275 * Constant key for passing service type name in the environment map during 276 * policy evaluation. The value for the key would be a <code>Set</code> 277 * with one element of type String. The string is the name of the 278 * <code>ServiceType</code> the policy evaluator has been instantiated for. 279 */ 280 static final String SERVICE_TYPE_NAME = "serviceTypeName"; 281 282 static final Object lock = new Object(); 283 284 /** 285 * Constructor to create a <code>PolicyEvaluator</code> given the <code> 286 * ServiceType</code> name. 287 * 288 * @param serviceTypeName the name of the <code>ServiceType</code> for 289 * which this evaluator can be used. 290 * @throws SSOException if <code>SSOToken</code> used by 291 * <code>PolicyEvaluator</code> is invalid 292 * @throws NameNotFoundException if the service with name 293 * <code>serviceTypeName</code> is not found 294 * @throws PolicyException for any other abnormal condition 295 * 296 * @supported.api 297 */ 298 public PolicyEvaluator(String serviceTypeName) 299 throws SSOException, NameNotFoundException, PolicyException { 300 301 this("", serviceTypeName); 302 303 registerListener(); 304 } 305 306 /** 307 * Constructor to create a <code>PolicyEvaluator</code> given organization 308 * name and the <code>ServiceType</code> name. 309 * 310 * @param orgName the name of the organization under which the evaluation 311 * is being done 312 * @param serviceTypeName the name of the <code>ServiceType</code> for 313 * which this evaluator can be used. 314 */ 315 public PolicyEvaluator(String orgName, String serviceTypeName) 316 throws SSOException, PolicyException, NameNotFoundException { 317 318 if ( (orgName == null) || (orgName.equals("/")) 319 || (orgName.length() == 0) ) { 320 orgName = ServiceManager.getBaseDN(); 321 } else { 322 orgName = com.sun.identity.sm.DNMapper.orgNameToDN(orgName); 323 } 324 this.orgName = orgName; 325 326 this.realm = com.sun.identity.sm.DNMapper.orgNameToRealmName(orgName); 327 this.serviceTypeName = serviceTypeName; 328 // Default application to be the service type, this maintains legacy behaviour. 329 this.applicationName = serviceTypeName; 330 331 this.policyCache = PolicyCache.getInstance(); 332 333 ServiceTypeManager stm = ServiceTypeManager.getServiceTypeManager(); 334 serviceType = stm.getServiceType(serviceTypeName); 335 policyManager = policyCache.getPolicyManager(orgName); 336 this.orgNames.add(policyManager.getOrganizationDN()); 337 this.serviceTypeNames.add(serviceTypeName); 338 resourceIndexManager = policyManager.getResourceIndexManager(); 339 340 String resultsCacheSessionCapString 341 = SystemProperties.get(RESULTS_CACHE_SESSION_CAP); 342 if (resultsCacheSessionCapString != null) { 343 try { 344 resultsCacheSessionCap 345 = Integer.parseInt(resultsCacheSessionCapString); 346 } catch (NumberFormatException nfe) { 347 if (PolicyManager.debug.warningEnabled()) { 348 PolicyManager.debug.warning("PolicyEvaluator:" 349 + "number format exception: " 350 + "defaulting resultsCacheSessionCap to " 351 + DEFAULT_RESULTS_CACHE_SESSION_CAP); 352 } 353 resultsCacheSessionCap = DEFAULT_RESULTS_CACHE_SESSION_CAP; 354 } 355 } else { 356 if (PolicyManager.debug.warningEnabled()) { 357 PolicyManager.debug.warning("PolicyEvaluator:" 358 + "resultsCacheSessionCap not specified, " 359 + "defaulting resultsCacheSessionCap to " 360 + DEFAULT_RESULTS_CACHE_SESSION_CAP); 361 } 362 resultsCacheSessionCap = DEFAULT_RESULTS_CACHE_SESSION_CAP; 363 } 364 if (PolicyManager.debug.messageEnabled()) { 365 PolicyManager.debug.message("PolicyEvaluator:" 366 + "resultsCacheSessionCap=" + resultsCacheSessionCap); 367 } 368 369 String resultsCacheResourceCapString 370 = SystemProperties.get(RESULTS_CACHE_RESOURCE_CAP); 371 if (resultsCacheResourceCapString != null) { 372 try { 373 resultsCacheResourceCap 374 = Integer.parseInt(resultsCacheResourceCapString); 375 } catch (NumberFormatException nfe) { 376 if (PolicyManager.debug.warningEnabled()) { 377 PolicyManager.debug.warning("PolicyEvaluator:" 378 + "number format exception: " 379 + "defaulting resultsCacheResourceCap to " 380 + DEFAULT_RESULTS_CACHE_RESOURCE_CAP); 381 } 382 resultsCacheResourceCap = DEFAULT_RESULTS_CACHE_RESOURCE_CAP; 383 } 384 } else { 385 if (PolicyManager.debug.warningEnabled()) { 386 PolicyManager.debug.warning("PolicyEvaluator:" 387 + "resultsCacheResourceCap not specified, " 388 + "defaulting resultsCacheResourceCap to " 389 + DEFAULT_RESULTS_CACHE_RESOURCE_CAP); 390 } 391 resultsCacheResourceCap = DEFAULT_RESULTS_CACHE_RESOURCE_CAP; 392 } 393 if (PolicyManager.debug.messageEnabled()) { 394 PolicyManager.debug.message("PolicyEvaluator:" 395 + "resultsCacheResourceCap=" + resultsCacheResourceCap); 396 } 397 398 } 399 400 /** 401 * Creates a new policy evaluator instance. 402 * 403 * @param orgName 404 * the name of the organization under which the evaluation is being done 405 * @param serviceTypeName 406 * the name of the <code>ServiceType</code> for which this evaluator can be used 407 * @param applicationName 408 * the application name containing the policies in question 409 * 410 * @throws PolicyException 411 * should some error occur constructor the evaluator 412 * @throws SSOException 413 * should some error occur with regards to any SSO token 414 */ 415 public PolicyEvaluator(String orgName, String serviceTypeName, String applicationName) 416 throws PolicyException, SSOException { 417 this(orgName, serviceTypeName); 418 this.applicationName = applicationName; 419 420 registerListener(); 421 } 422 423 /** 424 * Register a policy listener for updating policy decision cache if there is none already registered. 425 */ 426 private void registerListener() { 427 synchronized (lock) { 428 if (!policyListenerRegistry.containsKey(serviceTypeName)) { 429 listener = new PolicyDecisionCacheListener(serviceTypeName); 430 431 try { 432 PolicyCache.getInstance().addPolicyListener(listener); 433 } catch (PolicyException pe) { 434 DEBUG.error("PolicyEvaluator: registering policy decision cache listener failed"); 435 } 436 437 policyListenerRegistry.put(serviceTypeName, listener); 438 439 if (DEBUG.messageEnabled()) { 440 DEBUG.message("PolicyEvaluator:policy listener for service " + serviceTypeName + " added"); 441 } 442 443 } else { 444 listener = policyListenerRegistry.get(serviceTypeName); 445 } 446 } 447 } 448 449 /** 450 * Evaluates a simple privilege of boolean type. The privilege indicate 451 * if the user can perform specified action on the specified resource. 452 * Invoking this method would result in <code>PolicyException</code>, 453 * if the syntax for the <code>actionName</code> is not declared to be 454 * boolean, in the service schema. 455 * 456 * @param token single sign on token of the user evaluating policies 457 * @param resourceName name of the resource the user is trying to access 458 * @param actionName name of the action the user is trying to perform on 459 * the resource 460 * 461 * @return the result of the evaluation as a boolean value 462 * 463 * @exception SSOException single-sign-on token invalid or expired 464 * 465 */ 466 public boolean isAllowed(SSOToken token, String resourceName, 467 String actionName) throws PolicyException, SSOException { 468 return (isAllowed(token, resourceName, actionName, 469 new HashMap())); 470 } 471 472 /** 473 * Evaluates simple privileges of boolean type. The privilege indicate 474 * if the user can perform specified action on the specified resource. 475 * The evaluation depends on user's application environment parameters. 476 * Invoking this method would result in <code>PolicyException</code>, 477 * if the syntax for the <code>actionName</code> is not declared to be 478 * boolean, in the service schema. 479 * 480 * @param token single sign on token of the user evaluating policies 481 * @param resourceName name of the resource the user is trying to access 482 * @param actionName name of the action the user is trying to perform on 483 * the resource 484 * @param envParameters run-time environment parameters 485 * 486 * @return the result of the evaluation as a boolean value 487 * 488 * @throws SSOException single-sign-on token invalid or expired 489 * @throws PolicyException for any other abnormal condition 490 * 491 * @supported.api 492 */ 493 public boolean isAllowed(SSOToken token, String resourceName, 494 String actionName, Map envParameters) throws SSOException, 495 PolicyException { 496 if (PolicyManager.isMigratedToEntitlementService()) { 497 return isAllowedE(token, resourceName, actionName, envParameters); 498 } 499 return isAllowedO(token, resourceName, actionName, envParameters); 500 } 501 502 public boolean isAllowedO(SSOToken token, String resourceName, 503 String actionName, Map envParameters) throws SSOException, 504 PolicyException { 505 506 ActionSchema schema = serviceType.getActionSchema(actionName); 507 508 // Cache the false values for the action names 509 if (booleanActionNameFalseValues == null) { 510 booleanActionNameFalseValues = new HashMap(10); 511 } 512 String falseValue = null; 513 if ((falseValue = (String) 514 booleanActionNameFalseValues.get(actionName)) == null) { 515 falseValue = schema.getFalseValue(); 516 // Add it to the cache 517 booleanActionNameFalseValues.put(actionName, falseValue); 518 } 519 520 521 // Cache the true values for the action names 522 if (booleanActionNameTrueValues == null) { 523 booleanActionNameTrueValues = new HashMap(10); 524 } 525 526 String trueValue = null; 527 if ((trueValue = (String) 528 booleanActionNameTrueValues.get(actionName)) == null) { 529 trueValue = schema.getTrueValue(); 530 // Add it to the cache 531 booleanActionNameTrueValues.put(actionName, trueValue); 532 } 533 534 if (!AttributeSchema.Syntax.BOOLEAN.equals(schema.getSyntax())) { 535 String objs[] = {actionName}; 536 throw new PolicyException( 537 ResBundleUtils.rbName, 538 "action_does_not_have_boolean_syntax", objs, null); 539 } 540 541 boolean actionAllowed = false; 542 HashSet actionNames = new HashSet(2); 543 actionNames.add(actionName); 544 PolicyDecision policyDecision = getPolicyDecision(token, resourceName, 545 actionNames, envParameters); 546 ActionDecision actionDecision = 547 (ActionDecision) policyDecision.getActionDecisions() 548 .get(actionName); 549 550 if ( actionDecision != null ) { 551 Set set = (Set) actionDecision.getValues(); 552 if ( (set != null) ) { 553 if ( set.contains(falseValue) ) { 554 actionAllowed = false; 555 } else if ( set.contains(trueValue) ) { 556 actionAllowed = true; 557 } 558 } 559 } 560 561 return actionAllowed; 562 } 563 564 private void padEnvParameters(SSOToken token, String resourceName, 565 String actionName, Map envParameters) throws PolicyException, SSOException { 566 if ((resourceName == null) || (resourceName.trim().length() == 0)) { 567 resourceName = Rule.EMPTY_RESOURCE_NAME; 568 } 569 570 Set originalResourceNames = new HashSet(2); 571 originalResourceNames.add(resourceName); 572 573 String realmName = LDAPUtils.isDN(realm) ? 574 DNMapper.orgNameToRealmName(realm) : realm; 575 try { 576 Application appl = ApplicationManager.getApplication( 577 PolicyConstants.SUPER_ADMIN_SUBJECT, 578 realmName, applicationName); 579 resourceName = appl.getResourceComparator().canonicalize( 580 resourceName); 581 } catch (EntitlementException e) { 582 throw new PolicyException(e); 583 } 584 //Add request resourceName and request actionNames to the envParameters 585 //so that Condition(s)/ResponseProvider(s) can use them if necessary 586 Set resourceNames = new HashSet(2); 587 resourceNames.add(resourceName); 588 589 Set actions = new HashSet(); 590 if (actionName != null) { 591 actions.add(actionName); 592 } else { 593 Set actionNames = serviceType.getActionNames(); 594 if (actionNames != null) { 595 actions.addAll(actionNames); 596 } 597 } 598 599 envParameters.put(SUN_AM_REQUESTED_RESOURCE, resourceNames); 600 envParameters.put(SUN_AM_ORIGINAL_REQUESTED_RESOURCE, 601 originalResourceNames); 602 envParameters.put(SUN_AM_REQUESTED_ACTIONS, actions); 603 envParameters.put(REALM_DN, asSet(policyManager.getOrganizationDN())); 604 605 // Fix for OPENAM-811 606 String userid = null; 607 Principal principal = token.getPrincipal(); 608 if (principal != null) { 609 userid = principal.getName(); 610 } 611 if ((userid != null) && (userid.length() != 0)) { 612 HashSet<String> set = new HashSet<String>(); 613 set.add(userid); 614 // Required by the AMIdentityMembershipCondition 615 envParameters.put(Condition.INVOCATOR_PRINCIPAL_UUID, set); 616 } else { 617 if (DEBUG.messageEnabled()) { 618 DEBUG.message("PolicyEvaluator.padEnvParameters() unable to get userid from token."); 619 } 620 } 621 } 622 623 private boolean isAllowedE(SSOToken token, String resourceName, 624 String actionName, Map envParameters) throws SSOException, 625 PolicyException { 626 627 if ((envParameters == null) || envParameters.isEmpty()) { 628 envParameters = new HashMap(); 629 } 630 631 padEnvParameters(token, resourceName, actionName, envParameters); 632 633 ActionSchema schema = serviceType.getActionSchema(actionName); 634 635 if (!AttributeSchema.Syntax.BOOLEAN.equals(schema.getSyntax())) { 636 String objs[] = {actionName}; 637 throw new PolicyException( 638 ResBundleUtils.rbName, 639 "action_does_not_have_boolean_syntax", objs, null); 640 } 641 642 HashSet actions = new HashSet(2); 643 actions.add(actionName); 644 SSOToken adminSSOToken = (SSOToken) AccessController.doPrivileged( 645 AdminTokenAction.getInstance()); 646 647 try { 648 Subject adminSubject = SubjectUtils.createSubject(token); 649 650 Entitlement entitlement = new Entitlement(serviceTypeName, resourceName, actions); 651 entitlement.canonicalizeResources(adminSubject, realm); 652 653 Evaluator eval = new Evaluator(adminSubject, applicationName); 654 return eval.hasEntitlement(realm, SubjectUtils.createSubject(token), entitlement, envParameters); 655 656 } catch (EntitlementException e) { 657 throw new PolicyException(e); 658 } 659 } 660 661 private String getActionFalseBooleanValue(String actionName) 662 throws InvalidNameException { 663 664 if (serviceType == null) { 665 return Boolean.FALSE.toString(); 666 } 667 668 ActionSchema schema = serviceType.getActionSchema(actionName); 669 670 // Cache the false values for the action names 671 if (booleanActionNameFalseValues == null) { 672 booleanActionNameFalseValues = new HashMap(10); 673 } 674 String falseValue = null; 675 if ((falseValue = (String) 676 booleanActionNameFalseValues.get(actionName)) == null) { 677 falseValue = schema.getFalseValue(); 678 // Add it to the cache 679 booleanActionNameFalseValues.put(actionName, falseValue); 680 } 681 return falseValue; 682 } 683 684 private String getActionTrueBooleanValue(String actionName) 685 throws InvalidNameException { 686 687 if (serviceType == null) { 688 return Boolean.TRUE.toString(); 689 } 690 691 ActionSchema schema = serviceType.getActionSchema(actionName); 692 693 // Cache the true values for the action names 694 if (booleanActionNameTrueValues == null) { 695 booleanActionNameTrueValues = new HashMap(10); 696 } 697 698 String trueValue = null; 699 if ((trueValue = (String) 700 booleanActionNameTrueValues.get(actionName)) == null) { 701 trueValue = schema.getTrueValue(); 702 booleanActionNameTrueValues.put(actionName, trueValue); 703 } 704 705 return trueValue; 706 } 707 708 /** 709 * Evaluates privileges of the user to perform the specified actions 710 * on the specified resource. 711 * 712 * @param token single sign on token of the user evaluating policies 713 * @param resourceName name of the resource the user is trying to access 714 * @param actionNames a <code>Set</code> of <code>Sting</code> objects 715 * representing names of the actions the user is trying to perform on 716 * the resource 717 * 718 * @return policy decision 719 * 720 * @exception SSOException single-sign-on token invalid or expired 721 * @exception PolicyException for any other abnormal condition. 722 */ 723 public PolicyDecision getPolicyDecision(SSOToken token, String resourceName, 724 Set actionNames) throws PolicyException, SSOException { 725 return getPolicyDecision(token, resourceName, actionNames, null); 726 } 727 728 729 /** 730 * Evaluates privileges of the user to perform the specified actions 731 * on the specified resource. The evaluation depends on user's 732 * application environment parameters. 733 * 734 * @param token single sign on token of the user evaluating policies 735 * @param resourceName name of the resource the user is trying to access 736 * @param actionNames <code>Set</code> of names(<code>String</code>) of 737 * the action the user is trying to perform on the resource 738 * @param envParameters <code>Map</code> of run-time environment parameters 739 * 740 * @return policy decision 741 * 742 * @throws SSOException single-sign-on token invalid or expired 743 * @throws PolicyException for any other abnormal condition 744 * 745 * @supported.api 746 */ 747 public PolicyDecision getPolicyDecision( 748 SSOToken token, String resourceName, Set actionNames, 749 Map envParameters) throws SSOException, PolicyException { 750 if ( (resourceName == null) || (resourceName.length() == 0) ) { 751 resourceName = Rule.EMPTY_RESOURCE_NAME; 752 } 753 754 Set originalResourceNames = new HashSet(2); 755 originalResourceNames.add(resourceName); 756 757 resourceName = serviceType.canonicalize(resourceName); 758 759 //Add request resourceName and request actionNames to the envParameters 760 //so that Condition(s)/ResponseProvider(s) can use them if necessary 761 Set resourceNames = new HashSet(2); 762 resourceNames.add(resourceName); 763 764 /* compute for all action names if passed in actionNames is 765 null or empty */ 766 if ( (actionNames == null) || (actionNames.isEmpty()) ) { 767 actionNames = serviceType.getActionNames(); 768 } 769 770 Set actions = new HashSet(); 771 if (actionNames != null) { 772 actions.addAll(actionNames); 773 } 774 775 /* 776 * We create new HashMap in place of empty map since 777 * Collections.EMPTY_MAP can not be modified 778 */ 779 if ((envParameters == null) || envParameters.isEmpty()) { 780 envParameters = new HashMap(); 781 } 782 783 envParameters.put(SUN_AM_REQUESTED_RESOURCE, resourceNames); 784 envParameters.put(SUN_AM_ORIGINAL_REQUESTED_RESOURCE, 785 originalResourceNames); 786 envParameters.put(SUN_AM_REQUESTED_ACTIONS, actions); 787 envParameters.put(REALM_DN, asSet(policyManager.getOrganizationDN())); 788 789 return getPolicyDecision(token, resourceName, actionNames, 790 envParameters, new HashSet()); 791 } 792 793 /** 794 * Evaluates privileges of the user to perform the specified actions 795 * on the specified resource. The evaluation depends on user's 796 * application environment parameters. 797 * 798 * @param token single sign on token of the user evaluating policies 799 * @param resourceName name of the resource the user is trying to access 800 * @param actionNames <code>Set</code> of names(<code>String</code>) of the 801 * action the user is trying to perform on the resource. 802 * @param envParameters run-time environment parameters 803 * @param visitedOrgs names of organizations that have been already visited 804 * during policy evaluation for this request 805 * 806 * @return policy decision 807 * 808 * @exception SSOException single-sign-on token invalid or expired 809 * @exception PolicyException if any policy evaluation error. 810 */ 811 private PolicyDecision getPolicyDecision( 812 SSOToken token, String resourceName, Set actionNames, 813 Map envParameters, Set visitedOrgs) 814 throws PolicyException, SSOException { 815 if (MonitoringUtil.isRunning()) { 816 SsoServerPolicySvcImpl sspsi = 817 Agent.getPolicySvcMBean(); 818 sspsi.incPolicyEvalsIn(); 819 } 820 821 try { 822 return (PolicyManager.isMigratedToEntitlementService()) ? 823 getPolicyDecisionE(token, resourceName, actionNames, 824 envParameters) : getPolicyDecisionO(token, resourceName, 825 actionNames, 826 envParameters, visitedOrgs); 827 } finally { 828 if (MonitoringUtil.isRunning()) { 829 SsoServerPolicySvcImpl sspsi = 830 Agent.getPolicySvcMBean(); 831 sspsi.incPolicyEvalsOut(); 832 } 833 } 834 } 835 836 837 /** 838 * Evaluates privileges of the user to perform the specified actions 839 * on the specified resource. The evaluation depends on user's 840 * application environment parameters. 841 * 842 * @param token single sign on token of the user evaluating policies 843 * @param resourceName name of the resource the user is trying to access 844 * @param actionNames <code>Set</code> of names(<code>String</code>) of the 845 * action the user is trying to perform on the resource. 846 * @param envParameters run-time environment parameters 847 * @return policy decision 848 * 849 * @exception SSOException single-sign-on token invalid or expired 850 * @exception PolicyException if any policy evaluation error. 851 */ 852 private PolicyDecision getPolicyDecisionE( 853 SSOToken token, String resourceName, Set actionNames, 854 Map envParameters) 855 throws PolicyException, SSOException { 856 857 if ( DEBUG.messageEnabled() ) { 858 DEBUG.message("Evaluating policies at org " + orgName); 859 } 860 861 /* compute for all action names if passed in actionNames is 862 null or empty */ 863 if ( (actionNames == null) || (actionNames.isEmpty()) ) { 864 actionNames = serviceType.getActionNames(); 865 } 866 867 SSOToken adminSSOToken = (SSOToken) AccessController.doPrivileged( 868 AdminTokenAction.getInstance()); 869 870 try { 871 Evaluator eval = new Evaluator( 872 SubjectUtils.createSubject(adminSSOToken), applicationName); 873 Subject sbj = (token != null) ? SubjectUtils.createSubject(token) : 874 null; 875 List<Entitlement> entitlements = eval.evaluate( 876 orgName, sbj, resourceName, envParameters, false); 877 if ((entitlements != null) && !entitlements.isEmpty()) { 878 Entitlement e = entitlements.iterator().next(); 879 return (entitlementToPolicyDecision(e, actionNames)); 880 } 881 } catch (EntitlementException e) { 882 throw new PolicyException(e); 883 } 884 return (new PolicyDecision()); 885 } 886 887 private PolicyDecision getPolicyDecisionO( 888 SSOToken token, String resourceName, Set actionNames, 889 Map envParameters, Set visitedOrgs) 890 throws PolicyException, SSOException { 891 892 if ( DEBUG.messageEnabled() ) { 893 DEBUG.message("Evaluating policies at org " + orgName); 894 } 895 896 /* compute for all action names if passed in actionNames is 897 null or empty */ 898 if ( (actionNames == null) || (actionNames.isEmpty()) ) { 899 actionNames = serviceType.getActionNames(); 900 } 901 902 Set actions = new HashSet(); 903 actions.addAll(actionNames); 904 905 PolicyDecision mergedPolicyDecision = null; 906 Set policyNameSet = null; 907 Set toRemovePolicyNameSet = null; 908 policyNameSet = resourceIndexManager.getPolicyNames( 909 serviceType, resourceName, INCLUDE_SUPER_RESOURCE_POLCIES); 910 if ( DEBUG.messageEnabled() ) { 911 String tokenPrincipal = 912 (token != null) ? token.getPrincipal().getName() 913 : PolicyUtils.EMPTY_STRING; 914 DEBUG.message(new StringBuffer("at PolicyEvaluator") 915 .append(".getPolicyDecision()") 916 .append(" principal, resource name, ") 917 .append("action names, policy names,") 918 .append(" orgName =") 919 .append(tokenPrincipal) .append(", ") 920 .append(resourceName) .append(", ") 921 .append(actionNames) .append(", ") 922 .append(policyNameSet).append(", ") 923 .append(orgName).toString()); 924 } 925 Iterator policyIter = policyNameSet.iterator(); 926 while ( policyIter.hasNext() ) { 927 String policyName = (String) policyIter.next(); 928 Policy policy = policyManager.getPolicy(policyName, 929 USE_POLICY_CACHE); 930 if ( policy != null && policy.isActive()) { 931 //policy might have been removed or inactivated 932 PolicyDecision policyDecision = policy.getPolicyDecision(token, 933 serviceTypeName, resourceName, actions, envParameters); 934 if (!policy.isReferralPolicy() && policyDecision.hasAdvices()) { 935 addAdvice(policyDecision, ADVICING_ORGANIZATION, orgName); 936 } 937 938 // Let us log all policy evaluation results 939 if (PolicyUtils.logStatus && (token != null)) { 940 String decision = policyDecision.toString(); 941 if (decision != null && decision.length() != 0) { 942 String[] objs = { policyName, orgName, serviceTypeName, 943 resourceName, actionNames.toString(), 944 decision }; 945 PolicyUtils.logAccessMessage("POLICY_EVALUATION", 946 objs, token, serviceTypeName); 947 } 948 } 949 if ( mergedPolicyDecision == null ) { 950 mergedPolicyDecision = policyDecision; 951 } else { 952 mergePolicyDecisions(serviceType, policyDecision, 953 mergedPolicyDecision); 954 } 955 956 if (!PolicyConfig.continueEvaluationOnDenyDecision()) { 957 actions.removeAll(getFinalizedActions(serviceType, 958 mergedPolicyDecision)); 959 } 960 961 if ( actions.isEmpty() ) { 962 break; 963 } 964 } else { // add policy names to toRemovePolicyNameSet 965 if (toRemovePolicyNameSet == null) { 966 toRemovePolicyNameSet = new HashSet(); 967 } 968 toRemovePolicyNameSet.add(policyName); 969 if ( DEBUG.messageEnabled() ) { 970 DEBUG.message("PolicyEvaluator.getPolicyDecision():" 971 +policyName+ " is inactive or non-existent"); 972 } 973 } 974 } 975 976 // remove inactive/missing policies from policyNameSet 977 if (toRemovePolicyNameSet != null) { 978 policyNameSet.removeAll(toRemovePolicyNameSet); 979 } 980 981 Set orgsToVisit = getOrgsToVisit(policyNameSet); 982 983 if (PolicyConfig.orgAliasMappedResourcesEnabled() 984 && PolicyManager.WEB_AGENT_SERVICE.equalsIgnoreCase( 985 serviceTypeName)) { 986 String orgAlias = policyManager.getOrgAliasWithResource( 987 resourceName); 988 if (orgAlias != null) { 989 String orgWithAlias = policyManager.getOrgNameWithAlias( 990 orgAlias); 991 if (orgWithAlias != null) { 992 if ( DEBUG.messageEnabled() ) { 993 DEBUG.message("PolicyEvaluator.getPolicyDecision():" 994 + "adding orgWithAlias to orgsToVisit=" 995 + orgWithAlias); 996 } 997 orgsToVisit.add(orgWithAlias); 998 } 999 } 1000 } 1001 1002 if ( DEBUG.messageEnabled() ) { 1003 DEBUG.message(new StringBuffer("at PolicyEvaluator") 1004 .append(".getPolicyDecision()") 1005 .append(" orgsToVist=").append(orgsToVisit.toString()) 1006 .toString()); 1007 } 1008 orgsToVisit.removeAll(visitedOrgs); 1009 if ( DEBUG.messageEnabled() ) { 1010 DEBUG.message(new StringBuffer("at PolicyEvaluator") 1011 .append(".getPolicyDecision()") 1012 .append(" orgsToVist(after removing already visited orgs=") 1013 .append(orgsToVisit.toString()) 1014 .toString() ); 1015 } 1016 while ( !orgsToVisit.isEmpty() && !actions.isEmpty() ) { 1017 String orgToVisit = (String) orgsToVisit.iterator().next(); 1018 orgsToVisit.remove(orgToVisit); 1019 visitedOrgs.add(orgToVisit); 1020 try { 1021 // need to use admin sso token here. Need all privileges to 1022 // check for the organzation 1023 policyManager.verifyOrgName(orgToVisit); 1024 } catch (NameNotFoundException nnfe) { 1025 if( DEBUG.warningEnabled()) { 1026 DEBUG.warning("Organization does not exist - " 1027 + "skipping referral to " + orgToVisit); 1028 } 1029 continue; 1030 } 1031 PolicyEvaluator pe = new PolicyEvaluator(orgToVisit, 1032 serviceTypeName); 1033 /** 1034 * save current realm DN before passing control down to sub-realm 1035 */ 1036 Set<String> savedRealmDn = (Set<String>) envParameters.get(REALM_DN); 1037 // Update env to point to the realm policy config data. 1038 envParameters.put(REALM_DN, asSet(DNMapper.orgNameToDN(orgToVisit))); 1039 PolicyDecision policyDecision 1040 = pe.getPolicyDecision(token, resourceName, actionNames, 1041 envParameters,visitedOrgs); 1042 // restore back the policy config data for the parent realm 1043 envParameters.put(REALM_DN, savedRealmDn); 1044 if ( mergedPolicyDecision == null ) { 1045 mergedPolicyDecision = policyDecision; 1046 } else { 1047 mergePolicyDecisions(serviceType, policyDecision, 1048 mergedPolicyDecision); 1049 } 1050 if (!PolicyConfig.continueEvaluationOnDenyDecision()) { 1051 actions.removeAll(getFinalizedActions(serviceType, 1052 mergedPolicyDecision)); 1053 } 1054 } 1055 1056 if ( mergedPolicyDecision == null ) { 1057 mergedPolicyDecision = new PolicyDecision(); 1058 } 1059 1060 return mergedPolicyDecision; 1061 } 1062 1063 /** 1064 * Gets protected resources for a user identified by single sign on token 1065 * Conditions defined in the policies are ignored while 1066 * computing protected resources. 1067 * Only resources that are sub resources of the given 1068 * <code>rootResource</code> or equal to the given <code>rootResource</code> 1069 * would be returned. 1070 * If all policies applicable to a resource are 1071 * only referral policies, no <code>ProtectedResource</code> would be 1072 * returned for such a resource. 1073 * 1074 * @param token single sign on token of the user 1075 * @param rootResource only resources that are sub resources of the 1076 * given <code>rootResource</code> or equal to the 1077 * given <code>rootResource</code> would be returned 1078 * <code>rootResource</code> would be returned. 1079 * If <code>PolicyEvaluator.ALL_RESOURCES</code> is 1080 * passed as <code>rootResource</code>, resources under 1081 * all root resources of the service 1082 * type are considered while computing protected 1083 * resources. 1084 * @return <code>Set</code> of protected resources. The set 1085 * contains <code>ProtectedResource</code> objects. 1086 * 1087 * @throws SSOException if single sign on token is invalid 1088 * @throws PolicyException for any other abnormal condition 1089 * @see ProtectedResource 1090 * 1091 * @supported.api 1092 * 1093 */ 1094 public Set getProtectedResourcesIgnoreConditions( 1095 SSOToken token, String rootResource) 1096 throws SSOException, PolicyException 1097 { 1098 if ( (rootResource == null) || (rootResource.equals("")) ) { 1099 rootResource = EMPTY_RESOURCE_NAME; 1100 } 1101 Set protectedResources = new HashSet(); 1102 Set topLevelResources = null; 1103 if (rootResource.equals(ALL_RESOURCES)) { 1104 topLevelResources 1105 = resourceIndexManager.getTopLevelResourceNames( 1106 serviceType); 1107 } else { 1108 topLevelResources = new HashSet(); 1109 topLevelResources.add(rootResource); 1110 } 1111 Iterator iter = topLevelResources.iterator(); 1112 while (iter.hasNext()) { 1113 String topLevelResource = (String)iter.next(); 1114 Set resourceNames 1115 = getResourceNames(token, topLevelResource, true); 1116 Iterator resourceIter = resourceNames.iterator(); 1117 while (resourceIter.hasNext()) { 1118 String resourceName = (String)resourceIter.next(); 1119 Set protectingPolicies 1120 = getProtectingPolicies(token, resourceName); 1121 if ((protectingPolicies != null) 1122 && (!protectingPolicies.isEmpty())) { 1123 boolean allReferralPolicies = true; 1124 Iterator iter1 = protectingPolicies.iterator(); 1125 while (iter1.hasNext()){ 1126 Policy policy = (Policy)iter1.next(); 1127 if (!policy.isReferralPolicy()) { 1128 allReferralPolicies = false; 1129 break; 1130 } 1131 } 1132 if (!allReferralPolicies) { 1133 protectedResources.add( 1134 new ProtectedResource(resourceName, 1135 protectingPolicies)); 1136 } 1137 } 1138 } 1139 } 1140 return protectedResources; 1141 } 1142 1143 /** 1144 * Gets policies applicable to user that are protecting 1145 * the specified resource. 1146 * 1147 * @param token single sign on token of the user evaluating policies 1148 * @param resourceName name of the resource the user is trying to access 1149 * 1150 * @return set of policies applicable to user that are protecting the 1151 * specified resource 1152 * 1153 * @throws PolicyException policy exception coming from policy framework 1154 * @throws SSOException single-sign-on token invalid or expired 1155 * 1156 */ 1157 Set getProtectingPolicies( 1158 SSOToken token, String resourceName) 1159 throws PolicyException, SSOException 1160 { 1161 return getProtectingPolicies(token, resourceName, new HashSet()); 1162 } 1163 1164 /** 1165 * Gets policies applicable to user that are protecting 1166 * the specified resource. 1167 * 1168 * @param token single sign on token of the user evaluating policies 1169 * @param resourceName name of the resource the user is trying to access 1170 * 1171 * @param visitedOrgs names of organizations that have been 1172 * already visited during evaluation for this request 1173 * @return set of policies applicable to user that are protecting the 1174 * specified resource 1175 * 1176 * @throws PolicyException policy exception coming from policy framework 1177 * @throws SSOException single-sign-on token invalid or expired 1178 * 1179 */ 1180 private Set getProtectingPolicies( 1181 SSOToken token, String resourceName, Set visitedOrgs) 1182 throws PolicyException, SSOException 1183 { 1184 1185 Set protectingPolicies = new HashSet(); 1186 1187 1188 // false - do not include super resource policies 1189 // includes EXACT_MATCH and WILD_CARD_MATCH 1190 Set policyNameSet = resourceIndexManager.getPolicyNames( 1191 serviceType, resourceName, false); 1192 Set toRemovePolicyNameSet = null; 1193 if ( DEBUG.messageEnabled() ) { 1194 String tokenPrincipal = 1195 (token != null) ? token.getPrincipal().getName() 1196 : PolicyUtils.EMPTY_STRING; 1197 DEBUG.message(new StringBuffer( 1198 "at PolicyEvaluator.getProtectingPolicies()") 1199 .append(" principal, resource name, policy names,") 1200 .append(" orgName =") 1201 .append(tokenPrincipal) .append(", ") 1202 .append(resourceName) .append(", ") 1203 .append(policyNameSet).append(", ") 1204 .append(orgName).toString()); 1205 } 1206 Iterator policyIter = policyNameSet.iterator(); 1207 while ( policyIter.hasNext() ) { 1208 String policyName = (String) policyIter.next(); 1209 Policy policy = policyManager.getPolicy(policyName); 1210 if ( policy != null && policy.isActive()) { 1211 //policy might have been removed or inactivated 1212 if (!policy.isReferralPolicy()) { 1213 if (policy.isApplicableToUser(token)) { 1214 policy.setOrganizationName(orgName); 1215 protectingPolicies.add(policy); 1216 } 1217 } else { 1218 policy.setOrganizationName(orgName); 1219 protectingPolicies.add(policy); 1220 } 1221 } else { // add policy names to toRemovePolicyNameSet 1222 if (toRemovePolicyNameSet == null) { 1223 toRemovePolicyNameSet = new HashSet(); 1224 } 1225 toRemovePolicyNameSet.add(policyName); 1226 if ( DEBUG.messageEnabled() ) { 1227 DEBUG.message("PolicyEvaluator.getProtectingPolicies():" 1228 +policyName+ " is inactive or non-existent"); 1229 } 1230 } 1231 } 1232 1233 // remove inactive/missing policies from policyNameSet 1234 if (toRemovePolicyNameSet != null) { 1235 policyNameSet.removeAll(toRemovePolicyNameSet); 1236 } 1237 1238 //include super resource policies provided they are referral policies 1239 policyNameSet = resourceIndexManager.getSuperResourcePolicyNames( 1240 serviceType, resourceName); 1241 if (toRemovePolicyNameSet != null) { 1242 toRemovePolicyNameSet.clear(); 1243 } 1244 policyIter = policyNameSet.iterator(); 1245 while ( policyIter.hasNext() ) { 1246 String policyName = (String) policyIter.next(); 1247 Policy policy = policyManager.getPolicy(policyName); 1248 if ( policy != null && policy.isActive()) { 1249 //policy might have been removed or inactivated 1250 if (policy.isReferralPolicy()) { 1251 policy.setOrganizationName(orgName); 1252 protectingPolicies.add(policy); 1253 } 1254 } else { // add policy names to toRemovePolicyNameSet 1255 if (toRemovePolicyNameSet == null) { 1256 toRemovePolicyNameSet = new HashSet(); 1257 } 1258 toRemovePolicyNameSet.add(policyName); 1259 if ( DEBUG.messageEnabled() ) { 1260 DEBUG.message("PolicyEvaluator.getProtectingPolicies():" 1261 +policyName+ " is inactive or non-existent"); 1262 } 1263 } 1264 } 1265 // remove inactive/missing policies from policyNameSet 1266 if (toRemovePolicyNameSet != null) { 1267 policyNameSet.removeAll(toRemovePolicyNameSet); 1268 } 1269 1270 Set orgsToVisit = getOrgsToVisit(policyNameSet); 1271 if ( DEBUG.messageEnabled() ) { 1272 DEBUG.message(new StringBuffer( 1273 "at PolicyEvaluator.getProtectingPolicies()") 1274 .append(" orgsToVist=").append(orgsToVisit.toString()) 1275 .toString()); 1276 } 1277 1278 if (PolicyConfig.orgAliasMappedResourcesEnabled() 1279 && PolicyManager.WEB_AGENT_SERVICE.equalsIgnoreCase( 1280 serviceTypeName)) { 1281 String orgAlias = policyManager.getOrgAliasWithResource( 1282 resourceName); 1283 if (orgAlias != null) { 1284 String orgWithAlias = policyManager.getOrgNameWithAlias( 1285 orgAlias); 1286 if (orgWithAlias != null) { 1287 if ( DEBUG.messageEnabled() ) { 1288 DEBUG.message("PolicyEvaluator.getProtectingPolicies():" 1289 + "adding orgWithAlias to orgsToVisit=" 1290 + orgWithAlias); 1291 } 1292 orgsToVisit.add(orgWithAlias); 1293 } 1294 } 1295 } 1296 1297 orgsToVisit.removeAll(visitedOrgs); 1298 if ( DEBUG.messageEnabled() ) { 1299 DEBUG.message(new StringBuffer( 1300 "at PolicyEvaluator.getProtectingPolicies()") 1301 .append(" orgsToVist(after removing already visited orgs=") 1302 .append(orgsToVisit.toString()) 1303 .toString() ); 1304 } 1305 while (!orgsToVisit.isEmpty() ) { 1306 String orgToVisit = (String) orgsToVisit.iterator().next(); 1307 orgsToVisit.remove(orgToVisit); 1308 visitedOrgs.add(orgToVisit); 1309 try { 1310 // need to use admin sso token here. Need all privileges to 1311 // check for the organzation 1312 policyManager.verifyOrgName(orgToVisit); 1313 } catch (NameNotFoundException nnfe) { 1314 if( DEBUG.warningEnabled()) { 1315 DEBUG.warning("Organization does not exist - " 1316 + "skipping referral to " + orgToVisit); 1317 } 1318 continue; 1319 } 1320 PolicyEvaluator pe 1321 = new PolicyEvaluator(orgToVisit, serviceTypeName); 1322 Set pp = pe.getProtectingPolicies(token, resourceName, 1323 visitedOrgs); 1324 protectingPolicies.addAll(pp); 1325 } 1326 1327 String principalName = (token != null) 1328 ? token.getPrincipal().getName() 1329 : PolicyUtils.EMPTY_STRING; 1330 1331 StringBuffer sb = null; 1332 String pp = null; 1333 if (PolicyManager.debug.messageEnabled() || PolicyUtils.logStatus) { 1334 sb = new StringBuffer(); 1335 Iterator pIter = protectingPolicies.iterator(); 1336 while (pIter.hasNext()) { 1337 Policy policy = (Policy)pIter.next(); 1338 sb.append(policy.getOrganizationName()).append(":") 1339 .append(policy.getName()) .append(","); 1340 } 1341 pp = sb.toString(); 1342 } 1343 1344 1345 if (PolicyManager.debug.messageEnabled()) { 1346 PolicyManager.debug.message("Computed policies " 1347 + " protecting resource " 1348 + resourceName 1349 + "for principal:" + principalName + " " + pp); 1350 } 1351 1352 if (PolicyUtils.logStatus && (token != null)) { 1353 String[] objs = { principalName, 1354 resourceName, pp }; 1355 PolicyUtils.logAccessMessage("PROTECTED_RESOURCES", objs, token, 1356 serviceTypeName); 1357 } 1358 return protectingPolicies; 1359 } 1360 1361 /** 1362 * Gets resource result objects given a resource name. The set 1363 * contains <code>ResourceResult</code> objects for all resources 1364 * that would affect policy decisions for any resource associated with the 1365 * argument resource name. To determine whether to include the 1366 * <code>ResourceResult</code> of a resource, we compare argument resource 1367 * name and policy resource name, treating wild characters in the policy 1368 * resource name as wild. If the comparison resulted in 1369 * <code>EXACT_MATCH</code>, <code>WILD_CARD_MACTH</code> or 1370 * <code>SUB_RESOURCE_MACTH</code>, the resource result would be 1371 * included. 1372 * 1373 * @param token single sign on token of the user evaluating policies 1374 * @param resourceName name of the resource 1375 * @param scope indicates whether to compute the resource result based on 1376 * the policy decision for only the <code>resourceName</code> 1377 * or all the resources associated with the resource name. 1378 * The valid scope values are: 1379 * <ul> 1380 * <li><code>ResourceResult.SUBTREE_SCOPE</code> 1381 * <li><code>ResourceResult.STRICT_SUBTREE_SCOPE</code> 1382 * <li><code>ResourceResult.SELF_SCOPE</code> 1383 * <ul> 1384 * If the scope is <code>ResourceResult.SUBTREE_SCOPE</code>, 1385 * the method will return a set of <code>ResourceResult</code> 1386 * objects, one of them for the <code>resourceName</code> and 1387 * its sub resources; the others are for resources that match 1388 * the <code>resourceName</code> by wildcard. If the scope is 1389 * <code>ResourceResult.STRICT_SUBTREE_SCOPE</code>, the 1390 * method will return a set object that contains one 1391 * <code>ResourceResult</code> object. The 1392 * <code>ResourceResult</code> contains the policy decisions 1393 * regarding the <code>resourceName</code> and its sub 1394 * resources. If the scope is 1395 * <code>ResourceResult.SELF_SCOPE</code>, the method will 1396 * return a set object that contains one 1397 * <code>ResourceResult</code> object. 1398 * The <code>ResourceResult</code> contains the policy decision 1399 * regarding the <code>resourceName</code> only. 1400 * 1401 * @param envParameters run-time environment parameters 1402 * 1403 * @return set of <code>ResourceResult</code> objects 1404 * 1405 * @throws SSOException if <code>token</code> is invalid 1406 * @throws PolicyException for any other abnormal condition 1407 * 1408 * @see ResourceMatch#EXACT_MATCH 1409 * @see ResourceMatch#SUB_RESOURCE_MATCH 1410 * @see ResourceMatch#WILDCARD_MATCH 1411 * @see ResourceResult#SUBTREE_SCOPE 1412 * @see ResourceResult#STRICT_SUBTREE_SCOPE 1413 * @see ResourceResult#SELF_SCOPE 1414 * 1415 * 1416 * @supported.api 1417 */ 1418 public Set getResourceResults(SSOToken token, 1419 String resourceName, String scope, Map envParameters) 1420 throws SSOException, PolicyException { 1421 return (PolicyManager.isMigratedToEntitlementService()) ? 1422 getResourceResultsE(token, resourceName, scope, envParameters) : 1423 getResourceResultsO(token, resourceName, scope, envParameters); 1424 } 1425 1426 private Set getResourceResultsO(SSOToken token, 1427 String resourceName, String scope, Map envParameters) 1428 throws SSOException, PolicyException { 1429 Set resultsSet; 1430 1431 if (ResourceResult.SUBTREE_SCOPE.equals(scope)) { 1432 resultsSet = getResourceResultTree(token, resourceName, scope, 1433 envParameters).getResourceResults(); 1434 } else if (ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope) 1435 || ResourceResult.SELF_SCOPE.equals(scope)) { 1436 ResourceResult result = getResourceResultTree(token, resourceName, 1437 scope, envParameters); 1438 resultsSet = new HashSet(); 1439 resultsSet.add(result); 1440 } else { 1441 DEBUG.error("PolicyEvaluator: invalid request scope: " + scope); 1442 String objs[] = {scope}; 1443 throw new PolicyException(ResBundleUtils.rbName, 1444 "invalid_request_scope", objs, null); 1445 } 1446 1447 return resultsSet; 1448 } 1449 1450 private Set getResourceResultsE(SSOToken token, 1451 String resourceName, String scope, Map envParameters) 1452 throws SSOException, PolicyException { 1453 1454 if ((envParameters == null) || envParameters.isEmpty()) { 1455 envParameters = new HashMap(); 1456 } 1457 padEnvParameters(token, resourceName, null, envParameters); 1458 1459 Set resultsSet; 1460 boolean subTreeSearch = false; 1461 1462 if (ResourceResult.SUBTREE_SCOPE.equals(scope)) { 1463 subTreeSearch = true; 1464 //resultsSet = getResourceResultTree(token, resourceName, scope, 1465 // envParameters).getResourceResults(); 1466 } else if (ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope) 1467 || ResourceResult.SELF_SCOPE.equals(scope)) { 1468 /* 1469 ResourceResult result = getResourceResultTree(token, resourceName, 1470 scope, envParameters); 1471 resultsSet = new HashSet(); 1472 resultsSet.add(result);*/ 1473 } else { 1474 DEBUG.error("PolicyEvaluator: invalid request scope: " + scope); 1475 String objs[] = {scope}; 1476 throw new PolicyException(ResBundleUtils.rbName, 1477 "invalid_request_scope", objs, null); 1478 } 1479 1480 SSOToken adminSSOToken = (SSOToken)AccessController.doPrivileged( 1481 AdminTokenAction.getInstance()); 1482 1483 try { 1484 // Parse the resource name before proceeding. 1485 resourceName = serviceType.canonicalize(resourceName); 1486 1487 Subject userSubject = SubjectUtils.createSubject(token); 1488 Evaluator eval = new Evaluator( 1489 SubjectUtils.createSubject(adminSSOToken), applicationName); 1490 1491 List<Entitlement> entitlements = eval.evaluate( 1492 realm, userSubject, resourceName, 1493 envParameters, subTreeSearch); 1494 resultsSet = new HashSet(); 1495 1496 if (!entitlements.isEmpty()) { 1497 if (!subTreeSearch) { 1498 resultsSet.add(entitlementToResourceResult( 1499 (Entitlement)entitlements.iterator().next())); 1500 } else { 1501 ResourceResult virtualResourceResult = 1502 new ResourceResult(ResourceResult.VIRTUAL_ROOT, 1503 new PolicyDecision()); 1504 for (Entitlement ent : entitlements ) { 1505 ResourceResult r = entitlementToResourceResult(ent); 1506 virtualResourceResult.addResourceResult(r, serviceType); 1507 } 1508 1509 resultsSet.addAll( 1510 virtualResourceResult.getResourceResults()); 1511 } 1512 } 1513 } catch (Exception e) { 1514 DEBUG.error("Error in getResourceResults", e); 1515 throw new PolicyException(e.getMessage()); //TOFIX 1516 } 1517 1518 return resultsSet; 1519 } 1520 1521 1522 private ResourceResult entitlementToResourceResult( 1523 Entitlement entitlement 1524 ) throws PolicyException { 1525 return new ResourceResult(entitlement.getRequestedResourceName(), 1526 entitlementToPolicyDecision(entitlement, Collections.EMPTY_SET)); 1527 } 1528 1529 private PolicyDecision entitlementToPolicyDecision( 1530 Entitlement entitlement, 1531 Set<String> actionNames 1532 ) throws PolicyException { 1533 PolicyDecision pd = new PolicyDecision(); 1534 Map actionValues = entitlement.getActionValues(); 1535 1536 if ((actionValues != null) && !actionValues.isEmpty()) { 1537 for (Iterator i = actionValues.keySet().iterator(); i.hasNext();) { 1538 String actionName = (String) i.next(); 1539 Set set = new HashSet(); 1540 boolean isBooleanAction = true; 1541 if (serviceType != null) { 1542 ActionSchema as = null; 1543 try { 1544 as = serviceType.getActionSchema(actionName); 1545 } catch (InvalidNameException inex) { 1546 if (DEBUG.warningEnabled()) { 1547 DEBUG.warning("PolicyEvaluator." + 1548 "entitlementToPolicyDecision:", inex); 1549 } 1550 } 1551 isBooleanAction = (as != null) && 1552 as.getSyntax().equals(AttributeSchema.Syntax.BOOLEAN); 1553 } 1554 1555 if (isBooleanAction) { 1556 1557 Boolean values = (Boolean) actionValues.get(actionName); 1558 1559 if (values.booleanValue()) { 1560 set.add(getActionTrueBooleanValue(actionName)); 1561 } else { 1562 set.add(getActionFalseBooleanValue(actionName)); 1563 } 1564 } else { 1565 // Parse the action name to get the value 1566 int index = actionName.indexOf('_'); 1567 if (index != -1) { 1568 set.add(actionName.substring(index+1)); 1569 actionName = actionName.substring(0, index); 1570 } else { 1571 set.add(actionName); 1572 } 1573 } 1574 1575 ActionDecision ad = new ActionDecision(actionName, set); 1576 ad.setAdvices(entitlement.getAdvices()); 1577 ad.setTimeToLive(entitlement.getTTL()); 1578 pd.addActionDecision(ad, serviceType); 1579 } 1580 } else { 1581 Map advices = entitlement.getAdvices(); 1582 if ((advices != null) && (!advices.isEmpty()) && 1583 ((actionNames == null) || actionNames.isEmpty())) { 1584 actionNames = serviceType.getActionNames(); 1585 } 1586 for (String actionName : actionNames) { 1587 Set set = new HashSet(); 1588 // Determinte if the serviceType have boolean action values 1589 ActionSchema as = null; 1590 if (serviceType != null) { 1591 try { 1592 as = serviceType.getActionSchema(actionName); 1593 } catch (InvalidNameException inex) { 1594 if (DEBUG.warningEnabled()) { 1595 DEBUG.warning("PolicyEvaluator." + 1596 "entitlementToPolicyDecision:", inex); 1597 } 1598 } 1599 } 1600 if ((as == null) || 1601 as.getSyntax().equals(AttributeSchema.Syntax.BOOLEAN)) { 1602 set.add(getActionFalseBooleanValue(actionName)); 1603 } else { 1604 set.addAll(as.getDefaultValues()); 1605 } 1606 ActionDecision ad = new ActionDecision(actionName, set); 1607 ad.setAdvices(entitlement.getAdvices()); 1608 ad.setTimeToLive(entitlement.getTTL()); 1609 pd.addActionDecision(ad, serviceType); 1610 } 1611 } 1612 1613 pd.setTimeToLive(entitlement.getTTL()); 1614 pd.setResponseAttributes(entitlement.getAttributes()); 1615 return pd; 1616 } 1617 1618 /** 1619 * Gets resource result given a resource name. <code>ResourceResult</code> 1620 * is a tree representation of policy decisions for all resources rooted 1621 * at the resource name. 1622 * To determine whether a resource defined in the policy 1623 * is a sub resource of argument resource name, argument resource name 1624 * and policy resource name are compared, treating wild characters as 1625 * literals. If comparison resulted in <code>EXACT_MACTH</code> or 1626 * <code>SUB_RESOURCE_MACTH</code>, the resource would be included 1627 * 1628 * @param token single sign on token of the user evaluating policies 1629 * @param resourceName name of the resource 1630 * @param scope indicates whether to compute the resource result based on 1631 * the policy decision for only the <code>resourceName</code> 1632 * or all the resources associated with the resource name. 1633 * The valid scope values are: 1634 * <ul> 1635 * <li><code>ResourceResult.SUBTREE_SCOPE</code> 1636 * <li><code>ResourceResult.STRICT_SUBTREE_SCOPE</code> 1637 * <li><code>ResourceResult.SELF_SCOPE</code> 1638 * </ul> 1639 * If the scope is <code>ResourceResult.SUBTREE_SCOPE</code> or 1640 * <code>ResourceResult.STRICT_SUBTREE_SCOPE</code>, the method 1641 * will return a <code>ResourceResult</code> object that 1642 * contains the policy decisions regarding the 1643 * <code>resourceName</code> and its sub resources. 1644 * If the scope is <code>ResourceResult.SELF_SCOPE</code>, the 1645 * method will return a <code>ResourceResult</code> object that 1646 * contains the policy decision regarding the 1647 * <code>resourceName</code> only. Note, scope values 1648 * <code>ResourceResult.SUBTREE_SCOPE</code> and 1649 * <code>ResourceResult.STRICT_SUBTREE_SCOPE</code> are being 1650 * treated as the same for backword compatibility reasons. This 1651 * method is being deprecated. The method 1652 * <code>getResourceResults()</code> should be used instead. 1653 * 1654 * @param envParameters run-time environment parameters 1655 * 1656 * @return <code>ResourceResult</code>. 1657 * 1658 * @throws SSOException if <code>token</code> is invalid 1659 * @throws PolicyException for any other abnormal condition 1660 * 1661 * @see ResourceMatch#EXACT_MATCH 1662 * @see ResourceMatch#SUB_RESOURCE_MATCH 1663 * @see ResourceMatch#WILDCARD_MATCH 1664 * @see ResourceResult#SUBTREE_SCOPE 1665 * @see ResourceResult#STRICT_SUBTREE_SCOPE 1666 * @see ResourceResult#SELF_SCOPE 1667 * 1668 * @deprecated Use <code>getResourceResults()</code> 1669 * 1670 * @supported.api 1671 * 1672 */ 1673 public ResourceResult getResourceResult(SSOToken token, 1674 String resourceName, String scope, Map envParameters) 1675 throws SSOException, PolicyException { 1676 if (ResourceResult.SUBTREE_SCOPE.equals(scope) 1677 || ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope) 1678 || ResourceResult.SELF_SCOPE.equals(scope)) { 1679 if (ResourceResult.SUBTREE_SCOPE.equals(scope)) { 1680 scope = ResourceResult.STRICT_SUBTREE_SCOPE; 1681 } 1682 return getResourceResultTree(token, resourceName, scope, 1683 envParameters); 1684 } else { 1685 DEBUG.error("PolicyEvaluator: invalid request scope: " + scope); 1686 String objs[] = {scope}; 1687 throw new PolicyException(ResBundleUtils.rbName, 1688 "invalid_request_scope", objs, null); 1689 } 1690 } 1691 1692 /** 1693 * Gets resource result given a resource name. <code>ResourceResult</code> 1694 * is a tree representation of policy decisions for all resources 1695 * that are sub resources of argument resource name. 1696 * 1697 * @param token single sign on token of the user evaluating policies 1698 * @param resourceName name of the resource 1699 * @param scope indicates whether to compute the resource result based on 1700 * the policy decision for only the <code>resourceName</code> 1701 * or all the resources associated with the resource name. 1702 * @param envParameters run-time environment parameters 1703 * 1704 * @return <code>ResourceResult</code>. 1705 * 1706 * @exception SSOException if <code>token</code> is invalid 1707 * @exception PolicyException for any other abnormal condition 1708 * 1709 * @see ResourceMatch#EXACT_MATCH 1710 * @see ResourceMatch#SUB_RESOURCE_MATCH 1711 * @see ResourceMatch#WILDCARD_MATCH 1712 * 1713 */ 1714 private ResourceResult getResourceResultTree(SSOToken token, 1715 String resourceName, String scope, Map envParameters) 1716 throws PolicyException, SSOException { 1717 1718 String userSSOTokenIDStr = (token != null) 1719 ? token.getTokenID().toString() 1720 : PolicyUtils.EMPTY_STRING; 1721 1722 if (token == null) { 1723 if (DEBUG.messageEnabled()) { 1724 DEBUG.message("user sso token is null, forcing ResourceResult" 1725 + " evaluation to self_scope"); 1726 } 1727 scope = ResourceResult.SELF_SCOPE; 1728 1729 } 1730 1731 ResourceResult resourceResult = null; 1732 1733 if ( (resourceName == null) || (resourceName.equals("")) ) { 1734 resourceName = Rule.EMPTY_RESOURCE_NAME; 1735 } 1736 resourceName = serviceType.canonicalize(resourceName); 1737 Map clientEnv = PolicyUtils.cloneMap(envParameters); 1738 1739 1740 // check if we already have the result in the cache 1741 // policyResultsCache: 1742 // serviceType -> resource -> sessionId -> scope -> result 1743 synchronized(policyResultsCache) { 1744 // rscCACHE: resource -> sessionId -> scope -> result 1745 Map rscCache = (Map)policyResultsCache.get(serviceTypeName); 1746 if (rscCache != null) { 1747 // resultCACHE: sessionId -> scope -> resourceResult 1748 Map resultsCache = (Map)rscCache.get(resourceName); 1749 if (resultsCache != null) { 1750 Map results = (Map)resultsCache.get(userSSOTokenIDStr); 1751 if (results != null) { 1752 resourceResult = (ResourceResult)results.get(scope); 1753 if (resourceResult != null) { 1754 long currentTime = System.currentTimeMillis(); 1755 long ttlMinimal = resourceResult.getTimeToLive(); 1756 if (ttlMinimal > currentTime) { 1757 1758 //check envMap equality of request and cache 1759 Map cachedEnv = resourceResult.getEnvMap(); 1760 if ( ((clientEnv == null) 1761 && (cachedEnv == null)) 1762 || ((clientEnv != null) 1763 && clientEnv.equals(cachedEnv)) ) { 1764 if (DEBUG.messageEnabled()) { 1765 DEBUG.message("PolicyEvaluator." 1766 + " getResourceResult(): we get the " 1767 + "result from the cache.\n" 1768 + resourceResult.toXML()); 1769 } 1770 return resourceResult; 1771 } else { 1772 if (PolicyManager.debug.messageEnabled()) { 1773 PolicyManager.debug.message( 1774 "PolicyEvaluator.getResourceesultTree()" 1775 + ":cached envMap does not equal " 1776 + "request envMap, request envMap = " 1777 + clientEnv 1778 + ", cachedEnv=" + cachedEnv 1779 ); 1780 } 1781 } 1782 } 1783 } 1784 } 1785 } 1786 } 1787 } 1788 1789 /* compute all action names if passed in actionNames is 1790 null or empty */ 1791 if ( (actionNames == null) || (actionNames.isEmpty()) ) { 1792 actionNames = serviceType.getActionNames(); 1793 } 1794 1795 if (DEBUG.messageEnabled()) { 1796 DEBUG.message("PolicyEvaluator:computing policy decisions " 1797 + " for resource : " + resourceName); 1798 } 1799 PolicyDecision policyDecision = getPolicyDecision(token, resourceName, 1800 actionNames, envParameters); 1801 resourceResult = new ResourceResult(resourceName, policyDecision); 1802 1803 if (ResourceResult.SUBTREE_SCOPE.equals(scope)) { 1804 ResourceResult virtualResourceResult 1805 = new ResourceResult(ResourceResult.VIRTUAL_ROOT, 1806 new PolicyDecision()); 1807 virtualResourceResult.addResourceResult(resourceResult, 1808 serviceType); 1809 resourceResult = virtualResourceResult; 1810 } 1811 1812 if (ResourceResult.SUBTREE_SCOPE.equals(scope) 1813 || ResourceResult.STRICT_SUBTREE_SCOPE.equals(scope)) { 1814 Map resourceNamesCache 1815 = (Map)resourceNamesMap.get(serviceTypeName); 1816 if (resourceNamesCache == null) { 1817 resourceNamesCache = new Cache(resultsCacheResourceCap); 1818 resourceNamesMap.put(serviceTypeName, resourceNamesCache); 1819 } 1820 Set resourceNames = (Set)resourceNamesCache.get(resourceName); 1821 if (resourceNames == null) { 1822 if (DEBUG.messageEnabled()) { 1823 DEBUG.message("Computing subresources for: " 1824 + resourceName); 1825 } 1826 // true indicates to follow referral 1827 resourceNames = getResourceNames(token, resourceName, true); 1828 resourceNames = removeDuplicateResourceNames(resourceNames, 1829 serviceType); 1830 resourceNames = removeResourceName(resourceNames, 1831 serviceType, resourceName); 1832 resourceNamesCache.put(resourceName, resourceNames); 1833 } 1834 if (DEBUG.messageEnabled()) { 1835 DEBUG.message("PolicyEvaluator:computing policy decisions " 1836 + " for subresources : " + resourceNames); 1837 } 1838 1839 Iterator resourceNameIter = resourceNames.iterator(); 1840 while (resourceNameIter.hasNext()) { 1841 String subResourceName = (String) resourceNameIter.next(); 1842 if (ResourceResult.SUBTREE_SCOPE.equals(scope) || 1843 (serviceType.compare(resourceName, 1844 subResourceName, false).equals( 1845 ResourceMatch.SUB_RESOURCE_MATCH))) { 1846 PolicyDecision pDecision = getPolicyDecision(token, 1847 subResourceName, actionNames, envParameters); 1848 resourceResult.addResourceResult( 1849 new ResourceResult(subResourceName, pDecision), 1850 serviceType); 1851 } 1852 } 1853 } 1854 1855 // Do not cache policy decision with advices 1856 if ( (resourceResult != null) 1857 && !resourceResult.hasAdvices()) { 1858 resourceResult.setEnvMap(clientEnv); 1859 // add the evaluation result to the result cache 1860 Map scopeElem = null; 1861 //cacheElem: sessionId -> scope -> resourceResult 1862 Map cacheElem = null; 1863 Map rscElem = null; 1864 // serviceType -> resourceName -> sessionId -> scope -> resourceResult 1865 synchronized(policyResultsCache) { 1866 // rscElemCACHE: resourceName -> sessionId -> scope -> resourceResult 1867 rscElem = (Map)policyResultsCache.get( 1868 serviceTypeName); 1869 if (rscElem != null) { // serviceType has been seen earlier 1870 //CACHEElem: sessionId -> scope -> resourceResult 1871 cacheElem = (Map)rscElem.get(resourceName); 1872 if (cacheElem != null) { // resource seen earlier 1873 scopeElem = (Map)cacheElem.get( 1874 userSSOTokenIDStr); 1875 if (scopeElem == null) { // seeing sessionId first time 1876 scopeElem = new HashMap(); 1877 } 1878 } else { // seeing the resource first time 1879 if (PolicyManager.debug.messageEnabled()) { 1880 PolicyManager.debug.message( 1881 "PolicyEvaluator.getResourceResultTree()" 1882 + " Create Cache for:" 1883 + ", resourceName=" + resourceName 1884 + ", sessionId=" + userSSOTokenIDStr 1885 + ", scope=" + scope); 1886 } 1887 cacheElem = new Cache(resultsCacheSessionCap); 1888 scopeElem = new HashMap(); 1889 } 1890 } else { // seeing service for first time 1891 // rscElemCACHE: resourceName -> sessionId -> scope -> resourceResult 1892 rscElem = new Cache(resultsCacheResourceCap); 1893 //CACHEElem: sessionId -> scope -> resourceResult 1894 if (PolicyManager.debug.messageEnabled()) { 1895 PolicyManager.debug.message( 1896 "PolicyEvaluator.getResourceResultTree()" 1897 + " Create Cache for:" 1898 + ", resourceName=" + resourceName 1899 + ", sessionId=" + userSSOTokenIDStr 1900 + ", scope=" + scope 1901 + ", serviceType=" + serviceTypeName); 1902 } 1903 cacheElem = new Cache(resultsCacheSessionCap); 1904 scopeElem = new HashMap(); 1905 } 1906 scopeElem.put(scope, resourceResult); 1907 cacheElem.put(userSSOTokenIDStr, scopeElem); 1908 if (PolicyManager.debug.messageEnabled()) { 1909 PolicyManager.debug.message( 1910 "PolicyEvaluator.getResourceResultTree()" 1911 + " Create Cache for:" 1912 + ", resourceName=" + resourceName 1913 + ", sessionId=" + userSSOTokenIDStr 1914 + ", scope=" + scope 1915 + ", cacheSize=" + cacheElem.size()); 1916 } 1917 rscElem.put(resourceName, cacheElem); 1918 policyResultsCache.put(serviceTypeName, rscElem); 1919 } 1920 1921 if ( (token != null) 1922 && !(ssoListenerRegistry.containsKey( 1923 userSSOTokenIDStr))) { 1924 try { 1925 token.addSSOTokenListener(ssoListener); 1926 } catch (SSOException se) { 1927 DEBUG.error("PolicyEvaluator:" 1928 + "failed to add sso token listener"); 1929 } 1930 ssoListenerRegistry.put(userSSOTokenIDStr, ssoListener); 1931 if (DEBUG.messageEnabled()) { 1932 DEBUG.message("PolicyEvaluator.getResourceResultTree():" 1933 + " sso listener added .\n"); 1934 } 1935 } 1936 if (DEBUG.messageEnabled()) { 1937 DEBUG.message("PolicyEvaluator: we added the evaluation " 1938 + " result to the cache"); 1939 } 1940 } 1941 1942 return resourceResult; 1943 } 1944 1945 1946 /** 1947 * Gets resource names that are exact matches, sub resources or 1948 * wild card matches of argument resource name. 1949 * To determine whether to include a 1950 * resource name of a resource, we compare argument resource name and 1951 * policy resource name, treating wild characters in the policy 1952 * resource name as wild. If the comparison resulted in 1953 * <code>EXACT_MATCH</code>, <code>WILD_CARD_MACTH</code> or 1954 * <code>SUB_RESOURCE_MACTH</code>, the resource result would be 1955 * included. 1956 * 1957 * @param token single sign on token 1958 * 1959 * @param resourceName resoure name 1960 * @param followReferral indicates whether to follow the referrals 1961 * defined in policies to compute resource names 1962 * @return names of sub resources for the given <code>resourceName</code>. 1963 * The return value would also include the 1964 * <code>resourceName</code>. 1965 * 1966 * @exception SSOException if <code>token</code> is invalid 1967 * @exception PolicyException for any other abnormal condition 1968 * 1969 * @see ResourceMatch#EXACT_MATCH 1970 * @see ResourceMatch#SUB_RESOURCE_MATCH 1971 * @see ResourceMatch#WILDCARD_MATCH 1972 * 1973 */ 1974 public Set getResourceNames(SSOToken token, String resourceName, 1975 boolean followReferral) throws PolicyException, SSOException { 1976 Set visitedOrgs = new HashSet(); 1977 visitedOrgs.add(policyManager.getOrganizationDN()); 1978 return getResourceNames(token, resourceName, followReferral, 1979 visitedOrgs); 1980 } 1981 1982 /**Gets resource names that are exact matches, sub resources or 1983 * wild card matches of argument resource name. 1984 * To determine whether to include a 1985 * resource name of a resource, we compare argument resource name and 1986 * policy resource name, treating wild characters in the policy 1987 * resource name as wild. If the comparsion resulted in 1988 * <code>EXACT_MATCH</code>, <code>WILD_CARD_MACTH</code> or 1989 * <code>SUB_RESOURCE_MACTH</code>, the resource result would be 1990 * included. 1991 * 1992 * @param token single sign on token 1993 * 1994 * @param resourceName resoure name 1995 * @param followReferral indicates whether to follow the referrals 1996 * defined in policies to compute resource names 1997 * @param visitedOrgs organizations that were already visited to 1998 * compute resource names 1999 * @return names of sub resources for the given <code>resourceName</code>. 2000 * The return value would also include the 2001 * <code>resourceName</code>. 2002 * 2003 * @exception SSOException if <code>token</code> is invalid 2004 * @exception PolicyException for any other abnormal condition 2005 * 2006 * @see ResourceMatch#EXACT_MATCH 2007 * @see ResourceMatch#SUB_RESOURCE_MATCH 2008 * @see ResourceMatch#WILDCARD_MATCH 2009 * 2010 */ 2011 public Set getResourceNames(SSOToken token, String resourceName, 2012 boolean followReferral, Set visitedOrgs) 2013 throws PolicyException, SSOException { 2014 DEBUG.message("PolicyEvaluator.getResourceNames():entering"); 2015 Set resourceNames = new HashSet(); 2016 Set policyNameSet = null; 2017 Set toRemovePolicyNameSet = null; 2018 Set orgsToVisit = new HashSet(); 2019 policyNameSet = resourceIndexManager.getSubResourcePolicyNames( 2020 serviceType, resourceName); 2021 policyNameSet.addAll( 2022 resourceIndexManager.getPolicyNames(serviceType, 2023 resourceName, true)); //include policies of super resources 2024 policyNameSet.addAll( 2025 resourceIndexManager.getWildSubResourcePolicyNames( 2026 serviceType, resourceName)); 2027 if ( (policyNameSet != null) && (!policyNameSet.isEmpty()) ) { 2028 Iterator policyIter = policyNameSet.iterator(); 2029 while (policyIter.hasNext()) { 2030 String policyName = (String) policyIter.next(); 2031 Policy policy = policyManager.getPolicy(policyName, 2032 USE_POLICY_CACHE); 2033 // policy could have been deleted 2034 if ( policy != null && policy.isActive()) { 2035 // true inidicates to follow referrals 2036 Set pResourceNames = policy.getResourceNames(token, 2037 serviceTypeName, resourceName, true); 2038 if (pResourceNames != null) { 2039 resourceNames.addAll(pResourceNames); 2040 } 2041 } else { // add policy names to toRemovePolicyNameSet 2042 if (toRemovePolicyNameSet == null) { 2043 toRemovePolicyNameSet = new HashSet(); 2044 } 2045 toRemovePolicyNameSet.add(policyName); 2046 if ( DEBUG.messageEnabled() ) { 2047 DEBUG.message("PolicyEvaluator.getResourceNames():" 2048 +policyName+ " is inactive or non-existent"); 2049 } 2050 } 2051 } 2052 // remove inactive/missing policies from policyNameSet 2053 if (toRemovePolicyNameSet != null) { 2054 policyNameSet.removeAll(toRemovePolicyNameSet); 2055 } 2056 2057 orgsToVisit.addAll(getOrgsToVisit(policyNameSet)); 2058 2059 if ( DEBUG.messageEnabled() ) { 2060 DEBUG.message("PolicyEvaluator.getResourceNames():" 2061 + "realmAliasEnabled=" 2062 + PolicyConfig.orgAliasMappedResourcesEnabled() 2063 + ", serviceTypeName=" + serviceTypeName); 2064 } 2065 } 2066 if (PolicyConfig.orgAliasMappedResourcesEnabled() 2067 && PolicyManager.WEB_AGENT_SERVICE.equalsIgnoreCase( 2068 serviceTypeName)) { 2069 String orgAlias = policyManager.getOrgAliasWithResource( 2070 resourceName); 2071 if (orgAlias != null) { 2072 String orgWithAlias = policyManager.getOrgNameWithAlias( 2073 orgAlias); 2074 if (orgWithAlias != null) { 2075 if ( DEBUG.messageEnabled() ) { 2076 DEBUG.message("PolicyEvaluator." 2077 + "getgetResourceNames():" 2078 + "adding orgWithAlias to orgsToVisit=" 2079 + orgWithAlias); 2080 } 2081 orgsToVisit.add(orgWithAlias); 2082 } else { 2083 if ( DEBUG.messageEnabled() ) { 2084 DEBUG.message("PolicyEvaluator." 2085 + "getgetResourceNames():" 2086 + "no realm matched orgAlias:" + orgAlias); 2087 } 2088 } 2089 } 2090 } 2091 2092 orgsToVisit.removeAll(visitedOrgs); 2093 while (!orgsToVisit.isEmpty() ) { 2094 String orgToVisit = (String) orgsToVisit.iterator().next(); 2095 orgsToVisit.remove(orgToVisit); 2096 visitedOrgs.add(orgToVisit); 2097 //resourceNames.add(resourceName); 2098 try { 2099 // need to use admin sso token here. Need all privileges to 2100 // check for the organzation 2101 policyManager.verifyOrgName(orgToVisit); 2102 } catch (NameNotFoundException nnfe) { 2103 if( DEBUG.warningEnabled()) { 2104 DEBUG.warning("PolicyEvaluator." 2105 + "getgetResourceNames():" 2106 + "Organization does not exist - " 2107 + "skipping referral to " + orgToVisit); 2108 } 2109 continue; 2110 } 2111 PolicyEvaluator pe = new PolicyEvaluator(orgToVisit, 2112 serviceTypeName); 2113 resourceNames.addAll(pe.getResourceNames(token, 2114 resourceName, true, 2115 visitedOrgs)); 2116 } 2117 return resourceNames; 2118 } 2119 2120 /** Adds a policy listener that would be notified whenever a policy 2121 * is added, removed or changed 2122 * 2123 * @param policyListener the listener to be added 2124 * 2125 * @supported.api 2126 */ 2127 public void addPolicyListener(PolicyListener policyListener) { 2128 policyCache.addPolicyListener(policyListener); 2129 } 2130 2131 /** Removes a policy listener that was previously registered 2132 * to receive notifications whenever a policy is added, removed 2133 * or changed. It is not an error to attempt to remove a listener 2134 * that was not registered. It would return silently. 2135 * 2136 * @param policyListener the listener to be removed 2137 * 2138 * @supported.api 2139 */ 2140 public void removePolicyListener(PolicyListener policyListener) { 2141 policyCache.removePolicyListener(policyListener); 2142 } 2143 2144 /** Merges two policy decisions. 2145 * Merging policy decisions merges each action decision of the 2146 * policy with the corresponding action decision of the other 2147 * policy. This method also merges ResponseProviderDecision of one 2148 * policy ( response attributes per policy) 2149 * with that of the other policy. 2150 * These are the rules followed to merge each action decision: 2151 * If the action schema has boolean syntax, boolean false value 2152 * overrides boolean true value. The time to live of boolean false 2153 * value overrides the time to live of boolean true value. 2154 * Otherwise, action values are simply aggregated. Time to live 2155 * is set to the minimum of time to live(s) of all values of the 2156 * action. 2157 * For response attributes, all response attributes are aggregated. 2158 * In case of mutiple values for the same attribute 2159 * they appear as multi valued data for the attribute. 2160 * @param serviceType service type that would be consulted to merge the 2161 * policy decisions 2162 * @param pd1 policy decision 1 2163 * @param pd2 policy decision 2 2164 * @return the merged policy decision. 2165 * Policy decisions pd1 and pd2 are merged into pd2 and 2166 * pd2 is returned. 2167 */ 2168 static PolicyDecision mergePolicyDecisions(ServiceType 2169 serviceType, PolicyDecision pd1, PolicyDecision pd2) { 2170 Map actionDecisions1 = pd1.getActionDecisions(); 2171 Set actions = new HashSet(); 2172 actions.addAll(actionDecisions1.keySet()); 2173 Iterator iter = actions.iterator(); 2174 while ( iter.hasNext() ) { 2175 String action = (String) iter.next(); 2176 ActionDecision ad1 = (ActionDecision) actionDecisions1.get( 2177 action); 2178 pd2.addActionDecision(ad1, serviceType); 2179 } 2180 Map mergedReponseAttrsMap = new HashMap(); 2181 PolicyUtils.appendMapToMap(pd1.getResponseAttributes(), 2182 mergedReponseAttrsMap); 2183 PolicyUtils.appendMapToMap(pd2.getResponseAttributes(), 2184 mergedReponseAttrsMap); 2185 pd2.setResponseAttributes(mergedReponseAttrsMap); 2186 return pd2; 2187 } 2188 2189 /** Gets a set of action names for which final values have been 2190 * determined. We assume the final values have been determined 2191 * for an action if the action schema syntax is boolean and 2192 * the value is boolean false value 2193 * 2194 * @param serviceType service type that would be consulted to decide 2195 * the final values for actions 2196 * @param pd policy decision 2197 */ 2198 static Set getFinalizedActions(ServiceType 2199 serviceType, PolicyDecision pd) { 2200 Set finalizedActions = new HashSet(); 2201 Map actionDecisions = pd.getActionDecisions(); 2202 Iterator actions = actionDecisions.keySet().iterator(); 2203 while ( actions.hasNext() ) { 2204 String action = (String) actions.next(); 2205 ActionDecision actionDecision 2206 = (ActionDecision) actionDecisions.get(action); 2207 Set values = actionDecision.getValues(); 2208 if ( (values != null) && !values.isEmpty() ) { 2209 try { 2210 ActionSchema schema 2211 = serviceType.getActionSchema(action); 2212 if ((AttributeSchema.Syntax.BOOLEAN.equals( 2213 schema.getSyntax())) 2214 && values.contains(schema.getFalseValue()) ) { 2215 finalizedActions.add(action); 2216 } 2217 } catch(InvalidNameException e) { 2218 DEBUG.error("can not find action schmea for action = " + 2219 action, e ); 2220 } 2221 2222 } 2223 2224 2225 } 2226 return finalizedActions; 2227 } 2228 2229 /** 2230 * Gets names of organizations to visit for policy evaluation 2231 * based on the give policy names. This is used to follow 2232 * OrgReferral(s) defined in the policies 2233 * 2234 * @return names of organization to visit 2235 * @exception SSOException if <code>token</code> is invalid 2236 * @exception PolicyException for any other abnormal condition 2237 */ 2238 private Set getOrgsToVisit(Set policyNameSet) 2239 throws PolicyException, SSOException { 2240 Set orgsToVisit = new HashSet(); 2241 Iterator policyNames = policyNameSet.iterator(); 2242 while ( policyNames.hasNext() ) { 2243 String policyName = (String) policyNames.next(); 2244 Policy policy = policyManager.getPolicy(policyName, 2245 USE_POLICY_CACHE); 2246 if (policy != null) { 2247 orgsToVisit.addAll(policy.getReferredToOrganizations()); 2248 } 2249 } 2250 return orgsToVisit; 2251 } 2252 2253 /** 2254 * This would be a costly operation. 2255 * Can be avoided if ResourceName has api for getting canonical name. 2256 * When the policies are stored, resource names would be converted to and 2257 * stored as canonical name. 2258 */ 2259 private static Set removeDuplicateResourceNames(Set resourceNames, 2260 ServiceType serviceType) { 2261 Set answer = resourceNames; 2262 if ( (resourceNames != null) && (serviceType != null) ) { 2263 answer = new HashSet(resourceNames.size()); 2264 Iterator iter = resourceNames.iterator(); 2265 while ( iter.hasNext() ) { 2266 String resourceName = (String) iter.next(); 2267 Iterator answerIter = answer.iterator(); 2268 boolean duplicate = false; 2269 while (answerIter.hasNext()) { 2270 String answerResourceName = (String) answerIter.next(); 2271 2272 if ( serviceType.compare(resourceName, 2273 answerResourceName, false) 2274 .equals(ResourceMatch.EXACT_MATCH) ) { 2275 duplicate = true; 2276 break; 2277 } 2278 } 2279 if (!duplicate) { 2280 answer.add(resourceName); 2281 } 2282 } 2283 2284 } 2285 return answer; 2286 } 2287 2288 /** 2289 * Removes the <code>resourceName</code> from the <code>Set</code> 2290 * of resource names matching on <code>serviceType</code> and 2291 * performing a <code>ResourceMatch.EXACT_MATCH</code> 2292 */ 2293 2294 private static Set removeResourceName(Set resourceNames, 2295 ServiceType serviceType, String resourceName) { 2296 Set answer = resourceNames; 2297 if ( (resourceNames != null) && (serviceType != null) 2298 && (resourceName != null) ) { 2299 answer = new HashSet(resourceNames.size()); 2300 answer.addAll(resourceNames); 2301 Iterator iter = resourceNames.iterator(); 2302 while ( iter.hasNext() ) { 2303 String rName = (String) iter.next(); 2304 if ( serviceType.compare(resourceName, 2305 rName, false).equals(ResourceMatch.EXACT_MATCH) ) { 2306 answer.remove(rName); 2307 } 2308 } 2309 2310 } 2311 return answer; 2312 } 2313 2314 2315 /** 2316 * Handles policyChanged notifications - clears the cached resource 2317 * names for the service type name 2318 * 2319 * @param serviceTypeName service type name 2320 * @param pe policy event 2321 */ 2322 static void policyChanged(String serviceTypeName, PolicyEvent pe) { 2323 2324 if (DEBUG.messageEnabled()) { 2325 DEBUG.message("PolicyEvaulator.policyChanged():serviceTypeName=" 2326 + serviceTypeName); 2327 } 2328 resourceNamesMap.remove(serviceTypeName); 2329 2330 Cache resourceNamesCache 2331 = (Cache)resourceNamesMap.get(serviceTypeName); 2332 if ((resourceNamesCache == null) || (resourceNamesCache.isEmpty())) { 2333 return; 2334 } 2335 try { 2336 DEBUG.error("PolicyEvaluator.policyChanged: enterred try block"); 2337 ServiceTypeManager stm = ServiceTypeManager.getServiceTypeManager(); 2338 ServiceType serviceType = stm.getServiceType(serviceTypeName); 2339 Set resourceNamesToRemove = new HashSet(); 2340 synchronized(resourceNamesCache) { 2341 Enumeration resourceNames = resourceNamesCache.keys(); 2342 while (resourceNames.hasMoreElements()) { 2343 String resourceName = (String)resourceNames.nextElement(); 2344 if (resourceNamesToRemove.contains(resourceName)) { 2345 continue; 2346 } 2347 Set affectedResourceNames = pe.getResourceNames(); 2348 Iterator iter = affectedResourceNames.iterator(); 2349 while (iter.hasNext()) { 2350 String affectedResourceName = (String)iter.next(); 2351 if (serviceType.compare(resourceName, 2352 affectedResourceName) 2353 != ResourceMatch.NO_MATCH) { 2354 resourceNamesToRemove.add(resourceName); 2355 } 2356 } 2357 } 2358 Iterator iter1 = resourceNamesToRemove.iterator(); 2359 while (iter1.hasNext()) { 2360 String resourceNameToRemove = (String) iter1.next(); 2361 resourceNamesCache.remove(resourceNameToRemove); 2362 } 2363 } 2364 } catch (SSOException e) { 2365 DEBUG.error("PolicyEvaluator.policyChanged:", e); 2366 } catch (PolicyException pex) { 2367 DEBUG.error("PolicyEvaluator.policyChanged:", pex); 2368 } 2369 if (DEBUG.messageEnabled()) { 2370 DEBUG.message("PolicyEvaulator.policyChanged():serviceTypeName=" 2371 + serviceTypeName 2372 + ", new cached resoruceNames=" 2373 + resourceNamesMap.get(serviceTypeName)); 2374 } 2375 } 2376 2377 /** 2378 * Add an advice to the policy decision. 2379 * @param pd <code>PolicyDecision</code> in which to add the advice. 2380 * @param adviceKey key to the condition generating the advice 2381 * like SessionCondition.SESSION_CONDITION_ADVICE, 2382 * AuthSchemeCondition.AUTH_SCHEME_CONDITION_ADVICE 2383 * @param adviceValue advice message to be added to the advice 2384 */ 2385 private static void addAdvice(PolicyDecision pd, String adviceKey, 2386 String adviceValue) { 2387 if ((pd != null) 2388 && (pd.hasAdvices())) { 2389 Map actionDecisions = pd.getActionDecisions(); 2390 Iterator actionDecisionIter = actionDecisions.keySet().iterator(); 2391 while (actionDecisionIter.hasNext()) { 2392 String key = (String) actionDecisionIter.next(); 2393 ActionDecision ad = (ActionDecision) actionDecisions.get(key); 2394 Map advices = ad.getAdvices(); 2395 if ((advices != null) && !advices.isEmpty()) { 2396 Set values = (Set)advices.get(adviceKey); 2397 if (values == null) { 2398 values = new HashSet(); 2399 } 2400 values.add(adviceValue); 2401 advices.put(adviceKey, values); 2402 } 2403 } 2404 } 2405 } 2406 2407 /** 2408 * Get the policy decision for a resource ignoring the subject 2409 */ 2410 2411 PolicyDecision getPolicyDecisionIgnoreSubjects(String resourceName, 2412 Set actionNames, Map env) throws PolicyException, SSOException { 2413 2414 Set originalResourceNames = new HashSet(2); 2415 originalResourceNames.add(resourceName); 2416 2417 /* 2418 * Add request resourceName and request actionNames to the envParameters 2419 * so that Condition(s)/ResponseProvider(s) can use them if necessary 2420 */ 2421 Set resourceNames = new HashSet(2); 2422 resourceNames.add(resourceName); 2423 2424 /* compute for all action names if passed in actionNames is 2425 null or empty */ 2426 if ( (actionNames == null) || (actionNames.isEmpty()) ) { 2427 actionNames = serviceType.getActionNames(); 2428 } 2429 2430 Set actions = new HashSet(); 2431 if (actionNames != null) { 2432 actions.addAll(actionNames); 2433 } 2434 2435 //We create new HashMap in place of empty map since 2436 //Collections.EMPTY_MAP can not be modified 2437 if ((env == null) || env.isEmpty()) { 2438 env = new HashMap(); 2439 } 2440 2441 env.put(SUN_AM_REQUESTED_RESOURCE, resourceNames); 2442 env.put(SUN_AM_ORIGINAL_REQUESTED_RESOURCE, 2443 originalResourceNames); 2444 env.put(SUN_AM_REQUESTED_ACTIONS, actions); 2445 env.put(REALM_DN, asSet(policyManager.getOrganizationDN())); 2446 2447 return getPolicyDecision(null, resourceName, actionNames, env, 2448 new HashSet()); 2449 } 2450 2451 2452 /** 2453 * Get the set of role DNs of a user. The role DNs are cached to 2454 * improve the performance of IdentityServerRole subject membership 2455 * validation. 2456 * 2457 * @param token single sign on token of the user evaluating policies 2458 * 2459 * @return The set of user <code>nsRole</code> attribute values 2460 * 2461 * @exception SSOException single-sign-on token invalid or expired 2462 * @exception PolicyException if an error occured while getting the 2463 * user's nsRole attribute value set 2464 */ 2465 public static Set getUserNSRoleValues(SSOToken token) 2466 throws SSOException, PolicyException { 2467 if (userNSRoleCacheTTL == 0) { 2468 synchronized(userNSRoleCache) { 2469 String orgName = ServiceManager.getBaseDN(); 2470 Map pConfigValues = PolicyConfig.getPolicyConfig(orgName); 2471 userNSRoleCacheTTL = 2472 PolicyConfig.getSubjectsResultTtl(pConfigValues); 2473 if (userNSRoleCacheTTL <= 0) { 2474 userNSRoleCacheTTL = DEFAULT_USER_NSROLE_CACHE_TTL; 2475 if (DEBUG.warningEnabled()) { 2476 DEBUG.warning("Invalid TTL got from configuration." 2477 + " Set TTL to default:" 2478 + userNSRoleCacheTTL); 2479 } 2480 } 2481 if (DEBUG.messageEnabled()) { 2482 DEBUG.message("userNSRoleCacheTTL=" 2483 + userNSRoleCacheTTL); 2484 } 2485 } 2486 } 2487 if (token == null) { 2488 return null; 2489 } 2490 String tokenIDStr = token.getTokenID().toString(); 2491 Object[] element = (Object[])userNSRoleCache.get(tokenIDStr); 2492 if (element != null) { 2493 Long timeStamp = (Long)element[0]; 2494 long timeToLive = 0; 2495 if (timeStamp != null) { 2496 timeToLive = timeStamp.longValue(); 2497 } 2498 long currentTime = System.currentTimeMillis(); 2499 if (timeToLive > currentTime) { 2500 if (DEBUG.messageEnabled()) { 2501 DEBUG.message("PolicyEvaluator.getUserNSRoleValues():" 2502 + " get the nsRole values from cache.\n"); 2503 } 2504 return (HashSet)element[1]; 2505 } 2506 } 2507 // add or update the cache entry. 2508 // we come here either the token is first registered with the 2509 // cache or the cache element is out of date. 2510 try { 2511 AMStoreConnection am = new AMStoreConnection(token); 2512 AMUser user = am.getUser(token.getPrincipal().getName()); 2513 if ((user == null) || !(user.isActivated())) { 2514 return null; 2515 } 2516 Set roleSet = new HashSet(); 2517 Set roles = new HashSet(); 2518 // get all the roles assigned to the user 2519 Set staticRoles = user.getRoleDNs(); 2520 Set filteredRoles = user.getFilteredRoleDNs(); 2521 if (staticRoles != null) { 2522 roles.addAll(staticRoles); 2523 } 2524 if (filteredRoles != null) { 2525 roles.addAll(filteredRoles); 2526 } 2527 if (!roles.isEmpty()) { 2528 Iterator iter = roles.iterator(); 2529 while (iter.hasNext()) { 2530 String role = (String) iter.next(); 2531 if (role != null) { 2532 roleSet.add(LDAPUtils.formatToRFC(role)); 2533 } 2534 } 2535 } 2536 if (DEBUG.messageEnabled()) { 2537 DEBUG.message("PolicyEvaluator.getUserNSRoleValues():" 2538 + " added user nsRoles: " + roleSet); 2539 } 2540 Object[] elem = new Object[2]; 2541 elem[0] = new Long(System.currentTimeMillis() 2542 + userNSRoleCacheTTL); 2543 elem[1] = roleSet; 2544 userNSRoleCache.put(tokenIDStr, elem); 2545 if (!ssoListenerRegistry.containsKey(tokenIDStr)) { 2546 token.addSSOTokenListener(ssoListener); 2547 ssoListenerRegistry.put(tokenIDStr, ssoListener); 2548 if (DEBUG.messageEnabled()) { 2549 DEBUG.message("PolicyEvaluator.getUserNSRoleValues():" 2550 + " sso listener added .\n"); 2551 } 2552 } 2553 return roleSet; 2554 } catch (AMException e) { 2555 throw (new PolicyException(e)); 2556 } 2557 } 2558 2559 /** 2560 * record stats for policyResultsCache, ssoListenerRegistry, 2561 * policyListenerRegistry, userNSRoleCache, resouceNamesMap 2562 */ 2563 static void printStats(Stats policyStats) { 2564 2565 2566 int resultsCacheSize = 0; 2567 synchronized (policyResultsCache) { 2568 resultsCacheSize = policyResultsCache.size(); 2569 } 2570 policyStats.record("PolicyEvaluator: Number of services in " 2571 + " resultsCache: " + resultsCacheSize); 2572 2573 policyStats.record("PolicyEvaluator: Number of token IDs in " 2574 + " sessionListernerRgistry:" 2575 + ssoListenerRegistry.size()); 2576 2577 policyStats.record("PolicyEvaluator: Number of serviceNames " 2578 + " in policyListenerRegistry: " 2579 + policyListenerRegistry.size()); 2580 2581 policyStats.record("PolicyEvaluator: Number of token IDs " 2582 + " in role cahce: " + userNSRoleCache.size()); 2583 2584 policyStats.record("PolicyEvaluator:Number of serviceNames in " 2585 + " resourceNames cache: " 2586 + resourceNamesMap.size()); 2587 } 2588}