// Copyright (C) 2015 The Android Open Source Project
//
// 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.gerrit.gpg;

import static com.google.gerrit.extensions.common.GpgKeyInfo.Status.BAD;
import static com.google.gerrit.extensions.common.GpgKeyInfo.Status.OK;
import static com.google.gerrit.extensions.common.GpgKeyInfo.Status.TRUSTED;
import static com.google.gerrit.gpg.PublicKeyStore.keyIdToString;
import static com.google.gerrit.gpg.PublicKeyStore.keyToString;

import com.google.common.base.Joiner;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.common.GpgKeyInfo.Status;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.bouncycastle.bcpg.ArmoredInputStream;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.PGPSignatureList;
import org.bouncycastle.openpgp.bc.BcPGPObjectFactory;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.PushCertificate;
import org.eclipse.jgit.transport.PushCertificate.NonceStatus;

/** Checker for push certificates. */
public abstract class PushCertificateChecker {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static class Result {
    private final PGPPublicKey key;
    private final CheckResult checkResult;

    private Result(PGPPublicKey key, CheckResult checkResult) {
      this.key = key;
      this.checkResult = checkResult;
    }

    public PGPPublicKey getPublicKey() {
      return key;
    }

    public CheckResult getCheckResult() {
      return checkResult;
    }
  }

  private final PublicKeyChecker publicKeyChecker;

  private boolean checkNonce;

  protected PushCertificateChecker(PublicKeyChecker publicKeyChecker) {
    this.publicKeyChecker = publicKeyChecker;
    checkNonce = true;
  }

  /** Set whether to check the status of the nonce; defaults to true. */
  public PushCertificateChecker setCheckNonce(boolean checkNonce) {
    this.checkNonce = checkNonce;
    return this;
  }

  /**
   * Check a push certificate.
   *
   * @return result of the check.
   */
  public final Result check(PushCertificate cert) {
    if (checkNonce && cert.getNonceStatus() != NonceStatus.OK) {
      return new Result(null, CheckResult.bad("Invalid nonce"));
    }
    List<CheckResult> results = new ArrayList<>(2);
    Result sigResult = null;
    try {
      PGPSignature sig = readSignature(cert);
      if (sig != null) {
        @SuppressWarnings("resource")
        Repository repo = getRepository();
        try (PublicKeyStore store = new PublicKeyStore(repo)) {
          sigResult = checkSignature(sig, cert, store);
          results.add(checkCustom(repo));
        } finally {
          if (shouldClose(repo)) {
            repo.close();
          }
        }
      } else {
        results.add(CheckResult.bad("Invalid signature format"));
      }
    } catch (PGPException | IOException e) {
      String msg = "Internal error checking push certificate";
      logger.atSevere().withCause(e).log(msg);
      results.add(CheckResult.bad(msg));
    }

    return combine(sigResult, results);
  }

  private static Result combine(Result sigResult, List<CheckResult> results) {
    // Combine results:
    //  - If any input result is BAD, the final result is bad.
    //  - If sigResult is TRUSTED and no other result is BAD, the final result
    //    is TRUSTED.
    //  - Otherwise, the result is OK.
    List<String> problems = new ArrayList<>();
    boolean bad = false;
    for (CheckResult result : results) {
      problems.addAll(result.getProblems());
      bad |= result.getStatus() == BAD;
    }
    Status status = bad ? BAD : OK;

    PGPPublicKey key;
    if (sigResult != null) {
      key = sigResult.getPublicKey();
      CheckResult cr = sigResult.getCheckResult();
      problems.addAll(cr.getProblems());
      if (cr.getStatus() == BAD) {
        status = BAD;
      } else if (!bad && cr.getStatus() == TRUSTED) {
        status = TRUSTED;
      }
    } else {
      key = null;
    }
    return new Result(key, CheckResult.create(status, problems));
  }

  /**
   * Get the repository that this checker should operate on.
   *
   * <p>This method is called once per call to {@link #check(PushCertificate)}.
   *
   * @return the repository.
   * @throws IOException if an error occurred reading the repository.
   */
  protected abstract Repository getRepository() throws IOException;

  /**
   * Specifies whether this repository should be closed before returning froms {@link
   * #check(PushCertificate)}
   *
   * @param repo a repository previously returned by {@link #getRepository()}.
   * @return true if this repository should be closed before returning from {@link
   *     #check(PushCertificate)}.
   */
  protected abstract boolean shouldClose(Repository repo);

  /**
   * Perform custom checks.
   *
   * <p>Default implementation reports no problems, but may be overridden by subclasses.
   *
   * @param repo a repository previously returned by {@link #getRepository()}.
   * @return the result of the custom check.
   */
  protected CheckResult checkCustom(Repository repo) {
    return CheckResult.ok();
  }

  private PGPSignature readSignature(PushCertificate cert) throws IOException {
    ArmoredInputStream in =
        new ArmoredInputStream(new ByteArrayInputStream(Constants.encode(cert.getSignature())));
    PGPObjectFactory factory = new BcPGPObjectFactory(in);
    Object obj;
    while ((obj = factory.nextObject()) != null) {
      if (obj instanceof PGPSignatureList) {
        PGPSignatureList sigs = (PGPSignatureList) obj;
        if (!sigs.isEmpty()) {
          return sigs.get(0);
        }
      }
    }
    return null;
  }

  private Result checkSignature(PGPSignature sig, PushCertificate cert, PublicKeyStore store)
      throws PGPException, IOException {
    PGPPublicKeyRingCollection keys = store.get(sig.getKeyID());
    if (!keys.getKeyRings().hasNext()) {
      return new Result(
          null,
          CheckResult.bad("No public keys found for key ID " + keyIdToString(sig.getKeyID())));
    }
    PGPPublicKey signer = PublicKeyStore.getSigner(keys, sig, Constants.encode(cert.toText()));
    if (signer == null) {
      return new Result(
          null, CheckResult.bad("Signature by " + keyIdToString(sig.getKeyID()) + " is not valid"));
    }
    CheckResult result =
        publicKeyChecker.setStore(store).setEffectiveTime(sig.getCreationTime()).check(signer);
    if (!result.getProblems().isEmpty()) {
      StringBuilder err =
          new StringBuilder("Invalid public key ")
              .append(keyToString(signer))
              .append(":\n  ")
              .append(Joiner.on("\n  ").join(result.getProblems()));
      return new Result(signer, CheckResult.create(result.getStatus(), err.toString()));
    }
    return new Result(signer, result);
  }
}
