// Copyright (C) 2010 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.sshd;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Throwables;
import com.google.common.util.concurrent.Atomics;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PeerDaemonUser;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.sshd.SshScope.Context;
import com.google.inject.Inject;
import java.io.IOException;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.channel.ChannelSession;
import org.apache.sshd.server.command.Command;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

/**
 * Executes any other command as a different user identity.
 *
 * <p>The calling user must be authenticated as a {@link PeerDaemonUser}, which usually requires
 * public key authentication using this daemon's private host key, or a key on this daemon's peer
 * host key ring.
 */
public final class SuExec extends BaseCommand {
  private final SshScope sshScope;
  private final DispatchCommandProvider dispatcher;
  private final PermissionBackend permissionBackend;

  private boolean enableRunAs;
  private CurrentUser caller;
  private SshSession session;
  private IdentifiedUser.GenericFactory userFactory;
  private SshScope.Context callingContext;

  @Option(name = "--as", required = true)
  private Account.Id accountId;

  @Option(name = "--from")
  private SocketAddress peerAddress;

  @Argument(index = 0, multiValued = true, metaVar = "COMMAND")
  private List<String> args = new ArrayList<>();

  private final AtomicReference<Command> atomicCmd;

  @Inject
  SuExec(
      final SshScope sshScope,
      @CommandName(Commands.ROOT) final DispatchCommandProvider dispatcher,
      PermissionBackend permissionBackend,
      final CurrentUser caller,
      final SshSession session,
      final IdentifiedUser.GenericFactory userFactory,
      final SshScope.Context callingContext,
      AuthConfig config) {
    this.sshScope = sshScope;
    this.dispatcher = dispatcher;
    this.permissionBackend = permissionBackend;
    this.caller = caller;
    this.session = session;
    this.userFactory = userFactory;
    this.callingContext = callingContext;
    this.enableRunAs = config.isRunAsEnabled();
    atomicCmd = Atomics.newReference();
  }

  @Override
  public void start(ChannelSession channel, Environment env) throws IOException {
    try {
      checkCanRunAs();
      parseCommandLine();

      final Context ctx = callingContext.subContext(newSession(), join(args));
      final Context old = sshScope.set(ctx);
      try {
        final BaseCommand cmd = dispatcher.get();
        cmd.setArguments(args.toArray(new String[args.size()]));
        provideStateTo(cmd);
        atomicCmd.set(cmd);
        cmd.start(channel, env);
      } finally {
        sshScope.set(old);
      }
    } catch (UnloggedFailure e) {
      String msg = e.getMessage();
      if (!msg.endsWith("\n")) {
        msg += "\n";
      }
      err.write(msg.getBytes(UTF_8));
      err.flush();
      onExit(1);
    }
  }

  private void checkCanRunAs() throws UnloggedFailure {
    if (caller instanceof PeerDaemonUser) {
      // OK.
    } else if (!enableRunAs) {
      throw die("suexec disabled by auth.enableRunAs = false");
    } else {
      try {
        permissionBackend.user(caller).check(GlobalPermission.RUN_AS);
      } catch (AuthException e) {
        throw die("suexec not permitted", e);
      } catch (PermissionBackendException e) {
        throw die("suexec not available", e);
      }
    }
  }

  private SshSession newSession() {
    final SocketAddress peer;
    if (peerAddress == null) {
      peer = session.getRemoteAddress();
    } else {
      peer = peerAddress;
    }
    if (caller instanceof PeerDaemonUser) {
      caller = null;
    }
    return new SshSession(session, peer, userFactory.runAs(peer, accountId, caller));
  }

  private static String join(List<String> args) {
    StringBuilder r = new StringBuilder();
    for (String a : args) {
      if (r.length() > 0) {
        r.append(" ");
      }
      r.append(a);
    }
    return r.toString();
  }

  @Override
  public void destroy(ChannelSession channel) {
    Command cmd = atomicCmd.getAndSet(null);
    if (cmd != null) {
      try {
        cmd.destroy(channel);
      } catch (Exception e) {
        Throwables.throwIfUnchecked(e);
        throw new RuntimeException(e);
      }
    }
  }
}
