/**
   * Determines the return location and redirects based on federation termination Return URL of the
   * provider that sent the termination request.
   */
  private void returnToSource() {
    FSUtils.debug.message("Entered FSFedTerminationHandler::returnToSource");
    try {
      StringBuffer finalReturnURL = new StringBuffer();
      String retURL = remoteDescriptor.getFederationTerminationServiceReturnURL();
      if (FSUtils.debug.messageEnabled()) {
        FSUtils.debug.message("Redirecting to : " + retURL);
      }
      resetFederateCookie();
      FSUtils.debug.message("Checking retURL for null value");
      if (retURL == null || retURL.length() < 1) {
        FSUtils.debug.error("Return URL is null");

        FSServiceUtils.showErrorPage(
            response,
            error_page_url,
            IFSConstants.TERMINATION_INVALID_REDIRECT_URL,
            IFSConstants.METADATA_ERROR);
        return;
      } else {
        finalReturnURL.append(retURL);
        if (!(relayState == null || relayState.length() < 1)) {
          char delimiter;
          if (retURL.indexOf(IFSConstants.QUESTION_MARK) < 0) {
            delimiter = IFSConstants.QUESTION_MARK;
          } else {
            delimiter = IFSConstants.AMPERSAND;
          }
          finalReturnURL
              .append(delimiter)
              .append(RELAY_STATE)
              .append(IFSConstants.EQUAL_TO)
              .append(URLEncDec.encode(relayState));
        }
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message("Now sendRedirecting to : " + finalReturnURL.toString());
        }
        response.sendRedirect(finalReturnURL.toString());
        return;
      }
    } catch (IOException e) {
      FSUtils.debug.error(
          "Unable to get LRURL. No location to redirect." + " processing completed", e);
    }
    // create new bundle entry for redirect failure
    FSUtils.debug.message("After exception calling response.sendError");
    FSServiceUtils.showErrorPage(
        response,
        error_page_url,
        IFSConstants.TERMINATION_INVALID_REDIRECT_URL,
        IFSConstants.METADATA_ERROR);
    return;
  }
