// 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 token manager provides a set of methods for login agents to create and
// validate token files.

#include "chaps/token_file_manager.h"

#include <grp.h>
#include <pwd.h>
#include <sys/stat.h>

#include <string>

#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <chromeos/secure_blob.h>
#include <openssl/evp.h>
#include <openssl/rand.h>

#include "chaps/chaps_utility.h"

using std::string;
using base::FilePath;
using chromeos::SecureBlob;

namespace chaps {

namespace {

const FilePath::CharType kTokenFilePath[] =
    FILE_PATH_LITERAL("/var/lib/chaps/tokens/");

const mode_t kTokenDirectoryPermissions = (S_IRUSR | S_IWUSR | S_IXUSR);
const mode_t kFilePermissionsMask = (S_IRWXU | S_IRWXG | S_IRWXO);

const FilePath::CharType kSaltFileName[] = "salt";
const uint32_t kSaltIterations = 4096;
const size_t kSaltBytes = 32;
const size_t kSaltedKeyBytes = 32;

}  // namespace

TokenFileManager::TokenFileManager(uid_t chapsd_uid, gid_t chapsd_gid)
    : chapsd_uid_(chapsd_uid),
      chapsd_gid_(chapsd_gid) { }

TokenFileManager::~TokenFileManager() { }

bool TokenFileManager::GetUserTokenPath(const string& user,
                                        FilePath* token_path) {
  CHECK(token_path);
  *token_path = FilePath(kTokenFilePath).Append(user);
  return base::DirectoryExists(*token_path);
}

bool TokenFileManager::CreateUserTokenDirectory(const FilePath& token_path) {
  if (base::DirectoryExists(token_path)) {
    LOG(ERROR) << "Tried to create " << token_path.value()
               << " which already exists";
    return false;
  }
  if (!base::CreateDirectory(token_path)) {
    LOG(ERROR) << "Failed to create " << token_path.value();
    return false;
  }

  // Change permissions to be readable and writable only by user chaps.
  if (chmod(token_path.value().c_str(), kTokenDirectoryPermissions)) {
    LOG(ERROR) << "Failed to change permissions of token directory "
               << token_path.value();
    return false;
  }
  if (chown(token_path.value().c_str(), chapsd_uid_, chapsd_gid_)) {
    LOG(ERROR) << "Failed to change ownership of token directory "
               << token_path.value();
    return false;
  }

  // Create random salt file.
  string salt_string;
  salt_string.resize(kSaltBytes);
  if (1 != RAND_bytes(ConvertStringToByteBuffer(salt_string.data()),
                      kSaltBytes)) {
    LOG(ERROR) << "Failed to generate random salt for token directory "
               << token_path.value();
    return false;
  }
  SecureBlob salt(salt_string);
  ClearString(&salt_string);

  FilePath salt_file = token_path.Append(kSaltFileName);
  int bytes_written = base::WriteFile(
      salt_file, reinterpret_cast<const char*>(salt.const_data()), kSaltBytes);
  if (bytes_written != static_cast<int>(kSaltBytes)) {
    LOG(ERROR) << "Failed to write salt file in token directory "
               << token_path.value();
    return false;
  }

  return true;
}

bool TokenFileManager::CheckUserTokenPermissions(const FilePath& token_path) {
  struct stat token_stat;
  if (stat(token_path.value().c_str(), &token_stat)) {
    LOG(ERROR) << "Failed to stat token directory " << token_path.value();
    return false;
  }
  if ((token_stat.st_mode & kFilePermissionsMask) !=
      kTokenDirectoryPermissions) {
    LOG(ERROR) << "Incorrect permissions on token directory "
               << token_path.value();
    return false;
  }
  if (token_stat.st_uid != chapsd_uid_) {
    LOG(ERROR) << "Incorrect owner for token directory " << token_path.value();
    return false;
  }
  if (token_stat.st_gid != chapsd_gid_) {
    LOG(ERROR) << "Incorrect group for token directory " << token_path.value();
    return false;
  }
  return true;
}

bool TokenFileManager::SaltAuthData(const FilePath& token_path,
                                    const SecureBlob& auth_data,
                                    SecureBlob* salted_auth_data) {
  string salt_string;
  FilePath salt_file = token_path.Append(kSaltFileName);
  if (!base::ReadFileToString(salt_file, &salt_string)) {
    LOG(ERROR) << "Failed to read salt file in token directory "
               << token_path.value();
    return false;
  }
  SecureBlob salt(salt_string);
  ClearString(&salt_string);
  if (salt.size() != kSaltBytes) {
    LOG(ERROR) << "Salt invalid for token directory " << token_path.value();
    return false;
  }

  SecureBlob out_key(kSaltedKeyBytes);
  if (1 != PKCS5_PBKDF2_HMAC(
               reinterpret_cast<const char *>(auth_data.const_data()),
               auth_data.size(),
               reinterpret_cast<const unsigned char *>(salt.const_data()),
               kSaltBytes,
               kSaltIterations,
               EVP_sha512(),
               kSaltedKeyBytes,
               reinterpret_cast<unsigned char *>(out_key.data()))) {
    LOG(ERROR) << "Could not salt authorization data.";
    return false;
  }

  salted_auth_data->swap(out_key);
  return true;
}

}  // namespace chaps
