S3: smbd: Finish plumbing struct smb_filename * through the check_name() stack.
authorJeremy Allison <jra@samba.org>
Fri, 30 Jun 2017 18:59:20 +0000 (11:59 -0700)
committerJeremy Allison <jra@samba.org>
Sat, 1 Jul 2017 01:07:11 +0000 (03:07 +0200)
Signed-off-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Richard Sharpe <realrichardsharpe@gmail.com>
source3/smbd/dir.c
source3/smbd/filename.c
source3/smbd/open.c
source3/smbd/proto.h
source3/smbd/reply.c
source3/smbd/vfs.c

index 6b77409c73fdd175287e1338207e9ba74233c6f4..cb54be4de76a62e510671bca5dfa720ac12f62a8 100644 (file)
@@ -1704,7 +1704,7 @@ static struct smb_Dir *open_dir_safely(TALLOC_CTX *ctx,
         * Now the directory is pinned, use
         * REALPATH to ensure we can access it.
         */
-       status = check_name(conn, ".");
+       status = check_name(conn, smb_fname_cwd);
        if (!NT_STATUS_IS_OK(status)) {
                goto out;
        }
index 084849d4ba130b1e36bd6d891075b31f0d793360..1186918a7f23d3a442619239564d3ed9ac7476ee 100644 (file)
@@ -1231,8 +1231,11 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
  Ensure a path is not vetoed.
 ****************************************************************************/
 
-static NTSTATUS check_veto_path(connection_struct *conn, const char *name)
+static NTSTATUS check_veto_path(connection_struct *conn,
+                       const struct smb_filename *smb_fname)
 {
+       const char *name = smb_fname->base_name;
+
        if (IS_VETO_PATH(conn, name))  {
                /* Is it not dot or dot dot. */
                if (!(ISDOT(name) || ISDOTDOT(name))) {
@@ -1251,19 +1254,21 @@ static NTSTATUS check_veto_path(connection_struct *conn, const char *name)
  a valid one for the user to access.
 ****************************************************************************/
 
-NTSTATUS check_name(connection_struct *conn, const char *name)
+NTSTATUS check_name(connection_struct *conn,
+                       const struct smb_filename *smb_fname)
 {
-       NTSTATUS status = check_veto_path(conn, name);
+       NTSTATUS status = check_veto_path(conn, smb_fname);
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
 
        if (!lp_widelinks(SNUM(conn)) || !lp_follow_symlinks(SNUM(conn))) {
-               status = check_reduced_name(conn, NULL, name);
+               status = check_reduced_name(conn, NULL, smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(5,("check_name: name %s failed with %s\n",name,
-                                               nt_errstr(status)));
+                       DEBUG(5,("check_name: name %s failed with %s\n",
+                                       smb_fname->base_name,
+                                       nt_errstr(status)));
                        return status;
                }
        }
@@ -1278,15 +1283,15 @@ NTSTATUS check_name(connection_struct *conn, const char *name)
 
 static NTSTATUS check_name_with_privilege(connection_struct *conn,
                struct smb_request *smbreq,
-               const char *name)
+               const struct smb_filename *smb_fname)
 {
-       NTSTATUS status = check_veto_path(conn, name);
+       NTSTATUS status = check_veto_path(conn, smb_fname);
 
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
        return check_reduced_name_with_privilege(conn,
-                       name,
+                       smb_fname,
                        smbreq);
 }
 
@@ -1623,13 +1628,14 @@ static NTSTATUS filename_convert_internal(TALLOC_CTX *ctx,
        if ((ucf_flags & UCF_UNIX_NAME_LOOKUP) &&
                        VALID_STAT((*pp_smb_fname)->st) &&
                        S_ISLNK((*pp_smb_fname)->st.st_ex_mode)) {
-               return check_veto_path(conn, (*pp_smb_fname)->base_name);
+               return check_veto_path(conn, (*pp_smb_fname));
        }
 
        if (!smbreq) {
-               status = check_name(conn, (*pp_smb_fname)->base_name);
+               status = check_name(conn, (*pp_smb_fname));
        } else {
-               status = check_name_with_privilege(conn, smbreq, (*pp_smb_fname)->base_name);
+               status = check_name_with_privilege(conn, smbreq,
+                               (*pp_smb_fname));
        }
        if (!NT_STATUS_IS_OK(status)) {
                DEBUG(3,("filename_convert_internal: check_name failed "
index e8464ed83b2bba0e7b030bbfaf0cb48b6223f114..0eedf963f31ab54b537e75ac25425c64bfc8ffe2 100644 (file)
@@ -570,13 +570,6 @@ static int non_widelink_open(struct connection_struct *conn,
                goto out;
        }
 
-       /* Ensure the relative path is below the share. */
-       status = check_reduced_name(conn, parent_dir, final_component);
-       if (!NT_STATUS_IS_OK(status)) {
-               saved_errno = map_errno_from_nt_status(status);
-               goto out;
-       }
-
        smb_fname_rel = synthetic_smb_fname(talloc_tos(),
                                final_component,
                                smb_fname->stream_name,
@@ -587,6 +580,13 @@ static int non_widelink_open(struct connection_struct *conn,
                goto out;
        }
 
+       /* Ensure the relative path is below the share. */
+       status = check_reduced_name(conn, &parent_dir_fname, smb_fname_rel);
+       if (!NT_STATUS_IS_OK(status)) {
+               saved_errno = map_errno_from_nt_status(status);
+               goto out;
+       }
+
        flags |= O_NOFOLLOW;
 
        {
index 7d641bdab19626a3ea3b2eea73f40ecd1196927d..a688341c64dd37c8a054114c370913e12c115054 100644 (file)
@@ -345,7 +345,8 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx,
                      const char *orig_path,
                      struct smb_filename **smb_fname,
                      uint32_t ucf_flags);
-NTSTATUS check_name(connection_struct *conn, const char *name);
+NTSTATUS check_name(connection_struct *conn,
+                       const struct smb_filename *smb_fname);
 int get_real_filename(connection_struct *conn, const char *path,
                      const char *name, TALLOC_CTX *mem_ctx,
                      char **found_name);
@@ -1234,10 +1235,10 @@ int vfs_ChDir(connection_struct *conn,
                        const struct smb_filename *smb_fname);
 struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn);
 NTSTATUS check_reduced_name(connection_struct *conn,
-                       const char *cwd_name,
-                       const char *fname);
+                       const struct smb_filename *cwd_fname,
+                       const struct smb_filename *smb_fname);
 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
-                       const char *fname,
+                       const struct smb_filename *smb_fname,
                        struct smb_request *smbreq);
 int vfs_stat_smb_basename(struct connection_struct *conn,
                        const struct smb_filename *smb_fname_in,
index e6fabad8e0076a08713cfa4ab75378ec298b769e..e430a8e2d0f00e181ac6c3a6e617253bb3780d53 100644 (file)
@@ -3053,7 +3053,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        dirtype = FILE_ATTRIBUTE_NORMAL;
                }
 
-               status = check_name(conn, smb_fname->base_name);
+               status = check_name(conn, smb_fname);
                if (!NT_STATUS_IS_OK(status)) {
                        goto out;
                }
@@ -3087,11 +3087,6 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        }
                }
 
-               status = check_name(conn, fname_dir);
-               if (!NT_STATUS_IS_OK(status)) {
-                       goto out;
-               }
-
                smb_fname_dir = synthetic_smb_fname(talloc_tos(),
                                        fname_dir,
                                        NULL,
@@ -3102,6 +3097,11 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                        goto out;
                }
 
+               status = check_name(conn, smb_fname_dir);
+               if (!NT_STATUS_IS_OK(status)) {
+                       goto out;
+               }
+
                dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_dir, fname_mask,
                                  dirtype);
                if (dir_hnd == NULL) {
@@ -3161,7 +3161,7 @@ NTSTATUS unlink_internals(connection_struct *conn, struct smb_request *req,
                                goto out;
                        }
 
-                       status = check_name(conn, smb_fname->base_name);
+                       status = check_name(conn, smb_fname);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(frame);
@@ -6609,7 +6609,7 @@ NTSTATUS rename_internals_fsp(connection_struct *conn,
        uint32_t access_mask = SEC_DIR_ADD_FILE;
        bool dst_exists, old_is_stream, new_is_stream;
 
-       status = check_name(conn, smb_fname_dst_in->base_name);
+       status = check_name(conn, smb_fname_dst_in);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
        }
@@ -7088,11 +7088,6 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                }
        }
 
-       status = check_name(conn, fname_src_dir);
-       if (!NT_STATUS_IS_OK(status)) {
-               goto out;
-       }
-
        smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
                                fname_src_dir,
                                NULL,
@@ -7103,6 +7098,11 @@ NTSTATUS rename_internals(TALLOC_CTX *ctx,
                goto out;
        }
 
+       status = check_name(conn, smb_fname_src_dir);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto out;
+       }
+
        dir_hnd = OpenDir(talloc_tos(), conn, smb_fname_src_dir, fname_src_mask,
                          attrs);
        if (dir_hnd == NULL) {
@@ -7754,13 +7754,13 @@ void reply_copy(struct smb_request *req)
                        smb_fname_dst->base_name = fname_dst_mod;
                }
 
-               status = check_name(conn, smb_fname_src->base_name);
+               status = check_name(conn, smb_fname_src);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
                }
 
