blob: 50e0151fcf51a223c1d0134ad01e24a14427e417 [file] [log] [blame]
erikchenc04ab34c2015-07-27 20:28:201// Copyright 2015 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
5#include "ipc/attachment_broker_privileged_win.h"
6
7#include <windows.h>
8
9#include "base/process/process.h"
10#include "ipc/attachment_broker_messages.h"
11#include "ipc/brokerable_attachment.h"
12#include "ipc/handle_attachment_win.h"
13#include "ipc/ipc_channel.h"
14
15namespace IPC {
16
17AttachmentBrokerPrivilegedWin::AttachmentBrokerPrivilegedWin() {}
18
19AttachmentBrokerPrivilegedWin::~AttachmentBrokerPrivilegedWin() {}
20
21bool AttachmentBrokerPrivilegedWin::SendAttachmentToProcess(
22 const BrokerableAttachment* attachment,
23 base::ProcessId destination_process) {
24 switch (attachment->GetBrokerableType()) {
erikchen87351da2015-09-15 19:11:0925 case BrokerableAttachment::WIN_HANDLE: {
erikchenc04ab34c2015-07-27 20:28:2026 const internal::HandleAttachmentWin* handle_attachment =
27 static_cast<const internal::HandleAttachmentWin*>(attachment);
28 HandleWireFormat wire_format =
29 handle_attachment->GetWireFormat(destination_process);
30 HandleWireFormat new_wire_format =
31 DuplicateWinHandle(wire_format, base::Process::Current().Pid());
32 if (new_wire_format.handle == 0)
33 return false;
34 RouteDuplicatedHandle(new_wire_format);
35 return true;
erikchen87351da2015-09-15 19:11:0936 }
37 case BrokerableAttachment::PLACEHOLDER:
38 NOTREACHED();
39 return false;
erikchenc04ab34c2015-07-27 20:28:2040 }
41 return false;
42}
43
44bool AttachmentBrokerPrivilegedWin::OnMessageReceived(const Message& msg) {
45 bool handled = true;
erikchen3c175a32015-07-28 23:16:4846 switch (msg.type()) {
47 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateWinHandle,
48 OnDuplicateWinHandle(msg))
erikchenc04ab34c2015-07-27 20:28:2049 IPC_MESSAGE_UNHANDLED(handled = false)
erikchen3c175a32015-07-28 23:16:4850 }
erikchenc04ab34c2015-07-27 20:28:2051 return handled;
52}
53
erikchenc04ab34c2015-07-27 20:28:2054void AttachmentBrokerPrivilegedWin::OnDuplicateWinHandle(
erikchen3c175a32015-07-28 23:16:4855 const IPC::Message& message) {
56 AttachmentBrokerMsg_DuplicateWinHandle::Param param;
57 if (!AttachmentBrokerMsg_DuplicateWinHandle::Read(&message, &param))
58 return;
59 IPC::internal::HandleAttachmentWin::WireFormat wire_format =
60 base::get<0>(param);
61
erikchen16f9112d2015-09-23 06:05:2062 if (wire_format.destination_process == base::kNullProcessId) {
63 LogError(NO_DESTINATION);
erikchenc04ab34c2015-07-27 20:28:2064 return;
erikchen16f9112d2015-09-23 06:05:2065 }
erikchenc04ab34c2015-07-27 20:28:2066
67 HandleWireFormat new_wire_format =
erikchen3c175a32015-07-28 23:16:4868 DuplicateWinHandle(wire_format, message.get_sender_pid());
erikchenc04ab34c2015-07-27 20:28:2069 RouteDuplicatedHandle(new_wire_format);
70}
71
72void AttachmentBrokerPrivilegedWin::RouteDuplicatedHandle(
73 const HandleWireFormat& wire_format) {
74 // This process is the destination.
75 if (wire_format.destination_process == base::Process::Current().Pid()) {
76 scoped_refptr<BrokerableAttachment> attachment(
77 new internal::HandleAttachmentWin(wire_format));
78 HandleReceivedAttachment(attachment);
79 return;
80 }
81
82 // Another process is the destination.
83 base::ProcessId dest = wire_format.destination_process;
erikchena09b9be72015-08-10 19:22:3384 Sender* sender = GetSenderWithProcessId(dest);
85 if (!sender) {
erikchenc04ab34c2015-07-27 20:28:2086 // Assuming that this message was not sent from a malicious process, the
87 // channel endpoint that would have received this message will block
88 // forever.
89 LOG(ERROR) << "Failed to deliver brokerable attachment to process with id: "
90 << dest;
erikchen16f9112d2015-09-23 06:05:2091 LogError(DESTINATION_NOT_FOUND);
erikchenc04ab34c2015-07-27 20:28:2092 return;
93 }
94
erikchen16f9112d2015-09-23 06:05:2095 LogError(DESTINATION_FOUND);
erikchena09b9be72015-08-10 19:22:3396 sender->Send(new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format));
erikchenc04ab34c2015-07-27 20:28:2097}
98
99AttachmentBrokerPrivilegedWin::HandleWireFormat
100AttachmentBrokerPrivilegedWin::DuplicateWinHandle(
101 const HandleWireFormat& wire_format,
102 base::ProcessId source_pid) {
erikchenc04ab34c2015-07-27 20:28:20103 base::Process source_process =
104 base::Process::OpenWithExtraPrivileges(source_pid);
105 base::Process dest_process =
106 base::Process::OpenWithExtraPrivileges(wire_format.destination_process);
erikchen28299a12015-09-24 00:10:27107 int new_wire_format_handle = 0;
erikchenc04ab34c2015-07-27 20:28:20108 if (source_process.Handle() && dest_process.Handle()) {
erikchen959039d2015-08-11 21:17:47109 DWORD desired_access = 0;
110 DWORD options = 0;
111 switch (wire_format.permissions) {
112 case HandleWin::INVALID:
113 LOG(ERROR) << "Received invalid permissions for duplication.";
erikchen28299a12015-09-24 00:10:27114 return CopyWireFormat(wire_format, 0);
erikchen959039d2015-08-11 21:17:47115 case HandleWin::DUPLICATE:
116 options = DUPLICATE_SAME_ACCESS;
117 break;
118 case HandleWin::FILE_READ_WRITE:
119 desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
120 break;
121 }
122
erikchenc04ab34c2015-07-27 20:28:20123 HANDLE new_handle;
erikchen28299a12015-09-24 00:10:27124 HANDLE original_handle = LongToHandle(wire_format.handle);
erikchenc04ab34c2015-07-27 20:28:20125 DWORD result = ::DuplicateHandle(source_process.Handle(), original_handle,
erikchen959039d2015-08-11 21:17:47126 dest_process.Handle(), &new_handle,
127 desired_access, FALSE, options);
erikchenc04ab34c2015-07-27 20:28:20128
erikchen28299a12015-09-24 00:10:27129 new_wire_format_handle = (result != 0) ? HandleToLong(new_handle) : 0;
erikchenc04ab34c2015-07-27 20:28:20130 }
erikchen959039d2015-08-11 21:17:47131
erikchen28299a12015-09-24 00:10:27132 return CopyWireFormat(wire_format, new_wire_format_handle);
133}
134
135AttachmentBrokerPrivilegedWin::HandleWireFormat
136AttachmentBrokerPrivilegedWin::CopyWireFormat(
137 const HandleWireFormat& wire_format,
138 int handle) {
139 return HandleWireFormat(handle, wire_format.destination_process,
140 wire_format.permissions, wire_format.attachment_id);
erikchenc04ab34c2015-07-27 20:28:20141}
142
143} // namespace IPC