blob: 81a8f3c9313310e3b8298f2757e081982ea94f46 [file] [log] [blame]
// Copyright (c) 2011 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.
#include "login_manager/key_generator.h"
#include <sys/types.h>
#include <unistd.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <chromeos/cryptohome.h>
#include "login_manager/generator_job.h"
#include "login_manager/system_utils.h"
namespace login_manager {
using base::FilePath;
using std::string;
using std::vector;
// static
const char KeyGenerator::kTemporaryKeyFilename[] = "key.pub";
KeyGenerator::Delegate::~Delegate() {}
KeyGenerator::KeyGenerator(uid_t uid, SystemUtils *utils)
: uid_(uid),
utils_(utils),
delegate_(NULL),
factory_(new GeneratorJob::Factory),
generating_(false) {
}
KeyGenerator::~KeyGenerator() {}
bool KeyGenerator::Start(const string& username) {
DCHECK(!generating_) << "Must call Reset() between calls to Start()!";
base::FilePath user_path(chromeos::cryptohome::home::GetUserPath(username));
base::FilePath temporary_key_path(
user_path.AppendASCII(kTemporaryKeyFilename));
if (!base::DeleteFile(temporary_key_path, false)) {
PLOG(ERROR) << "Old keygen state still present; can't generate keys: ";
return false;
}
key_owner_username_ = username;
temporary_key_filename_ = temporary_key_path.value();
keygen_job_ = factory_->Create(temporary_key_filename_, user_path,
uid_, utils_);
if (!keygen_job_->RunInBackground())
return false;
pid_t pid = keygen_job_->CurrentPid();
if (pid < 0)
return false;
DLOG(INFO) << "Generating key at " << temporary_key_filename_
<< " using nssdb under " << user_path.value();
generating_ = true;
return true;
}
bool KeyGenerator::IsManagedJob(pid_t pid) {
return (keygen_job_ &&
keygen_job_->CurrentPid() > 0 &&
keygen_job_->CurrentPid() == pid);
}
void KeyGenerator::HandleExit(const siginfo_t& info) {
CHECK(delegate_) << "Must set a delegate before exit can be handled.";
if (info.si_status == 0) {
base::FilePath key_file(temporary_key_filename_);
delegate_->OnKeyGenerated(key_owner_username_, key_file);
} else {
DLOG(WARNING) << "Key generation failed with " << info.si_status;
}
Reset();
}
void KeyGenerator::RequestJobExit() {
if (keygen_job_ && keygen_job_->CurrentPid() > 0)
keygen_job_->Kill(SIGTERM, "");
}
void KeyGenerator::EnsureJobExit(base::TimeDelta timeout) {
if (keygen_job_ && keygen_job_->CurrentPid() > 0)
keygen_job_->WaitAndAbort(timeout);
}
void KeyGenerator::InjectJobFactory(
scoped_ptr<GeneratorJobFactoryInterface> factory) {
factory_ = factory.Pass();
}
void KeyGenerator::Reset() {
key_owner_username_.clear();
temporary_key_filename_.clear();
generating_ = false;
}
} // namespace login_manager