• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
EnsureSystemSaltIsLoaded()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 
SanitizeUserName(const std::string & username)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 
GetUserPathPrefix()80 FilePath GetUserPathPrefix() {
81   return FilePath(g_user_home_prefix);
82 }
83 
GetRootPathPrefix()84 FilePath GetRootPathPrefix() {
85   return FilePath(g_root_home_prefix);
86 }
87 
GetHashedUserPath(const std::string & hashed_username)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 
GetUserPath(const std::string & username)93 FilePath GetUserPath(const std::string& username) {
94   if (!EnsureSystemSaltIsLoaded())
95     return FilePath("");
96   return GetHashedUserPath(SanitizeUserName(username));
97 }
98 
GetRootPath(const std::string & username)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 
GetDaemonPath(const std::string & username,const std::string & daemon)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 
IsSanitizedUserName(const std::string & sanitized)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 
SetUserHomePrefix(const std::string & prefix)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 
SetRootHomePrefix(const std::string & prefix)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 
GetSystemSalt()132 std::string* GetSystemSalt() {
133   return salt;
134 }
135 
SetSystemSalt(std::string * value)136 void SetSystemSalt(std::string* value) {
137   salt = value;
138 }
139 
140 }  // namespace home
141 }  // namespace cryptohome
142 }  // namespace brillo
143