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 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