| // Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This provides some utility functions to do with chaps isolate support. |
| |
| #include "chaps/isolate.h" |
| |
| #include <grp.h> |
| #include <pwd.h> |
| |
| #include <string> |
| |
| #include <base/files/file_path.h> |
| #include <base/files/file_util.h> |
| #include <chromeos/secure_blob.h> |
| |
| using std::string; |
| using base::FilePath; |
| using chromeos::SecureBlob; |
| |
| namespace chaps { |
| |
| namespace { |
| |
| const FilePath::CharType kIsolateFilePath[] = |
| FILE_PATH_LITERAL("/var/lib/chaps/isolates/"); |
| |
| } // namespace |
| |
| IsolateCredentialManager::IsolateCredentialManager() { } |
| |
| IsolateCredentialManager::~IsolateCredentialManager() { } |
| |
| bool IsolateCredentialManager::GetCurrentUserIsolateCredential( |
| SecureBlob* isolate_credential) { |
| CHECK(isolate_credential); |
| |
| const uid_t uid = getuid(); |
| long buf_len = sysconf(_SC_GETPW_R_SIZE_MAX); // NOLINT(runtime/int) |
| if (buf_len < 0) |
| buf_len = 4096; |
| passwd pwd_buf; |
| passwd* pwd = nullptr; |
| std::vector<char> buf(buf_len); |
| if (getpwuid_r(uid, &pwd_buf, buf.data(), buf_len, &pwd) || !pwd) { |
| PLOG(ERROR) << "Failed to get user information for current user."; |
| return false; |
| } |
| |
| return GetUserIsolateCredential(pwd->pw_name, isolate_credential); |
| } |
| |
| bool IsolateCredentialManager::GetUserIsolateCredential( |
| const string& user, |
| SecureBlob* isolate_credential) { |
| CHECK(isolate_credential); |
| |
| string credential_string; |
| const FilePath credential_file = FilePath(kIsolateFilePath).Append(user); |
| if (!base::PathExists(credential_file) || |
| !base::ReadFileToString(credential_file, &credential_string)) { |
| LOG(INFO) << "Failed to find or read isolate credential for user " |
| << user; |
| return false; |
| } |
| const SecureBlob new_isolate_credential(credential_string); |
| if (new_isolate_credential.size() != kIsolateCredentialBytes) { |
| LOG(ERROR) << "Isolate credential invalid for user " << user; |
| return false; |
| } |
| |
| *isolate_credential = new_isolate_credential; |
| return true; |
| } |
| |
| bool IsolateCredentialManager::SaveIsolateCredential( |
| const string& user, |
| const SecureBlob& isolate_credential) { |
| CHECK_EQ(kIsolateCredentialBytes, isolate_credential.size()); |
| |
| // Look up user information. |
| long buf_len = sysconf(_SC_GETPW_R_SIZE_MAX); // NOLINT(runtime/int) |
| if (buf_len < 0) |
| buf_len = 4096; |
| passwd pwd_buf; |
| passwd* pwd = nullptr; |
| std::vector<char> buf(buf_len); |
| if (getpwnam_r(user.c_str(), &pwd_buf, buf.data(), buf_len, &pwd) || !pwd) { |
| LOG(ERROR) << "Failed to get user information."; |
| return false; |
| } |
| |
| // Write the isolate credential file. |
| const FilePath isolate_cred_file = FilePath(kIsolateFilePath).Append(user); |
| int bytes_written = base::WriteFile( |
| isolate_cred_file, |
| reinterpret_cast<const char *>(isolate_credential.data()), |
| kIsolateCredentialBytes); |
| if (bytes_written != static_cast<int>(kIsolateCredentialBytes)) { |
| LOG(ERROR) << "Failed to create isolate file for user " << user; |
| return false; |
| } |
| |
| // Change permissions to be readable by (and only by) the user. |
| if (chmod(isolate_cred_file.value().c_str(), S_IRUSR)) { |
| LOG(ERROR) << "Failed to change permissions of isolate file."; |
| return false; |
| } |
| if (chown(isolate_cred_file.value().c_str(), pwd->pw_uid, pwd->pw_gid)) { |
| LOG(ERROR) << "Failed to change ownership of isolate file."; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| } // namespace chaps |