[glib: 1/4] gio: add win32 SID helper functions
- From: Simon McVittie <smcv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/4] gio: add win32 SID helper functions
- Date: Wed, 19 Jan 2022 18:38:21 +0000 (UTC)
commit d4a66baadbfa98c95dc4f56c6dd1d30d5c34db42
Author: Marc-André Lureau <marcandre lureau redhat com>
Date: Wed Jan 12 17:21:23 2022 +0400
gio: add win32 SID helper functions
The code is based from #1351 patch and existing similar code in
gdbusprivate.c. The next commit will replace that existing code with
those helpers.
Signed-off-by: Marc-André Lureau <marcandre lureau redhat com>
gio/gwin32sid.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
gio/gwin32sid.h | 38 +++++++++++
gio/meson.build | 2 +
3 files changed, 249 insertions(+)
---
diff --git a/gio/gwin32sid.c b/gio/gwin32sid.c
new file mode 100644
index 000000000..978fb048e
--- /dev/null
+++ b/gio/gwin32sid.c
@@ -0,0 +1,209 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2018 Руслан Ижбулатов
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Руслан Ижбулатов <lrn1986 gmail com>
+ */
+
+#include "config.h"
+
+#include "gwin32sid.h"
+#include "gioerror.h"
+
+#include <sddl.h>
+
+/**
+ * _g_win32_sid_replace: (skip)
+ * @dest: A pointer to a SID storage
+ * @src: Existing SID
+ * @error: return location for a #GError, or %NULL
+ *
+ * Creates a copy of the @src SID and puts that into @dest, after freeing
+ * existing SID in @dest (if any).
+ *
+ * The @src SID must be valid (use IsValidSid() to ensure that).
+ *
+ * Returns: TRUE on success, FALSE otherwise
+ */
+static gboolean
+_g_win32_sid_replace (SID **dest,
+ SID *src,
+ GError **error)
+{
+ DWORD sid_len;
+ SID *new_sid;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ g_return_val_if_fail (src != NULL, FALSE);
+ g_return_val_if_fail (dest && *dest == NULL, FALSE);
+
+ sid_len = GetLengthSid (src);
+ new_sid = g_malloc (sid_len);
+
+ if (!CopySid (sid_len, new_sid, src))
+ {
+ g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "Failed to copy SID");
+
+ g_free (new_sid);
+ return FALSE;
+ }
+ else
+ {
+ g_free (*dest);
+ *dest = g_steal_pointer (&new_sid);
+
+ return TRUE;
+ }
+}
+
+/**
+ * _g_win32_token_get_sid: (skip)
+ * @token: A handle of an access token
+ * @error: return location for a #GError, or %NULL
+ *
+ * Gets user SID of the @token and returns a copy of that SID.
+ *
+ * Returns: A newly-allocated SID, or NULL in case of an error.
+ * Free the returned SID with g_free().
+ */
+static SID *
+_g_win32_token_get_sid (HANDLE token,
+ GError **error)
+{
+ TOKEN_USER *token_user = NULL;
+ DWORD n;
+ PSID psid;
+ SID *result = NULL;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (!GetTokenInformation (token, TokenUser, NULL, 0, &n)
+ && GetLastError () != ERROR_INSUFFICIENT_BUFFER)
+ {
+ g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "Failed to GetTokenInformation");
+
+ return NULL;
+ }
+
+ token_user = g_alloca (n);
+
+ if (!GetTokenInformation (token, TokenUser, token_user, n, &n))
+ {
+ g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "Failed to GetTokenInformation");
+
+ return NULL;
+ }
+
+ psid = token_user->User.Sid;
+
+ if (!IsValidSid (psid))
+ {
+ g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "Invalid SID token");
+
+ return NULL;
+ }
+
+ _g_win32_sid_replace (&result, psid, error);
+
+ return result;
+}
+
+/**
+ * _g_win32_process_get_access_token_sid: (skip)
+ * @process_id: Identifier of a process to get an access token of
+ * (use 0 to get a token of the current process)
+ * @error: return location for a #GError, or %NULL
+ *
+ * Opens the process identified by @process_id and opens its token,
+ * then retrieves SID of the token user and returns a copy of that SID.
+ *
+ * Returns: A newly-allocated SID, or NULL in case of an error.
+ * Free the returned SID with g_free().
+ */
+SID *
+_g_win32_process_get_access_token_sid (DWORD process_id,
+ GError **error)
+{
+ HANDLE process_handle;
+ HANDLE process_token;
+ SID *result = NULL;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (process_id == 0)
+ process_handle = GetCurrentProcess ();
+ else
+ process_handle = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, process_id);
+
+ if (process_handle == NULL)
+ {
+ g_set_error (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "%s failed", process_id == 0 ? "GetCurrentProcess" : "OpenProcess");
+
+ return NULL;
+ }
+
+ if (!OpenProcessToken (process_handle, TOKEN_QUERY, &process_token))
+ {
+ g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "OpenProcessToken failed");
+
+ CloseHandle (process_handle);
+ return NULL;
+ }
+
+ result = _g_win32_token_get_sid (process_token, error);
+
+ CloseHandle (process_token);
+ CloseHandle (process_handle);
+
+ return result;
+}
+
+/**
+ * _g_win32_sid_to_string: (skip)
+ * @sid: a SID.
+ * @error: return location for a #GError, or %NULL
+ *
+ * Convert a SID to its string form.
+ *
+ * Returns: A newly-allocated string, or NULL in case of an error.
+ */
+gchar *
+_g_win32_sid_to_string (SID *sid, GError **error)
+{
+ gchar *tmp, *ret;
+
+ g_return_val_if_fail (sid != NULL, NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ if (!ConvertSidToStringSidA (sid, &tmp))
+ {
+ g_set_error_literal (error, G_IO_ERROR, g_io_error_from_errno (GetLastError ()),
+ "Failed to ConvertSidToString");
+
+ return NULL;
+ }
+
+ ret = g_strdup (tmp);
+ LocalFree (tmp);
+ return ret;
+}
diff --git a/gio/gwin32sid.h b/gio/gwin32sid.h
new file mode 100644
index 000000000..030eac529
--- /dev/null
+++ b/gio/gwin32sid.h
@@ -0,0 +1,38 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2018 Руслан Ижбулатов
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Руслан Ижбулатов <lrn1986 gmail com>
+ */
+
+#ifndef __G_WIN32_SID_H__
+#define __G_WIN32_SID_H__
+
+#include <glib.h>
+#include <windows.h>
+
+G_BEGIN_DECLS
+
+SID * _g_win32_process_get_access_token_sid (DWORD process_id,
+ GError **error);
+
+gchar * _g_win32_sid_to_string (SID *sid,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __G_WIN32_SID_H__ */
diff --git a/gio/meson.build b/gio/meson.build
index c0e23291a..dbe903db2 100644
--- a/gio/meson.build
+++ b/gio/meson.build
@@ -433,6 +433,8 @@ else
'gwin32networkmonitor.c',
'gwin32networkmonitor.h',
'gwin32notificationbackend.c',
+ 'gwin32sid.c',
+ 'gwin32sid.h',
)
gio_win_rc = configure_file(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]