dlp_client.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chromeos/dbus/dlp/dlp_client.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/memory/raw_ptr.h"
  8. #include "base/memory/weak_ptr.h"
  9. #include "base/strings/strcat.h"
  10. #include "base/threading/thread_task_runner_handle.h"
  11. #include "chromeos/dbus/dlp/dlp_service.pb.h"
  12. #include "chromeos/dbus/dlp/fake_dlp_client.h"
  13. #include "dbus/bus.h"
  14. #include "dbus/message.h"
  15. #include "dbus/object_proxy.h"
  16. #include "third_party/abseil-cpp/absl/types/optional.h"
  17. #include "third_party/cros_system_api/dbus/dlp/dbus-constants.h"
  18. namespace chromeos {
  19. namespace {
  20. DlpClient* g_instance = nullptr;
  21. const char kDbusCallFailure[] = "Failed to call dlp.";
  22. const char kProtoMessageParsingFailure[] =
  23. "Failed to parse response message from dlp.";
  24. // Tries to parse a proto message from |response| into |proto| and returns null
  25. // if successful. If |response| is nullptr or the message cannot be parsed it
  26. // will return an appropriate error message.
  27. const char* DeserializeProto(dbus::Response* response,
  28. google::protobuf::MessageLite* proto) {
  29. if (!response)
  30. return kDbusCallFailure;
  31. dbus::MessageReader reader(response);
  32. if (!reader.PopArrayOfBytesAsProto(proto))
  33. return kProtoMessageParsingFailure;
  34. return nullptr;
  35. }
  36. // "Real" implementation of DlpClient talking to the Dlp daemon
  37. // on the Chrome OS side.
  38. class DlpClientImpl : public DlpClient {
  39. public:
  40. DlpClientImpl() = default;
  41. DlpClientImpl(const DlpClientImpl&) = delete;
  42. DlpClientImpl& operator=(const DlpClientImpl&) = delete;
  43. ~DlpClientImpl() override = default;
  44. void Init(dbus::Bus* bus) {
  45. proxy_ = bus->GetObjectProxy(dlp::kDlpServiceName,
  46. dbus::ObjectPath(dlp::kDlpServicePath));
  47. }
  48. void SetDlpFilesPolicy(const dlp::SetDlpFilesPolicyRequest request,
  49. SetDlpFilesPolicyCallback callback) override {
  50. dbus::MethodCall method_call(dlp::kDlpInterface,
  51. dlp::kSetDlpFilesPolicyMethod);
  52. dbus::MessageWriter writer(&method_call);
  53. if (!writer.AppendProtoAsArrayOfBytes(request)) {
  54. dlp::SetDlpFilesPolicyResponse response;
  55. response.set_error_message(base::StrCat(
  56. {"Failure to call d-bus method: ", dlp::kSetDlpFilesPolicyMethod}));
  57. base::ThreadTaskRunnerHandle::Get()->PostTask(
  58. FROM_HERE, base::BindOnce(std::move(callback), response));
  59. return;
  60. }
  61. proxy_->CallMethod(
  62. &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
  63. base::BindOnce(&DlpClientImpl::HandleSetDlpFilesPolicyResponse,
  64. weak_factory_.GetWeakPtr(), std::move(callback)));
  65. }
  66. void AddFile(const dlp::AddFileRequest request,
  67. AddFileCallback callback) override {
  68. dbus::MethodCall method_call(dlp::kDlpInterface, dlp::kAddFileMethod);
  69. dbus::MessageWriter writer(&method_call);
  70. if (!writer.AppendProtoAsArrayOfBytes(request)) {
  71. dlp::AddFileResponse response;
  72. response.set_error_message(base::StrCat(
  73. {"Failure to call d-bus method: ", dlp::kAddFileMethod}));
  74. base::ThreadTaskRunnerHandle::Get()->PostTask(
  75. FROM_HERE, base::BindOnce(std::move(callback), response));
  76. return;
  77. }
  78. proxy_->CallMethod(
  79. &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
  80. base::BindOnce(&DlpClientImpl::HandleAddFileResponse,
  81. weak_factory_.GetWeakPtr(), std::move(callback)));
  82. }
  83. void GetFilesSources(const dlp::GetFilesSourcesRequest request,
  84. GetFilesSourcesCallback callback) const override {
  85. dbus::MethodCall method_call(dlp::kDlpInterface,
  86. dlp::kGetFilesSourcesMethod);
  87. dbus::MessageWriter writer(&method_call);
  88. if (!writer.AppendProtoAsArrayOfBytes(request)) {
  89. dlp::GetFilesSourcesResponse response;
  90. response.set_error_message(base::StrCat(
  91. {"Failure to call d-bus method: ", dlp::kGetFilesSourcesMethod}));
  92. base::ThreadTaskRunnerHandle::Get()->PostTask(
  93. FROM_HERE, base::BindOnce(std::move(callback), response));
  94. return;
  95. }
  96. proxy_->CallMethod(
  97. &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
  98. base::BindOnce(&DlpClientImpl::HandleGetFilesSourcesResponse,
  99. weak_factory_.GetWeakPtr(), std::move(callback)));
  100. }
  101. void CheckFilesTransfer(const dlp::CheckFilesTransferRequest request,
  102. CheckFilesTransferCallback callback) const override {
  103. dbus::MethodCall method_call(dlp::kDlpInterface,
  104. dlp::kCheckFilesTransferMethod);
  105. dbus::MessageWriter writer(&method_call);
  106. if (!writer.AppendProtoAsArrayOfBytes(request)) {
  107. dlp::CheckFilesTransferResponse response;
  108. response.set_error_message(base::StrCat(
  109. {"Failure to call d-bus method: ", dlp::kCheckFilesTransferMethod}));
  110. base::ThreadTaskRunnerHandle::Get()->PostTask(
  111. FROM_HERE, base::BindOnce(std::move(callback), response));
  112. return;
  113. }
  114. proxy_->CallMethod(
  115. &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
  116. base::BindOnce(&DlpClientImpl::HandleCheckFilesTransferResponse,
  117. weak_factory_.GetWeakPtr(), std::move(callback)));
  118. }
  119. void RequestFileAccess(const dlp::RequestFileAccessRequest request,
  120. RequestFileAccessCallback callback) override {
  121. dbus::MethodCall method_call(dlp::kDlpInterface,
  122. dlp::kRequestFileAccessMethod);
  123. dbus::MessageWriter writer(&method_call);
  124. if (!writer.AppendProtoAsArrayOfBytes(request)) {
  125. dlp::RequestFileAccessResponse response;
  126. response.set_error_message(base::StrCat(
  127. {"Failure to call d-bus method: ", dlp::kRequestFileAccessMethod}));
  128. base::ThreadTaskRunnerHandle::Get()->PostTask(
  129. FROM_HERE,
  130. base::BindOnce(std::move(callback), response, base::ScopedFD()));
  131. return;
  132. }
  133. proxy_->CallMethod(
  134. &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
  135. base::BindOnce(&DlpClientImpl::HandleRequestFileAccessResponse,
  136. weak_factory_.GetWeakPtr(), std::move(callback)));
  137. }
  138. bool IsAlive() const override { return is_alive_; }
  139. private:
  140. TestInterface* GetTestInterface() override { return nullptr; }
  141. void HandleSetDlpFilesPolicyResponse(SetDlpFilesPolicyCallback callback,
  142. dbus::Response* response) {
  143. dlp::SetDlpFilesPolicyResponse response_proto;
  144. const char* error_message = DeserializeProto(response, &response_proto);
  145. if (error_message) {
  146. response_proto.set_error_message(error_message);
  147. }
  148. if (!response_proto.has_error_message()) {
  149. is_alive_ = true;
  150. }
  151. std::move(callback).Run(response_proto);
  152. }
  153. void HandleAddFileResponse(AddFileCallback callback,
  154. dbus::Response* response) {
  155. dlp::AddFileResponse response_proto;
  156. const char* error_message = DeserializeProto(response, &response_proto);
  157. if (error_message) {
  158. response_proto.set_error_message(error_message);
  159. }
  160. std::move(callback).Run(response_proto);
  161. }
  162. void HandleGetFilesSourcesResponse(GetFilesSourcesCallback callback,
  163. dbus::Response* response) {
  164. dlp::GetFilesSourcesResponse response_proto;
  165. const char* error_message = DeserializeProto(response, &response_proto);
  166. if (error_message) {
  167. response_proto.set_error_message(error_message);
  168. }
  169. std::move(callback).Run(response_proto);
  170. }
  171. void HandleCheckFilesTransferResponse(CheckFilesTransferCallback callback,
  172. dbus::Response* response) {
  173. dlp::CheckFilesTransferResponse response_proto;
  174. const char* error_message = DeserializeProto(response, &response_proto);
  175. if (error_message) {
  176. response_proto.set_error_message(error_message);
  177. }
  178. std::move(callback).Run(response_proto);
  179. }
  180. void HandleRequestFileAccessResponse(RequestFileAccessCallback callback,
  181. dbus::Response* response) {
  182. dlp::RequestFileAccessResponse response_proto;
  183. base::ScopedFD fd;
  184. if (!response) {
  185. response_proto.set_error_message(kDbusCallFailure);
  186. std::move(callback).Run(response_proto, std::move(fd));
  187. return;
  188. }
  189. dbus::MessageReader reader(response);
  190. if (!reader.PopArrayOfBytesAsProto(&response_proto)) {
  191. response_proto.set_error_message(kProtoMessageParsingFailure);
  192. std::move(callback).Run(response_proto, std::move(fd));
  193. return;
  194. }
  195. if (!reader.PopFileDescriptor(&fd)) {
  196. response_proto.set_error_message(kProtoMessageParsingFailure);
  197. std::move(callback).Run(response_proto, std::move(fd));
  198. return;
  199. }
  200. std::move(callback).Run(response_proto, std::move(fd));
  201. }
  202. // D-Bus proxy for the Dlp daemon, not owned.
  203. raw_ptr<dbus::ObjectProxy> proxy_ = nullptr;
  204. // Indicates whether the daemon was started and DLP Files rules are enforced.
  205. bool is_alive_ = false;
  206. base::WeakPtrFactory<DlpClientImpl> weak_factory_{this};
  207. };
  208. } // namespace
  209. DlpClient::DlpClient() {
  210. CHECK(!g_instance);
  211. g_instance = this;
  212. }
  213. DlpClient::~DlpClient() {
  214. CHECK_EQ(this, g_instance);
  215. g_instance = nullptr;
  216. }
  217. // static
  218. void DlpClient::Initialize(dbus::Bus* bus) {
  219. CHECK(bus);
  220. (new DlpClientImpl())->Init(bus);
  221. }
  222. // static
  223. void DlpClient::InitializeFake() {
  224. new FakeDlpClient();
  225. }
  226. // static
  227. void DlpClient::Shutdown() {
  228. CHECK(g_instance);
  229. delete g_instance;
  230. }
  231. // static
  232. DlpClient* DlpClient::Get() {
  233. return g_instance;
  234. }
  235. } // namespace chromeos