// Copyright 2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.enterprise.adaptor.secmgr.servlets;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.enterprise.adaptor.secmgr.authncontroller.ExportedState;
import com.google.enterprise.adaptor.secmgr.common.SecurityManagerUtil;
import com.google.enterprise.adaptor.secmgr.modules.SamlClient;
import com.google.enterprise.adaptor.secmgr.saml.OpenSamlUtil;
import com.google.enterprise.adaptor.secmgr.saml.SamlLogUtil;

import org.joda.time.DateTime;
import org.joda.time.DateTimeComparator;
import org.joda.time.DateTimeUtils;
import org.opensaml.saml2.core.Assertion;
import org.opensaml.saml2.core.Attribute;
import org.opensaml.saml2.core.AttributeStatement;
import org.opensaml.saml2.core.Audience;
import org.opensaml.saml2.core.AudienceRestriction;
import org.opensaml.saml2.core.Conditions;
import org.opensaml.saml2.core.Issuer;
import org.opensaml.saml2.core.NameIDType;
import org.opensaml.saml2.core.Response;
import org.opensaml.saml2.core.Subject;
import org.opensaml.saml2.core.SubjectConfirmation;
import org.opensaml.saml2.core.SubjectConfirmationData;
import org.opensaml.xml.XMLObject;

import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.concurrent.Immutable;

/**
 * A parser to disassemble and validate a SAML Response element.
 */
@Immutable
public final class ResponseParser {
  private static final Logger LOGGER = Logger.getLogger(ResponseParser.class.getName());
  private static final DateTimeComparator dtComparator = DateTimeComparator.getInstance();

  private final SamlClient client;
  private final String recipient;
  private final Response response;
  private final String sessionId;
  private final long now;
  private final Assertion assertion;

  private ResponseParser(SamlClient client, String recipient, Response response, String sessionId) {
    this.client = client;
    this.recipient = recipient;
    this.response = response;
    this.sessionId = sessionId;
    this.now = DateTimeUtils.currentTimeMillis();
    this.assertion = findSuitableAssertion();
  }

  public static ResponseParser make(SamlClient client, String recipient, Response response,
      String sessionId) {
    return new ResponseParser(client, recipient, response, sessionId);
  }

  /** Log messages as info. */
  private void inform(String... messages) {
    for (String message : messages) {
      LOGGER.info(SecurityManagerUtil.sessionLogMessage(sessionId, message));
    }
  }

  /** Log messages as warnings. */
  private void warn(String... messages) {
    for (String message : messages) {
      LOGGER.warning(SecurityManagerUtil.sessionLogMessage(sessionId, message));
    }
  }

  /**
   * If condition is false then log messages as warnings.
   * <p>
   * This method is used to modify a chain of &amp;&amp; boolean conditions.
   * For example:
   * <pre>
   *   return name != null
   *       && isValidName(name)
   *       && hasSession(name);
   * </pre>
   * becomes:
   * <pre>
   *   return warnIfFalse(name != null, "Name is null")
   *       && warnIfFalse(isValidName(name), "Invalid name: " + name)
   *       && warnIfFalse(hasSession(name), "Missing session for: " + name);
   * </pre>
   * <p>
   * @return value of condition
   */
  private boolean warnIfFalse(boolean condition, String ... messages) {
    if (!condition) {
      warn(messages);
    }
    return condition;
  }

  // to avoid having 3 try/catch loops in findSuitableAssertionHelper
  private Assertion findSuitableAssertion() {
    try {
      return findSuitableAssertionHelper();
    } catch (IOException e) {
      LOGGER.log(Level.WARNING, "An error occurred but logger could not parse "
                               + "the SamlResponse object.", e);
      return null;
    }
  }

  // TODO(cph): This logic is inadequate, but more or less the same as what the
  // GSA does.  Instead of trying to find a single valid assertion, we should
  // analyze the assertions as a whole and combine their content.  The SAML spec
  // allows the IdP to include arbitrary numbers of assertions, and with each
  // assertion an arbitrary number of statements.  The spec explicitly states
  // that an assertion with multiple statements is completely equivalent to
  // multiple assertions, each with a single statement (provided the other parts
  // of the assertions match one another).  It's the responsibility of the
  // relying party (us) to make sense of the information in whatever form the
  // IdP sends it.
  private Assertion findSuitableAssertionHelper() throws IOException {
    if (response.getAssertions().isEmpty()) {
      warn(SamlLogUtil.xmlMessage(
        "Received no assertions in this response.", response));
    }

    for (Assertion assertion : response.getAssertions()) {
      if (isAssertionValid(assertion)) {
        return assertion;
      }
      warn(SamlLogUtil.xmlMessage(
          "Rejected assertion because it was invalid", assertion));
    }
    warn(SamlLogUtil.xmlMessage(
        "Could not find a valid assertion for this response", response));
    return null;
  }

