blob: 03fda0630d5a7425f8b473634b1ea22ba53f8f0e [file] [log] [blame]
// Copyright 2016 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 <memory>
#include <base/at_exit.h>
#include <base/memory/ptr_util.h>
#include <base/sys_info.h>
#include <brillo/syslog_logging.h>
#include <brillo/daemons/dbus_daemon.h>
#include <install_attributes/libinstallattributes.h>
#include "authpolicy/authpolicy.h"
#include "authpolicy/constants.h"
#include "authpolicy/path_service.h"
#include "authpolicy/platform_helper.h"
namespace {
const char kObjectServicePath[] = "/org/chromium/AuthPolicy/ObjectManager";
const char kChromeOSReleaseTrack[] = "CHROMEOS_RELEASE_TRACK";
const char kBetaChannel[] = "beta-channel";
const char kStableChannel[] = "stable-channel";
const char kAuthPolicydUser[] = "authpolicyd";
const char kAuthPolicydExecUser[] = "authpolicyd-exec";
const int kExitCodeStartupFailure = 175; // This number is hex AF.
} // namespace
namespace authpolicy {
class Daemon : public brillo::DBusServiceDaemon {
public:
explicit Daemon(bool expect_config)
: DBusServiceDaemon(kAuthPolicyServiceName, kObjectServicePath),
expect_config_(expect_config) {}
protected:
void RegisterDBusObjectsAsync(AsyncEventSequencer* sequencer) override {
auth_policy_ = base::MakeUnique<AuthPolicy>(object_manager_.get());
auth_policy_->RegisterAsync(
sequencer->GetHandler("AuthPolicy.RegisterAsync() failed.", true));
std::unique_ptr<PathService> path_service = base::MakeUnique<PathService>();
ErrorType error =
auth_policy_->Initialize(std::move(path_service), expect_config_);
if (error != ERROR_NONE) {
LOG(ERROR) << "Failed to initialize SambaInterface. Error: " << error;
exit(kExitCodeStartupFailure);
}
}
void OnShutdown(int* return_code) override {
DBusServiceDaemon::OnShutdown(return_code);
auth_policy_.reset();
}
private:
bool expect_config_;
std::unique_ptr<AuthPolicy> auth_policy_;
DISALLOW_COPY_AND_ASSIGN(Daemon);
};
} // namespace authpolicy
int main(int argc, char* argv[]) {
brillo::OpenLog("authpolicyd", true);
brillo::InitLog(brillo::kLogToSyslog);
// Verify we're running as authpolicyd user.
uid_t authpolicyd_uid = authpolicy::GetUserId(kAuthPolicydUser);
if (authpolicyd_uid != authpolicy::GetEffectiveUserId()) {
LOG(ERROR) << "Failed to verify effective UID (must run as authpolicyd).";
exit(kExitCodeStartupFailure);
}
// Make it possible to switch to authpolicyd-exec without caps and drop caps.
uid_t authpolicyd_exec_uid = authpolicy::GetUserId(kAuthPolicydExecUser);
if (!authpolicy::SetSavedUserAndDropCaps(authpolicyd_exec_uid)) {
LOG(ERROR) << "Failed to establish user ids and drop caps.";
exit(kExitCodeStartupFailure);
}
// Disable on beta and stable (for now).
// TODO(ljusten): Reenable after launch reviews, see crbug.com/668119.
{
// base::SysInfo internally creates a singleton that adds itself to the
// current AtExitManager, so that it is destroyed when the manager goes out
// of scope. Daemon creates its own, so it has to be destroyed before the
// daemon is run.
base::AtExitManager at_exit_manager;
std::string channel;
if (!base::SysInfo::GetLsbReleaseValue(kChromeOSReleaseTrack, &channel)) {
LOG(ERROR) << "Failed to retrieve release track from sys info.";
exit(kExitCodeStartupFailure);
}
if (channel == kBetaChannel || channel == kStableChannel) {
LOG(ERROR) << "Not allowed to run on '" << kBetaChannel << "' and '"
<< kStableChannel << "'.";
exit(kExitCodeStartupFailure);
}
}
// Safety check to ensure that authpolicyd cannot run after the device has
// been locked to a mode other than enterprise_ad. (The lifetime management
// of authpolicyd happens through upstart, this check only serves as a second
// line of defense.)
bool expect_config = false;
InstallAttributesReader install_attributes_reader;
if (install_attributes_reader.IsLocked()) {
const std::string& mode =
install_attributes_reader.GetAttribute(
InstallAttributesReader::kAttrMode);
if (mode != InstallAttributesReader::kDeviceModeEnterpriseAD) {
LOG(ERROR) << "OOBE completed but device not in Active Directory "
"management mode.";
exit(kExitCodeStartupFailure);
} else {
LOG(INFO) << "Install attributes locked to Active Directory mode.";
// A configuration file should be present in this case.
expect_config = true;
}
} else {
LOG(INFO) << "No install attributes found.";
}
// Run daemon.
LOG(INFO) << "authpolicyd starting";
authpolicy::Daemon daemon(expect_config);
int res = daemon.Run();
LOG(INFO) << "authpolicyd stopping with exit code " << res;
return res;
}