// 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.keyIdToString;
import static com.google.gerrit.server.account.ExternalId.SCHEME_GPGKEY;

import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.io.BaseEncoding;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.account.ExternalId;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.query.account.InternalAccountQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPSignature;
import org.bouncycastle.openpgp.operator.bc.BcPGPContentVerifierBuilderProvider;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.transport.PushCertificateIdent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Checker for GPG public keys including Gerrit-specific checks.
 *
 * <p>For Gerrit, keys must contain a self-signed user ID certification matching a trusted external
 * ID in the database, or an email address thereof.
 */
public class GerritPublicKeyChecker extends PublicKeyChecker {
  private static final Logger log = LoggerFactory.getLogger(GerritPublicKeyChecker.class);

  @Singleton
  public static class Factory {
    private final Provider<InternalAccountQuery> accountQueryProvider;
    private final String webUrl;
    private final IdentifiedUser.GenericFactory userFactory;
    private final int maxTrustDepth;
    private final ImmutableMap<Long, Fingerprint> trusted;

    @Inject
    Factory(
        @GerritServerConfig Config cfg,
        Provider<InternalAccountQuery> accountQueryProvider,
        IdentifiedUser.GenericFactory userFactory,
        @CanonicalWebUrl String webUrl) {
      this.accountQueryProvider = accountQueryProvider;
      this.webUrl = webUrl;
      this.userFactory = userFactory;
      this.maxTrustDepth = cfg.getInt("receive", null, "maxTrustDepth", 0);

      String[] strs = cfg.getStringList("receive", null, "trustedKey");
      if (strs.length != 0) {
        Map<Long, Fingerprint> fps = Maps.newHashMapWithExpectedSize(strs.length);
        for (String str : strs) {
          str = CharMatcher.whitespace().removeFrom(str).toUpperCase();
          Fingerprint fp = new Fingerprint(BaseEncoding.base16().decode(str));
          fps.put(fp.getId(), fp);
        }
        trusted = ImmutableMap.copyOf(fps);
      } else {
        trusted = null;
      }
    }

    public GerritPublicKeyChecker create() {
      return new GerritPublicKeyChecker(this);
    }

    public GerritPublicKeyChecker create(IdentifiedUser expectedUser, PublicKeyStore store) {
      GerritPublicKeyChecker checker = new GerritPublicKeyChecker(this);
      checker.setExpectedUser(expectedUser);
      checker.setStore(store);
      return checker;
    }
  }

  private final Provider<InternalAccountQuery> accountQueryProvider;
  private final String webUrl;
  private final IdentifiedUser.GenericFactory userFactory;

  private IdentifiedUser expectedUser;

  private GerritPublicKeyChecker(Factory factory) {
    this.accountQueryProvider = factory.accountQueryProvider;
    this.webUrl = factory.webUrl;
    this.userFactory = factory.userFactory;
    if (factory.trusted != null) {
      enableTrust(factory.maxTrustDepth, factory.trusted);
    }
  }

  /**
   * Set the expected user for this checker.
   *
   * <p>If set, the top-level key passed to {@link #check(PGPPublicKey)} must belong to the given
   * user. (Other keys checked in the course of verifying the web of trust are checked against the
   * set of identities in the database belonging to the same user as the key.)
   */
  public GerritPublicKeyChecker setExpectedUser(IdentifiedUser expectedUser) {
    this.expectedUser = expectedUser;
    return this;
  }

  @Override
  public CheckResult checkCustom(PGPPublicKey key, int depth) {
    try {
      if (depth == 0 && expectedUser != null) {
        return checkIdsForExpectedUser(key);
      }
      return checkIdsForArbitraryUser(key);
    } catch (PGPException | OrmException e) {
      String msg = "Error checking user IDs for key";
      log.warn(msg + " " + keyIdToString(key.getKeyID()), e);
      return CheckResult.bad(msg);
    }
  }

