| // Copyright 2014 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 <base/bind.h> |
| #include <base/logging.h> |
| #include <base/stl_util.h> |
| #include <chromeos/libminijail.h> |
| #include <chromeos/minijail/minijail.h> |
| |
| #include "trunks/dbus_interface.h" |
| #include "trunks/error_codes.h" |
| #include "trunks/tpm_communication.pb.h" |
| #include "trunks/tpm_handle.h" |
| #include "trunks/trunks_service.h" |
| |
| namespace trunks { |
| |
| namespace { |
| |
| const uid_t kTrunksUID = 251; |
| const uid_t kRootUID = 0; |
| const char kTrunksUser[] = "trunks"; |
| const char kTrunksGroup[] = "trunks"; |
| const char kTrunksSeccompPath[] = "/usr/share/policy/trunksd-seccomp.policy"; |
| |
| } // namespace |
| |
| TrunksService::TrunksService() |
| : bus_(nullptr), |
| trunks_dbus_object_(nullptr) {} |
| |
| TrunksService::~TrunksService() {} |
| |
| void TrunksService::Init(TpmHandle* tpm) { |
| CHECK_EQ(getuid(), kRootUID) << "Trunks Daemon not initialized as root."; |
| tpm_ = tpm; |
| CHECK_EQ(tpm->Init(), TPM_RC_SUCCESS) |
| << "Trunks Daemon couldn't open the tpm handle."; |
| InitMinijailSandbox(); |
| InitDbusService(); |
| } |
| |
| void TrunksService::HandleSendCommand(dbus::MethodCall* method_call, |
| dbus::ExportedObject::ResponseSender response_sender) { |
| scoped_ptr<dbus::Response> response = |
| dbus::Response::FromMethodCall(method_call); |
| // Get the Command by reading the array passed with the method call. |
| dbus::MessageReader reader(method_call); |
| TpmCommand tpm_command_proto; |
| TpmResponse tpm_response_proto; |
| if (!reader.PopArrayOfBytesAsProto(&tpm_command_proto) || |
| !tpm_command_proto.has_command() || |
| tpm_command_proto.command().empty()) { |
| LOG(ERROR) << "Trunks Daemon could not read command to send to tpm."; |
| tpm_response_proto.set_result_code(TCTI_RC_GENERAL_FAILURE); |
| tpm_response_proto.set_response(std::string()); |
| dbus::MessageWriter writer(response.get()); |
| writer.AppendProtoAsArrayOfBytes(tpm_response_proto); |
| response_sender.Run(response.Pass()); |
| return; |
| } |
| // Get the TPM to process the command. |
| std::string tpm_response; |
| TPM_RC rc = tpm_->SendCommand(tpm_command_proto.command(), &tpm_response); |
| tpm_response_proto.set_result_code(rc); |
| tpm_response_proto.set_response(tpm_response); |
| // Send the response back via dbus. |
| dbus::MessageWriter writer(response.get()); |
| writer.AppendProtoAsArrayOfBytes(tpm_response_proto); |
| response_sender.Run(response.Pass()); |
| return; |
| } |
| |
| void TrunksService::InitMinijailSandbox() { |
| chromeos::Minijail* minijail = chromeos::Minijail::GetInstance(); |
| struct minijail* jail = minijail->New(); |
| minijail->DropRoot(jail, kTrunksUser, kTrunksGroup); |
| minijail->UseSeccompFilter(jail, kTrunksSeccompPath); |
| minijail->Enter(jail); |
| minijail->Destroy(jail); |
| CHECK_EQ(getuid(), kTrunksUID) |
| << "Trunks Daemon was not able to drop to trunks user."; |
| } |
| |
| |
| void TrunksService::InitDbusService() { |
| dbus::Bus::Options options; |
| options.bus_type = dbus::Bus::SYSTEM; |
| bus_ = new dbus::Bus(options); |
| CHECK(bus_->Connect()); |
| |
| trunks_dbus_object_ = bus_->GetExportedObject( |
| dbus::ObjectPath(kTrunksServicePath)); |
| CHECK(trunks_dbus_object_); |
| |
| trunks_dbus_object_->ExportMethodAndBlock(kTrunksInterface, kSendCommand, |
| base::Bind(&TrunksService::HandleSendCommand, base::Unretained(this))); |
| |
| CHECK(bus_->RequestOwnershipAndBlock(kTrunksServiceName, |
| dbus::Bus::REQUIRE_PRIMARY)) |
| << "Unable to take ownership of " << kTrunksServiceName; |
| } |
| |
| } // namespace trunks |