mirror of
				https://gitlab.gnome.org/GNOME/glib.git
				synced 2025-10-31 00:12:19 +01:00 
			
		
		
		
	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>
This commit is contained in:
		
							
								
								
									
										209
									
								
								gio/gwin32sid.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								gio/gwin32sid.c
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||
| } | ||||
							
								
								
									
										38
									
								
								gio/gwin32sid.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								gio/gwin32sid.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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__ */ | ||||
| @@ -433,6 +433,8 @@ else | ||||
|     'gwin32networkmonitor.c', | ||||
|     'gwin32networkmonitor.h', | ||||
|     'gwin32notificationbackend.c', | ||||
|     'gwin32sid.c', | ||||
|     'gwin32sid.h', | ||||
|   ) | ||||
|  | ||||
|   gio_win_rc = configure_file( | ||||
|   | ||||
		Reference in New Issue
	
	Block a user