Home | History | Annotate | Download | only in brillo
      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 // Path to user homes mounted with the mount_hidden option. The user home mount
     28 // will be located at:
     29 // kHiddenUserHomeBaseDir/<sanitized_user_name>/kHiddenUserHomeMountSubdir
     30 const char kHiddenUserHomeBaseDir[] = "/home/.shadow";
     31 const char kHiddenUserHomeMountSubdir[] = "mount";
     32 
     33 // Subdirectory of a user home mount where daemon-specific data is stored.
     34 // This is used to assemble daemon data storage paths for hidden user home
     35 // mounts.
     36 const char kHiddenUserHomeRootSubdir[] = "root";
     37 
     38 static char g_user_home_prefix[PATH_MAX] = "/home/user/";
     39 static char g_root_home_prefix[PATH_MAX] = "/home/root/";
     40 static char g_system_salt_path[PATH_MAX] = "/home/.shadow/salt";
     41 
     42 static std::string* salt = nullptr;
     43 
     44 static bool EnsureSystemSaltIsLoaded() {
     45   if (salt && !salt->empty())
     46     return true;
     47   FilePath salt_path(g_system_salt_path);
     48   int64_t file_size;
     49   if (!base::GetFileSize(salt_path, &file_size)) {
     50     PLOG(ERROR) << "Could not get size of system salt: " << g_system_salt_path;
     51     return false;
     52   }
     53   if (file_size > static_cast<int64_t>(std::numeric_limits<int>::max())) {
     54     LOG(ERROR) << "System salt too large: " << file_size;
     55     return false;
     56   }
     57   std::vector<char> buf;
     58   buf.resize(file_size);
     59   unsigned int data_read = base::ReadFile(salt_path, buf.data(), file_size);
     60   if (data_read != file_size) {
     61     PLOG(ERROR) << "Could not read entire file: " << data_read
     62                 << " != " << file_size;
     63     return false;
     64   }
     65 
     66   if (!salt)
     67     salt = new std::string();
     68   salt->assign(buf.data(), file_size);
     69   return true;
     70 }
     71 
     72 std::string SanitizeUserName(const std::string& username) {
     73   if (!EnsureSystemSaltIsLoaded())
     74     return std::string();
     75 
     76   unsigned char binmd[SHA_DIGEST_LENGTH];
     77   std::string lowercase(username);
     78   std::transform(
     79       lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower);
     80   SHA_CTX ctx;
     81   SHA1_Init(&ctx);
     82   SHA1_Update(&ctx, salt->data(), salt->size());
     83   SHA1_Update(&ctx, lowercase.data(), lowercase.size());
     84   SHA1_Final(binmd, &ctx);
     85   std::string final = base::HexEncode(binmd, sizeof(binmd));
     86   // Stay compatible with CryptoLib::HexEncodeToBuffer()
     87   std::transform(final.begin(), final.end(), final.begin(), ::tolower);
     88   return final;
     89 }
     90 
     91 FilePath GetUserPathPrefix() {
     92   return FilePath(g_user_home_prefix);
     93 }
     94 
     95 FilePath GetRootPathPrefix() {
     96   return FilePath(g_root_home_prefix);
     97 }
     98 
     99 FilePath GetHashedUserPath(const std::string& hashed_username) {
    100   return FilePath(
    101       base::StringPrintf("%s%s", g_user_home_prefix, hashed_username.c_str()));
    102 }
    103 
    104 FilePath GetUserPath(const std::string& username) {
    105   if (!EnsureSystemSaltIsLoaded())
    106     return FilePath();
    107   return GetHashedUserPath(SanitizeUserName(username));
    108 }
    109 
    110 FilePath GetRootPath(const std::string& username) {
    111   if (!EnsureSystemSaltIsLoaded())
    112     return FilePath();
    113   return FilePath(base::StringPrintf(
    114       "%s%s", g_root_home_prefix, SanitizeUserName(username).c_str()));
    115 }
    116 
    117 FilePath GetDaemonPath(const std::string& username, const std::string& daemon) {
    118   if (!EnsureSystemSaltIsLoaded())
    119     return FilePath();
    120   return GetRootPath(username).Append(daemon);
    121 }
    122 
    123 FilePath GetDaemonPathForHiddenUserHome(const std::string& username,
    124                                         const std::string& daemon) {
    125   if (!EnsureSystemSaltIsLoaded())
    126     return FilePath();
    127 
    128   return FilePath(kHiddenUserHomeBaseDir)
    129       .Append(SanitizeUserName(username))
    130       .Append(kHiddenUserHomeMountSubdir)
    131       .Append(kHiddenUserHomeRootSubdir)
    132       .Append(daemon);
    133 }
    134 
    135 bool IsSanitizedUserName(const std::string& sanitized) {
    136   std::vector<uint8_t> bytes;
    137   return (sanitized.length() == 2 * SHA_DIGEST_LENGTH) &&
    138          base::HexStringToBytes(sanitized, &bytes);
    139 }
    140 
    141 void SetUserHomePrefix(const std::string& prefix) {
    142   if (prefix.length() < sizeof(g_user_home_prefix)) {
    143     snprintf(
    144         g_user_home_prefix, sizeof(g_user_home_prefix), "%s", prefix.c_str());
    145   }
    146 }
    147 
    148 void SetRootHomePrefix(const std::string& prefix) {
    149   if (prefix.length() < sizeof(g_root_home_prefix)) {
    150     snprintf(
    151         g_root_home_prefix, sizeof(g_root_home_prefix), "%s", prefix.c_str());
    152   }
    153 }
    154 
    155 std::string* GetSystemSalt() {
    156   return salt;
    157 }
    158 
    159 void SetSystemSalt(std::string* value) {
    160   salt = value;
    161 }
    162 
    163 }  // namespace home
    164 }  // namespace cryptohome
    165 }  // namespace brillo
    166