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 19 using base::FilePath; 20 21 namespace brillo { 22 namespace cryptohome { 23 namespace home { 24 25 const char kGuestUserName[] = "$guest"; 26 27 static char g_user_home_prefix[PATH_MAX] = "/home/user/"; 28 static char g_root_home_prefix[PATH_MAX] = "/home/root/"; 29 static char g_system_salt_path[PATH_MAX] = "/home/.shadow/salt"; 30 31 static std::string* salt = nullptr; 32 33 static 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 61 std::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 80 FilePath GetUserPathPrefix() { 81 return FilePath(g_user_home_prefix); 82 } 83 84 FilePath GetRootPathPrefix() { 85 return FilePath(g_root_home_prefix); 86 } 87 88 FilePath GetHashedUserPath(const std::string& hashed_username) { 89 return FilePath( 90 base::StringPrintf("%s%s", g_user_home_prefix, hashed_username.c_str())); 91 } 92 93 FilePath GetUserPath(const std::string& username) { 94 if (!EnsureSystemSaltIsLoaded()) 95 return FilePath(""); 96 return GetHashedUserPath(SanitizeUserName(username)); 97 } 98 99 FilePath 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 106 FilePath GetDaemonPath(const std::string& username, const std::string& daemon) { 107 if (!EnsureSystemSaltIsLoaded()) 108 return FilePath(""); 109 return GetRootPath(username).Append(daemon); 110 } 111 112 bool 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 118 void 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 125 void 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 132 std::string* GetSystemSalt() { 133 return salt; 134 } 135 136 void SetSystemSalt(std::string* value) { 137 salt = value; 138 } 139 140 } // namespace home 141 } // namespace cryptohome 142 } // namespace brillo 143