1 // 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.
5 #include "ipc/attachment_broker_privileged_win.h"
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"
17 AttachmentBrokerPrivilegedWin::AttachmentBrokerPrivilegedWin() {}
19 AttachmentBrokerPrivilegedWin::~AttachmentBrokerPrivilegedWin() {}
21 bool AttachmentBrokerPrivilegedWin::SendAttachmentToProcess(
22 const BrokerableAttachment
* attachment
,
23 base::ProcessId destination_process
) {
24 switch (attachment
->GetBrokerableType()) {
25 case BrokerableAttachment::WIN_HANDLE
:
26 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)
34 RouteDuplicatedHandle(new_wire_format
);
40 bool AttachmentBrokerPrivilegedWin::OnMessageReceived(const Message
& msg
) {
43 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateWinHandle
,
44 OnDuplicateWinHandle(msg
))
45 IPC_MESSAGE_UNHANDLED(handled
= false)
50 void AttachmentBrokerPrivilegedWin::OnDuplicateWinHandle(
51 const IPC::Message
& message
) {
52 AttachmentBrokerMsg_DuplicateWinHandle::Param param
;
53 if (!AttachmentBrokerMsg_DuplicateWinHandle::Read(&message
, ¶m
))
55 IPC::internal::HandleAttachmentWin::WireFormat wire_format
=
58 if (wire_format
.destination_process
== base::kNullProcessId
)
61 HandleWireFormat new_wire_format
=
62 DuplicateWinHandle(wire_format
, message
.get_sender_pid());
63 RouteDuplicatedHandle(new_wire_format
);
66 void AttachmentBrokerPrivilegedWin::RouteDuplicatedHandle(
67 const HandleWireFormat
& wire_format
) {
68 // This process is the destination.
69 if (wire_format
.destination_process
== base::Process::Current().Pid()) {
70 scoped_refptr
<BrokerableAttachment
> attachment(
71 new internal::HandleAttachmentWin(wire_format
));
72 HandleReceivedAttachment(attachment
);
76 // Another process is the destination.
77 base::ProcessId dest
= wire_format
.destination_process
;
78 Sender
* sender
= GetSenderWithProcessId(dest
);
80 // Assuming that this message was not sent from a malicious process, the
81 // channel endpoint that would have received this message will block
83 LOG(ERROR
) << "Failed to deliver brokerable attachment to process with id: "
88 sender
->Send(new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format
));
91 AttachmentBrokerPrivilegedWin::HandleWireFormat
92 AttachmentBrokerPrivilegedWin::DuplicateWinHandle(
93 const HandleWireFormat
& wire_format
,
94 base::ProcessId source_pid
) {
95 HandleWireFormat new_wire_format
;
96 new_wire_format
.destination_process
= wire_format
.destination_process
;
97 new_wire_format
.attachment_id
= wire_format
.attachment_id
;
98 new_wire_format
.permissions
= wire_format
.permissions
;
99 new_wire_format
.handle
= 0;
101 HANDLE original_handle
= LongToHandle(wire_format
.handle
);
103 base::Process source_process
=
104 base::Process::OpenWithExtraPrivileges(source_pid
);
105 base::Process dest_process
=
106 base::Process::OpenWithExtraPrivileges(wire_format
.destination_process
);
107 if (source_process
.Handle() && dest_process
.Handle()) {
108 DWORD desired_access
= 0;
110 switch (wire_format
.permissions
) {
111 case HandleWin::INVALID
:
112 LOG(ERROR
) << "Received invalid permissions for duplication.";
113 return new_wire_format
;
114 case HandleWin::DUPLICATE
:
115 options
= DUPLICATE_SAME_ACCESS
;
117 case HandleWin::FILE_READ_WRITE
:
118 desired_access
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
123 DWORD result
= ::DuplicateHandle(source_process
.Handle(), original_handle
,
124 dest_process
.Handle(), &new_handle
,
125 desired_access
, FALSE
, options
);
127 new_wire_format
.handle
= (result
!= 0) ? HandleToLong(new_handle
) : 0;
130 return new_wire_format
;