  private CheckResult checkIdsForExpectedUser(PGPPublicKey key) throws PGPException {
    Set<String> allowedUserIds = getAllowedUserIds(expectedUser);
    if (allowedUserIds.isEmpty()) {
      return CheckResult.bad(
          "No identities found for user; check " + webUrl + "#" + PageLinks.SETTINGS_WEBIDENT);
    }
    if (hasAllowedUserId(key, allowedUserIds)) {
      return CheckResult.trusted();
    }
    return CheckResult.bad(missingUserIds(allowedUserIds));
  }

  private CheckResult checkIdsForArbitraryUser(PGPPublicKey key) throws PGPException, OrmException {
    List<AccountState> accountStates = accountQueryProvider.get().byExternalId(toExtIdKey(key));
    if (accountStates.isEmpty()) {
      return CheckResult.bad("Key is not associated with any users");
    }
    if (accountStates.size() > 1) {
      return CheckResult.bad("Key is associated with multiple users");
    }
    IdentifiedUser user = userFactory.create(accountStates.get(0));

    Set<String> allowedUserIds = getAllowedUserIds(user);
    if (allowedUserIds.isEmpty()) {
      return CheckResult.bad("No identities found for user");
    }
    if (hasAllowedUserId(key, allowedUserIds)) {
      return CheckResult.trusted();
    }
    return CheckResult.bad("Key does not contain any valid certifications for user's identities");
  }

  private boolean hasAllowedUserId(PGPPublicKey key, Set<String> allowedUserIds)
      throws PGPException {
    Iterator<String> userIds = key.getUserIDs();
    while (userIds.hasNext()) {
      String userId = userIds.next();
      if (isAllowed(userId, allowedUserIds)) {
        Iterator<PGPSignature> sigs = getSignaturesForId(key, userId);
        while (sigs.hasNext()) {
          if (isValidCertification(key, sigs.next(), userId)) {
            return true;
          }
        }
      }
    }

    return false;
  }

  private Iterator<PGPSignature> getSignaturesForId(PGPPublicKey key, String userId) {
    Iterator<PGPSignature> result = key.getSignaturesForID(userId);
    return result != null ? result : Collections.emptyIterator();
  }

  private Set<String> getAllowedUserIds(IdentifiedUser user) {
    Set<String> result = new HashSet<>();
    result.addAll(user.getEmailAddresses());
    for (ExternalId extId : user.state().getExternalIds()) {
      if (extId.isScheme(SCHEME_GPGKEY)) {
        continue; // Omit GPG keys.
      }
      result.add(extId.key().get());
    }
    return result;
  }

  private static boolean isAllowed(String userId, Set<String> allowedUserIds) {
    return allowedUserIds.contains(userId)
        || allowedUserIds.contains(PushCertificateIdent.parse(userId).getEmailAddress());
  }

  private static boolean isValidCertification(PGPPublicKey key, PGPSignature sig, String userId)
      throws PGPException {
    if (sig.getSignatureType() != PGPSignature.DEFAULT_CERTIFICATION
        && sig.getSignatureType() != PGPSignature.POSITIVE_CERTIFICATION) {
      return false;
    }
    if (sig.getKeyID() != key.getKeyID()) {
      return false;
    }
    // TODO(dborowitz): Handle certification revocations:
    // - Is there a revocation by either this key or another key trusted by the
    //   server?
    // - Does such a revocation postdate all other valid certifications?

    sig.init(new BcPGPContentVerifierBuilderProvider(), key);
    return sig.verifyCertification(userId, key);
  }

  private static String missingUserIds(Set<String> allowedUserIds) {
    StringBuilder sb =
        new StringBuilder(
            "Key must contain a valid certification for one of the following identities:\n");
    Iterator<String> sorted = allowedUserIds.stream().sorted().iterator();
    while (sorted.hasNext()) {
      sb.append("  ").append(sorted.next());
      if (sorted.hasNext()) {
        sb.append('\n');
      }
    }
    return sb.toString();
  }

  static ExternalId.Key toExtIdKey(PGPPublicKey key) {
    return ExternalId.Key.create(SCHEME_GPGKEY, BaseEncoding.base16().encode(key.getFingerprint()));
  }
}
