blob: 968e6513067fdd0f1948e07a7cab8ef9fffe44f7 [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/check.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/memory/weak_ptr.h>
#include <brillo/daemons/dbus_daemon.h>
#include <brillo/syslog_logging.h>
#include <brillo/userdb_utils.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 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 device_is_locked)
: DBusServiceDaemon(kAuthPolicyServiceName, kObjectServicePath),
device_is_locked_(device_is_locked),
weak_ptr_factory_(this) {}
Daemon(const Daemon&) = delete;
Daemon& operator=(const Daemon&) = delete;
// Cleans the authpolicy daemon state directory. Returns true if all files
// were cleared.
static bool CleanState() {
PathService path_service;
return AuthPolicy::CleanState(&path_service);
}
protected:
void RegisterDBusObjectsAsync(
brillo::dbus_utils::AsyncEventSequencer* sequencer) override {
brillo::dbus_utils::AsyncEventSequencer::Handler handler =
sequencer->GetHandler("AuthPolicy.RegisterAsync() failed.", true);
authpolicy_.RegisterAsync(
AuthPolicy::GetDBusObject(object_manager_.get()),
base::Bind(&Daemon::OnAuthPolicyRegistered,
weak_ptr_factory_.GetWeakPtr(), handler));
}
private:
void OnAuthPolicyRegistered(
const brillo::dbus_utils::AsyncEventSequencer::Handler& handler,
bool success) {
// If it wasn't successful, the sequencer handler should print an error and
// exit.
handler.Run(success);
CHECK(success);
LOG(INFO) << "authpolicyd started";
// Initialize authpolicy here, so that stuff like the machine password check
// happens after the daemon is registered.
ErrorType error = authpolicy_.Initialize(device_is_locked_);
if (error != ERROR_NONE) {
LOG(ERROR) << "SambaInterface failed to initialize with error code "
<< error;
exit(kExitCodeStartupFailure);
}
}
bool device_is_locked_;
// Keep this order! |authpolicy_| must be last as it depends on the other two.
AuthPolicyMetrics metrics_;
PathService path_service_;
AuthPolicy authpolicy_{&metrics_, &path_service_};
base::WeakPtrFactory<Daemon> weak_ptr_factory_;
};
} // 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;
CHECK(
brillo::userdb::GetUserInfo(kAuthPolicydUser, &authpolicyd_uid, nullptr));
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;
CHECK(brillo::userdb::GetUserInfo(kAuthPolicydExecUser, &authpolicyd_exec_uid,
nullptr));
if (!authpolicy::SetSavedUserAndDropCaps(authpolicyd_exec_uid)) {
LOG(ERROR) << "Failed to establish user ids and drop caps.";
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 device_is_locked = 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. Cleaning state and exiting.";
CHECK(authpolicy::Daemon::CleanState());
exit(kExitCodeStartupFailure);
} else {
LOG(INFO) << "Install attributes locked to Active Directory mode.";
// A configuration file should be present in this case.
device_is_locked = true;
}
} else {
LOG(INFO) << "No install attributes found. Cleaning state.";
CHECK(authpolicy::Daemon::CleanState());
}
// Run daemon.
LOG(INFO) << "authpolicyd starting";
authpolicy::Daemon daemon(device_is_locked);
int res = daemon.Run();
LOG(INFO) << "authpolicyd stopping with exit code " << res;
return res;
}