summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalf Habacker <ralf.habacker@freenet.de>2013-03-08 13:55:32 +0100
committerRalf Habacker <ralf.habacker@sag.eu>2013-04-05 11:17:26 +0200
commit8159956ed4d34ff217f67758a72005fe4362aa45 (patch)
tree943f5bc5b46f85d2523dadf8c424b9ba9f92b7cd
parent89c1ecdd7cdd6c836506065a47bfb47d20bbb874 (diff)
Add function _dbus_get_peer_pid_from_tcp_handle() which returns pid and sid from tcp connection peer.
This function is called by _dbus_read_credentials_socket() to fetch client credentials. Because Wine is used to check cross compiled dbus for windows, in calls to GetExtendedTcpTable() we use table class TCP_TABLE_OWNER_PID_ALL instead of TCP_TABLE_OWNER_PID_CONNECTIONS. This class is the only one which is available since wine 1.5.3. https://bugs.freedesktop.org/show_bug.cgi?id=61787 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
-rw-r--r--cmake/dbus/CMakeLists.txt4
-rw-r--r--configure.ac2
-rw-r--r--dbus/dbus-sysdeps-win.c144
3 files changed, 130 insertions, 20 deletions
diff --git a/cmake/dbus/CMakeLists.txt b/cmake/dbus/CMakeLists.txt
index 8a401716..66772c58 100644
--- a/cmake/dbus/CMakeLists.txt
+++ b/cmake/dbus/CMakeLists.txt
@@ -264,7 +264,7 @@ if(WIN32)
if(WINCE)
target_link_libraries(dbus-1 ws2)
else(WINCE)
- target_link_libraries(dbus-1 ws2_32 advapi32 netapi32)
+ target_link_libraries(dbus-1 ws2_32 advapi32 netapi32 iphlpapi)
endif(WINCE)
else(WIN32)
target_link_libraries(dbus-1 ${CMAKE_THREAD_LIBS_INIT} rt)
@@ -289,7 +289,7 @@ if(WIN32)
if(WINCE)
target_link_libraries(dbus-internal ws2)
else(WINCE)
- target_link_libraries(dbus-internal ws2_32 advapi32 netapi32)
+ target_link_libraries(dbus-internal ws2_32 advapi32 netapi32 iphlpapi)
endif(WINCE)
else(WIN32)
target_link_libraries(dbus-internal ${CMAKE_THREAD_LIBS_INIT} rt)
diff --git a/configure.ac b/configure.ac
index 3bd2405e..b6430c52 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1279,7 +1279,7 @@ if test x$dbus_win = xyes ; then
if test x$dbus_wince = xyes ; then
NETWORK_libs="-lws2"
else
- NETWORK_libs="-lws2_32"
+ NETWORK_libs="-lws2_32 -liphlpapi"
fi
fi
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index ce60d29e..66d6b767 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -6,7 +6,7 @@
* Copyright (C) 2005 Novell, Inc.
* Copyright (C) 2006 Peter Kümmel <syntheticpp@gmx.net>
* Copyright (C) 2006 Christian Ehrlicher <ch.ehrlicher@gmx.de>
- * Copyright (C) 2006-2010 Ralf Habacker <ralf.habacker@freenet.de>
+ * Copyright (C) 2006-2013 Ralf Habacker <ralf.habacker@freenet.de>
*
* Licensed under the Academic Free License version 2.1
*
@@ -54,8 +54,9 @@
#include <windows.h>
#include <ws2tcpip.h>
#include <wincrypt.h>
+#include <iphlpapi.h>
-/* Declarations missing in mingw's headers */
+/* Declarations missing in mingw's and windows sdk 7.0 headers */
extern BOOL WINAPI ConvertStringSidToSidA (LPCSTR StringSid, PSID *Sid);
extern BOOL WINAPI ConvertSidToStringSidA (PSID Sid, LPSTR *StringSid);
@@ -103,6 +104,93 @@ _dbus_win_set_errno (int err)
#endif
}
+/**
+ * @brief return peer process id from tcp handle for localhost connections
+ * @param handle tcp socket descriptor
+ * @return process id or 0 in case the process id could not be fetched
+ */
+static dbus_pid_t
+_dbus_get_peer_pid_from_tcp_handle (int handle)
+{
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof (addr);
+ int peer_port;
+
+ dbus_pid_t result;
+ DWORD size;
+ MIB_TCPTABLE_OWNER_PID *tcp_table;
+ DWORD i;
+ dbus_bool_t is_localhost = FALSE;
+
+ getpeername (handle, (struct sockaddr *) &addr, &len);
+
+ if (addr.ss_family == AF_INET)
+ {
+ struct sockaddr_in *s = (struct sockaddr_in *) &addr;
+ peer_port = ntohs (s->sin_port);
+ is_localhost = (htonl (s->sin_addr.s_addr) == INADDR_LOOPBACK);
+ }
+ else if (addr.ss_family == AF_INET6)
+ {
+ _dbus_verbose ("FIXME [61922]: IPV6 support not working on windows\n");
+ return 0;
+ /*
+ struct sockaddr_in6 *s = (struct sockaddr_in6 * )&addr;
+ peer_port = ntohs (s->sin6_port);
+ is_localhost = (memcmp(s->sin6_addr.s6_addr, in6addr_loopback.s6_addr, 16) == 0);
+ _dbus_verbose ("IPV6 %08x %08x\n", s->sin6_addr.s6_addr, in6addr_loopback.s6_addr);
+ */
+ }
+ else
+ {
+ _dbus_verbose ("no idea what address family %d is\n", addr.ss_family);
+ return 0;
+ }
+
+ if (!is_localhost)
+ {
+ _dbus_verbose ("could not fetch process id from remote process\n");
+ return 0;
+ }
+
+ if (peer_port == 0)
+ {
+ _dbus_verbose
+ ("Error not been able to fetch tcp peer port from connection\n");
+ return 0;
+ }
+
+ if ((result =
+ GetExtendedTcpTable (NULL, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ tcp_table = (MIB_TCPTABLE_OWNER_PID *) dbus_malloc (size);
+ if (tcp_table == NULL)
+ {
+ _dbus_verbose ("Error allocating memory\n");
+ return 0;
+ }
+ }
+
+ if ((result = GetExtendedTcpTable (tcp_table, &size, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0)) != NO_ERROR)
+ {
+ _dbus_verbose ("Error fetching tcp table %d\n", result);
+ dbus_free (tcp_table);
+ return 0;
+ }
+
+ result = 0;
+ for (i = 0; i < tcp_table->dwNumEntries; i++)
+ {
+ MIB_TCPROW_OWNER_PID *p = &tcp_table->table[i];
+ int local_port = ntohs (p->dwLocalPort);
+ if (p->dwState == MIB_TCP_STATE_ESTAB && local_port == peer_port)
+ result = p->dwOwningPid;
+ }
+
+ _dbus_verbose ("got pid %d\n", result);
+ dbus_free (tcp_table);
+ return result;
+}
/* Convert GetLastError() to a dbus error. */
const char*
@@ -738,22 +826,23 @@ _dbus_pid_for_log (void)
return _dbus_getpid ();
}
-
#ifndef DBUS_WINCE
/** Gets our SID
- * @param points to sid buffer, need to be freed with LocalFree()
+ * @param sid points to sid buffer, need to be freed with LocalFree()
+ * @param process_id the process id for which the sid should be returned
* @returns process sid
*/
static dbus_bool_t
-_dbus_getsid(char **sid)
+_dbus_getsid(char **sid, dbus_pid_t process_id)
{
HANDLE process_token = INVALID_HANDLE_VALUE;
TOKEN_USER *token_user = NULL;
DWORD n;
PSID psid;
int retval = FALSE;
-
- if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY, &process_token))
+ HANDLE process_handle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id);
+
+ if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token))
{
_dbus_win_warn_win_error ("OpenProcessToken failed", GetLastError ());
goto failed;
@@ -781,6 +870,7 @@ _dbus_getsid(char **sid)
retval = TRUE;
failed:
+ CloseHandle (process_handle);
if (process_token != INVALID_HANDLE_VALUE)
CloseHandle (process_token);
@@ -1665,7 +1755,7 @@ again:
* a byte was read, not whether we got valid credentials. On some
* systems, such as Linux, reading/writing the byte isn't actually
* required, but we do it anyway just to avoid multiple codepaths.
- *
+ *
* Fails if no byte is available, so you must select() first.
*
* The point of the byte is that on some systems we have to
@@ -1683,21 +1773,41 @@ _dbus_read_credentials_socket (int handle,
{
int bytes_read = 0;
DBusString buf;
-
+
+ char *sid = NULL;
+ dbus_pid_t pid;
+ int retval = FALSE;
+
// could fail due too OOM
- if (_dbus_string_init(&buf))
+ if (_dbus_string_init (&buf))
{
- bytes_read = _dbus_read_socket(handle, &buf, 1 );
+ bytes_read = _dbus_read_socket (handle, &buf, 1 );
if (bytes_read > 0)
- _dbus_verbose("got one zero byte from server\n");
+ _dbus_verbose ("got one zero byte from server\n");
- _dbus_string_free(&buf);
+ _dbus_string_free (&buf);
}
- _dbus_verbose("FIXME: fetch credentials from client connection\n");
+ pid = _dbus_get_peer_pid_from_tcp_handle (handle);
+ if (pid == 0)
+ return TRUE;
- return TRUE;
+ _dbus_credentials_add_pid (credentials, pid);
+
+ if (_dbus_getsid (&sid, pid))
+ {
+ if (!_dbus_credentials_add_windows_sid (credentials, sid))
+ goto out;
+ }
+
+ retval = TRUE;
+
+out:
+ if (sid)
+ LocalFree (sid);
+
+ return retval;
}
/**
@@ -1791,7 +1901,7 @@ _dbus_credentials_add_from_current_process (DBusCredentials *credentials)
dbus_bool_t retval = FALSE;
char *sid = NULL;
- if (!_dbus_getsid(&sid))
+ if (!_dbus_getsid(&sid, _dbus_getpid()))
goto failed;
if (!_dbus_credentials_add_pid (credentials, _dbus_getpid()))
@@ -1829,7 +1939,7 @@ _dbus_append_user_from_current_process (DBusString *str)
dbus_bool_t retval = FALSE;
char *sid = NULL;
- if (!_dbus_getsid(&sid))
+ if (!_dbus_getsid(&sid, _dbus_getpid()))
return FALSE;
retval = _dbus_string_append (str,sid);