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: PolicyManager.java,v 1.19 2010/01/25 23:48:15 veiming Exp $ 026 * 027 * Portions Copyrighted 2011-2016 ForgeRock AS. 028 */ 029 030package com.sun.identity.policy; 031 032import static org.forgerock.openam.entitlement.PolicyConstants.SUPER_ADMIN_SUBJECT; 033import static org.forgerock.openam.entitlement.utils.EntitlementUtils.getApplicationService; 034 035import java.io.ByteArrayInputStream; 036import java.net.MalformedURLException; 037import java.net.URL; 038import java.security.AccessController; 039import java.util.Collections; 040import java.util.Date; 041import java.util.HashMap; 042import java.util.HashSet; 043import java.util.Iterator; 044import java.util.Map; 045import java.util.Set; 046import java.util.concurrent.locks.Lock; 047 048import org.forgerock.openam.ldap.LDAPUtils; 049import org.forgerock.openam.shared.concurrency.LockFactory; 050import org.forgerock.openam.utils.Time; 051import org.forgerock.opendj.ldap.DN; 052import org.w3c.dom.Document; 053import org.w3c.dom.Node; 054 055import com.iplanet.am.util.SystemProperties; 056import com.iplanet.sso.SSOException; 057import com.iplanet.sso.SSOToken; 058import com.iplanet.sso.SSOTokenManager; 059import com.sun.identity.entitlement.Application; 060import com.sun.identity.entitlement.EntitlementException; 061import com.sun.identity.entitlement.IPrivilege; 062import com.sun.identity.entitlement.PrivilegeIndexStore; 063import com.sun.identity.entitlement.opensso.PrivilegeUtils; 064import com.sun.identity.entitlement.opensso.SubjectUtils; 065import com.sun.identity.idm.IdRepoException; 066import com.sun.identity.idm.IdUtils; 067import com.sun.identity.policy.interfaces.Subject; 068import com.sun.identity.security.AdminTokenAction; 069import com.sun.identity.shared.debug.Debug; 070import com.sun.identity.shared.xml.XMLUtils; 071import com.sun.identity.sm.DNMapper; 072import com.sun.identity.sm.OrganizationConfigManager; 073import com.sun.identity.sm.PluginSchema; 074import com.sun.identity.sm.SMSEntry; 075import com.sun.identity.sm.SMSException; 076import com.sun.identity.sm.ServiceAlreadyExistsException; 077import com.sun.identity.sm.ServiceConfig; 078import com.sun.identity.sm.ServiceConfigManager; 079import com.sun.identity.sm.ServiceListener; 080import com.sun.identity.sm.ServiceManager; 081import com.sun.identity.sm.ServiceNotFoundException; 082import com.sun.identity.sm.ServiceSchemaManager; 083 084/** 085 * The <code>PolicyManager</code> class manages policies 086 * for a specific organization, sub organization or a container. 087 * This class is the 088 * starting point for policy management, and provides methods to 089 * create/modify/delete policies. 090 * <p>It is a final class 091 * and hence cannot be further extended. The methods in this class 092 * works directly with the backend datastore (usually a 093 * directory server) to store and manage policies. Hence, user 094 * of this class must have valid <code>SSOToken</code> 095 * and privileges to the backend datastore. 096 * 097 * @supported.api 098 * @deprecated since 12.0.0 099 */ 100@Deprecated 101public final class PolicyManager { 102 103 /** 104 * The service name for Policy component. 105 * @supported.api 106 */ 107 public static final String POLICY_SERVICE_NAME = "iPlanetAMPolicyService"; 108 public static final String POLICY_DEBUG_NAME = "amPolicy"; 109 110 /** 111 * The key for the plugins to get the organization name. 112 * @supported.api 113 */ 114 public static final String ORGANIZATION_NAME = "OrganizationName"; 115 public static final String DELEGATION_REALM = 116 "/sunamhiddenrealmdelegationservicepermissions"; 117 118 public static final String NAMED_POLICY = "Policies"; 119 static final String REALM_SUBJECTS = "RealmSubjects"; 120 static final String XML_REALM_SUBJECTS = "xmlRealmSubjects"; 121 private static final String NAMED_POLICY_ID = "NamedPolicy"; 122 static final String RESOURCES_POLICY = "Resources"; 123 static final String RESOURCES_POLICY_ID = "ServiceType"; 124 private static final String SUBJECTS_POLICY = "Subjects"; 125 static final String SUBJECT_POLICY = "Subject"; 126 static final String REALM_SUBJECT_POLICY = "RealmSubject"; 127 static final String CONDITION_POLICY = "Condition"; 128 static final String RESP_PROVIDER_POLICY = "ResponseProvider"; 129 static final String REFERRAL_POLICY = "Referral"; 130 static final String REFERRALS_POLICY = "Referrals"; 131 private static final String POLICY_XML = "xmlpolicy"; 132 static final String POLICY_VERSION = "1.0"; 133 134 public static final String POLICY_ROOT_NODE = "Policy"; 135 static final String POLICY_RULE_NODE = "Rule"; 136 static final String POLICY_SUBJECTS_NODE = "Subjects"; 137 static final String POLICY_CONDITIONS_NODE = "Conditions"; 138 static final String POLICY_RESP_PROVIDERS_NODE = "ResponseProviders"; 139 static final String POLICY_REFERRALS_NODE = "Referrals"; 140 static final String POLICY_RULE_SERVICE_NODE = "ServiceName"; 141 static final String POLICY_RULE_RESOURCE_NODE = "ResourceName"; 142 static final String POLICY_RULE_EXCLUDED_RESOURCE_NODE = 143 "ExcludedResourceName"; 144 static final String POLICY_RULE_APPLICATION_NAME_NODE = "ApplicationName"; 145 static final String ATTR_VALUE_PAIR_NODE = "AttributeValuePair"; 146 static final String ATTR_NODE = "Attribute"; 147 static final String ATTR_VALUE_NODE = "Value"; 148 static final String NAME_ATTRIBUTE = "name"; 149 static final String TYPE_ATTRIBUTE = "type"; 150 static final String DESCRIPTION_ATTRIBUTE = "description"; 151 static final String CREATED_BY_ATTRIBUTE = "createdby"; 152 static final String CREATION_DATE_ATTRIBUTE = "creationdate"; 153 static final String LAST_MODIFIED_BY_ATTRIBUTE = "lastmodifiedby"; 154 static final String LAST_MODIFIED_DATE_ATTRIBUTE = "lastmodifieddate"; 155 static final String PRIORITY_ATTRIBUTE = "priority"; 156 static final String STATUS_ATTRIBUTE = "priority"; 157 static final String STATUS_ACTIVE = "active"; 158 static final String STATUS_INACTIVE = "inactive"; 159 static final String SERVICE_TYPE_NAME_ATTRIBUTE = "serviceName"; 160 161 static final String POLICY_INDEX_ROOT_NODE = "PolicyCrossReferences"; 162 static final String POLICY_INDEX_ROOT_NODE_NAME_ATTR = "name"; 163 static final String POLICY_INDEX_ROOT_NODE_TYPE_ATTR = "type"; 164 static final String 165 POLICY_INDEX_ROOT_NODE_TYPE_ATTR_RESOURCES_VALUE = "Resources"; 166 static final String POLICY_INDEX_REFERENCE_NODE = "Reference"; 167 static final String POLICY_INDEX_REFERENCE_NODE_NAME_ATTR = "name"; 168 static final String POLICY_INDEX_POLICYNAME_NODE = "PolicyName"; 169 static final String POLICY_INDEX_POLICYNAME_NODE_NAME_ATTR = "name"; 170 static final long DEFAULT_SUBJECTS_RESULT_TTL = 10 * 60 * 1000; 171 172 static final String WEB_AGENT_SERVICE = "iPlanetAMWebAgentService"; 173 public static final String ID_REPO_SERVICE = "sunIdentityRepositoryService"; 174 public static final String ORG_ALIAS = "sunOrganizationAliases"; 175 public static final String ORG_ALIAS_URL_HTTP_PREFIX = "http://"; 176 public static final String ORG_ALIAS_URL_HTTPS_PREFIX = "https://"; 177 public static final String ORG_ALIAS_URL_SUFFIX = ":*"; 178 179 private String org = "/"; 180 private String givenOrgName = ""; 181 private ServiceConfigManager scm; 182 private OrganizationConfigManager ocm; 183 private ResourceManager rm; 184 private ServiceTypeManager svtm; 185 private SubjectTypeManager stm; 186 private ConditionTypeManager ctm; 187 private ResponseProviderTypeManager rpm; 188 private ReferralTypeManager rtm; 189 private PolicyCache policyCache; 190 private ResourceIndexManager rim; 191 private final LockFactory<String> lockFactory; 192 193 private static ServiceSchemaManager ssm; 194 private static javax.security.auth.Subject adminSubject; 195 196 SSOToken token; 197 198 // Can be shared by classes 199 static Debug debug = Debug.getInstance(POLICY_DEBUG_NAME); 200 static DN delegationRealm = DN.valueOf(DNMapper.orgNameToDN(DELEGATION_REALM)); 201 202 /** 203 * Constructor for <code>PolicyManager</code> for the 204 * top (or root) organization. It requires a <code>SSOToken 205 * </code> which will be used to perform all data store 206 * operations. If the user does not have sufficient 207 * privileges <code>NoPermissionException</code> will be thrown. 208 * 209 * @param token <code>SSOToken</code> of the user managing policy 210 * 211 * @throws SSOException invalid or expired single-sign-on token 212 * @throws PolicyException for any other abnormal condition 213 * 214 * @supported.api 215 */ 216 public PolicyManager(SSOToken token) throws SSOException, PolicyException { 217 this(token, ""); 218 if (debug.messageEnabled()) { 219 debug.message("Policy Manager constructed using SSO token"); 220 } 221 } 222 223 /** 224 * Constructor for <code>PolicyManager</code> for the 225 * specified organization, sub organization or a container object. 226 * The names of the organization, sub organization or the 227 * container object could be either "/" separated (as per SMS) 228 * or could be the complete DN of the object. 229 * For example: <code>/isp/coke<code>, <code>/isp/pepsi/tacobell<code>, 230 * etc., or <code>"ou=tacobell, o=pepsi, o=isp"<code>, 231 * <code>"o=coke, o=isp"</code>, etc. 232 * The constructor also requires a single sign on token. 233 * which will be used to perform all data store 234 * operations. If the user does not have sufficient 235 * privileges <code>NoPermissionException</code> will be thrown. 236 * 237 * @param token single-sign-on token of the user managing policies 238 * @param name name of the organization, sub organization 239 * or container for which to manage policies. 240 * The name could be either slash (/) separated 241 * or the complete DN. 242 * 243 * @throws SSOException invalid or expired single-sign-on token 244 * @throws NameNotFoundException if the given organization, 245 * sub-organization or container name is not present 246 * @throws PolicyException for any other abnormal condition 247 * 248 * @supported.api 249 */ 250 public PolicyManager(SSOToken token, String name) 251 throws SSOException, NameNotFoundException, PolicyException { 252 SSOTokenManager.getInstance().validateToken(token); 253 this.token = token; 254 try { 255 scm = new ServiceConfigManager(POLICY_SERVICE_NAME, token); 256 257 // Check name i.e., org name 258 org = verifyOrgName(name); 259 givenOrgName = name; 260 261 rm = new ResourceManager(org); 262 } catch (SMSException se) { 263 debug.error("In constructor for PolicyManager with orgName" + 264 "Unable to get service config manager", se); 265 throw (new PolicyException(se)); 266 } 267 268 if (debug.messageEnabled()) { 269 debug.message("Policy Manager constructed with SSO token " + 270 " for organization: " + org); 271 } 272 if (SystemProperties.isServerMode()) { 273 policyCache = PolicyCache.getInstance(); 274 svtm = ServiceTypeManager.getServiceTypeManager(); 275 } else { 276 policyCache = PolicyCache.getInstance(token); 277 svtm = new ServiceTypeManager(token); 278 } 279 rim = new ResourceIndexManager(rm); 280 281 // Retrieves a singleton instance of LockFactory shared across policy. 282 lockFactory = PolicyLockFactory.INSTANCE.getFactory(); 283 } 284 285 /** 286 * Gets the organization name for which the policy manager 287 * was initialized with. The organization name could either be 288 * slash ("/") separated or could be the distinguished name 289 * depending on the manner in which it was initialized. 290 * 291 * @return organization name for which the policy manager was 292 * instantiated 293 * 294 * @supported.api 295 */ 296 public String getOrganizationName() { 297 return (givenOrgName); 298 } 299 300 /** 301 * Gets the policy config attribute values defined for this policy manager 302 * @return policy config attributes defined for this policy manager. Also, 303 * includes the organization distinguished name. 304 */ 305 public Map getPolicyConfig() { 306 Map policyConfig = null; 307 try { 308 policyConfig = PolicyConfig.getPolicyConfig(org); 309 } catch (PolicyException pe) { 310 debug.error("PolicyManager:can not get policy config " 311 + " for org : " + org, pe); 312 } 313 if (policyConfig != null) { 314 Set set = new HashSet(); 315 set.add(org); 316 policyConfig.put(ORGANIZATION_NAME, set); 317 } else { 318 debug.error("PolicyManager: policy config is null for org:" 319 + org + ". Most likely it has been unregistered." 320 + " It is not recommended to unregister the policy" 321 + " configuration serivce. If you do so, the result" 322 + " is undefined."); 323 } 324 return policyConfig; 325 } 326 327 /** 328 * Gets the organization DN 329 * @return DN of the organization for which this policy manager 330 * was created 331 */ 332 String getOrganizationDN() { 333 return (org); 334 } 335 336 /** 337 * Gets a set of names of polices defined in the 338 * organization for which the policy manager was instantiated. 339 * If there are no policies defined, this method returns 340 * an empty set (not null). 341 * 342 * @return <code>Set</code> of names of policies defined in the organization 343 * 344 * @throws SSOException invalid or expired single-sign-on token 345 * @throws NoPermissionException user does not have sufficient 346 * privileges to get policy names 347 * @throws PolicyException for any other abnormal condition 348 * 349 * @supported.api 350 */ 351 public Set getPolicyNames() throws SSOException, NoPermissionException, 352 PolicyException { 353 return (getPolicyNames("*")); 354 } 355 356 /** 357 * Gets a set of selected policy names matching the 358 * pattern in the given organization. The pattern 359 * accepts "*" as the wild card for searching policy names. 360 * For example if the pattern is "co*", it returns policies 361 * starting with "co". Similarly, if the pattern is "*net", it returns 362 * policies ending with "net". The wildcard can be anywhere in the 363 * the string. If there are no policies that match the provided filter, 364 * this method returns an empty set (not null). 365 * 366 * @param pattern search pattern that will be used to select policy names 367 * 368 * @return <code>Set</code> of policy names that satisfy the pattern 369 * 370 * @throws SSOException invalid or expired single-sign-on token 371 * @throws NoPermissionException user does not have sufficient 372 * privileges to get policy names 373 * @throws PolicyException for any other abnormal condition 374 * 375 * @supported.api 376 */ 377 public Set getPolicyNames(String pattern) throws SSOException, 378 NoPermissionException, PolicyException { 379 try { 380 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 381 ServiceConfig namedPolicy = (oConfig == null) ? null : 382 oConfig.getSubConfig(NAMED_POLICY); 383 if (namedPolicy == null) { 384 return (Collections.EMPTY_SET); 385 } else { 386 if (pattern.equals("*")) { 387 return (namedPolicy.getSubConfigNames()); 388 } else { 389 return (namedPolicy.getSubConfigNames(pattern)); 390 } 391 } 392 } catch (SMSException se) { 393 debug.error("Unable to get named policies for organization: " 394 + org); 395 // Check for permission exception 396 String objs[] = { org }; 397 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 398 throw (new NoPermissionException(ResBundleUtils.rbName, 399 "insufficient_access_rights", null)); 400 } else { 401 // Throw generic policy exception 402 throw (new PolicyException(ResBundleUtils.rbName, 403 "unable_to_get_policies_for_organization", objs, 404 se)); 405 } 406 } 407 } 408 409 /** 410 * Gets the LDAP DN (distinguished name) for the named policy 411 * @param policyName name of the policy 412 * @return DN of the policy 413 * @throws SSOException if single sign on token associated with the policy 414 * manager is not valid. 415 * @throws NoPermissionException if not enough permissions 416 * @throws NameNotFoundException if the policy is not found 417 * @throws PolicyException for any other abnormal condition 418 * 419 */ 420 public String getPolicyDN(String policyName) throws 421 SSOException, NoPermissionException, NameNotFoundException, 422 PolicyException { 423 // Get the policy. If the policy does not exists it will 424 // throw NameNotFoundException 425 getPolicy(policyName); 426 427 // Policy is present, construct the DN and return 428 StringBuilder answer = new StringBuilder(100); 429 answer.append("ou="); 430 answer.append(policyName); 431 answer.append(",ou="); 432 answer.append(NAMED_POLICY); 433 answer.append(",ou=default,ou=organizationConfig,ou="); 434 answer.append(POLICY_VERSION); 435 answer.append(",ou="); 436 answer.append(POLICY_SERVICE_NAME); 437 answer.append(",ou=services,"); 438 answer.append(org); 439 return (answer.toString()); 440 } 441 442 /** 443 * Gets the policy object given the name of the policy. 444 * 445 * @param policyName name of the policy 446 * @return policy with the given policy name 447 * @throws SSOException if single sign on token associated with the policy 448 * manager is not valid. 449 * @throws NoPermissionException if not enough permissions. 450 * @throws InvalidFormatException if <code>policyName</code> has 451 * invalid format. 452 * @throws NameNotFoundException if the policy is not found. 453 * @throws InvalidNameException if <code>policyName</code> is invalid. 454 * @throws PolicyException for any other abnormal condition. 455 * 456 * 457 * @supported.api 458 */ 459 public Policy getPolicy(String policyName) throws SSOException, 460 NoPermissionException, InvalidFormatException, 461 NameNotFoundException, 462 InvalidNameException, PolicyException { 463 if (policyName == null) { 464 throw (new InvalidNameException(ResBundleUtils.rbName, 465 "null_name", null, "null", PolicyException.POLICY)); 466 } 467 if (debug.messageEnabled()) { 468 debug.message("searching for named policy: " + policyName + 469 " in organization: " + org); 470 } 471 472 // Check the cache %%% Need to have notification for policy changes 473 Policy answer = null; 474 475 try { 476 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 477 ServiceConfig namedPolicy = (oConfig == null) ? null : 478 oConfig.getSubConfig(NAMED_POLICY); 479 ServiceConfig policy = null; 480 Map attrs = null; 481 Set res = null; 482 if ((namedPolicy == null) || 483 ((policy = namedPolicy.getSubConfig(policyName)) == null) || 484 ((attrs = policy.getAttributes()) == null) || 485 ((res = (Set) attrs.get(POLICY_XML)) == null) || 486 (res.size() <= 0)) { 487 // Named policy node or policy node does not exist 488 if (debug.warningEnabled()) { 489 debug.warning("Unable to find named policy: " + policyName + 490 " in organization: " + org); 491 } 492 String objs[] = { policyName, org }; 493 throw (new NameNotFoundException(ResBundleUtils.rbName, 494 "policy_not_found_in_organization", objs, policyName, 495 PolicyException.POLICY)); 496 } 497 498 // Now create a policy object out of the XML blob 499 Iterator it = res.iterator(); 500 String policyXml = (String) it.next(); 501 Document doc = null; 502 try { 503 doc = XMLUtils.getXMLDocument( 504 new ByteArrayInputStream(policyXml.getBytes("UTF8"))); 505 } catch (Exception xmle) { 506 debug.error("XML parsing error for policy: " + policyName + 507 " in organization: " + org); 508 // throw generic policy exception 509 throw (new PolicyException(xmle)); 510 } 511 Node rootNode = XMLUtils.getRootNode(doc, POLICY_ROOT_NODE); 512 if (rootNode == null) { 513 debug.error("invalid xml policy blob for named policy: " + 514 policyName + " in organization: " + org); 515 throw (new InvalidFormatException(ResBundleUtils.rbName, 516 "invalid_xml_policy_root_node", null, policyName, 517 PolicyException.POLICY)); 518 } 519 520 if (debug.messageEnabled()) { 521 debug.message("returning named policy: " + policyName + 522 " for organization: " + org); 523 } 524 525 // Return the policy object 526 answer = new Policy(this, rootNode); 527 Map policyConfig = getPolicyConfig(); 528 if (policyConfig != null) { 529 answer.setSubjectsResultTtl( 530 PolicyConfig.getSubjectsResultTtl(policyConfig)); 531 } 532 533 return (answer); 534 } catch (SMSException se) { 535 debug.error("SMS error in finding named policy: " + policyName + 536 " in organization: " + org); 537 // Check for permission exception 538 String objs[] = { policyName, org }; 539 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 540 throw (new NoPermissionException(ResBundleUtils.rbName, 541 "insufficient_access_rights", null)); 542 } else { 543 // Throw generic policy exception 544 throw (new PolicyException(ResBundleUtils.rbName, 545 "unable_to_get_policy", objs, se)); 546 } 547 } 548 549 } 550 551 /** 552 * Adds a policy to the data store. 553 * 554 * @param policy policy object to be added to the organization 555 * 556 * @throws SSOException invalid or expired single-sign-on token 557 * @throws NoPermissionException user does not have sufficient 558 * privileges to add policy 559 * @throws InvalidFormatException the data in the policy object 560 * has been corrupted or does not have a valid format 561 * @throws NameAlreadyExistsException a policy with the same 562 * name already exists 563 * @throws PolicyException for any other abnormal condition 564 * 565 * @supported.api 566 */ 567 public void addPolicy(Policy policy) throws SSOException, 568 NameAlreadyExistsException, NoPermissionException, 569 InvalidFormatException, PolicyException { 570 571 String realmName = getOrganizationDN(); 572 PolicyManager.initAdminSubject(); 573 574 //TODO: handle non DNs/ 575 realmName = LDAPUtils.formatToRFC(realmName); 576 String subjectRealm = policy.getSubjectRealm(); 577 String[] realmNames = {realmName, subjectRealm}; 578 if ((subjectRealm != null) && !subjectRealm.equals(realmName)) { 579 if (debug.messageEnabled()) { 580 debug.message("Can not add policy in realm :" 581 + realmName + ", policy has realm subjects " 582 + " from realm : " + subjectRealm); 583 } 584 585 //TODO : add logging? 586 587 throw (new InvalidFormatException(ResBundleUtils.rbName, 588 "policy_realm_does_not_match", realmNames, null, realmName, 589 PolicyException.POLICY)); 590 } 591 validateForResourcePrefix(policy); 592 validateReferrals(policy); 593 594 String testCreatedBy = policy.getCreatedBy(); 595 //testCreatedBy is set if we are doing policy replaced. 596 if ((testCreatedBy == null) || (testCreatedBy.length() == 0)) { 597 Date creationDate = Time.newDate(); 598 policy.setCreatedBy(token.getPrincipal().getName()); 599 policy.setCreationDate(creationDate.getTime()); 600 policy.setLastModifiedBy(token.getPrincipal().getName()); 601 policy.setLastModifiedDate(creationDate.getTime()); 602 } 603 604 // Construct the named policy 605 String policyXml = policy.toXML(); 606 Map attrs = new HashMap(); 607 Set set = new HashSet(); 608 set.add(policyXml); 609 attrs.put(POLICY_XML, set); 610 611 // Get(create if necessary) ou=policies entry 612 ServiceConfig namedPolicy = createOrGetPolicyConfig( 613 NAMED_POLICY, NAMED_POLICY, scm, org); 614 try { 615 //create the policy entry 616 namedPolicy.addSubConfig(policy.getName(), 617 NAMED_POLICY_ID, 0, attrs); 618 PrivilegeIndexStore pis = PrivilegeIndexStore.getInstance( 619 adminSubject, realmName); 620 Set<IPrivilege> privileges = PrivilegeUtils.policyToPrivileges( 621 policy); 622 pis.add(privileges); 623 policyCache.sendPolicyChangeNotification(null, policy, 624 ServiceListener.ADDED); 625 } catch (EntitlementException e) { 626 String[] objs = { policy.getName(), org }; 627 throw (new PolicyException(ResBundleUtils.rbName, 628 "unable_to_add_policy", objs, e)); 629 } catch (ServiceAlreadyExistsException e) { 630 String[] objs = { policy.getName(), org }; 631 if (PolicyUtils.logStatus) { 632 PolicyUtils.logErrorMessage( 633 "POLICY_ALREADY_EXISTS_IN_REALM", objs, token); 634 } 635 throw (new NameAlreadyExistsException(ResBundleUtils.rbName, 636 "policy_already_exists_in_org", objs, policy.getName(), 637 PolicyException.POLICY)); 638 } catch (SMSException se) { 639 String[] objs = { policy.getName(), org }; 640 if (PolicyUtils.logStatus) { 641 PolicyUtils.logErrorMessage("UNABLE_TO_ADD_POLICY", objs, 642 token); 643 } 644 debug.error("SMS error in add policy: " + 645 policy.getName() + " for org: " + org, se); 646 647 // Check for permission exception 648 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 649 throw (new NoPermissionException(ResBundleUtils.rbName, 650 "insufficient_access_rights", null)); 651 } else { 652 // Throw generic policy exception 653 throw (new PolicyException(ResBundleUtils.rbName, 654 "unable_to_add_policy", 655 objs, se)); 656 } 657 } 658 if (PolicyUtils.logStatus) { 659 String[] objs = { policy.getName(), org }; 660 PolicyUtils.logAccessMessage("POLICY_CREATE_SUCCESS", objs, token); 661 } 662 } 663 664 /** 665 * Replaces a policy object in the data store with the same policy name 666 * 667 * @param policy policy object to be added to the organization 668 * 669 * @throws SSOException invalid or expired single-sign-on token 670 * @throws NoPermissionException user does not have sufficient 671 * privileges to replace policy 672 * @throws NameNotFoundException policy with the same name does 673 * not exist. 674 * @throws InvalidFormatException the provide policy from the 675 * data store has been corrupted or does not have a valid format 676 * @throws PolicyException for any other abnormal condition. 677 * 678 * @supported.api 679 */ 680 public void replacePolicy(Policy policy) throws SSOException, 681 NameNotFoundException, NoPermissionException, 682 InvalidFormatException, PolicyException { 683 684 PolicyManager.initAdminSubject(); 685 String realm = getOrganizationDN(); 686 String subjectRealm = policy.getSubjectRealm(); 687 String[] realmNames = {realm, subjectRealm}; 688 if ((subjectRealm != null) && !subjectRealm.equals(realm)) { 689 690 if (debug.messageEnabled()) { 691 debug.message("Can not replace policy in realm :" 692 + realm + ", policy has realm subjects " 693 + " from realm : " + subjectRealm); 694 } 695 696 throw (new InvalidFormatException(ResBundleUtils.rbName, 697 "policy_realm_does_not_match", realmNames, null, realm, 698 PolicyException.POLICY)); 699 } 700 701 policy.setLastModifiedBy(token.getPrincipal().getName()); 702 Date lastModifiedDate = Time.newDate(); 703 policy.setLastModifiedDate(lastModifiedDate.getTime()); 704 705 // Construct the named policy 706 String policyXml = policy.toXML(); 707 Map attrs = new HashMap(); 708 Set set = new HashSet(); 709 set.add(policyXml); 710 attrs.put(POLICY_XML, set); 711 712 String name = null; 713 // Get(create if necessary) ou=policies entry 714 ServiceConfig namedPolicy = createOrGetPolicyConfig( 715 NAMED_POLICY, NAMED_POLICY, scm, org); 716 try { 717 String policyName = policy.getName(); 718 String oldPolicyName = policy.getOriginalName(); 719 ServiceConfig policyEntry = namedPolicy.getSubConfig(policyName); 720 ServiceConfig oldPolicyEntry = null; 721 if ( oldPolicyName != null ) { 722 oldPolicyEntry = namedPolicy.getSubConfig(oldPolicyName); 723 name = oldPolicyName; 724 } else { 725 name = policy.getName(); 726 } 727 if ( policyEntry == null ) { 728 if ( oldPolicyEntry != null ) { 729 removePolicy(oldPolicyName); 730 addPolicy(policy); 731 // reset the policy name 732 // TODO: need to think this through 733 policy.resetOriginalName(); 734 } else { 735 // neither the new policy nor the old policy is present 736 String objs[] = { policy.getName(), org }; 737 throw (new NameNotFoundException(ResBundleUtils.rbName, 738 "policy_not_found_in_organization", objs, 739 policy.getName(), PolicyException.POLICY)); 740 } 741 } else { //newPolicy exisits 742 String[] objs = { policy.getName(), org }; 743 if((oldPolicyName != null) && 744 !policy.getName().equalsIgnoreCase(oldPolicyName)) { 745 if (PolicyUtils.logStatus) { 746 PolicyUtils.logErrorMessage( 747 "DID_NOT_REPLACE_POLICY", 748 objs, token); 749 } 750 throw (new NameAlreadyExistsException(ResBundleUtils.rbName, 751 "policy_already_exists_in_org", objs, policy.getName(), 752 PolicyException.POLICY)); 753 } 754 755 Policy oldPolicy = getPolicy(policy.getName()); 756 validateForResourcePrefix(policy); 757 validateReferrals(policy); 758 policyEntry.setAttributes(attrs); 759 if (oldPolicy != null) { 760 // Acquire lock to ensure atomicity when updating policy. 761 Lock lock = lockFactory.acquireLock(policyName); 762 763 try { 764 lock.lock(); 765 PrivilegeIndexStore pis = PrivilegeIndexStore.getInstance( 766 SubjectUtils.createSubject(token), realm); 767 pis.delete(PrivilegeUtils.policyToPrivileges(oldPolicy)); 768 pis.add(PrivilegeUtils.policyToPrivileges(policy)); 769 } finally { 770 lock.unlock(); 771 } 772 773 policyCache.sendPolicyChangeNotification(oldPolicy, policy, ServiceListener.MODIFIED); 774 } 775 } 776 } catch (EntitlementException e) { 777 String[] objs = { name, org }; 778 throw (new PolicyException(ResBundleUtils.rbName, 779 "unable_to_replace_policy", objs, e)); 780 } catch (SMSException se) { 781 String[] objs = { name, org }; 782 if (PolicyUtils.logStatus) { 783 PolicyUtils.logErrorMessage("UNABLE_TO_REPLACE_POLICY", objs, 784 token); 785 } 786 debug.error("SMS error in replacing policy: " + 787 policy.getOriginalName() + " for org: " + org, se); 788 // Check for permission exception 789 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 790 throw (new NoPermissionException(ResBundleUtils.rbName, 791 "insufficient_access_rights", null)); 792 } else { 793 // Throw generic policy exception 794 throw (new PolicyException(ResBundleUtils.rbName, 795 "unable_to_replace_policy", objs, se)); 796 } 797 } 798 if (PolicyUtils.logStatus) { 799 String[] objs = { name, org }; 800 PolicyUtils.logAccessMessage("POLICY_MODIFY_SUCCESS", objs, token); 801 } 802 } 803 804 /** 805 * Deletes a policy in the organization with the given name. 806 * 807 * @param policyName name of the policy to be deleted 808 * 809 * @throws SSOException invalid or expired single-sign-on token 810 * @throws NoPermissionException user does not have sufficient 811 * privileges to remove policies 812 * @throws PolicyException for any other abnormal condition 813 * 814 * @supported.api 815 */ 816 public void removePolicy(String policyName) throws 817 SSOException, NoPermissionException, PolicyException { 818 // Check if name is valid 819 if (policyName == null) { 820 if (debug.warningEnabled()) { 821 debug.warning("In PolicyManager::removePolicy(), name is null"); 822 } 823 throw (new InvalidNameException(ResBundleUtils.rbName, 824 "null_name", null, "null", PolicyException.POLICY)); 825 } 826 827 try { 828 PolicyManager.initAdminSubject(); 829 // Get service config for named policy node 830 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 831 ServiceConfig namedPolicy = (oConfig == null) ? null : 832 oConfig.getSubConfig(NAMED_POLICY); 833 if (namedPolicy != null) { 834 /* Remove the named policy 835 * before removing the named policy 836 * prepare for changes in resources tree 837 */ 838 Policy policy = getPolicy(policyName); 839 840 // do the removal of policy 841 namedPolicy.removeSubConfig(policyName); 842 843 if (policy != null) { 844 // should use super admin token to remove the index store 845 // entry 846 PrivilegeIndexStore pis = PrivilegeIndexStore. 847 getInstance( 848 SubjectUtils.createSuperAdminSubject(), 849 getOrganizationDN()); 850 if (policy.isReferralPolicy()) { 851 pis.deleteReferral((policyName)); 852 } else { 853 pis.delete( 854 PrivilegeUtils.policyToPrivileges(policy)); 855 } 856 policyCache.sendPolicyChangeNotification(null, policy, 857 ServiceListener.REMOVED); 858 } 859 } 860 } catch (EntitlementException e) { 861 debug.error("Error while removing policy : " + e.getMessage()); 862 } catch (ServiceNotFoundException snfe) { 863 debug.error("Error while removing policy : " + 864 snfe.getMessage() ); 865 } catch (SMSException smse) { 866 String objs[] = { policyName, org }; 867 if (PolicyUtils.logStatus) { 868 PolicyUtils.logErrorMessage("UNABLE_TO_REMOVE_POLICY", objs, 869 token); 870 } 871 debug.error("SMS error in deleting policy: " + 872 policyName + " for org: " + org, smse); 873 // Check for permission exception 874 if (smse.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 875 throw (new NoPermissionException(ResBundleUtils.rbName, 876 "insufficient_access_rights", null)); 877 } else { 878 // Throw generic policy exception 879 throw (new PolicyException(ResBundleUtils.rbName, 880 "unable_to_remove_policy", objs, smse)); 881 } 882 } 883 String objs[] = { policyName, org }; 884 if (PolicyUtils.logStatus) { 885 PolicyUtils.logAccessMessage("POLICY_REMOVE_SUCCESS", objs, token); 886 } 887 } 888 889 /** 890 * Gets the <code>ResourceManager</code> object instance associated 891 * with this <code>PolicyManager</code> object instance 892 * 893 * @return <code>ResourceManager</code> object 894 * 895 * @supported.api 896 */ 897 public ResourceManager getResourceManager() { 898 return rm; 899 } 900 901 /** 902 * Gets the <code>SubjectTypeManager</code> object instance associated 903 * with this <code>PolicyManager</code> object instance 904 * 905 * @return <code>SubjectTypeManager</code> object 906 * 907 * @supported.api 908 */ 909 public SubjectTypeManager getSubjectTypeManager() { 910 if (stm == null) { 911 stm = new SubjectTypeManager(this); 912 } 913 return (stm); 914 } 915 916 /** 917 * Gets the <code>ConditionTypeManager</code> object instance associated 918 * with this <code>PolicyManager</code> object instance 919 * 920 * @return <code>ConditionTypeManager</code> object 921 * 922 * @supported.api 923 */ 924 public ConditionTypeManager getConditionTypeManager() { 925 if (ctm == null) { 926 ctm = new ConditionTypeManager(this); 927 } 928 return (ctm); 929 } 930 931 /** 932 * Gets the <code>ResponseProviderTypeManager</code> object instance 933 * associated with this <code>PolicyManager</code> object instance 934 * 935 * @return <code>ResponseProviderTypeManager</code> object 936 * 937 */ 938 public ResponseProviderTypeManager getResponseProviderTypeManager() { 939 if (rpm == null) { 940 rpm = new ResponseProviderTypeManager(this); 941 } 942 return (rpm); 943 } 944 945 /** Creates or gets a node (namedPolicy, resources, or userCollection) 946 * under ou=policies 947 */ 948 static ServiceConfig createOrGetPolicyConfig(String configName, 949 String configId, ServiceConfigManager scm, String org) 950 throws NoPermissionException, PolicyException, SSOException { 951 // Get service config that represents named policy node 952 ServiceConfig sConfig = null; 953 try { 954 ServiceConfig oConfig = scm.getOrganizationConfig(org, null); 955 sConfig = (oConfig == null) ? null : 956 oConfig.getSubConfig(configName); 957 if (sConfig == null) { 958 if (debug.messageEnabled()) { 959 debug.message("Creating the " + configName + 960 " tree for org: " + org); 961 } 962 // create the named policy node 963 createPolicyTree(configName, configId, scm, org); 964 965 // Check if policy tree is created 966 if (oConfig == null) { 967 oConfig = scm.getOrganizationConfig(org, null); 968 } 969 if ((oConfig == null) || ((sConfig = oConfig.getSubConfig( 970 configName)) == null)) { 971 // Throw generic policy exception 972 String objs[] = { configName }; 973 throw (new PolicyException(ResBundleUtils.rbName, 974 "unable_to_get_policy_node", objs, null)); 975 } 976 } 977 } catch (SMSException smse) { 978 // Debug messages 979 debug.error("SMS error in creating " + configName + 980 " node for org: " + org, smse); 981 982 // Check for permission exception 983 if (smse.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 984 String objs[] = { configName }; 985 throw (new NoPermissionException(ResBundleUtils.rbName, 986 "insufficient_access_rights", objs)); 987 } else { 988 // Throw generic policy exception 989 String objs[] = { configName }; 990 throw (new PolicyException(ResBundleUtils.rbName, 991 "unable_to_get_policy_node", objs, smse)); 992 } 993 } 994 return (sConfig); 995 } 996 997 /** 998 * Creates the policy tree, ou=policy, ou=services, ... 999 */ 1000 static void createPolicyTree(String configName, String configId, 1001 ServiceConfigManager scm, String org) throws NoPermissionException, 1002 PolicyException, SSOException { 1003 try { 1004 // Get the iPlanetPolicyService node 1005 ServiceConfig pConfig = scm.getOrganizationConfig(org, null); 1006 if (pConfig == null) { 1007 // Since not present, create organization services node 1008 // i.e, ou=services, <org dn> and ou=iPlanetPolicyService, 1009 // ou=services, ... 1010 scm.createOrganizationConfig(org, null); 1011 // Since it is created above, get it 1012 pConfig = scm.getOrganizationConfig(org, null); 1013 } 1014 // Create requested policy sub node 1015 // i.e., ou=<configName>, ou=iPlanetPolicyService, ou=services, ... 1016 pConfig.addSubConfig(configName, configId, 0, null); 1017 } catch (ServiceAlreadyExistsException se) { 1018 // do nothing 1019 if (debug.messageEnabled()) { 1020 debug.message("PolicyManager->createPolicyTree: Name: " + 1021 configName + " ID: " + configId + 1022 " Policy service already exists under org->" + org); 1023 } 1024 } catch (SMSException e) { 1025 // Check for permission exception 1026 String[] objs = { org }; 1027 if (e.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 1028 throw (new NoPermissionException(ResBundleUtils.rbName, 1029 "insufficient_access_rights", null)); 1030 } else { 1031 throw (new PolicyException(ResBundleUtils.rbName, 1032 "unable_to_create_policy_for_org", objs, e)); 1033 } 1034 } 1035 } 1036 1037 /** 1038 * Verifies if the name, which specifies a organization, 1039 * a suborganization or a container object, is in DN format; If not, 1040 * the name will be converted to a DN. Furthermore, whether the entry 1041 * corresponding to the DN exists is also checked. 1042 * 1043 * @param name name of the organization, suborganization 1044 * or container for which to manage policies. 1045 * The name could be either slash (/) separated 1046 * or the complete DN. 1047 * 1048 * @return the name in DN format (possibly converted from slash format) 1049 * 1050 * @throws SSOException invalid or expired single-sign-on token 1051 * @throws InvalidNameException the name is null 1052 * @throws NameNotFoundException if the given organization, 1053 * sub-organization or container name is not present 1054 */ 1055 String verifyOrgName(String name) 1056 throws InvalidNameException, NameNotFoundException, SSOException { 1057 String orgName = null; 1058 1059 // Check for null name 1060 if (name == null) { 1061 throw (new InvalidNameException(ResBundleUtils.rbName, "null_name", 1062 null, "null", PolicyException.ORGANIZATION)); 1063 } 1064 1065 /* this mapping call is required if name is not a DN 1066 * or if the name is not DN of a realm 1067 * This call is harmless if the DN is already DN of a realm 1068 */ 1069 orgName = DNMapper.orgNameToDN(name); 1070 1071 // Check to see if the organization exists 1072 // if not present throw NameNotFoundException 1073 if (!SMSEntry.checkIfEntryExists(orgName, token)) { 1074 if (debug.warningEnabled()) { 1075 debug.warning("Checking for organization name: " + 1076 orgName + " failed since entry does not exist"); 1077 } 1078 String[] objs = { name }; 1079 throw (new NameNotFoundException(ResBundleUtils.rbName, 1080 "org_not_found", objs, orgName, 1081 PolicyException.ORGANIZATION)); 1082 } 1083 return (orgName); 1084 } 1085 1086 /** 1087 * Gets a list of subordinate organizations or containers. If 1088 * there are no subordinate organizations or containers, returns 1089 * an empty set (not null). 1090 * 1091 * @return set of valid subordinate organizations or containers 1092 * 1093 * @throws SSOException invalid or expired single-sign-on token 1094 * @throws NoPermissionException user does not have sufficient 1095 * privileges to replace policy 1096 */ 1097 Set getSubOrganizationNames() throws SSOException, 1098 NoPermissionException, PolicyException { 1099 throw (new UnsupportedOperationException()); 1100 } 1101 1102 /** 1103 * Gets sub-organizations, given a filter. The filter 1104 * accepts "*" as the wild card for searching sub-organization names. 1105 * For example if the filter is "co*", it returns sub-organizations 1106 * starting with "co". Similarly, if the filter is "*net", it returns 1107 * sub-organizations ending with "net". 1108 * 1109 * @param filter the search filter that be used to 1110 * identify sub-organizations 1111 * 1112 * @return a set of sub-organizations 1113 */ 1114 Set getSubOrganizationNames(String filter) 1115 throws SSOException, PolicyException { 1116 throw (new UnsupportedOperationException()); 1117 } 1118 1119 /** 1120 * Gets sub-organization's policy manager. 1121 * 1122 * @param subOrgName name of the sub-organization organization. This 1123 * should be relative to the current organization. 1124 * 1125 * @return returns the policy manager for the organization; 1126 * else returns <code>null</code>. 1127 */ 1128 PolicyManager getSubOrganizationPolicyManager(String subOrgName) 1129 throws SSOException, PolicyException { 1130 // the assumption is that orgnames are / separated 1131 return (new PolicyManager(token, org + "/" + subOrgName)); 1132 } 1133 1134 /** 1135 * Gets <code>ServiceTypeManager</code> associated with this 1136 * policy manager 1137 */ 1138 ServiceTypeManager getServiceTypeManager() { 1139 return svtm; 1140 } 1141 1142 /** 1143 * Returns <code>ReferralTypeManager</code> associated with this 1144 * policy manager. 1145 * 1146 * @return <code>ReferralTypeManager</code> associated with this 1147 * policy manager. 1148 * @supported.api 1149 */ 1150 public ReferralTypeManager getReferralTypeManager() { 1151 if ( rtm == null ) { 1152 rtm = new ReferralTypeManager(this); 1153 } 1154 return rtm; 1155 } 1156 1157 1158 /** 1159 * Gets plugins schemas for a given interface name 1160 */ 1161 static Set getPluginSchemaNames(String interfaceName) { 1162 if (ssm == null || !ssm.isSSOTokenValid()) { 1163 try { 1164 ssm = new ServiceSchemaManager( 1165 PolicyManager.POLICY_SERVICE_NAME, 1166 ServiceTypeManager.getSSOToken()); 1167 } catch (Exception se) { 1168 PolicyManager.debug.error( 1169 "Cannot create service schema " + 1170 "manager for policy", se); 1171 return (Collections.EMPTY_SET); 1172 } 1173 } 1174 1175 Set answer = null; 1176 try { 1177 /* Get the plugin schema names for the root 1178 * In the future might want to customize it for org 1179 */ 1180 answer = ssm.getPluginSchemaNames(interfaceName, null); 1181 } catch (Exception e) { 1182 PolicyManager.debug.error( 1183 "Cannot get plugin schemas: " + 1184 interfaceName + " for policy", e); 1185 return (Collections.EMPTY_SET); 1186 } 1187 return ((answer == null) ? Collections.EMPTY_SET : answer); 1188 } 1189 1190 1191 /** 1192 * Gets PluginSchema object for the given plugin interface name 1193 * and plugin name. Returns <code>null</code> if not present. 1194 */ 1195 static PluginSchema getPluginSchema(String interfaceName, 1196 String pluginName) { 1197 Set plugins = getPluginSchemaNames(interfaceName); 1198 if (plugins.contains(pluginName)) { 1199 try { 1200 return (ssm.getPluginSchema(pluginName, interfaceName, null)); 1201 } catch (Exception e) { 1202 PolicyManager.debug.error( 1203 "Cannot get plugin schemas: " + 1204 interfaceName + " for policy", e); 1205 } 1206 } 1207 return (null); 1208 } 1209 1210 /** 1211 * Gets the view bean URL given the plugin type 1212 * and the plugin java class name 1213 * 1214 * @param pluginType type of plugin such as Subject, Referral, Condition 1215 * @param pluginClassName name of java class name implementing the plugin 1216 * type 1217 * 1218 * @return view bean URL defined for pluginType with name pluginName 1219 */ 1220 static String getViewBeanURL(String pluginType, String pluginClassName) { 1221 String viewBeanURL = null; 1222 if (pluginType != null) { 1223 Iterator items = PolicyManager.getPluginSchemaNames( 1224 pluginType).iterator(); 1225 while (items.hasNext()) { 1226 String pluginName = (String) items.next(); 1227 PluginSchema ps = PolicyManager.getPluginSchema(pluginType, 1228 pluginName); 1229 if (pluginClassName.equals(ps.getClassName())) { 1230 viewBeanURL = ps.getPropertiesViewBeanURL(); 1231 break; 1232 } 1233 } 1234 } 1235 return viewBeanURL; 1236 } 1237 1238 /** Gets a policy using policy cache. 1239 * @param policyName policy name 1240 * @param useCache flag to indicate whether to use cache or not 1241 * @return the policy with the given policy name 1242 * @throws SSOException 1243 * @throws NoPermissionException 1244 * @throws InvalidFormatException 1245 * @throws PolicyException 1246 */ 1247 Policy getPolicy(String policyName, boolean useCache) throws SSOException, 1248 NoPermissionException, InvalidFormatException, 1249 NameNotFoundException, 1250 InvalidFormatException, PolicyException { 1251 Policy policy = null; 1252 if ( useCache ) { 1253 policy = policyCache.getPolicy(org, policyName); 1254 } else { 1255 policy = getPolicy(policyName); 1256 } 1257 return policy; 1258 } 1259 1260 ResourceIndexManager getResourceIndexManager() { 1261 return rim; 1262 } 1263 1264 private boolean validateResourceForPrefix(ServiceType resourceType, 1265 String resourceName) throws PolicyException { 1266 Set<String> resourcePrefixes = Collections.emptySet(); 1267 return validateResourceForPrefix(resourceType, 1268 resourcePrefixes, resourceName); 1269 } 1270 1271 private boolean validateResourceForPrefixE( 1272 String realm, 1273 String serviceName, 1274 Set<String> resourcePrefixes, 1275 String resourceName) throws PolicyException, EntitlementException { 1276 1277 String realmName = LDAPUtils.isDN(realm) ? 1278 DNMapper.orgNameToRealmName(realm) :realm; 1279 1280 Application appl = getApplicationService(SUPER_ADMIN_SUBJECT, realmName).getApplication(serviceName); 1281 com.sun.identity.entitlement.interfaces.ResourceName resComp = appl. 1282 getResourceComparator(); 1283 resourceName = resComp.canonicalize(resourceName); 1284 1285 for (String prefix : resourcePrefixes) { 1286 boolean interpretWildCard = true; 1287 com.sun.identity.entitlement.ResourceMatch resMatch = 1288 resComp.compare(resourceName, 1289 resComp.canonicalize(prefix), interpretWildCard); 1290 if ( resMatch.equals( 1291 com.sun.identity.entitlement.ResourceMatch.SUPER_RESOURCE_MATCH) 1292 || resMatch.equals( 1293 com.sun.identity.entitlement.ResourceMatch.WILDCARD_MATCH) 1294 || resMatch.equals( 1295 com.sun.identity.entitlement.ResourceMatch.EXACT_MATCH) ) { 1296 return true; 1297 } 1298 1299 } 1300 return false; 1301 } 1302 1303 private boolean validateResourceForPrefix( 1304 ServiceType resourceType, 1305 Set<String> resourcePrefixes, 1306 String resourceName) throws PolicyException { 1307 1308 for (String prefix : resourcePrefixes) { 1309 boolean interpretWildCard = true; 1310 ResourceMatch resMatch = resourceType.compare(resourceName, prefix, 1311 interpretWildCard); 1312 if ( resMatch.equals(ResourceMatch.SUPER_RESOURCE_MATCH) 1313 || resMatch.equals(ResourceMatch.WILDCARD_MATCH) 1314 || resMatch.equals(ResourceMatch.EXACT_MATCH) ) { 1315 return true; 1316 } 1317 1318 } 1319 return false; 1320 } 1321 1322 private void validateForResourcePrefix(Policy policy) 1323 throws SSOException, PolicyException { 1324 DN orgDN = DN.valueOf(org); 1325 DN baseDN = DN.valueOf(ServiceManager.getBaseDN()); 1326 PolicyManager.initAdminSubject(); 1327 1328 if (!orgDN.equals(baseDN) && !orgDN.equals(delegationRealm)) { 1329 String realm = DNMapper.orgNameToRealmName(getOrganizationDN()); 1330 Iterator ruleNames = policy.getRuleNames().iterator(); 1331 while (ruleNames.hasNext()) { 1332 try { 1333 String ruleName = (String) ruleNames.next(); 1334 Rule rule = (Rule) policy.getRule(ruleName); 1335 String serviceTypeName = rule.getServiceTypeName(); 1336 String ruleResource = rule.getResourceName(); 1337 // Make sure adminSubject has been set before using 1338 if (adminSubject == null) { 1339 initialise(); 1340 } 1341 Set<String> referredResources = getApplicationService(adminSubject, realm) 1342 .getReferredResources(serviceTypeName); 1343 if ((referredResources == null) || referredResources. 1344 isEmpty()) { 1345 String[] objs = {org}; 1346 throw new PolicyException(ResBundleUtils.rbName, 1347 "no_referral_can_not_create_policy", objs, null); 1348 } 1349 ServiceType resourceType = getServiceTypeManager(). 1350 getServiceType(serviceTypeName); 1351 1352 if (!validateResourceForPrefixE(realm, serviceTypeName, 1353 referredResources, ruleResource)) { 1354 String[] objs = {ruleResource, resourceType.getName()}; 1355 throw new PolicyException(ResBundleUtils.rbName, 1356 "resource_name_not_permitted_by_prefix_names", objs, 1357 null); 1358 } 1359 } catch (EntitlementException ex) { 1360 String[] objs = {org}; 1361 throw new PolicyException(ResBundleUtils.rbName, 1362 "no_referral_can_not_create_policy", objs, null); 1363 } 1364 } 1365 } 1366 } 1367 1368 private void validateForResourcePrefixO(Policy policy) 1369 throws SSOException, PolicyException { 1370 DN orgDN = DN.valueOf(org); 1371 DN baseDN = DN.valueOf(ServiceManager.getBaseDN()); 1372 Set prefixes = getManagedResourceNames(); 1373 if (!orgDN.equals(baseDN) && !orgDN.equals(delegationRealm) 1374 && ((prefixes == null ) || prefixes.isEmpty()) ) { 1375 String[] objs = {org}; 1376 throw new PolicyException( 1377 ResBundleUtils.rbName, 1378 "no_referral_can_not_create_policy", objs, null); 1379 } 1380 Iterator ruleNames = policy.getRuleNames().iterator(); 1381 while ( ruleNames.hasNext() ) { 1382 String ruleName = (String) ruleNames.next(); 1383 Rule rule = (Rule) policy.getRule(ruleName); 1384 String serviceTypeName = rule.getServiceTypeName(); 1385 ServiceType resourceType = getServiceTypeManager() 1386 .getServiceType(serviceTypeName); 1387 String ruleResource = rule.getResourceName(); 1388 boolean validResource = true; 1389 if (!orgDN.equals(baseDN) && !orgDN.equals(delegationRealm)) { 1390 validResource = validateResourceForPrefix(resourceType, 1391 ruleResource); 1392 } 1393 if (!validResource) { 1394 String[] objs = { ruleResource, resourceType.getName() }; 1395 throw new PolicyException( 1396 ResBundleUtils.rbName, 1397 "resource_name_not_permitted_by_prefix_names", 1398 objs, null); 1399 } 1400 } 1401 1402 } 1403 1404 private void validateReferrals(Policy policy) 1405 throws SSOException, PolicyException { 1406 Set candidateOrgs = policy.getReferredToOrganizations(); 1407 if ( candidateOrgs.contains(org.toLowerCase()) ) { 1408 String[] objs = { org }; 1409 throw new PolicyException( 1410 ResBundleUtils.rbName, 1411 "invalid_referral_pointing_to_self", 1412 objs, null); 1413 } 1414 Iterator iter = candidateOrgs.iterator(); 1415 while ( iter.hasNext() ) { 1416 String candidateOrg = (String) iter.next(); 1417 1418 /* 1419 * check org orgName exisits - would result in 1420 * PolicyException if the orgName does not exist 1421 */ 1422 verifyOrgName(candidateOrg); 1423 } 1424 1425 } 1426 1427 void saveRealmSubjects(Subjects subjects) 1428 throws PolicyException, SSOException { 1429 ServiceConfig realmSubjects = createOrGetPolicyConfig( 1430 REALM_SUBJECTS, REALM_SUBJECTS, scm, org); 1431 Map attributes = new HashMap(1); 1432 Set values = new HashSet(1); 1433 String subjectsXML = subjects.toXML(); 1434 values.add(subjectsXML); 1435 attributes.put(XML_REALM_SUBJECTS, values); 1436 try { 1437 realmSubjects.setAttributes(attributes); 1438 } catch (SMSException se) { 1439 debug.error("SMS error in saving realm subjects " 1440 + " in organization: " + org); 1441 // Check for permission exception 1442 String objs[] = { org }; 1443 if (se.getExceptionCode() == SMSException.STATUS_NO_PERMISSION) { 1444 throw new PolicyException(ResBundleUtils.rbName, 1445 "insufficient_access_rights", null, se); 1446 } else { 1447 // Throw generic policy exception 1448 throw new PolicyException(ResBundleUtils.rbName, 1449 "unable_to_save_realm_subjects", objs, se); 1450 } 1451 } 1452 if (debug.messageEnabled()) { 1453 debug.message("saved realm subjects:" + subjectsXML); 1454 } 1455 } 1456 1457 Subjects readRealmSubjects() throws PolicyException, SSOException { 1458 Subjects subjects = null; 1459 ServiceConfig realmSubjects = createOrGetPolicyConfig( 1460 REALM_SUBJECTS, REALM_SUBJECTS, scm, org); 1461 Set values = null; 1462 values = (Set)realmSubjects.getAttributes().get(XML_REALM_SUBJECTS); 1463 if ((values != null) && !values.isEmpty()) { 1464 String xmlSubjects = (String)values.iterator().next(); 1465 Document doc = null; 1466 try { 1467 doc = XMLUtils.getXMLDocument( 1468 new ByteArrayInputStream(xmlSubjects.getBytes("UTF8"))); 1469 } catch (Exception xmle) { 1470 debug.error("XML parsing error for realmSubjects: " 1471 + " in organization: " + org); 1472 // throw generic policy exception 1473 throw (new PolicyException(xmle)); 1474 } 1475 Node subjectsNode = XMLUtils.getRootNode(doc, SUBJECTS_POLICY); 1476 if (subjectsNode == null) { 1477 debug.error("invalid xmlRealmSubjects blob " 1478 + " in organization: " + org); 1479 throw (new InvalidFormatException(ResBundleUtils.rbName, 1480 "invalid_xml_realmsubjects_root_node", null, 1481 org, PolicyException.POLICY)); 1482 } 1483 subjects = new Subjects(this, subjectsNode); 1484 } else { 1485 subjects = new Subjects(); 1486 } 1487 if (debug.messageEnabled()) { 1488 debug.message("read realm subjects:" + subjects.toXML()); 1489 } 1490 subjects.setPolicyConfig(getPolicyConfig()); 1491 return subjects; 1492 } 1493 1494 /** 1495 * Gets the set of policies that use the realm subject 1496 * @param subjectName name of the realm subject to check for 1497 * @return a <code>Set</code> of <code>Policy</code> objects 1498 * that use the realm subject 1499 */ 1500 public Set getPoliciesUsingRealmSubject(String subjectName) 1501 throws PolicyException, SSOException { 1502 Set policies = new HashSet(); 1503 Set policyNames = getPolicyNames(); 1504 for (Iterator policyIter = policyNames.iterator(); 1505 policyIter.hasNext();) { 1506 String policyName = (String)policyIter.next(); 1507 Policy policy = getPolicy(policyName); 1508 Set subjectNames = policy.getSubjectNames(); 1509 if (subjectNames.contains(subjectName)) { 1510 Subject subject = policy.getSubject(subjectName); 1511 if (subject instanceof SharedSubject) { 1512 policies.add(policy); 1513 } 1514 } 1515 } 1516 return policies; 1517 } 1518 1519 Policy getPolicyUsingRealmSubject(String subjectName) 1520 throws PolicyException, SSOException { 1521 Policy policy = null; 1522 Set policyNames = getPolicyNames(); 1523 for (Iterator policyIter = policyNames.iterator(); 1524 policyIter.hasNext();) { 1525 String policyName = (String)policyIter.next(); 1526 Policy p = getPolicy(policyName); 1527 Set subjectNames = p.getSubjectNames(); 1528 if (subjectNames.contains(subjectName)) { 1529 Subject subject = p.getSubject(subjectName); 1530 if (subject instanceof SharedSubject) { 1531 policy = p; 1532 break; 1533 } 1534 } 1535 } 1536 return policy; 1537 } 1538 1539 private Set getOrgAliasMappedResourceNames() 1540 throws PolicyException { 1541 if (debug.messageEnabled()) { 1542 debug.message("PolicyManager.getOrgAliasMappedResourceNames(): " 1543 + " entering:orgName = " + org); 1544 } 1545 Set managedResourceNames = new HashSet(3); 1546 if (ocm == null) { 1547 try { 1548 ocm = new OrganizationConfigManager(token, givenOrgName); 1549 } catch (SMSException sme) { 1550 String[] objs = { org }; 1551 throw (new PolicyException(ResBundleUtils.rbName, 1552 "unable_to_get_org_config_manager_for_org", 1553 objs, sme)); 1554 } 1555 } 1556 1557 Set orgAliases = null; 1558 try { 1559 Map orgAttributes = ocm.getAttributes(ID_REPO_SERVICE); 1560 orgAliases 1561 = (Set)orgAttributes.get(ORG_ALIAS); 1562 if (debug.messageEnabled()) { 1563 debug.message("PolicyManager.getOrgAliasMappedResourceNames(): " 1564 + " orgName = " + org 1565 + ":orgAliases=" + orgAliases); 1566 } 1567 } catch (SMSException sme) { 1568 String[] objs = { org }; 1569 throw (new PolicyException(ResBundleUtils.rbName, 1570 "unable_to_get_org_alias_for_org", objs, sme)); 1571 } 1572 if (orgAliases != null) { 1573 Iterator iter = orgAliases.iterator(); 1574 while (iter.hasNext()) { 1575 String orgAlias = (String)iter.next(); 1576 managedResourceNames.add(ORG_ALIAS_URL_HTTP_PREFIX 1577 + orgAlias.trim() 1578 + ORG_ALIAS_URL_SUFFIX); 1579 managedResourceNames.add(ORG_ALIAS_URL_HTTPS_PREFIX 1580 + orgAlias.trim() 1581 + ORG_ALIAS_URL_SUFFIX); 1582 } 1583 } 1584 if (debug.messageEnabled()) { 1585 debug.message("PolicyManager.getOrgAliasMappedResourceNames(): " 1586 + " returning: orgName = " + org 1587 + ":orgAliases=" + orgAliases 1588 + ":managedResourceNames=" + managedResourceNames); 1589 } 1590 return managedResourceNames; 1591 } 1592 1593 public Set getManagedResourceNames() 1594 throws PolicyException { 1595 PolicyManager.initAdminSubject(); 1596 Set managedResourceNames = rm.getManagedResourceNames(); 1597 if ((managedResourceNames == null) 1598 || (managedResourceNames == Collections.EMPTY_SET)) { 1599 managedResourceNames = new HashSet(); 1600 } 1601 managedResourceNames.addAll(getOrgAliasMappedResourceNames()); 1602 if (debug.messageEnabled()) { 1603 debug.message("PolicyManager.getManagedResourceNames(): " 1604 + " returning: orgName = " + org 1605 + ":managedResourceNames=" + managedResourceNames); 1606 } 1607 return managedResourceNames; 1608 } 1609 1610 String getOrgAliasWithResource(String resourceName) 1611 throws PolicyException, SSOException { 1612 if (debug.messageEnabled()) { 1613 debug.message("PolicyManager.getOrgAliasWithResource(): " 1614 + " orgName = " + org 1615 + ", resourceName = " + resourceName); 1616 } 1617 if (resourceName == null) { 1618 return null; 1619 } 1620 String orgAlias = null; 1621 try { 1622 URL url = new URL(resourceName); 1623 orgAlias = url.getHost(); 1624 } catch (MalformedURLException mfe) { 1625 String[] objs = { resourceName }; 1626 if (debug.messageEnabled()) { 1627 debug.message("PolicyManager.getOrgAliasWithResource(): " 1628 + " orgName = " + org 1629 + ", resourceName = " + resourceName 1630 + " is invalid URL, no org alias mapping can be found"); 1631 } 1632 } 1633 return orgAlias; 1634 } 1635 1636 String getOrgNameWithAlias(String orgAlias) 1637 throws PolicyException, SSOException { 1638 String aliasMappedOrg = null; 1639 try { 1640 aliasMappedOrg = IdUtils.getOrganization(token, orgAlias); 1641 } catch (IdRepoException re) { 1642 //idRepo throws exception if there is no mapping 1643 if (debug.messageEnabled()) { 1644 debug.message("PolicyManager.getOrgNameWithAlias(): " 1645 + " can not get orgName for orgAlias = " + orgAlias); 1646 } 1647 } 1648 if (debug.messageEnabled()) { 1649 debug.message("PolicyManager.getOrgNameWithAlias(): " 1650 + " orgAlias = " + orgAlias 1651 + ", mapped org = " + aliasMappedOrg); 1652 } 1653 return aliasMappedOrg; 1654 } 1655 1656 public boolean canCreatePolicies(Set<String> services) 1657 throws EntitlementException { 1658 PolicyManager.initAdminSubject(); 1659 String realm = DNMapper.orgNameToRealmName(getOrganizationDN()); 1660 if (realm.equals("/")) { 1661 return true; 1662 } 1663 1664 for (String s : services) { 1665 Set<String> res = getApplicationService(adminSubject, realm).getReferredResources(s); 1666 if ((res != null) && !res.isEmpty()) { 1667 return true; 1668 } 1669 } 1670 return false; 1671 } 1672 1673 private static void initialise() { 1674 1675 // Do this outside of a static block to avoid issues on container shutdown/restart 1676 adminSubject = SubjectUtils.createSubject( 1677 (SSOToken)AccessController.doPrivileged(AdminTokenAction.getInstance())); 1678 } 1679 1680 public boolean canCreateNewResource(String svcTypeName) { 1681 boolean can = false; 1682 ResourceManager resMgr = getResourceManager(); 1683 PolicyManager.initAdminSubject(); 1684 if (resMgr != null) { 1685 try { 1686 can = resMgr.canCreateNewResource(svcTypeName); 1687 } catch (PolicyException e) { 1688 debug.warning("PolicyManager.canCreateNewResource",e); 1689 } 1690 } 1691 return can; 1692 } 1693 1694 /** 1695 * To initialise the adminSubject if it was null. 1696 * This must be non-null for the migratedToEntitlementService to have been 1697 * calculated correctly 1698 */ 1699 public static void initAdminSubject(){ 1700 if (adminSubject == null){ 1701 initialise(); 1702 } 1703 } 1704}