[wing] Added function for getting WingCredentials from the named pipe
- From: Ignacio Casal Quinteiro <icq src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [wing] Added function for getting WingCredentials from the named pipe
- Date: Tue, 5 Dec 2017 15:20:53 +0000 (UTC)
commit 7659a0aa3e63d37019f6dfb79bfcfc2b05a0ef01
Author: Silvio Lazzeretti <silviola amazon com>
Date: Mon Dec 4 13:27:16 2017 +0100
Added function for getting WingCredentials from the named pipe
It is possible to get the process and user ids
of the client connected to the named pipe
through impersonation.
The method could fail if the caller process has
not enough privileges to impersonate the client
wing/wingnamedpipeconnection.c | 230 ++++++++++++++++++++++++++++++++++++++++
wing/wingnamedpipeconnection.h | 8 +-
2 files changed, 236 insertions(+), 2 deletions(-)
---
diff --git a/wing/wingnamedpipeconnection.c b/wing/wingnamedpipeconnection.c
index 2680511..8103566 100644
--- a/wing/wingnamedpipeconnection.c
+++ b/wing/wingnamedpipeconnection.c
@@ -25,6 +25,7 @@
#include <gio/gwin32outputstream.h>
#include <windows.h>
+#include <Sddl.h>
/**
* SECTION:wingnamedpipeconnection
@@ -237,3 +238,232 @@ wing_named_pipe_connection_get_pipe_name (WingNamedPipeConnection *connection)
return connection->pipe_name;
}
+
+static gulong
+get_client_process_id (WingNamedPipeConnection *connection,
+ GError **error)
+{
+ gulong process_id;
+
+ g_return_val_if_fail (WING_IS_NAMED_PIPE_CONNECTION (connection), 0);
+
+ if (!GetNamedPipeClientProcessId ((HANDLE)connection->handle, &process_id))
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error,
+ G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ "Could not get client process id: %s",
+ emsg);
+ g_free (emsg);
+
+ return 0;
+ }
+
+ return process_id;
+}
+
+static gchar *
+get_sid_from_token (HANDLE token,
+ GError **error)
+{
+ TOKEN_USER *user_info = NULL;
+ DWORD user_info_length = 0;
+ wchar_t *sid_string;
+ gchar *sid_utf8;
+
+ if (GetTokenInformation (token,
+ TokenUser,
+ user_info,
+ user_info_length,
+ &user_info_length) == FALSE)
+ {
+ int errsv = GetLastError ();
+
+ if (errsv != ERROR_INSUFFICIENT_BUFFER)
+ {
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error,
+ G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ "Could not get the token information: %s",
+ emsg);
+ g_free (emsg);
+
+ return NULL;
+ }
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ user_info = (TOKEN_USER *)g_malloc (user_info_length);
+
+ if (GetTokenInformation (token,
+ TokenUser,
+ user_info,
+ user_info_length,
+ &user_info_length) == FALSE)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error,
+ G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ "Could not get the token information: %s",
+ emsg);
+ g_free (emsg);
+
+ g_free (user_info);
+
+ return NULL;
+ }
+
+ if (ConvertSidToStringSidW (user_info->User.Sid, &sid_string) == FALSE)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error,
+ G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ "Could not convert Sid to string: %s",
+ emsg);
+ g_free (emsg);
+
+ g_free (user_info);
+
+ return NULL;
+ }
+
+ g_free (user_info);
+
+ sid_utf8 = g_utf16_to_utf8 ((gunichar2 *)sid_string, -1, NULL, NULL, NULL);
+ LocalFree (sid_string);
+
+ return sid_utf8;
+}
+
+static gchar *
+get_user_id (WingNamedPipeConnection *connection,
+ GError **error)
+{
+ HANDLE token;
+ gchar *sid;
+
+ if (ImpersonateNamedPipeClient (connection->handle) == FALSE)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error,
+ G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ "Could not impersonate the client: %s",
+ emsg);
+ g_free (emsg);
+
+ return NULL;
+ }
+
+ if (OpenThreadToken (GetCurrentThread (), TOKEN_QUERY, FALSE, &token) == FALSE)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ g_set_error (error,
+ G_IO_ERROR,
+ g_io_error_from_win32_error (errsv),
+ "Could not get the thread's token: %s",
+ emsg);
+ g_free (emsg);
+
+ if (RevertToSelf () == FALSE)
+ {
+ errsv = GetLastError ();
+ emsg = g_win32_error_message (errsv);
+
+ /*
+ * If we reach this point, it is better to abort the execution,
+ * because otherwise it will continue in the context of the client,
+ * which is not appropriate
+ */
+ g_error ("Failed to terminate the impersonation of the client: %s (%d)",
+ emsg,
+ errsv);
+ }
+
+ return NULL;
+ }
+
+ sid = get_sid_from_token (token, error);
+ CloseHandle (token);
+
+ if (RevertToSelf () == FALSE)
+ {
+ int errsv = GetLastError ();
+ gchar *emsg = g_win32_error_message (errsv);
+
+ /*
+ * If we reach this point, it is better to abort the execution,
+ * because otherwise it will continue in the context of the client,
+ * which is not appropriate
+ */
+ g_error ("Failed to terminate the impersonation of the client: %s (%d)",
+ emsg,
+ errsv);
+ }
+
+ return sid;
+}
+
+/**
+ * wing_named_pipe_connection_get_credentials():
+ * @connection: a #WingNamedPipeConnection.
+ * @error: a #GError location to store the error occurring, or %NULL to
+ * ignore.
+ *
+ * Retrieves the WingCredentials of the pipe's client
+ *
+ * Returns: (transfer full): a #WingCredentials on success, %NULL on error.
+ */
+WingCredentials *
+wing_named_pipe_connection_get_credentials (WingNamedPipeConnection *connection,
+ GError **error)
+{
+ WingCredentials *credentials;
+ gulong pid;
+ gchar *sid;
+
+ g_return_val_if_fail (WING_IS_NAMED_PIPE_CONNECTION (connection), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (connection->handle == NULL || connection->handle == INVALID_HANDLE_VALUE)
+ {
+ g_set_error_literal (error,
+ G_IO_ERROR,
+ G_IO_ERROR_INVALID_ARGUMENT,
+ "Pipe's handle is NULL or invalid");
+
+ return FALSE;
+ }
+
+ pid = get_client_process_id (connection, error);
+ if (pid == 0)
+ return NULL;
+
+ sid = get_user_id (connection, error);
+ if (sid == NULL)
+ return NULL;
+
+ credentials = wing_credentials_new (pid, sid);
+
+ g_free (sid);
+
+ return credentials;
+}
diff --git a/wing/wingnamedpipeconnection.h b/wing/wingnamedpipeconnection.h
index c1f680a..54d9340 100644
--- a/wing/wingnamedpipeconnection.h
+++ b/wing/wingnamedpipeconnection.h
@@ -22,6 +22,7 @@
#include <gio/gio.h>
#include <wing/wingversionmacros.h>
+#include <wing/wingcredentials.h>
G_BEGIN_DECLS
@@ -32,11 +33,14 @@ G_BEGIN_DECLS
typedef struct _WingNamedPipeConnection WingNamedPipeConnection;
WING_AVAILABLE_IN_ALL
-GType wing_named_pipe_connection_get_type (void) G_GNUC_CONST;
+GType wing_named_pipe_connection_get_type (void) G_GNUC_CONST;
WING_AVAILABLE_IN_ALL
-const gchar *wing_named_pipe_connection_get_pipe_name (WingNamedPipeConnection
*connection);
+const gchar *wing_named_pipe_connection_get_pipe_name (WingNamedPipeConnection
*connection);
+WING_AVAILABLE_IN_ALL
+WingCredentials *wing_named_pipe_connection_get_credentials (WingNamedPipeConnection
*connection,
+ GError
**error);
G_END_DECLS
#endif /* WING_NAMED_PIPE_CONNECTION_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]