001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2005 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: IdUtils.java,v 1.34 2009/11/20 23:52:54 ww203982 Exp $ 026 * 027 */ 028 029/* 030 * Portions Copyrighted [2011] [ForgeRock AS] 031 */ 032package com.sun.identity.idm; 033 034import com.iplanet.am.sdk.AMDirectoryAccessFactory; 035import com.iplanet.am.sdk.AMException; 036import com.iplanet.am.sdk.AMObject; 037import com.iplanet.am.sdk.AMOrganization; 038import com.iplanet.am.sdk.AMStoreConnection; 039import com.iplanet.am.sdk.AMConstants; 040import com.iplanet.am.sdk.common.IDirectoryServices; 041import com.iplanet.am.util.SystemProperties; 042import com.iplanet.sso.SSOException; 043import com.iplanet.sso.SSOToken; 044import com.sun.identity.common.CaseInsensitiveHashMap; 045import com.sun.identity.common.DNUtils; 046import com.sun.identity.security.AdminTokenAction; 047import com.sun.identity.shared.Constants; 048import com.sun.identity.shared.debug.Debug; 049import com.sun.identity.sm.DNMapper; 050import com.sun.identity.sm.SMSEntry; 051import com.sun.identity.sm.OrganizationConfigManager; 052import com.sun.identity.sm.OrgConfigViaAMSDK; 053 054import com.sun.identity.sm.SMSException; 055import com.sun.identity.sm.ServiceConfig; 056import com.sun.identity.sm.ServiceConfigManager; 057import com.sun.identity.sm.ServiceManager; 058 059import java.security.AccessController; 060import java.util.Collections; 061import java.util.HashSet; 062import java.util.Iterator; 063import java.util.Map; 064import java.util.Set; 065import java.util.StringTokenizer; 066 067import com.sun.identity.shared.ldap.LDAPDN; 068import com.sun.identity.shared.ldap.util.DN; 069 070 071/** 072 * The class defines some static utilities used by other components like policy 073 * and auth 074 * 075 * @supported.api 076 */ 077public final class IdUtils { 078 private static Debug debug = AMIdentityRepository.debug; 079 080 private static Map mapSupportedTypes = new CaseInsensitiveHashMap(10); 081 082 public static Set supportedTypes = new HashSet(); 083 084 private static Map mapTypesToServiceNames = new CaseInsensitiveHashMap(); 085 086 protected static Map typesCanBeMemberOf = new CaseInsensitiveHashMap(); 087 088 protected static Map typesCanHaveMembers = new CaseInsensitiveHashMap(); 089 090 protected static Map typesCanAddMembers = new CaseInsensitiveHashMap(); 091 092 // Static map to cache "orgIdentifier" and organization DN 093 private static Map orgIdentifierToOrgName = Collections.synchronizedMap( 094 new CaseInsensitiveHashMap()); 095 private static Map orgStatusCache = Collections.synchronizedMap( 096 new CaseInsensitiveHashMap()); 097 098 // ServiceConfigManager for sunidentityrepository service 099 private static String notificationId; 100 101 private static ServiceConfigManager serviceConfigManager; 102 103 // User naming attribute for AMSDK 104 private static String USER_NAMING_ATTR; 105 106 // Organization naming attribute for AMSDK 107 private static String ORG_NAMING_ATTR; 108 109 // SMS Root Suffix 110 private static String ROOT_SUFFIX; 111 112 // DN pointing to the services node 113 private static String SERVICES_SUFFIX; 114 115 // Special Users 116 private static Set specialUsers = new HashSet(); 117 118 static { 119 initialize(); 120 } 121 122 protected static void initialize() { 123 if (ServiceManager.isConfigMigratedTo70()) { 124 // IdRepo service schema exists. Read the supported 125 // entities from there 126 try { 127 SSOToken adminToken = (SSOToken) AccessController 128 .doPrivileged(AdminTokenAction.getInstance()); 129 serviceConfigManager = new ServiceConfigManager(adminToken, 130 IdConstants.REPO_SERVICE, "1.0"); 131 ServiceConfig ss = serviceConfigManager.getGlobalConfig(null); 132 Set typeSchemaNames = ss.getSubConfigNames("*", 133 IdConstants.SUPPORTED_TYPES); 134 if (typeSchemaNames == null || typeSchemaNames.isEmpty()) { 135 loadDefaultTypes(); 136 } else { 137 Iterator it = typeSchemaNames.iterator(); 138 while (it.hasNext()) { 139 String typeSchema = (String) it.next(); 140 IdType idType = new IdType(typeSchema); 141 supportedTypes.add(idType); 142 mapSupportedTypes.put(idType.getName(), idType); 143 ServiceConfig tsc = ss.getSubConfig(typeSchema); 144 Map attributes = tsc.getAttributes(); 145 Set serviceNameSet = (Set) attributes 146 .get(IdConstants.SERVICE_NAME); 147 Set canBeMembersOf = (Set) attributes 148 .get(IdConstants.ATTR_MEMBER_OF); 149 Set canHaveMembers = (Set) attributes 150 .get(IdConstants.ATTR_HAVE_MEMBERS); 151 Set canAddMembers = (Set) attributes 152 .get(IdConstants.ATTR_ADD_MEMBERS); 153 if (serviceNameSet != null && 154 !serviceNameSet.isEmpty()) { 155 mapTypesToServiceNames.put(typeSchema, 156 (String) serviceNameSet.iterator().next()); 157 } 158 if (canBeMembersOf != null && 159 !canBeMembersOf.isEmpty()) { 160 Set memberOfSet = getMemberSet(canBeMembersOf); 161 typesCanBeMemberOf.put(typeSchema, memberOfSet); 162 } 163 if (canHaveMembers != null && 164 !canHaveMembers.isEmpty()) { 165 Set memberSet = getMemberSet(canHaveMembers); 166 typesCanHaveMembers.put(typeSchema, memberSet); 167 } 168 if (canAddMembers != null && 169 !canAddMembers.isEmpty()) 170 { 171 Set memberSet = getMemberSet(canAddMembers); 172 typesCanAddMembers.put(typeSchema, memberSet); 173 } 174 } 175 } 176 } catch (SMSException e) { 177 String installTime = SystemProperties.get( 178 Constants.SYS_PROPERTY_INSTALL_TIME, "false"); 179 if (!installTime.equals("true")) { 180 debug.error( 181 "IdUtils.initialize: Loading default types.", e); 182 } 183 loadDefaultTypes(); 184 } catch (SSOException ssoe) { 185 debug.error("dUtils.initialize: Loading default types", ssoe); 186 loadDefaultTypes(); 187 } 188 } else { 189 loadDefaultTypes(); 190 } 191 192 // Register for SMS notifications to root realm 193 if (notificationId == null) { 194 try { 195 SSOToken adminToken = (SSOToken) AccessController 196 .doPrivileged(AdminTokenAction.getInstance()); 197 if (serviceConfigManager == null) { 198 serviceConfigManager = new ServiceConfigManager(adminToken, 199 IdConstants.REPO_SERVICE, "1.0"); 200 } 201 notificationId = serviceConfigManager.addListener( 202 new IdUtilsListener()); 203 } catch (SMSException e) { 204 String installTime = SystemProperties.get( 205 Constants.SYS_PROPERTY_INSTALL_TIME, "false"); 206 if (!installTime.equals("true")) { 207 debug.error( 208 "IdUtils.initialize: Register notification", e); 209 } 210 } catch (SSOException ssoe) { 211 String installTime = SystemProperties.get( 212 Constants.SYS_PROPERTY_INSTALL_TIME, "false"); 213 if (!installTime.equals("true")) { 214 debug.error( 215 "IdUtils.initialize: Register notification", ssoe); 216 } 217 } 218 } 219 } 220 221 /** 222 * @supported.api 223 * Returns a handle of the Identity object based on 224 * the SSO Token passed in (<code>AMIdentity</code> object of the user 225 * who is authenticated). 226 * 227 * @param token Single sign on token of user. 228 * @return Identity object. 229 * @throws IdRepoException if there are repository related error conditions. 230 * @throws SSOException if user's single sign on token is invalid. 231 */ 232 public static AMIdentity getIdentity(SSOToken token) 233 throws IdRepoException, SSOException { 234 String principal = token.getProperty(Constants.UNIVERSAL_IDENTIFIER); 235 if (principal == null) { 236 // This could happen during co-existence with AM 6.x 237 // and SSOToken created by AM 6.x server. In this case 238 // the principal name would be the DN 239 principal = token.getPrincipal().getName(); 240 } 241 return (getIdentity(token, principal)); 242 } 243 244 /** 245 * @supported.api 246 * 247 * Returns a string which uniquely represents this identity object. 248 * 249 * @param id 250 * <code>AMIdentity</code> object whose string represenation is 251 * needed. 252 * @return universal identifier of <code>id</code>. 253 */ 254 public static String getUniversalId(AMIdentity id) { 255 return id.getUniversalId(); 256 } 257 258 /** 259 * @supported.api 260 * 261 * Returns an <code>AMIdentity</code> object, if provided with a string 262 * identifier for the object. 263 * 264 * @param token SSOToken of the administrator 265 * @param univId String represenation of the identity. 266 * @return Identity object 267 * @throws IdRepoException if the identifier provided is wrong. 268 */ 269 public static AMIdentity getIdentity(SSOToken token, String univId) 270 throws IdRepoException { 271 return (getIdentity(token, univId, null)); 272 } 273 274 /** 275 * Returns an <code>AMIdentity</code> object, given the 276 * DN of an authenticated identity, realm name and identity type. 277 * This interface is mainly for authentication component to get 278 * back the identity of the user. 279 * 280 * @param token SSOToken of the administrator 281 * @param amsdkdn DN of the authenticated user 282 * @param realm realm name where the user was authenticated 283 * @return Identity object or <code>null</code> 284 * @throws IdRepoException if the underly components throws 285 * exception while obtaining the identity object 286 */ 287 public static AMIdentity getIdentity(SSOToken token, String amsdkdn, 288 String realm) throws IdRepoException { 289 DN amsdkdnObject = null; 290 if (amsdkdn == null || !(amsdkdnObject = new DN(amsdkdn)).isDN()) { 291 Object[] args = { amsdkdn }; 292 throw (new IdRepoException(IdRepoBundle.BUNDLE_NAME, 293 "215", args)); 294 } 295 296 // Try constructing the identity object 297 if (amsdkdn.toLowerCase().startsWith("id=")) { 298 try { 299 return (new AMIdentity(amsdkdnObject, token)); 300 } catch (IdRepoException ide) { 301 // this could be a AMSDK DN. Follow the AMSDK rules 302 if (debug.messageEnabled()) { 303 debug.message("IdUtils:getIdentity(token, " + 304 amsdkdn + ") got exception: " + ide.getMessage() + 305 "\n\tContinuing with AMSDK DN check"); 306 } 307 } 308 } 309 310 // Check for Special Users 311 initializeSpecialUsers(); 312 if (specialUsers.contains(DNUtils.normalizeDN(amsdkdnObject))) { 313 return (new AMIdentity(amsdkdnObject, token, LDAPDN.explodeDN( 314 amsdkdnObject, true)[0], IdType.USER, ROOT_SUFFIX)); 315 } 316 317 // Since "amsdkdn" is not a UUID, check if realm has AMSDK configured 318 // This change is to avoid the issue of IdUtils always checking the 319 // users in AMSDK as IdUtils does not check if AMSDK is configured in 320 // any of the realms. 321 try { 322 if (!ServiceManager.isAMSDKEnabled() || ((realm != null) && 323 !OrgConfigViaAMSDK.isAMSDKConfigured(realm)) || 324 (!ServiceManager.isAMSDKConfigured())) { 325 // Not configured for AMSDK, return 326 return (null); 327 } 328 } catch (SMSException smse) { 329 // Ignore the exception and continue 330 } 331 332 // Initialize root realm suffix, org and user naming attributes 333 initializeForGetIdentity(); 334 335 // Determine if the amsdkdn is valid. Obtain name & type 336 String name = null; 337 IdType type = null; 338 try { 339 // Since we would using AMSDK, get AMDirectoryManager preload 340 // all the attributes and check if it exists 341 IDirectoryServices dsServices = 342 AMDirectoryAccessFactory.getDirectoryServices(); 343 // Preload/cache all the attributes assuming it is a user 344 // Mainly for performance reasons, since getObjectType would 345 // force multiple another directory lookup 346 try { 347 if (amsdkdn.startsWith(USER_NAMING_ATTR)) { 348 dsServices.getAttributes(token, amsdkdn, AMObject.USER); 349 } 350 } catch (Exception e) { 351 // Ignore the exception and continue since this for cache 352 } 353 354 // Getting object type would use the cached attributes 355 int sdkType = dsServices.getObjectType(token, amsdkdn); 356 357 // Convert the sdkType to IdRepo type 358 type = getType(AMStoreConnection.getObjectName(sdkType)); 359 name = AMConstants.CONTAINER_DEFAULT_TEMPLATE_ROLE; 360 if (!type.equals(IdType.REALM)) { 361 name = LDAPDN.explodeDN(amsdkdnObject, true)[0]; 362 } 363 } catch (AMException ame) { 364 // Debug the message and return null 365 if (debug.messageEnabled()) { 366 debug.message("IdUtils.getIdentity: Unable to resolve " + 367 "AMSDK DN: " + amsdkdn, ame); 368 } 369 return (null); 370 } catch (SSOException ssoe) { 371 // Debug the message and return null 372 if (debug.messageEnabled()) { 373 debug.message("IdUtils.getIdentity: Unable to resolve " + 374 "AMSDK DN. Got SSOException", ssoe); 375 } 376 return (null); 377 } 378 379 // Need to determine realm for amsdkdn 380 String srealm = ROOT_SUFFIX; 381 if (!amsdkdn.equals(ROOT_SUFFIX) && 382 !amsdkdn.equals(SERVICES_SUFFIX)) { 383 // Need to get the object type and walk up the tree 384 int index = amsdkdn.indexOf(ORG_NAMING_ATTR); 385 if (index == 0) { 386 srealm = OrgConfigViaAMSDK.getRealmForAMSDK(amsdkdn, realm); 387 } else if (index > 0) { 388 srealm = OrgConfigViaAMSDK.getRealmForAMSDK( 389 amsdkdn.substring(index), realm); 390 } 391 if (debug.messageEnabled()) { 392 debug.message("IdUtils.getIdentity:: amsdkdn=" + 393 amsdkdn + " maps to realm=" + srealm); 394 } 395 } else if (amsdkdn.equals(SERVICES_SUFFIX)) { 396 // Since amsdkdn points to services node, 397 // it should be reset to root suffix 398 amsdkdn = ROOT_SUFFIX; 399 } 400 401 return (new AMIdentity(amsdkdnObject, token, name, type, srealm)); 402 } 403 404 /** 405 * Returns the name of service which defines the profile information for 406 * this type. Returns null, if nothing is defined. 407 * 408 * @param type IdType whose service name is needed. 409 * @return Name of the service. 410 */ 411 public static String getServiceName(IdType type) { 412 return (String) mapTypesToServiceNames.get(type.getName()); 413 } 414 415 /** 416 * Returns corresponding <code>IdType</code> object given a type. 417 * 418 * @param type of object to return. 419 * @return Idtype of type. 420 * @throws IdRepoException if there are no corresponding types. 421 */ 422 public static IdType getType(String type) throws IdRepoException { 423 if (type.equalsIgnoreCase("managedrole")) { 424 type = "role"; 425 } else if (type.equalsIgnoreCase("organization") 426 || type.equalsIgnoreCase("organizationalunit")) { 427 type = "realm"; 428 } 429 430 IdType returnType = (IdType) mapSupportedTypes.get(type); 431 if (returnType == null) { 432 Object args[] = { type }; 433 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, "217", args); 434 } 435 return returnType; 436 } 437 438 /** 439 * Returns the matching DN from the AM SDK for this entry. This utility is 440 * required by auth. 441 * 442 * @param id <code>AMIdentity</code> object. 443 * @return <code>DN</code> of the object, as represented in the datastore. 444 */ 445 public static String getDN(AMIdentity id) { 446 if (id.getDN() != null) { 447 return id.getDN(); 448 } else { 449 return id.getUniversalId(); 450 } 451 } 452 453 /** 454 * Returns an organization which maps to the identifier used by application 455 * 456 * @param orgIdentifier Organization identifier 457 * @return Organization mapping to that identifier. 458 */ 459 public static String getOrganization(SSOToken token, String orgIdentifier) 460 throws IdRepoException, SSOException { 461 // Check in cache first 462 String id = null; 463 if ((id = (String) orgIdentifierToOrgName.get(orgIdentifier)) != null) { 464 return (id); 465 } 466 467 // Compute the organization name 468 if (debug.messageEnabled()) { 469 debug.message("IdUtils:getOrganization Input orgname: " 470 + orgIdentifier); 471 } 472 if (orgIdentifier == null || orgIdentifier.length() == 0 473 || orgIdentifier.equals("/")) { 474 // Return base DN 475 id = DNMapper.orgNameToDN("/"); 476 } else if (orgIdentifier.startsWith("/")) { 477 // If orgIdentifier is in "/" format covert to DN and return 478 id = DNMapper.orgNameToDN(orgIdentifier); 479 } else if (DN.isDN(orgIdentifier)) { 480 id = orgIdentifier; 481 try { 482 // Search for realms with orgIdentifier name 483 OrganizationConfigManager ocm = 484 new OrganizationConfigManager(token, orgIdentifier); 485 } catch (SMSException smse) { 486 // debug message here. 487 if (debug.messageEnabled()) { 488 debug.message("IdUtils.getOrganization Exception in " 489 + "getting org name from SMS", smse); 490 } 491 Object[] args = { orgIdentifier }; 492 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, "401", 493 args); 494 } 495 } else if (ServiceManager.isCoexistenceMode()) { 496 // Return the org DN as determined by AMStoreConnection 497 if (debug.messageEnabled()) { 498 debug.message("IdUtils.getOrganization: getting from AMSDK"); 499 } 500 try { 501 AMStoreConnection amsc = new AMStoreConnection(token); 502 id = amsc.getOrganizationDN(orgIdentifier, null); 503 } catch (AMException ame) { 504 if (debug.messageEnabled()) { 505 debug.message("IdUtils.getOrganization Exception in " 506 + "getting org name from AMSDK", ame); 507 } 508 throw convertAMException(ame); 509 } 510 } else { 511 // Get the realm name from SMS 512 if (debug.messageEnabled()) { 513 debug.message("IdUtils.getOrganization: getting from " + 514 "SMS realms"); 515 } 516 try { 517 boolean foundOrg = false; 518 ServiceManager sm = new ServiceManager(token); 519 // First search for realms with orgIdentifier name 520 OrganizationConfigManager ocm = sm 521 .getOrganizationConfigManager("/"); 522 Set subOrgNames = ocm.getSubOrganizationNames(orgIdentifier, 523 true); 524 if (subOrgNames != null && !subOrgNames.isEmpty()) { 525 if (subOrgNames.size() == 1) { 526 id = DNMapper.orgNameToDN((String) subOrgNames 527 .iterator().next()); 528 foundOrg = true; 529 } else { 530 for (Iterator items = subOrgNames.iterator(); 531 items.hasNext();) { 532 // check for orgIdentifier 533 String subRealmName = (String) items.next(); 534 StringTokenizer st = new StringTokenizer( 535 subRealmName, "/"); 536 // Need to handle the scenario where multiple 537 // sub-realm with the same name should not be 538 // allowed 539 while (st.hasMoreTokens()) { 540 if (st.nextToken().equalsIgnoreCase( 541 orgIdentifier)) { 542 if (!foundOrg) { 543 id = DNMapper.orgNameToDN(subRealmName); 544 foundOrg = true; 545 } else { 546 Object[] args = {orgIdentifier}; 547 throw new IdRepoException(IdRepoBundle 548 .BUNDLE_NAME, "404", args); 549 } 550 } 551 } 552 } 553 } 554 } 555 556 // Check if organization name has been determined 557 if (debug.messageEnabled()) { 558 debug.message("IdUtils.getOrganization: getting from " + 559 "SMS realms aliases"); 560 } 561 // perform organization alias search 562 Set vals = new HashSet(); 563 vals.add(orgIdentifier); 564 Set orgAliases = sm.searchOrganizationNames( 565 IdConstants.REPO_SERVICE, 566 IdConstants.ORGANIZATION_ALIAS_ATTR, vals); 567 if (!foundOrg && 568 ((orgAliases == null) || orgAliases.isEmpty())) { 569 if (debug.warningEnabled()) { 570 debug.warning("IdUtils.getOrganization Unable" + 571 " to find Org name for: " + orgIdentifier); 572 } 573 Object[] args = {orgIdentifier}; 574 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, 575 "401", args); 576 } else if ((orgAliases != null) && (orgAliases.size() > 0) && 577 (foundOrg || orgAliases.size() > 1)) { 578 // Multiple realms should not have the same alias 579 if (debug.warningEnabled()) { 580 debug.warning("IdUtils.getOrganization Multiple " + 581 " matching Orgs found for: " + orgIdentifier); 582 } 583 Object[] args = {orgIdentifier}; 584 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, 585 "404", args); 586 } 587 if (!foundOrg) { 588 String tmpS = (String) orgAliases.iterator().next(); 589 id = DNMapper.orgNameToDN(tmpS); 590 } 591 } catch (SMSException smse) { 592 // debug message here. 593 if (debug.messageEnabled()) { 594 debug.message("IdUtils.getOrganization Exception in " 595 + "getting org name from SMS", smse); 596 } 597 Object[] args = { orgIdentifier }; 598 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, "401", 599 args); 600 } 601 } 602 603 if (debug.messageEnabled()) { 604 debug.message("IdUtils:getOrganization Search for OrgIdentifier:" + 605 orgIdentifier + " returning realm DN: " + id); 606 } 607 608 // Add to cache and return id 609 orgIdentifierToOrgName.put(orgIdentifier, id); 610 return id; 611 } 612 613 /** 614 * Clears the cache containing orgIdentifiers to organization names 615 */ 616 protected static void clearOrganizationNamesCache() { 617 orgIdentifierToOrgName.clear(); 618 orgStatusCache.clear(); 619 if (debug.messageEnabled()) { 620 debug.message("IdUtils.clearOrganizationNamesCache called"); 621 } 622 } 623 624 /** 625 * Returs true or false, depending on if this organization is enabled or 626 * not. The organization string passed to this method should be an 627 * identifier returned from the method 628 * <code> IdUtils.getOrganization </code>. In the default mode, where 629 * relams are enabled but backward comaptibility is required, this checks 630 * for organization status in the AM enabled Sun DS. Otherwise, it checks 631 * for organization status from the realms tree. 632 * 633 * @param token token SSOToken a valid SSOToken. 634 * @param org name of the organization of interest. 635 * @return <code>true</code> if org is active; 636 * otherwise <code>false</code> 637 * @throws IdRepoException if there are repository related error conditions. 638 * @throws SSOException If user's single sign on token is invalid. 639 */ 640 public static boolean isOrganizationActive(SSOToken token, String org) 641 throws IdRepoException, SSOException { 642 // Check the cache 643 if (orgStatusCache.containsKey(org)) { 644 return (((Boolean) orgStatusCache.get(org)).booleanValue()); 645 } 646 boolean isActive = true; 647 // Need to initialize ServiceManager by creating the constructor 648 if (!ServiceManager.isCoexistenceMode()) { 649 // Pick it up from the realms tree. 650 try { 651 OrganizationConfigManager ocm = new OrganizationConfigManager( 652 token, org); 653 if (ocm == null) { 654 Object[] args = { org }; 655 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, "401", 656 args); 657 } 658 Map attributes = ocm.getAttributes(IdConstants.REPO_SERVICE); 659 Set vals = (Set) attributes 660 .get(IdConstants.ORGANIZATION_STATUS_ATTR); 661 if (vals == null || vals.isEmpty()) { 662 isActive = true; 663 } else { 664 String stringActive = (String) vals.iterator().next(); 665 isActive = stringActive.equalsIgnoreCase("Active"); 666 } 667 } catch (SMSException smse) { 668 Object args[] = { org }; 669 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, "401", 670 args); 671 } 672 } else if (ServiceManager.isAMSDKEnabled()) { 673 // Return the org DN as determined by AMStoreConnection. 674 try { 675 AMStoreConnection amsc = new AMStoreConnection(token); 676 AMOrganization orgObj = amsc.getOrganization(org); 677 isActive = orgObj.isActivated(); 678 } catch (AMException ame) { 679 throw convertAMException(ame); 680 } 681 } 682 // Add to cache 683 orgStatusCache.put(org, isActive); 684 return isActive; 685 } 686 687 private static void initializeForGetIdentity() { 688 // Initialize root realm, if not already initalized 689 if (ROOT_SUFFIX == null) { 690 ROOT_SUFFIX = SMSEntry.getRootSuffix(); 691 StringBuilder sb = new StringBuilder(100); 692 sb.append(SMSEntry.SERVICES_RDN) 693 .append(SMSEntry.COMMA).append(ROOT_SUFFIX); 694 SERVICES_SUFFIX = DNUtils.normalizeDN(sb.toString()); 695 } 696 697 // Initialize organization and user naming attributes 698 if ((ORG_NAMING_ATTR == null) || (USER_NAMING_ATTR == null)) { 699 try { 700 ORG_NAMING_ATTR = AMStoreConnection.getNamingAttribute( 701 AMObject.ORGANIZATION).toLowerCase() + "="; 702 USER_NAMING_ATTR = AMStoreConnection.getNamingAttribute( 703 AMObject.USER).toLowerCase() + "="; 704 } catch (AMException ame) { 705 if (debug.warningEnabled()) { 706 debug.warning("IdUtils: unable to get naming " + 707 "attribute for org/user. Using \"o\"/\"uid\""); 708 } 709 ORG_NAMING_ATTR = "o="; 710 USER_NAMING_ATTR = "uid="; 711 } 712 } 713 } 714 715 private static void initializeSpecialUsers() { 716 // Populate special users 717 if (specialUsers.isEmpty()) { 718 String susers = SystemProperties.get( 719 Constants.AUTHENTICATION_SPECIAL_USERS, ""); 720 StringTokenizer st = new StringTokenizer( 721 susers, "|"); 722 while (st.hasMoreTokens()) { 723 specialUsers.add(DNUtils.normalizeDN(st.nextToken())); 724 } 725 susers = SystemProperties.get( 726 "com.sun.identity.authentication.super.user", ""); 727 specialUsers.add(DNUtils.normalizeDN(susers)); 728 } 729 } 730 731 /** 732 * Returns an IdRepoException based on an <code>AMException</code> 733 * 734 * @param ame 735 * @return IdRepoException based on ame. 736 */ 737 public static IdRepoException convertAMException(AMException ame) { 738 Object[] args = ame.getMessageArgs(); 739 String eCode = ame.getErrorCode(); 740 IdRepoException ide = null; 741 if (args == null) { 742 ide = new IdRepoException("amProfile", eCode, null); 743 } else { 744 ide = new IdRepoException("amProfile", ame.getErrorCode(), args); 745 } 746 ide.setLDAPErrorCode(ame.getLDAPErrorCode()); 747 return ide; 748 } 749 750 private static void loadDefaultTypes() { 751 supportedTypes.add(IdType.REALM); 752 supportedTypes.add(IdType.AGENT); 753 supportedTypes.add(IdType.USER); 754 supportedTypes.add(IdType.ROLE); 755 supportedTypes.add(IdType.GROUP); 756 supportedTypes.add(IdType.FILTEREDROLE); 757 mapSupportedTypes.put(IdType.REALM.getName(), IdType.REALM); 758 mapSupportedTypes.put(IdType.USER.getName(), IdType.USER); 759 mapSupportedTypes.put(IdType.ROLE.getName(), IdType.ROLE); 760 mapSupportedTypes.put(IdType.FILTEREDROLE.getName(), 761 IdType.FILTEREDROLE); 762 mapSupportedTypes.put(IdType.AGENT.getName(), IdType.AGENT); 763 mapSupportedTypes.put(IdType.GROUP.getName(), IdType.GROUP); 764 Set memberSet = new HashSet(); 765 memberSet.add(IdType.ROLE); 766 memberSet.add(IdType.GROUP); 767 memberSet.add(IdType.FILTEREDROLE); 768 typesCanBeMemberOf.put(IdType.USER.getName(), memberSet); 769 Set memberShipSet = new HashSet(); 770 memberShipSet.add(IdType.USER); 771 typesCanHaveMembers.put(IdType.ROLE.getName(), memberShipSet); 772 typesCanHaveMembers.put(IdType.GROUP.getName(), memberShipSet); 773 typesCanHaveMembers.put(IdType.FILTEREDROLE.getName(), memberShipSet); 774 typesCanAddMembers.put(IdType.GROUP.getName(), memberShipSet); 775 typesCanAddMembers.put(IdType.ROLE.getName(), memberShipSet); 776 } 777 778 private static Set getMemberSet(Set members) { 779 Set memberSet = new HashSet(members.size() * 2); 780 for (Iterator iter = members.iterator(); iter.hasNext();) { 781 String currType = (String) iter.next(); 782 memberSet.add(new IdType(currType)); 783 } 784 return memberSet; 785 } 786 787 /** 788 * Returns the user name extracted from the uuid 789 * if the orgName supplied in the parameter is 790 * not same realm name in uuid then <code>IdRepoException</code> 791 * is thrown 792 * 793 * @param uuid uuid of the user 794 * @param orgName the org user is trying to login to 795 * @return user name 796 * @throws IdRepoException 797 */ 798 public static String getIdentityName(String uuid, String orgName) 799 throws IdRepoException { 800 String username = uuid; 801 // Check uuid 802 if ((uuid != null) && uuid.toLowerCase().startsWith("id=")) { 803 // Could be universal id, get the identity object 804 AMIdentity id = new AMIdentity(null, uuid); 805 username = id.getName(); 806 // Check the realm names 807 String realm = DNUtils.normalizeDN(id.getRealm()); 808 if (!DNUtils.normalizeDN(orgName).equals(realm)) { 809 Object[] args = {uuid, orgName}; 810 throw new IdRepoException(IdRepoBundle.BUNDLE_NAME, "403", args); 811 } 812 } 813 return (username); 814 } 815 816 // SMS service listener to reinitialize if IdRepo service changes 817 static class IdUtilsListener implements com.sun.identity.sm.ServiceListener 818 { 819 public void schemaChanged(String serviceName, String version) { 820 initialize(); 821 } 822 823 public void globalConfigChanged(String serviceName, String version, 824 String groupName, String serviceComponent, int type) { 825 initialize(); 826 clearOrganizationNamesCache(); 827 } 828 829 public void organizationConfigChanged(String serviceName, 830 String version, String orgName, String groupName, 831 String serviceComponent, int type) { 832 clearOrganizationNamesCache(); 833 } 834 } 835}
Copyright © 2010-2017, ForgeRock All Rights Reserved.