From 761a138b6419c30f6213af46186f678600750404 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 17 Aug 2013 18:00:58 -0500 Subject: [PATCH] Add WIMLIB_INIT_FLAG_STRICT_{CAPTURE,APPLY}_PRIVILEGES --- doc/imagex-apply.1.in | 3 -- include/wimlib.h | 72 ++++++++++++++++++++++++++++-------------- include/wimlib/win32.h | 2 +- programs/imagex.c | 4 ++- src/util.c | 2 ++ src/wim.c | 9 ++++-- src/win32_common.c | 44 ++++++++++++-------------- 7 files changed, 82 insertions(+), 54 deletions(-) diff --git a/doc/imagex-apply.1.in b/doc/imagex-apply.1.in index 26128707..1166a6a6 100644 --- a/doc/imagex-apply.1.in +++ b/doc/imagex-apply.1.in @@ -374,9 +374,6 @@ default, invalid names will be ignored, and if there are multiple names differing only in case, one will be chosen to extract arbitrarily; however, with \fB--include-invalid-names\fR, all names will be sanitized and extracted in some form. -.TP -\fB--resume\fR -TODO .SH NOTES \fB@IMAGEX_PROGNAME@ apply\fR calculates the SHA1 message digest of every file stream it extracts and verifies that it is the same as the SHA1 message digest diff --git a/include/wimlib.h b/include/wimlib.h index 69a58b0e..f938add0 100644 --- a/include/wimlib.h +++ b/include/wimlib.h @@ -936,7 +936,7 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * contain this information. Please note that this flag is for convenience * only; Microsoft's @a imagex.exe will not understand this special information. * This flag cannot be combined with ::WIMLIB_ADD_FLAG_NTFS. */ -#define WIMLIB_ADD_FLAG_UNIX_DATA 0x00000010 +#define WIMLIB_ADD_FLAG_UNIX_DATA 0x00000010 /** Do not capture security descriptors. Only has an effect in NTFS capture * mode, or in Win32 native builds. */ @@ -971,10 +971,10 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * documentation for ::WIMLIB_ADD_FLAG_RPFIX. */ #define WIMLIB_ADD_FLAG_NORPFIX 0x00000200 -/** Do not exclude unsupported files or directories from capture; e.g. encrypted - * directories in NTFS-3g capture mode, or device files and FIFOs on UNIX-like - * systems. Instead, fail with ::WIMLIB_ERR_UNSUPPORTED_FILE when such a file - * is encountered. */ +/** Do not automatically exclude unsupported files or directories from capture; + * e.g. encrypted directories in NTFS-3g capture mode, or device files and FIFOs + * on UNIX-like systems. Instead, fail with ::WIMLIB_ERR_UNSUPPORTED_FILE when + * such a file is encountered. */ #define WIMLIB_ADD_FLAG_NO_UNSUPPORTED_EXCLUDE 0x00000400 /** Automatically select a capture configuration appropriate for capturing @@ -1057,8 +1057,9 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour /** Read the WIM file sequentially while extracting the image. */ #define WIMLIB_EXTRACT_FLAG_SEQUENTIAL 0x00000010 -/** Extract special UNIX data captured with ::WIMLIB_ADD_FLAG_UNIX_DATA. - * Cannot be used with ::WIMLIB_EXTRACT_FLAG_NTFS. */ +/** Extract special UNIX data captured with ::WIMLIB_ADD_FLAG_UNIX_DATA. Only + * valid on UNIX-like platforms, and when ::WIMLIB_EXTRACT_FLAG_NTFS was not + * specified. */ #define WIMLIB_EXTRACT_FLAG_UNIX_DATA 0x00000020 /** Do not extract security descriptors. */ @@ -1112,10 +1113,10 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * create symbolic links. */ #define WIMLIB_EXTRACT_FLAG_STRICT_SYMLINKS 0x00008000 -/** TODO */ +/** TODO: this flag is intended to allow resuming an aborted extraction, but the + * behavior is currently less than satisfactory. Do not use (yet). */ #define WIMLIB_EXTRACT_FLAG_RESUME 0x00010000 - /****************************** * WIMLIB_MOUNT_FLAG_* ******************************/ @@ -1153,39 +1154,41 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * causes the raw data of the WIM file, divided into 10 MB chunks, to be * checksummed and checked against the SHA1 message digests specified in the * integrity table. ::WIMLIB_ERR_INTEGRITY is returned if there are any - * mismatches. */ + * mismatches (or, ::WIMLIB_ERR_INVALID_INTEGRITY_TABLE is returned if the + * integrity table is invalid). */ #define WIMLIB_OPEN_FLAG_CHECK_INTEGRITY 0x00000001 -/** Do not issue an error if the WIM is part of a split WIM. */ +/** Do not issue an error if the WIM is part of a split WIM. Programs must + * specify this flag if they intend to open part of a split WIM, rather than + * only supporting standalone WIMs. */ #define WIMLIB_OPEN_FLAG_SPLIT_OK 0x00000002 /** Check if the WIM is writable and return ::WIMLIB_ERR_WIM_IS_READONLY if it * is not. A WIM is considered writable only if it is writable at the * filesystem level, does not have the WIM_HDR_FLAG_READONLY flag set in its * header, and is not part of a spanned set. It is not required to provide this - * flag to make changes to the WIM, but with this flag you get the error sooner - * rather than later. */ + * flag before attempting to make changes to the WIM, but with this flag you get + * an error sooner rather than later. */ #define WIMLIB_OPEN_FLAG_WRITE_ACCESS 0x00000004 /****************************** * WIMLIB_UNMOUNT_FLAG_* ******************************/ -/** Include an integrity table in the WIM after it's been unmounted. Ignored - * for read-only mounts. */ +/** See ::WIMLIB_WRITE_FLAG_CHECK_INTEGRITY. */ #define WIMLIB_UNMOUNT_FLAG_CHECK_INTEGRITY 0x00000001 /** Unless this flag is given, changes to a read-write mounted WIM are - * discarded. Ignored for read-only mounts. */ + * discarded. Ignored for read-only mounts. */ #define WIMLIB_UNMOUNT_FLAG_COMMIT 0x00000002 -/** See ::WIMLIB_WRITE_FLAG_REBUILD */ +/** See ::WIMLIB_WRITE_FLAG_REBUILD. */ #define WIMLIB_UNMOUNT_FLAG_REBUILD 0x00000004 /** See ::WIMLIB_WRITE_FLAG_RECOMPRESS */ #define WIMLIB_UNMOUNT_FLAG_RECOMPRESS 0x00000008 -/** Do a "lazy" unmount (detach filesystem immediately, even if busy) */ +/** Do a "lazy" unmount (detach filesystem immediately, even if busy). */ #define WIMLIB_UNMOUNT_FLAG_LAZY 0x00000010 /****************************** @@ -1193,7 +1196,7 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour ******************************/ /** Send ::WIMLIB_PROGRESS_MSG_UPDATE_BEGIN_COMMAND and - * ::WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND messages. */ + * ::WIMLIB_PROGRESS_MSG_UPDATE_END_COMMAND messages. */ #define WIMLIB_UPDATE_FLAG_SEND_PROGRESS 0x00000001 /****************************** @@ -1248,7 +1251,7 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * only minimal changes to correctly remove the image from the WIM will be * taken. In particular, all streams will be left alone, even if they are no * longer referenced. This is probably not what you want, because almost no - * space will be saved by deleting an image in this way. */ + * space will be saved by deleting an image in this way. */ #define WIMLIB_WRITE_FLAG_SOFT_DELETE 0x00000080 /** wimlib_overwrite() only: Allow overwriting the WIM even if the readonly @@ -1262,7 +1265,8 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour ******************************/ /** Assume that strings are represented in UTF-8, even if this is not the - * locale's character encoding. Not used on Windows. */ + * locale's character encoding. This flag is ignored on Windows, where wimlib + * always uses UTF-16LE. */ #define WIMLIB_INIT_FLAG_ASSUME_UTF8 0x00000001 /** Windows-only: do not attempt to acquire additional privileges (currently @@ -1274,6 +1278,20 @@ typedef int (*wimlib_iterate_lookup_table_callback_t)(const struct wimlib_resour * actually require additional privileges or not. */ #define WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES 0x00000002 +/** Windows only: If ::WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES not specified, + * return ::WIMLIB_ERR_INSUFFICIENT_PRIVILEGES if privileges that may be needed + * to read all possible data and metadata for a capture operation could not be + * acquired. Can be combined with ::WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES. + */ +#define WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES 0x00000004 + +/** Windows only: If ::WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES not specified, + * return ::WIMLIB_ERR_INSUFFICIENT_PRIVILEGES if privileges that may be needed + * to restore all possible data and metadata for an apply operation could not be + * acquired. Can be combined with ::WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES. + */ +#define WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES 0x00000008 + /** Specification of an update to perform on a WIM image. */ struct wimlib_update_command { @@ -1366,6 +1384,7 @@ enum wimlib_error_code { WIMLIB_ERR_ICONV_NOT_AVAILABLE, WIMLIB_ERR_IMAGE_COUNT, WIMLIB_ERR_IMAGE_NAME_COLLISION, + WIMLIB_ERR_INSUFFICIENT_PRIVILEGES, WIMLIB_ERR_INTEGRITY, WIMLIB_ERR_INVALID_CAPTURE_CONFIG, WIMLIB_ERR_INVALID_CHUNK_SIZE, @@ -2103,10 +2122,15 @@ wimlib_get_wim_info(WIMStruct *wim, struct wimlib_wim_info *info); * but you should not rely on this behavior.) * * @param init_flags - * Bitwise OR of ::WIMLIB_INIT_FLAG_ASSUME_UTF8 and/or - * ::WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES. + * Bitwise OR of flags prefixed with WIMLIB_INIT_FLAG. + * + * @return 0 on success; nonzero on failure. Currently, only the following + * error code is defined: * - * @return 0; other error codes may be returned in future releases. + * @retval ::WIMLIB_ERR_INSUFFICIENT_PRIVILEGES + * ::WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES and/or + * ::WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES were specified in @p + * init_flags, but the corresponding privileges could not be acquired. */ extern int wimlib_global_init(int init_flags); diff --git a/include/wimlib/win32.h b/include/wimlib/win32.h index 04fa4d12..e2bdde0e 100644 --- a/include/wimlib/win32.h +++ b/include/wimlib/win32.h @@ -26,7 +26,7 @@ read_win32_encrypted_file_prefix(const struct wim_lookup_table_entry *lte, int _ignored_flags); -extern void +extern int win32_global_init(int init_flags); extern void diff --git a/programs/imagex.c b/programs/imagex.c index 93072e4b..d005a12b 100644 --- a/programs/imagex.c +++ b/programs/imagex.c @@ -174,6 +174,8 @@ static const struct option apply_options[] = { {T("rpfix"), no_argument, NULL, IMAGEX_RPFIX_OPTION}, {T("norpfix"), no_argument, NULL, IMAGEX_NORPFIX_OPTION}, {T("include-invalid-names"), no_argument, NULL, IMAGEX_INCLUDE_INVALID_NAMES_OPTION}, + + /* --resume is undocumented for now as it needs improvement. */ {T("resume"), no_argument, NULL, IMAGEX_RESUME_OPTION}, {NULL, 0, NULL, 0}, }; @@ -3446,7 +3448,7 @@ T( " (DIRECTORY | NTFS_VOLUME) [--check] [--hardlink]\n" " [--symlink] [--verbose] [--ref=\"GLOB\"] [--unix-data]\n" " [--no-acls] [--strict-acls] [--rpfix] [--norpfix]\n" -" [--include-invalid-names] [--resume]\n" +" [--include-invalid-names]\n" ), [CMD_CAPTURE] = T( diff --git a/src/util.c b/src/util.c index 8875e4cb..9250b701 100644 --- a/src/util.c +++ b/src/util.c @@ -290,6 +290,8 @@ static const tchar *error_strings[] = { "resources, the WIM header, and/or the XML data"), [WIMLIB_ERR_IMAGE_NAME_COLLISION] = T("Tried to add an image with a name that is already in use"), + [WIMLIB_ERR_INSUFFICIENT_PRIVILEGES] + = T("The user does not have sufficient privileges"), [WIMLIB_ERR_INTEGRITY] = T("The WIM failed an integrity check"), [WIMLIB_ERR_INVALID_CAPTURE_CONFIG] diff --git a/src/wim.c b/src/wim.c index 1e006dab..5ebf94ca 100644 --- a/src/wim.c +++ b/src/wim.c @@ -797,6 +797,7 @@ WIMLIBAPI int wimlib_global_init(int init_flags) { static bool already_inited = false; + int ret; if (already_inited) return 0; @@ -809,10 +810,14 @@ wimlib_global_init(int init_flags) #endif } #ifdef __WIN32__ - win32_global_init(init_flags); + ret = win32_global_init(init_flags); + if (ret) + return ret; +#else + ret = 0; #endif already_inited = true; - return 0; + return ret; } /* API function documented in wimlib.h */ diff --git a/src/win32_common.c b/src/win32_common.c index c6605b4b..5a2b7948 100644 --- a/src/win32_common.c +++ b/src/win32_common.c @@ -479,38 +479,26 @@ out: return ret; } -static void +static bool win32_modify_capture_privileges(bool enable) { - win32_modify_privilege(SE_BACKUP_NAME, enable); - win32_modify_privilege(SE_SECURITY_NAME, enable); + return win32_modify_privilege(SE_BACKUP_NAME, enable) + && win32_modify_privilege(SE_SECURITY_NAME, enable); } -static void +static bool win32_modify_apply_privileges(bool enable) { - win32_modify_privilege(SE_RESTORE_NAME, enable); - win32_modify_privilege(SE_SECURITY_NAME, enable); - win32_modify_privilege(SE_TAKE_OWNERSHIP_NAME, enable); -} - -static void -win32_modify_capture_and_apply_privileges(bool enable) -{ - win32_modify_capture_privileges(enable); - win32_modify_apply_privileges(enable); -} - -static void -win32_acquire_capture_and_apply_privileges(void) -{ - win32_modify_capture_and_apply_privileges(true); + return win32_modify_privilege(SE_RESTORE_NAME, enable) + && win32_modify_privilege(SE_SECURITY_NAME, enable) + && win32_modify_privilege(SE_TAKE_OWNERSHIP_NAME, enable); } static void win32_release_capture_and_apply_privileges(void) { - win32_modify_capture_and_apply_privileges(false); + win32_modify_capture_privileges(false); + win32_modify_apply_privileges(false); } HANDLE @@ -563,12 +551,17 @@ windows_version_is_at_least(unsigned major, unsigned minor) } /* One-time initialization for Windows capture/apply code. */ -void +int win32_global_init(int init_flags) { /* Try to acquire useful privileges. */ if (!(init_flags & WIMLIB_INIT_FLAG_DONT_ACQUIRE_PRIVILEGES)) { - win32_acquire_capture_and_apply_privileges(); + if (!win32_modify_capture_privileges(true)) + if (init_flags & WIMLIB_INIT_FLAG_STRICT_CAPTURE_PRIVILEGES) + goto insufficient_privileges; + if (!win32_modify_apply_privileges(true)) + if (init_flags & WIMLIB_INIT_FLAG_STRICT_APPLY_PRIVILEGES) + goto insufficient_privileges; acquired_privileges = true; } @@ -589,6 +582,11 @@ win32_global_init(int init_flags) win32func_FindFirstStreamW = NULL; } } + return 0; + +insufficient_privileges: + win32_release_capture_and_apply_privileges(); + return WIMLIB_ERR_INSUFFICIENT_PRIVILEGES; } void -- 2.43.0