]> wimlib.net Git - wimlib/blobdiff - src/win32_capture.c
win32_capture.c: fix for opening encrypted files when key is unavailable
[wimlib] / src / win32_capture.c
index 449e73e07714dd5a6d2724a8a289d40eac0fff1b..264551b171f2ca653db79bc6526d421bfe1ff054 100644 (file)
 #  include "config.h"
 #endif
 
+#include <errno.h>
+
 #include "wimlib/win32_common.h"
 
+#include "wimlib/assert.h"
 #include "wimlib/capture.h"
 #include "wimlib/dentry.h"
 #include "wimlib/encoding.h"
@@ -38,8 +41,6 @@
 #include "wimlib/paths.h"
 #include "wimlib/reparse.h"
 
-#include <errno.h>
-
 struct winnt_scan_stats {
        unsigned long num_get_sd_access_denied;
        unsigned long num_get_sacl_priv_notheld;
@@ -385,7 +386,7 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                  size_t full_path_nchars,
                                  const wchar_t *filename,
                                  size_t filename_nchars,
-                                 struct add_image_params *params,
+                                 struct capture_params *params,
                                  struct winnt_scan_stats *stats,
                                  u32 vol_flags);
 
@@ -394,7 +395,7 @@ winnt_recurse_directory(HANDLE h,
                        wchar_t *full_path,
                        size_t full_path_nchars,
                        struct wim_dentry *parent,
-                       struct add_image_params *params,
+                       struct capture_params *params,
                        struct winnt_scan_stats *stats,
                        u32 vol_flags)
 {
@@ -610,7 +611,7 @@ out_close_root_dir:
 }
 
 static int
-winnt_rpfix_progress(struct add_image_params *params, const wchar_t *path,
+winnt_rpfix_progress(struct capture_params *params, const wchar_t *path,
                     const struct reparse_data *rpdata, int scan_status)
 {
        size_t print_name_nchars = rpdata->print_name_nbytes / sizeof(wchar_t);
@@ -627,7 +628,7 @@ winnt_rpfix_progress(struct add_image_params *params, const wchar_t *path,
 static int
 winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
                u64 capture_root_ino, u64 capture_root_dev,
-               const wchar_t *path, struct add_image_params *params)
+               const wchar_t *path, struct capture_params *params)
 {
        struct reparse_data rpdata;
        const wchar_t *rel_target;
@@ -746,7 +747,7 @@ winnt_try_rpfix(u8 *rpbuf, u16 *rpbuflen_p,
  */
 static int
 winnt_get_reparse_data(HANDLE h, const wchar_t *path,
-                      struct add_image_params *params,
+                      struct capture_params *params,
                       u8 *rpbuf, u16 *rpbuflen_ret)
 {
        DWORD bytes_returned;
@@ -1100,7 +1101,7 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                                  size_t full_path_nchars,
                                  const wchar_t *filename,
                                  size_t filename_nchars,
-                                 struct add_image_params *params,
+                                 struct capture_params *params,
                                  struct winnt_scan_stats *stats,
                                  u32 vol_flags)
 {
@@ -1113,6 +1114,7 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
        u8 *rpbuf;
        u16 rpbuflen;
        u16 not_rpfixed;
+       ACCESS_MASK requestedPerms;
 
        ret = try_exclude(full_path, full_path_nchars, params);
        if (ret < 0) /* Excluded? */
@@ -1121,32 +1123,44 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                goto out;
 
        /* Open the file.  */
+       requestedPerms = FILE_READ_DATA |
+                        FILE_READ_ATTRIBUTES |
+                        READ_CONTROL |
+                        ACCESS_SYSTEM_SECURITY |
+                        SYNCHRONIZE;
+retry_open:
        status = winnt_openat(cur_dir,
                              (cur_dir ? filename : full_path),
                              (cur_dir ? filename_nchars : full_path_nchars),
-                             FILE_READ_DATA |
-                                       FILE_READ_ATTRIBUTES |
-                                       READ_CONTROL |
-                                       ACCESS_SYSTEM_SECURITY |
-                                       SYNCHRONIZE,
+                             requestedPerms,
                              &h);
        if (unlikely(!NT_SUCCESS(status))) {
                if (status == STATUS_DELETE_PENDING) {
                        WARNING("\"%ls\": Deletion pending; skipping file",
                                printable_path(full_path));
                        ret = 0;
-               } else {
-                       set_errno_from_nt_status(status);
-                       ERROR_WITH_ERRNO("\"%ls\": Can't open file "
-                                        "(status=0x%08"PRIx32")",
-                                        printable_path(full_path), (u32)status);
-                       if (status == STATUS_FVE_LOCKED_VOLUME)
-                               ret = WIMLIB_ERR_FVE_LOCKED_VOLUME;
-                       else
-                               ret = WIMLIB_ERR_OPEN;
+                       goto out;
+               }
+               if (status == STATUS_ACCESS_DENIED &&
+                   (requestedPerms & FILE_READ_DATA)) {
+                       /* This happens on encrypted files.  */
+                       requestedPerms &= ~FILE_READ_DATA;
+                       goto retry_open;
                }
-               /* XXX: Provide option to exclude files that fail with
-                * STATUS_SHARING_VIOLATION?  */
+
+               if (status == STATUS_FVE_LOCKED_VOLUME) {
+                       ERROR("\"%ls\": Can't open file "
+                             "(encrypted volume has not been unlocked)",
+                             printable_path(full_path));
+                       ret = WIMLIB_ERR_FVE_LOCKED_VOLUME;
+                       goto out;
+               }
+
+               set_errno_from_nt_status(status);
+               ERROR_WITH_ERRNO("\"%ls\": Can't open file "
+                                "(status=0x%08"PRIx32")",
+                                printable_path(full_path), (u32)status);
+               ret = WIMLIB_ERR_OPEN;
                goto out;
        }
 
@@ -1171,6 +1185,15 @@ winnt_build_dentry_tree_recursive(struct wim_dentry **root_ret,
                }
        }
 
+       if (unlikely(!(requestedPerms & FILE_READ_DATA)) &&
+           !(file_info.BasicInformation.FileAttributes & FILE_ATTRIBUTE_ENCRYPTED))
+       {
+               ERROR("\"%ls\": Permission to read data was denied",
+                     printable_path(full_path));
+               ret = WIMLIB_ERR_OPEN;
+               goto out;
+       }
+
        if (unlikely(!cur_dir)) {
 
                /* Root of tree being captured; get volume information.  */
@@ -1420,7 +1443,7 @@ winnt_do_scan_warnings(const wchar_t *path, const struct winnt_scan_stats *stats
 int
 win32_build_dentry_tree(struct wim_dentry **root_ret,
                        const wchar_t *root_disk_path,
-                       struct add_image_params *params)
+                       struct capture_params *params)
 {
        wchar_t *path;
        int ret;