blob: 2a9158c39b01c2dcad6ce63b0579ea2f7ae2d918 [file] [log] [blame]
// 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 <brillo/secure_blob.h>
using base::FilePath;
using brillo::SecureBlob;
using std::string;
namespace chaps {
namespace {
const char kIsolateFilePath[] = "/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