Index: src/platform/pam_offline/authenticator.cc |
diff --git a/src/platform/pam_offline/authenticator.cc b/src/platform/pam_offline/authenticator.cc |
deleted file mode 100644 |
index 66154fa0875221e667f05b2dce6ff213d32a8865..0000000000000000000000000000000000000000 |
--- a/src/platform/pam_offline/authenticator.cc |
+++ /dev/null |
@@ -1,210 +0,0 @@ |
-// Copyright (c) 2009-2010 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. |
- |
-#include "pam_offline/authenticator.h" |
- |
-#include <openssl/sha.h> |
-#include <openssl/evp.h> |
-#include <openssl/err.h> |
-#include <stdlib.h> |
-#include <unistd.h> |
- |
-#include "chromeos/utility.h" |
-#include "base/logging.h" |
- |
-namespace pam_offline { |
- |
-using std::string; |
- |
-// system salt and user dirs start here... |
-const string kDefaultShadowRoot = "/home/.shadow/"; |
- |
-// String that appears at the start of OpenSSL cipher text with embedded salt |
-const string kOpenSSLMagic = "Salted__"; |
- |
-Authenticator::Authenticator(const string &shadow_root) |
- : shadow_root_(shadow_root) |
-{} |
- |
-Authenticator::Authenticator() : shadow_root_(kDefaultShadowRoot) {} |
- |
-Authenticator::~Authenticator() {} |
- |
-bool Authenticator::Init() { |
- return LoadFileBytes(PathAppend(shadow_root_, "salt"), &system_salt_); |
-} |
- |
-Blob Authenticator::GetSystemSalt() const { |
- return system_salt_; |
-} |
- |
-// This is the analog to cryptohome::password_to_wrapper from the |
-// cryptohome script. It computes a SHA1(salt + str) and returns an |
-// ASCII encoded version of the result as a string. The hashing step is |
-// repeated |iters| number of times. |
-// |
-string Authenticator::IteratedWrapHashedPassword( |
- const string &master_salt_file, const string &hashed_password, |
- const int iters) const { |
- |
- string master_salt; |
- if (!LoadFileString(master_salt_file, &master_salt)) { |
- return false; |
- } |
- |
- Blob blob(hashed_password.begin(), hashed_password.end()); |
- |
- for (int i = 0; i < iters; ++i) { |
- SHA_CTX ctx; |
- unsigned char md_value[SHA_DIGEST_LENGTH]; |
- |
- SHA1_Init(&ctx); |
- SHA1_Update(&ctx, master_salt.c_str(), master_salt.length()); |
- SHA1_Update(&ctx, &blob.front(), blob.size()); |
- SHA1_Final(md_value, &ctx); |
- |
- blob.assign(md_value, md_value + SHA_DIGEST_LENGTH); |
- } |
- |
- return AsciiEncode(blob); |
-} |
- |
-string Authenticator::WrapHashedPassword( |
- const string &master_salt_file, const string &hashed_password) const { |
- return IteratedWrapHashedPassword(master_salt_file, hashed_password, 1); |
-} |
- |
-bool Authenticator::TestDecrypt(const string passphrase, |
- const Blob salt, |
- const Blob cipher_text) const { |
- if (salt.size() < PKCS5_SALT_LEN) { |
- LOG(ERROR) << "Invalid salt"; |
- return false; |
- } |
- |
- unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; |
- |
- int rv = EVP_BytesToKey( |
- EVP_aes_256_cbc(), EVP_sha1(), &salt.front(), |
- reinterpret_cast<const unsigned char *>(passphrase.c_str()), |
- passphrase.size(), 1, key, iv); |
- |
- if (rv != EVP_MAX_KEY_LENGTH) { |
- LOG(ERROR) << "Key size is " << rv << " bytes, should be " |
- << EVP_MAX_KEY_LENGTH; |
- return false; |
- } |
- |
- int pt_size = cipher_text.size(); |
- |
- unsigned char *plain_text = new unsigned char[pt_size]; |
- int final_size = 0; |
- |
- EVP_CIPHER_CTX d_ctx; |
- EVP_CIPHER_CTX_init(&d_ctx); |
- EVP_DecryptInit_ex(&d_ctx, EVP_aes_256_ecb(), NULL, key, iv); |
- rv = EVP_DecryptUpdate(&d_ctx, plain_text, &pt_size, |
- &cipher_text.front(), |
- cipher_text.size()); |
- |
- rv = EVP_DecryptFinal_ex(&d_ctx, plain_text + pt_size, &final_size); |
- |
- pt_size += final_size; |
- |
- chromeos::SecureMemset(plain_text, sizeof(plain_text), 0); |
- delete plain_text; |
- |
- if (rv != 1) { |
- unsigned long err = ERR_get_error(); |
- ERR_load_ERR_strings(); |
- ERR_load_crypto_strings(); |
- |
- LOG(INFO) << "OpenSSL Error: " << err |
- << ": " << ERR_lib_error_string(err) |
- << ", " << ERR_func_error_string(err) |
- << ", " << ERR_reason_error_string(err); |
- |
- return false; |
- } |
- |
- return true; |
-} |
- |
-bool Authenticator::TestOneMasterKey(const string &master_key_file, |
- const string &hashed_password) const { |
- if (system_salt_.empty()) { |
- LOG(ERROR) << "System salt not loaded."; |
- return false; |
- } |
- |
- Blob cipher_text; |
- if (!LoadFileBytes(master_key_file, &cipher_text)) { |
- LOG(ERROR) << "Error loading master key from '" << master_key_file << "'"; |
- return false; |
- } |
- |
- unsigned int header_size = kOpenSSLMagic.length() + PKCS5_SALT_LEN; |
- if (cipher_text.size() <= header_size) { |
- LOG(ERROR) << "Master key file too short: '" << master_key_file << "'"; |
- return false; |
- } |
- |
- string magic(cipher_text.begin(), |
- cipher_text.begin() + kOpenSSLMagic.length()); |
- if (magic != kOpenSSLMagic) { |
- LOG(ERROR) << "Invalid magic in master key file: '" << master_key_file |
- << "'"; |
- return false; |
- } |
- |
- Blob salt(cipher_text.begin() + kOpenSSLMagic.length(), |
- cipher_text.begin() + header_size); |
- |
- string passphrase = WrapHashedPassword(master_key_file + ".salt", |
- hashed_password); |
- |
- cipher_text.erase(cipher_text.begin(), cipher_text.begin() + header_size); |
- return TestDecrypt(passphrase, salt, cipher_text); |
-} |
- |
-bool Authenticator::TestAllMasterKeys(const Credentials &credentials) const { |
-#ifdef CHROMEOS_PAM_LOCALACCOUNT |
- if (credentials.IsLocalAccount()) { |
- LOG(WARNING) << "Logging in with local account credentials."; |
- return true; |
- } |
-#endif |
- |
- if (system_salt_.empty()) { |
- LOG(ERROR) << "System salt not loaded."; |
- return false; |
- } |
- |
- string user_path(PathAppend(shadow_root_, |
- credentials.GetObfuscatedUsername(system_salt_))); |
- string weak_hash(credentials.GetPasswordWeakHash(system_salt_)); |
- char index_str[5]; |
- |
- // Test against all of the master keys (master.0, master.1, ...) |
- for (int i = 0; /* loop forever */ ; ++i) { |
- string master_key_file(PathAppend(user_path, "master.")); |
- if (0 == snprintf(index_str, sizeof(index_str), "%i", i)) |
- return false; |
- master_key_file.append(index_str); |
- |
- if (0 != access(master_key_file.c_str(), R_OK)) { |
- // master.N can't be read, assume we're done and have failed |
- break; |
- } |
- |
- if (TestOneMasterKey(master_key_file, weak_hash)) { |
- // decrypted ok, return success |
- return true; |
- } |
- } |
- |
- return false; |
-} |
- |
-} // namespace pam_offline |