| // Copyright (c) 2012 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 "brillo/cryptohome.h" |
| |
| #include <openssl/sha.h> |
| #include <stdint.h> |
| |
| #include <algorithm> |
| #include <cstring> |
| #include <limits> |
| #include <vector> |
| |
| #include <base/files/file_util.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <base/strings/stringprintf.h> |
| |
| using base::FilePath; |
| |
| namespace brillo { |
| namespace cryptohome { |
| namespace home { |
| |
| const char kGuestUserName[] = "$guest"; |
| |
| static char g_user_home_prefix[PATH_MAX] = "/home/user/"; |
| static char g_root_home_prefix[PATH_MAX] = "/home/root/"; |
| static char g_system_salt_path[PATH_MAX] = "/home/.shadow/salt"; |
| |
| static std::string* salt = nullptr; |
| |
| static bool EnsureSystemSaltIsLoaded() { |
| if (salt && !salt->empty()) |
| return true; |
| FilePath salt_path(g_system_salt_path); |
| int64_t file_size; |
| if (!base::GetFileSize(salt_path, &file_size)) { |
| PLOG(ERROR) << "Could not get size of system salt: " << g_system_salt_path; |
| return false; |
| } |
| if (file_size > static_cast<int64_t>(std::numeric_limits<int>::max())) { |
| LOG(ERROR) << "System salt too large: " << file_size; |
| return false; |
| } |
| std::vector<char> buf; |
| buf.resize(file_size); |
| unsigned int data_read = base::ReadFile(salt_path, buf.data(), file_size); |
| if (data_read != file_size) { |
| PLOG(ERROR) << "Could not read entire file: " << data_read |
| << " != " << file_size; |
| return false; |
| } |
| |
| if (!salt) |
| salt = new std::string(); |
| salt->assign(buf.data(), file_size); |
| return true; |
| } |
| |
| std::string SanitizeUserName(const std::string& username) { |
| if (!EnsureSystemSaltIsLoaded()) |
| return std::string(); |
| |
| unsigned char binmd[SHA_DIGEST_LENGTH]; |
| std::string lowercase(username); |
| std::transform( |
| lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower); |
| SHA_CTX ctx; |
| SHA1_Init(&ctx); |
| SHA1_Update(&ctx, salt->data(), salt->size()); |
| SHA1_Update(&ctx, lowercase.data(), lowercase.size()); |
| SHA1_Final(binmd, &ctx); |
| std::string final = base::HexEncode(binmd, sizeof(binmd)); |
| // Stay compatible with CryptoLib::HexEncodeToBuffer() |
| std::transform(final.begin(), final.end(), final.begin(), ::tolower); |
| return final; |
| } |
| |
| FilePath GetUserPathPrefix() { |
| return FilePath(g_user_home_prefix); |
| } |
| |
| FilePath GetRootPathPrefix() { |
| return FilePath(g_root_home_prefix); |
| } |
| |
| FilePath GetHashedUserPath(const std::string& hashed_username) { |
| return FilePath( |
| base::StringPrintf("%s%s", g_user_home_prefix, hashed_username.c_str())); |
| } |
| |
| FilePath GetUserPath(const std::string& username) { |
| if (!EnsureSystemSaltIsLoaded()) |
| return FilePath(""); |
| return GetHashedUserPath(SanitizeUserName(username)); |
| } |
| |
| FilePath GetRootPath(const std::string& username) { |
| if (!EnsureSystemSaltIsLoaded()) |
| return FilePath(""); |
| return FilePath(base::StringPrintf( |
| "%s%s", g_root_home_prefix, SanitizeUserName(username).c_str())); |
| } |
| |
| FilePath GetDaemonPath(const std::string& username, const std::string& daemon) { |
| if (!EnsureSystemSaltIsLoaded()) |
| return FilePath(""); |
| return GetRootPath(username).Append(daemon); |
| } |
| |
| bool IsSanitizedUserName(const std::string& sanitized) { |
| std::vector<uint8_t> bytes; |
| return (sanitized.length() == 2 * SHA_DIGEST_LENGTH) && |
| base::HexStringToBytes(sanitized, &bytes); |
| } |
| |
| void SetUserHomePrefix(const std::string& prefix) { |
| if (prefix.length() < sizeof(g_user_home_prefix)) { |
| snprintf( |
| g_user_home_prefix, sizeof(g_user_home_prefix), "%s", prefix.c_str()); |
| } |
| } |
| |
| void SetRootHomePrefix(const std::string& prefix) { |
| if (prefix.length() < sizeof(g_root_home_prefix)) { |
| snprintf( |
| g_root_home_prefix, sizeof(g_root_home_prefix), "%s", prefix.c_str()); |
| } |
| } |
| |
| std::string* GetSystemSalt() { |
| return salt; |
| } |
| |
| void SetSystemSalt(std::string* value) { |
| salt = value; |
| } |
| |
| } // namespace home |
| } // namespace cryptohome |
| } // namespace brillo |