Example #1
0
  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);
    }
  }
  /**
   * This method will be invoked when a service's global configuration data has been changed. The
   * parameter <code>groupName</code> denote the name of the configuration grouping (e.g. default)
   * and <code>serviceComponent</code> denotes the service's sub-component that changed (e.g. <code>
   * /NamedPolicy</code>, <code>/Templates</code>).
   *
   * @param serviceName Name of the service.
   * @param version Version of the service.
   * @param groupName Name of the configuration grouping.
   * @param serviceComponent Name of the service components that changed.
   * @param type change type, i.e., ADDED, REMOVED or MODIFIED.
   */
  public void globalConfigChanged(
      String serviceName, String version, String groupName, String serviceComponent, int type) {
    if (serviceName.equals(Constants.SVC_NAME_PLATFORM)) {
      if (serviceComponent.startsWith("/" + ConfigurationBase.CONFIG_SERVERS + "/")) {
        String serverName = serviceComponent.substring(PARENT_LEN);

        if (serverName.equals(ServerConfiguration.DEFAULT_SERVER_CONFIG)
            || serverName.equals(SystemProperties.getServerInstanceName())) {
          // always use the server instance name with initialising properties
          if (serverName.equals(ServerConfiguration.DEFAULT_SERVER_CONFIG)) {
            serverName = SystemProperties.getServerInstanceName();
          }

          SSOToken adminToken = AccessController.doPrivileged(AdminTokenAction.getInstance());
          try {
            Properties newProp = ServerConfiguration.getServerInstance(adminToken, serverName);
            SystemProperties.initializeProperties(newProp, true, true);
            notifies(Constants.SVC_NAME_PLATFORM);
          } catch (SSOException | IOException | SMSException ex) {
            // ignored
          }
        }
      } else {
        notifies(Constants.SVC_NAME_PLATFORM);
      }
    } else {
      /* need to do this else bcoz some of the property have been moved
       * to services
       */
      notifies(serviceName);
    }
  }
Example #3
0
  /**
   * 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();
    }
  }
Example #4
0
  /** 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();
  }
Example #5
0
  /**
   * 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;
  }
 private void createAttributeMapping() {
   // this does not apply client mode because client's property
   // never get store in SMS services
   if (SystemProperties.isServerMode()) {
     Map attributeMap = SystemProperties.getAttributeMap();
     for (Iterator i = attributeMap.values().iterator(); i.hasNext(); ) {
       AttributeStruct a = (AttributeStruct) i.next();
       migratedServiceNames.add(a.getServiceName());
     }
   }
 }
Example #7
0
 /**
  * @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");
 }
Example #8
0
  /**
   * Perform a remote setProperty on the Session using the remote Service URL.
   *
   * <p>{@inheritDoc}
   */
  public void setProperty(Session session, String name, String value) throws SessionException {
    if (debug.messageEnabled()) {
      debug.message(MessageFormat.format("Remote setProperty {0} {1}={2}", session, name, value));
    }

    SessionID sessionID = session.getID();
    SessionRequest sreq =
        new SessionRequest(SessionRequest.SetProperty, sessionID.toString(), false);
    sreq.setPropertyName(name);
    sreq.setPropertyValue(value);
    if (SystemProperties.isServerMode() && InternalSession.isProtectedProperty(name)) {
      try {
        SSOToken admSSOToken = SessionUtils.getAdminToken();
        sreq.setRequester(RestrictedTokenContext.marshal(admSSOToken));
      } catch (SSOException e) {
        throw new SessionException(e);
      } catch (Exception e) {
        throw new SessionException(e);
      }

      if (debug.messageEnabled()) {
        debug.message(
            "Session.setProperty: "
                + "added admSSOToken in sreq to set "
                + "externalProtectedProperty in remote server");
      }
    }
    requests.sendRequestWithRetry(session.getSessionServiceURL(), sreq, session);
  }
  private void generateSvrReport(String path) {
    if (loadConfig(path)) {
      ssoToken = getAdminSSOToken();
      if (ssoToken != null) {
        // All the properties should be loaded at this point
        Properties prop = SystemProperties.getAll();
        Properties amProp = new Properties();
        Properties sysProp = new Properties();

        for (Enumeration e = prop.propertyNames(); e.hasMoreElements(); ) {
          String key = (String) e.nextElement();
          String val = (String) prop.getProperty(key);
          if (key.startsWith(AM_PROP_SUN_SUFFIX)
              || key.startsWith(AM_PROP_SUFFIX)
              || key.startsWith(ENC_PWD_PROPERTY)) {
            amProp.put(key, val);
          } else {
            sysProp.put(key, val);
          }
        }
        printProperties(amProp, DEF_PROP);
        printProperties(sysProp, SYS_PROP);
        getInstanceProperties(ssoToken);
      } else {
        toolOutWriter.printError("rpt-auth-msg");
      }
    } else {
      toolOutWriter.printStatusMsg(false, "rpt-svr-gen");
    }
  }
