From: Eric Biggers Date: Sun, 18 Aug 2013 15:37:57 +0000 (-0500) Subject: Update security descriptor setting X-Git-Tag: v1.5.0~41 X-Git-Url: https://wimlib.net/git/?p=wimlib;a=commitdiff_plain;h=fd0584f6e32ed9ef19899b29d5f9aa6f4d9432f3 Update security descriptor setting --- diff --git a/include/wimlib/apply.h b/include/wimlib/apply.h index 31cda98f..ef623a6f 100644 --- a/include/wimlib/apply.h +++ b/include/wimlib/apply.h @@ -209,6 +209,8 @@ struct apply_ctx { tchar *realtarget; size_t realtarget_nchars; unsigned long invalid_sequence; + unsigned long partial_security_descriptors; + unsigned long no_security_descriptors; u64 num_streams_remaining; bool root_dentry_is_special; uint64_t next_progress; diff --git a/src/extract.c b/src/extract.c index c9a1dca0..3b434c42 100644 --- a/src/extract.c +++ b/src/extract.c @@ -766,11 +766,14 @@ extract_security(const tchar *path, struct apply_ctx *ctx, "descriptor on \"%"TS"\"", path); return ret; } else { + #if 0 if (errno != EACCES) { WARNING_WITH_ERRNO("Failed to set " "security descriptor " "on \"%"TS"\"", path); } + #endif + ctx->no_security_descriptors++; } } } @@ -2040,6 +2043,31 @@ do_feature_check(const struct wim_features *required_features, return 0; } +static void +do_extract_warnings(struct apply_ctx *ctx) +{ + if (ctx->partial_security_descriptors == 0 && + ctx->no_security_descriptors == 0) + return; + + WARNING("Extraction of \"%"TS"\" complete, but with one or more warnings:", + ctx->target); + if (ctx->partial_security_descriptors != 0) { + WARNING("- Could only partially set the security descriptor\n" + " on %lu files or directories.", + ctx->partial_security_descriptors); + } + if (ctx->no_security_descriptors != 0) { + WARNING("- Could not set security descriptor at all\n" + " on %lu files or directories.", + ctx->no_security_descriptors); + } +#ifdef __WIN32__ + WARNING("To fully restore all security descriptors, run the program\n" + " with Administrator rights."); +#endif +} + /* * extract_tree - Extract a file or directory tree from the currently selected * WIM image. @@ -2346,6 +2374,8 @@ extract_tree(WIMStruct *wim, const tchar *wim_source_path, const tchar *target, &ctx.progress); } + do_extract_warnings(&ctx); + ret = 0; out_free_realtarget: FREE(ctx.realtarget); diff --git a/src/win32_apply.c b/src/win32_apply.c index 77ff870e..b6f2e84c 100644 --- a/src/win32_apply.c +++ b/src/win32_apply.c @@ -33,6 +33,15 @@ #include "wimlib/error.h" #include "wimlib/lookup_table.h" +#ifdef WITH_NTDLL +# include +# include +NTSTATUS WINAPI +NtSetSecurityObject(HANDLE Handle, + SECURITY_INFORMATION SecurityInformation, + PSECURITY_DESCRIPTOR SecurityDescriptor); +#endif + static int win32_start_extract(const wchar_t *path, struct apply_ctx *ctx) { @@ -478,32 +487,84 @@ error: return WIMLIB_ERR_WRITE; /* XXX: need better error code */ } +static DWORD +do_win32_set_security_descriptor(HANDLE h, const wchar_t *path, + SECURITY_INFORMATION info, + PSECURITY_DESCRIPTOR desc) +{ +#ifdef WITH_NTDLL + return RtlNtStatusToDosError(NtSetSecurityObject(h, info, desc)); +#else + if (SetFileSecurity(path, info, desc)) + return ERROR_SUCCESS; + else + return GetLastError(); +#endif +} + static int -win32_set_security_descriptor(const wchar_t *path, const u8 *desc, size_t desc_size, - struct apply_ctx *ctx) +win32_set_security_descriptor(const wchar_t *path, const u8 *desc, + size_t desc_size, struct apply_ctx *ctx) { SECURITY_INFORMATION info; + HANDLE h; + DWORD err; + int ret; - info = OWNER_SECURITY_INFORMATION | - GROUP_SECURITY_INFORMATION | - DACL_SECURITY_INFORMATION | - SACL_SECURITY_INFORMATION; -retry: - if (!SetFileSecurity(path, info, (PSECURITY_DESCRIPTOR)desc)) { - if (!(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS) && - GetLastError() == ERROR_PRIVILEGE_NOT_HELD && - (info & SACL_SECURITY_INFORMATION)) + info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | + DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION; + h = INVALID_HANDLE_VALUE; + +#ifdef WITH_NTDLL + h = CreateFile(path, MAXIMUM_ALLOWED, 0, NULL, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | + FILE_FLAG_OPEN_REPARSE_POINT, + NULL); + if (h == INVALID_HANDLE_VALUE) { + ERROR_WITH_ERRNO("Can't open %ls (%u)", path, GetLastError()); + goto error; + } +#endif + + for (;;) { + err = do_win32_set_security_descriptor(h, path, info, + (PSECURITY_DESCRIPTOR)desc); + if (err == ERROR_SUCCESS) + break; + if ((err == ERROR_PRIVILEGE_NOT_HELD || + err == ERROR_ACCESS_DENIED) && + !(ctx->extract_flags & WIMLIB_EXTRACT_FLAG_STRICT_ACLS)) { - info &= ~SACL_SECURITY_INFORMATION; - goto retry; + if (info & SACL_SECURITY_INFORMATION) { + info &= ~SACL_SECURITY_INFORMATION; + ctx->partial_security_descriptors++; + continue; + } + if (info & DACL_SECURITY_INFORMATION) { + info &= ~DACL_SECURITY_INFORMATION; + continue; + } + if (info & OWNER_SECURITY_INFORMATION) { + info &= ~OWNER_SECURITY_INFORMATION; + continue; + } + ctx->partial_security_descriptors--; + ctx->no_security_descriptors++; + break; } goto error; } - return 0; + ret = 0; +out_close: +#ifdef WITH_NTDLL + CloseHandle(h); +#endif + return ret; error: set_errno_from_GetLastError(); - return WIMLIB_ERR_SET_SECURITY; + ret = WIMLIB_ERR_SET_SECURITY; + goto out_close; } static int