Win32: Acquire/release appropriate privileges
authorEric Biggers <ebiggers3@gmail.com>
Sun, 17 Mar 2013 02:16:08 +0000 (21:16 -0500)
committerEric Biggers <ebiggers3@gmail.com>
Sun, 17 Mar 2013 02:16:08 +0000 (21:16 -0500)
src/add_image.c
src/extract_image.c
src/wimlib_internal.h
src/win32.c

index 5b51f49..0ae5736 100644 (file)
@@ -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;
 }
 
index 6fb9442..8e5d130 100644 (file)
@@ -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))
index 193abc5..5a076a5 100644 (file)
@@ -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
index 7868b5f..3ac8dec 100644 (file)
@@ -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__ */