s3: smbd: Change canonicalize_ea_name() to take a const smb_filename * parameter...
[sfrench/samba-autobuild/.git] / source3 / smbd / trans2.c
index 43eeb492d23b7782798be29a4c62bd25ebe09b6a..2e10bbe79611a914b47848b5b07d2a8456dc0331 100644 (file)
@@ -242,12 +242,22 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
        char **names, **tmp;
        size_t num_names;
        ssize_t sizeret = -1;
+       NTSTATUS status;
+
+       if (pnames) {
+               *pnames = NULL;
+       }
+       *pnum_names = 0;
 
        if (!lp_ea_support(SNUM(conn))) {
-               if (pnames) {
-                       *pnames = NULL;
-               }
-               *pnum_names = 0;
+               return NT_STATUS_OK;
+       }
+
+       status = refuse_symlink(conn, fsp, fname);
+       if (!NT_STATUS_IS_OK(status)) {
+               /*
+                * Just return no EA's on a symlink.
+                */
                return NT_STATUS_OK;
        }
 
@@ -297,10 +307,6 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn,
 
        if (sizeret == 0) {
                TALLOC_FREE(names);
-               if (pnames) {
-                       *pnames = NULL;
-               }
-               *pnum_names = 0;
                return NT_STATUS_OK;
        }
 
@@ -624,12 +630,20 @@ static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp,
  Ensure the EA name is case insensitive by matching any existing EA name.
 ****************************************************************************/
 
-static void canonicalize_ea_name(connection_struct *conn, files_struct *fsp, const char *fname, fstring unix_ea_name)
+static void canonicalize_ea_name(connection_struct *conn,
+                       files_struct *fsp,
+                       const struct smb_filename *smb_fname,
+                       fstring unix_ea_name)
 {
        size_t total_ea_len;
        TALLOC_CTX *mem_ctx = talloc_tos();
        struct ea_list *ea_list;
-       NTSTATUS status = get_ea_list_from_file_path(mem_ctx, conn, fsp, fname, &total_ea_len, &ea_list);
+       NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
+                                       conn,
+                                       fsp,
+                                       smb_fname->base_name,
+                                       &total_ea_len,
+                                       &ea_list);
        if (!NT_STATUS_IS_OK(status)) {
                return;
        }
@@ -652,12 +666,16 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                const struct smb_filename *smb_fname, struct ea_list *ea_list)
 {
        NTSTATUS status;
-       char *fname = NULL;
 
        if (!lp_ea_support(SNUM(conn))) {
                return NT_STATUS_EAS_NOT_SUPPORTED;
        }
 
+       status = refuse_symlink(conn, fsp, smb_fname->base_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
        if (!NT_STATUS_IS_OK(status)) {
                return status;
@@ -677,8 +695,6 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                return STATUS_INVALID_EA_NAME;
        }
 
-       fname = smb_fname->base_name;
-
        for (;ea_list; ea_list = ea_list->next) {
                int ret;
                fstring unix_ea_name;
@@ -686,7 +702,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
                fstrcat(unix_ea_name, ea_list->ea.name);
 
-               canonicalize_ea_name(conn, fsp, fname, unix_ea_name);
+               canonicalize_ea_name(conn,
+                               fsp,
+                               smb_fname,
+                               unix_ea_name);
 
                DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
 
@@ -704,8 +723,10 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                                ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
                        } else {
                                DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
-                                       unix_ea_name, fname));
-                               ret = SMB_VFS_REMOVEXATTR(conn, fname, unix_ea_name);
+                                       unix_ea_name, smb_fname->base_name));
+                               ret = SMB_VFS_REMOVEXATTR(conn,
+                                               smb_fname->base_name,
+                                               unix_ea_name);
                        }
 #ifdef ENOATTR
                        /* Removing a non existent attribute always succeeds. */
@@ -724,9 +745,13 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
                                                        ea_list->ea.value.data, ea_list->ea.value.length, 0);
                        } else {
                                DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
-                                       unix_ea_name, fname));
-                               ret = SMB_VFS_SETXATTR(conn, fname, unix_ea_name,
-                                                       ea_list->ea.value.data, ea_list->ea.value.length, 0);
+                                       unix_ea_name, smb_fname->base_name));
+                               ret = SMB_VFS_SETXATTR(conn,
+                                               smb_fname->base_name,
+                                               unix_ea_name,
+                                               ea_list->ea.value.data,
+                                               ea_list->ea.value.length,
+                                               0);
                        }
                }
 
@@ -5346,6 +5371,13 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
                                uint16_t num_file_acls = 0;
                                uint16_t num_def_acls = 0;
 
+                               status = refuse_symlink(conn,
+                                               fsp,
+                                               smb_fname->base_name);
+                               if (!NT_STATUS_IS_OK(status)) {
+                                       return status;
+                               }
+
                                if (fsp && fsp->fh->fd != -1) {
                                        file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
                                                talloc_tos());
@@ -6932,6 +6964,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
        uint16_t num_def_acls;
        bool valid_file_acls = True;
        bool valid_def_acls = True;
+       NTSTATUS status;
 
        if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
                return NT_STATUS_INVALID_PARAMETER;
@@ -6959,6 +6992,11 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
                return NT_STATUS_INVALID_PARAMETER;
        }
 
+       status = refuse_symlink(conn, fsp, smb_fname->base_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
        DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
                smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
                (unsigned int)num_file_acls,