// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/pam_authorization_factory_posix.h"

#include <security/pam_appl.h>

#include <utility>

#include "base/bind.h"
#include "base/callback.h"
#include "base/environment.h"
#include "remoting/base/logging.h"
#include "remoting/host/username.h"
#include "remoting/protocol/channel_authenticator.h"
#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"

namespace remoting {

namespace {
class PamAuthorizer : public protocol::Authenticator {
 public:
  PamAuthorizer(std::unique_ptr<protocol::Authenticator> underlying);
  ~PamAuthorizer() override;

  // protocol::Authenticator interface.
  State state() const override;
  bool started() const override;
  RejectionReason rejection_reason() const override;
  void ProcessMessage(const jingle_xmpp::XmlElement* message,
                      const base::Closure& resume_callback) override;
  std::unique_ptr<jingle_xmpp::XmlElement> GetNextMessage() override;
  const std::string& GetAuthKey() const override;
  std::unique_ptr<protocol::ChannelAuthenticator> CreateChannelAuthenticator()
      const override;

 private:
  void MaybeCheckLocalLogin();
  bool IsLocalLoginAllowed();
  void OnMessageProcessed(const base::Closure& resume_callback);

  static int PamConversation(int num_messages,
                             const struct pam_message** messages,
                             struct pam_response** responses,
                             void* context);

  std::unique_ptr<protocol::Authenticator> underlying_;
  enum { NOT_CHECKED, ALLOWED, DISALLOWED } local_login_status_;
};

}  // namespace

PamAuthorizer::PamAuthorizer(
    std::unique_ptr<protocol::Authenticator> underlying)
    : underlying_(std::move(underlying)), local_login_status_(NOT_CHECKED) {}

PamAuthorizer::~PamAuthorizer() {}

protocol::Authenticator::State PamAuthorizer::state() const {
  if (local_login_status_ == DISALLOWED) {
    return REJECTED;
  } else {
    return underlying_->state();
  }
}

bool PamAuthorizer::started() const {
  return underlying_->started();
}

protocol::Authenticator::RejectionReason
PamAuthorizer::rejection_reason() const {
  if (local_login_status_ == DISALLOWED) {
    return INVALID_CREDENTIALS;
  } else {
    return underlying_->rejection_reason();
  }
}

void PamAuthorizer::ProcessMessage(const jingle_xmpp::XmlElement* message,
                                   const base::Closure& resume_callback) {
  // |underlying_| is owned, so Unretained() is safe here.
  underlying_->ProcessMessage(message, base::Bind(
      &PamAuthorizer::OnMessageProcessed,
      base::Unretained(this), resume_callback));
}

void PamAuthorizer::OnMessageProcessed(const base::Closure& resume_callback) {
  MaybeCheckLocalLogin();
  resume_callback.Run();
}

std::unique_ptr<jingle_xmpp::XmlElement> PamAuthorizer::GetNextMessage() {
  std::unique_ptr<jingle_xmpp::XmlElement> result(underlying_->GetNextMessage());
  MaybeCheckLocalLogin();
  return result;
}

const std::string& PamAuthorizer::GetAuthKey() const {
  return underlying_->GetAuthKey();
}

std::unique_ptr<protocol::ChannelAuthenticator>
PamAuthorizer::CreateChannelAuthenticator() const {
  return underlying_->CreateChannelAuthenticator();
}

void PamAuthorizer::MaybeCheckLocalLogin() {
  if (local_login_status_ == NOT_CHECKED && state() == ACCEPTED) {
    local_login_status_ = IsLocalLoginAllowed() ? ALLOWED : DISALLOWED;
  }
}

bool PamAuthorizer::IsLocalLoginAllowed() {
  std::string username = GetUsername();
  if (username.empty()) {
    return false;
  }
  struct pam_conv conv = { PamConversation, nullptr };
  pam_handle_t* handle = nullptr;
  int result = pam_start("chrome-remote-desktop", username.c_str(),
                         &conv, &handle);
  if (result == PAM_SUCCESS) {
    result = pam_acct_mgmt(handle, 0);
  }
  pam_end(handle, result);

  HOST_LOG << "Local login check for " << username
            << (result == PAM_SUCCESS ? " succeeded." : " failed.");

  return result == PAM_SUCCESS;
}

int PamAuthorizer::PamConversation(int num_messages,
                                   const struct pam_message** messages,
                                   struct pam_response** responses,
                                   void* context) {
  // Assume we're only being asked to log messages, in which case our response
  // need to be free()-able zero-initialized memory.
  *responses = static_cast<struct pam_response*>(
      calloc(num_messages, sizeof(struct pam_response)));

  // We don't expect this function to be called. Since we have no easy way
  // of returning a response, we consider it to be an error if we're asked
  // for one and abort. Informational and error messages are logged.
  for (int i = 0; i < num_messages; ++i) {
    const struct pam_message* message = messages[i];
    switch (message->msg_style) {
      case PAM_ERROR_MSG:
        LOG(ERROR) << "PAM conversation error message: " << message->msg;
        break;
      case PAM_TEXT_INFO:
        HOST_LOG << "PAM conversation message: " << message->msg;
        break;
      default:
        LOG(FATAL) << "Unexpected PAM conversation response required: "
                   << message->msg << "; msg_style = " << message->msg_style;
    }
  }
  return PAM_SUCCESS;
}

PamAuthorizationFactory::PamAuthorizationFactory(
    std::unique_ptr<protocol::AuthenticatorFactory> underlying)
    : underlying_(std::move(underlying)) {}

PamAuthorizationFactory::~PamAuthorizationFactory() {}

std::unique_ptr<protocol::Authenticator>
PamAuthorizationFactory::CreateAuthenticator(const std::string& local_jid,
                                             const std::string& remote_jid) {
  std::unique_ptr<protocol::Authenticator> authenticator(
      underlying_->CreateAuthenticator(local_jid, remote_jid));
  return std::make_unique<PamAuthorizer>(std::move(authenticator));
}

}  // namespace remoting