Example #2
0
  /*
   * Method to construct the URLEndpoint depending on whether basic
   * authentication of one provider to another is to be done. Otherwise the
   * SOAPEndpoint of the remote provider is returned
   * @param response the response object
   * @param partnerDecriptor the remote provider descriptor
   * @param needAuthn determines forced authn
   * @return Element corresponding to liberty request/response
   */
  public String createSOAPReceiverUrl(
      HttpServletResponse response, ProviderDescriptorType partnerDecriptor, boolean needAuthn)
      throws IOException {
    // TODO: need to handle needAuthn correctly
    // TODO: need to retrieve auth type, user name and password from meta
    // basic authentication
    String username = null;
    String password = null;
    String to = partnerDecriptor.getSoapEndpoint();
    String authtype = null;
    String soapURL = null;
    if (needAuthn) {
      int idnx = -1;
      if ((idnx = to.indexOf("//")) == -1) {
        FSUtils.debug.error(
            "FSSOAPService.createSOAPReceiverUrl: "
                + "createSOAPReceiverUrl: SOAP-Receiver-URL illegal format.");
        response.sendError(
            response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString("illegalFormatSOAPUrl"));
        return null;
      }
      String protocol = to.substring(0, idnx - 1);
      if (authtype.equalsIgnoreCase(IFSConstants.BASICAUTH)
          || authtype.equalsIgnoreCase(IFSConstants.NOAUTH)) {
        if (!protocol.equals(IFSConstants.HTTP)) {
          String[] data = {protocol, authtype};
          LogUtil.error(Level.INFO, LogUtil.MISMATCH_AUTH_TYPE_AND_PROTOCOL, data);
          response.sendError(
              response.SC_INTERNAL_SERVER_ERROR,
              FSUtils.bundle.getString("mismatchAuthTypeandProtocol"));
          return null;
        }
      } else if (authtype.equalsIgnoreCase(IFSConstants.SSLWITHBASICAUTH)
          || authtype.equalsIgnoreCase(IFSConstants.SSL)) {
        if (!protocol.equals(IFSConstants.HTTPS)) {
          String[] data = {protocol, authtype};
          LogUtil.error(Level.INFO, LogUtil.MISMATCH_AUTH_TYPE_AND_PROTOCOL, data);
          response.sendError(
              response.SC_INTERNAL_SERVER_ERROR,
              FSUtils.bundle.getString("mismatchAuthTypeandProtocol"));
          return null;
        }
      } else {
        String[] data = {authtype};
        LogUtil.error(Level.INFO, LogUtil.WRONG_AUTH_TYPE, data);
        response.sendError(
            response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString("wrongAuthType"));
        return null;
      }

      if (authtype.equalsIgnoreCase(IFSConstants.BASICAUTH)
          || authtype.equalsIgnoreCase(IFSConstants.SSLWITHBASICAUTH)) {
        Map userMap = null; // partnerDecriptor.getAuthType();
        username = (String) userMap.get(IFSConstants.USER);
        password = (String) userMap.get(IFSConstants.PASSWORD);
        if (username == null || password == null) {
          FSUtils.debug.error(
              "FSSOAPService.createSOAPReceiverUrl: "
                  + "PartnerSite required basic authentication. But "
                  + "the user name used for authentication is null.");
          response.sendError(
              response.SC_INTERNAL_SERVER_ERROR, FSUtils.bundle.getString("wrongConfigBasicAuth"));
          return null;
        }
        StringBuffer toSOAP = new StringBuffer(100);
        toSOAP
            .append(to.substring(0, idnx + 2))
            .append(username)
            .append(":")
            .append(password)
            .append("@")
            .append(to.substring(idnx + 2));
        soapURL = toSOAP.toString();
      }
      return null;
    } else {
      soapURL = to;
    }
    if (FSUtils.debug.messageEnabled()) {
      FSUtils.debug.message(
          "FSSOAPService.createSOAPReceiverUrl: Sending message to URL: " + soapURL);
    }
    String[] data = {soapURL};
    LogUtil.access(Level.FINER, "SOAP_RECEIVER_URL", data);
    return soapURL;
  }
  /**
   * Initiates federation termination at remote end. The termination requested is constructed and
   * based on the profile the request is sent over SOAP or as HTTP redirect. Profile is always based
   * on the SPs profile
   *
   * @param acctInfo represents the user account federation information
   * @return <code>true</code> if termination request is sent to remote provider successfully;
   *     <code>false</code> otherwise.
   */
  private boolean doFederationTermination(
      HttpServletRequest request, HttpServletResponse response, FSAccountFedInfo acctInfo) {
    FSUtils.debug.message("Entered FSFedTerminationHandler::doFederationTermination");
    try {
      if (FSUtils.debug.messageEnabled()) {
        FSUtils.debug.message(
            "FSFedTerminationHandler::doFederationTermination create" + " request start");
      }
      FSFederationTerminationNotification reqFedTermination =
          createFederationTerminationRequest(acctInfo);
      reqFedTermination.setMinorVersion(
          FSServiceUtils.getMinorVersion(remoteDescriptor.getProtocolSupportEnumeration()));
      if (reqFedTermination == null) {
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSIDPFedTerminationHandler::Termination request could " + "not be formed");
        }
        // Always show success page since local termination succeeded
        FSServiceUtils.returnLocallyAfterOperation(
            response,
            termination_done_url,
            true,
            IFSConstants.TERMINATION_SUCCESS,
            IFSConstants.TERMINATION_FAILURE);
        return false;
      }
      if (FSUtils.debug.messageEnabled()) {
        FSUtils.debug.message(
            "FSIDPFedTerminationHandler::Termination request formed" + "successfully");
      }
      // Find out which profile to use
      boolean isSOAPProfile = true;
      if (acctInfo.isRoleIDP()) {
        List hostProfiles = hostedDescriptor.getFederationTerminationNotificationProtocolProfile();
        if (hostProfiles == null || hostProfiles.isEmpty()) {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination no termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }
        String profile = (String) hostProfiles.iterator().next();
        if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_SOAP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_SOAP_PROFILE)) {
          isSOAPProfile = true;
        } else if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_HTTP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_HTTP_PROFILE)) {
          isSOAPProfile = false;
        } else {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination Invalid termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }
      } else {
        List remoteProfiles =
            remoteDescriptor.getFederationTerminationNotificationProtocolProfile();
        if (remoteProfiles == null || remoteProfiles.isEmpty()) {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination no termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }

        String profile = (String) remoteProfiles.iterator().next();
        if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_SOAP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_SOAP_PROFILE)) {
          isSOAPProfile = true;
        } else if (profile.equalsIgnoreCase(IFSConstants.TERMINATION_SP_HTTP_PROFILE)
            || profile.equalsIgnoreCase(IFSConstants.TERMINATION_IDP_HTTP_PROFILE)) {
          isSOAPProfile = false;
        } else {
          FSUtils.debug.error(
              "FSFedTerminationHandler::"
                  + "doFederationTermination Invalid termination profile"
                  + " cannot process request");
          FSServiceUtils.returnLocallyAfterOperation(
              response,
              termination_done_url,
              true,
              IFSConstants.TERMINATION_SUCCESS,
              IFSConstants.TERMINATION_FAILURE);
          return false;
        }
      }
      if (isSOAPProfile) {
        FSSOAPService instSOAP = FSSOAPService.getInstance();
        if (instSOAP != null) {
          FSUtils.debug.message("Signing suceeded. To call bindTerminationRequest");
          // String id = reqFedTermination.getRequestID();
          reqFedTermination.setID(IFSConstants.TERMINATIONID);
          SOAPMessage msgTermination = instSOAP.bind(reqFedTermination.toXMLString(true, true));
          if (msgTermination != null) {
            try {
              if (FSServiceUtils.isSigningOn()) {
                int minorVersion = reqFedTermination.getMinorVersion();
                if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
                  msgTermination =
                      signTerminationRequest(
                          msgTermination, IFSConstants.ID, reqFedTermination.getID());
                } else if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
                  msgTermination =
                      signTerminationRequest(
                          msgTermination,
                          IFSConstants.REQUEST_ID,
                          reqFedTermination.getRequestID());
                } else {
                  FSUtils.debug.message("invalid minor version.");
                }
              }
              boolean sendStatus =
                  instSOAP.sendTerminationMessage(
                      msgTermination, remoteDescriptor.getSoapEndpoint());
              // Call SP Adapter for SP initiated SOAP profile
              if (hostedProviderRole != null
                  && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) {
                FederationSPAdapter spAdapter =
                    FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig);
                if (spAdapter != null) {
                  try {
                    spAdapter.postTerminationNotificationSuccess(
                        hostedEntityId,
                        request,
                        response,
                        userID,
                        reqFedTermination,
                        IFSConstants.TERMINATION_SP_SOAP_PROFILE);
                  } catch (Exception e) {
                    // ignore adapter exception
                    FSUtils.debug.error("postTerm.SP/SOAP", e);
                  }
                }
              }

              // Always show success page since local termination
              // succeeded and that is what is important
              FSServiceUtils.returnLocallyAfterOperation(
                  response,
                  termination_done_url,
                  true,
                  IFSConstants.TERMINATION_SUCCESS,
                  IFSConstants.TERMINATION_FAILURE);
              return sendStatus;
            } catch (Exception e) {
              FSUtils.debug.error(
                  "FSFedTerminationHandler::"
                      + "doFederationTermination "
                      + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
              // Always show success page since local
              // termination succeeded
              FSServiceUtils.returnLocallyAfterOperation(
                  response,
                  termination_done_url,
                  true,
                  IFSConstants.TERMINATION_SUCCESS,
                  IFSConstants.TERMINATION_FAILURE);
              return false;
            }
          } else {
            if (FSUtils.debug.messageEnabled()) {
              FSUtils.debug.message(
                  "FSSPFedTerminationHandler::doFederation"
                      + "Termination failed. Error in forming Message");
            }
            FSUtils.debug.error(
                "FSSPFedTerminationHandler.doFederationTermination "
                    + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
            // Always show success page since local termination
            // succeeded
            FSServiceUtils.returnLocallyAfterOperation(
                response,
                termination_done_url,
                true,
                IFSConstants.TERMINATION_SUCCESS,
                IFSConstants.TERMINATION_FAILURE);
            return false;
          }
        }
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSFedTerminationHandler::doFederationTermination "
                  + "failed. Cannot get Service Manager instance");
        }
        FSUtils.debug.error(
            "FSSPFedTerminationHandler::doFederationTermination "
                + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
        // Always show success page since local termination succeeded
        FSServiceUtils.returnLocallyAfterOperation(
            response,
            termination_done_url,
            true,
            IFSConstants.TERMINATION_SUCCESS,
            IFSConstants.TERMINATION_FAILURE);
        return false;
      } else {
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSFedTerminationHandler::doFederationTermination " + "In Redirect profile");
        }
        String urlEncodedRequest = reqFedTermination.toURLEncodedQueryString();
        // Sign the request querystring
        if (FSServiceUtils.isSigningOn()) {
          String certAlias =
              IDFFMetaUtils.getFirstAttributeValueFromConfig(
                  hostedConfig, IFSConstants.SIGNING_CERT_ALIAS);
          if (certAlias == null || certAlias.length() == 0) {
            if (FSUtils.debug.messageEnabled()) {
              FSUtils.debug.message(
                  "FSBrowserArtifactConsumerHandler:: "
                      + "signSAMLRequest:"
                      + "couldn't obtain this site's cert alias.");
            }
            throw new SAMLResponderException(FSUtils.bundle.getString(IFSConstants.NO_CERT_ALIAS));
          }
          urlEncodedRequest =
              FSSignatureUtil.signAndReturnQueryString(urlEncodedRequest, certAlias);
        }
        StringBuffer redirectURL = new StringBuffer();
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message("Request to be sent : " + urlEncodedRequest);
        }
        String retURL = remoteDescriptor.getFederationTerminationServiceURL();
        redirectURL.append(retURL);
        if (retURL.indexOf(IFSConstants.QUESTION_MARK) == -1) {
          redirectURL.append(IFSConstants.QUESTION_MARK);
        } else {
          redirectURL.append(IFSConstants.AMPERSAND);
        }
        redirectURL.append(urlEncodedRequest);
        if (FSUtils.debug.messageEnabled()) {
          FSUtils.debug.message(
              "FSFedTerminationHandler::Redirect URL is " + redirectURL.toString());
        }
        // Call SP Adaper for SP initiated HTTP profile
        // ideally this should be called from the
        // FSTerminationReturnServlet, but info not available there
        if (hostedProviderRole != null && hostedProviderRole.equalsIgnoreCase(IFSConstants.SP)) {
          FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(hostedEntityId, hostedConfig);
          if (spAdapter != null) {
            try {
              spAdapter.postTerminationNotificationSuccess(
                  hostedEntityId,
                  request,
                  response,
                  userID,
                  reqFedTermination,
                  IFSConstants.TERMINATION_SP_HTTP_PROFILE);
            } catch (Exception e) {
              // ignore adapter exception
              FSUtils.debug.error("postTerm.SP/HTTP", e);
            }
          }
        }
        response.sendRedirect(redirectURL.toString());
        return true;
      }
    } catch (IOException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler"
              + FSUtils.bundle.getString(IFSConstants.FEDERATION_REDIRECT_FAILED));
    } catch (FSMsgException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler::doFederationTermination "
              + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
    } catch (SAMLResponderException e) {
      FSUtils.debug.error(
          "FSFedTerminationHandler::doFederationTermination "
              + FSUtils.bundle.getString(IFSConstants.TERMINATION_FAILED_SEND_REMOTE));
    }
    // Always show success page since local termination succeeded
    FSServiceUtils.returnLocallyAfterOperation(
        response,
        termination_done_url,
        true,
        IFSConstants.TERMINATION_SUCCESS,
        IFSConstants.TERMINATION_FAILURE);
    return false;
  }