Add SMB_VFS_CONNECTPATH operation
authorVolker Lendecke <vl@samba.org>
Thu, 28 May 2009 17:20:14 +0000 (19:20 +0200)
committerVolker Lendecke <vl@samba.org>
Tue, 2 Jun 2009 09:58:22 +0000 (11:58 +0200)
This is required for the shadow_copy2 module and "wide links = no". The file
system snapshots by nature are typically outside of share directory. So the
REALPATH result fails the wide links = no test.

source3/include/vfs.h
source3/include/vfs_macros.h
source3/modules/vfs_default.c
source3/modules/vfs_full_audit.c
source3/smbd/vfs.c

index 0c0e0938bd823fbaee9b43a1461ad79f171b2dcc..9a736a7ca0662ffc1dd4b1040a80b1759e467ea7 100644 (file)
@@ -221,6 +221,7 @@ typedef enum _vfs_op_type {
        SMB_VFS_OP_FILE_ID_CREATE,
        SMB_VFS_OP_STREAMINFO,
        SMB_VFS_OP_GET_REAL_FILENAME,
+       SMB_VFS_OP_CONNECTPATH,
        SMB_VFS_OP_BRL_LOCK_WINDOWS,
        SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
        SMB_VFS_OP_BRL_CANCEL_WINDOWS,
@@ -402,6 +403,9 @@ struct vfs_ops {
                                         TALLOC_CTX *mem_ctx,
                                         char **found_name);
 
+               const char *(*connectpath)(struct vfs_handle_struct *handle,
+                                          const char *filename);
+
                NTSTATUS (*brl_lock_windows)(struct vfs_handle_struct *handle,
                                             struct byte_range_lock *br_lck,
                                             struct lock_struct *plock,
@@ -564,6 +568,7 @@ struct vfs_ops {
                struct vfs_handle_struct *file_id_create;
                struct vfs_handle_struct *streaminfo;
                struct vfs_handle_struct *get_real_filename;
+               struct vfs_handle_struct *connectpath;
                struct vfs_handle_struct *brl_lock_windows;
                struct vfs_handle_struct *brl_unlock_windows;
                struct vfs_handle_struct *brl_cancel_windows;
index acb158e3a5a975d46a8b1410d1822cf4bd968ddf..0b59f8f3ad0d39c4fa7de05acc124f7a7da5375e 100644 (file)
@@ -88,6 +88,7 @@
 #define SMB_VFS_FILE_ID_CREATE(conn, sbuf) ((conn)->vfs.ops.file_id_create((conn)->vfs.handles.file_id_create, (sbuf)))
 #define SMB_VFS_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs.ops.streaminfo((conn)->vfs.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 #define SMB_VFS_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs.ops.get_real_filename((conn)->vfs.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
+#define SMB_VFS_CONNECTPATH(conn, fname) ((conn)->vfs.ops.connectpath((conn)->vfs.handles.connectpath, (fname)))
 #define SMB_VFS_BRL_LOCK_WINDOWS(conn, br_lck, plock, blocking_lock, blr) ((conn)->vfs.ops.brl_lock_windows((conn)->vfs.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
 #define SMB_VFS_BRL_UNLOCK_WINDOWS(conn, msg_ctx, br_lck, plock) ((conn)->vfs.ops.brl_unlock_windows((conn)->vfs.handles.brl_unlock_windows, (msg_ctx), (br_lck), (plock)))
 #define SMB_VFS_BRL_CANCEL_WINDOWS(conn, br_lck, plock, blr) ((conn)->vfs.ops.brl_cancel_windows((conn)->vfs.handles.brl_cancel_windows, (br_lck), (plock), (blr)))
 #define SMB_VFS_OPAQUE_FILE_ID_CREATE(conn, sbuf) ((conn)->vfs.ops_opaque.file_id_create((conn)->vfs_opaque.handles.file_id_create, (sbuf)))
 #define SMB_VFS_OPAQUE_STREAMINFO(conn, fsp, fname, mem_ctx, num_streams, streams) ((conn)->vfs_opaque.ops.streaminfo((conn)->vfs_opaque.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 #define SMB_VFS_OPAQUE_GET_REAL_FILENAME(conn, path, name, mem_ctx, found_name) ((conn)->vfs_opaque.ops.get_real_filename((conn)->vfs_opaque.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
+#define SMB_VFS_OPAQUE_CONNECTPATH(conn, fname) ((conn)->vfs_opaque.ops.connectpath((conn)->vfs_opaque.handles.connectpath, (fname)))
 #define SMB_VFS_OPAQUE_BRL_LOCK_WINDOWS(conn, br_lck, plock, blocking_lock, blr) ((conn)->vfs_opaque.ops.brl_lock_windows((conn)->vfs_opaque.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
 #define SMB_VFS_OPAQUE_BRL_UNLOCK_WINDOWS(conn, msg_ctx, br_lck, plock) ((conn)->vfs_opaque.ops.brl_unlock_windows((conn)->vfs_opaque.handles.brl_unlock_windows, (msg_ctx), (br_lck), (plock)))
 #define SMB_VFS_OPAQUE_BRL_CANCEL_WINDOWS(conn, br_lck, plock, blr) ((conn)->vfs_opaque.ops.brl_cancel_windows((conn)->vfs_opaque.handles.brl_cancel_windows, (br_lck), (plock), (blr)))
 #define SMB_VFS_NEXT_FILE_ID_CREATE(handle, sbuf) ((handle)->vfs_next.ops.file_id_create((handle)->vfs_next.handles.file_id_create, (sbuf)))
 #define SMB_VFS_NEXT_STREAMINFO(handle, fsp, fname, mem_ctx, num_streams, streams) ((handle)->vfs_next.ops.streaminfo((handle)->vfs_next.handles.streaminfo, (fsp), (fname), (mem_ctx), (num_streams), (streams)))
 #define SMB_VFS_NEXT_GET_REAL_FILENAME(handle, path, name, mem_ctx, found_name) ((handle)->vfs_next.ops.get_real_filename((handle)->vfs_next.handles.get_real_filename, (path), (name), (mem_ctx), (found_name)))
+#define SMB_VFS_NEXT_CONNECTPATH(conn, fname) ((conn)->vfs_next.ops.connectpath((conn)->vfs_next.handles.connectpath, (fname)))
 #define SMB_VFS_NEXT_BRL_LOCK_WINDOWS(handle, br_lck, plock, blocking_lock, blr) ((handle)->vfs_next.ops.brl_lock_windows((handle)->vfs_next.handles.brl_lock_windows, (br_lck), (plock), (blocking_lock), (blr)))
 #define SMB_VFS_NEXT_BRL_UNLOCK_WINDOWS(handle, msg_ctx, br_lck, plock) ((handle)->vfs_next.ops.brl_unlock_windows((handle)->vfs_next.handles.brl_unlock_windows, (msg_ctx), (br_lck), (plock)))
 #define SMB_VFS_NEXT_BRL_CANCEL_WINDOWS(handle, br_lck, plock, blr) ((handle)->vfs_next.ops.brl_cancel_windows((handle)->vfs_next.handles.brl_cancel_windows, (br_lck), (plock), (blr)))
index fe63d5001ac7c55bf463a43dd5f6def33399ade4..4368dcd7dad2d28ebb715995abb17605fa96c028 100644 (file)
@@ -1128,6 +1128,12 @@ static int vfswrap_get_real_filename(struct vfs_handle_struct *handle,
        return -1;
 }
 
+static const char *vfswrap_connectpath(struct vfs_handle_struct *handle,
+                                      const char *fname)
+{
+       return handle->conn->connectpath;
+}
+
 static NTSTATUS vfswrap_brl_lock_windows(struct vfs_handle_struct *handle,
                                         struct byte_range_lock *br_lck,
                                         struct lock_struct *plock,
@@ -1630,6 +1636,8 @@ static vfs_op_tuple vfs_default_ops[] = {
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME,
         SMB_VFS_LAYER_OPAQUE},
+       {SMB_VFS_OP(vfswrap_connectpath),       SMB_VFS_OP_CONNECTPATH,
+        SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_brl_lock_windows),  SMB_VFS_OP_BRL_LOCK_WINDOWS,
         SMB_VFS_LAYER_OPAQUE},
        {SMB_VFS_OP(vfswrap_brl_unlock_windows),SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
index ebe89ec5fd82a46aa275722eac44317914c40dc1..bbcb7b3364d397f7cdfd2ed59729eb50282d4e39 100644 (file)
@@ -221,6 +221,8 @@ static int smb_full_audit_get_real_filename(struct vfs_handle_struct *handle,
                                            const char *name,
                                            TALLOC_CTX *mem_ctx,
                                            char **found_name);
+static const char *smb_full_audit_connectpath(vfs_handle_struct *handle,
+                                             const char *fname);
 static NTSTATUS smb_full_audit_brl_lock_windows(struct vfs_handle_struct *handle,
                                                struct byte_range_lock *br_lck,
                                                struct lock_struct *plock,
@@ -483,6 +485,8 @@ static vfs_op_tuple audit_op_tuples[] = {
         SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_get_real_filename), SMB_VFS_OP_GET_REAL_FILENAME,
         SMB_VFS_LAYER_LOGGER},
+       {SMB_VFS_OP(smb_full_audit_connectpath), SMB_VFS_OP_CONNECTPATH,
+        SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_brl_lock_windows), SMB_VFS_OP_BRL_LOCK_WINDOWS,
         SMB_VFS_LAYER_LOGGER},
        {SMB_VFS_OP(smb_full_audit_brl_unlock_windows), SMB_VFS_OP_BRL_UNLOCK_WINDOWS,
@@ -667,6 +671,7 @@ static struct {
        { SMB_VFS_OP_FILE_ID_CREATE,    "file_id_create" },
        { SMB_VFS_OP_STREAMINFO,        "streaminfo" },
        { SMB_VFS_OP_GET_REAL_FILENAME, "get_real_filename" },
+       { SMB_VFS_OP_CONNECTPATH,       "connectpath" },
        { SMB_VFS_OP_BRL_LOCK_WINDOWS,  "brl_lock_windows" },
        { SMB_VFS_OP_BRL_UNLOCK_WINDOWS, "brl_unlock_windows" },
        { SMB_VFS_OP_BRL_CANCEL_WINDOWS, "brl_cancel_windows" },
@@ -1727,6 +1732,19 @@ static int smb_full_audit_get_real_filename(struct vfs_handle_struct *handle,
        return result;
 }
 
+static const char *smb_full_audit_connectpath(vfs_handle_struct *handle,
+                                             const char *fname)
+{
+       const char *result;
+
+       result = SMB_VFS_NEXT_CONNECTPATH(handle, fname);
+
+       do_log(SMB_VFS_OP_CONNECTPATH, result != NULL, handle,
+              "%s", fname);
+
+       return result;
+}
+
 static NTSTATUS smb_full_audit_brl_lock_windows(struct vfs_handle_struct *handle,
                                                struct byte_range_lock *br_lck,
                                                struct lock_struct *plock,
index bc6fd18b8ea6997c53522887c1702dd53afa93ed..873e65e4a4a0b56901142ee6cfa0a09bf5f722a6 100644 (file)
@@ -956,14 +956,28 @@ NTSTATUS check_reduced_name(connection_struct *conn, const char *fname)
        }
 
        /* Check for widelinks allowed. */
-       if (!lp_widelinks(SNUM(conn))
-           && (strncmp(conn->connectpath, resolved_name,
-                       strlen(conn->connectpath)) != 0)) {
-               DEBUG(2, ("reduce_name: Bad access attempt: %s is a symlink outside the share path", fname));
-               if (free_resolved_name) {
-                       SAFE_FREE(resolved_name);
-               }
-               return NT_STATUS_ACCESS_DENIED;
+       if (!lp_widelinks(SNUM(conn))) {
+                   const char *conn_rootdir;
+
+                   conn_rootdir = SMB_VFS_CONNECTPATH(conn, fname);
+                   if (conn_rootdir == NULL) {
+                           DEBUG(2, ("check_reduced_name: Could not get conn_rootdir\n"));
+                           if (free_resolved_name) {
+                                   SAFE_FREE(resolved_name);
+                           }
+                           return NT_STATUS_ACCESS_DENIED;
+                   }
+
+                   if (strncmp(conn_rootdir, resolved_name,
+                               strlen(conn_rootdir)) != 0) {
+                           DEBUG(2, ("reduce_name: Bad access attempt: %s is "
+                                     "a symlink outside the share path",
+                                     fname));
+                           if (free_resolved_name) {
+                                   SAFE_FREE(resolved_name);
+                           }
+                           return NT_STATUS_ACCESS_DENIED;
+                   }
        }
 
         /* Check if we are allowing users to follow symlinks */