-               status = check_name(conn, smb_fname_dst->base_name);
+               status = check_name(conn, smb_fname_dst);
                if (!NT_STATUS_IS_OK(status)) {
                        reply_nterror(req, status);
                        goto out;
@@ -7802,12 +7802,6 @@ void reply_copy(struct smb_request *req)
                        }
                }
 
-               status = check_name(conn, fname_src_dir);
-               if (!NT_STATUS_IS_OK(status)) {
-                       reply_nterror(req, status);
-                       goto out;
-               }
-
                smb_fname_src_dir = synthetic_smb_fname(talloc_tos(),
                                        fname_src_dir,
                                        NULL,
@@ -7818,6 +7812,12 @@ void reply_copy(struct smb_request *req)
                        goto out;
                }
 
+               status = check_name(conn, smb_fname_src_dir);
+               if (!NT_STATUS_IS_OK(status)) {
+                       reply_nterror(req, status);
+                       goto out;
+               }
+
                dir_hnd = OpenDir(ctx,
                                conn,
                                smb_fname_src_dir,
@@ -7891,7 +7891,7 @@ void reply_copy(struct smb_request *req)
                        TALLOC_FREE(smb_fname_dst->base_name);
                        smb_fname_dst->base_name = destname;
 
-                       status = check_name(conn, smb_fname_src->base_name);
+                       status = check_name(conn, smb_fname_src);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(talloced);
@@ -7899,7 +7899,7 @@ void reply_copy(struct smb_request *req)
                                goto out;
                        }
 
