summaryrefslogtreecommitdiffstats
path: root/ipc/ipc_channel_win.cc
diff options
context:
space:
mode:
authorjschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-17 02:20:46 +0000
committerjschuh@chromium.org <jschuh@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-17 02:20:46 +0000
commit5c41e6e1cd446c3b2bc0ed17e66dffbc76f7c650 (patch)
tree81e2f1a63b2109464dde8efa38b32381e2001829 /ipc/ipc_channel_win.cc
parentab25e338556b9580c54b3f4025009eaaf6ac83d3 (diff)
downloadchromium_src-5c41e6e1cd446c3b2bc0ed17e66dffbc76f7c650.zip
chromium_src-5c41e6e1cd446c3b2bc0ed17e66dffbc76f7c650.tar.gz
chromium_src-5c41e6e1cd446c3b2bc0ed17e66dffbc76f7c650.tar.bz2
Verify the child process with a secret hello
BUG=117627 TEST=IPCSyncChannelTest.Verified Review URL: http://codereview.chromium.org/9692035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@127327 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_channel_win.cc')
-rw-r--r--ipc/ipc_channel_win.cc69
1 files changed, 60 insertions, 9 deletions
diff --git a/ipc/ipc_channel_win.cc b/ipc/ipc_channel_win.cc
index ef974ee..e2f0535 100644
--- a/ipc/ipc_channel_win.cc
+++ b/ipc/ipc_channel_win.cc
@@ -10,6 +10,9 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/process_util.h"
+#include "base/rand_util.h"
+#include "base/string_number_conversions.h"
#include "base/threading/non_thread_safe.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_handle.h"
@@ -36,7 +39,9 @@ Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle &channel_handle,
pipe_(INVALID_HANDLE_VALUE),
waiting_connect_(mode & MODE_SERVER_FLAG),
processing_incoming_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
+ client_secret_(0),
+ validate_client_(false) {
CreatePipe(channel_handle, mode);
}
@@ -97,14 +102,13 @@ bool Channel::ChannelImpl::Send(Message* message) {
// static
bool Channel::ChannelImpl::IsNamedServerInitialized(
const std::string& channel_id) {
- if (WaitNamedPipe(PipeName(channel_id).c_str(), 1))
+ if (WaitNamedPipe(PipeName(channel_id, NULL).c_str(), 1))
return true;
// If ERROR_SEM_TIMEOUT occurred, the pipe exists but is handling another
// connection.
return GetLastError() == ERROR_SEM_TIMEOUT;
}
-
Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
char* buffer,
int buffer_len,
@@ -144,7 +148,16 @@ bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) {
// The hello message contains one parameter containing the PID.
- listener()->OnChannelConnected(MessageIterator(msg).NextInt());
+ MessageIterator it = MessageIterator(msg);
+ int32 claimed_pid = it.NextInt();
+ if (validate_client_ && (it.NextInt() != client_secret_)) {
+ NOTREACHED();
+ // Something went wrong. Abort connection.
+ Close();
+ listener()->OnChannelError();
+ return;
+ }
+ listener()->OnChannelConnected(claimed_pid);
}
bool Channel::ChannelImpl::DidEmptyInputBuffers() {
@@ -153,9 +166,21 @@ bool Channel::ChannelImpl::DidEmptyInputBuffers() {
}
// static
-const std::wstring Channel::ChannelImpl::PipeName(
- const std::string& channel_id) {
+const string16 Channel::ChannelImpl::PipeName(
+ const std::string& channel_id, int32* secret) {
std::string name("\\\\.\\pipe\\chrome.");
+
+ // Prevent the shared secret from ending up in the pipe name.
+ size_t index = channel_id.find_first_of('\\');
+ if (index != std::string::npos) {
+ if (secret) // Retrieve the secret if asked for.
+ base::StringToInt(channel_id.substr(index + 1), secret);
+ return ASCIIToWide(name.append(channel_id.substr(0, index - 1)));
+ }
+
+ // This case is here to support predictable named pipes in tests.
+ if (secret)
+ *secret = 0;
return ASCIIToWide(name.append(channel_id));
}
@@ -192,7 +217,8 @@ bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle,
DCHECK(!channel_handle.pipe.handle);
const DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
FILE_FLAG_FIRST_PIPE_INSTANCE;
- pipe_name = PipeName(channel_handle.name);
+ pipe_name = PipeName(channel_handle.name, &client_secret_);
+ validate_client_ = !!client_secret_;
pipe_ = CreateNamedPipeW(pipe_name.c_str(),
open_mode,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE,
@@ -203,7 +229,7 @@ bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle,
NULL);
} else if (mode & MODE_CLIENT_FLAG) {
DCHECK(!channel_handle.pipe.handle);
- pipe_name = PipeName(channel_handle.name);
+ pipe_name = PipeName(channel_handle.name, &client_secret_);
pipe_ = CreateFileW(pipe_name.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
@@ -228,7 +254,12 @@ bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle,
scoped_ptr<Message> m(new Message(MSG_ROUTING_NONE,
HELLO_MESSAGE_TYPE,
IPC::Message::PRIORITY_NORMAL));
- if (!m->WriteInt(GetCurrentProcessId())) {
+
+ // Don't send the secret to the untrusted process, and don't send a secret
+ // if the value is zero (for IPC backwards compatability).
+ int32 secret = validate_client_ ? 0 : client_secret_;
+ if (!m->WriteInt(GetCurrentProcessId()) ||
+ (secret && !m->WriteUInt32(secret))) {
CloseHandle(pipe_);
pipe_ = INVALID_HANDLE_VALUE;
return false;
@@ -441,4 +472,24 @@ bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
return ChannelImpl::IsNamedServerInitialized(channel_id);
}
+// static
+std::string Channel::GenerateVerifiedChannelID(const std::string& prefix) {
+ // Windows pipes can be enumerated by low-privileged processes. So, we
+ // append a strong random value after the \ character. This value is not
+ // included in the pipe name, but sent as part of the client hello, to
+ // hijacking the pipe name to spoof the client.
+
+ std::string id = prefix;
+ if (!id.empty())
+ id.append(".");
+
+ int secret;
+ do { // Guarantee we get a non-zero value.
+ secret = base::RandInt(0, std::numeric_limits<int>::max());
+ } while (secret == 0);
+
+ id.append(GenerateUniqueRandomChannelID());
+ return id.append(base::StringPrintf("\\%d", secret));
+}
+
} // namespace IPC