Example #10
0
  /**
   * 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;
  }
Example #11
0
 /* 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;
 }
Example #12
0
 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);
     }
   }
 }
 @Override
 public StoreMode getStoreMode() {
   String mode = SystemProperties.get(STORE_LOCATION);
   if (StringUtils.isNotEmpty(mode)) {
     return StoreMode.valueOf(mode.toUpperCase());
   } else {
     return StoreMode.DEFAULT;
   }
 }
Example #14
0
 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;
 }
Example #15
0
  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);
  }
  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());
    }
  }
Example #17
0
 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
 @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));
 }
Example #20
0
  /** Create the global information report * @return */
  private JsonValue globalInformationReport(Record record) {

    JsonObject report = JsonValueBuilder.jsonValue();
    synchronized (dateFormat) {
      report.put(DATE_LABEL, dateFormat.format(new Date()));
    }
    report.put(OPENAM_VERSION_LABEL, SystemPropertiesManager.get(Constants.AM_VERSION));

    // OpenAM properties contain a part of the OpenAM configuration, we need to have the config
    // export enable
    if (record.getRecordProperties().isConfigExportEnabled()) {
      JsonObject openAMPropertiesJson = JsonValueBuilder.jsonValue();
      Properties sysProps = SystemProperties.getProperties();
      for (String propertyName : sysProps.stringPropertyNames()) {
        report.put(propertyName, sysProps.getProperty(propertyName));
      }
      report.put(OPENAM_PROPERTIES_LABEL, openAMPropertiesJson.build().asMap());
    }

    return report.build();
  }
  /**
   * Returns Session Service URL for a Session ID.
   *
   * @param sid Session ID
   * @return Session Service URL.
   * @exception SessionException
   */
  public URL getSessionServiceURL(SessionID sid) throws SessionException {
    String primaryId;

    if (SystemProperties.isServerMode()) {

      /**
       * Validate that the SessionID contains valid Server and Site references. This check is not
       * appropriate for client side code as only the Site reference is exposed to client code.
       */
      sid.validate();

      SessionService ss = InjectorHolder.getInstance(SessionService.class);
      if (ss.isSiteEnabled() && ss.isLocalSite(sid)) {
        if (ss.isSessionFailoverEnabled()) {
          return getSessionServiceURL(ss.getCurrentHostServer(sid));
        } else {
          primaryId = sid.getExtension().getPrimaryID();
          return getSessionServiceURL(primaryId);
        }
      }
    } else {
      primaryId = sid.getExtension().getPrimaryID();
      if (primaryId != null) {
        String secondarysites = WebtopNaming.getSecondarySites(primaryId);

        String serverID = SessionService.getAMServerID();
        if ((secondarysites != null) && (serverID != null)) {
          if (secondarysites.indexOf(serverID) != -1) {
            return getSessionServiceURL(serverID);
          }
        }
      }
    }

    return getSessionServiceURL(
        sid.getSessionServerProtocol(),
        sid.getSessionServer(),
        sid.getSessionServerPort(),
        sid.getSessionServerURI());
  }
 /**
  * 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);
   }
 }
Example #23
0
  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;
  }
Example #24
0
  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"));
 }
Example #26
0
 static {
   debug = com.sun.identity.shared.debug.Debug.getInstance("amXMLHandler");
   messageEnabled = debug.messageEnabled();
   serviceURI = SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR) + "/authservice";
 }
Example #27
0
/**
 * 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/&lt;cookieName>=&lt;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;&lt;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?&lt;cookieName>=&lt;cookieValue>
   * protocol://server:port/path?queryString&amp;
   *       &lt;cookieName>=&lt;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?&lt;cookieName>=&lt;cookieValue>
   * protocol://server:port/path?queryString&amp;
   *        &lt;cookieName>=&lt;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);
      }
    }
  }
}
Example #28
0
  /**
   * 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;
    }
  }
/**
 * 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();
  }
}
Example #30
0
/**
 * 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);
  }
}