// 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.gpg.PublicKeyStore.keyToString;
import static com.google.gerrit.gpg.testutil.TestKeys.expiredKey;
import static com.google.gerrit.gpg.testutil.TestKeys.keyRevokedByExpiredKeyAfterExpiration;
import static com.google.gerrit.gpg.testutil.TestKeys.keyRevokedByExpiredKeyBeforeExpiration;
import static com.google.gerrit.gpg.testutil.TestKeys.revokedCompromisedKey;
import static com.google.gerrit.gpg.testutil.TestKeys.revokedNoLongerUsedKey;
import static com.google.gerrit.gpg.testutil.TestKeys.selfRevokedKey;
import static com.google.gerrit.gpg.testutil.TestKeys.validKeyWithExpiration;
import static com.google.gerrit.gpg.testutil.TestKeys.validKeyWithoutExpiration;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyA;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyB;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyC;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyD;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyE;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyF;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyG;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyH;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyI;
import static com.google.gerrit.gpg.testutil.TestTrustKeys.keyJ;
import static org.bouncycastle.bcpg.SignatureSubpacketTags.REVOCATION_KEY;
import static org.bouncycastle.openpgp.PGPSignature.DIRECT_KEY;
import static org.junit.Assert.assertEquals;

import com.google.gerrit.gpg.testutil.TestKey;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPSignature;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class PublicKeyCheckerTest {
  @Rule public ExpectedException thrown = ExpectedException.none();

  private InMemoryRepository repo;
  private PublicKeyStore store;

  @Before
  public void setUp() {
    repo = new InMemoryRepository(new DfsRepositoryDescription("repo"));
    store = new PublicKeyStore(repo);
  }

  @After
  public void tearDown() {
    if (store != null) {
      store.close();
      store = null;
    }
    if (repo != null) {
      repo.close();
      repo = null;
    }
  }

  @Test
  public void validKey() throws Exception {
    assertNoProblems(validKeyWithoutExpiration());
  }

  @Test
  public void keyExpiringInFuture() throws Exception {
    TestKey k = validKeyWithExpiration();

    PublicKeyChecker checker = new PublicKeyChecker().setStore(store);
    assertNoProblems(checker, k);

    checker.setEffectiveTime(parseDate("2015-07-10 12:00:00 -0400"));
    assertNoProblems(checker, k);

    checker.setEffectiveTime(parseDate("2075-07-10 12:00:00 -0400"));
    assertProblems(checker, k, "Key is expired");
  }

  @Test
  public void expiredKeyIsExpired() throws Exception {
    assertProblems(expiredKey(), "Key is expired");
  }

  @Test
  public void selfRevokedKeyIsRevoked() throws Exception {
    assertProblems(selfRevokedKey(), "Key is revoked (key material has been compromised)");
  }

  // Test keys specific to this test are at the bottom of this class. Each test
  // has a diagram of the trust network, where:
  //  - The notation M---N indicates N trusts M.
  //  - An 'x' indicates the key is expired.

  @Test
  public void trustValidPathLength2() throws Exception {
    // A---Bx
    //  \
    //   \---C---D
    //        \
    //         \---Ex
    //
    // D and E trust C to be a valid introducer of depth 2.
    TestKey ka = add(keyA());
    TestKey kb = add(keyB());
    TestKey kc = add(keyC());
    TestKey kd = add(keyD());
    TestKey ke = add(keyE());
    save();

    PublicKeyChecker checker = newChecker(2, kb, kd);
    assertNoProblems(checker, ka);
    assertProblems(checker, kb, "Key is expired");
    assertNoProblems(checker, kc);
    assertNoProblems(checker, kd);
    assertProblems(checker, ke, "Key is expired", "No path to a trusted key");
  }

  @Test
  public void trustValidPathLength1() throws Exception {
    // A---Bx
    //  \
    //   \---C---D
    //        \
    //         \---Ex
    //
    // D and E trust C to be a valid introducer of depth 2.
    TestKey ka = add(keyA());
    TestKey kb = add(keyB());
    TestKey kc = add(keyC());
    TestKey kd = add(keyD());
    add(keyE());
    save();

    PublicKeyChecker checker = newChecker(1, kd);
    assertProblems(checker, ka, "No path to a trusted key", notTrusted(kb), notTrusted(kc));
  }

  @Test
  public void trustCycle() throws Exception {
    // F---G---F, in a cycle.
    TestKey kf = add(keyF());
    TestKey kg = add(keyG());
    save();

    PublicKeyChecker checker = newChecker(10, keyA());
    assertProblems(checker, kf, "No path to a trusted key", notTrusted(kg));
    assertProblems(checker, kg, "No path to a trusted key", notTrusted(kf));
  }

  @Test
  public void trustInsufficientDepthInSignature() throws Exception {
    // H---I---J, but J is only trusted to length 1.
    TestKey kh = add(keyH());
    TestKey ki = add(keyI());
    add(keyJ());
    save();

    PublicKeyChecker checker = newChecker(10, keyJ());

    // J trusts I to a depth of 1, so I itself is valid, but I's certification
    // of K is not valid.
    assertNoProblems(checker, ki);
    assertProblems(checker, kh, "No path to a trusted key", notTrusted(ki));
  }

  @Test
  public void revokedKeyDueToCompromise() throws Exception {
    TestKey k = add(revokedCompromisedKey());
    add(validKeyWithoutExpiration());
    save();

    assertProblems(k, "Key is revoked (key material has been compromised): test6 compromised");

    PGPPublicKeyRing kr = removeRevokers(k.getPublicKeyRing());
    store.add(kr);
    save();

    // Key no longer specified as revoker.
    assertNoProblems(kr.getPublicKey());
  }

  @Test
  public void revokedKeyDueToCompromiseRevokesKeyRetroactively() throws Exception {
    TestKey k = add(revokedCompromisedKey());
    add(validKeyWithoutExpiration());
    save();

    String problem = "Key is revoked (key material has been compromised): test6 compromised";
    assertProblems(k, problem);

    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    PublicKeyChecker checker =
        new PublicKeyChecker().setStore(store).setEffectiveTime(df.parse("2010-01-01 12:00:00"));
    assertProblems(checker, k, problem);
  }

  @Test
  public void revokedByKeyNotPresentInStore() throws Exception {
    TestKey k = add(revokedCompromisedKey());
    save();

    assertProblems(k, "Key is revoked (key material has been compromised): test6 compromised");
  }

  @Test
  public void revokedKeyDueToNoLongerBeingUsed() throws Exception {
    TestKey k = add(revokedNoLongerUsedKey());
    add(validKeyWithoutExpiration());
    save();

    assertProblems(k, "Key is revoked (retired and no longer valid): test7 not used");
  }

  @Test
  public void revokedKeyDueToNoLongerBeingUsedDoesNotRevokeKeyRetroactively() throws Exception {
    TestKey k = add(revokedNoLongerUsedKey());
    add(validKeyWithoutExpiration());
    save();

    assertProblems(k, "Key is revoked (retired and no longer valid): test7 not used");

    PublicKeyChecker checker =
        new PublicKeyChecker()
            .setStore(store)
            .setEffectiveTime(parseDate("2010-01-01 12:00:00 -0400"));
    assertNoProblems(checker, k);
  }

  @Test
  public void keyRevokedByExpiredKeyAfterExpirationIsNotRevoked() throws Exception {
    TestKey k = add(keyRevokedByExpiredKeyAfterExpiration());
    add(expiredKey());
    save();

    PublicKeyChecker checker = new PublicKeyChecker().setStore(store);
    assertNoProblems(checker, k);
  }

  @Test
  public void keyRevokedByExpiredKeyBeforeExpirationIsRevoked() throws Exception {
    TestKey k = add(keyRevokedByExpiredKeyBeforeExpiration());
    add(expiredKey());
    save();

    PublicKeyChecker checker = new PublicKeyChecker().setStore(store);
    assertProblems(checker, k, "Key is revoked (retired and no longer valid): test9 not used");

    // Set time between key creation and revocation.
    checker.setEffectiveTime(parseDate("2005-08-01 13:00:00 -0400"));
    assertNoProblems(checker, k);
  }

  private PGPPublicKeyRing removeRevokers(PGPPublicKeyRing kr) {
    PGPPublicKey k = kr.getPublicKey();
    @SuppressWarnings("unchecked")
    Iterator<PGPSignature> sigs = k.getSignaturesOfType(DIRECT_KEY);
    while (sigs.hasNext()) {
      PGPSignature sig = sigs.next();
      if (sig.getHashedSubPackets().hasSubpacket(REVOCATION_KEY)) {
        k = PGPPublicKey.removeCertification(k, sig);
      }
    }
    return PGPPublicKeyRing.insertPublicKey(kr, k);
  }

  private PublicKeyChecker newChecker(int maxTrustDepth, TestKey... trusted) {
    Map<Long, Fingerprint> fps = new HashMap<>();
    for (TestKey k : trusted) {
      Fingerprint fp = new Fingerprint(k.getPublicKey().getFingerprint());
      fps.put(fp.getId(), fp);
    }
    return new PublicKeyChecker().enableTrust(maxTrustDepth, fps).setStore(store);
  }

  private TestKey add(TestKey k) {
    store.add(k.getPublicKeyRing());
    return k;
  }

  private void save() throws Exception {
    PersonIdent ident = new PersonIdent("A U Thor", "author@example.com");
    CommitBuilder cb = new CommitBuilder();
    cb.setAuthor(ident);
    cb.setCommitter(ident);
    RefUpdate.Result result = store.save(cb);
    switch (result) {
      case NEW:
      case FAST_FORWARD:
      case FORCED:
        break;
      case IO_FAILURE:
      case LOCK_FAILURE:
      case NOT_ATTEMPTED:
      case NO_CHANGE:
      case REJECTED:
      case REJECTED_CURRENT_BRANCH:
      case RENAMED:
      default:
        throw new AssertionError(result);
    }
  }

  private void assertProblems(PublicKeyChecker checker, TestKey k, String first, String... rest) {
    CheckResult result = checker.setStore(store).check(k.getPublicKey());
    assertEquals(list(first, rest), result.getProblems());
  }

  private void assertNoProblems(PublicKeyChecker checker, TestKey k) {
    CheckResult result = checker.setStore(store).check(k.getPublicKey());
    assertEquals(Collections.emptyList(), result.getProblems());
  }

  private void assertProblems(TestKey tk, String first, String... rest) {
    assertProblems(tk.getPublicKey(), first, rest);
  }

  private void assertNoProblems(TestKey tk) {
    assertNoProblems(tk.getPublicKey());
  }

  private void assertProblems(PGPPublicKey k, String first, String... rest) {
    CheckResult result = new PublicKeyChecker().setStore(store).check(k);
    assertEquals(list(first, rest), result.getProblems());
  }

  private void assertNoProblems(PGPPublicKey k) {
    CheckResult result = new PublicKeyChecker().setStore(store).check(k);
    assertEquals(Collections.emptyList(), result.getProblems());
  }

  private static String notTrusted(TestKey k) {
    return "Certification by "
        + keyToString(k.getPublicKey())
        + " is valid, but key is not trusted";
  }

  private static Date parseDate(String str) throws Exception {
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z").parse(str);
  }

  private static List<String> list(String first, String[] rest) {
    List<String> all = new ArrayList<>();
    all.add(first);
    all.addAll(Arrays.asList(rest));
    return all;
  }
}
