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
);
37 case BrokerableAttachment::PLACEHOLDER
:
44 bool AttachmentBrokerPrivilegedWin::OnMessageReceived(const Message
& msg
) {
47 IPC_MESSAGE_HANDLER_GENERIC(AttachmentBrokerMsg_DuplicateWinHandle
,
48 OnDuplicateWinHandle(msg
))
49 IPC_MESSAGE_UNHANDLED(handled
= false)
54 void AttachmentBrokerPrivilegedWin::OnDuplicateWinHandle(
55 const IPC::Message
& message
) {
56 AttachmentBrokerMsg_DuplicateWinHandle::Param param
;
57 if (!AttachmentBrokerMsg_DuplicateWinHandle::Read(&message
, ¶m
))
59 IPC::internal::HandleAttachmentWin::WireFormat wire_format
=
62 if (wire_format
.destination_process
== base::kNullProcessId
)
65 HandleWireFormat new_wire_format
=
66 DuplicateWinHandle(wire_format
, message
.get_sender_pid());
67 RouteDuplicatedHandle(new_wire_format
);
70 void AttachmentBrokerPrivilegedWin::RouteDuplicatedHandle(
71 const HandleWireFormat
& wire_format
) {
72 // This process is the destination.
73 if (wire_format
.destination_process
== base::Process::Current().Pid()) {
74 scoped_refptr
<BrokerableAttachment
> attachment(
75 new internal::HandleAttachmentWin(wire_format
));
76 HandleReceivedAttachment(attachment
);
80 // Another process is the destination.
81 base::ProcessId dest
= wire_format
.destination_process
;
82 Sender
* sender
= GetSenderWithProcessId(dest
);
84 // Assuming that this message was not sent from a malicious process, the
85 // channel endpoint that would have received this message will block
87 LOG(ERROR
) << "Failed to deliver brokerable attachment to process with id: "
92 sender
->Send(new AttachmentBrokerMsg_WinHandleHasBeenDuplicated(wire_format
));
95 AttachmentBrokerPrivilegedWin::HandleWireFormat
96 AttachmentBrokerPrivilegedWin::DuplicateWinHandle(
97 const HandleWireFormat
& wire_format
,
98 base::ProcessId source_pid
) {
99 HandleWireFormat new_wire_format
;
100 new_wire_format
.destination_process
= wire_format
.destination_process
;
101 new_wire_format
.attachment_id
= wire_format
.attachment_id
;
102 new_wire_format
.permissions
= wire_format
.permissions
;
103 new_wire_format
.handle
= 0;
105 HANDLE original_handle
= LongToHandle(wire_format
.handle
);
107 base::Process source_process
=
108 base::Process::OpenWithExtraPrivileges(source_pid
);
109 base::Process dest_process
=
110 base::Process::OpenWithExtraPrivileges(wire_format
.destination_process
);
111 if (source_process
.Handle() && dest_process
.Handle()) {
112 DWORD desired_access
= 0;
114 switch (wire_format
.permissions
) {
115 case HandleWin::INVALID
:
116 LOG(ERROR
) << "Received invalid permissions for duplication.";
117 return new_wire_format
;
118 case HandleWin::DUPLICATE
:
119 options
= DUPLICATE_SAME_ACCESS
;
121 case HandleWin::FILE_READ_WRITE
:
122 desired_access
= FILE_GENERIC_READ
| FILE_GENERIC_WRITE
;
127 DWORD result
= ::DuplicateHandle(source_process
.Handle(), original_handle
,
128 dest_process
.Handle(), &new_handle
,
129 desired_access
, FALSE
, options
);
131 new_wire_format
.handle
= (result
!= 0) ? HandleToLong(new_handle
) : 0;
134 return new_wire_format
;