blob: c888a8cadfc103a024a3598f094e5cefbb5c6fdf [file] [log] [blame]
// Copyright 2020 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 "arc/keymaster/context/context_adaptor.h"
#include <memory>
#include <base/logging.h>
#include <brillo/dbus/dbus_object.h>
#include <chromeos/dbus/service_constants.h>
#include <dbus/object_proxy.h>
#include <session_manager/dbus-proxies.h>
namespace arc {
namespace keymaster {
namespace context {
namespace {
scoped_refptr<::dbus::Bus> InitDBusInCurrentTaskRunner() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
scoped_refptr<::dbus::Bus> bus = new dbus::Bus(options);
CHECK(bus->Connect()) << "Failed to initialize adaptor DBus connection";
return bus;
}
} // namespace
ContextAdaptor::ContextAdaptor() : weak_ptr_factory_(this) {}
ContextAdaptor::~ContextAdaptor() = default;
scoped_refptr<::dbus::Bus> ContextAdaptor::GetBus() {
// Ensure |bus_| is initialized before usages.
if (!bus_)
bus_ = InitDBusInCurrentTaskRunner();
return bus_;
}
base::Optional<std::string> ContextAdaptor::FetchPrimaryUserEmail() {
// Short circuit if the results is already cached.
if (cached_email_.has_value())
return cached_email_.value();
// Prepare output variables.
std::string user_email;
std::string sanitized_username;
brillo::ErrorPtr error;
// Make dbus call.
org::chromium::SessionManagerInterfaceProxy session_manager_proxy(GetBus());
if (!session_manager_proxy.RetrievePrimarySession(
&user_email, &sanitized_username, &error)) {
std::string error_message = error ? error->GetMessage() : "Unknown error.";
LOG(INFO) << "Failed to get primary session: " << error_message;
return base::nullopt;
}
// Cache and return result.
cached_email_ = user_email;
return user_email;
}
base::Optional<CK_SLOT_ID> ContextAdaptor::FetchPrimaryUserSlot() {
// Short circuit if the results is already cached.
if (cached_slot_.has_value())
return cached_slot_.value();
// Fetch email of the primary signed in user.
base::Optional<std::string> user_email = FetchPrimaryUserEmail();
if (!user_email.has_value())
return base::nullopt;
// Create a dbus proxy.
dbus::ObjectProxy* cryptohome_proxy = GetBus()->GetObjectProxy(
cryptohome::kCryptohomeServiceName,
dbus::ObjectPath(cryptohome::kCryptohomeServicePath));
// Prepare a dbus method call.
dbus::MethodCall method_call(
cryptohome::kCryptohomeInterface,
cryptohome::kCryptohomePkcs11GetTpmTokenInfoForUser);
dbus::MessageWriter writer(&method_call);
writer.AppendString(user_email.value());
// Make dbus call.
std::unique_ptr<dbus::Response> response =
cryptohome_proxy->CallMethodAndBlock(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
if (!response)
return base::nullopt;
// Parse response.
dbus::MessageReader reader(response.get());
std::string label;
std::string user_pin;
int32_t slot;
reader.PopString(&label);
reader.PopString(&user_pin);
reader.PopInt32(&slot);
// Cache and return result.
cached_slot_ = slot;
return slot;
}
} // namespace context
} // namespace keymaster
} // namespace arc