-                       status = check_name(conn, smb_fname_dst->base_name);
+                       status = check_name(conn, smb_fname_dst);
                        if (!NT_STATUS_IS_OK(status)) {
                                TALLOC_FREE(dir_hnd);
                                TALLOC_FREE(talloced);
index 7607bcb0537501f0bfe2b49aeca8bc9854309cbf..9bc02dafcfe1a042d163c3a368c1d64db557221a 100644 (file)
@@ -1016,7 +1016,7 @@ struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
 ********************************************************************/
 
 NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
-                       const char *fname,
+                       const struct smb_filename *smb_fname,
                        struct smb_request *smbreq)
 {
        NTSTATUS status;
@@ -1026,6 +1026,7 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
        char *dir_name = NULL;
        char *resolved_name = NULL;
        const char *last_component = NULL;
+       const char *fname = smb_fname->base_name;
        struct smb_filename *resolved_fname = NULL;
        struct smb_filename *saved_dir_fname = NULL;
        struct smb_filename *smb_fname_cwd = NULL;
@@ -1208,11 +1209,12 @@ NTSTATUS check_reduced_name_with_privilege(connection_struct *conn,
 ********************************************************************/
 
 NTSTATUS check_reduced_name(connection_struct *conn,
-                               const char *cwd_name,
-                               const char *fname)
+                               const struct smb_filename *cwd_fname,
+                               const struct smb_filename *smb_fname)
 {
        TALLOC_CTX *ctx = talloc_tos();
-       struct smb_filename smb_fname = { .base_name = discard_const(fname) };
+       const char *cwd_name = cwd_fname ? cwd_fname->base_name : NULL;
+       const char *fname = smb_fname->base_name;
        struct smb_filename *resolved_fname;
        char *resolved_name = NULL;
        char *new_fname = NULL;
@@ -1221,7 +1223,7 @@ NTSTATUS check_reduced_name(connection_struct *conn,
 
        DBG_DEBUG("check_reduced_name [%s] [%s]\n", fname, conn->connectpath);
 
-       resolved_fname = SMB_VFS_REALPATH(conn, ctx, &smb_fname);
+       resolved_fname = SMB_VFS_REALPATH(conn, ctx, smb_fname);
 
        if (resolved_fname == NULL) {
                switch (errno) {