1// Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "brillo/cryptohome.h" 6 7#include <openssl/sha.h> 8#include <stdint.h> 9 10#include <algorithm> 11#include <cstring> 12#include <limits> 13#include <vector> 14 15#include <base/files/file_util.h> 16#include <base/strings/string_number_conversions.h> 17#include <base/strings/stringprintf.h> 18 19using base::FilePath; 20 21namespace brillo { 22namespace cryptohome { 23namespace home { 24 25const char kGuestUserName[] = "$guest"; 26 27static char g_user_home_prefix[PATH_MAX] = "/home/user/"; 28static char g_root_home_prefix[PATH_MAX] = "/home/root/"; 29static char g_system_salt_path[PATH_MAX] = "/home/.shadow/salt"; 30 31static std::string* salt = nullptr; 32 33static bool EnsureSystemSaltIsLoaded() { 34 if (salt && !salt->empty()) 35 return true; 36 FilePath salt_path(g_system_salt_path); 37 int64_t file_size; 38 if (!base::GetFileSize(salt_path, &file_size)) { 39 PLOG(ERROR) << "Could not get size of system salt: " << g_system_salt_path; 40 return false; 41 } 42 if (file_size > static_cast<int64_t>(std::numeric_limits<int>::max())) { 43 LOG(ERROR) << "System salt too large: " << file_size; 44 return false; 45 } 46 std::vector<char> buf; 47 buf.resize(file_size); 48 unsigned int data_read = base::ReadFile(salt_path, buf.data(), file_size); 49 if (data_read != file_size) { 50 PLOG(ERROR) << "Could not read entire file: " << data_read 51 << " != " << file_size; 52 return false; 53 } 54 55 if (!salt) 56 salt = new std::string(); 57 salt->assign(buf.data(), file_size); 58 return true; 59} 60 61std::string SanitizeUserName(const std::string& username) { 62 if (!EnsureSystemSaltIsLoaded()) 63 return std::string(); 64 65 unsigned char binmd[SHA_DIGEST_LENGTH]; 66 std::string lowercase(username); 67 std::transform( 68 lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower); 69 SHA_CTX ctx; 70 SHA1_Init(&ctx); 71 SHA1_Update(&ctx, salt->data(), salt->size()); 72 SHA1_Update(&ctx, lowercase.data(), lowercase.size()); 73 SHA1_Final(binmd, &ctx); 74 std::string final = base::HexEncode(binmd, sizeof(binmd)); 75 // Stay compatible with CryptoLib::HexEncodeToBuffer() 76 std::transform(final.begin(), final.end(), final.begin(), ::tolower); 77 return final; 78} 79 80FilePath GetUserPathPrefix() { 81 return FilePath(g_user_home_prefix); 82} 83 84FilePath GetRootPathPrefix() { 85 return FilePath(g_root_home_prefix); 86} 87 88FilePath GetHashedUserPath(const std::string& hashed_username) { 89 return FilePath( 90 base::StringPrintf("%s%s", g_user_home_prefix, hashed_username.c_str())); 91} 92 93FilePath GetUserPath(const std::string& username) { 94 if (!EnsureSystemSaltIsLoaded()) 95 return FilePath(""); 96 return GetHashedUserPath(SanitizeUserName(username)); 97} 98 99FilePath GetRootPath(const std::string& username) { 100 if (!EnsureSystemSaltIsLoaded()) 101 return FilePath(""); 102 return FilePath(base::StringPrintf( 103 "%s%s", g_root_home_prefix, SanitizeUserName(username).c_str())); 104} 105 106FilePath GetDaemonPath(const std::string& username, const std::string& daemon) { 107 if (!EnsureSystemSaltIsLoaded()) 108 return FilePath(""); 109 return GetRootPath(username).Append(daemon); 110} 111 112bool IsSanitizedUserName(const std::string& sanitized) { 113 std::vector<uint8_t> bytes; 114 return (sanitized.length() == 2 * SHA_DIGEST_LENGTH) && 115 base::HexStringToBytes(sanitized, &bytes); 116} 117 118void SetUserHomePrefix(const std::string& prefix) { 119 if (prefix.length() < sizeof(g_user_home_prefix)) { 120 snprintf( 121 g_user_home_prefix, sizeof(g_user_home_prefix), "%s", prefix.c_str()); 122 } 123} 124 125void SetRootHomePrefix(const std::string& prefix) { 126 if (prefix.length() < sizeof(g_root_home_prefix)) { 127 snprintf( 128 g_root_home_prefix, sizeof(g_root_home_prefix), "%s", prefix.c_str()); 129 } 130} 131 132std::string* GetSystemSalt() { 133 return salt; 134} 135 136void SetSystemSalt(std::string* value) { 137 salt = value; 138} 139 140} // namespace home 141} // namespace cryptohome 142} // namespace brillo 143