  /**
   * Is the response element valid?
   */
  public boolean isResponseValid() {
    Issuer issuer = response.getIssuer();
    return issuer == null || isValidIssuer(issuer);
  }

  /**
   * Get the response status code.
   * Must satisfy {@link #isResponseValid} prior to calling.
   */
  public String getResponseStatus() {
    return response.getStatus().getStatusCode().getValue();
  }

  /**
   * Are the assertions contained in this response valid?
   * Meaningful only when response status is "success".
   */
  public boolean areAssertionsValid() {
    return assertion != null;
  }

  /**
   * Get the asserted subject.
   * Must satisfy {@link #areAssertionsValid} prior to calling.
   */
  public String getSubject() {
    return assertion.getSubject().getNameID().getValue();
  }

  /**
   * Get the expiration time for the subject verification.
   * Must satisfy {@link #areAssertionsValid} prior to calling.
   *
   * @return The expiration time, or null if there is none.
   */
  public DateTime getExpirationTime() {
    DateTime time1 = assertion.getConditions().getNotOnOrAfter();
    List<SubjectConfirmation> confirmations = assertion.getSubject().getSubjectConfirmations();
    if (confirmations.isEmpty()) {
      return time1;
    }
    DateTime time2 = Iterables.find(confirmations, bearerPredicate)
        .getSubjectConfirmationData()
        .getNotOnOrAfter();
    return (time1 == null || dtComparator.compare(time1, time2) > 0) ? time2 : time1;
  }

  /**
   * Gets an exported-state object.  This information is a security manager
   * extension.  Must satisfy {@link #areAssertionsValid} prior to calling.
   */
  public ExportedState getExportedState() {
    return getExportedState(assertion);
  }

  /**
   * Gets an exported-state object from a given assertion.  This information is
   * a security manager extension.
   *
   * @param assertion The assertion to get the identities from.
   * @return A exported-state object, or {@code null} if there's none.
   */
  @VisibleForTesting
  public static ExportedState getExportedState(Assertion assertion) {
    for (AttributeStatement attributeStatement : assertion.getAttributeStatements()) {
      for (Attribute attribute : attributeStatement.getAttributes()) {
        if (ExportedState.ATTRIBUTE_NAME.equals(attribute.getName())) {
          List<XMLObject> attributeValues = attribute.getAttributeValues();
          if (attributeValues.size() == 1) {
            XMLObject attributeValue = attributeValues.get(0);
            String textContent = attributeValue.getDOM().getTextContent();
            return ExportedState.fromJsonString(textContent);
          }
        }
      }
    }
    return null;
  }

  /**
   * Get any groups that are provided by the assertions.
   * This information is a security manager extension.
   * Must satisfy {@link #areAssertionsValid} prior to calling.
   */
  public ImmutableSet<String> getGroups() {
    return getGroups(assertion);
  }

  /**
   * Gets any groups that are provided by a given assertion.  This information
   * is a security manager extension.
   *
   * @param assertion An assertion to get the groups from.
   * @return An immutable set of the groups found; may be empty.
   */
  @VisibleForTesting
  public static ImmutableSet<String> getGroups(Assertion assertion) {
    ExportedState state = getExportedState(assertion);
    return (state != null)
        ? state.getPviCredentials().getGroups()
        : ImmutableSet.<String>of();
  }

  // **************** Validation primitives ****************

  private boolean isAssertionValid(Assertion assertion) {
    String validityDescription
        = "is empty (of statements): " + assertion.getAuthnStatements().isEmpty()
        + ", assertion issuer: " +  assertion.getIssuer()
        + ", is valid issuer: " + isValidIssuer(assertion.getIssuer())
        + ", is valid subject: " + isValidSubject(assertion.getSubject())
        + ", are valid conditions: " + isValidConditions(assertion.getConditions());
    inform(validityDescription);

    return !assertion.getAuthnStatements().isEmpty()
        && (assertion.getIssuer() != null)
        && isValidIssuer(assertion.getIssuer())
        && isValidSubject(assertion.getSubject())
        && isValidConditions(assertion.getConditions());
  }

  private boolean isValidIssuer(Issuer issuer) {
    return warnIfFalse(issuer.getFormat() == null || NameIDType.ENTITY.equals(issuer.getFormat()),
                "Issuer contains a format: " + issuer.getFormat() +
                " but is not equal to expected format: " + NameIDType.ENTITY)
        && warnIfFalse(client.getPeerEntity().getEntityID().equals(issuer.getValue()),
                "Issuer value: " + issuer.getValue() + " is not equals to "
                + "expected value: " + client.getPeerEntity().getEntityID());
  }

