From: Eric Biggers Date: Sun, 17 Mar 2013 02:16:08 +0000 (-0500) Subject: Win32: Acquire/release appropriate privileges X-Git-Tag: v1.3.0~27 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=655c1ad6412165c62a9489a44161b62b93489838 Win32: Acquire/release appropriate privileges --- diff --git a/src/add_image.c b/src/add_image.c index 5b51f493..0ae57361 100644 --- a/src/add_image.c +++ b/src/add_image.c @@ -536,6 +536,7 @@ out_find_close: FindClose(hFind); return ret; } + #endif /* @@ -939,11 +940,11 @@ static int build_dentry_tree(struct wim_dentry **root_ret, } out_close_handle: CloseHandle(hFile); +out_free_path_utf16: + FREE(path_utf16); out_destroy_sd_set: if (extra_arg == NULL) destroy_sd_set(sd_set); -out_free_path_utf16: - FREE(path_utf16); #endif /* The below lines of code are common to both UNIX and Win32 builds. It * simply returns the captured directory tree if the capture was @@ -1544,6 +1545,11 @@ WIMLIBAPI int wimlib_add_image_multisource(WIMStruct *w, } else { size_t i; +#if defined(__CYGWIN__) || defined(__WIN32__) + win32_acquire_privilege(SE_BACKUP_NAME); + win32_acquire_privilege(SE_SECURITY_NAME); + win32_acquire_privilege(SE_TAKE_OWNERSHIP_NAME); +#endif root_dentry = NULL; i = 0; do { @@ -1637,6 +1643,11 @@ out_free_security_data: out_destroy_capture_config: destroy_capture_config(&config); out: +#if defined(__CYGWIN__) || defined(__WIN32__) + win32_release_privilege(SE_BACKUP_NAME); + win32_release_privilege(SE_SECURITY_NAME); + win32_release_privilege(SE_TAKE_OWNERSHIP_NAME); +#endif return ret; } diff --git a/src/extract_image.c b/src/extract_image.c index 6fb94427..8e5d130e 100644 --- a/src/extract_image.c +++ b/src/extract_image.c @@ -775,7 +775,6 @@ static int apply_dentry_timestamps_normal(struct wim_dentry *dentry, void *arg) size_t utf16_path_len; DWORD err; HANDLE h; - BOOL bret1, bret2; ret = utf8_to_utf16(output_path, len, &utf16_path, &utf16_path_len); if (ret) @@ -1319,6 +1318,11 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, w->lookup_table = joined_tab; } +#if defined(__CYGWIN__) || defined(__WIN32__) + win32_acquire_privilege(SE_RESTORE_NAME); + win32_acquire_privilege(SE_SECURITY_NAME); + win32_acquire_privilege(SE_TAKE_OWNERSHIP_NAME); +#endif if (image == WIMLIB_ALL_IMAGES) { extract_flags |= WIMLIB_EXTRACT_FLAG_MULTI_IMAGE; ret = extract_all_images(w, target, extract_flags, @@ -1328,6 +1332,11 @@ WIMLIBAPI int wimlib_extract_image(WIMStruct *w, ret = extract_single_image(w, image, target, extract_flags, progress_func); } +#if defined(__CYGWIN__) || defined(__WIN32__) + win32_release_privilege(SE_RESTORE_NAME); + win32_release_privilege(SE_SECURITY_NAME); + win32_release_privilege(SE_TAKE_OWNERSHIP_NAME); +#endif if (extract_flags & (WIMLIB_EXTRACT_FLAG_SYMLINK | WIMLIB_EXTRACT_FLAG_HARDLINK)) diff --git a/src/wimlib_internal.h b/src/wimlib_internal.h index 193abc5e..5a076a5c 100644 --- a/src/wimlib_internal.h +++ b/src/wimlib_internal.h @@ -535,6 +535,8 @@ extern int win32_read_file(const char *filename, void *handle, u64 offset, size_t size, u8 *buf); extern void *win32_open_file_readonly(const void *path_utf16); extern void win32_close_file(void *handle); +extern bool win32_acquire_privilege(const char *privilege); +extern bool win32_release_privilege(const char *privilege); #ifdef ENABLE_ERROR_MESSAGES extern void win32_error(u32 err); #else diff --git a/src/win32.c b/src/win32.c index 7868b5fa..3ac8deca 100644 --- a/src/win32.c +++ b/src/win32.c @@ -68,4 +68,57 @@ void win32_close_file(void *handle) CloseHandle((HANDLE)handle); } +static bool win32_modify_privilege(const char *privilege, bool enable) +{ + HANDLE hToken; + LUID luid; + TOKEN_PRIVILEGES newState; + bool ret = false; + + DEBUG("%s privilege %s", + enable ? "Enabling" : "Disabling", privilege); + + if (!OpenProcessToken(GetCurrentProcess(), + TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken)) + { + DEBUG("OpenProcessToken() failed"); + goto out; + } + + if (!LookupPrivilegeValue(NULL, privilege, &luid)) { + DEBUG("LookupPrivilegeValue() failed"); + goto out; + } + + newState.PrivilegeCount = 1; + newState.Privileges[0].Luid = luid; + newState.Privileges[0].Attributes = (enable ? SE_PRIVILEGE_ENABLED : 0); + ret = AdjustTokenPrivileges(hToken, FALSE, &newState, 0, NULL, NULL); + if (!ret) + DEBUG("AdjustTokenPrivileges() failed"); + CloseHandle(hToken); +out: + if (!ret) { + DWORD err = GetLastError(); + win32_error(err); + WARNING("Failed to %s privilege %s", + enable ? "enable" : "disable", privilege); + WARNING("The program will continue, but if permission issues are " + "encountered, you may need to run this program as the administrator"); + } + return ret; +} + +bool win32_acquire_privilege(const char *privilege) +{ + return win32_modify_privilege(privilege, true); +} + +bool win32_release_privilege(const char *privilege) +{ + return win32_modify_privilege(privilege, false); +} + + #endif /* __CYGWIN__ || __WIN32__ */