// 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 <brillo/secure_blob.h>
#include <openssl/evp.h>
#include <openssl/rand.h>

#include "chaps/chaps_utility.h"

using std::string;
using base::FilePath;
using brillo::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.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(auth_data.char_data(),
                             auth_data.size(),
                             salt.data(),
                             kSaltBytes,
                             kSaltIterations,
                             EVP_sha512(),
                             kSaltedKeyBytes,
                             out_key.data())) {
    LOG(ERROR) << "Could not salt authorization data.";
    return false;
  }

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

}  // namespace chaps