  private boolean isValidSubject(Subject subject) {
    return warnIfFalse(subject != null, "Subject is null.")
        && warnIfFalse(hasValidId(subject), "Subject has an invalid ID.")
        && warnIfFalse(areValidSubjectConfirmations(subject.getSubjectConfirmations()),
                "Subject does not have valid confirmations.");
  }

  // This is a security manager requirement; it's not mandated by the spec.
  private boolean hasValidId(Subject subject) {
    return warnIfFalse(subject.getBaseID() == null, "Subject BaseID is not null.")
        && warnIfFalse(subject.getNameID() != null, "Subject NameID is null")
        && warnIfFalse(!Strings.isNullOrEmpty(subject.getNameID().getValue()),
                "Subject NameID string is null or empty.")
        && warnIfFalse(subject.getEncryptedID() == null, "Subject contains an EncryptedID.");
  }

  private boolean areValidSubjectConfirmations(List<SubjectConfirmation> confirmations) {
    if (confirmations.isEmpty()) {
      // This violates the SAML spec, but the GSA has historically ignored this
      // information, so we must allow it.
      warn("SAML assertion received without subject confirmation");
      return true;
    }
    Iterable<SubjectConfirmation> bearers = Iterables.filter(confirmations, bearerPredicate);
    return warnIfFalse(!Iterables.isEmpty(bearers), "SubjectConfirmations contains no bearers.")
        && warnIfFalse(Iterables.all(bearers, validBearerPredicate),
        "SubjectConfirmations were invalid.");
  }

  private Predicate<SubjectConfirmation> bearerPredicate =
      new Predicate<SubjectConfirmation>() {
        public boolean apply(SubjectConfirmation confirmation) {
          return OpenSamlUtil.BEARER_METHOD.equals(confirmation.getMethod());
        }
      };

  private Predicate<SubjectConfirmation> validBearerPredicate =
      new Predicate<SubjectConfirmation>() {
        public boolean apply(SubjectConfirmation bearer) {
          return isValidSubjectConfirmationData(bearer.getSubjectConfirmationData());
        }
      };

  private boolean isValidSubjectConfirmationData(SubjectConfirmationData data) {
    return warnIfFalse(recipient.equals(data.getRecipient()),
                "SubjectConfirmationData - recipient not equals : " + recipient +
                "but was instead: " + data.getRecipient())
        && warnIfFalse(isValidExpiration(data.getNotOnOrAfter()), "Invalid expiration.")
        && warnIfFalse(client.getRequestId().equals((data.getInResponseTo())),
                "Assertion inResponseTo: " + data.getInResponseTo() +
                  " was not equal to this client's RequestID: " + client.getRequestId());
  }

  private boolean isValidExpiration(DateTime expiration) {
    return warnIfFalse(expiration != null, "Assertion expiration was null.") &&
           warnIfFalse(SecurityManagerUtil.isRemoteOnOrAfterTimeValid(expiration.getMillis(), now),
                "The assertion's expiration time is invalid.",
                "Security Manager Current Time: " + new DateTime(now).toString(),
                "Assertion expiration:" + new DateTime(expiration.getMillis()).toString());
  }

  // TODO(cph): This code needs to handle <OneTimeUse> and <ProxyRestriction>
  // conditions.
  private boolean isValidConditions(Conditions conditions) {
    return warnIfFalse(conditions != null, "Assertion conditions was null.")
        && warnIfFalse(isValidConditionNotBefore(conditions.getNotBefore()),
                "ConditionNotBefore is invalid: " + conditions.getNotBefore())
        && warnIfFalse(isValidConditionNotOnOrAfter(conditions.getNotOnOrAfter()),
                "ConditionNotOnOrAfter is invalid: " + conditions.getNotOnOrAfter())
        && warnIfFalse(isValidConditionAudienceRestrictions(conditions.getAudienceRestrictions()),
                "ConditionAudienceRestrictions is invalid: " +
                conditions.getAudienceRestrictions());
  }

  private boolean isValidConditionNotBefore(DateTime notBefore) {
    return notBefore == null ||
        SecurityManagerUtil.isRemoteBeforeTimeValid(notBefore.getMillis(), now);
  }

  private boolean isValidConditionNotOnOrAfter(DateTime notOnOrAfter) {
    return notOnOrAfter == null ||
        SecurityManagerUtil.isRemoteOnOrAfterTimeValid(notOnOrAfter.getMillis(), now);
  }

  private boolean isValidConditionAudienceRestrictions(List<AudienceRestriction> restrictions) {
    String localEntityId = client.getLocalEntity().getEntityID();
    for (AudienceRestriction restriction : restrictions) {
      for (Audience audience : restriction.getAudiences()) {
        if (localEntityId.equals(audience.getAudienceURI())) {
          return true;
        }
      }
    }
    return false;
  }
}
