static { String status = SystemProperties.get(Constants.AM_LOGSTATUS, "INACTIVE"); if ("ACTIVE".equalsIgnoreCase(status)) { logStatus = true; } // Get Directory Port value try { directoryPort = Integer.parseInt(SystemProperties.get(Constants.AM_DIRECTORY_PORT)); } catch (java.lang.NumberFormatException nfex) { directoryPort = 0; } // Get Session store String useHttpSessionStr = SystemProperties.get(ISAuthConstants.SESSION_STORE); if (useHttpSessionStr != null && useHttpSessionStr.equalsIgnoreCase("HttpSession")) { useHttpSession = true; } debug = Debug.getInstance(BUNDLE_NAME); if (debug.messageEnabled()) { debug.message("Directory Host: " + directoryHostName + "\nDirectory PORT : " + directoryPort); debug.message("Session store using " + useHttpSessionStr); } }
/** Creates <code>AuthXMLHandler</code> object */ public AuthXMLHandler() { localAuthServerProtocol = SystemProperties.get(Constants.AM_SERVER_PROTOCOL); localAuthServer = SystemProperties.get(Constants.AM_SERVER_HOST); localAuthServerPort = SystemProperties.get(Constants.AM_SERVER_PORT); AuthContext.localAuthServiceID = localAuthServerProtocol + "://" + localAuthServer + ":" + localAuthServerPort; locale = (new ISLocaleContext()).getLocale(); }
/** * Updates the <code>iPlanetAMLoggingService<code> service schema. * * @return true if successful otherwise false. */ public boolean migrateService() { boolean isSuccess = false; try { // read the values from AMConfig.properties String logStatus = SystemProperties.get("com.iplanet.am.logStatus"); String resolveHostName = SystemProperties.get("com.sun.identity.log.resolveHostName"); // update default value Set defaultValues = new HashSet(); defaultValues.add("NameID"); UpgradeUtils.addAttributeDefaultValues( SERVICE_NAME, null, schemaType, LOG_ALL_FIELDS_ATTR_NAME, defaultValues); // update choice value Map choiceValuesMap = new HashMap(); choiceValuesMap.put("choiceNameID", defaultValues); UpgradeUtils.addAttributeChoiceValues( SERVICE_NAME, null, schemaType, LOG_ATTR_NAME, choiceValuesMap); // add new attribute schema String fileName = UpgradeUtils.getAbsolutePath(SERVICE_DIR, SCHEMA_FILE); UpgradeUtils.addAttributeToSchema(SERVICE_NAME, schemaType, fileName); // populate the default values for logstatus & resolveHostName // from amconfig.properties defaultValues.clear(); defaultValues.add(logStatus); UpgradeUtils.setAttributeDefaultValues( SERVICE_NAME, null, schemaType, LOG_STATUS_ATTR, defaultValues); defaultValues.clear(); defaultValues.add(resolveHostName); UpgradeUtils.setAttributeDefaultValues( SERVICE_NAME, null, schemaType, RESOLVE_HOSTNAME_ATTR, defaultValues); String histNumFile = UpgradeUtils.getAttributeValueString(SERVICE_NAME, LOG_HIST_NUM_ATTR_NAME, schemaType); if (histNumFile != null && histNumFile.equals(DEFAULT_HIST_NUM)) { defaultValues.clear(); defaultValues.add(NEW_DEFAULT_HIST_NUM); UpgradeUtils.setAttributeDefaultValues( SERVICE_NAME, null, schemaType, LOG_HIST_NUM_ATTR_NAME, defaultValues); } String maxLogSize = UpgradeUtils.getAttributeValueString( SERVICE_NAME, LOG_MAX_FILE_SIZE_ATTR_NAME, schemaType); if (maxLogSize != null && maxLogSize.equals(DEFAULT_LOG_SIZE)) { defaultValues.clear(); defaultValues.add(NEW_DEFAULT_LOG_SIZE); UpgradeUtils.setAttributeDefaultValues( SERVICE_NAME, null, schemaType, LOG_MAX_FILE_SIZE_ATTR_NAME, defaultValues); } isSuccess = true; } catch (UpgradeException e) { UpgradeUtils.debug.error("Error loading data:" + SERVICE_NAME, e); } return isSuccess; }
@Override public void updateExternalLdapConfiguration( ModifiedProperty<String> hosts, ModifiedProperty<String> username, ModifiedProperty<String> password, ModifiedProperty<String> maxConnections, ModifiedProperty<Boolean> sslMode, ModifiedProperty<Integer> heartbeat) { hosts.set(SystemProperties.get(STORE_HOSTNAME)); username.set(SystemProperties.get(STORE_USERNAME)); password.set(AMPasswordUtil.decrypt(SystemProperties.get(STORE_PASSWORD))); maxConnections.set(SystemProperties.get(STORE_MAX_CONNECTIONS)); sslMode.set(SystemProperties.getAsBoolean(STORE_SSL_ENABLED, false)); heartbeat.set(SystemProperties.getAsInt(STORE_HEARTBEAT, -1)); }
/* build the trust source set*/ private static Set getTrustedSourceList() throws SessionException { Set result = new HashSet(); try { String rawList = SystemProperties.get(Constants.TRUSTED_SOURCE_LIST); if (rawList != null) { StringTokenizer stk = new StringTokenizer(rawList, ","); while (stk.hasMoreTokens()) { result.add(InetAddress.getByName(stk.nextToken())); } } else { // use platform server list as a default fallback Vector psl = WebtopNaming.getPlatformServerList(); if (psl == null) { throw new SessionException(SessionBundle.rbName, "emptyTrustedSourceList", null); } for (Enumeration e = psl.elements(); e.hasMoreElements(); ) { try { URL url = new URL((String) e.nextElement()); result.add(InetAddress.getByName(url.getHost())); } catch (Exception ex) { debug.error("SessionUtils.getTrustedSourceList : " + "Validating Host exception", ex); } } } } catch (Exception e) { throw new SessionException(e); } return result; }
/** * Returns Replication Status by invoking OpenDJ <code>dsreplication</code> CLI * * @param port LDAP port number of embedded OpenDJ * @param passwd Directory Manager password * @param oo Standard output * @param err : Standard error * @return <code>dsreplication</code> CLI exit code. */ public static int getReplicationStatus( String port, String passwd, OutputStream oo, OutputStream err) { Debug debug = Debug.getInstance(SetupConstants.DEBUG_NAME); String baseDir = SystemProperties.get(SystemProperties.CONFIG_PATH); String[] statusCmd = { "status", "--no-prompt", "-h", "localhost", "-p", port, "--adminUID", "admin", "--adminPassword", passwd, "-s", "--configFile", baseDir + "/opends/config/config.ldif" }; if (debug.messageEnabled()) { String dbgcmd = concat(statusCmd).replaceAll(passwd, "****"); debug.message("EmbeddedOpenDS:getReplicationStatus:exec dsreplication :" + dbgcmd); } int ret = ReplicationCliMain.mainCLI(statusCmd, false, oo, err, null); if (debug.messageEnabled()) { debug.message("EmbeddedOpenDS:getReplicationStatus:dsreplication ret:" + ret); } return ret; }
private AuthD() { debug.message("AuthD initializing"); try { rootSuffix = defaultOrg = ServiceManager.getBaseDN(); initAuthSessions(); initAuthServiceGlobalSettings(); initPlatformServiceGlobalSettings(); initSessionServiceDynamicSettings(); initAuthConfigGlobalSettings(); bundle = com.sun.identity.shared.locale.Locale.getInstallResourceBundle(BUNDLE_NAME); ResourceBundle platBundle = com.sun.identity.shared.locale.Locale.getInstallResourceBundle("amPlatform"); platformCharset = platBundle.getString(ISAuthConstants.PLATFORM_CHARSET_ATTR); printProfileAttrs(); // Initialize AuthXMLHandler so that AdminTokenAction can // generate DPro Session's SSOToken new com.sun.identity.authentication.server.AuthXMLHandler(); authInitFailed = false; } catch (Exception ex) { debug.error("AuthD init()", ex); authInitFailed = true; } try { enforceJAASThread = Boolean.valueOf(SystemProperties.get(Constants.ENFORCE_JAAS_THREAD)).booleanValue(); } catch (Exception e) { if (debug.messageEnabled()) { debug.message("Wrong format of " + Constants.ENFORCE_JAAS_THREAD); } } }
/** * @param config the ServletConfig object that contains configutation information for this * servlet. * @exception ServletException if an exception occurs that interrupts the servlet's normal * operation. */ public void init(ServletConfig config) throws ServletException { super.init(config); if (debug.messageEnabled()) { debug.message("CDCClientServlet.init:CDCClientServlet " + "Initializing..."); } try { tokenManager = SSOTokenManager.getInstance(); } catch (SSOException ssoe) { debug.error("CDCClientServlet.init:unable to get SSOTokenManager", ssoe); } authURLCookieName = SystemProperties.get(Constants.AUTH_UNIQUE_COOKIE_NAME, "sunIdentityServerAuthNServer"); authURLCookieDomain = SystemProperties.get(Constants.AUTH_UNIQUE_COOKIE_DOMAIN, ""); deployDescriptor = SystemProperties.get(Constants.AM_DISTAUTH_DEPLOYMENT_DESCRIPTOR, "/distauth"); }
@Override public StoreMode getStoreMode() { String mode = SystemProperties.get(STORE_LOCATION); if (StringUtils.isNotEmpty(mode)) { return StoreMode.valueOf(mode.toUpperCase()); } else { return StoreMode.DEFAULT; } }
/** * Retrieves all server info set on the server. * * @param context Current Server Context. * @param realm realm in whose security context we use. */ private Promise<ResourceResponse, ResourceException> getAllServerInfo( Context context, String realm) { JsonValue result = new JsonValue(new LinkedHashMap<String, Object>(1)); Set<String> cookieDomains; ResourceResponse resource; // added for the XUI to be able to understand its locale to request the appropriate translations // to cache ISLocaleContext localeContext = new ISLocaleContext(); HttpContext httpContext = context.asContext(HttpContext.class); localeContext.setLocale( httpContext); // we have nothing else to go on at this point other than their request SelfServiceInfo selfServiceInfo = configHandler.getConfig(realm, SelfServiceInfoBuilder.class); RestSecurity restSecurity = restSecurityProvider.get(realm); Set<String> protectedUserAttributes = new HashSet<>(); protectedUserAttributes.addAll(selfServiceInfo.getProtectedUserAttributes()); protectedUserAttributes.addAll(restSecurity.getProtectedUserAttributes()); try { cookieDomains = AuthClientUtils.getCookieDomains(); result.put("domains", cookieDomains); result.put("protectedUserAttributes", protectedUserAttributes); result.put( "cookieName", SystemProperties.get(Constants.AM_COOKIE_NAME, "iPlanetDirectoryPro")); result.put("secureCookie", CookieUtils.isCookieSecure()); result.put("forgotPassword", String.valueOf(selfServiceInfo.isForgottenPasswordEnabled())); result.put("forgotUsername", String.valueOf(selfServiceInfo.isForgottenUsernameEnabled())); result.put("kbaEnabled", String.valueOf(selfServiceInfo.isKbaEnabled())); result.put("selfRegistration", String.valueOf(selfServiceInfo.isUserRegistrationEnabled())); result.put("lang", getJsLocale(localeContext.getLocale())); result.put("successfulUserRegistrationDestination", "default"); result.put("socialImplementations", getSocialAuthnImplementations(realm)); result.put("referralsEnabled", Boolean.FALSE.toString()); result.put("zeroPageLogin", AuthUtils.getZeroPageLoginConfig(realm)); result.put("realm", realm); result.put( "xuiUserSessionValidationEnabled", SystemProperties.getAsBoolean(Constants.XUI_USER_SESSION_VALIDATION_ENABLED, true)); if (debug.messageEnabled()) { debug.message( "ServerInfoResource.getAllServerInfo ::" + " Added resource to response: " + ALL_SERVER_INFO); } resource = newResourceResponse(ALL_SERVER_INFO, Integer.toString(result.asMap().hashCode()), result); return newResultPromise(resource); } catch (Exception e) { debug.error( "ServerInfoResource.getAllServerInfo : Cannot retrieve all server info domains.", e); return new NotFoundException(e.getMessage()).asPromise(); } }
private static void initConfig() { adviceParams.add("module"); adviceParams.add("authlevel"); adviceParams.add("role"); adviceParams.add("service"); adviceParams.add("user"); adviceParams.add("realm"); adviceParams.add("org"); adviceParams.add("resource"); adviceParams.add("sunamcompositeadvice"); String invalidStrings = SystemPropertiesManager.get(Constants.INVALID_GOTO_STRINGS); if (INVALID_SET.isEmpty()) { debug.message("CDCClientServlet.initConfig: creating invalidSet"); if (invalidStrings == null) { debug.message("CDCClientServlet.initConfig: invalidStrings is null"); INVALID_SET.add(LEFT_ANGLE); INVALID_SET.add(RIGHT_ANGLE); INVALID_SET.add(URLENC_LEFT_ANGLE); INVALID_SET.add(URLENC_RIGHT_ANGLE); INVALID_SET.add(JAVASCRIPT); INVALID_SET.add(URLENC_JAVASCRIPT); } else { if (debug.messageEnabled()) { debug.message("CDCClientServlet.initConfig: invalidStrings is: " + invalidStrings); } StringTokenizer st = new StringTokenizer(invalidStrings, DELIM); while (st.hasMoreTokens()) { INVALID_SET.add(st.nextToken()); } } debug.message("CDCClientServlet.initConfig: created invalidSet " + INVALID_SET); } String urlFromProps = SystemProperties.get(Constants.CDCSERVLET_LOGIN_URL); cdcAuthURI = (urlFromProps != null) ? urlFromProps : AUTHURI; String validLoginURIStrings = SystemPropertiesManager.get(Constants.VALID_LOGIN_URIS); debug.message("CDCClientServlet.initConfig: creating validLoginURISet"); if (validLoginURIStrings == null) { debug.message( "CDCClientServlet.initConfig: validLoginURIStrings is null, creating default set"); VALID_LOGIN_URIS.add(cdcAuthURI); } else { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.initConfig: validLoginURIStrings is: " + validLoginURIStrings); } StringTokenizer st = new StringTokenizer(validLoginURIStrings, DELIM); while (st.hasMoreTokens()) { VALID_LOGIN_URIS.add(st.nextToken()); } } debug.message("CDCClientServlet.initConfig: created validLoginURISet " + VALID_LOGIN_URIS); }
private static HashSet getPropertyRetryErrorCodes(String key) { HashSet codes = new HashSet(); String retryErrorStr = SystemProperties.get(key); if (retryErrorStr != null && retryErrorStr.trim().length() > 0) { StringTokenizer stz = new StringTokenizer(retryErrorStr, ","); while (stz.hasMoreTokens()) { codes.add(stz.nextToken().trim()); } } return codes; }
static { String tmp = SystemProperties.get("com.iplanet.am.jssproxy.trustAllServerCerts"); trustAllServerCerts = (tmp != null && tmp.equalsIgnoreCase("true")); tmp = SystemProperties.get("com.iplanet.am.jssproxy.checkSubjectAltName"); checkSubjectAltName = (tmp != null && tmp.equalsIgnoreCase("true")); tmp = SystemProperties.get("com.iplanet.am.jssproxy.resolveIPAddress"); resolveIPAddress = (tmp != null && tmp.equalsIgnoreCase("true")); tmp = SystemProperties.get("com.iplanet.am.jssproxy.SSLTrustHostList", null); if (tmp != null) { getSSLTrustHosts(tmp); } if (debug.messageEnabled()) { debug.message("AMHostnameVerifier trustAllServerCerts = " + trustAllServerCerts); debug.message("AMHostnameVerifier checkSubjectAltName = " + checkSubjectAltName); debug.message("AMHostnameVerifier resolveIPAddress = " + resolveIPAddress); debug.message("AMHostnameVerifier SSLTrustHostList = " + sslTrustHosts.toString()); } }
public Class<? extends DataLayerConnectionModule> getConfigurationClass() { String configuredTypeKey = CONFIGURATION_CLASS_PROPERTY_PREFIX + this.name(); String configuredType = SystemProperties.get(configuredTypeKey); if (StringUtils.isNotBlank(configuredType)) { try { return Class.forName(configuredType).asSubclass(DataLayerConnectionModule.class); } catch (ClassNotFoundException e) { throw new IllegalStateException( "Configured data layer configuration type does not exist: " + configuredTypeKey + " is configured as " + configuredType); } } return configurationClass; }
// Static Initialization Stanza. static { sessionDebug = Debug.getInstance("amSession"); if (doRequestFlag != null) { if (doRequestFlag.equals("false")) doRequest = false; } if (hcPath == null) { String deployuri = SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR, "/openam"); hcPath = deployuri + "/namingservice"; if (!hcPath.startsWith("/")) { hcPath += "/" + hcPath; } GET_REQUEST = "GET " + hcPath + " HTTP/1.0"; } } // End of Static Initialization Stanza
/** * Method to check if caching is enabled or disabled and configure the size of the cache * accordingly. */ private static void initializeParams() { // Check if the caching property is set in System runtime. String cacheSize = SystemProperties.get(CACHE_MAX_SIZE_KEY, "10000"); try { maxSize = Integer.parseInt(cacheSize); if (maxSize < 1) { maxSize = 10000; // Default } if (getDebug().messageEnabled()) { getDebug() .message( "CachedRemoteServicesImpl." + "intializeParams() Caching size set to: " + maxSize); } } catch (NumberFormatException ne) { maxSize = 10000; getDebug() .warning( "CachedRemoteServicesImpl.initializeParams() " + "- invalid value for cache size specified. Setting " + "to default value: " + maxSize); } }
private int validateTokenId(HttpServletRequest request) throws ServletException, IOException { String tokenId = request.getHeader(RestServiceManager.SUBJECT_HEADER_NAME); String hashed = request.getParameter(RestServiceManager.HASHED_SUBJECT_QUERY); if (((tokenId == null) || (tokenId.trim().length() == 0)) && ((hashed == null) || (hashed.trim().length() == 0))) { // by pass the check return HttpServletResponse.SC_OK; } if ((tokenId == null) || (tokenId.trim().length() == 0)) { try { SSOTokenManager mgr = SSOTokenManager.getInstance(); SSOToken token = mgr.createSSOToken(request); tokenId = token.getTokenID().toString(); } catch (SSOException e) { return HttpServletResponse.SC_UNAUTHORIZED; } } if (!Boolean.parseBoolean( SystemProperties.get(RestServiceManager.DISABLE_HASHED_SUBJECT_CHECK, "false"))) { if ((hashed == null) || (hashed.trim().length() == 0)) { return HttpServletResponse.SC_UNAUTHORIZED; } else { int idx = tokenId.indexOf(':'); if (idx != -1) { tokenId = tokenId.substring(idx + 1); } if (!Hash.hash(tokenId).equals(hashed)) { return HttpServletResponse.SC_UNAUTHORIZED; } } } return HttpServletResponse.SC_OK; }
private static int getPropertyIntValue(String key, int defaultValue) { int value = defaultValue; String valueStr = SystemProperties.get(key); if (valueStr != null && valueStr.trim().length() > 0) { try { value = Integer.parseInt(valueStr); } catch (NumberFormatException e) { value = defaultValue; if (debugger.warningEnabled()) { debugger.warning( "EventService.getPropertyIntValue(): " + "Invalid value for property: " + EVENT_CONNECTION_NUM_RETRIES + " Defaulting to value: " + defaultValue); } } } if (debugger.messageEnabled()) { debugger.message("EventService.getPropertyIntValue(): " + key + " = " + value); } return value; }
private String getSsoTokenId(OAuth2Request request) { return cookieExtractor.extract( ServletUtils.getRequest(request.<Request>getRequest()), SystemProperties.get("com.iplanet.am.cookie.name")); }
/** * This class is used to initialize the Authentication service and retrieve the Global attributes * for the Authentication service. It also initializes the other dependent services in the OpenSSO * system and hence used as bootstrap class for the authentication server. */ public class AuthD { /** Debug instance for error / message logging */ public static Debug debug; private static Map bundles = new HashMap(); private static AuthD authInstance; private static boolean authInitFailed = false; private static String superAdmin = DNUtils.normalizeDN(SystemProperties.get(Constants.AUTHENTICATION_SUPER_USER, "")); private static AMIdentity superUserIdentity = null; private static String specialUser = SystemProperties.get(Constants.AUTHENTICATION_SPECIAL_USERS, ""); // Admin Console properties private static final String consoleProto = SystemProperties.get(Constants.AM_CONSOLE_PROTOCOL, "http"); private static final String consoleHost = SystemProperties.get(Constants.AM_CONSOLE_HOST); private static final String consolePort = SystemProperties.get(Constants.AM_CONSOLE_PORT); private static final boolean isConsoleRemote = Boolean.valueOf(SystemProperties.get(Constants.AM_CONSOLE_REMOTE)).booleanValue(); /** Default auth level for auth module */ public static final String DEFAULT_AUTH_LEVEL = "0"; /** Configured value for access logging */ public static final int LOG_ACCESS = 0; /** Configured value for error logging */ public static final int LOG_ERROR = 1; /** supported Auth Modules cache - lw */ public static Hashtable sAuth; /** Flag to force to use JAAS thread. Default is false. */ public static boolean enforceJAASThread = false; /** Configured directory server host name for auth */ public static String directoryHostName = SystemProperties.get(Constants.AM_DIRECTORY_HOST); /** Configured directory server port number for auth */ public static int directoryPort; /** Configured revisionNumber for auth service */ public static int revisionNumber; private static HashMap idRepoMap = new HashMap(); private static HashMap orgMap = new HashMap(); private static HashMap orgValidDomains = new HashMap(); /** Configured bundle name for auth service */ public static final String BUNDLE_NAME = ISAuthConstants.AUTH_BUNDLE_NAME; private String defaultOrg; private String platformLocale; private String platformCharset; /** ResourceBundle for auth service */ public ResourceBundle bundle = null; private SSOToken ssoAuthSession = null; private Session authSession = null; private AMStoreConnection dpStore = null; // client detection and client type variable String clientDetectionClass = null; /** locale read from AMConfig.properties used for remote client auth. */ public static String platLocale = SystemProperties.get(Constants.AM_LOCALE); // auth default locale defined in iPlanetAMAuthService private String defaultAuthLocale; // platform service schema ServiceSchema platformSchema; // session service schema ServiceSchema sessionSchema; // table for service templates private static boolean logStatus = false; /** Set of default URLs for login success */ public Set defaultSuccessURLSet = null; /** Current default URLs for login success */ public String defaultSuccessURL = null; /** Set of default URLs for login failure */ public Set defaultFailureURLSet = null; /** Current default URLs for login failure */ public String defaultFailureURL = null; /** Set of default URLs for service success */ public Set defaultServiceSuccessURLSet = null; /** Set of default URLs for service failure */ public Set defaultServiceFailureURLSet = null; private String adminAuthModule; /** Default auth level for module */ public String defaultAuthLevel; private Hashtable authMethods = new Hashtable(); private long defaultSleepTime = 300; /* 5 minutes */ private ServletContext servletContext; private static boolean useHttpSession; static { String status = SystemProperties.get(Constants.AM_LOGSTATUS, "INACTIVE"); if ("ACTIVE".equalsIgnoreCase(status)) { logStatus = true; } // Get Directory Port value try { directoryPort = Integer.parseInt(SystemProperties.get(Constants.AM_DIRECTORY_PORT)); } catch (java.lang.NumberFormatException nfex) { directoryPort = 0; } // Get Session store String useHttpSessionStr = SystemProperties.get(ISAuthConstants.SESSION_STORE); if (useHttpSessionStr != null && useHttpSessionStr.equalsIgnoreCase("HttpSession")) { useHttpSession = true; } debug = Debug.getInstance(BUNDLE_NAME); if (debug.messageEnabled()) { debug.message("Directory Host: " + directoryHostName + "\nDirectory PORT : " + directoryPort); debug.message("Session store using " + useHttpSessionStr); } } String rootSuffix = null; private AuthD() { debug.message("AuthD initializing"); try { rootSuffix = defaultOrg = ServiceManager.getBaseDN(); initAuthSessions(); initAuthServiceGlobalSettings(); initPlatformServiceGlobalSettings(); initSessionServiceDynamicSettings(); initAuthConfigGlobalSettings(); bundle = com.sun.identity.shared.locale.Locale.getInstallResourceBundle(BUNDLE_NAME); ResourceBundle platBundle = com.sun.identity.shared.locale.Locale.getInstallResourceBundle("amPlatform"); platformCharset = platBundle.getString(ISAuthConstants.PLATFORM_CHARSET_ATTR); printProfileAttrs(); // Initialize AuthXMLHandler so that AdminTokenAction can // generate DPro Session's SSOToken new com.sun.identity.authentication.server.AuthXMLHandler(); authInitFailed = false; } catch (Exception ex) { debug.error("AuthD init()", ex); authInitFailed = true; } try { enforceJAASThread = Boolean.valueOf(SystemProperties.get(Constants.ENFORCE_JAAS_THREAD)).booleanValue(); } catch (Exception e) { if (debug.messageEnabled()) { debug.message("Wrong format of " + Constants.ENFORCE_JAAS_THREAD); } } } /** * Initialized auth service global attributes * * @throws SMSException if it fails to get auth service for name * @throws SSOException if admin <code>SSOToken</code> is not valid * @throws Exception */ private void initAuthServiceGlobalSettings() throws SMSException, SSOException, Exception { ServiceSchemaManager scm = new ServiceSchemaManager(ISAuthConstants.AUTH_SERVICE_NAME, ssoAuthSession); revisionNumber = scm.getRevisionNumber(); if (debug.messageEnabled()) { debug.message("revision number = " + revisionNumber); } updateAuthServiceGlobals(scm); new AuthConfigMonitor(scm); } /** * Update the AuthService global and organization settings. most of the code is moved in from * AuthenticatorManager.java. * * @param scm <code>ServiceSchemaManager</code> to be used for update * @throws SMSException if it fails to update auth service * @throws Exception */ synchronized void updateAuthServiceGlobals(ServiceSchemaManager scm) throws SMSException, Exception { ServiceSchema schema = scm.getOrganizationSchema(); Map attrs = schema.getAttributeDefaults(); // get Global type attributes for iPlanetAMAuthService schema = scm.getGlobalSchema(); attrs.putAll(schema.getAttributeDefaults()); if (debug.messageEnabled()) { debug.message("attrs : " + attrs); } defaultAuthLocale = CollectionHelper.getMapAttr(attrs, ISAuthConstants.AUTH_LOCALE_ATTR); adminAuthModule = CollectionHelper.getMapAttr(attrs, ISAuthConstants.ADMIN_AUTH_MODULE); defaultAuthLevel = CollectionHelper.getMapAttr(attrs, ISAuthConstants.DEFAULT_AUTH_LEVEL, DEFAULT_AUTH_LEVEL); Set s = (Set) attrs.get(ISAuthConstants.AUTHENTICATORS); Iterator iter = s.iterator(); while (iter.hasNext()) { String name = (String) iter.next(); int dot = name.lastIndexOf('.'); if (dot > -1) { String tmp = name.substring(dot + 1, name.length()); authMethods.put(tmp, name); } else { authMethods.put(name, name); } } if (debug.messageEnabled()) { debug.message("AM.update authMethods = " + authMethods.toString()); } defaultSuccessURLSet = (Set) attrs.get(ISAuthConstants.LOGIN_SUCCESS_URL); defaultFailureURLSet = (Set) attrs.get(ISAuthConstants.LOGIN_FAILURE_URL); if (debug.messageEnabled()) { debug.message("Default Success URL Set = " + defaultSuccessURLSet); debug.message("Default Failure URL Set = " + defaultFailureURLSet); } Integer sleepTime = new Integer(CollectionHelper.getMapAttr(attrs, ISAuthConstants.SLEEP_INTERVAL)); defaultSleepTime = sleepTime.longValue(); } /** * Initialize the AuthConfiguration global attributes. * * @throws SMSException if it fails to get auth service for name * @throws SSOException if admin <code>SSOToken</code> is not valid * @throws Exception */ private void initAuthConfigGlobalSettings() throws SMSException, SSOException, Exception { ServiceSchemaManager scm = new ServiceSchemaManager(ISAuthConstants.AUTHCONFIG_SERVICE_NAME, ssoAuthSession); updateAuthConfigGlobals(scm); new AuthConfigMonitor(scm); } /** * Update the AuthConfiguration organization attributes. * * @param scm <code>ServiceSchemaManager</code> to be used for update * @throws SMSException if it fails to update auth service */ synchronized void updateAuthConfigGlobals(ServiceSchemaManager scm) throws SMSException { ServiceSchema schema = scm.getOrganizationSchema(); schema = schema.getSubSchema("Configurations"); schema = schema.getSubSchema("NamedConfiguration"); Map attrs = schema.getAttributeDefaults(); if (attrs != null) { defaultServiceSuccessURLSet = (Set) attrs.get(ISAuthConstants.LOGIN_SUCCESS_URL); defaultServiceFailureURLSet = (Set) attrs.get(ISAuthConstants.LOGIN_FAILURE_URL); } if (debug.messageEnabled()) { debug.message("Default Service Success URL Set = " + defaultServiceSuccessURLSet); debug.message("Default Service Failure URL Set = " + defaultServiceFailureURLSet); } } /** * Initialized platform service global attributes * * @throws SMSException if it fails to initialize platform service * @throws SSOException if admin <code>SSOToken</code> is not valid */ private void initPlatformServiceGlobalSettings() throws SMSException, SSOException { ServiceSchemaManager scm = new ServiceSchemaManager(ISAuthConstants.PLATFORM_SERVICE_NAME, ssoAuthSession); updatePlatformServiceGlobals(scm); new AuthConfigMonitor(scm); } /** * Update the PlatformService global attributes. * * @param scm <code>ServiceSchemaManager</code> to be used for update * @throws SMSException if it fails to initialize platform service */ synchronized void updatePlatformServiceGlobals(ServiceSchemaManager scm) throws SMSException { platformSchema = scm.getGlobalSchema(); Map attrs = platformSchema.getAttributeDefaults(); platformLocale = CollectionHelper.getMapAttr(attrs, ISAuthConstants.PLATFORM_LOCALE_ATTR); if (debug.messageEnabled()) { debug.message("PlatformLocale = " + platformLocale); } } /** * Initialize iPlanetAMSessionService Dynamic attributes * * @throws SMSException if it fails to initialize session service * @throws SSOException if admin <code>SSOToken</code> is not valid */ private void initSessionServiceDynamicSettings() throws SMSException, SSOException { ServiceSchemaManager scm = new ServiceSchemaManager(ISAuthConstants.SESSION_SERVICE_NAME, ssoAuthSession); updateSessionServiceDynamics(scm); new AuthConfigMonitor(scm); } /** * Update the SessionService dynamic attributes. * * @param scm <code>ServiceSchemaManager</code> to be used for update * @throws SMSException if it fails to update session service */ synchronized void updateSessionServiceDynamics(ServiceSchemaManager scm) throws SMSException { sessionSchema = scm.getDynamicSchema(); if (debug.messageEnabled()) { Map attrs = sessionSchema.getAttributeDefaults(); String defaultMaxSessionTime = CollectionHelper.getMapAttr(attrs, ISAuthConstants.MAX_SESSION_TIME, "120"); String defaultMaxIdleTime = CollectionHelper.getMapAttr(attrs, ISAuthConstants.SESS_MAX_IDLE_TIME, "30"); String defaultMaxCachingTime = CollectionHelper.getMapAttr(attrs, ISAuthConstants.SESS_MAX_CACHING_TIME, "3"); debug.message( "AuthD.defaultMaxSessionTime=" + defaultMaxSessionTime + "\nAuthD.defaultMaxIdleTime=" + defaultMaxIdleTime + "\nAuthD.defaultMaxCachingTime=" + defaultMaxCachingTime); } } /** * Return max session time * * @return max session time */ String getDefaultMaxSessionTime() { return CollectionHelper.getMapAttr( sessionSchema.getAttributeDefaults(), ISAuthConstants.MAX_SESSION_TIME, "120"); } /** * Return max session idle time * * @return max session idle time */ String getDefaultMaxIdleTime() { return CollectionHelper.getMapAttr( sessionSchema.getAttributeDefaults(), ISAuthConstants.SESS_MAX_IDLE_TIME, "30"); } /** * Return max session caching time * * @return max session caching time */ String getDefaultMaxCachingTime() { return CollectionHelper.getMapAttr( sessionSchema.getAttributeDefaults(), ISAuthConstants.SESS_MAX_CACHING_TIME, "3"); } /** * Returns attribute map of the specified service in the specified organization. * * @param orgDN Organization DN in which the service exists. * @param serviceName Service name of which the attributes are retrieved. * @return Map containing the attributes of the service. */ public Map getOrgServiceAttributes(String orgDN, String serviceName) { Map map = Collections.EMPTY_MAP; try { AMIdentityRepository idRepo = getAMIdentityRepository(orgDN); AMIdentity realmIdentity = idRepo.getRealmIdentity(); Set set = realmIdentity.getAssignedServices(); if (set.contains(serviceName)) { map = realmIdentity.getServiceAttributes(serviceName); } } catch (Exception e) { if (debug.messageEnabled()) { debug.message( "Exception in getting service attributes for " + serviceName + " in org " + orgDN); } } return map; } /** * Returns Authenticator singleton instance. * * @return Authenticator singleton instance. */ public static AuthD getAuth() { if (authInstance == null) { synchronized (AuthD.class) { if (authInstance == null) { authInstance = new AuthD(); if (authInitFailed) { authInstance = null; } } } } return authInstance; } /** * Destroy sessionfor given <code>SessionID</code> * * @param sid <code>SessionID</code> to be destroyed */ public void destroySession(SessionID sid) { getSS().destroyInternalSession(sid); } /** * Logout sessionfor given <code>SessionID</code> * * @param sid <code>SessionID</code> to be logout */ public void logoutSession(SessionID sid) { getSS().logoutInternalSession(sid); } /** * Creates a new session. * * @param domain Domain Name. * @param httpSession HTTP Session. * @return new <code>InternalSession</code> */ public static InternalSession newSession(String domain, HttpSession httpSession) { InternalSession is = null; try { is = getSS().newInternalSession(domain, httpSession); } catch (Exception ex) { ex.printStackTrace(); debug.error("Error creating session: ", ex); } return is; } /** * Returns the session associated with a session ID. * * @param sessId Session ID. * @return the <code>InternalSession</code> associated with a session ID. */ public static InternalSession getSession(String sessId) { if (debug.messageEnabled()) { debug.message("getSession for " + sessId); } InternalSession is = null; if (sessId != null) { SessionID sid = new SessionID(sessId); is = getSession(sid); } if (is == null) { debug.message("getSession returned null"); } return is; } /** * Returns the session associated with a session ID. * * @param sid Session ID. * @return the <code>InternalSession</code> associated with a session ID. */ public static InternalSession getSession(SessionID sid) { InternalSession is = null; if (sid != null) { is = getSS().getInternalSession(sid); } return is; } /** * Returns the session associated with an HTTP Servlet Request. * * @param req HTTP Servlet Request. * @return the <code>InternalSession</code> associated with anHTTP Servlet Request. */ public InternalSession getSession(HttpServletRequest req) { SessionID sid = new SessionID(req); return getSession(sid); } //////////////////////////////////////////////////////////////// // AuthD utilities //////////////////////////////////////////////////////////////// /** * Returns an Authenticator for a specific module name. * * @param moduleName Module name example <code>LDAP</code>. * @return Authenticator for a specific module name. */ public String getAuthenticatorForName(String moduleName) { return (String) authMethods.get(moduleName); } /** * Returns <code>true</code> if the specified module is one of the authenticators. * * @param module Module name example <code>LDAP</code>. * @return <code>true</code> if the specified module is one of the authenticators. */ public boolean containsAuthenticator(String module) { return authMethods.containsKey(module); } /** * Return configured Authenticators * * @return list of configured Authenticators */ public Iterator getAuthenticators() { return authMethods.keySet().iterator(); } /** * Return number configured Authenticators * * @return number configured Authenticators */ public int getAuthenticatorCount() { return authMethods.size(); } /** * Return configured PlatformCharset * * @return configured PlatformCharset */ public String getPlatformCharset() { return platformCharset; } /** * Return configured PlatformLocale * * @return configured PlatformLocale */ public String getPlatformLocale() { return platformLocale; } /** * Return configured <code>Locale</code> for auth service * * @return configured <code>Locale</code> for auth service */ public String getCoreAuthLocaleFromAuthService() { /* Method used by LoginState to find out core * auth locale is defined or not */ return defaultAuthLocale; } /** * Return default <code>Locale</code> for auth service * * @return default <code>Locale</code> for auth service */ public String getDefaultAuthLocale() { /* Since this method returned a fallback locale "en_US" * and is a public method, * It is configured to return en_US in case defaultAuthLocale == null */ if (defaultAuthLocale == null || defaultAuthLocale.length() == 0) return "en_US"; return defaultAuthLocale; } /** Log Logout status */ public void logLogout(SSOToken ssot) { try { String logLogout = bundle.getString("logout"); List dataList = new ArrayList(); dataList.add(logLogout); StringBuilder messageId = new StringBuilder(); messageId.append("LOGOUT"); String indexType = ssot.getProperty(ISAuthConstants.INDEX_TYPE); if (indexType != null) { messageId.append("_").append(indexType.toString().toUpperCase()); dataList.add(indexType.toString()); if (indexType.equals(AuthContext.IndexType.USER.toString())) { dataList.add(ssot.getProperty(ISAuthConstants.PRINCIPAL)); } else if (indexType.equals(AuthContext.IndexType.ROLE.toString())) { dataList.add(ssot.getProperty(ISAuthConstants.ROLE)); } else if (indexType.equals(AuthContext.IndexType.SERVICE.toString())) { dataList.add(ssot.getProperty(ISAuthConstants.SERVICE)); } else if (indexType.equals(AuthContext.IndexType.LEVEL.toString())) { dataList.add(ssot.getProperty(ISAuthConstants.AUTH_LEVEL)); } else if (indexType.equals(AuthContext.IndexType.MODULE_INSTANCE.toString())) { dataList.add(ssot.getProperty(ISAuthConstants.AUTH_TYPE)); } } Hashtable props = new Hashtable(); String client = ssot.getProperty(ISAuthConstants.HOST); if (client != null) { props.put(LogConstants.IP_ADDR, client); } String userDN = ssot.getProperty(ISAuthConstants.PRINCIPAL); if (userDN != null) { props.put(LogConstants.LOGIN_ID, userDN); } String orgDN = ssot.getProperty(ISAuthConstants.ORGANIZATION); if (orgDN != null) { props.put(LogConstants.DOMAIN, orgDN); } String authMethName = ssot.getProperty(ISAuthConstants.AUTH_TYPE); if (authMethName != null) { props.put(LogConstants.MODULE_NAME, authMethName); } String contextId = null; contextId = ssot.getProperty(Constants.AM_CTX_ID); if (contextId != null) { props.put(LogConstants.CONTEXT_ID, contextId); } props.put(LogConstants.LOGIN_ID_SID, ssot.getTokenID().toString()); String[] data = (String[]) dataList.toArray(new String[0]); this.logIt(data, this.LOG_ACCESS, messageId.toString(), props); } catch (SSOException ssoExp) { debug.error("AuthD.logLogout: SSO Error", ssoExp); } catch (Exception e) { debug.error("AuthD.logLogout: Error ", e); } } //////////////////////////////////////////////////////////////// // Other utilities //////////////////////////////////////////////////////////////// com.sun.identity.log.Logger logger = null; /** * Writes a log record. * * @param s Array of data information for the log record. * @param type Type of log either <code>LOG_ERROR</code> or <code>LOG_ACCESS</code>. * @param messageName Message ID for the log record. * @param ssoProperties Single Sign On Properties to be written to the log record. If this is * <code>null</code>, properties will be retrieved from administrator Single Sign On Token. */ public void logIt(String[] s, int type, String messageName, Hashtable ssoProperties) { if (logStatus && (s != null)) { try { LogMessageProviderBase provider = (LogMessageProviderBase) MessageProviderFactory.getProvider("Authentication"); com.sun.identity.log.LogRecord lr = null; SSOToken ssot = (SSOToken) AccessController.doPrivileged(AdminTokenAction.getInstance()); if (ssoProperties == null) { lr = provider.createLogRecord(messageName, s, ssot); } else { lr = provider.createLogRecord(messageName, s, ssoProperties); } switch (type) { case LOG_ACCESS: logger = (com.sun.identity.log.Logger) Logger.getLogger("amAuthentication.access"); logger.log(lr, ssot); break; case LOG_ERROR: logger = (com.sun.identity.log.Logger) Logger.getLogger("amAuthentication.error"); logger.log(lr, ssot); break; default: logger = (com.sun.identity.log.Logger) Logger.getLogger("amAuthentication.access"); logger.log(lr, ssot); break; } } catch (IOException ex) { ex.printStackTrace(); debug.error("Logging exception : " + ex.getMessage()); } } } /** * Returns connection for AM store. Only used for backward compatibilty support, for retrieving * user container DN and usernaming attr. * * @return connection for AM store */ public AMStoreConnection getSDK() { if (dpStore == null) { try { dpStore = new AMStoreConnection(ssoAuthSession); } catch (SSOException e) { debug.warning("AuthD.getSDK", e); } } return dpStore; } void printProfileAttrs() { if (!debug.messageEnabled()) { return; } debug.message("Authd Profile Attributes"); String adminAuthName = adminAuthModule; int index = adminAuthModule.lastIndexOf("."); if (index > 0) { adminAuthName = adminAuthModule.substring(index + 1); } if (debug.messageEnabled()) { debug.message( "adminAuthModule->" + adminAuthModule + "\nadminAuthName->" + adminAuthName + "\ndefaultOrg->" + defaultOrg + "\nlocale->" + platformLocale + "\ncharset>" + platformCharset); } } static SessionService getSS() { SessionService ss = SessionService.getSessionService(); if (ss == null) { debug.error("AuthD failed to get session service instance"); } return ss; } /** * Return default organization * * @return default organization */ public String getDefaultOrg() { return defaultOrg; } /** * Return current session for auth * * @return current session for auth */ public Session getAuthSession() { return authSession; } /** * Return current sso session for auth * * @return current sso session for auth */ public SSOToken getSSOAuthSession() { return ssoAuthSession; } private void initAuthSessions() throws SSOException, SessionException { if (authSession == null) { authSession = getSS().getAuthenticationSession(defaultOrg, null); if (authSession == null) { debug.error("AuthD failed to get auth session"); throw new SessionException(BUNDLE_NAME, "gettingSessionFailed", null); } String clientID = authSession.getClientID(); authSession.setProperty("Principal", clientID); authSession.setProperty("Organization", defaultOrg); authSession.setProperty("Host", authSession.getID().getSessionServer()); DN dn = new DN(clientID); if (dn.isDN()) { String[] tokens = dn.explodeDN(true); String id = "id=" + tokens[0] + ",ou=user," + ServiceManager.getBaseDN(); authSession.setProperty(Constants.UNIVERSAL_IDENTIFIER, id); } SSOTokenManager ssoManager = SSOTokenManager.getInstance(); ssoAuthSession = ssoManager.createSSOToken(authSession.getID().toString()); } } /** * get inetDomainStatus attribute for the org * * @param orgName org name to check inetDomainStatus * @return true if org is active * @throws IdRepoException if can not can any information for org * @throws SSOException if can not use <code>SSOToken</code> for admin */ boolean getInetDomainStatus(String orgName) throws IdRepoException, SSOException { return IdUtils.isOrganizationActive(ssoAuthSession, orgName); } /** * Returns <code>true</code> if distinguished user name is a super administrator DN. * * @param dn Distinguished name of user. * @return <code>true</code> if user is super administrator. */ public boolean isSuperAdmin(String dn) { boolean isAdmin = false; String nDN = DNUtils.normalizeDN(dn); if ((nDN != null) && (superAdmin != null || specialUser != null)) { if (debug.messageEnabled()) { debug.message("passed dn is :" + dn); } if (superAdmin != null) { if (debug.messageEnabled()) { debug.message("normalized super dn is :" + superAdmin); } isAdmin = nDN.equals(superAdmin); } if (!isAdmin) { isAdmin = isSpecialUser(nDN); } } if (debug.messageEnabled()) { debug.message("is Super Admin :" + isAdmin); } return isAdmin; } /** * Returns <code>true</code> if and only if the user name belongs to a super user * * @param dn DN of the user * @return <code>true</code> if the user is an admin user. */ public boolean isSuperUser(String dn) { if (superUserIdentity == null) { superUserIdentity = new AMIdentity( AccessController.doPrivileged(AdminTokenAction.getInstance()), superAdmin, IdType.USER, "/", null); } return superUserIdentity.getUniversalId().equalsIgnoreCase(dn); } /** * Returns <code>true</code> if distinguished user name is a special user DN. * * @param dn Distinguished name of user. * @return <code>true</code> if user is a special user. */ public boolean isSpecialUser(String dn) { // dn in all the invocation is normalized. boolean isSpecialUser = false; String nDN = DNUtils.normalizeDN(dn); if ((nDN != null) && (specialUser != null)) { StringTokenizer st = new StringTokenizer(specialUser, "|"); while (st.hasMoreTokens()) { String specialAdminDN = (String) st.nextToken(); if (specialAdminDN != null) { String normSpecialAdmin = DNUtils.normalizeDN(specialAdminDN); if (debug.messageEnabled()) { debug.message("normalized special dn is :" + normSpecialAdmin); } if (nDN.equals(normSpecialAdmin)) { isSpecialUser = true; break; } } } } if (debug.messageEnabled()) { debug.message("is Special User :"******"userOrg is : " + userOrg); debug.message("rootSuffix is : " + rootSuffix); debug.message("rootSuffixDN is : " + rootSuffixDN); debug.message("userOrgDN is : " + userOrgDN); } if ((userOrgDN.equals(rootSuffixDN)) || (userOrgDN.isDescendantOf(rootSuffixDN))) { orgDN = userOrgDN.toString(); } else { orgDN = (new StringBuffer(50)) .append(userOrgDN.toString()) .append(",") .append(rootSuffixDN) .toString(); } if (debug.messageEnabled()) { debug.message("Returning OrgDN is : " + orgDN); } return orgDN.toString(); } /** * Returns the dynamic replacement of the URL from the Success or Failure URLs. * * @param URL * @param servletRequest * @return the dynamic replacement of the URL from the Success or Failure URLs. */ public String processURL(String URL, HttpServletRequest servletRequest) { String url = URL; if (url != null) { url = processDynamicVariables(url, servletRequest); } if (debug.messageEnabled()) { debug.message("processURL : " + url); } return url; } /** * This function returns the dynamic replacement of the protocol from the Success or Failure urls * * @param rawURL Raw url with out real protocol * @param servletRequest Servlet request has real protocol value * @return the dynamic replacement of the protocol from the Success or Failure urls */ private String processDynamicVariables(String rawURL, HttpServletRequest servletRequest) { if (rawURL.indexOf("%") != -1) { int index; StringBuilder sb = new StringBuilder(200); // protocol processing if ((index = rawURL.indexOf("%protocol")) != -1) { sb.append(rawURL.substring(0, index)); if (isConsoleRemote) { sb.append(consoleProto); } else { String protocol = null; if (servletRequest != null) { protocol = RequestUtils.getRedirectProtocol( servletRequest.getScheme(), servletRequest.getServerName()); } if (protocol != null) { sb.append(protocol); } else { sb.append(consoleProto); } } sb.append(rawURL.substring(index + "%protocol".length())); rawURL = sb.toString(); } if ((index = rawURL.indexOf("%host")) != -1) { int hostlen = "%host".length(); sb.delete(0, 200); sb.append(rawURL.substring(0, index)); if (isConsoleRemote) { sb.append(consoleHost); } else { String host = null; if (servletRequest != null) { host = servletRequest.getHeader("Host"); } if (host != null) { sb.append(host); // This is to remove extra ":" hostlen = hostlen + 1; } else { sb.append(consoleHost); } } sb.append(rawURL.substring(index + hostlen)); rawURL = sb.toString(); } if ((index = rawURL.indexOf("%port")) != -1) { sb.delete(0, 200); sb.append(rawURL.substring(0, index)); if (isConsoleRemote) { sb.append(consolePort); } sb.append(rawURL.substring(index + "%port".length())); rawURL = sb.toString(); } } return rawURL; } /** * Sets the Servlet Context. * * @param servletContext Servlet Context to be set. */ public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; if (debug.messageEnabled()) { debug.message("Setting servletContext" + servletContext); } } /** * Returns the Servlet Context. * * @return Servlet Context. */ public ServletContext getServletContext() { return servletContext; } /** * Returns the OpenSSO Identity Repository for an organization. * * @param orgDN name of the organization * @return OpenSSO Identity Repository. */ public AMIdentityRepository getAMIdentityRepository(String orgDN) { AMIdentityRepository amIdentityRepository = null; try { if ((idRepoMap != null) && (!idRepoMap.isEmpty())) { amIdentityRepository = (AMIdentityRepository) idRepoMap.get(orgDN); } if (amIdentityRepository == null) { amIdentityRepository = new AMIdentityRepository(ssoAuthSession, orgDN); synchronized (idRepoMap) { idRepoMap.put(orgDN, amIdentityRepository); } } } catch (Exception id) { if (debug.messageEnabled()) { debug.message("Error getAMIdentityRepository", id); } } return amIdentityRepository; } /** * Returns the Organization Configuration Manager for an organization. * * @param orgDN Name of the organization. * @return Organization Configuration Manager for an organization. */ public OrganizationConfigManager getOrgConfigManager(String orgDN) { OrganizationConfigManager orgConfigMgr = null; try { if ((orgMap != null) && (!orgMap.isEmpty())) { orgConfigMgr = (OrganizationConfigManager) orgMap.get(orgDN); } synchronized (orgMap) { if (orgConfigMgr == null) { orgConfigMgr = new OrganizationConfigManager(ssoAuthSession, orgDN); orgMap.put(orgDN, orgConfigMgr); } } } catch (Exception id) { if (debug.messageEnabled()) { debug.message("Error getAMIdentityRepository", id); } } return orgConfigMgr; } /** * Returns the <code>AMIdentity</code> object for the given parameters. If there is no such * identity, or there is more then one matching identity, then an AuthException will be thrown. * * @param idType Identity Type. * @param idName Identity Name. * @param orgName organization name. * @return <code>AMIdentity</code> object. * @throws AuthException if there was no result, or if there was more results then one. */ public AMIdentity getIdentity(IdType idType, String idName, String orgName) throws AuthException { if (debug.messageEnabled()) { debug.message("IdType is :" + idType); debug.message("IdName is :" + idName); debug.message("orgName is :" + orgName); } AMIdentity amIdentity = null; // Try getting the identity using IdUtils.getIdentity(...) try { if (debug.messageEnabled()) { debug.message("AuthD.getIdentity() from IdUtils Name: " + idName + " Org: " + orgName); } amIdentity = IdUtils.getIdentity(getSSOAuthSession(), idName, orgName); if ((amIdentity != null) && (amIdentity.isExists()) && (amIdentity.getType().equals(idType)) && (amIdentity.getAttributes() != null)) { if (debug.messageEnabled()) { debug.message( "AuthD.getIdentity obtained identity" + "using IdUtil.getIdentity: " + amIdentity); } return (amIdentity); } } catch (IdRepoException e) { // Ignore this exception and continue with search if (debug.messageEnabled()) { debug.message( "AuthD.getIdentity: Got IdRepoException while " + "getting Identity from IdUtils: " + e.getMessage()); } } catch (SSOException ssoe) { // Ignore this exception and continue with search if (debug.messageEnabled()) { debug.message( "AuthD.getIdentity: Got SSOException while " + "getting Identity from IdUtils: " + ssoe.getMessage()); } } // Obtain AMIdentity object by searching within IdRepo try { amIdentity = null; idName = DNUtils.DNtoName(idName); AMIdentityRepository amIdRepo = getAMIdentityRepository(orgName); IdSearchControl idsc = new IdSearchControl(); idsc.setRecursive(true); idsc.setTimeOut(0); idsc.setMaxResults(0); idsc.setAllReturnAttributes(false); IdSearchResults searchResults = amIdRepo.searchIdentities(idType, idName, idsc); Set results = Collections.EMPTY_SET; if (searchResults != null) { results = searchResults.getSearchResults(); } if ((results != null) && (results.size() > 1)) { // multiple user match found, throw exception, // user need to login as super admin to fix it debug.error("getIdentity: Multiple matches found for " + "user '" + idName); throw new AuthException(AMAuthErrorCode.AUTH_ERROR, null); } Iterator users = results.iterator(); if (users.hasNext()) { amIdentity = (AMIdentity) users.next(); } } catch (SSOException sso) { if (debug.messageEnabled()) { debug.message("getIdentity error " + sso.getMessage()); } } catch (IdRepoException ide) { if (debug.messageEnabled()) { debug.message("IdRepoException error " + ide.getMessage()); } } if (amIdentity == null) { throw new AuthException(AMAuthErrorCode.AUTH_PROFILE_ERROR, null); } return amIdentity; } /** * Returns the Super Admin user Name. * * @return super admin user name. */ public String getSuperUserName() { return superAdmin; } /** * Return <code>true</code> if it use http session * * @return <code>true</code> if it use http session */ public static boolean isHttpSessionUsed() { return useHttpSession; } /** * Returns the authentication service or chain configured for the given organization. * * @param orgDN organization DN. * @return the authentication service or chain configured for the given organization. */ public String getOrgConfiguredAuthenticationChain(String orgDN) { String orgAuthConfig = null; try { OrganizationConfigManager orgConfigMgr = getOrgConfigManager(orgDN); ServiceConfig svcConfig = orgConfigMgr.getServiceConfig(ISAuthConstants.AUTH_SERVICE_NAME); Map attrs = svcConfig.getAttributes(); orgAuthConfig = Misc.getMapAttr(attrs, ISAuthConstants.AUTHCONFIG_ORG); } catch (Exception e) { debug.error("Error in getOrgConfiguredAuthenticationChain : ", e); } return orgAuthConfig; } /** * Returns a list of domains defined by iplanet-am-auth-valid-goto-domains in iPlanetAMAuthService * plus organization aliases * * @param orgDN organization DN. * @return a Set object containing a list of valid domains, null if * iplanet-am-auth-valid-goto-domains is empty. */ private Set getValidGotoUrlDomains(String orgDN) { Set validGotoUrlDomains = null; try { OrganizationConfigManager orgConfigMgr = getOrgConfigManager(orgDN); ServiceConfig svcConfig = orgConfigMgr.getServiceConfig(ISAuthConstants.AUTH_SERVICE_NAME); Map attrs = svcConfig.getAttributes(); validGotoUrlDomains = (Set) attrs.get(ISAuthConstants.AUTH_GOTO_DOMAINS); if (debug.messageEnabled()) { debug.message("AuthD.getValidGotoUrlDomains(): " + validGotoUrlDomains); } } catch (Exception e) { debug.error("AuthD.getValidGotoUrlDomains():" + "Error in getValidGotoUrlDomains : ", e); } return validGotoUrlDomains; } /** * Checks whether an input URL is valid in an organization * * @param url a String representing a URL to be validated * @param orgDN organization DN. * @return true if input URL is valid, else false. */ public boolean isGotoUrlValid(String url, String orgDN) { Set validGotoUrlDomains = null; if ((!orgValidDomains.isEmpty()) && (orgValidDomains.containsKey(orgDN))) { validGotoUrlDomains = (Set) orgValidDomains.get(orgDN); } else { validGotoUrlDomains = getValidGotoUrlDomains(orgDN); synchronized (orgValidDomains) { if (!orgValidDomains.containsKey(orgDN)) { orgValidDomains.put(orgDN, validGotoUrlDomains); } } } if (validGotoUrlDomains == null || validGotoUrlDomains.isEmpty()) { return true; } URLPatternMatcher patternMatcher = new URLPatternMatcher(); try { return patternMatcher.match(url, new ArrayList(validGotoUrlDomains), true); } catch (MalformedURLException me) { debug.error("AuthD.isGotoUrlValid():" + "Error in validating GotoUrl: " + url, me); return false; } } }
/** * Determine the listener list based on the diable list property and SMS DataStore notification * property in Realm mode */ private static void getListenerList() { String list = SystemProperties.get(EVENT_LISTENER_DISABLE_LIST, ""); if (debugger.messageEnabled()) { debugger.message( "EventService.getListenerList(): " + EVENT_LISTENER_DISABLE_LIST + ": " + list); } boolean enableDataStoreNotification = Boolean.parseBoolean(SystemProperties.get(Constants.SMS_ENABLE_DB_NOTIFICATION)); if (debugger.messageEnabled()) { debugger.message( "EventService.getListenerList(): " + "com.sun.identity.sm.enableDataStoreNotification: " + enableDataStoreNotification); } boolean configTime = Boolean.parseBoolean(SystemProperties.get(Constants.SYS_PROPERTY_INSTALL_TIME)); if (debugger.messageEnabled()) { debugger.message( "EventService.getListenerList(): " + Constants.SYS_PROPERTY_INSTALL_TIME + ": " + configTime); } // Copy the default listeners String[] tmpListeners = new String[ALL_LISTENERS.length]; System.arraycopy(ALL_LISTENERS, 0, tmpListeners, 0, ALL_LISTENERS.length); // Process the configured disabled list first boolean disableACI = false, disableUM = false, disableSM = false; if (list.length() != 0) { StringTokenizer st = new StringTokenizer(list, ","); String listener = ""; while (st.hasMoreTokens()) { listener = st.nextToken().trim(); if (listener.equalsIgnoreCase("aci")) { disableACI = true; } else if (listener.equalsIgnoreCase("um")) { disableUM = true; } else if (listener.equalsIgnoreCase("sm")) { disableSM = true; } else { debugger.error( "EventService.getListenerList() - " + "Invalid listener name: " + listener); } } } if (!disableUM || !disableACI) { // Check if AMSDK is configured boolean disableAMSDK = true; if (!configTime) { try { ServiceSchemaManager scm = new ServiceSchemaManager(getSSOToken(), IdConstants.REPO_SERVICE, "1.0"); ServiceSchema idRepoSubSchema = scm.getOrganizationSchema(); Set idRepoPlugins = idRepoSubSchema.getSubSchemaNames(); if (idRepoPlugins.contains("amSDK")) { disableAMSDK = false; } } catch (SMSException ex) { if (debugger.warningEnabled()) { debugger.warning( "EventService.getListenerList() - " + "Unable to obtain idrepo service", ex); } } catch (SSOException ex) { // Should not happen, ignore the exception } } if (disableAMSDK) { disableUM = true; disableACI = true; if (debugger.messageEnabled()) { debugger.message( "EventService.getListener" + "List(): AMSDK is not configured or config time. " + "Disabling UM and ACI event listeners"); } } } // Verify if SMSnotification should be enabled if (configTime || ServiceManager.isRealmEnabled()) { disableSM = !enableDataStoreNotification; if (debugger.messageEnabled()) { debugger.message( "EventService.getListenerList(): In realm " + "mode or config time, SMS listener is set to datastore " + "notification flag: " + enableDataStoreNotification); } } // Disable the selected listeners if (disableACI) { tmpListeners[0] = null; } if (disableUM) { tmpListeners[1] = null; } if (disableSM) { tmpListeners[2] = null; } listeners = tmpListeners; // if all disabled, signal to not start the thread if (disableACI && disableUM && disableSM) { if (debugger.messageEnabled()) { debugger.message( "EventService.getListenerList() - " + "all listeners are disabled, EventService won't start"); } _allDisabled = true; } else { _allDisabled = false; } }
/** * Redirects the HTTP request to the Authentication module. It gets the authentication url from * <code>SystemProperties</code>. * * @param request an HttpServletRequest object that contains the request the client has made of * the servlet. * @param response an HttpServletResponse object that contains the response the servlet sends to * the client. * @exception IOException If an input or output exception occurs */ private void redirectForAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication: " + "requestURL=" + request.getRequestURL()); } StringBuffer redirectURL = new StringBuffer(100); StringBuffer gotoURL = new StringBuffer(100); // Check if user has authenticated to another OpenSSO // instance String authURL = null; Cookie authCookie = CookieUtils.getCookieFromReq(request, authURLCookieName); if (authCookie != null) { authURL = CookieUtils.getCookieValue(authCookie); if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication: " + "got an authenticated URL= " + authURL); } } try { if (authURL == null || authURL.length() == 0 || !authURL.toLowerCase().startsWith("http") || policyAdviceList != null) { String finalURL = request.getParameter(GOTO_PARAMETER); if (finalURL == null || finalURL.equals("")) { finalURL = request.getParameter(TARGET_PARAMETER); } if (finalURL == null || finalURL.equals("")) { showError(response, "GOTO or TARGET parameter is missing" + " in the request"); return; } gotoURL .append(deployDescriptor) .append(CDCURI) .append(QUESTION_MARK) .append(TARGET_PARAMETER) .append(EQUAL_TO) .append(URLEncDec.encode(finalURL)) .append(AMPERSAND) .append(requestParams); // Construct the login URL String cdcurl = SystemProperties.get(Constants.CDCSERVLET_LOGIN_URL); if (cdcurl != null && cdcurl.length() > 0) { if (cdcurl.indexOf("?") == -1) { redirectURLStr = cdcurl + QUESTION_MARK; } else { redirectURLStr = cdcurl + AMPERSAND; } } else { redirectURLStr = AUTHURI + QUESTION_MARK; } if (debug.messageEnabled()) { debug.message("CDCClientServlet init redirect URL is" + "set to= " + redirectURLStr); } redirectURL.append(redirectURLStr); if (policyAdviceList != null) { redirectURL.append(policyAdviceList).append(AMPERSAND); } redirectURL .append(GOTO_PARAMETER) .append(EQUAL_TO) .append(URLEncDec.encode(gotoURL.toString())); // Check for policy advices if (policyAdviceList != null) { redirectURL.append(AMPERSAND).append(policyAdviceList); } if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication" + ":redirectURL before dispatching is=" + redirectURL); } RequestDispatcher dispatcher = request.getRequestDispatcher(redirectURL.toString()); dispatcher.forward(request, response); } else { // Redirect the user to the authenticated URL redirectURL .append(authURL) .append(deployDescriptor) .append(CDCURI) .append(QUESTION_MARK) .append(request.getQueryString()); // Reset the cookie value to null, to avoid continous loop // when a load balancer is used if (authCookie != null) { authCookie.setValue(""); response.addCookie(authCookie); } response.sendRedirect(redirectURL.toString()); } if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication:" + "Forwarding for authentication to= " + redirectURL); } } catch (IOException ex) { debug.error( "CDCClientServlet.redirectForAuthentication: Failed " + "in forwarding to Authentication service. IOException", ex); showError(response, "Could for forward to authentication service:" + ex.getMessage()); } catch (ServletException se) { debug.error( "CDCClientServlet.redirectForAuthentication : Failed " + "in forwarding to Authentication service. ServletException", se); showError(response, "Could for forward to authentication service:" + se.getMessage()); } catch (IllegalStateException ie) { debug.error( "CDCClientServlet.redirectForAuthentication : Failed " + "in forwarding to Authentication service. Illegal state", ie); showError(response, "Could for forward to authentication service:" + ie.getMessage()); } }
static { debug = com.sun.identity.shared.debug.Debug.getInstance("amXMLHandler"); messageEnabled = debug.messageEnabled(); serviceURI = SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR) + "/authservice"; }
/** * This class Implements utility methods for handling HTTP Session. * * <p> */ public class SessionUtils { /** The QUERY encoding scheme */ public static final short QUERY = 0; /** The SLASH encoding scheme */ public static final short SLASH = 1; /** The SEMICOLON encoding scheme */ public static final short SEMICOLON = 2; static Debug debug = Debug.getInstance("amSessionUtils"); /** Set of trusted Inetaddresses */ private static Set trustedSources = null; /** The HTTPClient IPHeader */ private static final String httpClientIPHeader = SystemProperties.get(Constants.HTTP_CLIENT_IP_HEADER, "proxy-ip"); /** The SESSION_ENCRYPTION to check if this is encrypted session */ private static final boolean SESSION_ENCRYPTION = Boolean.valueOf(SystemProperties.get(Constants.SESSION_REPOSITORY_ENCRYPTION, "false")) .booleanValue(); /** * Returns a SessionID string based on a HttpServletRequest object or null if session id is not * present or there was an error. * * <p> * * @param request The HttpServletRequest object which contains the session string. * @return an encodeURL with sessionID or the url if session was not present or there was an * error. */ public static String getSessionId(HttpServletRequest request) { String sidString = (new SessionID(request)).toString(); if (sidString.length() == 0) { sidString = null; } return sidString; } /** * Returns URL encoded with the cookie Value (SSOToken ID) if cookies are not support. Throws an * SSOException in case of an error. * * <p>The cookie Value is written in the URL based on the encodingScheme specified. The Cookie * Value could be written as path info separated by either a "/" OR ";" or as a query string. * * <p>If the encoding scheme is SLASH then the cookie value would be written in the URL as extra * path info in the following format: * * <pre> * protocol://server:port/servletpath/<cookieName>=<cookieValue>? * queryString * </pre> * * <p>Note that this format works only if the path is a servlet, if a a jsp file is specified then * webcontainers return with "File Not found" error. To rewrite links which are JSP files with * cookie value use the SEMICOLON OR QUERY encoding scheme. * * <p>If the encoding scheme is SEMICOLON then the cookie value would be written in the URL as * extra path info in the following format: * * <pre> * protocol://server:port/path;<cookieName=cookieValue>?queryString * </pre> * * Note that this is not supported in the servlet specification and some web containers do not * support this. * * <p>If the encoding scheme is QUERY then the cookie value would be written in the URL in the * following format: * * <pre> * protocol://server:port/path?<cookieName>=<cookieValue> * protocol://server:port/path?queryString& * <cookieName>=<cookieValue> * </pre> * * <p>This is the default and OpenSSO always encodes in this format unless otherwise specified. If * the URL passed in has query parameter then entity escaping of ampersand will be done before * appending the cookie if the escape is true.Only the ampersand before appending cookie parameter * will be entity escaped. * * <p> * * @param ssoToken Single Sign Token which contains the session string. * @param url the URL to be encoded * @param encodingScheme possible values are <code>QUERY</code>, <code>SLASH</code>, <code> * SEMICOLON</code>. * @param escape <code>true</code> to escape ampersand when appending the Single Sign On Token ID * to request query string. * @return encoded URL with cookie value (session ID) based on the encoding scheme. * @exception SSOException if URL cannot be encoded. */ public static String encodeURL( SSOToken ssoToken, String url, short encodingScheme, boolean escape) throws SSOException { String encodedURL = url; try { SSOTokenID ssoTokenId = ssoToken.getTokenID(); SessionID sessionID = new SessionID(ssoTokenId.toString()); Session session = Session.getSession(sessionID); encodedURL = session.encodeURL(url, encodingScheme, escape); } catch (Exception e) { debug.message("Exception encoding URL ", e); throw new SSOException(e); } return encodedURL; } /** * Returns URL encoded with the cookie Value (SSOToken ID) if cookies are not supported. * * <p>This method assumes default encoding scheme which is QUERY. The cookie value would be * written in the URL in the following format: * * <pre> * protocol://server:port/path?<cookieName>=<cookieValue> * protocol://server:port/path?queryString& * <cookieName>=<cookieValue> * </pre> * * <p>This is the default and OpenSSO always encodes in this format unless otherwise specified. If * the URL passed in has query parameter then entity escaping of ampersand will be done before * appending the cookie if the escape is true.Only the ampersand before appending cookie parameter * will be entity escaped. * * <p> * * @param ssoToken Single Sign Token which contains the session string. * @param url the URL to be encoded. * @param escape <code>true</code> to escape ampersand when appending the Single Sign On Token ID * to request query string. * @return URL encoded with cookie Value in the query string. * @exception SSOException if URL cannot be encoded. */ public static String encodeURL(SSOToken ssoToken, String url, boolean escape) throws SSOException { String encodedURL = url; try { encodedURL = encodeURL(ssoToken, url, QUERY, escape); } catch (Exception e) { debug.message("Exception encoding url", e); throw new SSOException(e); } return encodedURL; } /** * Returns the remote IP address of the client * * @param servletRequest The HttpServletRequest object which contains the session string. * @return InetAddress the client address * @exception Exception */ public static InetAddress getClientAddress(HttpServletRequest servletRequest) throws Exception { InetAddress remoteClient = InetAddress.getByName(servletRequest.getRemoteAddr()); if (isTrustedSource(remoteClient)) { String proxyHeader = servletRequest.getHeader(httpClientIPHeader); if (proxyHeader != null) { remoteClient = InetAddress.getByName(proxyHeader); } } return remoteClient; } /* build the trust source set*/ private static Set getTrustedSourceList() throws SessionException { Set result = new HashSet(); try { String rawList = SystemProperties.get(Constants.TRUSTED_SOURCE_LIST); if (rawList != null) { StringTokenizer stk = new StringTokenizer(rawList, ","); while (stk.hasMoreTokens()) { result.add(InetAddress.getByName(stk.nextToken())); } } else { // use platform server list as a default fallback Vector psl = WebtopNaming.getPlatformServerList(); if (psl == null) { throw new SessionException(SessionBundle.rbName, "emptyTrustedSourceList", null); } for (Enumeration e = psl.elements(); e.hasMoreElements(); ) { try { URL url = new URL((String) e.nextElement()); result.add(InetAddress.getByName(url.getHost())); } catch (Exception ex) { debug.error("SessionUtils.getTrustedSourceList : " + "Validating Host exception", ex); } } } } catch (Exception e) { throw new SessionException(e); } return result; } /** * Returns the remote IP address of the client is a trusted source * * @param source the InetAddress of the remote client * @return a <code>true </code> if is a trusted source.<code>false> otherwise * @exception Exception */ public static boolean isTrustedSource(InetAddress source) throws SessionException { if (trustedSources == null) { trustedSources = getTrustedSourceList(); } return trustedSources.contains(source); } /** * Helper method to serialize and encrypt objects saved in the repository * * @param obj object to be serialized and encrypted * @return encrypted byte array containing serialized objects * @throws Exception if anything goes wrong */ public static byte[] encode(Object obj) throws Exception { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objOutStream = new ObjectOutputStream(byteOut); // convert object to byte using streams objOutStream.writeObject(obj); objOutStream.close(); final byte[] blob = byteOut.toByteArray(); if (SESSION_ENCRYPTION) { return (byte[]) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { return Crypt.getEncryptor().encrypt(blob); } }); } return blob; } /** * Deserializes and decrypts objects retrieved from the repository. * * @param blob Byte array containing serialized and encrypted object value. * @return retrieved object. * @throws Exception if anything goes wrong. */ public static Object decode(final byte blob[]) throws Exception { byte[] decryptedBlob; if (SESSION_ENCRYPTION) { decryptedBlob = (byte[]) AccessController.doPrivileged( new PrivilegedExceptionAction() { public Object run() throws Exception { return Crypt.getEncryptor().decrypt(blob); } }); } else { decryptedBlob = blob; } ByteArrayInputStream byteIn = new ByteArrayInputStream(decryptedBlob); ObjectInputStream objInStream = new ObjectInputStream(byteIn); return objInStream.readObject(); } /** * Helper method to get the encrypted session storage key * * @param sessionID SessionID * @return encrypted session storage key * @throws Exception if anything goes wrong */ public static String getEncryptedStorageKey(SessionID sessionID) throws Exception { String sKey = sessionID.getExtension(SessionID.STORAGE_KEY); if (SESSION_ENCRYPTION) { String strEncrypted = (String) AccessController.doPrivileged( new EncodeAction(sKey, Crypt.getHardcodedKeyEncryptor())); return strEncrypted; } return sKey; } /** * Helper method to get admin token. This is not amadmin user but the user configured in * serverconfig.xml as super user. * * @return SSOToken of super admin. */ public static SSOToken getAdminToken() throws SSOException { SSOToken adminToken = (SSOToken) AccessController.doPrivileged(AdminTokenAction.getInstance()); if (adminToken == null) { I18n i18n = I18n.getInstance(IUMSConstants.UMS_PKG); String rbName = i18n.getResBundleName(); throw new SSOException(rbName, IUMSConstants.NULL_TOKEN, null); } return (adminToken); } /** * Helper method to compare if the user token passed is same as admin token. It does not check if * user token or admin token is valid. * * @param admToken Admin Single Sign-On token. * @param usrToken User Single Sign-On token to compare against admin Single Sign-On token. * @return <code>true</code> if they both are same. */ public static boolean isAdmin(SSOToken admToken, SSOToken usrToken) { if (usrToken == null) { debug.error("SessionUtils.isAdmin(): user token is null"); return false; } if (admToken == null) { debug.error("SessionUtils.isAdmin(): admin token is null"); return false; } boolean result = false; String usrName = null; String admName = null; try { usrName = usrToken.getPrincipal().getName(); } catch (SSOException ssoEx) { debug.error("SessionUtils.isAdmin(): user token fails" + "to get principal"); return false; } try { admName = admToken.getPrincipal().getName(); } catch (SSOException ssoEx) { debug.error("SessionUtils.isAdmin(): admin token fails " + "to get principal"); return false; } if (usrName.equalsIgnoreCase(admName)) { result = true; } if (debug.messageEnabled()) { debug.message( "SessionUtils.isAdmin(): returns " + result + " for user principal: " + usrName + " against admin principal: " + admName); } return result; } /** * Helper method to check if client has taken permission to set value to it. If * * @param clientToken Token of the client setting protected property. * @param key Property key * @param value Property value. * @throws SessionException if the key is protected property. */ public static void checkPermissionToSetProperty(SSOToken clientToken, String key, String value) throws SessionException { if (InternalSession.isProtectedProperty(key)) { if (clientToken == null) { // Throw Ex. Client should identify itself. if (SessionService.sessionDebug.warningEnabled()) { SessionService.sessionDebug.warning( "SessionUtils.checkPermissionToSetProperty(): " + "Attempt to set protected property without client " + "token [" + key + "=" + value + "]"); } throw new SessionException( SessionBundle.getString("protectedPropertyNoClientToken") + " " + key); } SSOTokenManager ssoTokenManager = null; try { ssoTokenManager = SSOTokenManager.getInstance(); } catch (SSOException ssoEx) { // Throw Ex. Not able to get SSOTokenManager instance. SessionService.sessionDebug.error( "SessionUtils.checkPermissionToSetProperty(): " + "Cannot get instance of SSOTokenManager."); throw new SessionException( SessionBundle.getString("protectedPropertyNoSSOTokenMgrInstance") + " " + key); } if (!ssoTokenManager.isValidToken(clientToken)) { // Throw Ex. Client should identify itself. if (SessionService.sessionDebug.warningEnabled()) { SessionService.sessionDebug.warning( "SessionUtils.checkPermissionToSetProperty(): " + "Attempt to set protected property with invalid client" + " token [" + key + "=" + value + "]"); } throw new SessionException( SessionBundle.getString("protectedPropertyInvalidClientToken") + " " + key); } SSOToken admToken = null; try { admToken = SessionUtils.getAdminToken(); } catch (SSOException ssoEx) { // Throw Ex. Server not able to get Admin Token. SessionService.sessionDebug.error( "SessionUtils.checkPermissionToSetProperty(): " + "Cannot get Admin Token for validation to set protected " + "property [" + key + "=" + value + "]"); throw new SessionException( SessionBundle.getString("protectedPropertyNoAdminToken") + " " + key); } if (!SessionUtils.isAdmin(admToken, clientToken)) { // Throw Ex. Client not authorized to set this property. SessionService.sessionDebug.error( "SessionUtils.checkPermissionToSetProperty(): " + "Client does not have permission to set protected " + "property" + key + "=" + value + "]"); throw new SessionException( SessionBundle.getString("protectedPropertyNoPermission") + " " + key); } } } }
/** * The <code>CDCClientServlet</code> is the heart of the Cross Domain Single Signon mechanism of * OpenAM in the DMZ along with the distributed auth. <br> * The following is the algorithm used by the program: * * <ol> * <li>If request does not contain SSO related cookie or policy has generated some advices then * redirect request to the distributed auth service. * <li>If request contains SSO related cookie and no advices. * <ul> * <li>Tunnel the Request to OpenAM. * <li>Send the received AuthNResponse as Form POST to the original request requested using * the goto parameter in the query string. * </ul> * </ol> */ public class CDCClientServlet extends HttpServlet { private static final ArrayList adviceParams = new ArrayList(); private static final Set<String> INVALID_SET = new HashSet<String>(); private static final Set<String> VALID_LOGIN_URIS = new HashSet<String>(); private static final String LEFT_ANGLE = "<"; private static final String RIGHT_ANGLE = ">"; private static final String URLENC_RIGHT_ANGLE = "%3e"; private static final String URLENC_LEFT_ANGLE = "%3c"; private static final String URLENC_JAVASCRIPT = "javascript%3a"; private static final String JAVASCRIPT = "javascript:"; private static final String DELIM = ","; private static final String DEBUG_FILE_NAME = "amCDC"; private static final char QUESTION_MARK = '?'; private static final char AMPERSAND = '&'; private static final char EQUAL_TO = '='; private static final char SEMI_COLON = ';'; private static final char SPACE = ' '; private static final String GOTO_PARAMETER = "goto"; private static final String TARGET_PARAMETER = "TARGET"; private static final String CDCURI = "/cdcservlet"; private static final String LOGIN_URI = "loginURI"; private static String cdcAuthURI; private static final String AUTHURI = "/UI/Login"; private static final String RESPONSE_HEADER_ALERT = "X-DSAME-Assertion-Form"; private static final String RESPONSE_HEADER_ALERT_VALUE = "true"; private static final String FORBIDDEN_STR_MATCH = "#403x"; private static final String SERVER_ERROR_STR_MATCH = "#500x"; static Debug debug = Debug.getInstance(DEBUG_FILE_NAME); static { initConfig(); } private static SSOTokenManager tokenManager; private static String sessionServiceName = "iPlanetAMSessionService"; private static String authURLCookieName; private static String authURLCookieDomain; private static String deployDescriptor; boolean serverMode = Boolean.valueOf( System.getProperty( Constants.SERVER_MODE, SystemProperties.get(Constants.SERVER_MODE, "false"))) .booleanValue(); private static boolean cookieEncoding = SystemProperties.getAsBoolean(Constants.AM_COOKIE_ENCODE); /** * @param config the ServletConfig object that contains configutation information for this * servlet. * @exception ServletException if an exception occurs that interrupts the servlet's normal * operation. */ public void init(ServletConfig config) throws ServletException { super.init(config); if (debug.messageEnabled()) { debug.message("CDCClientServlet.init:CDCClientServlet " + "Initializing..."); } try { tokenManager = SSOTokenManager.getInstance(); } catch (SSOException ssoe) { debug.error("CDCClientServlet.init:unable to get SSOTokenManager", ssoe); } authURLCookieName = SystemProperties.get(Constants.AUTH_UNIQUE_COOKIE_NAME, "sunIdentityServerAuthNServer"); authURLCookieDomain = SystemProperties.get(Constants.AUTH_UNIQUE_COOKIE_DOMAIN, ""); deployDescriptor = SystemProperties.get(Constants.AM_DISTAUTH_DEPLOYMENT_DESCRIPTOR, "/distauth"); } /** * Handles the HTTP GET request. * * @param request an HttpServletRequest object that contains the request the client has made of * the servlet. * @param response an HttpServletResponse object that contains the response the servlet sends to * the client. * @exception ServletException if an input or output error is detected when the servlet handles * the GET request * @exception IOException if the request for the GET could not be handled */ @Override public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } /** * Handles the HTTP POST request. * * @param request an HttpServletRequest object that contains the request the client has made of * the servlet. * @param response an HttpServletResponse object that contains the response the servlet sends to * the client. * @exception ServletException if an input or output error is detected when the servlet handles * the GET request * @exception IOException if the request for the GET could not be handled */ @Override public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGetPost(request, response); } /** * The method redirects the user to the authentication module if he is not authenticated; else * redirects him back to the original referrer. * * @param request an HttpServletRequest object that contains the request the client has made of * the servlet. * @param response an HttpServletResponse object that contains the response the servlet sends to * the client. * @exception ServletException if an input or output error is detected when the servlet handles * the GET request * @exception IOException if the request for the GET could not be handled */ private void doGetPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.doGetPost:Query String received= " + request.getQueryString()); } String gotoParameter = request.getParameter(GOTO_PARAMETER); String targetParameter = request.getParameter(TARGET_PARAMETER); if (targetParameter == null) { targetParameter = request.getParameter(TARGET_PARAMETER.toLowerCase()); } // if check if goto ot target have invalid strings, to avoid // accepting invalid injected javascript. if ((gotoParameter != null) || (targetParameter != null)) { if (debug.messageEnabled()) { debug.message( "CDCClientServlet:doGetPost():validating goto: " + gotoParameter + " and target: " + targetParameter); } for (String invalidStr : INVALID_SET) { if (gotoParameter != null && gotoParameter.toLowerCase().contains(invalidStr)) { showError(response, SERVER_ERROR_STR_MATCH + "GOTO parameter has invalid characters"); return; } if (targetParameter != null && targetParameter.toLowerCase().contains(invalidStr)) { showError(response, SERVER_ERROR_STR_MATCH + "TARGET parameter has invalid characters"); return; } } } /* Steps to be done * 1. If no SSOToken or policy advice present , forward to * authentication. * 2. If SSOToken is valid tunnel request to the backend AM's * CDCServlet and Form POST the received response to the agent. */ // Check for a valid SSOToken in the request. If SSOToken is not found // or if the token is invalid, redirect the user for authentication. // Also re-direct if there are policy advices in the query string SSOToken token = getSSOToken(request, response); // collect advices in parsedRequestParams[0] String and rest of params // other than original goto url in parsedRequestParams[1] String. String[] parsedRequestParams = parseRequestParams(request); if ((token == null) || (parsedRequestParams[0] != null)) { // Redirect to authentication redirectForAuthentication(request, response, parsedRequestParams[0], parsedRequestParams[1]); } else { // tunnel request to AM // send the request to the CDCServlet of AM where the session // was created. sendAuthnRequest(request, response, token); } } /** * This the main method of this servlet which takes in the request opens a URLConnection to the * CDCServlet endpoint in the OpenAM, and tunnels the request content to it. It parses the * Response received and if the HTTP_STATUS is "HTTP_OK" or "HTTP_MOVED_TEMP" POSTs the received * Liberty Authn Response to the goto URL specified in the original request. */ private void sendAuthnRequest( HttpServletRequest request, HttpServletResponse response, SSOToken token) throws ServletException, IOException { SessionID sessid = new SessionID(request); URL CDCServletURL = null; URL sessionServiceURL = null; try { sessionServiceURL = Session.getSessionServiceURL(sessid); } catch (SessionException se) { debug.error( "CDCClientServlet.sendAuthnRequest: Cannot locate" + " OpenAM instance to forward to.", se); showError(response, "Cannot locate OpenAM instance to forward to"); } if (sessionServiceURL == null) { showError(response, "Cannot locate OpenAM instance to forward to"); } // replace "sessionservice" by cdcservlet in obtained URL // we use naming so that we get the URL of the exact server // where the session is located and get the right deployment // descriptor. String sessionServiceURLString = sessionServiceURL.toString(); int serviceNameIndex = sessionServiceURLString.lastIndexOf( "/", sessionServiceURLString.length() - 2); // avoiding trailing "/" // if any StringBuilder buffer = new StringBuilder(150); buffer .append(sessionServiceURLString.substring(0, serviceNameIndex)) .append(CDCURI) .append(QUESTION_MARK) .append(request.getQueryString()); // add query string to // CDCServletURL CDCServletURL = new URL(buffer.toString()); // save the go to URL of the agent side to ultimately // POST to. try { HttpURLConnection connection = HttpURLConnectionManager.getConnection(CDCServletURL); connection.setRequestMethod("GET"); connection.setRequestProperty("Content-Type", "text/html;charset=UTF-8"); connection.setDoOutput(true); connection.setUseCaches(false); // replay cookies String strCookies = getCookiesFromRequest(request); if (strCookies != null) { if (debug.messageEnabled()) { debug.message("CDCClientServlet.sendAuthnRequest:Setting " + "cookies = " + strCookies); } connection.setRequestProperty("Cookie", strCookies); } // dont wish to follow redirect to agent, since // the response needs to go via the CDCClientServlet. HttpURLConnection.setFollowRedirects(false); // Receiving input from CDCServlet on the AM server instance if (debug.messageEnabled()) { debug.message( "CDCClientServlet.sendAuthnRequest:Getting " + "response back from " + CDCServletURL); debug.message( "CDCClientServlet.sendAuthnRequest:Response " + "Code " + connection.getResponseCode()); debug.message( "CDCClientServlet.sendAuthnRequest:Response " + "Message= " + connection.getResponseMessage()); } // Check response code if ((connection.getResponseCode() == HttpURLConnection.HTTP_OK) || (connection.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP)) { /** * Read the response back from CDCServlet, got a redirect since this response contains the * "LARES" ( Liberty authn response, which needs to be posted back to the dest url (agent). */ StringBuilder inBuf = new StringBuilder(); BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8")); int len; char[] buf = new char[1024]; while ((len = in.read(buf, 0, buf.length)) != -1) { inBuf.append(buf, 0, len); } String inString = inBuf.toString(); if (debug.messageEnabled()) { debug.message( "CDCClientServlet.sendAuthnRequest:" + "Received response data = " + inString); } // put the received Liberty Auth Response // in the servlet's response. sendAuthnResponse(request, response, inString); } else { debug.error("CDCClientServlet.sendAuthnRequest: Response " + "code NOT OK/MOVED_TEMP "); showError( response, "ERROR: Received HTTP error code " + connection.getResponseCode() + " from " + CDCServletURL); } } catch (ConnectException ce) { // Debug the exception if (debug.warningEnabled()) { debug.warning( "CDCClientServlet.sendAuthnRequest: " + "Connection Exception to " + CDCServletURL, ce); } showError( response, "Could not connect to CDCServlet at " + CDCServletURL + ":" + ce.getMessage()); } } // Get cookies string from HTTP request object private String getCookiesFromRequest(HttpServletRequest request) { Cookie cookies[] = CookieUtils.getCookieArrayFromReq(request); // above call would return pure sid in iPlanetDirectoryPro cookie // independent of container encoding StringBuilder cookieStr = null; String strCookies = null; if (cookies != null) { for (int nCookie = 0; nCookie < cookies.length; nCookie++) { String cookieName = cookies[nCookie].getName(); String cookieVal = cookies[nCookie].getValue(); if (cookieName.equals(CookieUtils.getAmCookieName()) && cookieEncoding) { cookieVal = URLEncDec.encode(cookieVal); } if (debug.messageEnabled()) { debug.message("CDCClientServlet.getCookiesFromRequest:" + "Cookie name = " + cookieName); debug.message("CDCClientServlet.getCookiesFromRequest:" + "Cookie val= " + cookieVal); } if (cookieStr == null) { cookieStr = new StringBuilder(); } else { cookieStr.append(SEMI_COLON).append(SPACE); } cookieStr.append(cookieName).append(EQUAL_TO).append(cookieVal); } } if (cookieStr != null) { strCookies = cookieStr.toString(); } return strCookies; } /** * Gathers the parameters in the request as a HTTP URL string. to form request parameters and * policy advice String array. It collects all the parameters from the original request except the * original goto url and any advice parameters. Note: All the paramters will be url decoded by * default., we should make sure that these values are encoded again * * @param request an HttpServletRequest object that contains the request the client has made of * the servlet. * @return An String array, index 0 is policy advice, index 1 is rest of the request parameters */ private String[] parseRequestParams(HttpServletRequest request) { StringBuilder adviceList = null; StringBuilder parameterString = new StringBuilder(100); for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) { String paramName = (String) e.nextElement(); if (adviceParams.contains(paramName.toLowerCase())) { if (adviceList == null) { adviceList = new StringBuilder(); } else { adviceList.append(AMPERSAND); } String[] values = request.getParameterValues(paramName); for (int i = 0; values != null && i < values.length; i++) { adviceList.append(paramName).append(EQUAL_TO).append(values[i]); } } else { if (!paramName.equals(GOTO_PARAMETER)) { String[] values = request.getParameterValues(paramName); for (int i = 0; values != null && i < values.length; i++) { parameterString .append(AMPERSAND) .append(paramName) .append(EQUAL_TO) .append(URLEncDec.encode(values[i])); } } } } if (debug.messageEnabled()) { debug.message("CDCClientServlet.parseRequestParams:" + "Advice List is = " + adviceList); debug.message( "CDCClientServlet.parseRequestParams:" + "Parameter String is = " + parameterString.toString()); } String policyAdviceList; String requestParams; if (adviceList == null) { policyAdviceList = null; } else { policyAdviceList = adviceList.toString(); } if (parameterString.length() > 0) { requestParams = (parameterString.deleteCharAt(0).toString()); } else { requestParams = parameterString.toString(); } return new String[] {policyAdviceList, requestParams}; } /** * Redirects the HTTP request to the Authentication module. It gets the authentication url from * <code>SystemProperties</code>. * * @param request an HttpServletRequest object that contains the request the client has made of * the servlet. * @param response an HttpServletResponse object that contains the response the servlet sends to * the client. * @exception IOException If an input or output exception occurs */ private void redirectForAuthentication( HttpServletRequest request, HttpServletResponse response, String policyAdviceList, String requestParams) throws IOException { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication: " + "requestURL=" + request.getRequestURL()); } StringBuilder redirectURL = new StringBuilder(100); StringBuilder gotoURL = new StringBuilder(100); // Check if user has authenticated to another OpenAM // instance String authURL = null; Cookie authCookie = CookieUtils.getCookieFromReq(request, authURLCookieName); if (authCookie != null) { authURL = CookieUtils.getCookieValue(authCookie); if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication: " + "got an authenticated URL= " + authURL); } } try { if (authURL == null || authURL.length() == 0 || !authURL.toLowerCase().startsWith("http") || policyAdviceList != null) { String finalURL = request.getParameter(GOTO_PARAMETER); if (finalURL == null || finalURL.equals("")) { finalURL = request.getParameter(TARGET_PARAMETER); } if (finalURL == null || finalURL.equals("")) { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication: " + "goto or target parameter is missing in the request."); } showError(response, SERVER_ERROR_STR_MATCH); return; } gotoURL .append(deployDescriptor) .append(CDCURI) .append(QUESTION_MARK) .append(TARGET_PARAMETER) .append(EQUAL_TO) .append(URLEncDec.encode(finalURL)) .append(AMPERSAND) .append(requestParams); // Construct the login URL String loginURI = request.getParameter(LOGIN_URI); String cdcUri; if (loginURI != null && !loginURI.isEmpty() && isValidCDCURI(loginURI)) { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication:found " + LOGIN_URI + "=" + loginURI); } cdcUri = loginURI; } else { cdcUri = cdcAuthURI; } if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication: Login URI is set to = " + cdcUri); } if (cdcUri.indexOf(QUESTION_MARK) == -1) { redirectURL.append(cdcUri).append(QUESTION_MARK); } else { redirectURL.append(cdcUri).append(AMPERSAND); } if (policyAdviceList != null) { redirectURL.append(policyAdviceList).append(AMPERSAND); } redirectURL .append(GOTO_PARAMETER) .append(EQUAL_TO) .append(URLEncDec.encode(gotoURL.toString())); if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication" + ":redirectURL before dispatching is=" + redirectURL); } RequestDispatcher dispatcher = request.getRequestDispatcher(redirectURL.toString()); dispatcher.forward(request, response); } else { // Redirect the user to the authenticated URL redirectURL .append(authURL) .append(deployDescriptor) .append(CDCURI) .append(QUESTION_MARK) .append(request.getQueryString()); // Reset the cookie value to null, to avoid continuous loop // when a load balancer is used if (authCookie != null) { authCookie.setValue(""); response.addCookie(authCookie); } response.sendRedirect(redirectURL.toString()); } if (debug.messageEnabled()) { debug.message( "CDCClientServlet.redirectForAuthentication:" + "Forwarding for authentication to= " + redirectURL); } } catch (IOException ex) { debug.error( "CDCClientServlet.redirectForAuthentication: Failed " + "in forwarding to Authentication service. IOException", ex); showError(response, "Could for forward to authentication service:" + ex.getMessage()); } catch (ServletException se) { debug.error( "CDCClientServlet.redirectForAuthentication : Failed " + "in forwarding to Authentication service. ServletException", se); showError(response, "Could for forward to authentication service:" + se.getMessage()); } catch (IllegalStateException ie) { debug.error( "CDCClientServlet.redirectForAuthentication : Failed " + "in forwarding to Authentication service. Illegal state", ie); showError(response, "Could for forward to authentication service:" + ie.getMessage()); } } /** * Shows Application Error message to the user. * * @param response an HttpServletResponse object that contains the response the servlet sends to * the client. * @param msg Message to be displayed. */ private void showError(HttpServletResponse response, String msg) throws IOException { ServletOutputStream out = null; if (msg == null || msg.equals("") || msg.contains(SERVER_ERROR_STR_MATCH)) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } try { out = response.getOutputStream(); out.println(msg); out.flush(); } catch (IOException e) { debug.error("CDCClientServlet.showError::Could not show error " + "message to the user " + e); } finally { try { out.close(); } catch (IOException ignore) { } } } /** * Returns the SSOToken of the user. If user has not authenticated re-directs the user to login * page */ private SSOToken getSSOToken(HttpServletRequest request, HttpServletResponse response) throws IOException { SSOToken token = null; try { /* SSOTokenManager.createSSOToken() throws an SSOException if the * token is not valid, so for a invalid token manager.isValidToken() * will never get executed for an invalid token. */ if (((token = tokenManager.createSSOToken(request)) == null) || !tokenManager.isValidToken(token)) { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.getSSOToken:SSOToken is " + "either null or not valid: " + token + "\nRedirecting for authentication"); } token = null; } } catch (com.iplanet.sso.SSOException e) { if (debug.messageEnabled()) { debug.message("CDCClientServlet.getSSOToken:SSOException " + "caught= " + e); } token = null; } return (token); } private void sendAuthnResponse( HttpServletRequest request, HttpServletResponse response, String authnResponse) { if (debug.messageEnabled()) { debug.message("CDCClientServlet.sendAuthnResponse: Called"); } try { if (debug.messageEnabled()) { debug.message("CDCClientServlet.sendAuthnResponse: " + "AuthnResponse= " + authnResponse); } response.setContentType("text/html"); response.setHeader("Pragma", "no-cache"); response.setHeader(RESPONSE_HEADER_ALERT, RESPONSE_HEADER_ALERT_VALUE); if (authnResponse.contains(FORBIDDEN_STR_MATCH)) { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.sendAuthnResponse: " + "AuthnResponse showing 403 error page"); } response.sendError(HttpServletResponse.SC_FORBIDDEN); return; } if (authnResponse.contains(SERVER_ERROR_STR_MATCH)) { if (debug.messageEnabled()) { debug.error( "CDCClientServlet.sendAuthnResponse: " + "ERROR: An application error has occured."); } response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } PrintWriter out = response.getWriter(); out.println(authnResponse); out.close(); if (debug.messageEnabled()) { debug.message("CDCClientServlet.sendAuthnResponse: " + "AuthnResponse sent successfully"); } return; } catch (IOException ioe) { debug.error("CDCClientServlet.sendAuthnResponse:" + ioe.getMessage()); } } /** * Return <code>true</code> if the passed URI is valid compared to the valid set loaded during * initialization. * * @param cdcUri The URI to test. * @return <code>true</code> if the URI is considered valid, <code>false</code> otherwise. */ private boolean isValidCDCURI(String cdcUri) { int questionMark = cdcUri.indexOf(QUESTION_MARK); // We are only interested in the URI part up to any parameters that may be included. if (questionMark != -1) { cdcUri = cdcUri.substring(0, questionMark); } // If there is not an exact match for the passed value then it cannot be considered valid boolean result = VALID_LOGIN_URIS.contains(cdcUri); if (debug.messageEnabled()) { debug.message( "CDCClientServlet.isValidCDCURI: checking if " + cdcUri + " is in validLoginURISet: " + VALID_LOGIN_URIS + " result:" + result); } return result; } private static void initConfig() { adviceParams.add("module"); adviceParams.add("authlevel"); adviceParams.add("role"); adviceParams.add("service"); adviceParams.add("user"); adviceParams.add("realm"); adviceParams.add("org"); adviceParams.add("resource"); adviceParams.add("sunamcompositeadvice"); String invalidStrings = SystemPropertiesManager.get(Constants.INVALID_GOTO_STRINGS); if (INVALID_SET.isEmpty()) { debug.message("CDCClientServlet.initConfig: creating invalidSet"); if (invalidStrings == null) { debug.message("CDCClientServlet.initConfig: invalidStrings is null"); INVALID_SET.add(LEFT_ANGLE); INVALID_SET.add(RIGHT_ANGLE); INVALID_SET.add(URLENC_LEFT_ANGLE); INVALID_SET.add(URLENC_RIGHT_ANGLE); INVALID_SET.add(JAVASCRIPT); INVALID_SET.add(URLENC_JAVASCRIPT); } else { if (debug.messageEnabled()) { debug.message("CDCClientServlet.initConfig: invalidStrings is: " + invalidStrings); } StringTokenizer st = new StringTokenizer(invalidStrings, DELIM); while (st.hasMoreTokens()) { INVALID_SET.add(st.nextToken()); } } debug.message("CDCClientServlet.initConfig: created invalidSet " + INVALID_SET); } String urlFromProps = SystemProperties.get(Constants.CDCSERVLET_LOGIN_URL); cdcAuthURI = (urlFromProps != null) ? urlFromProps : AUTHURI; String validLoginURIStrings = SystemPropertiesManager.get(Constants.VALID_LOGIN_URIS); debug.message("CDCClientServlet.initConfig: creating validLoginURISet"); if (validLoginURIStrings == null) { debug.message( "CDCClientServlet.initConfig: validLoginURIStrings is null, creating default set"); VALID_LOGIN_URIS.add(cdcAuthURI); } else { if (debug.messageEnabled()) { debug.message( "CDCClientServlet.initConfig: validLoginURIStrings is: " + validLoginURIStrings); } StringTokenizer st = new StringTokenizer(validLoginURIStrings, DELIM); while (st.hasMoreTokens()) { VALID_LOGIN_URIS.add(st.nextToken()); } } debug.message("CDCClientServlet.initConfig: created validLoginURISet " + VALID_LOGIN_URIS); } }
/** * A <code>ClusterStateService </code> class implements monitoring the state of server instances * that are participating in the cluster environment. It is used in making routing decisions in * "internal request routing" mode */ public class ClusterStateService extends GeneralTaskRunnable { // Inner Class definition of ServerInfo Object. // Contains information about each Server. private class ServerInfo implements Comparable { String id; String protocol; URL url; InetSocketAddress address; boolean isUp; boolean isLocal; public int compareTo(Object o) { return id.compareTo(((ServerInfo) o).id); } /** * toString Override. * * @return String representation of this Inner Object Class. */ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("ServerInfo ID:[").append(this.id).append("], "); sb.append("Protocol:[").append(this.protocol).append("], "); sb.append("URL:[").append(((this.url == null) ? "null" : this.url.toString())); sb.append("], "); sb.append("Address:["); if (this.address == null) { sb.append("null], "); } else { sb.append(this.address.toString()).append("], Unresolved:["); sb.append(this.address.isUnresolved()).append("], "); } sb.append("Local:[").append(this.isLocal).append("], "); sb.append("Up:[").append(this.isUp).append("].\n"); return sb.toString(); } } // . End of Inner Class Definition. /** Service Globals */ public static Debug sessionDebug = null; /** Servers in the cluster environment */ private static Map<String, ServerInfo> servers = new HashMap<String, ServerInfo>(); /** Servers are down in the cluster environment */ private static Set<String> downServers = new HashSet<String>(); /** Server Information */ private static ServerInfo[] serverSelectionList = new ServerInfo[0]; /** Last selected Server */ private static int lastSelected = -1; /** individual server wait default time out 10 milliseconds */ public static final int DEFAULT_TIMEOUT = 1000; private static String GET_REQUEST = ""; private static final String EMPTY_STRING = ""; private static final String SUCCESS_200 = "200"; private static final String HTTP = "http"; private static String hcPath = SystemProperties.get(Constants.URLCHECKER_TARGET_URL, null); private static boolean doRequest = true; private static final String doRequestFlag = SystemProperties.get(Constants.URLCHECKER_DOREQUEST, "false"); private int timeout = DEFAULT_TIMEOUT; // in milliseconds /** default ServerInfo check time 10 milliseconds */ public static final long DEFAULT_PERIOD = 1000; private static long period = DEFAULT_PERIOD; // in milliseconds // server instance id private static String localServerId = null; // SessionService private static volatile SessionService sessionService = null; // Static Initialization Stanza. static { sessionDebug = Debug.getInstance("amSession"); if (doRequestFlag != null) { if (doRequestFlag.equals("false")) doRequest = false; } if (hcPath == null) { String deployuri = SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR, "/openam"); hcPath = deployuri + "/namingservice"; if (!hcPath.startsWith("/")) { hcPath += "/" + hcPath; } GET_REQUEST = "GET " + hcPath + " HTTP/1.0"; } } // End of Static Initialization Stanza /** * Get Servers within Cluster * * @return Map<String, ServerInfo> */ protected Map<String, ServerInfo> getServers() { return servers; } /** * Get Server IDs which are in a Down State. * * @return Set<String> */ protected Set<String> getDownServers() { return downServers; } /** * Get the Server Selection List, common to all Servers in Cluster. * * @return ServerInfo[] Array of Servers in Selection list in proper order. */ protected ServerInfo[] getServerSelectionList() { return serverSelectionList; } /** * Get our Local Server Id * * @return String of Local Server Id. */ protected String getLocalServerId() { return localServerId; } /** * Is Specified ServerId our Local Server Id? * * @param serverId * @return boolean indicating true if specified server id is our local Server Id or false ir not. */ protected boolean isLocalServerId(String serverId) { return ((serverId == null) || (!serverId.equalsIgnoreCase(this.localServerId))) ? false : true; } /** * Constructs an instance for the cluster service * * @param localServerId id of the server instance in which this ClusterStateService instance is * running * @param timeout timeout for waiting on an individual server (millisec) * @param period checking cycle period (millisecs) * @param members map if server id - > url for all cluster members * @throws Exception */ protected ClusterStateService( SessionService sessionService, String localServerId, int timeout, long period, Map<String, String> members) throws Exception { if ((localServerId == null) || (localServerId.isEmpty())) { String message = "ClusterStateService: Local Server Id argument is null, unable to instantiate Cluster State Service!"; sessionDebug.error(message); throw new IllegalArgumentException(message); } // Ensure we Synchronize this Instantiation. synchronized (this) { this.sessionService = sessionService; this.localServerId = localServerId; this.timeout = timeout; this.period = period; serverSelectionList = new ServerInfo[members.size()]; for (Map.Entry<String, String> entry : members.entrySet()) { ServerInfo info = new ServerInfo(); info.id = entry.getKey(); URL url = new URL(entry.getValue() + "/namingservice"); info.url = url; info.protocol = url.getProtocol(); info.address = new InetSocketAddress(url.getHost(), url.getPort()); // Fix for Deadlock. If this is our server, set to true, else false. info.isUp = isLocalServerId(info.id); info.isLocal = info.isUp; // Set our Local Server Indicator, per above interrogation. // Check for Down Servers. if (!info.isUp) { downServers.add(info.id); } // Add Server to Server List. servers.put(info.id, info); // Associate to a Server Selection Bucket. serverSelectionList[getNextSelected()] = info; if (sessionDebug.messageEnabled()) { sessionDebug.error("Added Server to ClusterStateService: " + info.toString()); } } // End of For Loop. // to ensure that ordering in different server instances is identical Arrays.sort(serverSelectionList); SystemTimer.getTimer().schedule(this, new Date((System.currentTimeMillis() / 1000) * 1000)); } // End of Synchronized Block. } /** * Implements "wrap-around" lastSelected index advancement * * @return updated lastSelected index value */ private int getNextSelected() { return lastSelected = (lastSelected + 1) % serverSelectionList.length; } /** * Returns currently known status of the server instance identified by serverId * * @param serverId server instance id * @return true if server is up, false otherwise */ boolean isUp(String serverId) { if ((serverId == null) || (serverId.isEmpty())) { return false; } if (serverId.equalsIgnoreCase(this.localServerId)) { return true; } if ((servers == null) || servers.isEmpty()) { return false; } return (servers.get(serverId) != null) ? servers.get(serverId).isUp : false; } /** * Actively checks and updates the status of the server instance identified by serverId * * @param serverId server instance id * @return true if server is up, false otherwise */ boolean checkServerUp(String serverId) { if ((serverId == null) || (serverId.isEmpty())) { return false; } if (serverId.equalsIgnoreCase(this.localServerId)) { return true; } if ((servers == null) || servers.isEmpty()) { return false; } ServerInfo info = servers.get(serverId); info.isUp = checkServerUp(info); return info.isUp; } /** * Returns size of the server list * * @return size of the server list */ int getServerSelectionListSize() { return (serverSelectionList == null) ? 0 : serverSelectionList.length; } /** * Returns server id for a given index inside the server list or null if out of bounds. * * @param index index in the server list, relative to Zero. * @return server id */ String getServerSelection(int index) { if ((getServerSelectionListSize() <= 0) || (index < 0) || (index >= getServerSelectionListSize())) { return null; } return serverSelectionList[index].id; } /** * Implements for GeneralTaskRunnable * * @return The run period of the task. */ public long getRunPeriod() { return period; } /** * Implements for GeneralTaskRunnable. * * @return false since this class will not be used as container. */ public boolean addElement(Object obj) { return false; } /** * Implements for GeneralTaskRunnable. * * @return false since this class will not be used as container. */ public boolean removeElement(Object obj) { return false; } /** * Implements for GeneralTaskRunnable. * * @return true since this class will not be used as container. */ public boolean isEmpty() { return true; } /** Monitoring logic used by background thread */ public void run() { try { boolean cleanRemoteSessions = false; synchronized (servers) { for (Map.Entry<String, ServerInfo> server : servers.entrySet()) { ServerInfo info = server.getValue(); info.isUp = checkServerUp(info); if (!info.isUp) { downServers.add(info.id); } else { if (!downServers.isEmpty() && downServers.remove(info.id)) { cleanRemoteSessions = true; } } } } if (cleanRemoteSessions) { sessionService.cleanUpRemoteSessions(); } } catch (Exception ex) { sessionDebug.error( "cleanRemoteSessions Background thread has encountered an Exception: " + ex.getMessage(), ex); } } /** * Internal method for checking health status using sock.connect() * * <p>TODO -- Use a better mechanism for alive status. 10.1+. * * @param info server info instance * @return true if server is up, false otherwise */ private boolean checkServerUp(ServerInfo info) { if (info == null) { return false; } if (localServerId.equals(info.id)) { return true; } boolean result = false; Socket sock = new Socket(); PrintWriter out = null; BufferedReader in = null; try { sock.connect(info.address, timeout); /* * If we need to check for a front end proxy, we need * to send a request. */ if (doRequest) { if (info.protocol.equals(HTTP)) { out = new PrintWriter(sock.getOutputStream()); in = new BufferedReader(new InputStreamReader(sock.getInputStream())); out.println(GET_REQUEST); out.println(EMPTY_STRING); out.flush(); String response = in.readLine(); if (response.contains(SUCCESS_200)) { result = true; } else { result = false; } } else { HttpsURLConnection connection = null; int responseCode = 0; InputStream is = null; try { connection = (HttpsURLConnection) info.url.openConnection(); connection.setHostnameVerifier( new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); responseCode = connection.getResponseCode(); is = connection.getInputStream(); int ret = 0; byte[] buf = new byte[512]; // clear the stream while ((ret = is.read(buf)) > 0) { // do nothing } // close the inputstream is.close(); } catch (IOException ioe) { InputStream es = null; try { es = ((HttpsURLConnection) connection).getErrorStream(); int ret = 0; byte[] buf = new byte[512]; // read the response body to clear while ((ret = es.read(buf)) > 0) { // do nothing } // close the errorstream es.close(); } catch (IOException ex) { // deal with the exception } } if (responseCode == HttpURLConnection.HTTP_OK) { result = true; } else { result = false; } } } else { result = true; } } catch (Exception ex) { result = false; } finally { try { sock.close(); } catch (Exception ex) { } } return result; } // TODO -- Develop Method to write our Server State to the Session Persistence Store. /** * Override toString * * @return */ @Override public String toString() { final StringBuffer sb = new StringBuffer(); sb.append("ClusterStateService: "); sb.append("{ lastSelected=").append(lastSelected); sb.append(", timeout=").append(timeout).append("\n"); sb.append(" Current Server Selection List:").append("\n"); for (ServerInfo serverInfo : getServerSelectionList()) { sb.append(serverInfo.toString()); } sb.append('}'); return sb.toString(); } }