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

// A helper which provides methods to extract data from a pam_handle.

#include "chaps/pam_helper.h"

#include <security/pam_appl.h>
#include <security/pam_modules.h>

#include <vector>

#include <base/logging.h>
#include <chromeos/secure_blob.h>

#include "chaps/chaps_utility.h"

using std::string;
using std::vector;
using chromeos::SecureBlob;

namespace chaps {

namespace {

const char* kUserKey = "chaps_user_key";
const char* kPasswordKey = "chaps_password_key";

static void FreeUser(pam_handle_t *pam_handle, void *data,
                     int error_status) {
  if (data != NULL) {
    string* user = reinterpret_cast<string*>(data);
    delete user;
  }
}

static void FreePassword(pam_handle_t *pam_handle, void *data,
                         int error_status) {
  if (data != NULL) {
    SecureBlob* password = reinterpret_cast<SecureBlob*>(data);
    password->clear();
    delete password;
  }
}

}  // namespace

PamHelper::~PamHelper() { }

bool PamHelper::GetPamUser(pam_handle_t* pam_handle, string* user) {
  const char* user_raw;
  int result;

  result = pam_get_user(pam_handle, &user_raw, NULL);
  if (result != PAM_SUCCESS) {
    LOG(ERROR) << "Could not get the pam user name: "
               << pam_strerror(pam_handle, result);
    return false;
  }

  *user = string(user_raw);
  // Note: user_raw is the actual data, so should not be overwritten or freed.
  return true;
}

bool PamHelper::GetPamPassword(pam_handle_t* pam_handle,
                               bool old_password,
                               SecureBlob* data) {
  const char* data_raw;
  int result;
  int pam_item_type;

  pam_item_type = old_password ? PAM_OLDAUTHTOK : PAM_AUTHTOK;

  result = pam_get_item(pam_handle, pam_item_type,
                        reinterpret_cast<const void **>(&data_raw));
  if (result != PAM_SUCCESS || data_raw == NULL) {
    // TODO(rmcilroy): Prompt for password if possible.
    LOG(WARNING) << "Could not get pam password: "
                 << pam_strerror(pam_handle, result);
    return false;
  }

  string data_string(data_raw, strlen(data_raw));
  SecureBlob tmp(data_string);
  data->swap(tmp);

  // Note: data_raw is the actual data, so should not be overwritten or freed.
  return true;
}

bool PamHelper::SaveUserAndPassword(pam_handle_t* pam_handle,
                                    const string& user,
                                    const SecureBlob& password) {
  void* user_data = new string(user);
  if (pam_set_data(pam_handle, kUserKey, user_data, FreeUser) != PAM_SUCCESS) {
    LOG(ERROR) << "Could not save user name in PAM handle";
    return false;
  }

  void* password_data = new SecureBlob(password);
  if (pam_set_data(pam_handle, kPasswordKey, password_data, FreePassword) !=
      PAM_SUCCESS) {
    LOG(ERROR) << "Could not save password in PAM handle";
    return false;
  }

  return true;
}

bool PamHelper::RetrieveUserAndPassword(pam_handle_t* pam_handle,
                                        string* user,
                                        SecureBlob* password) {
  CHECK(user);
  CHECK(password);

  const void* user_data;
  if (pam_get_data(pam_handle, kUserKey, &user_data) != PAM_SUCCESS) {
    VLOG(1) << "Could not retrieve user name from PAM handle";
    return false;
  }
  *user = *reinterpret_cast<const string*>(user_data);

  const void* password_data;
  if (pam_get_data(pam_handle, kPasswordKey, &password_data) != PAM_SUCCESS) {
    LOG(INFO) << "Could not retrieve password from PAM handle";
    return false;
  }
  SecureBlob tmp(*reinterpret_cast<const SecureBlob*>(password_data));
  password->swap(tmp);

  return true;
}

bool PamHelper::PutEnvironmentVariable(pam_handle_t* pam_handle,
                                       const string& name,
                                       const string& value) {
  string env_var = name + "=" + value;
  return pam_putenv(pam_handle, env_var.c_str()) == PAM_SUCCESS;
}

bool PamHelper::GetEnvironmentVariable(pam_handle_t* pam_handle,
                                       const string& name,
                                       string* value) {
  CHECK(value);
  const char* value_raw = pam_getenv(pam_handle, name.c_str());
  if (value_raw == NULL || value_raw[0] == '\0')
    return false;
  *value = string(value_raw);
  return true;
}

}  // namespace chaps
