LCOV - code coverage report
Current view: top level - source3/smbd - trans2.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 3278 4662 70.3 %
Date: 2021-08-25 13:27:56 Functions: 83 109 76.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB transaction2 handling
       4             :    Copyright (C) Jeremy Allison                 1994-2007
       5             :    Copyright (C) Stefan (metze) Metzmacher      2003
       6             :    Copyright (C) Volker Lendecke                2005-2007
       7             :    Copyright (C) Steve French                   2005
       8             :    Copyright (C) James Peach                    2006-2007
       9             : 
      10             :    Extensively modified by Andrew Tridgell, 1995
      11             : 
      12             :    This program is free software; you can redistribute it and/or modify
      13             :    it under the terms of the GNU General Public License as published by
      14             :    the Free Software Foundation; either version 3 of the License, or
      15             :    (at your option) any later version.
      16             : 
      17             :    This program is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20             :    GNU General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU General Public License
      23             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "ntioctl.h"
      28             : #include "system/filesys.h"
      29             : #include "lib/util/time_basic.h"
      30             : #include "version.h"
      31             : #include "smbd/smbd.h"
      32             : #include "smbd/globals.h"
      33             : #include "../libcli/auth/libcli_auth.h"
      34             : #include "../librpc/gen_ndr/xattr.h"
      35             : #include "../librpc/gen_ndr/ndr_security.h"
      36             : #include "libcli/security/security.h"
      37             : #include "trans2.h"
      38             : #include "auth.h"
      39             : #include "smbprofile.h"
      40             : #include "rpc_server/srv_pipe_hnd.h"
      41             : #include "printing.h"
      42             : #include "lib/util_ea.h"
      43             : #include "lib/readdir_attr.h"
      44             : #include "messages.h"
      45             : #include "smb1_utils.h"
      46             : #include "libcli/smb/smb2_posix.h"
      47             : #include "lib/util/string_wrappers.h"
      48             : 
      49             : #define DIR_ENTRY_SAFETY_MARGIN 4096
      50             : 
      51             : static char *store_file_unix_basic(connection_struct *conn,
      52             :                                 char *pdata,
      53             :                                 files_struct *fsp,
      54             :                                 const SMB_STRUCT_STAT *psbuf);
      55             : 
      56             : static char *store_file_unix_basic_info2(connection_struct *conn,
      57             :                                 char *pdata,
      58             :                                 files_struct *fsp,
      59             :                                 const SMB_STRUCT_STAT *psbuf);
      60             : 
      61             : /****************************************************************************
      62             :  Check if an open file handle is a symlink.
      63             : ****************************************************************************/
      64             : 
      65       30936 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
      66             : {
      67             : 
      68       30936 :         if (!VALID_STAT(fsp->fsp_name->st)) {
      69           0 :                 return NT_STATUS_ACCESS_DENIED;
      70             :         }
      71       30936 :         if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
      72           0 :                 return NT_STATUS_ACCESS_DENIED;
      73             :         }
      74       30936 :         if (fsp_get_pathref_fd(fsp) == -1) {
      75           0 :                 return NT_STATUS_ACCESS_DENIED;
      76             :         }
      77       30936 :         return NT_STATUS_OK;
      78             : }
      79             : 
      80        6409 : NTSTATUS check_access_fsp(struct files_struct *fsp,
      81             :                           uint32_t access_mask)
      82             : {
      83        6409 :         if (!fsp->fsp_flags.is_fsa) {
      84         127 :                 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
      85             :                                                     fsp,
      86             :                                                     false,
      87             :                                                     access_mask);
      88             :         }
      89        6282 :         if (!(fsp->access_mask & access_mask)) {
      90          30 :                 return NT_STATUS_ACCESS_DENIED;
      91             :         }
      92        6252 :         return NT_STATUS_OK;
      93             : }
      94             : 
      95             : #if defined(HAVE_POSIX_ACLS)
      96             : /****************************************************************************
      97             :  Utility function to open a fsp for a POSIX handle operation.
      98             : ****************************************************************************/
      99             : 
     100          88 : static NTSTATUS get_posix_fsp(connection_struct *conn,
     101             :                         struct smb_request *req,
     102             :                         struct smb_filename *smb_fname,
     103             :                         uint32_t access_mask,
     104             :                         files_struct **ret_fsp)
     105             : {
     106             :         NTSTATUS status;
     107          88 :         uint32_t create_disposition = FILE_OPEN;
     108          88 :         uint32_t share_access = FILE_SHARE_READ|
     109             :                                 FILE_SHARE_WRITE|
     110             :                                 FILE_SHARE_DELETE;
     111          88 :         struct smb2_create_blobs *posx = NULL;
     112             : 
     113             :         /*
     114             :          * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
     115             :          * but set reasonable defaults.
     116             :          */
     117          88 :         uint32_t file_attributes = 0664;
     118          88 :         uint32_t oplock = NO_OPLOCK;
     119          88 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
     120             : 
     121             :         /* File or directory must exist. */
     122          88 :         if (!VALID_STAT(smb_fname->st)) {
     123           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     124             :         }
     125             :         /* Cannot be a symlink. */
     126          88 :         if (S_ISLNK(smb_fname->st.st_ex_mode)) {
     127          16 :                 return NT_STATUS_ACCESS_DENIED;
     128             :         }
     129             :         /* Set options correctly for directory open. */
     130          72 :         if (S_ISDIR(smb_fname->st.st_ex_mode)) {
     131             :                 /*
     132             :                  * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
     133             :                  * directories, but set reasonable defaults.
     134             :                  */
     135          24 :                 file_attributes = 0775;
     136          24 :                 create_options = FILE_DIRECTORY_FILE;
     137             :         }
     138             : 
     139          72 :         status = make_smb2_posix_create_ctx(
     140             :                 talloc_tos(), &posx, file_attributes);
     141          72 :         if (!NT_STATUS_IS_OK(status)) {
     142           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
     143             :                             nt_errstr(status));
     144           0 :                 goto done;
     145             :         }
     146             : 
     147          72 :         status = SMB_VFS_CREATE_FILE(
     148             :                 conn,           /* conn */
     149             :                 req,            /* req */
     150             :                 smb_fname,      /* fname */
     151             :                 access_mask,    /* access_mask */
     152             :                 share_access,   /* share_access */
     153             :                 create_disposition,/* create_disposition*/
     154             :                 create_options, /* create_options */
     155             :                 file_attributes,/* file_attributes */
     156             :                 oplock,         /* oplock_request */
     157             :                 NULL,           /* lease */
     158             :                 0,              /* allocation_size */
     159             :                 0,              /* private_flags */
     160             :                 NULL,           /* sd */
     161             :                 NULL,           /* ea_list */
     162             :                 ret_fsp,        /* result */
     163             :                 NULL,           /* pinfo */
     164             :                 posx,           /* in_context */
     165             :                 NULL);          /* out_context */
     166             : 
     167          72 : done:
     168          72 :         TALLOC_FREE(posx);
     169          72 :         return status;
     170             : }
     171             : #endif
     172             : 
     173             : /********************************************************************
     174             :  Roundup a value to the nearest allocation roundup size boundary.
     175             :  Only do this for Windows clients.
     176             : ********************************************************************/
     177             : 
     178     1371136 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
     179             : {
     180     1371136 :         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
     181             : 
     182             :         /* Only roundup for Windows clients. */
     183     1371136 :         enum remote_arch_types ra_type = get_remote_arch();
     184     1371136 :         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
     185           0 :                 val = SMB_ROUNDUP(val,rval);
     186             :         }
     187     1371136 :         return val;
     188             : }
     189             : 
     190             : /****************************************************************************
     191             :  Utility functions for dealing with extended attributes.
     192             : ****************************************************************************/
     193             : 
     194             : /****************************************************************************
     195             :  Refuse to allow clients to overwrite our private xattrs.
     196             : ****************************************************************************/
     197             : 
     198      581300 : bool samba_private_attr_name(const char *unix_ea_name)
     199             : {
     200             :         static const char * const prohibited_ea_names[] = {
     201             :                 SAMBA_POSIX_INHERITANCE_EA_NAME,
     202             :                 SAMBA_XATTR_DOS_ATTRIB,
     203             :                 SAMBA_XATTR_MARKER,
     204             :                 XATTR_NTACL_NAME,
     205             :                 NULL
     206             :         };
     207             : 
     208             :         int i;
     209             : 
     210     1724200 :         for (i = 0; prohibited_ea_names[i]; i++) {
     211     1713605 :                 if (strequal( prohibited_ea_names[i], unix_ea_name))
     212      568877 :                         return true;
     213             :         }
     214       10595 :         if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
     215             :                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
     216         134 :                 return true;
     217             :         }
     218       10461 :         return false;
     219             : }
     220             : 
     221             : /****************************************************************************
     222             :  Get one EA value. Fill in a struct ea_struct.
     223             : ****************************************************************************/
     224             : 
     225       16254 : NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
     226             :                           files_struct *fsp,
     227             :                           const char *ea_name,
     228             :                           struct ea_struct *pea)
     229             : {
     230             :         /* Get the value of this xattr. Max size is 64k. */
     231       16254 :         size_t attr_size = 256;
     232       16254 :         char *val = NULL;
     233             :         ssize_t sizeret;
     234       16254 :         size_t max_xattr_size = 0;
     235             : 
     236       16254 :         if (fsp == NULL) {
     237           0 :                 return NT_STATUS_INVALID_HANDLE;
     238             :         }
     239             : 
     240       16254 :         max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
     241             : 
     242       16416 :  again:
     243             : 
     244       16416 :         val = talloc_realloc(mem_ctx, val, char, attr_size);
     245       16416 :         if (!val) {
     246           0 :                 return NT_STATUS_NO_MEMORY;
     247             :         }
     248             : 
     249       16416 :         sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
     250       16416 :         if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
     251         162 :                 attr_size = max_xattr_size;
     252         162 :                 goto again;
     253             :         }
     254             : 
     255       16254 :         if (sizeret == -1) {
     256        2548 :                 return map_nt_error_from_unix(errno);
     257             :         }
     258             : 
     259       13706 :         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
     260       13706 :         dump_data(10, (uint8_t *)val, sizeret);
     261             : 
     262       13706 :         pea->flags = 0;
     263       13706 :         if (strnequal(ea_name, "user.", 5)) {
     264       13622 :                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
     265             :         } else {
     266          84 :                 pea->name = talloc_strdup(mem_ctx, ea_name);
     267             :         }
     268       13706 :         if (pea->name == NULL) {
     269           0 :                 TALLOC_FREE(val);
     270           0 :                 return NT_STATUS_NO_MEMORY;
     271             :         }
     272       13706 :         pea->value.data = (unsigned char *)val;
     273       13706 :         pea->value.length = (size_t)sizeret;
     274       13706 :         return NT_STATUS_OK;
     275             : }
     276             : 
     277      334227 : NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
     278             :                                 files_struct *fsp,
     279             :                                 char ***pnames,
     280             :                                 size_t *pnum_names)
     281             : {
     282             :         char smallbuf[1024];
     283             :         /* Get a list of all xattrs. Max namesize is 64k. */
     284      334227 :         size_t ea_namelist_size = 1024;
     285      334227 :         char *ea_namelist = smallbuf;
     286      334227 :         char *to_free = NULL;
     287             : 
     288             :         char *p;
     289             :         char **names;
     290             :         size_t num_names;
     291      334227 :         ssize_t sizeret = -1;
     292             :         NTSTATUS status;
     293             : 
     294      334227 :         if (pnames) {
     295      332964 :                 *pnames = NULL;
     296             :         }
     297      334227 :         *pnum_names = 0;
     298             : 
     299      334227 :         if (fsp == NULL) {
     300             :                 /*
     301             :                  * Callers may pass fsp == NULL when passing smb_fname->fsp of a
     302             :                  * symlink. This is ok, handle it here, by just return no EA's
     303             :                  * on a symlink.
     304             :                  */
     305           0 :                 return NT_STATUS_OK;
     306             :         }
     307             : 
     308             :         /* should be the case that fsp != NULL */
     309      333192 :         SMB_ASSERT(fsp != NULL);
     310             : 
     311      334227 :         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     312             :                                      ea_namelist_size);
     313             : 
     314      334227 :         if ((sizeret == -1) && (errno == ERANGE)) {
     315           0 :                 ea_namelist_size = 65536;
     316           0 :                 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
     317           0 :                 if (ea_namelist == NULL) {
     318           0 :                         return NT_STATUS_NO_MEMORY;
     319             :                 }
     320           0 :                 to_free = ea_namelist;
     321             : 
     322           0 :                 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     323             :                                              ea_namelist_size);
     324             :         }
     325             : 
     326      334227 :         if (sizeret == -1) {
     327           2 :                 status = map_nt_error_from_unix(errno);
     328           2 :                 TALLOC_FREE(to_free);
     329           2 :                 return status;
     330             :         }
     331             : 
     332      334225 :         DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
     333             : 
     334      334225 :         if (sizeret == 0) {
     335       25151 :                 TALLOC_FREE(to_free);
     336       25151 :                 return NT_STATUS_OK;
     337             :         }
     338             : 
     339             :         /*
     340             :          * Ensure the result is 0-terminated
     341             :          */
     342             : 
     343      309074 :         if (ea_namelist[sizeret-1] != '\0') {
     344           0 :                 TALLOC_FREE(to_free);
     345           0 :                 return NT_STATUS_INTERNAL_ERROR;
     346             :         }
     347             : 
     348             :         /*
     349             :          * count the names
     350             :          */
     351      308078 :         num_names = 0;
     352             : 
     353     1696279 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     354     1388201 :                 num_names += 1;
     355             :         }
     356             : 
     357      309074 :         *pnum_names = num_names;
     358             : 
     359      309074 :         if (pnames == NULL) {
     360        1259 :                 TALLOC_FREE(to_free);
     361        1259 :                 return NT_STATUS_OK;
     362             :         }
     363             : 
     364      307815 :         names = talloc_array(mem_ctx, char *, num_names);
     365      307815 :         if (names == NULL) {
     366           0 :                 DEBUG(0, ("talloc failed\n"));
     367           0 :                 TALLOC_FREE(to_free);
     368           0 :                 return NT_STATUS_NO_MEMORY;
     369             :         }
     370             : 
     371      307815 :         if (ea_namelist == smallbuf) {
     372      307815 :                 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
     373      307815 :                 if (ea_namelist == NULL) {
     374           0 :                         TALLOC_FREE(names);
     375           0 :                         return NT_STATUS_NO_MEMORY;
     376             :                 }
     377             :         } else {
     378           0 :                 talloc_steal(names, ea_namelist);
     379             : 
     380           0 :                 ea_namelist = talloc_realloc(names, ea_namelist, char,
     381             :                                              sizeret);
     382           0 :                 if (ea_namelist == NULL) {
     383           0 :                         TALLOC_FREE(names);
     384           0 :                         return NT_STATUS_NO_MEMORY;
     385             :                 }
     386             :         }
     387             : 
     388      307815 :         num_names = 0;
     389             : 
     390     1689399 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     391     1381584 :                 names[num_names++] = p;
     392             :         }
     393             : 
     394      307815 :         *pnames = names;
     395             : 
     396      307815 :         return NT_STATUS_OK;
     397             : }
     398             : 
     399             : /****************************************************************************
     400             :  Return a linked list of the total EA's. Plus the total size
     401             : ****************************************************************************/
     402             : 
     403      328265 : static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
     404             :                                 files_struct *fsp,
     405             :                                 size_t *pea_total_len,
     406             :                                 struct ea_list **ea_list)
     407             : {
     408             :         /* Get a list of all xattrs. Max namesize is 64k. */
     409             :         size_t i, num_names;
     410             :         char **names;
     411      328265 :         struct ea_list *ea_list_head = NULL;
     412      328265 :         bool posix_pathnames = false;
     413             :         NTSTATUS status;
     414             : 
     415      328265 :         *pea_total_len = 0;
     416      328265 :         *ea_list = NULL;
     417             : 
     418             :         /* symlink */
     419      328265 :         if (fsp == NULL) {
     420          20 :                 return NT_STATUS_OK;
     421             :         }
     422             : 
     423      328245 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     424           0 :                 return NT_STATUS_OK;
     425             :         }
     426             : 
     427      328245 :         if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
     428           8 :                 return NT_STATUS_INVALID_PARAMETER;
     429             :         }
     430             : 
     431      328237 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     432             : 
     433      328237 :         status = get_ea_names_from_fsp(talloc_tos(),
     434             :                                 fsp,
     435             :                                 &names,
     436             :                                 &num_names);
     437             : 
     438      328237 :         if (!NT_STATUS_IS_OK(status)) {
     439           0 :                 return status;
     440             :         }
     441             : 
     442      328237 :         if (num_names == 0) {
     443       25141 :                 return NT_STATUS_OK;
     444             :         }
     445             : 
     446     1672946 :         for (i=0; i<num_names; i++) {
     447             :                 struct ea_list *listp;
     448             :                 fstring dos_ea_name;
     449             : 
     450     1370769 :                 if (strnequal(names[i], "system.", 7)
     451      567506 :                     || samba_private_attr_name(names[i]))
     452     2730194 :                         continue;
     453             : 
     454             :                 /*
     455             :                  * Filter out any underlying POSIX EA names
     456             :                  * that a Windows client can't handle.
     457             :                  */
     458       11340 :                 if (!posix_pathnames &&
     459        5668 :                                 is_invalid_windows_ea_name(names[i])) {
     460           0 :                         continue;
     461             :                 }
     462             : 
     463        5672 :                 listp = talloc(mem_ctx, struct ea_list);
     464        5672 :                 if (listp == NULL) {
     465           0 :                         return NT_STATUS_NO_MEMORY;
     466             :                 }
     467             : 
     468       11344 :                 status = get_ea_value_fsp(listp,
     469             :                                           fsp,
     470        5672 :                                           names[i],
     471             :                                           &listp->ea);
     472             : 
     473        5672 :                 if (!NT_STATUS_IS_OK(status)) {
     474           0 :                         TALLOC_FREE(listp);
     475           0 :                         return status;
     476             :                 }
     477             : 
     478        5672 :                 if (listp->ea.value.length == 0) {
     479             :                         /*
     480             :                          * We can never return a zero length EA.
     481             :                          * Windows reports the EA's as corrupted.
     482             :                          */
     483           0 :                         TALLOC_FREE(listp);
     484           0 :                         continue;
     485        5672 :                 } else if (listp->ea.value.length > 65536) {
     486             :                         /*
     487             :                          * SMB clients may report error with file
     488             :                          * if large EA is presented to them.
     489             :                          */
     490           0 :                         DBG_ERR("EA [%s] on file [%s] exceeds "
     491             :                                 "maximum permitted EA size of 64KiB: %zu\n.",
     492             :                                 listp->ea.name, fsp_str_dbg(fsp),
     493             :                                 listp->ea.value.length);
     494           0 :                         TALLOC_FREE(listp);
     495           0 :                         continue;
     496             :                 }
     497             : 
     498        5672 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     499             : 
     500       11344 :                 *pea_total_len +=
     501        5672 :                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     502             : 
     503        5672 :                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
     504             :                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
     505             :                           (unsigned int)listp->ea.value.length));
     506             : 
     507        5672 :                 DLIST_ADD_END(ea_list_head, listp);
     508             : 
     509             :         }
     510             : 
     511             :         /* Add on 4 for total length. */
     512      303096 :         if (*pea_total_len) {
     513        3728 :                 *pea_total_len += 4;
     514             :         }
     515             : 
     516      303096 :         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
     517             :                    (unsigned int)*pea_total_len));
     518             : 
     519      303096 :         *ea_list = ea_list_head;
     520      303096 :         return NT_STATUS_OK;
     521             : }
     522             : 
     523             : /****************************************************************************
     524             :  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
     525             :  that was filled.
     526             : ****************************************************************************/
     527             : 
     528         170 : static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
     529             :         connection_struct *conn, struct ea_list *ea_list)
     530             : {
     531         170 :         unsigned int ret_data_size = 4;
     532         170 :         char *p = pdata;
     533             : 
     534         170 :         SMB_ASSERT(total_data_size >= 4);
     535             : 
     536         170 :         if (!lp_ea_support(SNUM(conn))) {
     537           0 :                 SIVAL(pdata,4,0);
     538           0 :                 return 4;
     539             :         }
     540             : 
     541         358 :         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
     542             :                 size_t dos_namelen;
     543             :                 fstring dos_ea_name;
     544         188 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     545         188 :                 dos_namelen = strlen(dos_ea_name);
     546         188 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     547             :                         break;
     548             :                 }
     549         188 :                 if (ea_list->ea.value.length > 65535) {
     550           0 :                         break;
     551             :                 }
     552         188 :                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
     553           0 :                         break;
     554             :                 }
     555             : 
     556             :                 /* We know we have room. */
     557         188 :                 SCVAL(p,0,ea_list->ea.flags);
     558         188 :                 SCVAL(p,1,dos_namelen);
     559         188 :                 SSVAL(p,2,ea_list->ea.value.length);
     560         188 :                 strlcpy(p+4, dos_ea_name, dos_namelen+1);
     561         188 :                 if (ea_list->ea.value.length > 0) {
     562         203 :                         memcpy(p + 4 + dos_namelen + 1,
     563         111 :                                ea_list->ea.value.data,
     564             :                                ea_list->ea.value.length);
     565             :                 }
     566             : 
     567         188 :                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
     568         188 :                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
     569             :         }
     570             : 
     571         170 :         ret_data_size = PTR_DIFF(p, pdata);
     572         170 :         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
     573         170 :         SIVAL(pdata,0,ret_data_size);
     574         142 :         return ret_data_size;
     575             : }
     576             : 
     577      154862 : static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
     578             :                                        char *pdata,
     579             :                                        unsigned int total_data_size,
     580             :                                        unsigned int *ret_data_size,
     581             :                                        connection_struct *conn,
     582             :                                        struct ea_list *ea_list)
     583             : {
     584      154862 :         uint8_t *p = (uint8_t *)pdata;
     585      154862 :         uint8_t *last_start = NULL;
     586      154862 :         bool do_store_data = (pdata != NULL);
     587             : 
     588      154862 :         *ret_data_size = 0;
     589             : 
     590      154862 :         if (!lp_ea_support(SNUM(conn))) {
     591           0 :                 return NT_STATUS_NO_EAS_ON_FILE;
     592             :         }
     593             : 
     594      313240 :         for (; ea_list; ea_list = ea_list->next) {
     595             :                 size_t dos_namelen;
     596             :                 fstring dos_ea_name;
     597             :                 size_t this_size;
     598        1758 :                 size_t pad = 0;
     599             : 
     600        1758 :                 if (last_start != NULL && do_store_data) {
     601           0 :                         SIVAL(last_start, 0, PTR_DIFF(p, last_start));
     602             :                 }
     603        1758 :                 last_start = p;
     604             : 
     605        1758 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     606        1758 :                 dos_namelen = strlen(dos_ea_name);
     607        1758 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     608           0 :                         return NT_STATUS_INTERNAL_ERROR;
     609             :                 }
     610        1758 :                 if (ea_list->ea.value.length > 65535) {
     611           0 :                         return NT_STATUS_INTERNAL_ERROR;
     612             :                 }
     613             : 
     614        1758 :                 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
     615             : 
     616        1758 :                 if (ea_list->next) {
     617         879 :                         pad = (4 - (this_size % 4)) % 4;
     618         879 :                         this_size += pad;
     619             :                 }
     620             : 
     621        1758 :                 if (do_store_data) {
     622           0 :                         if (this_size > total_data_size) {
     623           0 :                                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     624             :                         }
     625             : 
     626             :                         /* We know we have room. */
     627           0 :                         SIVAL(p, 0x00, 0); /* next offset */
     628           0 :                         SCVAL(p, 0x04, ea_list->ea.flags);
     629           0 :                         SCVAL(p, 0x05, dos_namelen);
     630           0 :                         SSVAL(p, 0x06, ea_list->ea.value.length);
     631           0 :                         strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
     632           0 :                         memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
     633           0 :                         if (pad) {
     634           0 :                                 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
     635             :                                         '\0',
     636             :                                         pad);
     637             :                         }
     638           0 :                         total_data_size -= this_size;
     639             :                 }
     640             : 
     641        1758 :                 p += this_size;
     642             :         }
     643             : 
     644      154862 :         *ret_data_size = PTR_DIFF(p, pdata);
     645      154862 :         DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
     646      154862 :         return NT_STATUS_OK;
     647             : }
     648             : 
     649      325508 : static unsigned int estimate_ea_size(files_struct *fsp)
     650             : {
     651      325508 :         size_t total_ea_len = 0;
     652             :         TALLOC_CTX *mem_ctx;
     653      325508 :         struct ea_list *ea_list = NULL;
     654             :         NTSTATUS status;
     655             : 
     656             :         /* symlink */
     657      325508 :         if (fsp == NULL) {
     658        1280 :                 return 0;
     659             :         }
     660             : 
     661      324228 :         mem_ctx = talloc_stackframe();
     662      324228 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     663           0 :                 return 0;
     664             :         }
     665             : 
     666             :         /* If this is a stream fsp, then we need to instead find the
     667             :          * estimated ea len from the main file, not the stream
     668             :          * (streams cannot have EAs), but the estimate isn't just 0 in
     669             :          * this case! */
     670      324228 :         if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
     671         132 :                 fsp = fsp->base_fsp;
     672             :         }
     673      324228 :         (void)get_ea_list_from_fsp(mem_ctx,
     674             :                                    fsp,
     675             :                                    &total_ea_len,
     676             :                                    &ea_list);
     677             : 
     678      324228 :         if(fsp->conn->sconn->using_smb2) {
     679             :                 unsigned int ret_data_size;
     680             :                 /*
     681             :                  * We're going to be using fill_ea_chained_buffer() to
     682             :                  * marshall EA's - this size is significantly larger
     683             :                  * than the SMB1 buffer. Re-calculate the size without
     684             :                  * marshalling.
     685             :                  */
     686      309724 :                 status = fill_ea_chained_buffer(mem_ctx,
     687             :                                                 NULL,
     688             :                                                 0,
     689             :                                                 &ret_data_size,
     690      154862 :                                                 fsp->conn,
     691             :                                                 ea_list);
     692      154862 :                 if (!NT_STATUS_IS_OK(status)) {
     693           0 :                         ret_data_size = 0;
     694             :                 }
     695      154862 :                 total_ea_len = ret_data_size;
     696             :         }
     697      324228 :         TALLOC_FREE(mem_ctx);
     698      324228 :         return total_ea_len;
     699             : }
     700             : 
     701             : /****************************************************************************
     702             :  Ensure the EA name is case insensitive by matching any existing EA name.
     703             : ****************************************************************************/
     704             : 
     705        3839 : static void canonicalize_ea_name(files_struct *fsp,
     706             :                         fstring unix_ea_name)
     707             : {
     708             :         size_t total_ea_len;
     709        3839 :         TALLOC_CTX *mem_ctx = talloc_tos();
     710             :         struct ea_list *ea_list;
     711        3839 :         NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
     712             :                                                fsp,
     713             :                                                &total_ea_len,
     714             :                                                &ea_list);
     715        3839 :         if (!NT_STATUS_IS_OK(status)) {
     716           0 :                 return;
     717             :         }
     718             : 
     719        4351 :         for (; ea_list; ea_list = ea_list->next) {
     720        2118 :                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
     721        1113 :                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
     722             :                                 &unix_ea_name[5], ea_list->ea.name));
     723        1113 :                         strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
     724        1113 :                         break;
     725             :                 }
     726             :         }
     727             : }
     728             : 
     729             : /****************************************************************************
     730             :  Set or delete an extended attribute.
     731             : ****************************************************************************/
     732             : 
     733        3193 : NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
     734             :                 struct ea_list *ea_list)
     735             : {
     736             :         NTSTATUS status;
     737        3193 :         bool posix_pathnames = false;
     738             : 
     739        3193 :         if (!lp_ea_support(SNUM(conn))) {
     740           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
     741             :         }
     742             : 
     743        3193 :         if (fsp == NULL) {
     744           0 :                 return NT_STATUS_INVALID_HANDLE;
     745             :         }
     746             : 
     747        3193 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     748             : 
     749        3193 :         status = refuse_symlink_fsp(fsp);
     750        3193 :         if (!NT_STATUS_IS_OK(status)) {
     751           0 :                 return status;
     752             :         }
     753             : 
     754        3193 :         status = check_access_fsp(fsp, FILE_WRITE_EA);
     755        3193 :         if (!NT_STATUS_IS_OK(status)) {
     756           0 :                 return status;
     757             :         }
     758             : 
     759             :         /* Setting EAs on streams isn't supported. */
     760        3193 :         if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
     761           4 :                 return NT_STATUS_INVALID_PARAMETER;
     762             :         }
     763             : 
     764             :         /*
     765             :          * Filter out invalid Windows EA names - before
     766             :          * we set *any* of them.
     767             :          */
     768             : 
     769        3189 :         if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
     770         235 :                 return STATUS_INVALID_EA_NAME;
     771             :         }
     772             : 
     773       13133 :         for (;ea_list; ea_list = ea_list->next) {
     774             :                 int ret;
     775             :                 fstring unix_ea_name;
     776             : 
     777        3839 :                 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
     778        3839 :                 fstrcat(unix_ea_name, ea_list->ea.name);
     779             : 
     780        3839 :                 canonicalize_ea_name(fsp, unix_ea_name);
     781             : 
     782        3839 :                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
     783             : 
     784        3839 :                 if (samba_private_attr_name(unix_ea_name)) {
     785           0 :                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
     786           0 :                         return NT_STATUS_ACCESS_DENIED;
     787             :                 }
     788             : 
     789        3839 :                 if (ea_list->ea.value.length == 0) {
     790             :                         /* Remove the attribute. */
     791        1060 :                         DBG_DEBUG("deleting ea name %s on "
     792             :                                   "file %s by file descriptor.\n",
     793             :                                   unix_ea_name, fsp_str_dbg(fsp));
     794        1060 :                         ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
     795             : #ifdef ENOATTR
     796             :                         /* Removing a non existent attribute always succeeds. */
     797        1060 :                         if (ret == -1 && errno == ENOATTR) {
     798           5 :                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
     799             :                                                 unix_ea_name));
     800           4 :                                 ret = 0;
     801             :                         }
     802             : #endif
     803             :                 } else {
     804        2779 :                         DEBUG(10,("set_ea: setting ea name %s on file "
     805             :                                   "%s by file descriptor.\n",
     806             :                                   unix_ea_name, fsp_str_dbg(fsp)));
     807        2779 :                         ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
     808             :                                                 ea_list->ea.value.data, ea_list->ea.value.length, 0);
     809             :                 }
     810             : 
     811        3838 :                 if (ret == -1) {
     812             : #ifdef ENOTSUP
     813           0 :                         if (errno == ENOTSUP) {
     814           0 :                                 return NT_STATUS_EAS_NOT_SUPPORTED;
     815             :                         }
     816             : #endif
     817           0 :                         return map_nt_error_from_unix(errno);
     818             :                 }
     819             : 
     820             :         }
     821        2954 :         return NT_STATUS_OK;
     822             : }
     823             : /****************************************************************************
     824             :  Read a list of EA names from an incoming data buffer. Create an ea_list with them.
     825             : ****************************************************************************/
     826             : 
     827         164 : static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     828             : {
     829         164 :         struct ea_list *ea_list_head = NULL;
     830         164 :         size_t converted_size, offset = 0;
     831             : 
     832         504 :         while (offset + 2 < data_size) {
     833         176 :                 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
     834         176 :                 unsigned int namelen = CVAL(pdata,offset);
     835             : 
     836         176 :                 offset++; /* Go past the namelen byte. */
     837             : 
     838             :                 /* integer wrap paranioa. */
     839         176 :                 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
     840         324 :                                 (offset > data_size) || (namelen > data_size) ||
     841         148 :                                 (offset + namelen >= data_size)) {
     842             :                         break;
     843             :                 }
     844             :                 /* Ensure the name is null terminated. */
     845         176 :                 if (pdata[offset + namelen] != '\0') {
     846           0 :                         return NULL;
     847             :                 }
     848         176 :                 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
     849             :                                        &converted_size)) {
     850           0 :                         DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
     851             :                                  "failed: %s", strerror(errno)));
     852             :                 }
     853         176 :                 if (!eal->ea.name) {
     854           0 :                         return NULL;
     855             :                 }
     856             : 
     857         176 :                 offset += (namelen + 1); /* Go past the name + terminating zero. */
     858         176 :                 DLIST_ADD_END(ea_list_head, eal);
     859         176 :                 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
     860             :         }
     861             : 
     862         136 :         return ea_list_head;
     863             : }
     864             : 
     865             : /****************************************************************************
     866             :  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
     867             : ****************************************************************************/
     868             : 
     869        3032 : static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     870             : {
     871        3032 :         struct ea_list *ea_list_head = NULL;
     872        3032 :         size_t offset = 0;
     873        3032 :         size_t bytes_used = 0;
     874             : 
     875        9850 :         while (offset < data_size) {
     876        3794 :                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
     877             : 
     878        3794 :                 if (!eal) {
     879           8 :                         return NULL;
     880             :                 }
     881             : 
     882        3786 :                 DLIST_ADD_END(ea_list_head, eal);
     883        3786 :                 offset += bytes_used;
     884             :         }
     885             : 
     886        2516 :         return ea_list_head;
     887             : }
     888             : 
     889             : /****************************************************************************
     890             :  Count the total EA size needed.
     891             : ****************************************************************************/
     892             : 
     893         166 : static size_t ea_list_size(struct ea_list *ealist)
     894             : {
     895             :         fstring dos_ea_name;
     896             :         struct ea_list *listp;
     897         166 :         size_t ret = 0;
     898             : 
     899         350 :         for (listp = ealist; listp; listp = listp->next) {
     900         184 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     901         184 :                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     902             :         }
     903             :         /* Add on 4 for total length. */
     904         166 :         if (ret) {
     905         166 :                 ret += 4;
     906             :         }
     907             : 
     908         166 :         return ret;
     909             : }
     910             : 
     911             : /****************************************************************************
     912             :  Return a union of EA's from a file list and a list of names.
     913             :  The TALLOC context for the two lists *MUST* be identical as we steal
     914             :  memory from one list to add to another. JRA.
     915             : ****************************************************************************/
     916             : 
     917         166 : static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
     918             : {
     919             :         struct ea_list *nlistp, *flistp;
     920             : 
     921         350 :         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
     922         312 :                 for (flistp = file_list; flistp; flistp = flistp->next) {
     923         263 :                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
     924          88 :                                 break;
     925             :                         }
     926             :                 }
     927             : 
     928         184 :                 if (flistp) {
     929             :                         /* Copy the data from this entry. */
     930         107 :                         nlistp->ea.flags = flistp->ea.flags;
     931         107 :                         nlistp->ea.value = flistp->ea.value;
     932             :                 } else {
     933             :                         /* Null entry. */
     934          77 :                         nlistp->ea.flags = 0;
     935          77 :                         ZERO_STRUCT(nlistp->ea.value);
     936             :                 }
     937             :         }
     938             : 
     939         166 :         *total_ea_len = ea_list_size(name_list);
     940         166 :         return name_list;
     941             : }
     942             : 
     943             : /****************************************************************************
     944             :   Send the required number of replies back.
     945             :   We assume all fields other than the data fields are
     946             :   set correctly for the type of call.
     947             :   HACK ! Always assumes smb_setup field is zero.
     948             : ****************************************************************************/
     949             : 
     950       27342 : void send_trans2_replies(connection_struct *conn,
     951             :                         struct smb_request *req,
     952             :                         NTSTATUS status,
     953             :                          const char *params,
     954             :                          int paramsize,
     955             :                          const char *pdata,
     956             :                          int datasize,
     957             :                          int max_data_bytes)
     958             : {
     959             :         /* As we are using a protocol > LANMAN1 then the max_send
     960             :          variable must have been set in the sessetupX call.
     961             :          This takes precedence over the max_xmit field in the
     962             :          global struct. These different max_xmit variables should
     963             :          be merged as this is now too confusing */
     964             : 
     965       27342 :         int data_to_send = datasize;
     966       27342 :         int params_to_send = paramsize;
     967             :         int useable_space;
     968       27342 :         const char *pp = params;
     969       27342 :         const char *pd = pdata;
     970             :         int params_sent_thistime, data_sent_thistime, total_sent_thistime;
     971       27342 :         int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
     972       27342 :         int data_alignment_offset = 0;
     973       27342 :         bool overflow = False;
     974       27342 :         struct smbXsrv_connection *xconn = req->xconn;
     975       27342 :         int max_send = xconn->smb1.sessions.max_send;
     976             : 
     977             :         /* Modify the data_to_send and datasize and set the error if
     978             :            we're trying to send more than max_data_bytes. We still send
     979             :            the part of the packet(s) that fit. Strange, but needed
     980             :            for OS/2. */
     981             : 
     982       27342 :         if (max_data_bytes > 0 && datasize > max_data_bytes) {
     983           0 :                 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
     984             :                         max_data_bytes, datasize ));
     985           0 :                 datasize = data_to_send = max_data_bytes;
     986           0 :                 overflow = True;
     987             :         }
     988             : 
     989             :         /* If there genuinely are no parameters or data to send just send the empty packet */
     990             : 
     991       27342 :         if(params_to_send == 0 && data_to_send == 0) {
     992           8 :                 reply_outbuf(req, 10, 0);
     993           8 :                 if (NT_STATUS_V(status)) {
     994             :                         uint8_t eclass;
     995             :                         uint32_t ecode;
     996           0 :                         ntstatus_to_dos(status, &eclass, &ecode);
     997           0 :                         error_packet_set((char *)req->outbuf,
     998             :                                         eclass, ecode, status,
     999             :                                         __LINE__,__FILE__);
    1000             :                 }
    1001           8 :                 show_msg((char *)req->outbuf);
    1002          32 :                 if (!srv_send_smb(xconn,
    1003           8 :                                 (char *)req->outbuf,
    1004           8 :                                 true, req->seqnum+1,
    1005           8 :                                 IS_CONN_ENCRYPTED(conn),
    1006             :                                 &req->pcd)) {
    1007           0 :                         exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
    1008             :                 }
    1009           8 :                 TALLOC_FREE(req->outbuf);
    1010           8 :                 return;
    1011             :         }
    1012             : 
    1013             :         /* When sending params and data ensure that both are nicely aligned */
    1014             :         /* Only do this alignment when there is also data to send - else
    1015             :                 can cause NT redirector problems. */
    1016             : 
    1017       27334 :         if (((params_to_send % 4) != 0) && (data_to_send != 0))
    1018       19243 :                 data_alignment_offset = 4 - (params_to_send % 4);
    1019             : 
    1020             :         /* Space is bufsize minus Netbios over TCP header minus SMB header */
    1021             :         /* The alignment_offset is to align the param bytes on an even byte
    1022             :                 boundary. NT 4.0 Beta needs this to work correctly. */
    1023             : 
    1024       27334 :         useable_space = max_send - (smb_size
    1025             :                                     + 2 * 10 /* wct */
    1026       26194 :                                     + alignment_offset
    1027       27334 :                                     + data_alignment_offset);
    1028             : 
    1029       27334 :         if (useable_space < 0) {
    1030           0 :                 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
    1031             :                           "= %d!!!", useable_space));
    1032           0 :                 exit_server_cleanly("send_trans2_replies: Not enough space");
    1033             :         }
    1034             : 
    1035       80874 :         while (params_to_send || data_to_send) {
    1036             :                 /* Calculate whether we will totally or partially fill this packet */
    1037             : 
    1038       27346 :                 total_sent_thistime = params_to_send + data_to_send;
    1039             : 
    1040             :                 /* We can never send more than useable_space */
    1041             :                 /*
    1042             :                  * Note that 'useable_space' does not include the alignment offsets,
    1043             :                  * but we must include the alignment offsets in the calculation of
    1044             :                  * the length of the data we send over the wire, as the alignment offsets
    1045             :                  * are sent here. Fix from Marc_Jacobsen@hp.com.
    1046             :                  */
    1047             : 
    1048       27346 :                 total_sent_thistime = MIN(total_sent_thistime, useable_space);
    1049             : 
    1050       54692 :                 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
    1051       27346 :                              + data_alignment_offset);
    1052             : 
    1053             :                 /* Set total params and data to be sent */
    1054       27346 :                 SSVAL(req->outbuf,smb_tprcnt,paramsize);
    1055       27346 :                 SSVAL(req->outbuf,smb_tdrcnt,datasize);
    1056             : 
    1057             :                 /* Calculate how many parameters and data we can fit into
    1058             :                  * this packet. Parameters get precedence
    1059             :                  */
    1060             : 
    1061       27346 :                 params_sent_thistime = MIN(params_to_send,useable_space);
    1062       27346 :                 data_sent_thistime = useable_space - params_sent_thistime;
    1063       27346 :                 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
    1064             : 
    1065       27346 :                 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
    1066             : 
    1067             :                 /* smb_proff is the offset from the start of the SMB header to the
    1068             :                         parameter bytes, however the first 4 bytes of outbuf are
    1069             :                         the Netbios over TCP header. Thus use smb_base() to subtract
    1070             :                         them from the calculation */
    1071             : 
    1072       27346 :                 SSVAL(req->outbuf,smb_proff,
    1073             :                       ((smb_buf(req->outbuf)+alignment_offset)
    1074             :                        - smb_base(req->outbuf)));
    1075             : 
    1076       27346 :                 if(params_sent_thistime == 0)
    1077        1432 :                         SSVAL(req->outbuf,smb_prdisp,0);
    1078             :                 else
    1079             :                         /* Absolute displacement of param bytes sent in this packet */
    1080       25914 :                         SSVAL(req->outbuf,smb_prdisp,pp - params);
    1081             : 
    1082       27346 :                 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
    1083       27346 :                 if(data_sent_thistime == 0) {
    1084        5059 :                         SSVAL(req->outbuf,smb_droff,0);
    1085        5059 :                         SSVAL(req->outbuf,smb_drdisp, 0);
    1086             :                 } else {
    1087             :                         /* The offset of the data bytes is the offset of the
    1088             :                                 parameter bytes plus the number of parameters being sent this time */
    1089       22287 :                         SSVAL(req->outbuf, smb_droff,
    1090             :                               ((smb_buf(req->outbuf)+alignment_offset)
    1091             :                                - smb_base(req->outbuf))
    1092             :                               + params_sent_thistime + data_alignment_offset);
    1093       22287 :                         SSVAL(req->outbuf,smb_drdisp, pd - pdata);
    1094             :                 }
    1095             : 
    1096             :                 /* Initialize the padding for alignment */
    1097             : 
    1098       26206 :                 if (alignment_offset != 0) {
    1099       27346 :                         memset(smb_buf(req->outbuf), 0, alignment_offset);
    1100             :                 }
    1101             : 
    1102             :                 /* Copy the param bytes into the packet */
    1103             : 
    1104       27346 :                 if(params_sent_thistime) {
    1105       25914 :                         memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
    1106             :                                params_sent_thistime);
    1107             :                 }
    1108             : 
    1109             :                 /* Copy in the data bytes */
    1110       27346 :                 if(data_sent_thistime) {
    1111       22287 :                         if (data_alignment_offset != 0) {
    1112       19251 :                                 memset((smb_buf(req->outbuf)+alignment_offset+
    1113             :                                         params_sent_thistime), 0,
    1114             :                                        data_alignment_offset);
    1115             :                         }
    1116       44574 :                         memcpy(smb_buf(req->outbuf)+alignment_offset
    1117       22287 :                                +params_sent_thistime+data_alignment_offset,
    1118             :                                pd,data_sent_thistime);
    1119             :                 }
    1120             : 
    1121       27346 :                 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
    1122             :                         params_sent_thistime, data_sent_thistime, useable_space));
    1123       27346 :                 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
    1124             :                         params_to_send, data_to_send, paramsize, datasize));
    1125             : 
    1126       27346 :                 if (overflow) {
    1127           0 :                         error_packet_set((char *)req->outbuf,
    1128             :                                          ERRDOS,ERRbufferoverflow,
    1129           0 :                                          STATUS_BUFFER_OVERFLOW,
    1130             :                                          __LINE__,__FILE__);
    1131       27346 :                 } else if (NT_STATUS_V(status)) {
    1132             :                         uint8_t eclass;
    1133             :                         uint32_t ecode;
    1134         235 :                         ntstatus_to_dos(status, &eclass, &ecode);
    1135         235 :                         error_packet_set((char *)req->outbuf,
    1136             :                                         eclass, ecode, status,
    1137             :                                         __LINE__,__FILE__);
    1138             :                 }
    1139             : 
    1140             :                 /* Send the packet */
    1141       27346 :                 show_msg((char *)req->outbuf);
    1142      109384 :                 if (!srv_send_smb(xconn,
    1143       27346 :                                 (char *)req->outbuf,
    1144       27346 :                                 true, req->seqnum+1,
    1145       27346 :                                 IS_CONN_ENCRYPTED(conn),
    1146             :                                 &req->pcd))
    1147           0 :                         exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
    1148             : 
    1149       27346 :                 TALLOC_FREE(req->outbuf);
    1150             : 
    1151       27346 :                 pp += params_sent_thistime;
    1152       27346 :                 pd += data_sent_thistime;
    1153             : 
    1154       27346 :                 params_to_send -= params_sent_thistime;
    1155       27346 :                 data_to_send -= data_sent_thistime;
    1156             : 
    1157             :                 /* Sanity check */
    1158       27346 :                 if(params_to_send < 0 || data_to_send < 0) {
    1159           0 :                         DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
    1160             :                                 params_to_send, data_to_send));
    1161           0 :                         return;
    1162             :                 }
    1163             :         }
    1164             : 
    1165       26194 :         return;
    1166             : }
    1167             : 
    1168             : /****************************************************************************
    1169             :  Reply to a TRANSACT2_OPEN.
    1170             : ****************************************************************************/
    1171             : 
    1172          98 : static void call_trans2open(connection_struct *conn,
    1173             :                             struct smb_request *req,
    1174             :                             char **pparams, int total_params,
    1175             :                             char **ppdata, int total_data,
    1176             :                             unsigned int max_data_bytes)
    1177             : {
    1178          98 :         struct smb_filename *smb_fname = NULL;
    1179          98 :         char *params = *pparams;
    1180          98 :         char *pdata = *ppdata;
    1181             :         int deny_mode;
    1182             :         int32_t open_attr;
    1183             :         bool oplock_request;
    1184             : #if 0
    1185             :         bool return_additional_info;
    1186             :         int16 open_sattr;
    1187             :         time_t open_time;
    1188             : #endif
    1189             :         int open_ofun;
    1190             :         uint32_t open_size;
    1191             :         char *pname;
    1192          98 :         char *fname = NULL;
    1193          98 :         off_t size=0;
    1194          98 :         int fattr=0,mtime=0;
    1195          98 :         SMB_INO_T inode = 0;
    1196          98 :         int smb_action = 0;
    1197             :         files_struct *fsp;
    1198          98 :         struct ea_list *ea_list = NULL;
    1199          98 :         uint16_t flags = 0;
    1200             :         NTSTATUS status;
    1201             :         uint32_t access_mask;
    1202             :         uint32_t share_mode;
    1203             :         uint32_t create_disposition;
    1204          98 :         uint32_t create_options = 0;
    1205          98 :         uint32_t private_flags = 0;
    1206          98 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    1207          98 :         TALLOC_CTX *ctx = talloc_tos();
    1208             : 
    1209             :         /*
    1210             :          * Ensure we have enough parameters to perform the operation.
    1211             :          */
    1212             : 
    1213          98 :         if (total_params < 29) {
    1214           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1215           0 :                 goto out;
    1216             :         }
    1217             : 
    1218          98 :         flags = SVAL(params, 0);
    1219          98 :         deny_mode = SVAL(params, 2);
    1220          98 :         open_attr = SVAL(params,6);
    1221          98 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
    1222          98 :         if (oplock_request) {
    1223           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
    1224             :         }
    1225             : 
    1226             : #if 0
    1227             :         return_additional_info = BITSETW(params,0);
    1228             :         open_sattr = SVAL(params, 4);
    1229             :         open_time = make_unix_date3(params+8);
    1230             : #endif
    1231          98 :         open_ofun = SVAL(params,12);
    1232          98 :         open_size = IVAL(params,14);
    1233          98 :         pname = &params[28];
    1234             : 
    1235          98 :         if (IS_IPC(conn)) {
    1236           0 :                 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
    1237           0 :                 goto out;
    1238             :         }
    1239             : 
    1240          98 :         if (req->posix_pathnames) {
    1241           0 :                 srvstr_get_path_posix(ctx,
    1242             :                         params,
    1243           0 :                         req->flags2,
    1244             :                         &fname,
    1245             :                         pname,
    1246           0 :                         total_params - 28,
    1247             :                         STR_TERMINATE,
    1248             :                         &status);
    1249             :         } else {
    1250         196 :                 srvstr_get_path(ctx,
    1251             :                         params,
    1252          98 :                         req->flags2,
    1253             :                         &fname,
    1254             :                         pname,
    1255          98 :                         total_params - 28,
    1256             :                         STR_TERMINATE,
    1257             :                         &status);
    1258             :         }
    1259          98 :         if (!NT_STATUS_IS_OK(status)) {
    1260           0 :                 reply_nterror(req, status);
    1261           0 :                 goto out;
    1262             :         }
    1263             : 
    1264          98 :         DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
    1265             :                 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
    1266             :                 (unsigned int)open_ofun, open_size));
    1267             : 
    1268          98 :         status = filename_convert(ctx,
    1269             :                                 conn,
    1270             :                                 fname,
    1271             :                                 ucf_flags,
    1272             :                                 0,
    1273             :                                 &smb_fname);
    1274          98 :         if (!NT_STATUS_IS_OK(status)) {
    1275           0 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    1276           0 :                         reply_botherror(req,
    1277             :                                 NT_STATUS_PATH_NOT_COVERED,
    1278             :                                 ERRSRV, ERRbadpath);
    1279           0 :                         goto out;
    1280             :                 }
    1281           0 :                 reply_nterror(req, status);
    1282           0 :                 goto out;
    1283             :         }
    1284             : 
    1285          98 :         if (open_ofun == 0) {
    1286          10 :                 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
    1287          10 :                 goto out;
    1288             :         }
    1289             : 
    1290          88 :         if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
    1291             :                                          open_ofun,
    1292             :                                          &access_mask, &share_mode,
    1293             :                                          &create_disposition,
    1294             :                                          &create_options,
    1295             :                                          &private_flags)) {
    1296           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1297           0 :                 goto out;
    1298             :         }
    1299             : 
    1300             :         /* Any data in this call is an EA list. */
    1301          88 :         if (total_data && (total_data != 4)) {
    1302          88 :                 if (total_data < 10) {
    1303           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1304           0 :                         goto out;
    1305             :                 }
    1306             : 
    1307          88 :                 if (IVAL(pdata,0) > total_data) {
    1308           0 :                         DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
    1309             :                                 IVAL(pdata,0), (unsigned int)total_data));
    1310           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1311           0 :                         goto out;
    1312             :                 }
    1313             : 
    1314          88 :                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
    1315          88 :                                        total_data - 4);
    1316          88 :                 if (!ea_list) {
    1317           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    1318           0 :                         goto out;
    1319             :                 }
    1320             : 
    1321          88 :                 if (!lp_ea_support(SNUM(conn))) {
    1322           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    1323           0 :                         goto out;
    1324             :                 }
    1325             : 
    1326         176 :                 if (!req->posix_pathnames &&
    1327          88 :                                 ea_list_has_invalid_name(ea_list)) {
    1328           0 :                         int param_len = 30;
    1329           0 :                         *pparams = (char *)SMB_REALLOC(*pparams, param_len);
    1330           0 :                         if(*pparams == NULL ) {
    1331           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1332           0 :                                 goto out;
    1333             :                         }
    1334           0 :                         params = *pparams;
    1335           0 :                         memset(params, '\0', param_len);
    1336           0 :                         send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
    1337             :                                 params, param_len, NULL, 0, max_data_bytes);
    1338           0 :                         goto out;
    1339             :                 }
    1340             :         }
    1341             : 
    1342          88 :         status = SMB_VFS_CREATE_FILE(
    1343             :                 conn,                                   /* conn */
    1344             :                 req,                                    /* req */
    1345             :                 smb_fname,                              /* fname */
    1346             :                 access_mask,                            /* access_mask */
    1347             :                 share_mode,                             /* share_access */
    1348             :                 create_disposition,                     /* create_disposition*/
    1349             :                 create_options,                         /* create_options */
    1350             :                 open_attr,                              /* file_attributes */
    1351             :                 oplock_request,                         /* oplock_request */
    1352             :                 NULL,                                   /* lease */
    1353             :                 open_size,                              /* allocation_size */
    1354             :                 private_flags,
    1355             :                 NULL,                                   /* sd */
    1356             :                 ea_list,                                /* ea_list */
    1357             :                 &fsp,                                       /* result */
    1358             :                 &smb_action,                                /* psbuf */
    1359             :                 NULL, NULL);                            /* create context */
    1360             : 
    1361          88 :         if (!NT_STATUS_IS_OK(status)) {
    1362          33 :                 if (open_was_deferred(req->xconn, req->mid)) {
    1363             :                         /* We have re-scheduled this call. */
    1364           0 :                         goto out;
    1365             :                 }
    1366             : 
    1367          33 :                 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    1368          23 :                         reply_openerror(req, status);
    1369          23 :                         goto out;
    1370             :                 }
    1371             : 
    1372          10 :                 fsp = fcb_or_dos_open(
    1373             :                         req,
    1374             :                         smb_fname,
    1375             :                         access_mask,
    1376             :                         create_options,
    1377             :                         private_flags);
    1378          10 :                 if (fsp == NULL) {
    1379          10 :                         bool ok = defer_smb1_sharing_violation(req);
    1380          10 :                         if (ok) {
    1381           4 :                                 goto out;
    1382             :                         }
    1383           5 :                         reply_openerror(req, status);
    1384           5 :                         goto out;
    1385             :                 }
    1386             : 
    1387           0 :                 smb_action = FILE_WAS_OPENED;
    1388             :         }
    1389             : 
    1390          55 :         size = get_file_size_stat(&smb_fname->st);
    1391          55 :         fattr = fdos_mode(fsp);
    1392          55 :         mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
    1393          55 :         inode = smb_fname->st.st_ex_ino;
    1394          55 :         if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
    1395           0 :                 close_file(req, fsp, ERROR_CLOSE);
    1396           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    1397           0 :                 goto out;
    1398             :         }
    1399             : 
    1400             :         /* Realloc the size of parameters and data we will return */
    1401          55 :         *pparams = (char *)SMB_REALLOC(*pparams, 30);
    1402          55 :         if(*pparams == NULL ) {
    1403           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    1404           0 :                 goto out;
    1405             :         }
    1406          55 :         params = *pparams;
    1407             : 
    1408          55 :         SSVAL(params,0,fsp->fnum);
    1409          55 :         SSVAL(params,2,fattr);
    1410          55 :         srv_put_dos_date2(params,4, mtime);
    1411          55 :         SIVAL(params,8, (uint32_t)size);
    1412          55 :         SSVAL(params,12,deny_mode);
    1413          55 :         SSVAL(params,14,0); /* open_type - file or directory. */
    1414          55 :         SSVAL(params,16,0); /* open_state - only valid for IPC device. */
    1415             : 
    1416          55 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    1417           0 :                 smb_action |= EXTENDED_OPLOCK_GRANTED;
    1418             :         }
    1419             : 
    1420          55 :         SSVAL(params,18,smb_action);
    1421             : 
    1422             :         /*
    1423             :          * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
    1424             :          */
    1425          55 :         SIVAL(params,20,inode);
    1426          55 :         SSVAL(params,24,0); /* Padding. */
    1427          55 :         if (flags & 8) {
    1428           0 :                 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
    1429           0 :                 SIVAL(params, 26, ea_size);
    1430             :         } else {
    1431          55 :                 SIVAL(params, 26, 0);
    1432             :         }
    1433             : 
    1434             :         /* Send the required number of replies */
    1435          55 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
    1436          99 :  out:
    1437          98 :         TALLOC_FREE(smb_fname);
    1438          98 : }
    1439             : 
    1440             : /*********************************************************
    1441             :  Routine to check if a given string matches exactly.
    1442             :  as a special case a mask of "." does NOT match. That
    1443             :  is required for correct wildcard semantics
    1444             :  Case can be significant or not.
    1445             : **********************************************************/
    1446             : 
    1447      515999 : static bool exact_match(bool has_wild,
    1448             :                         bool case_sensitive,
    1449             :                         const char *str,
    1450             :                         const char *mask)
    1451             : {
    1452      515999 :         if (mask[0] == '.' && mask[1] == 0) {
    1453           0 :                 return false;
    1454             :         }
    1455             : 
    1456      515999 :         if (has_wild) {
    1457      501487 :                 return false;
    1458             :         }
    1459             : 
    1460       14414 :         if (case_sensitive) {
    1461          42 :                 return strcmp(str,mask)==0;
    1462             :         } else {
    1463       14372 :                 return strcasecmp_m(str,mask) == 0;
    1464             :         }
    1465             : }
    1466             : 
    1467             : /****************************************************************************
    1468             :  Return the filetype for UNIX extensions.
    1469             : ****************************************************************************/
    1470             : 
    1471         472 : static uint32_t unix_filetype(mode_t mode)
    1472             : {
    1473         472 :         if(S_ISREG(mode))
    1474         280 :                 return UNIX_TYPE_FILE;
    1475         192 :         else if(S_ISDIR(mode))
    1476          80 :                 return UNIX_TYPE_DIR;
    1477             : #ifdef S_ISLNK
    1478         112 :         else if(S_ISLNK(mode))
    1479         112 :                 return UNIX_TYPE_SYMLINK;
    1480             : #endif
    1481             : #ifdef S_ISCHR
    1482           0 :         else if(S_ISCHR(mode))
    1483           0 :                 return UNIX_TYPE_CHARDEV;
    1484             : #endif
    1485             : #ifdef S_ISBLK
    1486           0 :         else if(S_ISBLK(mode))
    1487           0 :                 return UNIX_TYPE_BLKDEV;
    1488             : #endif
    1489             : #ifdef S_ISFIFO
    1490           0 :         else if(S_ISFIFO(mode))
    1491           0 :                 return UNIX_TYPE_FIFO;
    1492             : #endif
    1493             : #ifdef S_ISSOCK
    1494           0 :         else if(S_ISSOCK(mode))
    1495           0 :                 return UNIX_TYPE_SOCKET;
    1496             : #endif
    1497             : 
    1498           0 :         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
    1499           0 :         return UNIX_TYPE_UNKNOWN;
    1500             : }
    1501             : 
    1502             : /****************************************************************************
    1503             :  Map wire perms onto standard UNIX permissions. Obey share restrictions.
    1504             : ****************************************************************************/
    1505             : 
    1506         870 : NTSTATUS unix_perms_from_wire(connection_struct *conn,
    1507             :                               const SMB_STRUCT_STAT *psbuf,
    1508             :                               uint32_t perms,
    1509             :                               enum perm_type ptype,
    1510             :                               mode_t *ret_perms)
    1511             : {
    1512         870 :         mode_t ret = 0;
    1513             : 
    1514         870 :         if (perms == SMB_MODE_NO_CHANGE) {
    1515         132 :                 if (!VALID_STAT(*psbuf)) {
    1516           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1517             :                 } else {
    1518         132 :                         *ret_perms = psbuf->st_ex_mode;
    1519         132 :                         return NT_STATUS_OK;
    1520             :                 }
    1521             :         }
    1522             : 
    1523         738 :         ret = wire_perms_to_unix(perms);
    1524             : 
    1525         738 :         if (ptype == PERM_NEW_FILE) {
    1526             :                 /*
    1527             :                  * "create mask"/"force create mode" are
    1528             :                  * only applied to new files, not existing ones.
    1529             :                  */
    1530         474 :                 ret &= lp_create_mask(SNUM(conn));
    1531             :                 /* Add in force bits */
    1532         474 :                 ret |= lp_force_create_mode(SNUM(conn));
    1533         264 :         } else if (ptype == PERM_NEW_DIR) {
    1534             :                 /*
    1535             :                  * "directory mask"/"force directory mode" are
    1536             :                  * only applied to new directories, not existing ones.
    1537             :                  */
    1538         172 :                 ret &= lp_directory_mask(SNUM(conn));
    1539             :                 /* Add in force bits */
    1540         172 :                 ret |= lp_force_directory_mode(SNUM(conn));
    1541             :         }
    1542             : 
    1543         738 :         *ret_perms = ret;
    1544         738 :         return NT_STATUS_OK;
    1545             : }
    1546             : 
    1547             : /****************************************************************************
    1548             :  Needed to show the msdfs symlinks as directories. Modifies psbuf
    1549             :  to be a directory if it's a msdfs link.
    1550             : ****************************************************************************/
    1551             : 
    1552         276 : static bool check_msdfs_link(struct files_struct *dirfsp,
    1553             :                              struct smb_filename *atname,
    1554             :                              struct smb_filename *smb_fname)
    1555             : {
    1556         276 :         int saved_errno = errno;
    1557         552 :         if(lp_host_msdfs() &&
    1558         538 :                 lp_msdfs_root(SNUM(dirfsp->conn)) &&
    1559         262 :                 is_msdfs_link(dirfsp, atname)) {
    1560             : 
    1561             :                 /*
    1562             :                  * Copy the returned stat struct from the relative
    1563             :                  * to the full pathname.
    1564             :                  */
    1565         262 :                 smb_fname->st = atname->st;
    1566             : 
    1567         262 :                 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
    1568             :                         "as a directory\n",
    1569             :                         smb_fname->base_name));
    1570         262 :                 smb_fname->st.st_ex_mode =
    1571         262 :                         (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
    1572         262 :                 errno = saved_errno;
    1573         262 :                 return true;
    1574             :         }
    1575          14 :         errno = saved_errno;
    1576          14 :         return false;
    1577             : }
    1578             : 
    1579             : 
    1580             : /****************************************************************************
    1581             :  Get a level dependent lanman2 dir entry.
    1582             : ****************************************************************************/
    1583             : 
    1584             : struct smbd_dirptr_lanman2_state {
    1585             :         connection_struct *conn;
    1586             :         uint32_t info_level;
    1587             :         bool check_mangled_names;
    1588             :         bool has_wild;
    1589             :         bool got_exact_match;
    1590             : };
    1591             : 
    1592      510134 : static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
    1593             :                                          void *private_data,
    1594             :                                          const char *dname,
    1595             :                                          const char *mask,
    1596             :                                          char **_fname)
    1597             : {
    1598      510134 :         struct smbd_dirptr_lanman2_state *state =
    1599             :                 (struct smbd_dirptr_lanman2_state *)private_data;
    1600             :         bool ok;
    1601             :         char mangled_name[13]; /* mangled 8.3 name. */
    1602             :         bool got_match;
    1603             :         const char *fname;
    1604             : 
    1605             :         /* Mangle fname if it's an illegal name. */
    1606      510134 :         if (mangle_must_mangle(dname, state->conn->params)) {
    1607             :                 /*
    1608             :                  * Slow path - ensure we can push the original name as UCS2. If
    1609             :                  * not, then just don't return this name.
    1610             :                  */
    1611             :                 NTSTATUS status;
    1612          54 :                 size_t ret_len = 0;
    1613          54 :                 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
    1614          54 :                 uint8_t *tmp = talloc_array(talloc_tos(),
    1615             :                                         uint8_t,
    1616             :                                         len);
    1617             : 
    1618          54 :                 status = srvstr_push(NULL,
    1619             :                         FLAGS2_UNICODE_STRINGS,
    1620             :                         tmp,
    1621             :                         dname,
    1622             :                         len,
    1623             :                         STR_TERMINATE,
    1624             :                         &ret_len);
    1625             : 
    1626          54 :                 TALLOC_FREE(tmp);
    1627             : 
    1628          54 :                 if (!NT_STATUS_IS_OK(status)) {
    1629          40 :                         return false;
    1630             :                 }
    1631             : 
    1632          34 :                 ok = name_to_8_3(dname, mangled_name,
    1633          34 :                                  true, state->conn->params);
    1634          34 :                 if (!ok) {
    1635           0 :                         return false;
    1636             :                 }
    1637          34 :                 fname = mangled_name;
    1638             :         } else {
    1639      509895 :                 fname = dname;
    1640             :         }
    1641             : 
    1642      510114 :         got_match = exact_match(state->has_wild,
    1643      510114 :                                 state->conn->case_sensitive,
    1644             :                                 fname, mask);
    1645      510114 :         state->got_exact_match = got_match;
    1646      510114 :         if (!got_match) {
    1647      508634 :                 got_match = mask_match(fname, mask,
    1648      508634 :                                        state->conn->case_sensitive);
    1649             :         }
    1650             : 
    1651      524626 :         if(!got_match && state->check_mangled_names &&
    1652       14512 :            !mangle_is_8_3(fname, false, state->conn->params)) {
    1653             :                 /*
    1654             :                  * It turns out that NT matches wildcards against
    1655             :                  * both long *and* short names. This may explain some
    1656             :                  * of the wildcard wierdness from old DOS clients
    1657             :                  * that some people have been seeing.... JRA.
    1658             :                  */
    1659             :                 /* Force the mangling into 8.3. */
    1660        5885 :                 ok = name_to_8_3(fname, mangled_name,
    1661        5885 :                                  false, state->conn->params);
    1662        5885 :                 if (!ok) {
    1663           0 :                         return false;
    1664             :                 }
    1665             : 
    1666        5885 :                 got_match = exact_match(state->has_wild,
    1667        5885 :                                         state->conn->case_sensitive,
    1668             :                                         mangled_name, mask);
    1669        5885 :                 state->got_exact_match = got_match;
    1670        5885 :                 if (!got_match) {
    1671        5885 :                         got_match = mask_match(mangled_name, mask,
    1672        5885 :                                                state->conn->case_sensitive);
    1673             :                 }
    1674             :         }
    1675             : 
    1676      510114 :         if (!got_match) {
    1677       14512 :                 return false;
    1678             :         }
    1679             : 
    1680      495602 :         *_fname = talloc_strdup(ctx, fname);
    1681      495602 :         if (*_fname == NULL) {
    1682           0 :                 return false;
    1683             :         }
    1684             : 
    1685      495602 :         return true;
    1686             : }
    1687             : 
    1688      495402 : static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
    1689             :                                         void *private_data,
    1690             :                                         struct files_struct *dirfsp,
    1691             :                                         struct smb_filename *atname,
    1692             :                                         struct smb_filename *smb_fname,
    1693             :                                         bool get_dosmode,
    1694             :                                         uint32_t *_mode)
    1695             : {
    1696      495402 :         struct smbd_dirptr_lanman2_state *state =
    1697             :                 (struct smbd_dirptr_lanman2_state *)private_data;
    1698      495402 :         bool ms_dfs_link = false;
    1699             : 
    1700      495402 :         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
    1701         546 :                 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
    1702           0 :                         DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
    1703             :                                  "Couldn't lstat [%s] (%s)\n",
    1704             :                                  smb_fname_str_dbg(smb_fname),
    1705             :                                  strerror(errno)));
    1706           0 :                         return false;
    1707             :                 }
    1708         546 :                 return true;
    1709      495132 :         } else if (!VALID_STAT(smb_fname->st) &&
    1710         276 :                    SMB_VFS_STAT(state->conn, smb_fname) != 0) {
    1711             :                 /* Needed to show the msdfs symlinks as
    1712             :                  * directories */
    1713             : 
    1714         276 :                 ms_dfs_link = check_msdfs_link(dirfsp,
    1715             :                                                atname,
    1716             :                                                smb_fname);
    1717         276 :                 if (!ms_dfs_link) {
    1718          14 :                         DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
    1719             :                                  "Couldn't stat [%s] (%s)\n",
    1720             :                                  smb_fname_str_dbg(smb_fname),
    1721             :                                  strerror(errno)));
    1722          14 :                         return false;
    1723             :                 }
    1724             : 
    1725         262 :                 *_mode = dos_mode_msdfs(state->conn, smb_fname);
    1726         262 :                 return true;
    1727             :         }
    1728             : 
    1729      494580 :         if (!get_dosmode) {
    1730       41770 :                 return true;
    1731             :         }
    1732             : 
    1733      452810 :         *_mode = fdos_mode(smb_fname->fsp);
    1734      452810 :         smb_fname->st = smb_fname->fsp->fsp_name->st;
    1735             : 
    1736      452810 :         return true;
    1737             : }
    1738             : 
    1739      494704 : static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
    1740             :                                     connection_struct *conn,
    1741             :                                     uint16_t flags2,
    1742             :                                     uint32_t info_level,
    1743             :                                     struct ea_list *name_list,
    1744             :                                     bool check_mangled_names,
    1745             :                                     bool requires_resume_key,
    1746             :                                     uint32_t mode,
    1747             :                                     const char *fname,
    1748             :                                     const struct smb_filename *smb_fname,
    1749             :                                     int space_remaining,
    1750             :                                     uint8_t align,
    1751             :                                     bool do_pad,
    1752             :                                     char *base_data,
    1753             :                                     char **ppdata,
    1754             :                                     char *end_data,
    1755             :                                     uint64_t *last_entry_off)
    1756             : {
    1757      494704 :         char *p, *q, *pdata = *ppdata;
    1758      494704 :         uint32_t reskey=0;
    1759      494704 :         uint64_t file_size = 0;
    1760      494704 :         uint64_t allocation_size = 0;
    1761      494704 :         uint64_t file_id = 0;
    1762      494704 :         size_t len = 0;
    1763      494704 :         struct timespec mdate_ts = {0};
    1764      494704 :         struct timespec adate_ts = {0};
    1765      494704 :         struct timespec cdate_ts = {0};
    1766      494704 :         struct timespec create_date_ts = {0};
    1767      494704 :         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
    1768             :         char *nameptr;
    1769             :         char *last_entry_ptr;
    1770             :         bool was_8_3;
    1771             :         int off;
    1772      494704 :         int pad = 0;
    1773             :         NTSTATUS status;
    1774      494704 :         struct readdir_attr_data *readdir_attr_data = NULL;
    1775             : 
    1776      494704 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    1777      448667 :                 file_size = get_file_size_stat(&smb_fname->st);
    1778             :         }
    1779      494704 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
    1780             : 
    1781             :         /*
    1782             :          * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
    1783             :          * a DFS symlink.
    1784             :          */
    1785      987673 :         if (smb_fname->fsp != NULL &&
    1786      492969 :             !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
    1787      493154 :                 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
    1788             :                                                ctx,
    1789             :                                                &readdir_attr_data);
    1790      493154 :                 if (!NT_STATUS_IS_OK(status)) {
    1791      492866 :                         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
    1792             :                                              status)) {
    1793           0 :                                 return status;
    1794             :                         }
    1795             :                 }
    1796             :         }
    1797             : 
    1798      494704 :         file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
    1799             : 
    1800      494704 :         mdate_ts = smb_fname->st.st_ex_mtime;
    1801      494704 :         adate_ts = smb_fname->st.st_ex_atime;
    1802      494704 :         create_date_ts = get_create_timespec(conn, NULL, smb_fname);
    1803      494704 :         cdate_ts = get_change_timespec(conn, NULL, smb_fname);
    1804             : 
    1805      494704 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    1806           0 :                 dos_filetime_timespec(&create_date_ts);
    1807           0 :                 dos_filetime_timespec(&mdate_ts);
    1808           0 :                 dos_filetime_timespec(&adate_ts);
    1809           0 :                 dos_filetime_timespec(&cdate_ts);
    1810             :         }
    1811             : 
    1812      494704 :         create_date = convert_timespec_to_time_t(create_date_ts);
    1813      494704 :         mdate = convert_timespec_to_time_t(mdate_ts);
    1814      494704 :         adate = convert_timespec_to_time_t(adate_ts);
    1815             : 
    1816             :         /* align the record */
    1817      494704 :         SMB_ASSERT(align >= 1);
    1818             : 
    1819      494704 :         off = (int)PTR_DIFF(pdata, base_data);
    1820      494704 :         pad = (off + (align-1)) & ~(align-1);
    1821      494704 :         pad -= off;
    1822             : 
    1823      494704 :         if (pad && pad > space_remaining) {
    1824           0 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1825             :                         "for padding (wanted %u, had %d)\n",
    1826             :                         (unsigned int)pad,
    1827             :                         space_remaining ));
    1828           0 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1829             :         }
    1830             : 
    1831      494704 :         off += pad;
    1832             :         /* initialize padding to 0 */
    1833      494704 :         if (pad) {
    1834      255732 :                 memset(pdata, 0, pad);
    1835             :         }
    1836      494704 :         space_remaining -= pad;
    1837             : 
    1838      494704 :         DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
    1839             :                 space_remaining ));
    1840             : 
    1841      494704 :         pdata += pad;
    1842      494704 :         p = pdata;
    1843      494704 :         last_entry_ptr = p;
    1844             : 
    1845      494704 :         pad = 0;
    1846      494704 :         off = 0;
    1847             : 
    1848      494704 :         switch (info_level) {
    1849        8406 :         case SMB_FIND_INFO_STANDARD:
    1850        8406 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
    1851        8406 :                 if(requires_resume_key) {
    1852           0 :                         SIVAL(p,0,reskey);
    1853           0 :                         p += 4;
    1854             :                 }
    1855        8406 :                 srv_put_dos_date2(p,0,create_date);
    1856        8406 :                 srv_put_dos_date2(p,4,adate);
    1857        8406 :                 srv_put_dos_date2(p,8,mdate);
    1858        8406 :                 SIVAL(p,12,(uint32_t)file_size);
    1859        8406 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1860        8406 :                 SSVAL(p,20,mode);
    1861        8406 :                 p += 23;
    1862        8406 :                 nameptr = p;
    1863        8406 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1864        8406 :                         p += ucs2_align(base_data, p, 0);
    1865             :                 }
    1866        8406 :                 status = srvstr_push(base_data, flags2, p,
    1867             :                                   fname, PTR_DIFF(end_data, p),
    1868             :                                   STR_TERMINATE, &len);
    1869        8406 :                 if (!NT_STATUS_IS_OK(status)) {
    1870           0 :                         return status;
    1871             :                 }
    1872        8406 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1873        8406 :                         if (len > 2) {
    1874        8406 :                                 SCVAL(nameptr, -1, len - 2);
    1875             :                         } else {
    1876           0 :                                 SCVAL(nameptr, -1, 0);
    1877             :                         }
    1878             :                 } else {
    1879           0 :                         if (len > 1) {
    1880           0 :                                 SCVAL(nameptr, -1, len - 1);
    1881             :                         } else {
    1882           0 :                                 SCVAL(nameptr, -1, 0);
    1883             :                         }
    1884             :                 }
    1885        8406 :                 p += len;
    1886        8406 :                 break;
    1887             : 
    1888      106206 :         case SMB_FIND_EA_SIZE:
    1889      106206 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
    1890      106206 :                 if (requires_resume_key) {
    1891       97800 :                         SIVAL(p,0,reskey);
    1892       97800 :                         p += 4;
    1893             :                 }
    1894      106206 :                 srv_put_dos_date2(p,0,create_date);
    1895      106206 :                 srv_put_dos_date2(p,4,adate);
    1896      106206 :                 srv_put_dos_date2(p,8,mdate);
    1897      106206 :                 SIVAL(p,12,(uint32_t)file_size);
    1898      106206 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1899      106206 :                 SSVAL(p,20,mode);
    1900             :                 {
    1901      106206 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    1902      106206 :                         SIVAL(p,22,ea_size); /* Extended attributes */
    1903             :                 }
    1904      106206 :                 p += 27;
    1905      106206 :                 nameptr = p - 1;
    1906      106206 :                 status = srvstr_push(base_data, flags2,
    1907             :                                   p, fname, PTR_DIFF(end_data, p),
    1908             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1909      106206 :                 if (!NT_STATUS_IS_OK(status)) {
    1910           0 :                         return status;
    1911             :                 }
    1912      106206 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1913      106206 :                         if (len > 2) {
    1914      106206 :                                 len -= 2;
    1915             :                         } else {
    1916           0 :                                 len = 0;
    1917             :                         }
    1918             :                 } else {
    1919           0 :                         if (len > 1) {
    1920           0 :                                 len -= 1;
    1921             :                         } else {
    1922           0 :                                 len = 0;
    1923             :                         }
    1924             :                 }
    1925      106206 :                 SCVAL(nameptr,0,len);
    1926      106206 :                 p += len;
    1927      106206 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1928      106206 :                 break;
    1929             : 
    1930          18 :         case SMB_FIND_EA_LIST:
    1931             :         {
    1932          18 :                 struct ea_list *file_list = NULL;
    1933          18 :                 size_t ea_len = 0;
    1934             : 
    1935          18 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
    1936          18 :                 if (!name_list) {
    1937           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1938             :                 }
    1939          18 :                 if (requires_resume_key) {
    1940          18 :                         SIVAL(p,0,reskey);
    1941          18 :                         p += 4;
    1942             :                 }
    1943          18 :                 srv_put_dos_date2(p,0,create_date);
    1944          18 :                 srv_put_dos_date2(p,4,adate);
    1945          18 :                 srv_put_dos_date2(p,8,mdate);
    1946          18 :                 SIVAL(p,12,(uint32_t)file_size);
    1947          18 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1948          18 :                 SSVAL(p,20,mode);
    1949          18 :                 p += 22; /* p now points to the EA area. */
    1950             : 
    1951          18 :                 status = get_ea_list_from_fsp(ctx,
    1952          18 :                                                smb_fname->fsp,
    1953             :                                                &ea_len, &file_list);
    1954          18 :                 if (!NT_STATUS_IS_OK(status)) {
    1955           0 :                         file_list = NULL;
    1956             :                 }
    1957          18 :                 name_list = ea_list_union(name_list, file_list, &ea_len);
    1958             : 
    1959             :                 /* We need to determine if this entry will fit in the space available. */
    1960             :                 /* Max string size is 255 bytes. */
    1961          18 :                 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
    1962           0 :                         DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1963             :                                 "(wanted %u, had %d)\n",
    1964             :                                 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
    1965             :                                 space_remaining ));
    1966           0 :                         return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1967             :                 }
    1968             : 
    1969             :                 /* Push the ea_data followed by the name. */
    1970          18 :                 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
    1971          18 :                 nameptr = p;
    1972          18 :                 status = srvstr_push(base_data, flags2,
    1973             :                                   p + 1, fname, PTR_DIFF(end_data, p+1),
    1974             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1975          18 :                 if (!NT_STATUS_IS_OK(status)) {
    1976           0 :                         return status;
    1977             :                 }
    1978          18 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1979          18 :                         if (len > 2) {
    1980          18 :                                 len -= 2;
    1981             :                         } else {
    1982           0 :                                 len = 0;
    1983             :                         }
    1984             :                 } else {
    1985           0 :                         if (len > 1) {
    1986           0 :                                 len -= 1;
    1987             :                         } else {
    1988           0 :                                 len = 0;
    1989             :                         }
    1990             :                 }
    1991          18 :                 SCVAL(nameptr,0,len);
    1992          18 :                 p += len + 1;
    1993          18 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1994          18 :                 break;
    1995             :         }
    1996             : 
    1997      119859 :         case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    1998      119859 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
    1999      119859 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    2000      119859 :                 p += 4;
    2001      119859 :                 SIVAL(p,0,reskey); p += 4;
    2002      119859 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    2003      119859 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    2004      119859 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    2005      119859 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    2006      119859 :                 SOFF_T(p,0,file_size); p += 8;
    2007      119859 :                 SOFF_T(p,0,allocation_size); p += 8;
    2008      119859 :                 SIVAL(p,0,mode); p += 4;
    2009      119859 :                 q = p; p += 4; /* q is placeholder for name length. */
    2010      119859 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    2011          58 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    2012             :                 } else {
    2013      119801 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    2014      119801 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    2015             :                 }
    2016      119859 :                 p += 4;
    2017             :                 /* Clear the short name buffer. This is
    2018             :                  * IMPORTANT as not doing so will trigger
    2019             :                  * a Win2k client bug. JRA.
    2020             :                  */
    2021      135783 :                 if (!was_8_3 && check_mangled_names) {
    2022             :                         char mangled_name[13]; /* mangled 8.3 name. */
    2023       15932 :                         if (!name_to_8_3(fname,mangled_name,True,
    2024       15932 :                                            conn->params)) {
    2025             :                                 /* Error - mangle failed ! */
    2026           0 :                                 memset(mangled_name,'\0',12);
    2027             :                         }
    2028       15932 :                         mangled_name[12] = 0;
    2029       15932 :                         status = srvstr_push(base_data, flags2,
    2030             :                                           p+2, mangled_name, 24,
    2031             :                                           STR_UPPER|STR_UNICODE, &len);
    2032       15932 :                         if (!NT_STATUS_IS_OK(status)) {
    2033           0 :                                 return status;
    2034             :                         }
    2035       15932 :                         if (len < 24) {
    2036       10444 :                                 memset(p + 2 + len,'\0',24 - len);
    2037             :                         }
    2038       15932 :                         SSVAL(p, 0, len);
    2039             :                 } else {
    2040      103837 :                         memset(p,'\0',26);
    2041             :                 }
    2042      119859 :                 p += 2 + 24;
    2043      119859 :                 status = srvstr_push(base_data, flags2, p,
    2044             :                                   fname, PTR_DIFF(end_data, p),
    2045             :                                   STR_TERMINATE_ASCII, &len);
    2046      119859 :                 if (!NT_STATUS_IS_OK(status)) {
    2047           6 :                         return status;
    2048             :                 }
    2049      119853 :                 SIVAL(q,0,len);
    2050      119853 :                 p += len;
    2051             : 
    2052      119853 :                 len = PTR_DIFF(p, pdata);
    2053      119853 :                 pad = (len + (align-1)) & ~(align-1);
    2054             :                 /*
    2055             :                  * offset to the next entry, the caller
    2056             :                  * will overwrite it for the last entry
    2057             :                  * that's why we always include the padding
    2058             :                  */
    2059      119853 :                 SIVAL(pdata,0,pad);
    2060             :                 /*
    2061             :                  * set padding to zero
    2062             :                  */
    2063      119853 :                 if (do_pad) {
    2064       36037 :                         memset(p, 0, pad - len);
    2065       35939 :                         p = pdata + pad;
    2066             :                 } else {
    2067       83914 :                         p = pdata + len;
    2068             :                 }
    2069      119755 :                 break;
    2070             : 
    2071       20961 :         case SMB_FIND_FILE_DIRECTORY_INFO:
    2072       20961 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
    2073       20961 :                 p += 4;
    2074       20961 :                 SIVAL(p,0,reskey); p += 4;
    2075       20961 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    2076       20961 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    2077       20961 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    2078       20961 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    2079       20961 :                 SOFF_T(p,0,file_size); p += 8;
    2080       20961 :                 SOFF_T(p,0,allocation_size); p += 8;
    2081       20961 :                 SIVAL(p,0,mode); p += 4;
    2082       20961 :                 status = srvstr_push(base_data, flags2,
    2083             :                                   p + 4, fname, PTR_DIFF(end_data, p+4),
    2084             :                                   STR_TERMINATE_ASCII, &len);
    2085       20961 :                 if (!NT_STATUS_IS_OK(status)) {
    2086           0 :                         return status;
    2087             :                 }
    2088       20961 :                 SIVAL(p,0,len);
    2089       20961 :                 p += 4 + len;
    2090             : 
    2091       20961 :                 len = PTR_DIFF(p, pdata);
    2092       20961 :                 pad = (len + (align-1)) & ~(align-1);
    2093             :                 /*
    2094             :                  * offset to the next entry, the caller
    2095             :                  * will overwrite it for the last entry
    2096             :                  * that's why we always include the padding
    2097             :                  */
    2098       20961 :                 SIVAL(pdata,0,pad);
    2099             :                 /*
    2100             :                  * set padding to zero
    2101             :                  */
    2102       20961 :                 if (do_pad) {
    2103        8406 :                         memset(p, 0, pad - len);
    2104        8406 :                         p = pdata + pad;
    2105             :                 } else {
    2106       12555 :                         p = pdata + len;
    2107             :                 }
    2108       20961 :                 break;
    2109             : 
    2110       20317 :         case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    2111       20317 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
    2112       20317 :                 p += 4;
    2113       20317 :                 SIVAL(p,0,reskey); p += 4;
    2114       20317 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    2115       20317 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    2116       20317 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    2117       20317 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    2118       20317 :                 SOFF_T(p,0,file_size); p += 8;
    2119       20317 :                 SOFF_T(p,0,allocation_size); p += 8;
    2120       20317 :                 SIVAL(p,0,mode); p += 4;
    2121       20317 :                 q = p; p += 4; /* q is placeholder for name length. */
    2122       20317 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    2123           0 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    2124             :                 } else {
    2125       20317 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    2126       20317 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    2127             :                 }
    2128       20317 :                 p +=4;
    2129       20317 :                 status = srvstr_push(base_data, flags2, p,
    2130             :                                   fname, PTR_DIFF(end_data, p),
    2131             :                                   STR_TERMINATE_ASCII, &len);
    2132       20317 :                 if (!NT_STATUS_IS_OK(status)) {
    2133           0 :                         return status;
    2134             :                 }
    2135       20317 :                 SIVAL(q, 0, len);
    2136       20317 :                 p += len;
    2137             : 
    2138       20317 :                 len = PTR_DIFF(p, pdata);
    2139       20317 :                 pad = (len + (align-1)) & ~(align-1);
    2140             :                 /*
    2141             :                  * offset to the next entry, the caller
    2142             :                  * will overwrite it for the last entry
    2143             :                  * that's why we always include the padding
    2144             :                  */
    2145       20317 :                 SIVAL(pdata,0,pad);
    2146             :                 /*
    2147             :                  * set padding to zero
    2148             :                  */
    2149       20317 :                 if (do_pad) {
    2150        8928 :                         memset(p, 0, pad - len);
    2151        8841 :                         p = pdata + pad;
    2152             :                 } else {
    2153       11476 :                         p = pdata + len;
    2154             :                 }
    2155       20230 :                 break;
    2156             : 
    2157      146973 :         case SMB_FIND_FILE_NAMES_INFO:
    2158      146973 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
    2159      146973 :                 p += 4;
    2160      146973 :                 SIVAL(p,0,reskey); p += 4;
    2161      146973 :                 p += 4;
    2162             :                 /* this must *not* be null terminated or w2k gets in a loop trying to set an
    2163             :                    acl on a dir (tridge) */
    2164      146973 :                 status = srvstr_push(base_data, flags2, p,
    2165             :                                   fname, PTR_DIFF(end_data, p),
    2166             :                                   STR_TERMINATE_ASCII, &len);
    2167      146973 :                 if (!NT_STATUS_IS_OK(status)) {
    2168           0 :                         return status;
    2169             :                 }
    2170      146973 :                 SIVAL(p, -4, len);
    2171      146973 :                 p += len;
    2172             : 
    2173      146973 :                 len = PTR_DIFF(p, pdata);
    2174      146973 :                 pad = (len + (align-1)) & ~(align-1);
    2175             :                 /*
    2176             :                  * offset to the next entry, the caller
    2177             :                  * will overwrite it for the last entry
    2178             :                  * that's why we always include the padding
    2179             :                  */
    2180      146973 :                 SIVAL(pdata,0,pad);
    2181             :                 /*
    2182             :                  * set padding to zero
    2183             :                  */
    2184      146973 :                 if (do_pad) {
    2185           6 :                         memset(p, 0, pad - len);
    2186           6 :                         p = pdata + pad;
    2187             :                 } else {
    2188      146967 :                         p = pdata + len;
    2189             :                 }
    2190      146973 :                 break;
    2191             : 
    2192       19846 :         case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    2193       19846 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
    2194       19846 :                 p += 4;
    2195       19846 :                 SIVAL(p,0,reskey); p += 4;
    2196       19846 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    2197       19846 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    2198       19846 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    2199       19846 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    2200       19846 :                 SOFF_T(p,0,file_size); p += 8;
    2201       19846 :                 SOFF_T(p,0,allocation_size); p += 8;
    2202       19846 :                 SIVAL(p,0,mode); p += 4;
    2203       19846 :                 q = p; p += 4; /* q is placeholder for name length. */
    2204       19846 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    2205           0 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    2206             :                 } else {
    2207       19846 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    2208       19846 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    2209             :                 }
    2210       19846 :                 p += 4;
    2211       19846 :                 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
    2212       19846 :                 SBVAL(p,0,file_id); p += 8;
    2213       19846 :                 status = srvstr_push(base_data, flags2, p,
    2214             :                                   fname, PTR_DIFF(end_data, p),
    2215             :                                   STR_TERMINATE_ASCII, &len);
    2216       19846 :                 if (!NT_STATUS_IS_OK(status)) {
    2217           0 :                         return status;
    2218             :                 }
    2219       19846 :                 SIVAL(q, 0, len);
    2220       19846 :                 p += len;
    2221             : 
    2222       19846 :                 len = PTR_DIFF(p, pdata);
    2223       19846 :                 pad = (len + (align-1)) & ~(align-1);
    2224             :                 /*
    2225             :                  * offset to the next entry, the caller
    2226             :                  * will overwrite it for the last entry
    2227             :                  * that's why we always include the padding
    2228             :                  */
    2229       19846 :                 SIVAL(pdata,0,pad);
    2230             :                 /*
    2231             :                  * set padding to zero
    2232             :                  */
    2233       19846 :                 if (do_pad) {
    2234        8406 :                         memset(p, 0, pad - len);
    2235        8406 :                         p = pdata + pad;
    2236             :                 } else {
    2237       11440 :                         p = pdata + len;
    2238             :                 }
    2239       19846 :                 break;
    2240             : 
    2241       52108 :         case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    2242       52108 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
    2243       52108 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    2244       52108 :                 p += 4;
    2245       52108 :                 SIVAL(p,0,reskey); p += 4;
    2246       52108 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    2247       52108 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    2248       52108 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    2249       52108 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    2250       52108 :                 SOFF_T(p,0,file_size); p += 8;
    2251       52108 :                 SOFF_T(p,0,allocation_size); p += 8;
    2252       52108 :                 SIVAL(p,0,mode); p += 4;
    2253       52108 :                 q = p; p += 4; /* q is placeholder for name length */
    2254       52108 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    2255         204 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    2256       52002 :                 } else if (readdir_attr_data &&
    2257          98 :                            readdir_attr_data->type == RDATTR_AAPL) {
    2258             :                         /*
    2259             :                          * OS X specific SMB2 extension negotiated via
    2260             :                          * AAPL create context: return max_access in
    2261             :                          * ea_size field.
    2262             :                          */
    2263          98 :                         SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
    2264             :                 } else {
    2265       51806 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    2266       51806 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    2267             :                 }
    2268       52108 :                 p += 4;
    2269             : 
    2270       52206 :                 if (readdir_attr_data &&
    2271          98 :                     readdir_attr_data->type == RDATTR_AAPL) {
    2272             :                         /*
    2273             :                          * OS X specific SMB2 extension negotiated via
    2274             :                          * AAPL create context: return resource fork
    2275             :                          * length and compressed FinderInfo in
    2276             :                          * shortname field.
    2277             :                          *
    2278             :                          * According to documentation short_name_len
    2279             :                          * should be 0, but on the wire behaviour
    2280             :                          * shows its set to 24 by clients.
    2281             :                          */
    2282          98 :                         SSVAL(p, 0, 24);
    2283             : 
    2284             :                         /* Resourefork length */
    2285          98 :                         SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
    2286             : 
    2287             :                         /* Compressed FinderInfo */
    2288          98 :                         memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
    2289       63188 :                 } else if (!was_8_3 && check_mangled_names) {
    2290             :                         char mangled_name[13]; /* mangled 8.3 name. */
    2291       11178 :                         if (!name_to_8_3(fname,mangled_name,True,
    2292       11178 :                                         conn->params)) {
    2293             :                                 /* Error - mangle failed ! */
    2294           0 :                                 memset(mangled_name,'\0',12);
    2295             :                         }
    2296       11178 :                         mangled_name[12] = 0;
    2297       11178 :                         status = srvstr_push(base_data, flags2,
    2298             :                                           p+2, mangled_name, 24,
    2299             :                                           STR_UPPER|STR_UNICODE, &len);
    2300       11178 :                         if (!NT_STATUS_IS_OK(status)) {
    2301           0 :                                 return status;
    2302             :                         }
    2303       11178 :                         SSVAL(p, 0, len);
    2304       11178 :                         if (len < 24) {
    2305       10176 :                                 memset(p + 2 + len,'\0',24 - len);
    2306             :                         }
    2307       11178 :                         SSVAL(p, 0, len);
    2308             :                 } else {
    2309             :                         /* Clear the short name buffer. This is
    2310             :                          * IMPORTANT as not doing so will trigger
    2311             :                          * a Win2k client bug. JRA.
    2312             :                          */
    2313       40832 :                         memset(p,'\0',26);
    2314             :                 }
    2315       52108 :                 p += 26;
    2316             : 
    2317             :                 /* Reserved ? */
    2318       52206 :                 if (readdir_attr_data &&
    2319         196 :                     readdir_attr_data->type == RDATTR_AAPL) {
    2320             :                         /*
    2321             :                          * OS X specific SMB2 extension negotiated via
    2322             :                          * AAPL create context: return UNIX mode in
    2323             :                          * reserved field.
    2324             :                          */
    2325          98 :                         uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
    2326          98 :                         SSVAL(p, 0, aapl_mode);
    2327             :                 } else {
    2328       52010 :                         SSVAL(p, 0, 0);
    2329             :                 }
    2330       52108 :                 p += 2;
    2331             : 
    2332       52108 :                 SBVAL(p,0,file_id); p += 8;
    2333       52108 :                 status = srvstr_push(base_data, flags2, p,
    2334             :                                   fname, PTR_DIFF(end_data, p),
    2335             :                                   STR_TERMINATE_ASCII, &len);
    2336       52108 :                 if (!NT_STATUS_IS_OK(status)) {
    2337          14 :                         return status;
    2338             :                 }
    2339       52094 :                 SIVAL(q,0,len);
    2340       52094 :                 p += len;
    2341             : 
    2342       52094 :                 len = PTR_DIFF(p, pdata);
    2343       52094 :                 pad = (len + (align-1)) & ~(align-1);
    2344             :                 /*
    2345             :                  * offset to the next entry, the caller
    2346             :                  * will overwrite it for the last entry
    2347             :                  * that's why we always include the padding
    2348             :                  */
    2349       52094 :                 SIVAL(pdata,0,pad);
    2350             :                 /*
    2351             :                  * set padding to zero
    2352             :                  */
    2353       52094 :                 if (do_pad) {
    2354        8406 :                         memset(p, 0, pad - len);
    2355        8406 :                         p = pdata + pad;
    2356             :                 } else {
    2357       43688 :                         p = pdata + len;
    2358             :                 }
    2359       52094 :                 break;
    2360             : 
    2361             :         /* CIFS UNIX Extension. */
    2362             : 
    2363          10 :         case SMB_FIND_FILE_UNIX:
    2364             :         case SMB_FIND_FILE_UNIX_INFO2:
    2365          10 :                 p+= 4;
    2366          10 :                 SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
    2367             : 
    2368             :                 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
    2369             : 
    2370          10 :                 if (info_level == SMB_FIND_FILE_UNIX) {
    2371           6 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
    2372           6 :                         p = store_file_unix_basic(conn, p,
    2373             :                                                 NULL, &smb_fname->st);
    2374           6 :                         status = srvstr_push(base_data, flags2, p,
    2375             :                                           fname, PTR_DIFF(end_data, p),
    2376             :                                           STR_TERMINATE, &len);
    2377           6 :                         if (!NT_STATUS_IS_OK(status)) {
    2378           0 :                                 return status;
    2379             :                         }
    2380             :                 } else {
    2381           4 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
    2382           4 :                         p = store_file_unix_basic_info2(conn, p,
    2383             :                                                 NULL, &smb_fname->st);
    2384           4 :                         nameptr = p;
    2385           4 :                         p += 4;
    2386           4 :                         status = srvstr_push(base_data, flags2, p, fname,
    2387             :                                           PTR_DIFF(end_data, p), 0, &len);
    2388           4 :                         if (!NT_STATUS_IS_OK(status)) {
    2389           0 :                                 return status;
    2390             :                         }
    2391           4 :                         SIVAL(nameptr, 0, len);
    2392             :                 }
    2393             : 
    2394          10 :                 p += len;
    2395             : 
    2396          10 :                 len = PTR_DIFF(p, pdata);
    2397          10 :                 pad = (len + (align-1)) & ~(align-1);
    2398             :                 /*
    2399             :                  * offset to the next entry, the caller
    2400             :                  * will overwrite it for the last entry
    2401             :                  * that's why we always include the padding
    2402             :                  */
    2403          10 :                 SIVAL(pdata,0,pad);
    2404             :                 /*
    2405             :                  * set padding to zero
    2406             :                  */
    2407          10 :                 if (do_pad) {
    2408          10 :                         memset(p, 0, pad - len);
    2409          10 :                         p = pdata + pad;
    2410             :                 } else {
    2411           0 :                         p = pdata + len;
    2412             :                 }
    2413             :                 /* End of SMB_QUERY_FILE_UNIX_BASIC */
    2414             : 
    2415          10 :                 break;
    2416             : 
    2417           0 :         default:
    2418           0 :                 return NT_STATUS_INVALID_LEVEL;
    2419             :         }
    2420             : 
    2421      494684 :         if (PTR_DIFF(p,pdata) > space_remaining) {
    2422        1852 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    2423             :                         "(wanted %u, had %d)\n",
    2424             :                         (unsigned int)PTR_DIFF(p,pdata),
    2425             :                         space_remaining ));
    2426        1852 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    2427             :         }
    2428             : 
    2429             :         /* Setup the last entry pointer, as an offset from base_data */
    2430      492832 :         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
    2431             :         /* Advance the data pointer to the next slot */
    2432      492832 :         *ppdata = p;
    2433             : 
    2434      492832 :         return NT_STATUS_OK;
    2435             : }
    2436             : 
    2437      514450 : NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
    2438             :                                connection_struct *conn,
    2439             :                                struct dptr_struct *dirptr,
    2440             :                                uint16_t flags2,
    2441             :                                const char *path_mask,
    2442             :                                uint32_t dirtype,
    2443             :                                int info_level,
    2444             :                                int requires_resume_key,
    2445             :                                bool dont_descend,
    2446             :                                bool ask_sharemode,
    2447             :                                bool get_dosmode,
    2448             :                                uint8_t align,
    2449             :                                bool do_pad,
    2450             :                                char **ppdata,
    2451             :                                char *base_data,
    2452             :                                char *end_data,
    2453             :                                int space_remaining,
    2454             :                                struct smb_filename **_smb_fname,
    2455             :                                bool *got_exact_match,
    2456             :                                int *_last_entry_off,
    2457             :                                struct ea_list *name_list,
    2458             :                                struct file_id *file_id)
    2459             : {
    2460             :         const char *p;
    2461      514450 :         const char *mask = NULL;
    2462      514450 :         long prev_dirpos = 0;
    2463      514450 :         uint32_t mode = 0;
    2464      514450 :         char *fname = NULL;
    2465      514450 :         struct smb_filename *smb_fname = NULL;
    2466             :         struct smbd_dirptr_lanman2_state state;
    2467             :         bool ok;
    2468      514450 :         uint64_t last_entry_off = 0;
    2469             :         NTSTATUS status;
    2470             :         enum mangled_names_options mangled_names;
    2471             :         bool marshall_with_83_names;
    2472             : 
    2473      514450 :         mangled_names = lp_mangled_names(conn->params);
    2474             : 
    2475      514450 :         ZERO_STRUCT(state);
    2476      514450 :         state.conn = conn;
    2477      514450 :         state.info_level = info_level;
    2478      514450 :         if (mangled_names != MANGLED_NAMES_NO) {
    2479      514450 :                 state.check_mangled_names = true;
    2480             :         }
    2481      514450 :         state.has_wild = dptr_has_wild(dirptr);
    2482      514450 :         state.got_exact_match = false;
    2483             : 
    2484      514450 :         *got_exact_match = false;
    2485             : 
    2486      514450 :         p = strrchr_m(path_mask,'/');
    2487      514450 :         if(p != NULL) {
    2488           0 :                 if(p[1] == '\0') {
    2489           0 :                         mask = "*.*";
    2490             :                 } else {
    2491           0 :                         mask = p+1;
    2492             :                 }
    2493             :         } else {
    2494      514220 :                 mask = path_mask;
    2495             :         }
    2496             : 
    2497      514450 :         ok = smbd_dirptr_get_entry(ctx,
    2498             :                                    dirptr,
    2499             :                                    mask,
    2500             :                                    dirtype,
    2501             :                                    dont_descend,
    2502             :                                    ask_sharemode,
    2503             :                                    get_dosmode,
    2504             :                                    smbd_dirptr_lanman2_match_fn,
    2505             :                                    smbd_dirptr_lanman2_mode_fn,
    2506             :                                    &state,
    2507             :                                    &fname,
    2508             :                                    &smb_fname,
    2509             :                                    &mode,
    2510             :                                    &prev_dirpos);
    2511      514450 :         if (!ok) {
    2512       19746 :                 return NT_STATUS_END_OF_FILE;
    2513             :         }
    2514             : 
    2515      494704 :         *got_exact_match = state.got_exact_match;
    2516             : 
    2517      494704 :         marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
    2518             : 
    2519      494704 :         status = smbd_marshall_dir_entry(ctx,
    2520             :                                      conn,
    2521             :                                      flags2,
    2522             :                                      info_level,
    2523             :                                      name_list,
    2524             :                                      marshall_with_83_names,
    2525             :                                      requires_resume_key,
    2526             :                                      mode,
    2527             :                                      fname,
    2528             :                                      smb_fname,
    2529             :                                      space_remaining,
    2530             :                                      align,
    2531             :                                      do_pad,
    2532             :                                      base_data,
    2533             :                                      ppdata,
    2534             :                                      end_data,
    2535             :                                      &last_entry_off);
    2536      494704 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
    2537          20 :                 DEBUG(1,("Conversion error: illegal character: %s\n",
    2538             :                          smb_fname_str_dbg(smb_fname)));
    2539             :         }
    2540             : 
    2541      494704 :         if (file_id != NULL) {
    2542      310054 :                 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    2543             :         }
    2544             : 
    2545      496576 :         if (!NT_STATUS_IS_OK(status) &&
    2546        1872 :             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
    2547             :         {
    2548          20 :                 TALLOC_FREE(smb_fname);
    2549          20 :                 TALLOC_FREE(fname);
    2550          20 :                 return status;
    2551             :         }
    2552             : 
    2553      494684 :         if (_smb_fname != NULL) {
    2554             :                 /*
    2555             :                  * smb_fname is already talloc'ed off ctx.
    2556             :                  * We just need to make sure we don't return
    2557             :                  * any stream_name, and replace base_name
    2558             :                  * with fname in case base_name got mangled.
    2559             :                  * This allows us to preserve any smb_fname->fsp
    2560             :                  * for asynchronous handle lookups.
    2561             :                  */
    2562      310040 :                 TALLOC_FREE(smb_fname->stream_name);
    2563      310040 :                 TALLOC_FREE(smb_fname->base_name);
    2564      310040 :                 smb_fname->base_name = talloc_strdup(smb_fname, fname);
    2565             : 
    2566      310040 :                 if (smb_fname->base_name == NULL) {
    2567           0 :                         TALLOC_FREE(smb_fname);
    2568           0 :                         TALLOC_FREE(fname);
    2569           0 :                         return NT_STATUS_NO_MEMORY;
    2570             :                 }
    2571      310040 :                 *_smb_fname = smb_fname;
    2572             :         } else {
    2573      184644 :                 TALLOC_FREE(smb_fname);
    2574             :         }
    2575      494684 :         TALLOC_FREE(fname);
    2576             : 
    2577      494684 :         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
    2578        1852 :                 dptr_SeekDir(dirptr, prev_dirpos);
    2579        1852 :                 return status;
    2580             :         }
    2581             : 
    2582      492832 :         *_last_entry_off = last_entry_off;
    2583      492832 :         return NT_STATUS_OK;
    2584             : }
    2585             : 
    2586      191145 : static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
    2587             :                                 connection_struct *conn,
    2588             :                                 struct dptr_struct *dirptr,
    2589             :                                 uint16_t flags2,
    2590             :                                 const char *path_mask,
    2591             :                                 uint32_t dirtype,
    2592             :                                 int info_level,
    2593             :                                 bool requires_resume_key,
    2594             :                                 bool dont_descend,
    2595             :                                 bool ask_sharemode,
    2596             :                                 char **ppdata,
    2597             :                                 char *base_data,
    2598             :                                 char *end_data,
    2599             :                                 int space_remaining,
    2600             :                                 bool *got_exact_match,
    2601             :                                 int *last_entry_off,
    2602             :                                 struct ea_list *name_list)
    2603             : {
    2604      191145 :         uint8_t align = 4;
    2605      191145 :         const bool do_pad = true;
    2606             : 
    2607      191145 :         if (info_level >= 1 && info_level <= 3) {
    2608             :                 /* No alignment on earlier info levels. */
    2609      114822 :                 align = 1;
    2610             :         }
    2611             : 
    2612      191145 :         return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
    2613             :                                          path_mask, dirtype, info_level,
    2614             :                                          requires_resume_key, dont_descend, ask_sharemode,
    2615             :                                          true, align, do_pad,
    2616             :                                          ppdata, base_data, end_data,
    2617             :                                          space_remaining,
    2618             :                                          NULL,
    2619             :                                          got_exact_match,
    2620             :                                          last_entry_off, name_list, NULL);
    2621             : }
    2622             : 
    2623             : /****************************************************************************
    2624             :  Reply to a TRANS2_FINDFIRST.
    2625             : ****************************************************************************/
    2626             : 
    2627        7100 : static void call_trans2findfirst(connection_struct *conn,
    2628             :                                  struct smb_request *req,
    2629             :                                  char **pparams, int total_params,
    2630             :                                  char **ppdata, int total_data,
    2631             :                                  unsigned int max_data_bytes)
    2632             : {
    2633             :         /* We must be careful here that we don't return more than the
    2634             :                 allowed number of data bytes. If this means returning fewer than
    2635             :                 maxentries then so be it. We assume that the redirector has
    2636             :                 enough room for the fixed number of parameter bytes it has
    2637             :                 requested. */
    2638        7100 :         struct smb_filename *smb_dname = NULL;
    2639        7100 :         char *params = *pparams;
    2640        7100 :         char *pdata = *ppdata;
    2641             :         char *data_end;
    2642             :         uint32_t dirtype;
    2643             :         int maxentries;
    2644             :         uint16_t findfirst_flags;
    2645             :         bool close_after_first;
    2646             :         bool close_if_end;
    2647             :         bool requires_resume_key;
    2648             :         int info_level;
    2649        7100 :         char *directory = NULL;
    2650        7100 :         char *mask = NULL;
    2651             :         char *p;
    2652        7100 :         int last_entry_off=0;
    2653        7100 :         int dptr_num = -1;
    2654        7100 :         int numentries = 0;
    2655             :         int i;
    2656        7100 :         bool finished = False;
    2657        7100 :         bool dont_descend = False;
    2658        7100 :         bool out_of_space = False;
    2659             :         int space_remaining;
    2660        7100 :         struct ea_list *ea_list = NULL;
    2661        7100 :         NTSTATUS ntstatus = NT_STATUS_OK;
    2662        7100 :         bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
    2663        7100 :         struct smbd_server_connection *sconn = req->sconn;
    2664        7100 :         uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
    2665        7100 :                         ucf_flags_from_smb_request(req);
    2666        7100 :         bool backup_priv = false;
    2667        7100 :         bool as_root = false;
    2668        7100 :         files_struct *fsp = NULL;
    2669        7100 :         const struct loadparm_substitution *lp_sub =
    2670             :                 loadparm_s3_global_substitution();
    2671             :         int ret;
    2672             : 
    2673        7100 :         if (total_params < 13) {
    2674           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2675           0 :                 goto out;
    2676             :         }
    2677             : 
    2678        7100 :         dirtype = SVAL(params,0);
    2679        7100 :         maxentries = SVAL(params,2);
    2680        7100 :         findfirst_flags = SVAL(params,4);
    2681        7100 :         close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
    2682        7100 :         close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
    2683        7100 :         requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
    2684        7106 :         backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
    2685           6 :                                 security_token_has_privilege(get_current_nttok(conn),
    2686             :                                                 SEC_PRIV_BACKUP));
    2687             : 
    2688        7100 :         info_level = SVAL(params,6);
    2689             : 
    2690        7100 :         DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
    2691             : close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
    2692             :                 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
    2693             :                 (int)backup_priv,
    2694             :                 info_level, max_data_bytes));
    2695             : 
    2696        7100 :         if (!maxentries) {
    2697             :                 /* W2K3 seems to treat zero as 1. */
    2698          12 :                 maxentries = 1;
    2699             :         }
    2700             : 
    2701        7100 :         switch (info_level) {
    2702        6952 :                 case SMB_FIND_INFO_STANDARD:
    2703             :                 case SMB_FIND_EA_SIZE:
    2704             :                 case SMB_FIND_EA_LIST:
    2705             :                 case SMB_FIND_FILE_DIRECTORY_INFO:
    2706             :                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    2707             :                 case SMB_FIND_FILE_NAMES_INFO:
    2708             :                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    2709             :                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    2710             :                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    2711        6952 :                         break;
    2712          16 :                 case SMB_FIND_FILE_UNIX:
    2713             :                 case SMB_FIND_FILE_UNIX_INFO2:
    2714          16 :                         if (!lp_unix_extensions()) {
    2715           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2716           0 :                                 goto out;
    2717             :                         }
    2718          16 :                         break;
    2719           0 :                 default:
    2720           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    2721           0 :                         goto out;
    2722             :         }
    2723             : 
    2724        7100 :         if (req->posix_pathnames) {
    2725             :                 /* Always use filesystem for UNIX mtime query. */
    2726          38 :                 ask_sharemode = false;
    2727             :         }
    2728             : 
    2729        7100 :         if (req->posix_pathnames) {
    2730          76 :                 srvstr_get_path_posix(talloc_tos(),
    2731             :                                 params,
    2732          38 :                                 req->flags2,
    2733             :                                 &directory,
    2734          38 :                                 params+12,
    2735          38 :                                 total_params - 12,
    2736             :                                 STR_TERMINATE,
    2737             :                                 &ntstatus);
    2738             :         } else {
    2739       14124 :                 srvstr_get_path(talloc_tos(),
    2740             :                                 params,
    2741        7062 :                                 req->flags2,
    2742             :                                 &directory,
    2743        7062 :                                 params+12,
    2744        7062 :                                 total_params - 12,
    2745             :                                 STR_TERMINATE,
    2746             :                                 &ntstatus);
    2747             :         }
    2748        7100 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    2749           0 :                 reply_nterror(req, ntstatus);
    2750           0 :                 goto out;
    2751             :         }
    2752             : 
    2753        7100 :         if (backup_priv) {
    2754           0 :                 become_root();
    2755           0 :                 as_root = true;
    2756           0 :                 ntstatus = filename_convert_with_privilege(talloc_tos(),
    2757             :                                 conn,
    2758             :                                 req,
    2759             :                                 directory,
    2760             :                                 ucf_flags,
    2761             :                                 &smb_dname);
    2762             :         } else {
    2763        7100 :                 ntstatus = filename_convert(talloc_tos(), conn,
    2764             :                                     directory,
    2765             :                                     ucf_flags,
    2766             :                                     0,
    2767             :                                     &smb_dname);
    2768             :         }
    2769             : 
    2770        7100 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    2771          16 :                 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
    2772           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    2773             :                                         ERRSRV, ERRbadpath);
    2774           0 :                         goto out;
    2775             :                 }
    2776          16 :                 reply_nterror(req, ntstatus);
    2777          16 :                 goto out;
    2778             :         }
    2779             : 
    2780             :         /*
    2781             :          * The above call to filename_convert() is on the path from the client
    2782             :          * including the search mask. Until the code that chops of the search
    2783             :          * mask from the path below is moved before the call to
    2784             :          * filename_convert(), we close a possible pathref fsp to ensure
    2785             :          * SMB_VFS_CREATE_FILE() below will internally open a pathref fsp on the
    2786             :          * correct path.
    2787             :          */
    2788        7084 :         if (smb_dname->fsp != NULL) {
    2789         731 :                 ntstatus = fd_close(smb_dname->fsp);
    2790         731 :                 if (!NT_STATUS_IS_OK(ntstatus)) {
    2791           0 :                         reply_nterror(req, ntstatus);
    2792           0 :                         goto out;
    2793             :                 }
    2794             :                 /*
    2795             :                  * The pathref fsp link destructor will set smb_dname->fsp to
    2796             :                  * NULL. Turning this into an assert to give a hint at readers
    2797             :                  * of the code trying to understand the mechanics.
    2798             :                  */
    2799         731 :                 file_free(req, smb_dname->fsp);
    2800         731 :                 SMB_ASSERT(smb_dname->fsp == NULL);
    2801             :         }
    2802             : 
    2803        7084 :         mask = get_original_lcomp(talloc_tos(),
    2804             :                                 conn,
    2805             :                                 directory,
    2806             :                                 ucf_flags);
    2807        7084 :         if (mask == NULL) {
    2808           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2809           0 :                 goto out;
    2810             :         }
    2811             : 
    2812        7084 :         directory = smb_dname->base_name;
    2813             : 
    2814        7084 :         p = strrchr_m(directory,'/');
    2815        7084 :         if(p == NULL) {
    2816             :                 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
    2817        1109 :                 if((directory[0] == '.') && (directory[1] == '\0')) {
    2818           0 :                         mask = talloc_strdup(talloc_tos(),"*");
    2819           0 :                         if (!mask) {
    2820           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2821           0 :                                 goto out;
    2822             :                         }
    2823             :                 }
    2824             :         } else {
    2825        5975 :                 *p = 0;
    2826             :         }
    2827             : 
    2828        7084 :         if (p == NULL || p == directory) {
    2829        1109 :                 struct smb_filename *old_name = smb_dname;
    2830             : 
    2831             :                 /* Ensure we don't have a directory name of "". */
    2832        2218 :                 smb_dname = synthetic_smb_fname(talloc_tos(),
    2833             :                                                 ".",
    2834             :                                                 NULL,
    2835        1109 :                                                 &old_name->st,
    2836             :                                                 old_name->twrp,
    2837             :                                                 old_name->flags);
    2838        1109 :                 TALLOC_FREE(old_name);
    2839        1109 :                 if (smb_dname == NULL) {
    2840           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    2841           0 :                         goto out;
    2842             :                 }
    2843        1109 :                 directory = smb_dname->base_name;
    2844             :         }
    2845             : 
    2846        7084 :         DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
    2847             : 
    2848        7084 :         if (info_level == SMB_FIND_EA_LIST) {
    2849             :                 uint32_t ea_size;
    2850             : 
    2851           6 :                 if (total_data < 4) {
    2852           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2853           0 :                         goto out;
    2854             :                 }
    2855             : 
    2856           6 :                 ea_size = IVAL(pdata,0);
    2857           6 :                 if (ea_size != total_data) {
    2858           0 :                         DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
    2859             : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
    2860           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2861           0 :                         goto out;
    2862             :                 }
    2863             : 
    2864           6 :                 if (!lp_ea_support(SNUM(conn))) {
    2865           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    2866           0 :                         goto out;
    2867             :                 }
    2868             : 
    2869             :                 /* Pull out the list of names. */
    2870           6 :                 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
    2871           6 :                 if (!ea_list) {
    2872           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2873           0 :                         goto out;
    2874             :                 }
    2875             :         }
    2876             : 
    2877        7084 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    2878           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    2879           0 :                 goto out;
    2880             :         }
    2881             : 
    2882        7084 :         *ppdata = (char *)SMB_REALLOC(
    2883             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2884        7084 :         if(*ppdata == NULL ) {
    2885           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2886           0 :                 goto out;
    2887             :         }
    2888        7084 :         pdata = *ppdata;
    2889        7084 :         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    2890             :         /*
    2891             :          * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
    2892             :          * error.
    2893             :          */
    2894        7216 :         memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
    2895             :         /* Realloc the params space */
    2896        7084 :         *pparams = (char *)SMB_REALLOC(*pparams, 10);
    2897        7084 :         if (*pparams == NULL) {
    2898           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    2899           0 :                 goto out;
    2900             :         }
    2901        7084 :         params = *pparams;
    2902             : 
    2903             :         /*
    2904             :          * As we've cut off the last component from
    2905             :          * smb_fname we need to re-stat smb_dname
    2906             :          * so FILE_OPEN disposition knows the directory
    2907             :          * exists.
    2908             :          */
    2909        7084 :         ret = vfs_stat(conn, smb_dname);
    2910        7084 :         if (ret == -1) {
    2911           0 :                 ntstatus = map_nt_error_from_unix(errno);
    2912           0 :                 reply_nterror(req, ntstatus);
    2913           0 :                 goto out;
    2914             :         }
    2915             : 
    2916        7084 :         ntstatus = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
    2917        7084 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    2918           0 :                 reply_nterror(req, ntstatus);
    2919           0 :                 goto out;
    2920             :         }
    2921             : 
    2922             :         /*
    2923             :          * Open an fsp on this directory for the dptr.
    2924             :          */
    2925        7084 :         ntstatus = SMB_VFS_CREATE_FILE(
    2926             :                         conn, /* conn */
    2927             :                         req, /* req */
    2928             :                         smb_dname, /* dname */
    2929             :                         FILE_LIST_DIRECTORY, /* access_mask */
    2930             :                         FILE_SHARE_READ|
    2931             :                         FILE_SHARE_WRITE, /* share_access */
    2932             :                         FILE_OPEN, /* create_disposition*/
    2933             :                         FILE_DIRECTORY_FILE, /* create_options */
    2934             :                         FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
    2935             :                         NO_OPLOCK, /* oplock_request */
    2936             :                         NULL, /* lease */
    2937             :                         0, /* allocation_size */
    2938             :                         0, /* private_flags */
    2939             :                         NULL, /* sd */
    2940             :                         NULL, /* ea_list */
    2941             :                         &fsp, /* result */
    2942             :                         NULL, /* pinfo */
    2943             :                         NULL, /* in_context */
    2944             :                         NULL);/* out_context */
    2945             : 
    2946        7084 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    2947           0 :                 DBG_ERR("failed to open directory %s\n",
    2948             :                         smb_fname_str_dbg(smb_dname));
    2949           0 :                 reply_nterror(req, ntstatus);
    2950           0 :                 goto out;
    2951             :         }
    2952             : 
    2953             :         /* Save the wildcard match and attribs we are using on this directory -
    2954             :                 needed as lanman2 assumes these are being saved between calls */
    2955             : 
    2956       14168 :         ntstatus = dptr_create(conn,
    2957             :                                 req,
    2958             :                                 fsp, /* fsp */
    2959             :                                 False,
    2960             :                                 True,
    2961        7084 :                                 req->smbpid,
    2962             :                                 mask,
    2963             :                                 dirtype,
    2964        7084 :                                 &fsp->dptr);
    2965             : 
    2966        7084 :         if (!NT_STATUS_IS_OK(ntstatus)) {
    2967             :                 /*
    2968             :                  * Use NULL here for the first parameter (req)
    2969             :                  * as this is not a client visible handle so
    2970             :                  * can'tbe part of an SMB1 chain.
    2971             :                  */
    2972           0 :                 close_file(NULL, fsp, NORMAL_CLOSE);
    2973           0 :                 fsp = NULL;
    2974           0 :                 reply_nterror(req, ntstatus);
    2975           0 :                 goto out;
    2976             :         }
    2977             : 
    2978        7084 :         if (backup_priv) {
    2979             :                 /* Remember this in case we have
    2980             :                    to do a findnext. */
    2981           0 :                 dptr_set_priv(fsp->dptr);
    2982             :         }
    2983             : 
    2984        7084 :         dptr_num = dptr_dnum(fsp->dptr);
    2985        7084 :         DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
    2986             : 
    2987             :         /* We don't need to check for VOL here as this is returned by
    2988             :                 a different TRANS2 call. */
    2989             : 
    2990        7084 :         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
    2991             :                  directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
    2992       14168 :         if (in_list(directory,
    2993        7084 :                     lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
    2994        7084 :                         conn->case_sensitive)) {
    2995           0 :                 dont_descend = True;
    2996             :         }
    2997             : 
    2998        7084 :         p = pdata;
    2999        7084 :         space_remaining = max_data_bytes;
    3000        7084 :         out_of_space = False;
    3001             : 
    3002       44675 :         for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
    3003       37591 :                 bool got_exact_match = False;
    3004             : 
    3005             :                 /* this is a heuristic to avoid seeking the dirptr except when
    3006             :                         absolutely necessary. It allows for a filename of about 40 chars */
    3007       37591 :                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
    3008           0 :                         out_of_space = True;
    3009           0 :                         finished = False;
    3010             :                 } else {
    3011      112773 :                         ntstatus = get_lanman2_dir_entry(talloc_tos(),
    3012             :                                         conn,
    3013       37591 :                                         fsp->dptr,
    3014       37591 :                                         req->flags2,
    3015             :                                         mask,dirtype,info_level,
    3016             :                                         requires_resume_key,dont_descend,
    3017             :                                         ask_sharemode,
    3018             :                                         &p,pdata,data_end,
    3019             :                                         space_remaining,
    3020             :                                         &got_exact_match,
    3021             :                                         &last_entry_off, ea_list);
    3022       37591 :                         if (NT_STATUS_EQUAL(ntstatus,
    3023             :                                         NT_STATUS_ILLEGAL_CHARACTER)) {
    3024             :                                 /*
    3025             :                                  * Bad character conversion on name. Ignore this
    3026             :                                  * entry.
    3027             :                                  */
    3028           6 :                                 continue;
    3029             :                         }
    3030       37585 :                         if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
    3031           0 :                                 out_of_space = true;
    3032             :                         } else {
    3033       37585 :                                 finished = !NT_STATUS_IS_OK(ntstatus);
    3034             :                         }
    3035             :                 }
    3036             : 
    3037       37585 :                 if (!finished && !out_of_space)
    3038       31346 :                         numentries++;
    3039             : 
    3040             :                 /*
    3041             :                  * As an optimisation if we know we aren't looking
    3042             :                  * for a wildcard name (ie. the name matches the wildcard exactly)
    3043             :                  * then we can finish on any (first) match.
    3044             :                  * This speeds up large directory searches. JRA.
    3045             :                  */
    3046             : 
    3047       37585 :                 if(got_exact_match)
    3048         727 :                         finished = True;
    3049             : 
    3050             :                 /* Ensure space_remaining never goes -ve. */
    3051       37585 :                 if (PTR_DIFF(p,pdata) > max_data_bytes) {
    3052           0 :                         space_remaining = 0;
    3053           0 :                         out_of_space = true;
    3054             :                 } else {
    3055       37585 :                         space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
    3056             :                 }
    3057             :         }
    3058             : 
    3059             :         /* Check if we can close the dirptr */
    3060        7084 :         if(close_after_first || (finished && close_if_end)) {
    3061        6966 :                 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
    3062        6966 :                 dptr_num = -1;
    3063        6966 :                 close_file(NULL, fsp, NORMAL_CLOSE);
    3064        6966 :                 fsp = NULL;
    3065             :         }
    3066             : 
    3067             :         /*
    3068             :          * If there are no matching entries we must return ERRDOS/ERRbadfile -
    3069             :          * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
    3070             :          * the protocol level is less than NT1. Tested with smbclient. JRA.
    3071             :          * This should fix the OS/2 client bug #2335.
    3072             :          */
    3073             : 
    3074        7084 :         if(numentries == 0) {
    3075         134 :                 dptr_num = -1;
    3076             :                 /*
    3077             :                  * We may have already closed the file in the
    3078             :                  * close_after_first or finished case above.
    3079             :                  */
    3080         134 :                 if (fsp != NULL) {
    3081           0 :                         close_file(NULL, fsp, NORMAL_CLOSE);
    3082           0 :                         fsp = NULL;
    3083             :                 }
    3084         134 :                 if (get_Protocol() < PROTOCOL_NT1) {
    3085           0 :                         reply_force_doserror(req, ERRDOS, ERRnofiles);
    3086           0 :                         goto out;
    3087             :                 } else {
    3088         134 :                         reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
    3089             :                                         ERRDOS, ERRbadfile);
    3090         134 :                         goto out;
    3091             :                 }
    3092             :         }
    3093             : 
    3094             :         /* At this point pdata points to numentries directory entries. */
    3095             : 
    3096             :         /* Set up the return parameter block */
    3097        6950 :         SSVAL(params,0,dptr_num);
    3098        6950 :         SSVAL(params,2,numentries);
    3099        6950 :         SSVAL(params,4,finished);
    3100        6950 :         SSVAL(params,6,0); /* Never an EA error */
    3101        6950 :         SSVAL(params,8,last_entry_off);
    3102             : 
    3103        6950 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
    3104             :                             max_data_bytes);
    3105             : 
    3106        6950 :         if ((! *directory) && dptr_path(sconn, dptr_num)) {
    3107           0 :                 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
    3108           0 :                 if (!directory) {
    3109           0 :                         reply_nterror(req, NT_STATUS_NO_MEMORY);
    3110             :                 }
    3111             :         }
    3112             : 
    3113        6950 :         DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
    3114             :                 smb_fn_name(req->cmd),
    3115             :                 mask, directory, dirtype, numentries ) );
    3116             : 
    3117             :         /*
    3118             :          * Force a name mangle here to ensure that the
    3119             :          * mask as an 8.3 name is top of the mangled cache.
    3120             :          * The reasons for this are subtle. Don't remove
    3121             :          * this code unless you know what you are doing
    3122             :          * (see PR#13758). JRA.
    3123             :          */
    3124             : 
    3125        6950 :         if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
    3126             :                 char mangled_name[13];
    3127        6812 :                 name_to_8_3(mask, mangled_name, True, conn->params);
    3128             :         }
    3129        7238 :  out:
    3130             : 
    3131        7100 :         if (as_root) {
    3132           0 :                 unbecome_root();
    3133             :         }
    3134             : 
    3135        7100 :         TALLOC_FREE(smb_dname);
    3136        7100 :         return;
    3137             : }
    3138             : 
    3139             : /****************************************************************************
    3140             :  Reply to a TRANS2_FINDNEXT.
    3141             : ****************************************************************************/
    3142             : 
    3143        1708 : static void call_trans2findnext(connection_struct *conn,
    3144             :                                 struct smb_request *req,
    3145             :                                 char **pparams, int total_params,
    3146             :                                 char **ppdata, int total_data,
    3147             :                                 unsigned int max_data_bytes)
    3148             : {
    3149             :         /* We must be careful here that we don't return more than the
    3150             :                 allowed number of data bytes. If this means returning fewer than
    3151             :                 maxentries then so be it. We assume that the redirector has
    3152             :                 enough room for the fixed number of parameter bytes it has
    3153             :                 requested. */
    3154        1708 :         char *params = *pparams;
    3155        1708 :         char *pdata = *ppdata;
    3156             :         char *data_end;
    3157             :         int dptr_num;
    3158             :         int maxentries;
    3159             :         uint16_t info_level;
    3160             :         uint32_t resume_key;
    3161             :         uint16_t findnext_flags;
    3162             :         bool close_after_request;
    3163             :         bool close_if_end;
    3164             :         bool requires_resume_key;
    3165             :         bool continue_bit;
    3166        1708 :         char *resume_name = NULL;
    3167        1708 :         const char *mask = NULL;
    3168        1708 :         const char *directory = NULL;
    3169        1708 :         char *p = NULL;
    3170             :         uint16_t dirtype;
    3171        1708 :         int numentries = 0;
    3172        1708 :         int i, last_entry_off=0;
    3173        1708 :         bool finished = False;
    3174        1708 :         bool dont_descend = False;
    3175        1708 :         bool out_of_space = False;
    3176             :         int space_remaining;
    3177        1708 :         struct ea_list *ea_list = NULL;
    3178        1708 :         NTSTATUS ntstatus = NT_STATUS_OK;
    3179        1708 :         bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
    3180        1708 :         TALLOC_CTX *ctx = talloc_tos();
    3181        1708 :         struct smbd_server_connection *sconn = req->sconn;
    3182        1708 :         bool backup_priv = false; 
    3183        1708 :         bool as_root = false;
    3184        1708 :         files_struct *fsp = NULL;
    3185        1708 :         const struct loadparm_substitution *lp_sub =
    3186             :                 loadparm_s3_global_substitution();
    3187             : 
    3188        1708 :         if (total_params < 13) {
    3189           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3190           0 :                 return;
    3191             :         }
    3192             : 
    3193        1708 :         dptr_num = SVAL(params,0);
    3194        1708 :         maxentries = SVAL(params,2);
    3195        1708 :         info_level = SVAL(params,4);
    3196        1708 :         resume_key = IVAL(params,6);
    3197        1708 :         findnext_flags = SVAL(params,10);
    3198        1708 :         close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
    3199        1708 :         close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
    3200        1708 :         requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
    3201        1708 :         continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
    3202             : 
    3203        1708 :         if (!continue_bit) {
    3204             :                 /* We only need resume_name if continue_bit is zero. */
    3205        1408 :                 if (req->posix_pathnames) {
    3206           0 :                         srvstr_get_path_posix(ctx,
    3207             :                                 params,
    3208           0 :                                 req->flags2,
    3209             :                                 &resume_name,
    3210           0 :                                 params+12,
    3211           0 :                                 total_params - 12,
    3212             :                                 STR_TERMINATE,
    3213             :                                 &ntstatus);
    3214             :                 } else {
    3215        2816 :                         srvstr_get_path(ctx,
    3216             :                                 params,
    3217        1408 :                                 req->flags2,
    3218             :                                 &resume_name,
    3219        1408 :                                 params+12,
    3220        1408 :                                 total_params - 12,
    3221             :                                 STR_TERMINATE,
    3222             :                                 &ntstatus);
    3223             :                 }
    3224        1408 :                 if (!NT_STATUS_IS_OK(ntstatus)) {
    3225             :                         /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
    3226             :                            complain (it thinks we're asking for the directory above the shared
    3227             :                            path or an invalid name). Catch this as the resume name is only compared, never used in
    3228             :                            a file access. JRA. */
    3229           0 :                         srvstr_pull_talloc(ctx, params, req->flags2,
    3230             :                                 &resume_name, params+12,
    3231             :                                 total_params - 12,
    3232             :                                 STR_TERMINATE);
    3233             : 
    3234           0 :                         if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
    3235           0 :                                 reply_nterror(req, ntstatus);
    3236           0 :                                 return;
    3237             :                         }
    3238             :                 }
    3239             :         }
    3240             : 
    3241        1708 :         DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
    3242             : close_after_request=%d, close_if_end = %d requires_resume_key = %d \
    3243             : resume_key = %d resume name = %s continue=%d level = %d\n",
    3244             :                 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end, 
    3245             :                 requires_resume_key, resume_key,
    3246             :                 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
    3247             : 
    3248        1708 :         if (!maxentries) {
    3249             :                 /* W2K3 seems to treat zero as 1. */
    3250           0 :                 maxentries = 1;
    3251             :         }
    3252             : 
    3253        1708 :         switch (info_level) {
    3254        1708 :                 case SMB_FIND_INFO_STANDARD:
    3255             :                 case SMB_FIND_EA_SIZE:
    3256             :                 case SMB_FIND_EA_LIST:
    3257             :                 case SMB_FIND_FILE_DIRECTORY_INFO:
    3258             :                 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    3259             :                 case SMB_FIND_FILE_NAMES_INFO:
    3260             :                 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    3261             :                 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    3262             :                 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    3263        1708 :                         break;
    3264           0 :                 case SMB_FIND_FILE_UNIX:
    3265             :                 case SMB_FIND_FILE_UNIX_INFO2:
    3266             :                         /* Always use filesystem for UNIX mtime query. */
    3267           0 :                         ask_sharemode = false;
    3268           0 :                         if (!lp_unix_extensions()) {
    3269           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    3270           0 :                                 return;
    3271             :                         }
    3272           0 :                         break;
    3273           0 :                 default:
    3274           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    3275           0 :                         return;
    3276             :         }
    3277             : 
    3278        1708 :         if (info_level == SMB_FIND_EA_LIST) {
    3279             :                 uint32_t ea_size;
    3280             : 
    3281           6 :                 if (total_data < 4) {
    3282           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3283           0 :                         return;
    3284             :                 }
    3285             : 
    3286           6 :                 ea_size = IVAL(pdata,0);
    3287           6 :                 if (ea_size != total_data) {
    3288           0 :                         DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
    3289             : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
    3290           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3291           0 :                         return;
    3292             :                 }
    3293             : 
    3294           6 :                 if (!lp_ea_support(SNUM(conn))) {
    3295           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    3296           0 :                         return;
    3297             :                 }
    3298             : 
    3299             :                 /* Pull out the list of names. */
    3300           6 :                 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
    3301           6 :                 if (!ea_list) {
    3302           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3303           0 :                         return;
    3304             :                 }
    3305             :         }
    3306             : 
    3307        1708 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    3308           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    3309           0 :                 return;
    3310             :         }
    3311             : 
    3312        1708 :         *ppdata = (char *)SMB_REALLOC(
    3313             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    3314        1708 :         if(*ppdata == NULL) {
    3315           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    3316           0 :                 return;
    3317             :         }
    3318             : 
    3319        1708 :         pdata = *ppdata;
    3320        1708 :         data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    3321             : 
    3322             :         /*
    3323             :          * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
    3324             :          * error.
    3325             :          */
    3326        1708 :         memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
    3327             :         /* Realloc the params space */
    3328        1708 :         *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
    3329        1708 :         if(*pparams == NULL ) {
    3330           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    3331           0 :                 return;
    3332             :         }
    3333             : 
    3334        1708 :         params = *pparams;
    3335             : 
    3336             :         /* Check that the dptr is valid */
    3337        1708 :         fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
    3338        1708 :         if (fsp == NULL) {
    3339           0 :                 reply_nterror(req, STATUS_NO_MORE_FILES);
    3340           0 :                 return;
    3341             :         }
    3342             : 
    3343        1708 :         directory = dptr_path(sconn, dptr_num);
    3344             : 
    3345             :         /* Get the wildcard mask from the dptr */
    3346        1708 :         if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
    3347           0 :                 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
    3348           0 :                 reply_nterror(req, STATUS_NO_MORE_FILES);
    3349           0 :                 return;
    3350             :         }
    3351             : 
    3352             :         /* Get the attr mask from the dptr */
    3353        1708 :         dirtype = dptr_attr(sconn, dptr_num);
    3354             : 
    3355        1708 :         backup_priv = dptr_get_priv(fsp->dptr);
    3356             : 
    3357        1708 :         DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
    3358             :                 "backup_priv = %d\n",
    3359             :                 dptr_num, mask, dirtype,
    3360             :                 (long)fsp->dptr,
    3361             :                 dptr_TellDir(fsp->dptr),
    3362             :                 (int)backup_priv));
    3363             : 
    3364             :         /* We don't need to check for VOL here as this is returned by
    3365             :                 a different TRANS2 call. */
    3366             : 
    3367        1708 :         DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
    3368             :                  directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
    3369        1708 :         if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
    3370           0 :                 dont_descend = True;
    3371             : 
    3372        1708 :         p = pdata;
    3373        1708 :         space_remaining = max_data_bytes;
    3374        1708 :         out_of_space = False;
    3375             : 
    3376        1708 :         if (backup_priv) {
    3377           0 :                 become_root();
    3378           0 :                 as_root = true;
    3379             :         }
    3380             : 
    3381             :         /*
    3382             :          * Seek to the correct position. We no longer use the resume key but
    3383             :          * depend on the last file name instead.
    3384             :          */
    3385             : 
    3386        1708 :         if(!continue_bit && resume_name && *resume_name) {
    3387             :                 SMB_STRUCT_STAT st;
    3388             : 
    3389        1408 :                 long current_pos = 0;
    3390             :                 /*
    3391             :                  * Remember, name_to_8_3 is called by
    3392             :                  * get_lanman2_dir_entry(), so the resume name
    3393             :                  * could be mangled. Ensure we check the unmangled name.
    3394             :                  */
    3395             : 
    3396        1408 :                 if (mangle_is_mangled(resume_name, conn->params)) {
    3397           0 :                         char *new_resume_name = NULL;
    3398           0 :                         mangle_lookup_name_from_8_3(ctx,
    3399             :                                                 resume_name,
    3400             :                                                 &new_resume_name,
    3401           0 :                                                 conn->params);
    3402           0 :                         if (new_resume_name) {
    3403           0 :                                 resume_name = new_resume_name;
    3404             :                         }
    3405             :                 }
    3406             : 
    3407             :                 /*
    3408             :                  * Fix for NT redirector problem triggered by resume key indexes
    3409             :                  * changing between directory scans. We now return a resume key of 0
    3410             :                  * and instead look for the filename to continue from (also given
    3411             :                  * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
    3412             :                  * findfirst/findnext (as is usual) then the directory pointer
    3413             :                  * should already be at the correct place.
    3414             :                  */
    3415             : 
    3416        1408 :                 finished = !dptr_SearchDir(fsp->dptr, resume_name, &current_pos, &st);
    3417             :         } /* end if resume_name && !continue_bit */
    3418             : 
    3419      155262 :         for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
    3420      153554 :                 bool got_exact_match = False;
    3421             : 
    3422             :                 /* this is a heuristic to avoid seeking the fsp->dptr except when
    3423             :                         absolutely necessary. It allows for a filename of about 40 chars */
    3424      153554 :                 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
    3425           0 :                         out_of_space = True;
    3426           0 :                         finished = False;
    3427             :                 } else {
    3428      307108 :                         ntstatus = get_lanman2_dir_entry(ctx,
    3429             :                                                 conn,
    3430             :                                                 fsp->dptr,
    3431      153554 :                                                 req->flags2,
    3432             :                                                 mask,dirtype,info_level,
    3433             :                                                 requires_resume_key,dont_descend,
    3434             :                                                 ask_sharemode,
    3435             :                                                 &p,pdata,data_end,
    3436             :                                                 space_remaining,
    3437             :                                                 &got_exact_match,
    3438             :                                                 &last_entry_off, ea_list);
    3439      153554 :                         if (NT_STATUS_EQUAL(ntstatus,
    3440             :                                         NT_STATUS_ILLEGAL_CHARACTER)) {
    3441             :                                 /*
    3442             :                                  * Bad character conversion on name. Ignore this
    3443             :                                  * entry.
    3444             :                                  */
    3445           0 :                                 continue;
    3446             :                         }
    3447      153554 :                         if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
    3448           0 :                                 out_of_space = true;
    3449             :                         } else {
    3450      153554 :                                 finished = !NT_STATUS_IS_OK(ntstatus);
    3451             :                         }
    3452             :                 }
    3453             : 
    3454      153554 :                 if (!finished && !out_of_space)
    3455      153298 :                         numentries++;
    3456             : 
    3457             :                 /*
    3458             :                  * As an optimisation if we know we aren't looking
    3459             :                  * for a wildcard name (ie. the name matches the wildcard exactly)
    3460             :                  * then we can finish on any (first) match.
    3461             :                  * This speeds up large directory searches. JRA.
    3462             :                  */
    3463             : 
    3464      153554 :                 if(got_exact_match)
    3465           0 :                         finished = True;
    3466             : 
    3467      153554 :                 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
    3468             :         }
    3469             : 
    3470        1708 :         DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
    3471             :                 smb_fn_name(req->cmd),
    3472             :                 mask, directory, dirtype, numentries ) );
    3473             : 
    3474             :         /* Check if we can close the fsp->dptr */
    3475        1708 :         if(close_after_request || (finished && close_if_end)) {
    3476          94 :                 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
    3477          94 :                 dptr_num = -1;
    3478          94 :                 close_file(NULL, fsp, NORMAL_CLOSE);
    3479          94 :                 fsp = NULL;
    3480             :         }
    3481             : 
    3482        1708 :         if (as_root) {
    3483           0 :                 unbecome_root();
    3484             :         }
    3485             : 
    3486             :         /* Set up the return parameter block */
    3487        1708 :         SSVAL(params,0,numentries);
    3488        1708 :         SSVAL(params,2,finished);
    3489        1708 :         SSVAL(params,4,0); /* Never an EA error */
    3490        1708 :         SSVAL(params,6,last_entry_off);
    3491             : 
    3492        1708 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
    3493             :                             max_data_bytes);
    3494             : 
    3495        1708 :         return;
    3496             : }
    3497             : 
    3498         110 : unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
    3499             : {
    3500         110 :         const struct loadparm_substitution *lp_sub =
    3501             :                 loadparm_s3_global_substitution();
    3502             : 
    3503         110 :         E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
    3504         110 :         return objid;
    3505             : }
    3506             : 
    3507          40 : static void samba_extended_info_version(struct smb_extended_info *extended_info)
    3508             : {
    3509          40 :         SMB_ASSERT(extended_info != NULL);
    3510             : 
    3511          40 :         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
    3512          40 :         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
    3513             :                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
    3514             :                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
    3515             : #ifdef SAMBA_VERSION_REVISION
    3516             :         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
    3517             : #endif
    3518          40 :         extended_info->samba_subversion = 0;
    3519             : #ifdef SAMBA_VERSION_RC_RELEASE
    3520             :         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
    3521             : #else
    3522             : #ifdef SAMBA_VERSION_PRE_RELEASE
    3523          40 :         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
    3524             : #endif
    3525             : #endif
    3526             : #ifdef SAMBA_VERSION_VENDOR_PATCH
    3527             :         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
    3528             : #endif
    3529          40 :         extended_info->samba_gitcommitdate = 0;
    3530             : #ifdef SAMBA_VERSION_COMMIT_TIME
    3531             :         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
    3532             : #endif
    3533             : 
    3534          40 :         memset(extended_info->samba_version_string, 0,
    3535             :                sizeof(extended_info->samba_version_string));
    3536             : 
    3537          40 :         snprintf (extended_info->samba_version_string,
    3538             :                   sizeof(extended_info->samba_version_string),
    3539             :                   "%s", samba_version_string());
    3540          40 : }
    3541             : 
    3542        2683 : NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
    3543             :                          connection_struct *conn,
    3544             :                          TALLOC_CTX *mem_ctx,
    3545             :                          uint16_t info_level,
    3546             :                          uint16_t flags2,
    3547             :                          unsigned int max_data_bytes,
    3548             :                          size_t *fixed_portion,
    3549             :                          struct smb_filename *fname,
    3550             :                          char **ppdata,
    3551             :                          int *ret_data_len)
    3552             : {
    3553        2683 :         const struct loadparm_substitution *lp_sub =
    3554             :                 loadparm_s3_global_substitution();
    3555             :         char *pdata, *end_data;
    3556        2683 :         int data_len = 0;
    3557        2683 :         size_t len = 0;
    3558        2683 :         const char *vname = volume_label(talloc_tos(), SNUM(conn));
    3559        2683 :         int snum = SNUM(conn);
    3560        2683 :         const char *fstype = lp_fstype(SNUM(conn));
    3561        2683 :         const char *filename = NULL;
    3562        2683 :         const uint64_t bytes_per_sector = 512;
    3563        2683 :         uint32_t additional_flags = 0;
    3564             :         struct smb_filename smb_fname;
    3565             :         SMB_STRUCT_STAT st;
    3566        2683 :         NTSTATUS status = NT_STATUS_OK;
    3567             :         uint64_t df_ret;
    3568             : 
    3569        2683 :         if (fname == NULL || fname->base_name == NULL) {
    3570         918 :                 filename = ".";
    3571             :         } else {
    3572        1765 :                 filename = fname->base_name;
    3573             :         }
    3574             : 
    3575        2683 :         if (IS_IPC(conn)) {
    3576         190 :                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
    3577           0 :                         DEBUG(0,("smbd_do_qfsinfo: not an allowed "
    3578             :                                 "info level (0x%x) on IPC$.\n",
    3579             :                                 (unsigned int)info_level));
    3580           0 :                         return NT_STATUS_ACCESS_DENIED;
    3581             :                 }
    3582             :         }
    3583             : 
    3584        2683 :         DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
    3585             : 
    3586        2683 :         smb_fname = (struct smb_filename) {
    3587             :                 .base_name = discard_const_p(char, filename),
    3588        2683 :                 .flags = fname ? fname->flags : 0,
    3589        2683 :                 .twrp = fname ? fname->twrp : 0,
    3590             :         };
    3591             : 
    3592        2683 :         if(info_level != SMB_FS_QUOTA_INFORMATION
    3593        2679 :            && SMB_VFS_STAT(conn, &smb_fname) != 0) {
    3594           0 :                 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
    3595           0 :                 return map_nt_error_from_unix(errno);
    3596             :         }
    3597             : 
    3598        2683 :         st = smb_fname.st;
    3599             : 
    3600        2683 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    3601           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3602             :         }
    3603             : 
    3604        2683 :         *ppdata = (char *)SMB_REALLOC(
    3605             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    3606        2683 :         if (*ppdata == NULL) {
    3607           0 :                 return NT_STATUS_NO_MEMORY;
    3608             :         }
    3609             : 
    3610        2683 :         pdata = *ppdata;
    3611        2683 :         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    3612        2683 :         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    3613             : 
    3614        2683 :         *fixed_portion = 0;
    3615             : 
    3616        2683 :         switch (info_level) {
    3617           0 :                 case SMB_INFO_ALLOCATION:
    3618             :                 {
    3619             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    3620           0 :                         data_len = 18;
    3621           0 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    3622             :                                                 &dfree, &dsize);
    3623           0 :                         if (df_ret == (uint64_t)-1) {
    3624           0 :                                 return map_nt_error_from_unix(errno);
    3625             :                         }
    3626             : 
    3627           0 :                         block_size = lp_block_size(snum);
    3628           0 :                         if (bsize < block_size) {
    3629           0 :                                 uint64_t factor = block_size/bsize;
    3630           0 :                                 bsize = block_size;
    3631           0 :                                 dsize /= factor;
    3632           0 :                                 dfree /= factor;
    3633             :                         }
    3634           0 :                         if (bsize > block_size) {
    3635           0 :                                 uint64_t factor = bsize/block_size;
    3636           0 :                                 bsize = block_size;
    3637           0 :                                 dsize *= factor;
    3638           0 :                                 dfree *= factor;
    3639             :                         }
    3640           0 :                         sectors_per_unit = bsize/bytes_per_sector;
    3641             : 
    3642           0 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
    3643             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
    3644             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    3645             : 
    3646             :                         /*
    3647             :                          * For large drives, return max values and not modulo.
    3648             :                          */
    3649           0 :                         dsize = MIN(dsize, UINT32_MAX);
    3650           0 :                         dfree = MIN(dfree, UINT32_MAX);
    3651             : 
    3652           0 :                         SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
    3653           0 :                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
    3654           0 :                         SIVAL(pdata,l1_cUnit,dsize);
    3655           0 :                         SIVAL(pdata,l1_cUnitAvail,dfree);
    3656           0 :                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
    3657           0 :                         break;
    3658             :                 }
    3659             : 
    3660           0 :                 case SMB_INFO_VOLUME:
    3661             :                         /* Return volume name */
    3662             :                         /* 
    3663             :                          * Add volume serial number - hash of a combination of
    3664             :                          * the called hostname and the service name.
    3665             :                          */
    3666           0 :                         SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
    3667             :                         /*
    3668             :                          * Win2k3 and previous mess this up by sending a name length
    3669             :                          * one byte short. I believe only older clients (OS/2 Win9x) use
    3670             :                          * this call so try fixing this by adding a terminating null to
    3671             :                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
    3672             :                          */
    3673           0 :                         status = srvstr_push(
    3674             :                                 pdata, flags2,
    3675             :                                 pdata+l2_vol_szVolLabel, vname,
    3676             :                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
    3677             :                                 STR_NOALIGN|STR_TERMINATE, &len);
    3678           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3679           0 :                                 return status;
    3680             :                         }
    3681           0 :                         SCVAL(pdata,l2_vol_cch,len);
    3682           0 :                         data_len = l2_vol_szVolLabel + len;
    3683           0 :                         DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
    3684             :                                  (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
    3685             :                                  (unsigned)len, vname));
    3686           0 :                         break;
    3687             : 
    3688         422 :                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
    3689             :                 case SMB_FS_ATTRIBUTE_INFORMATION:
    3690             : 
    3691         422 :                         additional_flags = 0;
    3692             : #if defined(HAVE_SYS_QUOTAS)
    3693         422 :                         additional_flags |= FILE_VOLUME_QUOTAS;
    3694             : #endif
    3695             : 
    3696         422 :                         if(lp_nt_acl_support(SNUM(conn))) {
    3697         422 :                                 additional_flags |= FILE_PERSISTENT_ACLS;
    3698             :                         }
    3699             : 
    3700             :                         /* Capabilities are filled in at connection time through STATVFS call */
    3701         422 :                         additional_flags |= conn->fs_capabilities;
    3702         422 :                         additional_flags |= lp_parm_int(conn->params->service,
    3703             :                                                         "share", "fake_fscaps",
    3704             :                                                         0);
    3705             : 
    3706         422 :                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
    3707             :                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
    3708             :                                 additional_flags); /* FS ATTRIBUTES */
    3709             : 
    3710         422 :                         SIVAL(pdata,4,255); /* Max filename component length */
    3711             :                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
    3712             :                                 and will think we can't do long filenames */
    3713         422 :                         status = srvstr_push(pdata, flags2, pdata+12, fstype,
    3714             :                                           PTR_DIFF(end_data, pdata+12),
    3715             :                                           STR_UNICODE, &len);
    3716         422 :                         if (!NT_STATUS_IS_OK(status)) {
    3717           0 :                                 return status;
    3718             :                         }
    3719         422 :                         SIVAL(pdata,8,len);
    3720         422 :                         data_len = 12 + len;
    3721         422 :                         if (max_data_bytes >= 16 && data_len > max_data_bytes) {
    3722             :                                 /* the client only requested a portion of the
    3723             :                                    file system name */
    3724          16 :                                 data_len = max_data_bytes;
    3725          16 :                                 status = STATUS_BUFFER_OVERFLOW;
    3726             :                         }
    3727         422 :                         *fixed_portion = 16;
    3728         422 :                         break;
    3729             : 
    3730           0 :                 case SMB_QUERY_FS_LABEL_INFO:
    3731             :                 case SMB_FS_LABEL_INFORMATION:
    3732           0 :                         status = srvstr_push(pdata, flags2, pdata+4, vname,
    3733             :                                           PTR_DIFF(end_data, pdata+4), 0, &len);
    3734           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3735           0 :                                 return status;
    3736             :                         }
    3737           0 :                         data_len = 4 + len;
    3738           0 :                         SIVAL(pdata,0,len);
    3739           0 :                         break;
    3740             : 
    3741         128 :                 case SMB_QUERY_FS_VOLUME_INFO:      
    3742             :                 case SMB_FS_VOLUME_INFORMATION:
    3743             : 
    3744             :                         /* 
    3745             :                          * Add volume serial number - hash of a combination of
    3746             :                          * the called hostname and the service name.
    3747             :                          */
    3748         128 :                         SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
    3749             :                                 (str_checksum(get_local_machine_name())<<16));
    3750             : 
    3751             :                         /* Max label len is 32 characters. */
    3752         128 :                         status = srvstr_push(pdata, flags2, pdata+18, vname,
    3753             :                                           PTR_DIFF(end_data, pdata+18),
    3754             :                                           STR_UNICODE, &len);
    3755         128 :                         if (!NT_STATUS_IS_OK(status)) {
    3756           0 :                                 return status;
    3757             :                         }
    3758         128 :                         SIVAL(pdata,12,len);
    3759         128 :                         data_len = 18+len;
    3760             : 
    3761         128 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
    3762             :                                 (int)strlen(vname),vname,
    3763             :                                 lp_servicename(talloc_tos(), lp_sub, snum)));
    3764         128 :                         if (max_data_bytes >= 24 && data_len > max_data_bytes) {
    3765             :                                 /* the client only requested a portion of the
    3766             :                                    volume label */
    3767           0 :                                 data_len = max_data_bytes;
    3768           0 :                                 status = STATUS_BUFFER_OVERFLOW;
    3769             :                         }
    3770         128 :                         *fixed_portion = 24;
    3771         128 :                         break;
    3772             : 
    3773        1049 :                 case SMB_QUERY_FS_SIZE_INFO:
    3774             :                 case SMB_FS_SIZE_INFORMATION:
    3775             :                 {
    3776             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    3777        1049 :                         data_len = 24;
    3778        1049 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    3779             :                                                 &dfree, &dsize);
    3780        1049 :                         if (df_ret == (uint64_t)-1) {
    3781           0 :                                 return map_nt_error_from_unix(errno);
    3782             :                         }
    3783        1049 :                         block_size = lp_block_size(snum);
    3784        1049 :                         if (bsize < block_size) {
    3785        1003 :                                 uint64_t factor = block_size/bsize;
    3786        1003 :                                 bsize = block_size;
    3787        1003 :                                 dsize /= factor;
    3788        1003 :                                 dfree /= factor;
    3789             :                         }
    3790        1049 :                         if (bsize > block_size) {
    3791          42 :                                 uint64_t factor = bsize/block_size;
    3792          42 :                                 bsize = block_size;
    3793          42 :                                 dsize *= factor;
    3794          42 :                                 dfree *= factor;
    3795             :                         }
    3796        1049 :                         sectors_per_unit = bsize/bytes_per_sector;
    3797        1049 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    3798             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    3799             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    3800        1049 :                         SBIG_UINT(pdata,0,dsize);
    3801        1049 :                         SBIG_UINT(pdata,8,dfree);
    3802        1049 :                         SIVAL(pdata,16,sectors_per_unit);
    3803        1049 :                         SIVAL(pdata,20,bytes_per_sector);
    3804        1049 :                         *fixed_portion = 24;
    3805        1049 :                         break;
    3806             :                 }
    3807             : 
    3808         398 :                 case SMB_FS_FULL_SIZE_INFORMATION:
    3809             :                 {
    3810             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    3811         398 :                         data_len = 32;
    3812         398 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    3813             :                                                 &dfree, &dsize);
    3814         398 :                         if (df_ret == (uint64_t)-1) {
    3815           0 :                                 return map_nt_error_from_unix(errno);
    3816             :                         }
    3817         398 :                         block_size = lp_block_size(snum);
    3818         398 :                         if (bsize < block_size) {
    3819         394 :                                 uint64_t factor = block_size/bsize;
    3820         394 :                                 bsize = block_size;
    3821         394 :                                 dsize /= factor;
    3822         394 :                                 dfree /= factor;
    3823             :                         }
    3824         398 :                         if (bsize > block_size) {
    3825           4 :                                 uint64_t factor = bsize/block_size;
    3826           4 :                                 bsize = block_size;
    3827           4 :                                 dsize *= factor;
    3828           4 :                                 dfree *= factor;
    3829             :                         }
    3830         398 :                         sectors_per_unit = bsize/bytes_per_sector;
    3831         398 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    3832             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    3833             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    3834         398 :                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
    3835         398 :                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
    3836         398 :                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
    3837         398 :                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
    3838         398 :                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
    3839         398 :                         *fixed_portion = 32;
    3840         398 :                         break;
    3841             :                 }
    3842             : 
    3843          44 :                 case SMB_QUERY_FS_DEVICE_INFO:
    3844             :                 case SMB_FS_DEVICE_INFORMATION:
    3845             :                 {
    3846          44 :                         uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
    3847             : 
    3848          44 :                         if (!CAN_WRITE(conn)) {
    3849           0 :                                 characteristics |= FILE_READ_ONLY_DEVICE;
    3850             :                         }
    3851          44 :                         data_len = 8;
    3852          44 :                         SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
    3853          44 :                         SIVAL(pdata,4,characteristics);
    3854          44 :                         *fixed_portion = 8;
    3855          44 :                         break;
    3856             :                 }
    3857             : 
    3858             : #ifdef HAVE_SYS_QUOTAS
    3859           4 :                 case SMB_FS_QUOTA_INFORMATION:
    3860             :                 /* 
    3861             :                  * what we have to send --metze:
    3862             :                  *
    3863             :                  * Unknown1:            24 NULL bytes
    3864             :                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
    3865             :                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
    3866             :                  * Quota Flags:         2 byte :
    3867             :                  * Unknown3:            6 NULL bytes
    3868             :                  *
    3869             :                  * 48 bytes total
    3870             :                  * 
    3871             :                  * details for Quota Flags:
    3872             :                  * 
    3873             :                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
    3874             :                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
    3875             :                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
    3876             :                  * 0x0001 Enable Quotas: enable quota for this fs
    3877             :                  *
    3878             :                  */
    3879             :                 {
    3880             :                         /* we need to fake up a fsp here,
    3881             :                          * because its not send in this call
    3882             :                          */
    3883             :                         files_struct fsp;
    3884             :                         SMB_NTQUOTA_STRUCT quotas;
    3885             : 
    3886           4 :                         ZERO_STRUCT(fsp);
    3887           4 :                         ZERO_STRUCT(quotas);
    3888             : 
    3889           4 :                         fsp.conn = conn;
    3890           4 :                         fsp.fnum = FNUM_FIELD_INVALID;
    3891             : 
    3892             :                         /* access check */
    3893           4 :                         if (get_current_uid(conn) != 0) {
    3894           4 :                                 DEBUG(0,("get_user_quota: access_denied "
    3895             :                                          "service [%s] user [%s]\n",
    3896             :                                          lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    3897             :                                          conn->session_info->unix_info->unix_name));
    3898           8 :                                 return NT_STATUS_ACCESS_DENIED;
    3899             :                         }
    3900             : 
    3901           0 :                         status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
    3902             :                                                  NULL, &quotas);
    3903           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3904           0 :                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    3905           0 :                                 return status;
    3906             :                         }
    3907             : 
    3908           0 :                         data_len = 48;
    3909             : 
    3910           0 :                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
    3911             :                                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    3912             : 
    3913             :                         /* Unknown1 24 NULL bytes*/
    3914           0 :                         SBIG_UINT(pdata,0,(uint64_t)0);
    3915           0 :                         SBIG_UINT(pdata,8,(uint64_t)0);
    3916           0 :                         SBIG_UINT(pdata,16,(uint64_t)0);
    3917             : 
    3918             :                         /* Default Soft Quota 8 bytes */
    3919           0 :                         SBIG_UINT(pdata,24,quotas.softlim);
    3920             : 
    3921             :                         /* Default Hard Quota 8 bytes */
    3922           0 :                         SBIG_UINT(pdata,32,quotas.hardlim);
    3923             : 
    3924             :                         /* Quota flag 2 bytes */
    3925           0 :                         SSVAL(pdata,40,quotas.qflags);
    3926             : 
    3927             :                         /* Unknown3 6 NULL bytes */
    3928           0 :                         SSVAL(pdata,42,0);
    3929           0 :                         SIVAL(pdata,44,0);
    3930             : 
    3931           0 :                         break;
    3932             :                 }
    3933             : #endif /* HAVE_SYS_QUOTAS */
    3934          40 :                 case SMB_FS_OBJECTID_INFORMATION:
    3935             :                 {
    3936             :                         unsigned char objid[16];
    3937             :                         struct smb_extended_info extended_info;
    3938          40 :                         memcpy(pdata,create_volume_objectid(conn, objid),16);
    3939          40 :                         samba_extended_info_version (&extended_info);
    3940          40 :                         SIVAL(pdata,16,extended_info.samba_magic);
    3941          40 :                         SIVAL(pdata,20,extended_info.samba_version);
    3942          40 :                         SIVAL(pdata,24,extended_info.samba_subversion);
    3943          40 :                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
    3944          40 :                         memcpy(pdata+36,extended_info.samba_version_string,28);
    3945          40 :                         data_len = 64;
    3946          40 :                         break;
    3947             :                 }
    3948             : 
    3949           6 :                 case SMB_FS_SECTOR_SIZE_INFORMATION:
    3950             :                 {
    3951           6 :                         data_len = 28;
    3952             :                         /*
    3953             :                          * These values match a physical Windows Server 2012
    3954             :                          * share backed by NTFS atop spinning rust.
    3955             :                          */
    3956           6 :                         DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
    3957             :                         /* logical_bytes_per_sector */
    3958           6 :                         SIVAL(pdata, 0, bytes_per_sector);
    3959             :                         /* phys_bytes_per_sector_atomic */
    3960           6 :                         SIVAL(pdata, 4, bytes_per_sector);
    3961             :                         /* phys_bytes_per_sector_perf */
    3962           6 :                         SIVAL(pdata, 8, bytes_per_sector);
    3963             :                         /* fs_effective_phys_bytes_per_sector_atomic */
    3964           6 :                         SIVAL(pdata, 12, bytes_per_sector);
    3965             :                         /* flags */
    3966           6 :                         SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
    3967             :                                 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
    3968             :                         /* byte_off_sector_align */
    3969           6 :                         SIVAL(pdata, 20, 0);
    3970             :                         /* byte_off_partition_align */
    3971           6 :                         SIVAL(pdata, 24, 0);
    3972           6 :                         *fixed_portion = 28;
    3973           6 :                         break;
    3974             :                 }
    3975             : 
    3976             : 
    3977             :                 /*
    3978             :                  * Query the version and capabilities of the CIFS UNIX extensions
    3979             :                  * in use.
    3980             :                  */
    3981             : 
    3982         560 :                 case SMB_QUERY_CIFS_UNIX_INFO:
    3983             :                 {
    3984         560 :                         bool large_write = lp_min_receive_file_size() &&
    3985           0 :                                         !srv_is_signing_active(xconn);
    3986         560 :                         bool large_read = !srv_is_signing_active(xconn);
    3987         560 :                         int encrypt_caps = 0;
    3988             : 
    3989         560 :                         if (!lp_unix_extensions()) {
    3990           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3991             :                         }
    3992             : 
    3993         560 :                         switch (conn->encrypt_level) {
    3994           0 :                         case SMB_SIGNING_OFF:
    3995           0 :                                 encrypt_caps = 0;
    3996           0 :                                 break;
    3997         417 :                         case SMB_SIGNING_DESIRED:
    3998             :                         case SMB_SIGNING_IF_REQUIRED:
    3999             :                         case SMB_SIGNING_DEFAULT:
    4000         417 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
    4001         417 :                                 break;
    4002         143 :                         case SMB_SIGNING_REQUIRED:
    4003         143 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
    4004             :                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
    4005         143 :                                 large_write = false;
    4006         143 :                                 large_read = false;
    4007         143 :                                 break;
    4008             :                         }
    4009             : 
    4010         560 :                         data_len = 12;
    4011         560 :                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
    4012         560 :                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
    4013             : 
    4014             :                         /* We have POSIX ACLs, pathname, encryption, 
    4015             :                          * large read/write, and locking capability. */
    4016             : 
    4017         560 :                         SBIG_UINT(pdata,4,((uint64_t)(
    4018             :                                         CIFS_UNIX_POSIX_ACLS_CAP|
    4019             :                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
    4020             :                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
    4021             :                                         CIFS_UNIX_EXTATTR_CAP|
    4022             :                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
    4023             :                                         encrypt_caps|
    4024             :                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
    4025             :                                         (large_write ?
    4026             :                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
    4027         560 :                         break;
    4028             :                 }
    4029             : 
    4030           0 :                 case SMB_QUERY_POSIX_FS_INFO:
    4031             :                 {
    4032             :                         int rc;
    4033             :                         vfs_statvfs_struct svfs;
    4034             : 
    4035           0 :                         if (!lp_unix_extensions()) {
    4036           0 :                                 return NT_STATUS_INVALID_LEVEL;
    4037             :                         }
    4038             : 
    4039           0 :                         rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
    4040             : 
    4041           0 :                         if (!rc) {
    4042           0 :                                 data_len = 56;
    4043           0 :                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
    4044           0 :                                 SIVAL(pdata,4,svfs.BlockSize);
    4045           0 :                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
    4046           0 :                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
    4047           0 :                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
    4048           0 :                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
    4049           0 :                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
    4050           0 :                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
    4051           0 :                                 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
    4052             : #ifdef EOPNOTSUPP
    4053           0 :                         } else if (rc == EOPNOTSUPP) {
    4054           0 :                                 return NT_STATUS_INVALID_LEVEL;
    4055             : #endif /* EOPNOTSUPP */
    4056             :                         } else {
    4057           0 :                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    4058           0 :                                 return NT_STATUS_DOS(ERRSRV, ERRerror);
    4059             :                         }
    4060           0 :                         break;
    4061             :                 }
    4062             : 
    4063          32 :                 case SMB_QUERY_POSIX_WHOAMI:
    4064             :                 {
    4065          32 :                         uint32_t flags = 0;
    4066             :                         uint32_t sid_bytes;
    4067             :                         int i;
    4068             : 
    4069          32 :                         if (!lp_unix_extensions()) {
    4070           0 :                                 return NT_STATUS_INVALID_LEVEL;
    4071             :                         }
    4072             : 
    4073          32 :                         if (max_data_bytes < 40) {
    4074           0 :                                 return NT_STATUS_BUFFER_TOO_SMALL;
    4075             :                         }
    4076             : 
    4077          32 :                         if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
    4078           6 :                                 flags |= SMB_WHOAMI_GUEST;
    4079             :                         }
    4080             : 
    4081             :                         /* NOTE: 8 bytes for UID/GID, irrespective of native
    4082             :                          * platform size. This matches
    4083             :                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
    4084             :                          */
    4085          32 :                         data_len = 4 /* flags */
    4086             :                             + 4 /* flag mask */
    4087             :                             + 8 /* uid */
    4088             :                             + 8 /* gid */
    4089             :                             + 4 /* ngroups */
    4090             :                             + 4 /* num_sids */
    4091             :                             + 4 /* SID bytes */
    4092             :                             + 4 /* pad/reserved */
    4093          32 :                             + (conn->session_info->unix_token->ngroups * 8)
    4094             :                                 /* groups list */
    4095          32 :                             + (conn->session_info->security_token->num_sids *
    4096             :                                     SID_MAX_SIZE)
    4097             :                                 /* SID list */;
    4098             : 
    4099          32 :                         SIVAL(pdata, 0, flags);
    4100          32 :                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
    4101          32 :                         SBIG_UINT(pdata, 8,
    4102             :                                   (uint64_t)conn->session_info->unix_token->uid);
    4103          32 :                         SBIG_UINT(pdata, 16,
    4104             :                                   (uint64_t)conn->session_info->unix_token->gid);
    4105             : 
    4106             : 
    4107          32 :                         if (data_len >= max_data_bytes) {
    4108             :                                 /* Potential overflow, skip the GIDs and SIDs. */
    4109             : 
    4110          14 :                                 SIVAL(pdata, 24, 0); /* num_groups */
    4111          14 :                                 SIVAL(pdata, 28, 0); /* num_sids */
    4112          14 :                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
    4113          14 :                                 SIVAL(pdata, 36, 0); /* reserved */
    4114             : 
    4115          14 :                                 data_len = 40;
    4116          14 :                                 break;
    4117             :                         }
    4118             : 
    4119          18 :                         SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
    4120          18 :                         SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
    4121             : 
    4122             :                         /* We walk the SID list twice, but this call is fairly
    4123             :                          * infrequent, and I don't expect that it's performance
    4124             :                          * sensitive -- jpeach
    4125             :                          */
    4126         224 :                         for (i = 0, sid_bytes = 0;
    4127         188 :                              i < conn->session_info->security_token->num_sids; ++i) {
    4128         188 :                                 sid_bytes += ndr_size_dom_sid(
    4129         188 :                                         &conn->session_info->security_token->sids[i],
    4130             :                                         0);
    4131             :                         }
    4132             : 
    4133             :                         /* SID list byte count */
    4134          18 :                         SIVAL(pdata, 32, sid_bytes);
    4135             : 
    4136             :                         /* 4 bytes pad/reserved - must be zero */
    4137          18 :                         SIVAL(pdata, 36, 0);
    4138          18 :                         data_len = 40;
    4139             : 
    4140             :                         /* GID list */
    4141         176 :                         for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
    4142         158 :                                 SBIG_UINT(pdata, data_len,
    4143             :                                           (uint64_t)conn->session_info->unix_token->groups[i]);
    4144         158 :                                 data_len += 8;
    4145             :                         }
    4146             : 
    4147             :                         /* SID list */
    4148         224 :                         for (i = 0;
    4149         188 :                             i < conn->session_info->security_token->num_sids; ++i) {
    4150         188 :                                 int sid_len = ndr_size_dom_sid(
    4151         188 :                                         &conn->session_info->security_token->sids[i],
    4152             :                                         0);
    4153             : 
    4154         188 :                                 sid_linearize((uint8_t *)(pdata + data_len),
    4155             :                                               sid_len,
    4156         188 :                                     &conn->session_info->security_token->sids[i]);
    4157         188 :                                 data_len += sid_len;
    4158             :                         }
    4159             : 
    4160          18 :                         break;
    4161             :                 }
    4162             : 
    4163           0 :                 case SMB_MAC_QUERY_FS_INFO:
    4164             :                         /*
    4165             :                          * Thursby MAC extension... ONLY on NTFS filesystems
    4166             :                          * once we do streams then we don't need this
    4167             :                          */
    4168           0 :                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
    4169           0 :                                 data_len = 88;
    4170           0 :                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
    4171           0 :                                 break;
    4172             :                         }
    4173             : 
    4174             :                         FALL_THROUGH;
    4175             :                 default:
    4176           0 :                         return NT_STATUS_INVALID_LEVEL;
    4177             :         }
    4178             : 
    4179        2679 :         *ret_data_len = data_len;
    4180        2679 :         return status;
    4181             : }
    4182             : 
    4183           0 : static NTSTATUS smb_set_fsquota(connection_struct *conn,
    4184             :                         struct smb_request *req,
    4185             :                         files_struct *fsp,
    4186             :                         const DATA_BLOB *qdata)
    4187             : {
    4188           0 :         const struct loadparm_substitution *lp_sub =
    4189             :                 loadparm_s3_global_substitution();
    4190             :         NTSTATUS status;
    4191             :         SMB_NTQUOTA_STRUCT quotas;
    4192             : 
    4193           0 :         ZERO_STRUCT(quotas);
    4194             : 
    4195             :         /* access check */
    4196           0 :         if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
    4197           0 :                 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
    4198             :                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    4199             :                           conn->session_info->unix_info->unix_name));
    4200           0 :                 return NT_STATUS_ACCESS_DENIED;
    4201             :         }
    4202             : 
    4203           0 :         if (!check_fsp_ntquota_handle(conn, req,
    4204             :                                       fsp)) {
    4205           0 :                 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
    4206           0 :                 return NT_STATUS_INVALID_HANDLE;
    4207             :         }
    4208             : 
    4209             :         /* note: normally there're 48 bytes,
    4210             :          * but we didn't use the last 6 bytes for now
    4211             :          * --metze
    4212             :          */
    4213           0 :         if (qdata->length < 42) {
    4214           0 :                 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
    4215             :                         (unsigned int)qdata->length));
    4216           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4217             :         }
    4218             : 
    4219             :         /* unknown_1 24 NULL bytes in pdata*/
    4220             : 
    4221             :         /* the soft quotas 8 bytes (uint64_t)*/
    4222           0 :         quotas.softlim = BVAL(qdata->data,24);
    4223             : 
    4224             :         /* the hard quotas 8 bytes (uint64_t)*/
    4225           0 :         quotas.hardlim = BVAL(qdata->data,32);
    4226             : 
    4227             :         /* quota_flags 2 bytes **/
    4228           0 :         quotas.qflags = SVAL(qdata->data,40);
    4229             : 
    4230             :         /* unknown_2 6 NULL bytes follow*/
    4231             : 
    4232             :         /* now set the quotas */
    4233           0 :         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
    4234           0 :                 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
    4235             :                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    4236           0 :                 status =  map_nt_error_from_unix(errno);
    4237             :         } else {
    4238           0 :                 status = NT_STATUS_OK;
    4239             :         }
    4240           0 :         return status;
    4241             : }
    4242             : 
    4243           0 : NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
    4244             :                                 struct smb_request *req,
    4245             :                                 TALLOC_CTX *mem_ctx,
    4246             :                                 uint16_t info_level,
    4247             :                                 files_struct *fsp,
    4248             :                                 const DATA_BLOB *pdata)
    4249             : {
    4250           0 :         switch (info_level) {
    4251           0 :                 case SMB_FS_QUOTA_INFORMATION:
    4252             :                 {
    4253           0 :                         return smb_set_fsquota(conn,
    4254             :                                                 req,
    4255             :                                                 fsp,
    4256             :                                                 pdata);
    4257             :                 }
    4258             : 
    4259           0 :                 default:
    4260           0 :                         break;
    4261             :         }
    4262           0 :         return NT_STATUS_INVALID_LEVEL;
    4263             : }
    4264             : 
    4265             : /****************************************************************************
    4266             :  Reply to a TRANS2_QFSINFO (query filesystem info).
    4267             : ****************************************************************************/
    4268             : 
    4269         918 : static void call_trans2qfsinfo(connection_struct *conn,
    4270             :                                struct smb_request *req,
    4271             :                                char **pparams, int total_params,
    4272             :                                char **ppdata, int total_data,
    4273             :                                unsigned int max_data_bytes)
    4274             : {
    4275         918 :         char *params = *pparams;
    4276             :         uint16_t info_level;
    4277         918 :         int data_len = 0;
    4278             :         size_t fixed_portion;
    4279             :         NTSTATUS status;
    4280             : 
    4281         918 :         if (total_params < 2) {
    4282           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4283           0 :                 return;
    4284             :         }
    4285             : 
    4286         918 :         info_level = SVAL(params,0);
    4287             : 
    4288         918 :         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
    4289           0 :                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
    4290           0 :                         DEBUG(0,("call_trans2qfsinfo: encryption required "
    4291             :                                 "and info level 0x%x sent.\n",
    4292             :                                 (unsigned int)info_level));
    4293           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    4294           0 :                         return;
    4295             :                 }
    4296             :         }
    4297             : 
    4298         918 :         DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
    4299             : 
    4300         918 :         status = smbd_do_qfsinfo(req->xconn, conn, req,
    4301             :                                  info_level,
    4302         918 :                                  req->flags2,
    4303             :                                  max_data_bytes,
    4304             :                                  &fixed_portion,
    4305             :                                  NULL,
    4306             :                                  ppdata, &data_len);
    4307         918 :         if (!NT_STATUS_IS_OK(status)) {
    4308           0 :                 reply_nterror(req, status);
    4309           0 :                 return;
    4310             :         }
    4311             : 
    4312         918 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
    4313             :                             max_data_bytes);
    4314             : 
    4315         918 :         DEBUG( 4, ( "%s info_level = %d\n",
    4316             :                     smb_fn_name(req->cmd), info_level) );
    4317             : 
    4318         918 :         return;
    4319             : }
    4320             : 
    4321             : /****************************************************************************
    4322             :  Reply to a TRANS2_SETFSINFO (set filesystem info).
    4323             : ****************************************************************************/
    4324             : 
    4325         904 : static void call_trans2setfsinfo(connection_struct *conn,
    4326             :                                  struct smb_request *req,
    4327             :                                  char **pparams, int total_params,
    4328             :                                  char **ppdata, int total_data,
    4329             :                                  unsigned int max_data_bytes)
    4330             : {
    4331         904 :         const struct loadparm_substitution *lp_sub =
    4332             :                 loadparm_s3_global_substitution();
    4333         904 :         struct smbXsrv_connection *xconn = req->xconn;
    4334         904 :         char *pdata = *ppdata;
    4335         904 :         char *params = *pparams;
    4336             :         uint16_t info_level;
    4337             : 
    4338         904 :         DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
    4339             :                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    4340             : 
    4341             :         /*  */
    4342         904 :         if (total_params < 4) {
    4343           0 :                 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
    4344             :                         total_params));
    4345           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    4346           0 :                 return;
    4347             :         }
    4348             : 
    4349         904 :         info_level = SVAL(params,2);
    4350             : 
    4351         904 :         if (IS_IPC(conn)) {
    4352         380 :                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
    4353           0 :                                 info_level != SMB_SET_CIFS_UNIX_INFO) {
    4354           0 :                         DEBUG(0,("call_trans2setfsinfo: not an allowed "
    4355             :                                 "info level (0x%x) on IPC$.\n",
    4356             :                                 (unsigned int)info_level));
    4357           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    4358           0 :                         return;
    4359             :                 }
    4360             :         }
    4361             : 
    4362         904 :         if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
    4363           0 :                 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
    4364           0 :                         DEBUG(0,("call_trans2setfsinfo: encryption required "
    4365             :                                 "and info level 0x%x sent.\n",
    4366             :                                 (unsigned int)info_level));
    4367           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    4368           0 :                         return;
    4369             :                 }
    4370             :         }
    4371             : 
    4372         904 :         switch(info_level) {
    4373         112 :                 case SMB_SET_CIFS_UNIX_INFO:
    4374         112 :                         if (!lp_unix_extensions()) {
    4375           0 :                                 DEBUG(2,("call_trans2setfsinfo: "
    4376             :                                         "SMB_SET_CIFS_UNIX_INFO is invalid with "
    4377             :                                         "unix extensions off\n"));
    4378           0 :                                 reply_nterror(req,
    4379             :                                               NT_STATUS_INVALID_LEVEL);
    4380           0 :                                 return;
    4381             :                         }
    4382             : 
    4383             :                         /* There should be 12 bytes of capabilities set. */
    4384         112 :                         if (total_data < 12) {
    4385           0 :                                 reply_nterror(
    4386             :                                         req,
    4387             :                                         NT_STATUS_INVALID_PARAMETER);
    4388           0 :                                 return;
    4389             :                         }
    4390         112 :                         xconn->smb1.unix_info.client_major = SVAL(pdata,0);
    4391         112 :                         xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
    4392         112 :                         xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
    4393         112 :                         xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
    4394             :                         /* Just print these values for now. */
    4395         112 :                         DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
    4396             :                                    "major = %u, minor = %u cap_low = 0x%x, "
    4397             :                                    "cap_high = 0x%xn",
    4398             :                                    (unsigned int)xconn->
    4399             :                                    smb1.unix_info.client_major,
    4400             :                                    (unsigned int)xconn->
    4401             :                                    smb1.unix_info.client_minor,
    4402             :                                    (unsigned int)xconn->
    4403             :                                    smb1.unix_info.client_cap_low,
    4404             :                                    (unsigned int)xconn->
    4405             :                                    smb1.unix_info.client_cap_high));
    4406             : 
    4407             :                         /* Here is where we must switch to posix pathname processing... */
    4408         112 :                         if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
    4409         112 :                                 lp_set_posix_pathnames();
    4410         112 :                                 mangle_change_to_posix();
    4411             :                         }
    4412             : 
    4413         224 :                         if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
    4414         112 :                             !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
    4415             :                                 /* Client that knows how to do posix locks,
    4416             :                                  * but not posix open/mkdir operations. Set a
    4417             :                                  * default type for read/write checks. */
    4418             : 
    4419           0 :                                 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
    4420             : 
    4421             :                         }
    4422         112 :                         break;
    4423             : 
    4424         792 :                 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
    4425             :                         {
    4426             :                                 NTSTATUS status;
    4427         792 :                                 size_t param_len = 0;
    4428         792 :                                 size_t data_len = total_data;
    4429             : 
    4430         792 :                                 if (!lp_unix_extensions()) {
    4431           0 :                                         reply_nterror(
    4432             :                                                 req,
    4433             :                                                 NT_STATUS_INVALID_LEVEL);
    4434           0 :                                         return;
    4435             :                                 }
    4436             : 
    4437         792 :                                 if (lp_server_smb_encrypt(SNUM(conn)) ==
    4438             :                                     SMB_ENCRYPTION_OFF) {
    4439           0 :                                         reply_nterror(
    4440             :                                                 req,
    4441             :                                                 NT_STATUS_NOT_SUPPORTED);
    4442           0 :                                         return;
    4443             :                                 }
    4444             : 
    4445         792 :                                 if (xconn->smb1.echo_handler.trusted_fde) {
    4446           0 :                                         DEBUG( 2,("call_trans2setfsinfo: "
    4447             :                                                 "request transport encryption disabled"
    4448             :                                                 "with 'fork echo handler = yes'\n"));
    4449           0 :                                         reply_nterror(
    4450             :                                                 req,
    4451             :                                                 NT_STATUS_NOT_SUPPORTED);
    4452           0 :                                         return;
    4453             :                                 }
    4454             : 
    4455         792 :                                 DEBUG( 4,("call_trans2setfsinfo: "
    4456             :                                         "request transport encryption.\n"));
    4457             : 
    4458         792 :                                 status = srv_request_encryption_setup(conn,
    4459             :                                                                 (unsigned char **)ppdata,
    4460             :                                                                 &data_len,
    4461             :                                                                 (unsigned char **)pparams,
    4462             :                                                                 &param_len);
    4463             : 
    4464        1188 :                                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
    4465         396 :                                                 !NT_STATUS_IS_OK(status)) {
    4466           0 :                                         reply_nterror(req, status);
    4467           0 :                                         return;
    4468             :                                 }
    4469             : 
    4470        1584 :                                 send_trans2_replies(conn, req,
    4471         792 :                                                 NT_STATUS_OK,
    4472             :                                                 *pparams,
    4473             :                                                 param_len,
    4474             :                                                 *ppdata,
    4475             :                                                 data_len,
    4476             :                                                 max_data_bytes);
    4477             : 
    4478         792 :                                 if (NT_STATUS_IS_OK(status)) {
    4479             :                                         /* Server-side transport
    4480             :                                          * encryption is now *on*. */
    4481         396 :                                         status = srv_encryption_start(conn);
    4482         396 :                                         if (!NT_STATUS_IS_OK(status)) {
    4483           0 :                                                 char *reason = talloc_asprintf(talloc_tos(),
    4484             :                                                                                "Failure in setting "
    4485             :                                                                                "up encrypted transport: %s",
    4486             :                                                                                nt_errstr(status));
    4487           0 :                                                 exit_server_cleanly(reason);
    4488             :                                         }
    4489             :                                 }
    4490         792 :                                 return;
    4491             :                         }
    4492             : 
    4493           0 :                 case SMB_FS_QUOTA_INFORMATION:
    4494             :                         {
    4495             :                                 NTSTATUS status;
    4496           0 :                                 DATA_BLOB qdata = {
    4497             :                                                 .data = (uint8_t *)pdata,
    4498             :                                                 .length = total_data
    4499             :                                 };
    4500           0 :                                 files_struct *fsp = NULL;
    4501           0 :                                 fsp = file_fsp(req, SVAL(params,0));
    4502             : 
    4503           0 :                                 status = smb_set_fsquota(conn,
    4504             :                                                         req,
    4505             :                                                         fsp,
    4506             :                                                         &qdata);
    4507           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    4508           0 :                                         reply_nterror(req, status);
    4509           0 :                                         return;
    4510             :                                 }
    4511           0 :                                 break;
    4512             :                         }
    4513           0 :                 default:
    4514           0 :                         DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
    4515             :                                 info_level));
    4516           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    4517           0 :                         return;
    4518             :                         break;
    4519             :         }
    4520             : 
    4521             :         /* 
    4522             :          * sending this reply works fine, 
    4523             :          * but I'm not sure it's the same 
    4524             :          * like windows do...
    4525             :          * --metze
    4526             :          */
    4527         112 :         reply_outbuf(req, 10, 0);
    4528             : }
    4529             : 
    4530             : #if defined(HAVE_POSIX_ACLS)
    4531             : /****************************************************************************
    4532             :  Utility function to count the number of entries in a POSIX acl.
    4533             : ****************************************************************************/
    4534             : 
    4535         128 : static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
    4536             : {
    4537         128 :         unsigned int ace_count = 0;
    4538         128 :         int entry_id = SMB_ACL_FIRST_ENTRY;
    4539             :         SMB_ACL_ENTRY_T entry;
    4540             : 
    4541         524 :         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
    4542             :                 /* get_next... */
    4543         268 :                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
    4544          52 :                         entry_id = SMB_ACL_NEXT_ENTRY;
    4545             :                 }
    4546         268 :                 ace_count++;
    4547             :         }
    4548         128 :         return ace_count;
    4549             : }
    4550             : 
    4551             : /****************************************************************************
    4552             :  Utility function to marshall a POSIX acl into wire format.
    4553             : ****************************************************************************/
    4554             : 
    4555         128 : static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
    4556             : {
    4557         128 :         int entry_id = SMB_ACL_FIRST_ENTRY;
    4558             :         SMB_ACL_ENTRY_T entry;
    4559             : 
    4560         524 :         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
    4561             :                 SMB_ACL_TAG_T tagtype;
    4562             :                 SMB_ACL_PERMSET_T permset;
    4563         268 :                 unsigned char perms = 0;
    4564             :                 unsigned int own_grp;
    4565             : 
    4566             :                 /* get_next... */
    4567         268 :                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
    4568          52 :                         entry_id = SMB_ACL_NEXT_ENTRY;
    4569             :                 }
    4570             : 
    4571         268 :                 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
    4572           0 :                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
    4573           0 :                         return False;
    4574             :                 }
    4575             : 
    4576         268 :                 if (sys_acl_get_permset(entry, &permset) == -1) {
    4577           0 :                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
    4578           0 :                         return False;
    4579             :                 }
    4580             : 
    4581         268 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
    4582         268 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
    4583         268 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
    4584             : 
    4585         268 :                 SCVAL(pdata,1,perms);
    4586             : 
    4587         268 :                 switch (tagtype) {
    4588          52 :                         case SMB_ACL_USER_OBJ:
    4589          52 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
    4590          52 :                                 own_grp = (unsigned int)pst->st_ex_uid;
    4591          52 :                                 SIVAL(pdata,2,own_grp);
    4592          52 :                                 SIVAL(pdata,6,0);
    4593          52 :                                 break;
    4594          40 :                         case SMB_ACL_USER:
    4595             :                                 {
    4596          40 :                                         uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
    4597          40 :                                         if (!puid) {
    4598           0 :                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
    4599           0 :                                                 return False;
    4600             :                                         }
    4601          40 :                                         own_grp = (unsigned int)*puid;
    4602          40 :                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
    4603          40 :                                         SIVAL(pdata,2,own_grp);
    4604          40 :                                         SIVAL(pdata,6,0);
    4605          40 :                                         break;
    4606             :                                 }
    4607          52 :                         case SMB_ACL_GROUP_OBJ:
    4608          52 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
    4609          52 :                                 own_grp = (unsigned int)pst->st_ex_gid;
    4610          52 :                                 SIVAL(pdata,2,own_grp);
    4611          52 :                                 SIVAL(pdata,6,0);
    4612          52 :                                 break;
    4613          36 :                         case SMB_ACL_GROUP:
    4614             :                                 {
    4615          36 :                                         gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
    4616          36 :                                         if (!pgid) {
    4617           0 :                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
    4618           0 :                                                 return False;
    4619             :                                         }
    4620          36 :                                         own_grp = (unsigned int)*pgid;
    4621          36 :                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
    4622          36 :                                         SIVAL(pdata,2,own_grp);
    4623          36 :                                         SIVAL(pdata,6,0);
    4624          36 :                                         break;
    4625             :                                 }
    4626          36 :                         case SMB_ACL_MASK:
    4627          36 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
    4628          36 :                                 SIVAL(pdata,2,0xFFFFFFFF);
    4629          36 :                                 SIVAL(pdata,6,0xFFFFFFFF);
    4630          36 :                                 break;
    4631          52 :                         case SMB_ACL_OTHER:
    4632          52 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
    4633          52 :                                 SIVAL(pdata,2,0xFFFFFFFF);
    4634          52 :                                 SIVAL(pdata,6,0xFFFFFFFF);
    4635          52 :                                 break;
    4636           0 :                         default:
    4637           0 :                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
    4638           0 :                                 return False;
    4639             :                 }
    4640         268 :                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
    4641             :         }
    4642             : 
    4643         128 :         return True;
    4644             : }
    4645             : #endif
    4646             : 
    4647             : /****************************************************************************
    4648             :  Store the FILE_UNIX_BASIC info.
    4649             : ****************************************************************************/
    4650             : 
    4651         118 : static char *store_file_unix_basic(connection_struct *conn,
    4652             :                                 char *pdata,
    4653             :                                 files_struct *fsp,
    4654             :                                 const SMB_STRUCT_STAT *psbuf)
    4655             : {
    4656             :         dev_t devno;
    4657             : 
    4658         118 :         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
    4659         118 :         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
    4660             : 
    4661         118 :         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
    4662         118 :         pdata += 8;
    4663             : 
    4664         118 :         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
    4665         118 :         pdata += 8;
    4666             : 
    4667         118 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime);       /* Change Time 64 Bit */
    4668         118 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime);     /* Last access time 64 Bit */
    4669         118 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
    4670         118 :         pdata += 24;
    4671             : 
    4672         118 :         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
    4673         118 :         SIVAL(pdata,4,0);
    4674         118 :         pdata += 8;
    4675             : 
    4676         118 :         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
    4677         118 :         SIVAL(pdata,4,0);
    4678         118 :         pdata += 8;
    4679             : 
    4680         118 :         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
    4681         118 :         pdata += 4;
    4682             : 
    4683         118 :         if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
    4684           0 :                 devno = psbuf->st_ex_rdev;
    4685             :         } else {
    4686         118 :                 devno = psbuf->st_ex_dev;
    4687             :         }
    4688             : 
    4689         118 :         SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
    4690         118 :         SIVAL(pdata,4,0);
    4691         118 :         pdata += 8;
    4692             : 
    4693         118 :         SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
    4694         118 :         SIVAL(pdata,4,0);
    4695         118 :         pdata += 8;
    4696             : 
    4697         118 :         SINO_T_VAL(pdata, 0, psbuf->st_ex_ino);   /* inode number */
    4698         118 :         pdata += 8;
    4699             : 
    4700         118 :         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
    4701         118 :         SIVAL(pdata,4,0);
    4702         118 :         pdata += 8;
    4703             : 
    4704         118 :         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
    4705         118 :         SIVAL(pdata,4,0);
    4706         118 :         pdata += 8;
    4707             : 
    4708         118 :         return pdata;
    4709             : }
    4710             : 
    4711             : /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
    4712             :  * the chflags(2) (or equivalent) flags.
    4713             :  *
    4714             :  * XXX: this really should be behind the VFS interface. To do this, we would
    4715             :  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
    4716             :  * Each VFS module could then implement its own mapping as appropriate for the
    4717             :  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
    4718             :  */
    4719             : static const struct {unsigned stat_fflag; unsigned smb_fflag;}
    4720             :         info2_flags_map[] =
    4721             : {
    4722             : #ifdef UF_NODUMP
    4723             :     { UF_NODUMP, EXT_DO_NOT_BACKUP },
    4724             : #endif
    4725             : 
    4726             : #ifdef UF_IMMUTABLE
    4727             :     { UF_IMMUTABLE, EXT_IMMUTABLE },
    4728             : #endif
    4729             : 
    4730             : #ifdef UF_APPEND
    4731             :     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
    4732             : #endif
    4733             : 
    4734             : #ifdef UF_HIDDEN
    4735             :     { UF_HIDDEN, EXT_HIDDEN },
    4736             : #endif
    4737             : 
    4738             :     /* Do not remove. We need to guarantee that this array has at least one
    4739             :      * entry to build on HP-UX.
    4740             :      */
    4741             :     { 0, 0 }
    4742             : 
    4743             : };
    4744             : 
    4745          24 : static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
    4746             :                                 uint32_t *smb_fflags, uint32_t *smb_fmask)
    4747             : {
    4748             :         int i;
    4749             : 
    4750          48 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    4751          24 :             *smb_fmask |= info2_flags_map[i].smb_fflag;
    4752          24 :             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
    4753           0 :                     *smb_fflags |= info2_flags_map[i].smb_fflag;
    4754             :             }
    4755             :         }
    4756          24 : }
    4757             : 
    4758         128 : static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
    4759             :                                 const uint32_t smb_fflags,
    4760             :                                 const uint32_t smb_fmask,
    4761             :                                 int *stat_fflags)
    4762             : {
    4763         128 :         uint32_t max_fmask = 0;
    4764             :         int i;
    4765             : 
    4766         128 :         *stat_fflags = psbuf->st_ex_flags;
    4767             : 
    4768             :         /* For each flags requested in smb_fmask, check the state of the
    4769             :          * corresponding flag in smb_fflags and set or clear the matching
    4770             :          * stat flag.
    4771             :          */
    4772             : 
    4773         256 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    4774         128 :             max_fmask |= info2_flags_map[i].smb_fflag;
    4775         128 :             if (smb_fmask & info2_flags_map[i].smb_fflag) {
    4776           0 :                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
    4777           0 :                             *stat_fflags |= info2_flags_map[i].stat_fflag;
    4778             :                     } else {
    4779           0 :                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
    4780             :                     }
    4781             :             }
    4782             :         }
    4783             : 
    4784             :         /* If smb_fmask is asking to set any bits that are not supported by
    4785             :          * our flag mappings, we should fail.
    4786             :          */
    4787         128 :         if ((smb_fmask & max_fmask) != smb_fmask) {
    4788         128 :                 return False;
    4789             :         }
    4790             : 
    4791           0 :         return True;
    4792             : }
    4793             : 
    4794             : 
    4795             : /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
    4796             :  * of file flags and birth (create) time.
    4797             :  */
    4798          24 : static char *store_file_unix_basic_info2(connection_struct *conn,
    4799             :                                 char *pdata,
    4800             :                                 files_struct *fsp,
    4801             :                                 const SMB_STRUCT_STAT *psbuf)
    4802             : {
    4803          24 :         uint32_t file_flags = 0;
    4804          24 :         uint32_t flags_mask = 0;
    4805             : 
    4806          24 :         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
    4807             : 
    4808             :         /* Create (birth) time 64 bit */
    4809          24 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
    4810          24 :         pdata += 8;
    4811             : 
    4812          24 :         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
    4813          24 :         SIVAL(pdata, 0, file_flags); /* flags */
    4814          24 :         SIVAL(pdata, 4, flags_mask); /* mask */
    4815          24 :         pdata += 8;
    4816             : 
    4817          24 :         return pdata;
    4818             : }
    4819             : 
    4820        3584 : static NTSTATUS marshall_stream_info(unsigned int num_streams,
    4821             :                                      const struct stream_struct *streams,
    4822             :                                      char *data,
    4823             :                                      unsigned int max_data_bytes,
    4824             :                                      unsigned int *data_size)
    4825             : {
    4826             :         unsigned int i;
    4827        3584 :         unsigned int ofs = 0;
    4828             : 
    4829        3584 :         if (max_data_bytes < 32) {
    4830         128 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
    4831             :         }
    4832             : 
    4833       14892 :         for (i = 0; i < num_streams; i++) {
    4834             :                 unsigned int next_offset;
    4835             :                 size_t namelen;
    4836             :                 smb_ucs2_t *namebuf;
    4837             : 
    4838        4014 :                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
    4839        8028 :                                       streams[i].name, &namelen) ||
    4840        4014 :                     namelen <= 2)
    4841             :                 {
    4842          24 :                         return NT_STATUS_INVALID_PARAMETER;
    4843             :                 }
    4844             : 
    4845             :                 /*
    4846             :                  * name_buf is now null-terminated, we need to marshall as not
    4847             :                  * terminated
    4848             :                  */
    4849             : 
    4850        4014 :                 namelen -= 2;
    4851             : 
    4852             :                 /*
    4853             :                  * We cannot overflow ...
    4854             :                  */
    4855        4014 :                 if ((ofs + 24 + namelen) > max_data_bytes) {
    4856          24 :                         DEBUG(10, ("refusing to overflow reply at stream %u\n",
    4857             :                                 i));
    4858          24 :                         TALLOC_FREE(namebuf);
    4859          24 :                         return STATUS_BUFFER_OVERFLOW;
    4860             :                 }
    4861             : 
    4862        3990 :                 SIVAL(data, ofs+4, namelen);
    4863        3990 :                 SOFF_T(data, ofs+8, streams[i].size);
    4864        3990 :                 SOFF_T(data, ofs+16, streams[i].alloc_size);
    4865        3990 :                 memcpy(data+ofs+24, namebuf, namelen);
    4866        3990 :                 TALLOC_FREE(namebuf);
    4867             : 
    4868        3990 :                 next_offset = ofs + 24 + namelen;
    4869             : 
    4870        3990 :                 if (i == num_streams-1) {
    4871        3192 :                         SIVAL(data, ofs, 0);
    4872             :                 }
    4873             :                 else {
    4874         798 :                         unsigned int align = ndr_align_size(next_offset, 8);
    4875             : 
    4876         798 :                         if ((next_offset + align) > max_data_bytes) {
    4877           0 :                                 DEBUG(10, ("refusing to overflow align "
    4878             :                                         "reply at stream %u\n",
    4879             :                                         i));
    4880           0 :                                 TALLOC_FREE(namebuf);
    4881           0 :                                 return STATUS_BUFFER_OVERFLOW;
    4882             :                         }
    4883             : 
    4884         798 :                         memset(data+next_offset, 0, align);
    4885         798 :                         next_offset += align;
    4886             : 
    4887         798 :                         SIVAL(data, ofs, next_offset - ofs);
    4888         798 :                         ofs = next_offset;
    4889             :                 }
    4890             : 
    4891        3990 :                 ofs = next_offset;
    4892             :         }
    4893             : 
    4894        3432 :         DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
    4895             : 
    4896        3432 :         *data_size = ofs;
    4897             : 
    4898        3432 :         return NT_STATUS_OK;
    4899             : }
    4900             : 
    4901          24 : static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
    4902             :                                 struct smb_request *req,
    4903             :                                 struct smb_filename *smb_fname,
    4904             :                                 char *pdata,
    4905             :                                 unsigned int data_size_in,
    4906             :                                 unsigned int *pdata_size_out)
    4907             : {
    4908             :         NTSTATUS status;
    4909          24 :         size_t len = 0;
    4910          24 :         int link_len = 0;
    4911          24 :         struct smb_filename *parent_fname = NULL;
    4912          24 :         struct smb_filename *base_name = NULL;
    4913             : 
    4914          24 :         char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
    4915             : 
    4916          24 :         if (!buffer) {
    4917           0 :                 return NT_STATUS_NO_MEMORY;
    4918             :         }
    4919             : 
    4920          24 :         DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
    4921             :                 smb_fname_str_dbg(smb_fname));
    4922             : 
    4923          24 :         if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
    4924           0 :                 TALLOC_FREE(buffer);
    4925           0 :                 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
    4926             :         }
    4927             : 
    4928          24 :         status = parent_pathref(talloc_tos(),
    4929             :                                 conn->cwd_fsp,
    4930             :                                 smb_fname,
    4931             :                                 &parent_fname,
    4932             :                                 &base_name);
    4933          24 :         if (!NT_STATUS_IS_OK(status)) {
    4934           0 :                 TALLOC_FREE(buffer);
    4935           0 :                 return status;
    4936             :         }
    4937             : 
    4938          24 :         link_len = SMB_VFS_READLINKAT(conn,
    4939             :                                 parent_fname->fsp,
    4940             :                                 base_name,
    4941             :                                 buffer,
    4942             :                                 PATH_MAX);
    4943             : 
    4944          24 :         TALLOC_FREE(parent_fname);
    4945             : 
    4946          24 :         if (link_len == -1) {
    4947           0 :                 TALLOC_FREE(buffer);
    4948           0 :                 return map_nt_error_from_unix(errno);
    4949             :         }
    4950             : 
    4951          24 :         buffer[link_len] = 0;
    4952          24 :         status = srvstr_push(pdata,
    4953             :                         req->flags2,
    4954             :                         pdata,
    4955             :                         buffer,
    4956             :                         data_size_in,
    4957             :                         STR_TERMINATE,
    4958             :                         &len);
    4959          24 :         TALLOC_FREE(buffer);
    4960          24 :         if (!NT_STATUS_IS_OK(status)) {
    4961           0 :                 return status;
    4962             :         }
    4963          24 :         *pdata_size_out = len;
    4964             : 
    4965          24 :         return NT_STATUS_OK;
    4966             : }
    4967             : 
    4968             : #if defined(HAVE_POSIX_ACLS)
    4969          80 : static NTSTATUS smb_query_posix_acl(connection_struct *conn,
    4970             :                                 struct smb_request *req,
    4971             :                                 files_struct *fsp,
    4972             :                                 struct smb_filename *smb_fname,
    4973             :                                 char *pdata,
    4974             :                                 unsigned int data_size_in,
    4975             :                                 unsigned int *pdata_size_out)
    4976             : {
    4977          80 :         SMB_ACL_T file_acl = NULL;
    4978          80 :         SMB_ACL_T def_acl = NULL;
    4979          80 :         uint16_t num_file_acls = 0;
    4980          80 :         uint16_t num_def_acls = 0;
    4981          80 :         unsigned int size_needed = 0;
    4982             :         NTSTATUS status;
    4983             :         bool ok;
    4984          80 :         bool close_fsp = false;
    4985             : 
    4986             :         /*
    4987             :          * Ensure we always operate on a file descriptor, not just
    4988             :          * the filename.
    4989             :          */
    4990          80 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    4991          80 :                 uint32_t access_mask = SEC_STD_READ_CONTROL|
    4992             :                                         FILE_READ_ATTRIBUTES|
    4993             :                                         FILE_WRITE_ATTRIBUTES;
    4994             : 
    4995          80 :                 status = get_posix_fsp(conn,
    4996             :                                         req,
    4997             :                                         smb_fname,
    4998             :                                         access_mask,
    4999             :                                         &fsp);
    5000             : 
    5001          80 :                 if (!NT_STATUS_IS_OK(status)) {
    5002          16 :                         goto out;
    5003             :                 }
    5004          64 :                 close_fsp = true;
    5005             :         }
    5006             : 
    5007          64 :         SMB_ASSERT(fsp != NULL);
    5008             : 
    5009          64 :         status = refuse_symlink_fsp(fsp);
    5010          64 :         if (!NT_STATUS_IS_OK(status)) {
    5011           0 :                 goto out;
    5012             :         }
    5013             : 
    5014          64 :         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
    5015             :                                         talloc_tos());
    5016             : 
    5017          64 :         if (file_acl == NULL && no_acl_syscall_error(errno)) {
    5018           0 :                 DBG_INFO("ACLs not implemented on "
    5019             :                         "filesystem containing %s\n",
    5020             :                         fsp_str_dbg(fsp));
    5021           0 :                 status = NT_STATUS_NOT_IMPLEMENTED;
    5022           0 :                 goto out;
    5023             :         }
    5024             : 
    5025          64 :         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
    5026             :                 /*
    5027             :                  * We can only have default POSIX ACLs on
    5028             :                  * directories.
    5029             :                  */
    5030          20 :                 if (!fsp->fsp_flags.is_directory) {
    5031           0 :                         DBG_INFO("Non-directory open %s\n",
    5032             :                                 fsp_str_dbg(fsp));
    5033           0 :                         status = NT_STATUS_INVALID_HANDLE;
    5034           0 :                         goto out;
    5035             :                 }
    5036          20 :                 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
    5037             :                                         SMB_ACL_TYPE_DEFAULT,
    5038             :                                         talloc_tos());
    5039          20 :                 def_acl = free_empty_sys_acl(conn, def_acl);
    5040             :         }
    5041             : 
    5042          64 :         num_file_acls = count_acl_entries(conn, file_acl);
    5043          64 :         num_def_acls = count_acl_entries(conn, def_acl);
    5044             : 
    5045             :         /* Wrap checks. */
    5046          64 :         if (num_file_acls + num_def_acls < num_file_acls) {
    5047           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5048           0 :                 goto out;
    5049             :         }
    5050             : 
    5051          64 :         size_needed = num_file_acls + num_def_acls;
    5052             : 
    5053             :         /*
    5054             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    5055             :          * than UINT_MAX, so check by division.
    5056             :          */
    5057          64 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    5058           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5059           0 :                 goto out;
    5060             :         }
    5061             : 
    5062          64 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    5063          64 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    5064           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5065           0 :                 goto out;
    5066             :         }
    5067          64 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    5068             : 
    5069          64 :         if ( data_size_in < size_needed) {
    5070           0 :                 DBG_INFO("data_size too small (%u) need %u\n",
    5071             :                         data_size_in,
    5072             :                         size_needed);
    5073           0 :                 status = NT_STATUS_BUFFER_TOO_SMALL;
    5074           0 :                 goto out;
    5075             :         }
    5076             : 
    5077          64 :         SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
    5078          64 :         SSVAL(pdata,2,num_file_acls);
    5079          64 :         SSVAL(pdata,4,num_def_acls);
    5080          64 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    5081             : 
    5082          64 :         ok = marshall_posix_acl(conn,
    5083             :                         pdata,
    5084          64 :                         &fsp->fsp_name->st,
    5085             :                         file_acl);
    5086          64 :         if (!ok) {
    5087           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    5088           0 :                 goto out;
    5089             :         }
    5090          64 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    5091             : 
    5092          64 :         ok = marshall_posix_acl(conn,
    5093             :                         pdata,
    5094          64 :                         &fsp->fsp_name->st,
    5095             :                         def_acl);
    5096          64 :         if (!ok) {
    5097           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    5098           0 :                 goto out;
    5099             :         }
    5100             : 
    5101          64 :         *pdata_size_out = size_needed;
    5102          64 :         status = NT_STATUS_OK;
    5103             : 
    5104          80 :   out:
    5105             : 
    5106          80 :         if (close_fsp) {
    5107             :                 /*
    5108             :                  * Ensure the stat struct in smb_fname is up to
    5109             :                  * date. Structure copy.
    5110             :                  */
    5111          64 :                 smb_fname->st = fsp->fsp_name->st;
    5112          64 :                 (void)close_file(req, fsp, NORMAL_CLOSE);
    5113          64 :                 fsp = NULL;
    5114             :         }
    5115             : 
    5116          80 :         TALLOC_FREE(file_acl);
    5117          80 :         TALLOC_FREE(def_acl);
    5118          80 :         return status;
    5119             : }
    5120             : #endif
    5121             : 
    5122             : /****************************************************************************
    5123             :  Reply to a TRANSACT2_QFILEINFO on a PIPE !
    5124             : ****************************************************************************/
    5125             : 
    5126           0 : static void call_trans2qpipeinfo(connection_struct *conn,
    5127             :                                  struct smb_request *req,
    5128             :                                  unsigned int tran_call,
    5129             :                                  char **pparams, int total_params,
    5130             :                                  char **ppdata, int total_data,
    5131             :                                  unsigned int max_data_bytes)
    5132             : {
    5133           0 :         char *params = *pparams;
    5134           0 :         char *pdata = *ppdata;
    5135           0 :         unsigned int data_size = 0;
    5136           0 :         unsigned int param_size = 2;
    5137             :         uint16_t info_level;
    5138             :         files_struct *fsp;
    5139             : 
    5140           0 :         if (!params) {
    5141           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5142           0 :                 return;
    5143             :         }
    5144             : 
    5145           0 :         if (total_params < 4) {
    5146           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5147           0 :                 return;
    5148             :         }
    5149             : 
    5150           0 :         fsp = file_fsp(req, SVAL(params,0));
    5151           0 :         if (!fsp_is_np(fsp)) {
    5152           0 :                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    5153           0 :                 return;
    5154             :         }
    5155             : 
    5156           0 :         info_level = SVAL(params,2);
    5157             : 
    5158           0 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    5159           0 :         if (*pparams == NULL) {
    5160           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5161           0 :                 return;
    5162             :         }
    5163           0 :         params = *pparams;
    5164           0 :         SSVAL(params,0,0);
    5165           0 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    5166           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5167           0 :                 return;
    5168             :         }
    5169           0 :         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
    5170           0 :         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
    5171           0 :         if (*ppdata == NULL ) {
    5172           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5173           0 :                 return;
    5174             :         }
    5175           0 :         pdata = *ppdata;
    5176             : 
    5177           0 :         switch (info_level) {
    5178           0 :                 case SMB_FILE_STANDARD_INFORMATION:
    5179           0 :                         memset(pdata,0,24);
    5180           0 :                         SOFF_T(pdata,0,4096LL);
    5181           0 :                         SIVAL(pdata,16,1);
    5182           0 :                         SIVAL(pdata,20,1);
    5183           0 :                         data_size = 24;
    5184           0 :                         break;
    5185             : 
    5186           0 :                 default:
    5187           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    5188           0 :                         return;
    5189             :         }
    5190             : 
    5191           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
    5192             :                             max_data_bytes);
    5193             : 
    5194           0 :         return;
    5195             : }
    5196             : 
    5197       24659 : NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
    5198             :                                TALLOC_CTX *mem_ctx,
    5199             :                                struct smb_request *req,
    5200             :                                uint16_t info_level,
    5201             :                                files_struct *fsp,
    5202             :                                struct smb_filename *smb_fname,
    5203             :                                bool delete_pending,
    5204             :                                struct timespec write_time_ts,
    5205             :                                struct ea_list *ea_list,
    5206             :                                int lock_data_count,
    5207             :                                char *lock_data,
    5208             :                                uint16_t flags2,
    5209             :                                unsigned int max_data_bytes,
    5210             :                                size_t *fixed_portion,
    5211             :                                char **ppdata,
    5212             :                                unsigned int *pdata_size)
    5213             : {
    5214       24659 :         char *pdata = *ppdata;
    5215             :         char *dstart, *dend;
    5216             :         unsigned int data_size;
    5217             :         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
    5218             :         time_t create_time, mtime, atime, c_time;
    5219       24659 :         SMB_STRUCT_STAT *psbuf = NULL;
    5220             :         char *p;
    5221             :         char *base_name;
    5222             :         char *dos_fname;
    5223             :         int mode;
    5224             :         int nlink;
    5225             :         NTSTATUS status;
    5226       24659 :         uint64_t file_size = 0;
    5227       24659 :         uint64_t pos = 0;
    5228       24659 :         uint64_t allocation_size = 0;
    5229       24659 :         uint64_t file_id = 0;
    5230       24659 :         uint32_t access_mask = 0;
    5231       24659 :         size_t len = 0;
    5232             : 
    5233       24659 :         if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
    5234           0 :                 return NT_STATUS_INVALID_LEVEL;
    5235             :         }
    5236             : 
    5237       24659 :         DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
    5238             :                  smb_fname_str_dbg(smb_fname),
    5239             :                  fsp_fnum_dbg(fsp),
    5240             :                  info_level, max_data_bytes));
    5241             : 
    5242             :         /*
    5243             :          * In case of querying a symlink in POSIX context,
    5244             :          * fsp will be NULL. fdos_mode() deals with it.
    5245             :          */
    5246       24659 :         if (fsp != NULL) {
    5247       24391 :                 smb_fname = fsp->fsp_name;
    5248             :         }
    5249       24659 :         mode = fdos_mode(fsp);
    5250       24659 :         psbuf = &smb_fname->st;
    5251             : 
    5252       24659 :         nlink = psbuf->st_ex_nlink;
    5253             : 
    5254       24659 :         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
    5255        3082 :                 nlink = 1;
    5256             :         }
    5257             : 
    5258       24659 :         if ((nlink > 0) && delete_pending) {
    5259         233 :                 nlink -= 1;
    5260             :         }
    5261             : 
    5262       24659 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    5263           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5264             :         }
    5265             : 
    5266       24659 :         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
    5267       24659 :         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
    5268       24659 :         if (*ppdata == NULL) {
    5269           0 :                 return NT_STATUS_NO_MEMORY;
    5270             :         }
    5271       24659 :         pdata = *ppdata;
    5272       24659 :         dstart = pdata;
    5273       24659 :         dend = dstart + data_size - 1;
    5274             : 
    5275       24659 :         if (!is_omit_timespec(&write_time_ts) &&
    5276       12517 :             !INFO_LEVEL_IS_UNIX(info_level))
    5277             :         {
    5278       16618 :                 update_stat_ex_mtime(psbuf, write_time_ts);
    5279             :         }
    5280             : 
    5281       24659 :         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
    5282       24659 :         mtime_ts = psbuf->st_ex_mtime;
    5283       24659 :         atime_ts = psbuf->st_ex_atime;
    5284       24659 :         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
    5285             : 
    5286       24659 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    5287           0 :                 dos_filetime_timespec(&create_time_ts);
    5288           0 :                 dos_filetime_timespec(&mtime_ts);
    5289           0 :                 dos_filetime_timespec(&atime_ts);
    5290           0 :                 dos_filetime_timespec(&ctime_ts);
    5291             :         }
    5292             : 
    5293       24659 :         create_time = convert_timespec_to_time_t(create_time_ts);
    5294       24659 :         mtime = convert_timespec_to_time_t(mtime_ts);
    5295       24659 :         atime = convert_timespec_to_time_t(atime_ts);
    5296       24659 :         c_time = convert_timespec_to_time_t(ctime_ts);
    5297             : 
    5298       24659 :         p = strrchr_m(smb_fname->base_name,'/');
    5299       24659 :         if (!p)
    5300       12008 :                 base_name = smb_fname->base_name;
    5301             :         else
    5302       12651 :                 base_name = p+1;
    5303             : 
    5304             :         /* NT expects the name to be in an exact form of the *full*
    5305             :            filename. See the trans2 torture test */
    5306       24659 :         if (ISDOT(base_name)) {
    5307         208 :                 dos_fname = talloc_strdup(mem_ctx, "\\");
    5308         416 :                 if (!dos_fname) {
    5309           0 :                         return NT_STATUS_NO_MEMORY;
    5310             :                 }
    5311             :         } else {
    5312       24451 :                 dos_fname = talloc_asprintf(mem_ctx,
    5313             :                                 "\\%s",
    5314             :                                 smb_fname->base_name);
    5315       24451 :                 if (!dos_fname) {
    5316           0 :                         return NT_STATUS_NO_MEMORY;
    5317             :                 }
    5318       24451 :                 if (is_ntfs_stream_smb_fname(smb_fname)) {
    5319         512 :                         dos_fname = talloc_asprintf(dos_fname, "%s",
    5320             :                                                     smb_fname->stream_name);
    5321         512 :                         if (!dos_fname) {
    5322           0 :                                 return NT_STATUS_NO_MEMORY;
    5323             :                         }
    5324             :                 }
    5325             : 
    5326       24451 :                 string_replace(dos_fname, '/', '\\');
    5327             :         }
    5328             : 
    5329       24659 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
    5330             : 
    5331       24659 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    5332             :                 /* Do we have this path open ? */
    5333             :                 files_struct *fsp1;
    5334        8522 :                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
    5335        8522 :                 fsp1 = file_find_di_first(conn->sconn, fileid, true);
    5336        8522 :                 if (fsp1 && fsp1->initial_allocation_size) {
    5337         105 :                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
    5338             :                 }
    5339             :         }
    5340             : 
    5341       24659 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    5342       21577 :                 file_size = get_file_size_stat(psbuf);
    5343             :         }
    5344             : 
    5345       24659 :         if (fsp) {
    5346       24391 :                 pos = fh_get_position_information(fsp->fh);
    5347             :         }
    5348             : 
    5349       24659 :         if (fsp) {
    5350       24391 :                 access_mask = fsp->access_mask;
    5351             :         } else {
    5352             :                 /* GENERIC_EXECUTE mapping from Windows */
    5353         268 :                 access_mask = 0x12019F;
    5354             :         }
    5355             : 
    5356             :         /* This should be an index number - looks like
    5357             :            dev/ino to me :-)
    5358             : 
    5359             :            I think this causes us to fail the IFSKIT
    5360             :            BasicFileInformationTest. -tpot */
    5361       24659 :         file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
    5362             : 
    5363       24659 :         *fixed_portion = 0;
    5364             : 
    5365       24659 :         switch (info_level) {
    5366         411 :                 case SMB_INFO_STANDARD:
    5367         411 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
    5368         411 :                         data_size = 22;
    5369         411 :                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
    5370         411 :                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
    5371         411 :                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
    5372         411 :                         SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
    5373         411 :                         SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
    5374         411 :                         SSVAL(pdata,l1_attrFile,mode);
    5375         411 :                         break;
    5376             : 
    5377           8 :                 case SMB_INFO_QUERY_EA_SIZE:
    5378             :                 {
    5379           8 :                         unsigned int ea_size =
    5380           8 :                             estimate_ea_size(smb_fname->fsp);
    5381           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
    5382           8 :                         data_size = 26;
    5383           8 :                         srv_put_dos_date2(pdata,0,create_time);
    5384           8 :                         srv_put_dos_date2(pdata,4,atime);
    5385           8 :                         srv_put_dos_date2(pdata,8,mtime); /* write time */
    5386           8 :                         SIVAL(pdata,12,(uint32_t)file_size);
    5387           8 :                         SIVAL(pdata,16,(uint32_t)allocation_size);
    5388           8 :                         SSVAL(pdata,20,mode);
    5389           8 :                         SIVAL(pdata,22,ea_size);
    5390           8 :                         break;
    5391             :                 }
    5392             : 
    5393           8 :                 case SMB_INFO_IS_NAME_VALID:
    5394           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
    5395           8 :                         if (fsp) {
    5396             :                                 /* os/2 needs this ? really ?*/
    5397           0 :                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
    5398             :                         }
    5399             :                         /* This is only reached for qpathinfo */
    5400           8 :                         data_size = 0;
    5401           8 :                         break;
    5402             : 
    5403         152 :                 case SMB_INFO_QUERY_EAS_FROM_LIST:
    5404             :                 {
    5405         152 :                         size_t total_ea_len = 0;
    5406         152 :                         struct ea_list *ea_file_list = NULL;
    5407         152 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
    5408             : 
    5409         152 :                         status =
    5410             :                             get_ea_list_from_fsp(mem_ctx,
    5411         152 :                                                   smb_fname->fsp,
    5412             :                                                   &total_ea_len, &ea_file_list);
    5413         152 :                         if (!NT_STATUS_IS_OK(status)) {
    5414           4 :                                 return status;
    5415             :                         }
    5416             : 
    5417         148 :                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
    5418             : 
    5419         148 :                         if (!ea_list || (total_ea_len > data_size)) {
    5420           0 :                                 data_size = 4;
    5421           0 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    5422         148 :                                 break;
    5423             :                         }
    5424             : 
    5425         148 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    5426         148 :                         break;
    5427             :                 }
    5428             : 
    5429          20 :                 case SMB_INFO_QUERY_ALL_EAS:
    5430             :                 {
    5431             :                         /* We have data_size bytes to put EA's into. */
    5432          20 :                         size_t total_ea_len = 0;
    5433          20 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
    5434             : 
    5435          20 :                         status = get_ea_list_from_fsp(mem_ctx,
    5436          20 :                                                         smb_fname->fsp,
    5437             :                                                         &total_ea_len, &ea_list);
    5438          20 :                         if (!NT_STATUS_IS_OK(status)) {
    5439           4 :                                 return status;
    5440             :                         }
    5441             : 
    5442          16 :                         if (!ea_list || (total_ea_len > data_size)) {
    5443          12 :                                 data_size = 4;
    5444          12 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    5445          28 :                                 break;
    5446             :                         }
    5447             : 
    5448           4 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    5449           4 :                         break;
    5450             :                 }
    5451             : 
    5452           8 :                 case SMB2_FILE_FULL_EA_INFORMATION:
    5453             :                 {
    5454             :                         /* We have data_size bytes to put EA's into. */
    5455           8 :                         size_t total_ea_len = 0;
    5456           8 :                         struct ea_list *ea_file_list = NULL;
    5457             : 
    5458           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
    5459             : 
    5460             :                         /*TODO: add filtering and index handling */
    5461             : 
    5462           8 :                         status  =
    5463             :                                 get_ea_list_from_fsp(mem_ctx,
    5464           8 :                                                   smb_fname->fsp,
    5465             :                                                   &total_ea_len, &ea_file_list);
    5466           8 :                         if (!NT_STATUS_IS_OK(status)) {
    5467           8 :                                 return status;
    5468             :                         }
    5469           8 :                         if (!ea_file_list) {
    5470           8 :                                 return NT_STATUS_NO_EAS_ON_FILE;
    5471             :                         }
    5472             : 
    5473           0 :                         status = fill_ea_chained_buffer(mem_ctx,
    5474             :                                                         pdata,
    5475             :                                                         data_size,
    5476             :                                                         &data_size,
    5477             :                                                         conn, ea_file_list);
    5478           0 :                         if (!NT_STATUS_IS_OK(status)) {
    5479           0 :                                 return status;
    5480             :                         }
    5481           0 :                         break;
    5482             :                 }
    5483             : 
    5484        4671 :                 case SMB_FILE_BASIC_INFORMATION:
    5485             :                 case SMB_QUERY_FILE_BASIC_INFO:
    5486             : 
    5487        4671 :                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
    5488        4281 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
    5489        4281 :                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
    5490             :                         } else {
    5491         390 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
    5492         390 :                                 data_size = 40;
    5493         390 :                                 SIVAL(pdata,36,0);
    5494             :                         }
    5495        4671 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    5496        4671 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    5497        4671 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    5498        4671 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    5499        4671 :                         SIVAL(pdata,32,mode);
    5500             : 
    5501        4671 :                         DEBUG(5,("SMB_QFBI - "));
    5502        4671 :                         DEBUG(5,("create: %s ", ctime(&create_time)));
    5503        4671 :                         DEBUG(5,("access: %s ", ctime(&atime)));
    5504        4671 :                         DEBUG(5,("write: %s ", ctime(&mtime)));
    5505        4671 :                         DEBUG(5,("change: %s ", ctime(&c_time)));
    5506        4671 :                         DEBUG(5,("mode: %x\n", mode));
    5507        4671 :                         *fixed_portion = data_size;
    5508        4671 :                         break;
    5509             : 
    5510        2651 :                 case SMB_FILE_STANDARD_INFORMATION:
    5511             :                 case SMB_QUERY_FILE_STANDARD_INFO:
    5512             : 
    5513        2651 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
    5514        2651 :                         data_size = 24;
    5515        2651 :                         SOFF_T(pdata,0,allocation_size);
    5516        2651 :                         SOFF_T(pdata,8,file_size);
    5517        2651 :                         SIVAL(pdata,16,nlink);
    5518        2651 :                         SCVAL(pdata,20,delete_pending?1:0);
    5519        2651 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    5520        2651 :                         SSVAL(pdata,22,0); /* Padding. */
    5521        2651 :                         *fixed_portion = 24;
    5522        2651 :                         break;
    5523             : 
    5524          32 :                 case SMB_FILE_EA_INFORMATION:
    5525             :                 case SMB_QUERY_FILE_EA_INFO:
    5526             :                 {
    5527          32 :                         unsigned int ea_size =
    5528          32 :                             estimate_ea_size(smb_fname->fsp);
    5529          32 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
    5530          32 :                         data_size = 4;
    5531          32 :                         *fixed_portion = 4;
    5532          32 :                         SIVAL(pdata,0,ea_size);
    5533          32 :                         break;
    5534             :                 }
    5535             : 
    5536             :                 /* Get the 8.3 name - used if NT SMB was negotiated. */
    5537        1716 :                 case SMB_QUERY_FILE_ALT_NAME_INFO:
    5538             :                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
    5539             :                 {
    5540             :                         char mangled_name[13];
    5541        1716 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
    5542        1716 :                         if (!name_to_8_3(base_name,mangled_name,
    5543        1716 :                                                 True,conn->params)) {
    5544           0 :                                 return NT_STATUS_NO_MEMORY;
    5545             :                         }
    5546        1716 :                         status = srvstr_push(dstart, flags2,
    5547             :                                           pdata+4, mangled_name,
    5548             :                                           PTR_DIFF(dend, pdata+4),
    5549             :                                           STR_UNICODE, &len);
    5550        1716 :                         if (!NT_STATUS_IS_OK(status)) {
    5551           0 :                                 return status;
    5552             :                         }
    5553        1716 :                         data_size = 4 + len;
    5554        1716 :                         SIVAL(pdata,0,len);
    5555        1716 :                         *fixed_portion = 8;
    5556        1716 :                         break;
    5557             :                 }
    5558             : 
    5559         151 :                 case SMB_QUERY_FILE_NAME_INFO:
    5560             :                 {
    5561             :                         /*
    5562             :                           this must be *exactly* right for ACLs on mapped drives to work
    5563             :                          */
    5564         151 :                         status = srvstr_push(dstart, flags2,
    5565             :                                           pdata+4, dos_fname,
    5566             :                                           PTR_DIFF(dend, pdata+4),
    5567             :                                           STR_UNICODE, &len);
    5568         151 :                         if (!NT_STATUS_IS_OK(status)) {
    5569           0 :                                 return status;
    5570             :                         }
    5571         151 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
    5572         151 :                         data_size = 4 + len;
    5573         151 :                         SIVAL(pdata,0,len);
    5574         151 :                         break;
    5575             :                 }
    5576             : 
    5577          96 :                 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
    5578             :                 {
    5579          96 :                         char *nfname = NULL;
    5580             : 
    5581          96 :                         if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
    5582           8 :                                 return NT_STATUS_INVALID_LEVEL;
    5583             :                         }
    5584             : 
    5585          88 :                         nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
    5586          88 :                         if (nfname == NULL) {
    5587           0 :                                 return NT_STATUS_NO_MEMORY;
    5588             :                         }
    5589             : 
    5590          88 :                         if (ISDOT(nfname)) {
    5591           4 :                                 nfname[0] = '\0';
    5592             :                         }
    5593          88 :                         string_replace(nfname, '/', '\\');
    5594             : 
    5595          88 :                         if (smb_fname->stream_name != NULL) {
    5596          32 :                                 const char *s = smb_fname->stream_name;
    5597          32 :                                 const char *e = NULL;
    5598             :                                 size_t n;
    5599             : 
    5600          32 :                                 SMB_ASSERT(s[0] != '\0');
    5601             : 
    5602             :                                 /*
    5603             :                                  * smb_fname->stream_name is in form
    5604             :                                  * of ':StrEam:$DATA', but we should only
    5605             :                                  * append ':StrEam' here.
    5606             :                                  */
    5607             : 
    5608          32 :                                 e = strchr(&s[1], ':');
    5609          32 :                                 if (e == NULL) {
    5610           8 :                                         n = strlen(s);
    5611             :                                 } else {
    5612          24 :                                         n = PTR_DIFF(e, s);
    5613             :                                 }
    5614          32 :                                 nfname = talloc_strndup_append(nfname, s, n);
    5615          32 :                                 if (nfname == NULL) {
    5616           0 :                                         return NT_STATUS_NO_MEMORY;
    5617             :                                 }
    5618             :                         }
    5619             : 
    5620          88 :                         status = srvstr_push(dstart, flags2,
    5621             :                                           pdata+4, nfname,
    5622             :                                           PTR_DIFF(dend, pdata+4),
    5623             :                                           STR_UNICODE, &len);
    5624          88 :                         if (!NT_STATUS_IS_OK(status)) {
    5625           0 :                                 return status;
    5626             :                         }
    5627          88 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
    5628          88 :                         data_size = 4 + len;
    5629          88 :                         SIVAL(pdata,0,len);
    5630          88 :                         *fixed_portion = 8;
    5631          88 :                         break;
    5632             :                 }
    5633             : 
    5634           8 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    5635             :                 case SMB_QUERY_FILE_ALLOCATION_INFO:
    5636           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
    5637           8 :                         data_size = 8;
    5638           8 :                         SOFF_T(pdata,0,allocation_size);
    5639           8 :                         break;
    5640             : 
    5641           8 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    5642             :                 case SMB_QUERY_FILE_END_OF_FILEINFO:
    5643           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
    5644           8 :                         data_size = 8;
    5645           8 :                         SOFF_T(pdata,0,file_size);
    5646           8 :                         break;
    5647             : 
    5648        1884 :                 case SMB_QUERY_FILE_ALL_INFO:
    5649             :                 case SMB_FILE_ALL_INFORMATION:
    5650             :                 {
    5651        1884 :                         unsigned int ea_size =
    5652        1884 :                             estimate_ea_size(smb_fname->fsp);
    5653        1884 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
    5654        1884 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    5655        1884 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    5656        1884 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    5657        1884 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    5658        1884 :                         SIVAL(pdata,32,mode);
    5659        1884 :                         SIVAL(pdata,36,0); /* padding. */
    5660        1884 :                         pdata += 40;
    5661        1884 :                         SOFF_T(pdata,0,allocation_size);
    5662        1884 :                         SOFF_T(pdata,8,file_size);
    5663        1884 :                         SIVAL(pdata,16,nlink);
    5664        1884 :                         SCVAL(pdata,20,delete_pending);
    5665        1884 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    5666        1884 :                         SSVAL(pdata,22,0);
    5667        1884 :                         pdata += 24;
    5668        1884 :                         SIVAL(pdata,0,ea_size);
    5669        1884 :                         pdata += 4; /* EA info */
    5670        1884 :                         status = srvstr_push(dstart, flags2,
    5671             :                                           pdata+4, dos_fname,
    5672             :                                           PTR_DIFF(dend, pdata+4),
    5673             :                                           STR_UNICODE, &len);
    5674        1884 :                         if (!NT_STATUS_IS_OK(status)) {
    5675           0 :                                 return status;
    5676             :                         }
    5677        1884 :                         SIVAL(pdata,0,len);
    5678        1884 :                         pdata += 4 + len;
    5679        1884 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    5680        1884 :                         *fixed_portion = 10;
    5681        1884 :                         break;
    5682             :                 }
    5683             : 
    5684        5608 :                 case SMB2_FILE_ALL_INFORMATION:
    5685             :                 {
    5686        5608 :                         unsigned int ea_size =
    5687        5608 :                             estimate_ea_size(smb_fname->fsp);
    5688        5608 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
    5689        5608 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
    5690        5608 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
    5691        5608 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
    5692        5608 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
    5693        5608 :                         SIVAL(pdata,    0x20, mode);
    5694        5608 :                         SIVAL(pdata,    0x24, 0); /* padding. */
    5695        5608 :                         SBVAL(pdata,    0x28, allocation_size);
    5696        5608 :                         SBVAL(pdata,    0x30, file_size);
    5697        5608 :                         SIVAL(pdata,    0x38, nlink);
    5698        5608 :                         SCVAL(pdata,    0x3C, delete_pending);
    5699        5608 :                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    5700        5608 :                         SSVAL(pdata,    0x3E, 0); /* padding */
    5701        5608 :                         SBVAL(pdata,    0x40, file_id);
    5702        5608 :                         SIVAL(pdata,    0x48, ea_size);
    5703        5608 :                         SIVAL(pdata,    0x4C, access_mask);
    5704        5608 :                         SBVAL(pdata,    0x50, pos);
    5705        5608 :                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
    5706        5608 :                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
    5707             : 
    5708        5608 :                         pdata += 0x60;
    5709             : 
    5710        5608 :                         status = srvstr_push(dstart, flags2,
    5711             :                                           pdata+4, dos_fname,
    5712             :                                           PTR_DIFF(dend, pdata+4),
    5713             :                                           STR_UNICODE, &len);
    5714        5608 :                         if (!NT_STATUS_IS_OK(status)) {
    5715           0 :                                 return status;
    5716             :                         }
    5717        5608 :                         SIVAL(pdata,0,len);
    5718        5608 :                         pdata += 4 + len;
    5719        5608 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    5720        5608 :                         *fixed_portion = 104;
    5721        5608 :                         break;
    5722             :                 }
    5723          54 :                 case SMB_FILE_INTERNAL_INFORMATION:
    5724             : 
    5725          54 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
    5726          54 :                         SBVAL(pdata, 0, file_id);
    5727          54 :                         data_size = 8;
    5728          54 :                         *fixed_portion = 8;
    5729          54 :                         break;
    5730             : 
    5731        1052 :                 case SMB_FILE_ACCESS_INFORMATION:
    5732        1052 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
    5733        1052 :                         SIVAL(pdata, 0, access_mask);
    5734        1052 :                         data_size = 4;
    5735        1052 :                         *fixed_portion = 4;
    5736        1052 :                         break;
    5737             : 
    5738           8 :                 case SMB_FILE_NAME_INFORMATION:
    5739             :                         /* Pathname with leading '\'. */
    5740             :                         {
    5741             :                                 size_t byte_len;
    5742           8 :                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
    5743           8 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
    5744           8 :                                 SIVAL(pdata,0,byte_len);
    5745           8 :                                 data_size = 4 + byte_len;
    5746           8 :                                 break;
    5747             :                         }
    5748             : 
    5749           8 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    5750           8 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
    5751           8 :                         data_size = 1;
    5752           8 :                         SCVAL(pdata,0,delete_pending);
    5753           8 :                         *fixed_portion = 1;
    5754           8 :                         break;
    5755             : 
    5756        1813 :                 case SMB_FILE_POSITION_INFORMATION:
    5757        1813 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
    5758        1813 :                         data_size = 8;
    5759        1813 :                         SOFF_T(pdata,0,pos);
    5760        1813 :                         *fixed_portion = 8;
    5761        1813 :                         break;
    5762             : 
    5763          32 :                 case SMB_FILE_MODE_INFORMATION:
    5764          32 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
    5765          32 :                         SIVAL(pdata,0,mode);
    5766          32 :                         data_size = 4;
    5767          32 :                         *fixed_portion = 4;
    5768          32 :                         break;
    5769             : 
    5770          32 :                 case SMB_FILE_ALIGNMENT_INFORMATION:
    5771          32 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
    5772          32 :                         SIVAL(pdata,0,0); /* No alignment needed. */
    5773          32 :                         data_size = 4;
    5774          32 :                         *fixed_portion = 4;
    5775          32 :                         break;
    5776             : 
    5777             :                 /*
    5778             :                  * NT4 server just returns "invalid query" to this - if we try
    5779             :                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
    5780             :                  * want this. JRA.
    5781             :                  */
    5782             :                 /* The first statement above is false - verified using Thursby
    5783             :                  * client against NT4 -- gcolley.
    5784             :                  */
    5785        3648 :                 case SMB_QUERY_FILE_STREAM_INFO:
    5786             :                 case SMB_FILE_STREAM_INFORMATION: {
    5787        3648 :                         unsigned int num_streams = 0;
    5788        3648 :                         struct stream_struct *streams = NULL;
    5789             : 
    5790        3648 :                         DEBUG(10,("smbd_do_qfilepathinfo: "
    5791             :                                   "SMB_FILE_STREAM_INFORMATION\n"));
    5792             : 
    5793        3648 :                         if (is_ntfs_stream_smb_fname(smb_fname)) {
    5794         280 :                                 return NT_STATUS_INVALID_PARAMETER;
    5795             :                         }
    5796             : 
    5797        3584 :                         status = vfs_fstreaminfo(fsp,
    5798             :                                                 mem_ctx,
    5799             :                                                 &num_streams,
    5800             :                                                 &streams);
    5801             : 
    5802        3584 :                         if (!NT_STATUS_IS_OK(status)) {
    5803           0 :                                 DEBUG(10, ("could not get stream info: %s\n",
    5804             :                                            nt_errstr(status)));
    5805           0 :                                 return status;
    5806             :                         }
    5807             : 
    5808        3584 :                         status = marshall_stream_info(num_streams, streams,
    5809             :                                                       pdata, max_data_bytes,
    5810             :                                                       &data_size);
    5811             : 
    5812        3584 :                         if (!NT_STATUS_IS_OK(status)) {
    5813         152 :                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
    5814             :                                            nt_errstr(status)));
    5815         152 :                                 TALLOC_FREE(streams);
    5816         152 :                                 return status;
    5817             :                         }
    5818             : 
    5819        3432 :                         TALLOC_FREE(streams);
    5820             : 
    5821        3432 :                         *fixed_portion = 32;
    5822             : 
    5823        3432 :                         break;
    5824             :                 }
    5825          80 :                 case SMB_QUERY_COMPRESSION_INFO:
    5826             :                 case SMB_FILE_COMPRESSION_INFORMATION:
    5827          80 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
    5828          80 :                         SOFF_T(pdata,0,file_size);
    5829          80 :                         SIVAL(pdata,8,0); /* ??? */
    5830          80 :                         SIVAL(pdata,12,0); /* ??? */
    5831          80 :                         data_size = 16;
    5832          80 :                         *fixed_portion = 16;
    5833          80 :                         break;
    5834             : 
    5835         240 :                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
    5836         240 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
    5837         240 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    5838         240 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    5839         240 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    5840         240 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    5841         240 :                         SOFF_T(pdata,32,allocation_size);
    5842         240 :                         SOFF_T(pdata,40,file_size);
    5843         240 :                         SIVAL(pdata,48,mode);
    5844         240 :                         SIVAL(pdata,52,0); /* ??? */
    5845         240 :                         data_size = 56;
    5846         240 :                         *fixed_portion = 56;
    5847         240 :                         break;
    5848             : 
    5849          48 :                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
    5850          48 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
    5851          48 :                         SIVAL(pdata,0,mode);
    5852          48 :                         SIVAL(pdata,4,0);
    5853          48 :                         data_size = 8;
    5854          48 :                         *fixed_portion = 8;
    5855          48 :                         break;
    5856             : 
    5857             :                 /*
    5858             :                  * CIFS UNIX Extensions.
    5859             :                  */
    5860             : 
    5861          88 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    5862             : 
    5863          88 :                         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
    5864          88 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    5865             : 
    5866          88 :                         DEBUG(4,("smbd_do_qfilepathinfo: "
    5867             :                                  "SMB_QUERY_FILE_UNIX_BASIC\n"));
    5868          88 :                         dump_data(4, (uint8_t *)(*ppdata), data_size);
    5869             : 
    5870          88 :                         break;
    5871             : 
    5872          20 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    5873             : 
    5874          20 :                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
    5875          20 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    5876             : 
    5877             :                         {
    5878             :                                 int i;
    5879          20 :                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
    5880             : 
    5881        2020 :                                 for (i=0; i<100; i++)
    5882        2000 :                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
    5883          20 :                                 DEBUG(4,("\n"));
    5884             :                         }
    5885             : 
    5886          20 :                         break;
    5887             : 
    5888          24 :                 case SMB_QUERY_FILE_UNIX_LINK:
    5889             :                         {
    5890          24 :                                 status = smb_unix_read_symlink(conn,
    5891             :                                                         req,
    5892             :                                                         smb_fname,
    5893             :                                                         pdata,
    5894             :                                                         data_size,
    5895             :                                                         &data_size);
    5896          24 :                                 if (!NT_STATUS_IS_OK(status)) {
    5897           0 :                                         return status;
    5898             :                                 }
    5899          24 :                                 break;
    5900             :                         }
    5901             : 
    5902             : #if defined(HAVE_POSIX_ACLS)
    5903          80 :                 case SMB_QUERY_POSIX_ACL:
    5904             :                         {
    5905          80 :                                 status = smb_query_posix_acl(conn,
    5906             :                                                         req,
    5907             :                                                         fsp,
    5908             :                                                         smb_fname,
    5909             :                                                         pdata,
    5910             :                                                         data_size,
    5911             :                                                         &data_size);
    5912          80 :                                 if (!NT_STATUS_IS_OK(status)) {
    5913          16 :                                         return status;
    5914             :                                 }
    5915          64 :                                 break;
    5916             :                         }
    5917             : #endif
    5918             : 
    5919             : 
    5920           0 :                 case SMB_QUERY_POSIX_LOCK:
    5921             :                 {
    5922             :                         uint64_t count;
    5923             :                         uint64_t offset;
    5924             :                         uint64_t smblctx;
    5925             :                         enum brl_type lock_type;
    5926             : 
    5927             :                         /* We need an open file with a real fd for this. */
    5928           0 :                         if (fsp == NULL ||
    5929           0 :                             fsp->fsp_flags.is_pathref ||
    5930           0 :                             fsp_get_io_fd(fsp) == -1)
    5931             :                         {
    5932           0 :                                 return NT_STATUS_INVALID_LEVEL;
    5933             :                         }
    5934             : 
    5935           0 :                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
    5936           0 :                                 return NT_STATUS_INVALID_PARAMETER;
    5937             :                         }
    5938             : 
    5939           0 :                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
    5940           0 :                                 case POSIX_LOCK_TYPE_READ:
    5941           0 :                                         lock_type = READ_LOCK;
    5942           0 :                                         break;
    5943           0 :                                 case POSIX_LOCK_TYPE_WRITE:
    5944           0 :                                         lock_type = WRITE_LOCK;
    5945           0 :                                         break;
    5946           0 :                                 case POSIX_LOCK_TYPE_UNLOCK:
    5947             :                                 default:
    5948             :                                         /* There's no point in asking for an unlock... */
    5949           0 :                                         return NT_STATUS_INVALID_PARAMETER;
    5950             :                         }
    5951             : 
    5952           0 :                         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
    5953           0 :                         offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
    5954           0 :                         count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
    5955             : 
    5956           0 :                         status = query_lock(fsp,
    5957             :                                         &smblctx,
    5958             :                                         &count,
    5959             :                                         &offset,
    5960             :                                         &lock_type,
    5961             :                                         POSIX_LOCK);
    5962             : 
    5963           0 :                         if (ERROR_WAS_LOCK_DENIED(status)) {
    5964             :                                 /* Here we need to report who has it locked... */
    5965           0 :                                 data_size = POSIX_LOCK_DATA_SIZE;
    5966             : 
    5967           0 :                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
    5968           0 :                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
    5969           0 :                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
    5970           0 :                                 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
    5971           0 :                                 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
    5972             : 
    5973           0 :                         } else if (NT_STATUS_IS_OK(status)) {
    5974             :                                 /* For success we just return a copy of what we sent
    5975             :                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
    5976           0 :                                 data_size = POSIX_LOCK_DATA_SIZE;
    5977           0 :                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
    5978           0 :                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
    5979             :                         } else {
    5980           0 :                                 return status;
    5981             :                         }
    5982           0 :                         break;
    5983             :                 }
    5984             : 
    5985           0 :                 default:
    5986           0 :                         return NT_STATUS_INVALID_LEVEL;
    5987             :         }
    5988             : 
    5989       24403 :         *pdata_size = data_size;
    5990       24403 :         return NT_STATUS_OK;
    5991             : }
    5992             : 
    5993             : /****************************************************************************
    5994             :  Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
    5995             :  file name or file id).
    5996             : ****************************************************************************/
    5997             : 
    5998       13536 : static void call_trans2qfilepathinfo(connection_struct *conn,
    5999             :                                      struct smb_request *req,
    6000             :                                      unsigned int tran_call,
    6001             :                                      char **pparams, int total_params,
    6002             :                                      char **ppdata, int total_data,
    6003             :                                      unsigned int max_data_bytes)
    6004             : {
    6005       13536 :         char *params = *pparams;
    6006       13536 :         char *pdata = *ppdata;
    6007             :         uint16_t info_level;
    6008       13536 :         unsigned int data_size = 0;
    6009       13536 :         unsigned int param_size = 2;
    6010       13536 :         struct smb_filename *smb_fname = NULL;
    6011       13536 :         bool delete_pending = False;
    6012             :         struct timespec write_time_ts;
    6013       13536 :         files_struct *fsp = NULL;
    6014             :         struct file_id fileid;
    6015       13536 :         struct ea_list *ea_list = NULL;
    6016       13536 :         int lock_data_count = 0;
    6017       13536 :         char *lock_data = NULL;
    6018             :         size_t fixed_portion;
    6019       13536 :         NTSTATUS status = NT_STATUS_OK;
    6020             : 
    6021       13536 :         if (!params) {
    6022           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6023           0 :                 return;
    6024             :         }
    6025             : 
    6026       13536 :         ZERO_STRUCT(write_time_ts);
    6027             : 
    6028       13536 :         if (tran_call == TRANSACT2_QFILEINFO) {
    6029        3523 :                 if (total_params < 4) {
    6030           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6031           0 :                         return;
    6032             :                 }
    6033             : 
    6034        3523 :                 if (IS_IPC(conn)) {
    6035           0 :                         call_trans2qpipeinfo(conn, req, tran_call,
    6036             :                                              pparams, total_params,
    6037             :                                              ppdata, total_data,
    6038             :                                              max_data_bytes);
    6039           0 :                         return;
    6040             :                 }
    6041             : 
    6042        3523 :                 fsp = file_fsp(req, SVAL(params,0));
    6043        3523 :                 info_level = SVAL(params,2);
    6044             : 
    6045        3523 :                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
    6046             : 
    6047        3523 :                 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
    6048           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    6049           0 :                         return;
    6050             :                 }
    6051             : 
    6052             :                 /* Initial check for valid fsp ptr. */
    6053        3523 :                 if (!check_fsp_open(conn, req, fsp)) {
    6054         144 :                         return;
    6055             :                 }
    6056             : 
    6057        3379 :                 smb_fname = fsp->fsp_name;
    6058             : 
    6059        3379 :                 if(fsp->fake_file_handle) {
    6060             :                         /*
    6061             :                          * This is actually for the QUOTA_FAKE_FILE --metze
    6062             :                          */
    6063             : 
    6064             :                         /* We know this name is ok, it's already passed the checks. */
    6065             : 
    6066        3379 :                 } else if(fsp_get_pathref_fd(fsp) == -1) {
    6067             :                         /*
    6068             :                          * This is actually a QFILEINFO on a directory
    6069             :                          * handle (returned from an NT SMB). NT5.0 seems
    6070             :                          * to do this call. JRA.
    6071             :                          */
    6072             : 
    6073           0 :                         if (INFO_LEVEL_IS_UNIX(info_level)) {
    6074             :                                 /* Always do lstat for UNIX calls. */
    6075           0 :                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
    6076           0 :                                         DEBUG(3,("call_trans2qfilepathinfo: "
    6077             :                                                  "SMB_VFS_LSTAT of %s failed "
    6078             :                                                  "(%s)\n",
    6079             :                                                  smb_fname_str_dbg(smb_fname),
    6080             :                                                  strerror(errno)));
    6081           0 :                                         reply_nterror(req,
    6082             :                                                 map_nt_error_from_unix(errno));
    6083           0 :                                         return;
    6084             :                                 }
    6085           0 :                         } else if (SMB_VFS_STAT(conn, smb_fname)) {
    6086           0 :                                 DEBUG(3,("call_trans2qfilepathinfo: "
    6087             :                                          "SMB_VFS_STAT of %s failed (%s)\n",
    6088             :                                          smb_fname_str_dbg(smb_fname),
    6089             :                                          strerror(errno)));
    6090           0 :                                 reply_nterror(req,
    6091             :                                         map_nt_error_from_unix(errno));
    6092           0 :                                 return;
    6093             :                         }
    6094             : 
    6095           0 :                         if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
    6096           0 :                                 fileid = vfs_file_id_from_sbuf(
    6097           0 :                                         conn, &smb_fname->st);
    6098           0 :                                 get_file_infos(fileid, fsp->name_hash,
    6099             :                                                &delete_pending,
    6100             :                                                &write_time_ts);
    6101             :                         }
    6102             :                 } else {
    6103             :                         /*
    6104             :                          * Original code - this is an open file.
    6105             :                          */
    6106        3379 :                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
    6107           0 :                                 DEBUG(3, ("fstat of %s failed (%s)\n",
    6108             :                                           fsp_fnum_dbg(fsp), strerror(errno)));
    6109           0 :                                 reply_nterror(req,
    6110             :                                         map_nt_error_from_unix(errno));
    6111           0 :                                 return;
    6112             :                         }
    6113        3379 :                         if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
    6114        3379 :                                 fileid = vfs_file_id_from_sbuf(
    6115        3379 :                                         conn, &smb_fname->st);
    6116        3379 :                                 get_file_infos(fileid, fsp->name_hash,
    6117             :                                                &delete_pending,
    6118             :                                                &write_time_ts);
    6119             :                         }
    6120             :                 }
    6121             : 
    6122             :         } else {
    6123             :                 uint32_t name_hash;
    6124       10013 :                 char *fname = NULL;
    6125       10013 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    6126             : 
    6127             :                 /* qpathinfo */
    6128       10013 :                 if (total_params < 7) {
    6129           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    6130           0 :                         return;
    6131             :                 }
    6132             : 
    6133       10013 :                 info_level = SVAL(params,0);
    6134             : 
    6135       10013 :                 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
    6136             : 
    6137       10013 :                 if (INFO_LEVEL_IS_UNIX(info_level)) {
    6138         216 :                         if (!lp_unix_extensions()) {
    6139           0 :                                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    6140           0 :                                 return;
    6141             :                         }
    6142             :                 }
    6143             : 
    6144       10013 :                 if (req->posix_pathnames) {
    6145         640 :                         srvstr_get_path_posix(req,
    6146             :                                 params,
    6147         320 :                                 req->flags2,
    6148             :                                 &fname,
    6149         320 :                                 &params[6],
    6150         320 :                                 total_params - 6,
    6151             :                                 STR_TERMINATE,
    6152             :                                 &status);
    6153             :                 } else {
    6154       19386 :                         srvstr_get_path(req,
    6155             :                                 params,
    6156        9693 :                                 req->flags2,
    6157             :                                 &fname,
    6158        9693 :                                 &params[6],
    6159        9693 :                                 total_params - 6,
    6160             :                                 STR_TERMINATE,
    6161             :                                 &status);
    6162             :                 }
    6163       10013 :                 if (!NT_STATUS_IS_OK(status)) {
    6164         148 :                         reply_nterror(req, status);
    6165         148 :                         return;
    6166             :                 }
    6167             : 
    6168        9865 :                 status = filename_convert(req,
    6169             :                                         conn,
    6170             :                                         fname,
    6171             :                                         ucf_flags,
    6172             :                                         0,
    6173             :                                         &smb_fname);
    6174        9865 :                 if (!NT_STATUS_IS_OK(status)) {
    6175         792 :                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    6176          54 :                                 reply_botherror(req,
    6177             :                                                 NT_STATUS_PATH_NOT_COVERED,
    6178             :                                                 ERRSRV, ERRbadpath);
    6179          54 :                                 return;
    6180             :                         }
    6181         738 :                         reply_nterror(req, status);
    6182         738 :                         return;
    6183             :                 }
    6184             : 
    6185             :                 /*
    6186             :                  * smb_fname->fsp may be NULL if smb_fname points at a symlink
    6187             :                  * and we're in POSIX context, so be careful when using fsp
    6188             :                  * below, it can still be NULL.
    6189             :                  */
    6190        9073 :                 fsp = smb_fname->fsp;
    6191             : 
    6192             :                 /* If this is a stream, check if there is a delete_pending. */
    6193        9073 :                 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
    6194        4073 :                     && is_ntfs_stream_smb_fname(smb_fname)) {
    6195             :                         struct smb_filename *smb_fname_base;
    6196             : 
    6197             :                         /* Create an smb_filename with stream_name == NULL. */
    6198         192 :                         smb_fname_base = synthetic_smb_fname(
    6199             :                                                 talloc_tos(),
    6200          64 :                                                 smb_fname->base_name,
    6201             :                                                 NULL,
    6202             :                                                 NULL,
    6203          64 :                                                 smb_fname->twrp,
    6204          64 :                                                 smb_fname->flags);
    6205          64 :                         if (smb_fname_base == NULL) {
    6206           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    6207           0 :                                 return;
    6208             :                         }
    6209             : 
    6210          64 :                         if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
    6211             :                                 /* Always do lstat for UNIX calls. */
    6212           0 :                                 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
    6213           0 :                                         DEBUG(3,("call_trans2qfilepathinfo: "
    6214             :                                                  "SMB_VFS_LSTAT of %s failed "
    6215             :                                                  "(%s)\n",
    6216             :                                                  smb_fname_str_dbg(smb_fname_base),
    6217             :                                                  strerror(errno)));
    6218           0 :                                         TALLOC_FREE(smb_fname_base);
    6219           0 :                                         reply_nterror(req,
    6220             :                                                 map_nt_error_from_unix(errno));
    6221           0 :                                         return;
    6222             :                                 }
    6223             :                         } else {
    6224          64 :                                 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
    6225           0 :                                         DEBUG(3,("call_trans2qfilepathinfo: "
    6226             :                                                  "fileinfo of %s failed "
    6227             :                                                  "(%s)\n",
    6228             :                                                  smb_fname_str_dbg(smb_fname_base),
    6229             :                                                  strerror(errno)));
    6230           0 :                                         TALLOC_FREE(smb_fname_base);
    6231           0 :                                         reply_nterror(req,
    6232             :                                                 map_nt_error_from_unix(errno));
    6233           0 :                                         return;
    6234             :                                 }
    6235             :                         }
    6236             : 
    6237          64 :                         status = file_name_hash(conn,
    6238             :                                         smb_fname_str_dbg(smb_fname_base),
    6239             :                                         &name_hash);
    6240          64 :                         if (!NT_STATUS_IS_OK(status)) {
    6241           0 :                                 TALLOC_FREE(smb_fname_base);
    6242           0 :                                 reply_nterror(req, status);
    6243           0 :                                 return;
    6244             :                         }
    6245             : 
    6246          64 :                         fileid = vfs_file_id_from_sbuf(conn,
    6247          64 :                                                        &smb_fname_base->st);
    6248          64 :                         TALLOC_FREE(smb_fname_base);
    6249          64 :                         get_file_infos(fileid, name_hash, &delete_pending, NULL);
    6250          64 :                         if (delete_pending) {
    6251           4 :                                 reply_nterror(req, NT_STATUS_DELETE_PENDING);
    6252           4 :                                 return;
    6253             :                         }
    6254             :                 }
    6255             : 
    6256        9069 :                 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
    6257             :                         /* Always do lstat for UNIX calls. */
    6258         848 :                         if (SMB_VFS_LSTAT(conn, smb_fname)) {
    6259           0 :                                 DEBUG(3,("call_trans2qfilepathinfo: "
    6260             :                                          "SMB_VFS_LSTAT of %s failed (%s)\n",
    6261             :                                          smb_fname_str_dbg(smb_fname),
    6262             :                                          strerror(errno)));
    6263           0 :                                 reply_nterror(req,
    6264             :                                         map_nt_error_from_unix(errno));
    6265           0 :                                 return;
    6266             :                         }
    6267             : 
    6268             :                 } else {
    6269        8645 :                         if (SMB_VFS_STAT(conn, smb_fname) != 0) {
    6270         420 :                                 DEBUG(3,("call_trans2qfilepathinfo: "
    6271             :                                          "SMB_VFS_STAT of %s failed (%s)\n",
    6272             :                                          smb_fname_str_dbg(smb_fname),
    6273             :                                          strerror(errno)));
    6274         420 :                                 reply_nterror(req,
    6275             :                                         map_nt_error_from_unix(errno));
    6276         420 :                                 return;
    6277             :                         }
    6278             :                 }
    6279             : 
    6280        8649 :                 status = file_name_hash(conn,
    6281             :                                 smb_fname_str_dbg(smb_fname),
    6282             :                                 &name_hash);
    6283        8649 :                 if (!NT_STATUS_IS_OK(status)) {
    6284           0 :                         reply_nterror(req, status);
    6285           0 :                         return;
    6286             :                 }
    6287             : 
    6288        8649 :                 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
    6289        8649 :                         fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    6290        8649 :                         get_file_infos(fileid, name_hash, &delete_pending,
    6291             :                                        &write_time_ts);
    6292             :                 }
    6293             : 
    6294        8649 :                 if (delete_pending) {
    6295         119 :                         reply_nterror(req, NT_STATUS_DELETE_PENDING);
    6296         119 :                         return;
    6297             :                 }
    6298             :         }
    6299             : 
    6300       11909 :         DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
    6301             :                  "total_data=%d\n", smb_fname_str_dbg(smb_fname),
    6302             :                  fsp_fnum_dbg(fsp),
    6303             :                  info_level,tran_call,total_data));
    6304             : 
    6305             :         /* Pull out any data sent here before we realloc. */
    6306       11909 :         switch (info_level) {
    6307         152 :                 case SMB_INFO_QUERY_EAS_FROM_LIST:
    6308             :                 {
    6309             :                         /* Pull any EA list from the data portion. */
    6310             :                         uint32_t ea_size;
    6311             : 
    6312         152 :                         if (total_data < 4) {
    6313           0 :                                 reply_nterror(
    6314             :                                         req, NT_STATUS_INVALID_PARAMETER);
    6315           0 :                                 return;
    6316             :                         }
    6317         152 :                         ea_size = IVAL(pdata,0);
    6318             : 
    6319         152 :                         if (total_data > 0 && ea_size != total_data) {
    6320           0 :                                 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
    6321             : total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
    6322           0 :                                 reply_nterror(
    6323             :                                         req, NT_STATUS_INVALID_PARAMETER);
    6324           0 :                                 return;
    6325             :                         }
    6326             : 
    6327         152 :                         if (!lp_ea_support(SNUM(conn))) {
    6328           0 :                                 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    6329           0 :                                 return;
    6330             :                         }
    6331             : 
    6332             :                         /* Pull out the list of names. */
    6333         152 :                         ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
    6334         152 :                         if (!ea_list) {
    6335           0 :                                 reply_nterror(
    6336             :                                         req, NT_STATUS_INVALID_PARAMETER);
    6337           0 :                                 return;
    6338             :                         }
    6339         124 :                         break;
    6340             :                 }
    6341             : 
    6342           8 :                 case SMB_QUERY_POSIX_LOCK:
    6343             :                 {
    6344           8 :                         if (fsp == NULL ||
    6345           0 :                             fsp->fsp_flags.is_pathref ||
    6346           0 :                             fsp_get_io_fd(fsp) == -1)
    6347             :                         {
    6348           8 :                                 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
    6349           8 :                                 return;
    6350             :                         }
    6351             : 
    6352           0 :                         if (total_data != POSIX_LOCK_DATA_SIZE) {
    6353           0 :                                 reply_nterror(
    6354             :                                         req, NT_STATUS_INVALID_PARAMETER);
    6355           0 :                                 return;
    6356             :                         }
    6357             : 
    6358             :                         /* Copy the lock range data. */
    6359           0 :                         lock_data = (char *)talloc_memdup(
    6360             :                                 req, pdata, total_data);
    6361           0 :                         if (!lock_data) {
    6362           0 :                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    6363           0 :                                 return;
    6364             :                         }
    6365           0 :                         lock_data_count = total_data;
    6366           0 :                         break;
    6367             :                 }
    6368       11328 :                 default:
    6369       11328 :                         break;
    6370             :         }
    6371             : 
    6372       11901 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    6373       11901 :         if (*pparams == NULL) {
    6374           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    6375           0 :                 return;
    6376             :         }
    6377       11901 :         params = *pparams;
    6378       11901 :         SSVAL(params,0,0);
    6379             : 
    6380             :         /*
    6381             :          * draft-leach-cifs-v1-spec-02.txt
    6382             :          * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
    6383             :          * says:
    6384             :          *
    6385             :          *  The requested information is placed in the Data portion of the
    6386             :          *  transaction response. For the information levels greater than 0x100,
    6387             :          *  the transaction response has 1 parameter word which should be
    6388             :          *  ignored by the client.
    6389             :          *
    6390             :          * However Windows only follows this rule for the IS_NAME_VALID call.
    6391             :          */
    6392       11901 :         switch (info_level) {
    6393           8 :         case SMB_INFO_IS_NAME_VALID:
    6394           8 :                 param_size = 0;
    6395           8 :                 break;
    6396             :         }
    6397             : 
    6398       11901 :         if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
    6399             :                 /*
    6400             :                  * We use levels that start with 0xFF00
    6401             :                  * internally to represent SMB2 specific levels
    6402             :                  */
    6403           0 :                 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    6404           0 :                 return;
    6405             :         }
    6406             : 
    6407       11901 :         status = smbd_do_qfilepathinfo(conn, req, req, info_level,
    6408             :                                        fsp, smb_fname,
    6409             :                                        delete_pending, write_time_ts,
    6410             :                                        ea_list,
    6411             :                                        lock_data_count, lock_data,
    6412       11901 :                                        req->flags2, max_data_bytes,
    6413             :                                        &fixed_portion,
    6414             :                                        ppdata, &data_size);
    6415       11901 :         if (!NT_STATUS_IS_OK(status)) {
    6416          44 :                 if (open_was_deferred(req->xconn, req->mid)) {
    6417             :                         /* We have re-scheduled this call. */
    6418           4 :                         return;
    6419             :                 }
    6420          40 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    6421           0 :                         bool ok = defer_smb1_sharing_violation(req);
    6422           0 :                         if (ok) {
    6423           0 :                                 return;
    6424             :                         }
    6425             :                 }
    6426          40 :                 reply_nterror(req, status);
    6427          40 :                 return;
    6428             :         }
    6429       11857 :         if (fixed_portion > max_data_bytes) {
    6430           0 :                 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
    6431           0 :                 return;
    6432             :         }
    6433             : 
    6434       11857 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
    6435             :                             max_data_bytes);
    6436             : 
    6437       11857 :         return;
    6438             : }
    6439             : 
    6440             : /****************************************************************************
    6441             :  Set a hard link (called by UNIX extensions and by NT rename with HARD link
    6442             :  code.
    6443             : ****************************************************************************/
    6444             : 
    6445          29 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
    6446             :                 connection_struct *conn,
    6447             :                 struct smb_request *req,
    6448             :                 bool overwrite_if_exists,
    6449             :                 const struct smb_filename *smb_fname_old,
    6450             :                 struct smb_filename *smb_fname_new)
    6451             : {
    6452          29 :         NTSTATUS status = NT_STATUS_OK;
    6453             :         int ret;
    6454             :         bool ok;
    6455          29 :         struct smb_filename *parent_fname_old = NULL;
    6456          29 :         struct smb_filename *base_name_old = NULL;
    6457          29 :         struct smb_filename *parent_fname_new = NULL;
    6458          29 :         struct smb_filename *base_name_new = NULL;
    6459             : 
    6460             :         /* source must already exist. */
    6461          29 :         if (!VALID_STAT(smb_fname_old->st)) {
    6462           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    6463           0 :                 goto out;
    6464             :         }
    6465             : 
    6466             :         /* No links from a directory. */
    6467          29 :         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
    6468           8 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    6469           8 :                 goto out;
    6470             :         }
    6471             : 
    6472             :         /* Setting a hardlink to/from a stream isn't currently supported. */
    6473          21 :         ok = is_ntfs_stream_smb_fname(smb_fname_old);
    6474          21 :         if (ok) {
    6475           0 :                 DBG_DEBUG("Old name has streams\n");
    6476           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6477           0 :                 goto out;
    6478             :         }
    6479          21 :         ok = is_ntfs_stream_smb_fname(smb_fname_new);
    6480          21 :         if (ok) {
    6481           0 :                 DBG_DEBUG("New name has streams\n");
    6482           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    6483           0 :                 goto out;
    6484             :         }
    6485             : 
    6486          21 :         status = parent_pathref(talloc_tos(),
    6487             :                                 conn->cwd_fsp,
    6488             :                                 smb_fname_old,
    6489             :                                 &parent_fname_old,
    6490             :                                 &base_name_old);
    6491          21 :         if (!NT_STATUS_IS_OK(status)) {
    6492           0 :                 goto out;
    6493             :         }
    6494             : 
    6495          21 :         status = parent_pathref(talloc_tos(),
    6496             :                                 conn->cwd_fsp,
    6497             :                                 smb_fname_new,
    6498             :                                 &parent_fname_new,
    6499             :                                 &base_name_new);
    6500          21 :         if (!NT_STATUS_IS_OK(status)) {
    6501           0 :                 goto out;
    6502             :         }
    6503             : 
    6504          21 :         if (VALID_STAT(smb_fname_new->st)) {
    6505           0 :                 if (overwrite_if_exists) {
    6506           0 :                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
    6507           0 :                                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    6508           0 :                                 goto out;
    6509             :                         }
    6510           0 :                         status = unlink_internals(conn,
    6511             :                                                 req,
    6512             :                                                 FILE_ATTRIBUTE_NORMAL,
    6513             :                                                 smb_fname_new,
    6514             :                                                 false);
    6515           0 :                         if (!NT_STATUS_IS_OK(status)) {
    6516           0 :                                 goto out;
    6517             :                         }
    6518             :                 } else {
    6519             :                         /* Disallow if newname already exists. */
    6520           0 :                         status = NT_STATUS_OBJECT_NAME_COLLISION;
    6521           0 :                         goto out;
    6522             :                 }
    6523             :         }
    6524             : 
    6525          21 :         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
    6526             :                   smb_fname_old->base_name, smb_fname_new->base_name));
    6527             : 
    6528          21 :         ret = SMB_VFS_LINKAT(conn,
    6529             :                         parent_fname_old->fsp,
    6530             :                         base_name_old,
    6531             :                         parent_fname_new->fsp,
    6532             :                         base_name_new,
    6533             :                         0);
    6534             : 
    6535          21 :         if (ret != 0) {
    6536           0 :                 status = map_nt_error_from_unix(errno);
    6537           0 :                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
    6538             :                          nt_errstr(status), smb_fname_old->base_name,
    6539             :                          smb_fname_new->base_name));
    6540             :         }
    6541             : 
    6542          50 :   out:
    6543             : 
    6544          29 :         TALLOC_FREE(parent_fname_old);
    6545          29 :         TALLOC_FREE(parent_fname_new);
    6546          29 :         return status;
    6547             : }
    6548             : 
    6549             : /****************************************************************************
    6550             :  Deal with setting the time from any of the setfilepathinfo functions.
    6551             :  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
    6552             :  calling this function.
    6553             : ****************************************************************************/
    6554             : 
    6555       10594 : NTSTATUS smb_set_file_time(connection_struct *conn,
    6556             :                            files_struct *fsp,
    6557             :                            struct smb_filename *smb_fname,
    6558             :                            struct smb_file_time *ft,
    6559             :                            bool setting_write_time)
    6560             : {
    6561       10594 :         struct files_struct *set_fsp = NULL;
    6562             :         struct timeval_buf tbuf[4];
    6563       10594 :         uint32_t action =
    6564             :                 FILE_NOTIFY_CHANGE_LAST_ACCESS
    6565             :                 |FILE_NOTIFY_CHANGE_LAST_WRITE
    6566             :                 |FILE_NOTIFY_CHANGE_CREATION;
    6567             :         int ret;
    6568             : 
    6569       10594 :         if (!VALID_STAT(smb_fname->st)) {
    6570           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    6571             :         }
    6572             : 
    6573       10594 :         if (fsp == NULL) {
    6574             :                 /* A symlink */
    6575           0 :                 return NT_STATUS_OK;
    6576             :         }
    6577             : 
    6578       10594 :         set_fsp = fsp->base_fsp == NULL ? fsp : fsp->base_fsp;
    6579             : 
    6580             :         /* get some defaults (no modifications) if any info is zero or -1. */
    6581       10594 :         if (is_omit_timespec(&ft->create_time)) {
    6582        9758 :                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
    6583             :         }
    6584             : 
    6585       10594 :         if (is_omit_timespec(&ft->atime)) {
    6586        9691 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
    6587             :         }
    6588             : 
    6589       10594 :         if (is_omit_timespec(&ft->mtime)) {
    6590        3061 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    6591             :         }
    6592             : 
    6593       10594 :         if (!setting_write_time) {
    6594             :                 /* ft->mtime comes from change time, not write time. */
    6595        6322 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    6596             :         }
    6597             : 
    6598             :         /* Ensure the resolution is the correct for
    6599             :          * what we can store on this filesystem. */
    6600             : 
    6601       10594 :         round_timespec(conn->ts_res, &ft->create_time);
    6602       10594 :         round_timespec(conn->ts_res, &ft->ctime);
    6603       10594 :         round_timespec(conn->ts_res, &ft->atime);
    6604       10594 :         round_timespec(conn->ts_res, &ft->mtime);
    6605             : 
    6606       10594 :         DBG_DEBUG("smb_set_filetime: actime: %s\n ",
    6607             :                   timespec_string_buf(&ft->atime, true, &tbuf[0]));
    6608       10594 :         DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
    6609             :                   timespec_string_buf(&ft->mtime, true, &tbuf[1]));
    6610       10594 :         DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
    6611             :                   timespec_string_buf(&ft->ctime, true, &tbuf[2]));
    6612       10594 :         DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
    6613             :                   timespec_string_buf(&ft->create_time, true, &tbuf[3]));
    6614             : 
    6615       10594 :         if (setting_write_time) {
    6616             :                 /*
    6617             :                  * This was a Windows setfileinfo on an open file.
    6618             :                  * NT does this a lot. We also need to 
    6619             :                  * set the time here, as it can be read by 
    6620             :                  * FindFirst/FindNext and with the patch for bug #2045
    6621             :                  * in smbd/fileio.c it ensures that this timestamp is
    6622             :                  * kept sticky even after a write. We save the request
    6623             :                  * away and will set it on file close and after a write. JRA.
    6624             :                  */
    6625             : 
    6626        4272 :                 DBG_DEBUG("setting pending modtime to %s\n",
    6627             :                           timespec_string_buf(&ft->mtime, true, &tbuf[0]));
    6628             : 
    6629        4272 :                 if (set_fsp != NULL) {
    6630        4272 :                         set_sticky_write_time_fsp(set_fsp, ft->mtime);
    6631             :                 } else {
    6632           0 :                         set_sticky_write_time_path(
    6633           0 :                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
    6634             :                                 ft->mtime);
    6635             :                 }
    6636             :         }
    6637             : 
    6638       10594 :         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
    6639             : 
    6640       10594 :         ret = file_ntimes(conn, set_fsp, ft);
    6641       10594 :         if (ret != 0) {
    6642           2 :                 return map_nt_error_from_unix(errno);
    6643             :         }
    6644             : 
    6645       10592 :         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
    6646       10592 :                      smb_fname->base_name);
    6647       10592 :         return NT_STATUS_OK;
    6648             : }
    6649             : 
    6650             : /****************************************************************************
    6651             :  Deal with setting the dosmode from any of the setfilepathinfo functions.
    6652             :  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
    6653             :  done before calling this function.
    6654             : ****************************************************************************/
    6655             : 
    6656        2758 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
    6657             :                                      struct files_struct *fsp,
    6658             :                                      struct smb_filename *smb_fname,
    6659             :                                      uint32_t dosmode)
    6660             : {
    6661             :         struct smb_filename *smb_fname_base;
    6662             :         NTSTATUS status;
    6663             : 
    6664        2758 :         if (!VALID_STAT(smb_fname->st)) {
    6665           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    6666             :         }
    6667             : 
    6668             :         /* Always operate on the base_name, even if a stream was passed in. */
    6669        5516 :         status = synthetic_pathref(talloc_tos(),
    6670             :                                         conn->cwd_fsp,
    6671        2758 :                                         smb_fname->base_name,
    6672             :                                         NULL,
    6673             :                                         NULL,
    6674             :                                         smb_fname->twrp,
    6675             :                                         smb_fname->flags,
    6676             :                                         &smb_fname_base);
    6677             : 
    6678             :         /* do we handle link as non error here ? */
    6679        2758 :         if (!NT_STATUS_IS_OK(status)) {
    6680           0 :                 return status;
    6681             :         }
    6682             : 
    6683        2758 :         if (dosmode) {
    6684        1239 :                 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
    6685         180 :                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
    6686             :                 } else {
    6687        1059 :                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
    6688             :                 }
    6689             :         }
    6690             : 
    6691        2758 :         DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
    6692             : 
    6693             :         /* check the mode isn't different, before changing it */
    6694        2758 :         if ((dosmode != 0) && (dosmode != fdos_mode(fsp))) {
    6695         891 :                 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
    6696             :                           "0x%x\n", smb_fname_str_dbg(smb_fname_base),
    6697             :                           (unsigned int)dosmode));
    6698             : 
    6699         891 :                 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
    6700             :                                     false)) {
    6701           0 :                         DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
    6702             :                                  "%s failed (%s)\n",
    6703             :                                  smb_fname_str_dbg(smb_fname_base),
    6704             :                                  strerror(errno)));
    6705           0 :                         status = map_nt_error_from_unix(errno);
    6706           0 :                         goto out;
    6707             :                 }
    6708             :         }
    6709        2726 :         status = NT_STATUS_OK;
    6710        2758 :  out:
    6711        2758 :         TALLOC_FREE(smb_fname_base);
    6712        2758 :         return status;
    6713             : }
    6714             : 
    6715             : /****************************************************************************
    6716             :  Deal with setting the size from any of the setfilepathinfo functions.
    6717             : ****************************************************************************/
    6718             : 
    6719         469 : static NTSTATUS smb_set_file_size(connection_struct *conn,
    6720             :                                   struct smb_request *req,
    6721             :                                   files_struct *fsp,
    6722             :                                   struct smb_filename *smb_fname,
    6723             :                                   const SMB_STRUCT_STAT *psbuf,
    6724             :                                   off_t size,
    6725             :                                   bool fail_after_createfile)
    6726             : {
    6727         469 :         NTSTATUS status = NT_STATUS_OK;
    6728         469 :         files_struct *new_fsp = NULL;
    6729             : 
    6730         469 :         if (!VALID_STAT(*psbuf)) {
    6731           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    6732             :         }
    6733             : 
    6734         469 :         DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
    6735             :                  (uint64_t)size,
    6736             :                  get_file_size_stat(psbuf));
    6737             : 
    6738         469 :         if (size == get_file_size_stat(psbuf)) {
    6739         148 :                 if (fsp == NULL) {
    6740           0 :                         return NT_STATUS_OK;
    6741             :                 }
    6742         148 :                 if (!fsp->fsp_flags.modified) {
    6743         144 :                         return NT_STATUS_OK;
    6744             :                 }
    6745           4 :                 trigger_write_time_update_immediate(fsp);
    6746           4 :                 return NT_STATUS_OK;
    6747             :         }
    6748             : 
    6749         321 :         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
    6750             :                   smb_fname_str_dbg(smb_fname), (double)size));
    6751             : 
    6752         634 :         if (fsp &&
    6753         594 :             !fsp->fsp_flags.is_pathref &&
    6754         281 :             fsp_get_io_fd(fsp) != -1)
    6755             :         {
    6756             :                 /* Handle based call. */
    6757         281 :                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
    6758           0 :                         return NT_STATUS_ACCESS_DENIED;
    6759             :                 }
    6760             : 
    6761         281 :                 if (vfs_set_filelen(fsp, size) == -1) {
    6762           8 :                         return map_nt_error_from_unix(errno);
    6763             :                 }
    6764         273 :                 trigger_write_time_update_immediate(fsp);
    6765         273 :                 return NT_STATUS_OK;
    6766             :         }
    6767             : 
    6768          40 :         status = SMB_VFS_CREATE_FILE(
    6769             :                 conn,                                   /* conn */
    6770             :                 req,                                    /* req */
    6771             :                 smb_fname,                              /* fname */
    6772             :                 FILE_WRITE_DATA,                        /* access_mask */
    6773             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    6774             :                     FILE_SHARE_DELETE),
    6775             :                 FILE_OPEN,                              /* create_disposition*/
    6776             :                 0,                                      /* create_options */
    6777             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    6778             :                 0,                                      /* oplock_request */
    6779             :                 NULL,                                   /* lease */
    6780             :                 0,                                      /* allocation_size */
    6781             :                 0,                                      /* private_flags */
    6782             :                 NULL,                                   /* sd */
    6783             :                 NULL,                                   /* ea_list */
    6784             :                 &new_fsp,                           /* result */
    6785             :                 NULL,                                   /* pinfo */
    6786             :                 NULL, NULL);                            /* create context */
    6787             : 
    6788          40 :         if (!NT_STATUS_IS_OK(status)) {
    6789             :                 /* NB. We check for open_was_deferred in the caller. */
    6790          28 :                 return status;
    6791             :         }
    6792             : 
    6793             :         /* See RAW-SFILEINFO-END-OF-FILE */
    6794          12 :         if (fail_after_createfile) {
    6795           4 :                 close_file(req, new_fsp,NORMAL_CLOSE);
    6796           4 :                 return NT_STATUS_INVALID_LEVEL;
    6797             :         }
    6798             : 
    6799           8 :         if (vfs_set_filelen(new_fsp, size) == -1) {
    6800           0 :                 status = map_nt_error_from_unix(errno);
    6801           0 :                 close_file(req, new_fsp,NORMAL_CLOSE);
    6802           0 :                 return status;
    6803             :         }
    6804             : 
    6805           8 :         trigger_write_time_update_immediate(new_fsp);
    6806           8 :         close_file(req, new_fsp,NORMAL_CLOSE);
    6807           8 :         return NT_STATUS_OK;
    6808             : }
    6809             : 
    6810             : /****************************************************************************
    6811             :  Deal with SMB_INFO_SET_EA.
    6812             : ****************************************************************************/
    6813             : 
    6814        2939 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
    6815             :                                 const char *pdata,
    6816             :                                 int total_data,
    6817             :                                 files_struct *fsp,
    6818             :                                 struct smb_filename *smb_fname)
    6819             : {
    6820        2939 :         struct ea_list *ea_list = NULL;
    6821        2939 :         TALLOC_CTX *ctx = NULL;
    6822        2939 :         NTSTATUS status = NT_STATUS_OK;
    6823             : 
    6824        2939 :         if (total_data < 10) {
    6825             : 
    6826             :                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
    6827             :                    length. They seem to have no effect. Bug #3212. JRA */
    6828             : 
    6829           0 :                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
    6830             :                         /* We're done. We only get EA info in this call. */
    6831           0 :                         return NT_STATUS_OK;
    6832             :                 }
    6833             : 
    6834           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6835             :         }
    6836             : 
    6837        2939 :         if (IVAL(pdata,0) > total_data) {
    6838           0 :                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
    6839             :                         IVAL(pdata,0), (unsigned int)total_data));
    6840           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6841             :         }
    6842             : 
    6843        2939 :         ctx = talloc_tos();
    6844        2939 :         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
    6845        2939 :         if (!ea_list) {
    6846           8 :                 return NT_STATUS_INVALID_PARAMETER;
    6847             :         }
    6848             : 
    6849        2931 :         if (fsp == NULL) {
    6850             :                 /*
    6851             :                  * The only way fsp can be NULL here is if
    6852             :                  * smb_fname points at a symlink and
    6853             :                  * and we're in POSIX context.
    6854             :                  * Ensure this is the case.
    6855             :                  *
    6856             :                  * In this case we cannot set the EA.
    6857             :                  */
    6858           4 :                 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
    6859           4 :                 return NT_STATUS_ACCESS_DENIED;
    6860             :         }
    6861             : 
    6862        2927 :         status = set_ea(conn, fsp, ea_list);
    6863             : 
    6864        2927 :         return status;
    6865             : }
    6866             : 
    6867             : /****************************************************************************
    6868             :  Deal with SMB_FILE_FULL_EA_INFORMATION set.
    6869             : ****************************************************************************/
    6870             : 
    6871           8 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
    6872             :                                 const char *pdata,
    6873             :                                 int total_data,
    6874             :                                 files_struct *fsp)
    6875             : {
    6876           8 :         struct ea_list *ea_list = NULL;
    6877             :         NTSTATUS status;
    6878             : 
    6879           8 :         if (fsp == NULL) {
    6880           8 :                 return NT_STATUS_INVALID_HANDLE;
    6881             :         }
    6882             : 
    6883           0 :         if (!lp_ea_support(SNUM(conn))) {
    6884           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
    6885             :                         "EA's not supported.\n",
    6886             :                         (unsigned int)total_data));
    6887           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
    6888             :         }
    6889             : 
    6890           0 :         if (total_data < 10) {
    6891           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
    6892             :                         "too small.\n",
    6893             :                         (unsigned int)total_data));
    6894           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6895             :         }
    6896             : 
    6897           0 :         ea_list = read_nttrans_ea_list(talloc_tos(),
    6898             :                                 pdata,
    6899             :                                 total_data);
    6900             : 
    6901           0 :         if (!ea_list) {
    6902           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6903             :         }
    6904             : 
    6905           0 :         status = set_ea(conn, fsp, ea_list);
    6906             : 
    6907           0 :         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
    6908             :                 smb_fname_str_dbg(fsp->fsp_name),
    6909             :                 nt_errstr(status) ));
    6910             : 
    6911           0 :         return status;
    6912             : }
    6913             : 
    6914             : 
    6915             : /****************************************************************************
    6916             :  Deal with SMB_SET_FILE_DISPOSITION_INFO.
    6917             : ****************************************************************************/
    6918             : 
    6919        2600 : static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
    6920             :                                 const char *pdata,
    6921             :                                 int total_data,
    6922             :                                 files_struct *fsp,
    6923             :                                 struct smb_filename *smb_fname)
    6924             : {
    6925        2600 :         NTSTATUS status = NT_STATUS_OK;
    6926             :         bool delete_on_close;
    6927        2600 :         uint32_t dosmode = 0;
    6928             : 
    6929        2600 :         if (total_data < 1) {
    6930           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6931             :         }
    6932             : 
    6933        2600 :         if (fsp == NULL) {
    6934           8 :                 return NT_STATUS_INVALID_HANDLE;
    6935             :         }
    6936             : 
    6937        2592 :         delete_on_close = (CVAL(pdata,0) ? True : False);
    6938        2592 :         dosmode = fdos_mode(fsp);
    6939             : 
    6940        2592 :         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
    6941             :                 "delete_on_close = %u\n",
    6942             :                 smb_fname_str_dbg(smb_fname),
    6943             :                 (unsigned int)dosmode,
    6944             :                 (unsigned int)delete_on_close ));
    6945             : 
    6946        2592 :         if (delete_on_close) {
    6947        2549 :                 status = can_set_delete_on_close(fsp, dosmode);
    6948        2549 :                 if (!NT_STATUS_IS_OK(status)) {
    6949          46 :                         return status;
    6950             :                 }
    6951             :         }
    6952             : 
    6953             :         /* The set is across all open files on this dev/inode pair. */
    6954        2546 :         if (!set_delete_on_close(fsp, delete_on_close,
    6955        2546 :                                  conn->session_info->security_token,
    6956        2546 :                                  conn->session_info->unix_token)) {
    6957           0 :                 return NT_STATUS_ACCESS_DENIED;
    6958             :         }
    6959        2546 :         return NT_STATUS_OK;
    6960             : }
    6961             : 
    6962             : /****************************************************************************
    6963             :  Deal with SMB_FILE_POSITION_INFORMATION.
    6964             : ****************************************************************************/
    6965             : 
    6966          94 : static NTSTATUS smb_file_position_information(connection_struct *conn,
    6967             :                                 const char *pdata,
    6968             :                                 int total_data,
    6969             :                                 files_struct *fsp)
    6970             : {
    6971             :         uint64_t position_information;
    6972             : 
    6973          94 :         if (total_data < 8) {
    6974           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6975             :         }
    6976             : 
    6977          94 :         if (fsp == NULL) {
    6978             :                 /* Ignore on pathname based set. */
    6979           8 :                 return NT_STATUS_OK;
    6980             :         }
    6981             : 
    6982          86 :         position_information = (uint64_t)IVAL(pdata,0);
    6983          86 :         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
    6984             : 
    6985          86 :         DEBUG(10,("smb_file_position_information: Set file position "
    6986             :                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
    6987             :                   (double)position_information));
    6988          86 :         fh_set_position_information(fsp->fh, position_information);
    6989          86 :         return NT_STATUS_OK;
    6990             : }
    6991             : 
    6992             : /****************************************************************************
    6993             :  Deal with SMB_FILE_MODE_INFORMATION.
    6994             : ****************************************************************************/
    6995             : 
    6996           8 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
    6997             :                                 const char *pdata,
    6998             :                                 int total_data)
    6999             : {
    7000             :         uint32_t mode;
    7001             : 
    7002           8 :         if (total_data < 4) {
    7003           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7004             :         }
    7005           8 :         mode = IVAL(pdata,0);
    7006           8 :         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
    7007           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7008             :         }
    7009           8 :         return NT_STATUS_OK;
    7010             : }
    7011             : 
    7012             : /****************************************************************************
    7013             :  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
    7014             : ****************************************************************************/
    7015             : 
    7016         118 : static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
    7017             :                                        struct smb_request *req,
    7018             :                                        const char *pdata,
    7019             :                                        int total_data,
    7020             :                                        struct smb_filename *new_smb_fname)
    7021             : {
    7022         118 :         char *link_target = NULL;
    7023             :         struct smb_filename target_fname;
    7024         118 :         TALLOC_CTX *ctx = talloc_tos();
    7025             :         NTSTATUS status;
    7026             :         int ret;
    7027         118 :         struct smb_filename *parent_fname = NULL;
    7028         118 :         struct smb_filename *base_name = NULL;
    7029             : 
    7030             :         /* Set a symbolic link. */
    7031             :         /* Don't allow this if follow links is false. */
    7032             : 
    7033         118 :         if (total_data == 0) {
    7034           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7035             :         }
    7036             : 
    7037         118 :         if (!lp_follow_symlinks(SNUM(conn))) {
    7038           0 :                 return NT_STATUS_ACCESS_DENIED;
    7039             :         }
    7040             : 
    7041         118 :         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
    7042             :                     total_data, STR_TERMINATE);
    7043             : 
    7044         118 :         if (!link_target) {
    7045           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7046             :         }
    7047             : 
    7048         118 :         target_fname = (struct smb_filename) {
    7049             :                 .base_name = link_target,
    7050             :         };
    7051             : 
    7052             :         /* Removes @GMT tokens if any */
    7053         118 :         status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
    7054         118 :         if (!NT_STATUS_IS_OK(status)) {
    7055           0 :                 return status;
    7056             :         }
    7057             : 
    7058         118 :         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
    7059             :                         new_smb_fname->base_name, link_target ));
    7060             : 
    7061         118 :         status = parent_pathref(talloc_tos(),
    7062             :                                 conn->cwd_fsp,
    7063             :                                 new_smb_fname,
    7064             :                                 &parent_fname,
    7065             :                                 &base_name);
    7066         118 :         if (!NT_STATUS_IS_OK(status)) {
    7067           0 :                 return status;
    7068             :         }
    7069             : 
    7070         118 :         ret = SMB_VFS_SYMLINKAT(conn,
    7071             :                         &target_fname,
    7072             :                         parent_fname->fsp,
    7073             :                         base_name);
    7074         118 :         if (ret != 0) {
    7075           8 :                 TALLOC_FREE(parent_fname);
    7076           8 :                 return map_nt_error_from_unix(errno);
    7077             :         }
    7078             : 
    7079         110 :         TALLOC_FREE(parent_fname);
    7080         110 :         return NT_STATUS_OK;
    7081             : }
    7082             : 
    7083             : /****************************************************************************
    7084             :  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
    7085             : ****************************************************************************/
    7086             : 
    7087          16 : static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
    7088             :                                         struct smb_request *req,
    7089             :                                         const char *pdata, int total_data,
    7090             :                                         struct smb_filename *smb_fname_new)
    7091             : {
    7092          16 :         char *oldname = NULL;
    7093          16 :         struct smb_filename *smb_fname_old = NULL;
    7094          16 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    7095          16 :         TALLOC_CTX *ctx = talloc_tos();
    7096          16 :         NTSTATUS status = NT_STATUS_OK;
    7097             : 
    7098             :         /* Set a hard link. */
    7099          16 :         if (total_data == 0) {
    7100           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7101             :         }
    7102             : 
    7103          16 :         if (req->posix_pathnames) {
    7104          32 :                 srvstr_get_path_posix(ctx,
    7105             :                         pdata,
    7106          16 :                         req->flags2,
    7107             :                         &oldname,
    7108             :                         pdata,
    7109             :                         total_data,
    7110             :                         STR_TERMINATE,
    7111             :                         &status);
    7112             :         } else {
    7113           0 :                 srvstr_get_path(ctx,
    7114             :                         pdata,
    7115           0 :                         req->flags2,
    7116             :                         &oldname,
    7117             :                         pdata,
    7118             :                         total_data,
    7119             :                         STR_TERMINATE,
    7120             :                         &status);
    7121             :         }
    7122          16 :         if (!NT_STATUS_IS_OK(status)) {
    7123           0 :                 return status;
    7124             :         }
    7125             : 
    7126          16 :         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
    7127             :                 smb_fname_str_dbg(smb_fname_new), oldname));
    7128             : 
    7129          16 :         status = filename_convert(ctx,
    7130             :                                 conn,
    7131             :                                 oldname,
    7132             :                                 ucf_flags,
    7133             :                                 0,
    7134             :                                 &smb_fname_old);
    7135          16 :         if (!NT_STATUS_IS_OK(status)) {
    7136           0 :                 return status;
    7137             :         }
    7138             : 
    7139          16 :         return hardlink_internals(ctx, conn, req, false,
    7140             :                         smb_fname_old, smb_fname_new);
    7141             : }
    7142             : 
    7143             : /****************************************************************************
    7144             :  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
    7145             : ****************************************************************************/
    7146             : 
    7147         281 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
    7148             :                                             struct smb_request *req,
    7149             :                                             const char *pdata,
    7150             :                                             int total_data,
    7151             :                                             files_struct *fsp,
    7152             :                                             struct smb_filename *smb_fname_src)
    7153             : {
    7154             :         bool overwrite;
    7155             :         uint32_t len;
    7156         281 :         char *newname = NULL;
    7157         281 :         struct smb_filename *smb_fname_dst = NULL;
    7158         281 :         const char *dst_original_lcomp = NULL;
    7159         281 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    7160         281 :         NTSTATUS status = NT_STATUS_OK;
    7161         281 :         TALLOC_CTX *ctx = talloc_tos();
    7162             : 
    7163         281 :         if (!fsp) {
    7164           0 :                 return NT_STATUS_INVALID_HANDLE;
    7165             :         }
    7166             : 
    7167         281 :         if (total_data < 20) {
    7168           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7169             :         }
    7170             : 
    7171         281 :         overwrite = (CVAL(pdata,0) ? True : False);
    7172         281 :         len = IVAL(pdata,16);
    7173             : 
    7174         281 :         if (len > (total_data - 20) || (len == 0)) {
    7175           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7176             :         }
    7177             : 
    7178         281 :         if (req->posix_pathnames) {
    7179           0 :                 srvstr_get_path_posix(ctx,
    7180             :                                 pdata,
    7181           0 :                                 req->flags2,
    7182             :                                 &newname,
    7183             :                                 &pdata[20],
    7184             :                                 len,
    7185             :                                 STR_TERMINATE,
    7186             :                                 &status);
    7187             :         } else {
    7188         562 :                 srvstr_get_path(ctx,
    7189             :                                 pdata,
    7190         281 :                                 req->flags2,
    7191             :                                 &newname,
    7192             :                                 &pdata[20],
    7193             :                                 len,
    7194             :                                 STR_TERMINATE,
    7195             :                                 &status);
    7196             :         }
    7197         281 :         if (!NT_STATUS_IS_OK(status)) {
    7198           0 :                 return status;
    7199             :         }
    7200             : 
    7201         281 :         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
    7202             :                                 newname));
    7203             : 
    7204         281 :         status = filename_convert(ctx,
    7205             :                                 conn,
    7206             :                                 newname,
    7207             :                                 ucf_flags,
    7208             :                                 0,
    7209             :                                 &smb_fname_dst);
    7210         281 :         if (!NT_STATUS_IS_OK(status)) {
    7211           0 :                 return status;
    7212             :         }
    7213             : 
    7214         281 :         if (fsp->base_fsp) {
    7215             :                 /* newname must be a stream name. */
    7216          16 :                 if (newname[0] != ':') {
    7217           0 :                         return NT_STATUS_NOT_SUPPORTED;
    7218             :                 }
    7219             : 
    7220             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    7221          48 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    7222          16 :                                         fsp->base_fsp->fsp_name->base_name,
    7223             :                                         newname,
    7224             :                                         NULL,
    7225          16 :                                         fsp->base_fsp->fsp_name->twrp,
    7226          16 :                                         fsp->base_fsp->fsp_name->flags);
    7227          16 :                 if (smb_fname_dst == NULL) {
    7228           0 :                         status = NT_STATUS_NO_MEMORY;
    7229           0 :                         goto out;
    7230             :                 }
    7231             :         }
    7232             : 
    7233             :         /*
    7234             :          * Set the original last component, since
    7235             :          * rename_internals_fsp() requires it.
    7236             :          */
    7237         281 :         dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    7238             :                                         conn,
    7239             :                                         newname,
    7240             :                                         ucf_flags);
    7241         281 :         if (dst_original_lcomp == NULL) {
    7242           0 :                 status = NT_STATUS_NO_MEMORY;
    7243           0 :                 goto out;
    7244             :         }
    7245             : 
    7246         281 :         DEBUG(10,("smb2_file_rename_information: "
    7247             :                   "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    7248             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    7249             :                   smb_fname_str_dbg(smb_fname_dst)));
    7250         281 :         status = rename_internals_fsp(conn,
    7251             :                                 fsp,
    7252             :                                 smb_fname_dst,
    7253             :                                 dst_original_lcomp,
    7254             :                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
    7255             :                                 overwrite);
    7256             : 
    7257         281 :  out:
    7258         281 :         TALLOC_FREE(smb_fname_dst);
    7259         281 :         return status;
    7260             : }
    7261             : 
    7262           8 : static NTSTATUS smb_file_link_information(connection_struct *conn,
    7263             :                                             struct smb_request *req,
    7264             :                                             const char *pdata,
    7265             :                                             int total_data,
    7266             :                                             files_struct *fsp,
    7267             :                                             struct smb_filename *smb_fname_src)
    7268             : {
    7269             :         bool overwrite;
    7270             :         uint32_t len;
    7271           8 :         char *newname = NULL;
    7272           8 :         struct smb_filename *smb_fname_dst = NULL;
    7273           8 :         NTSTATUS status = NT_STATUS_OK;
    7274           8 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    7275           8 :         TALLOC_CTX *ctx = talloc_tos();
    7276             : 
    7277           8 :         if (!fsp) {
    7278           8 :                 return NT_STATUS_INVALID_HANDLE;
    7279             :         }
    7280             : 
    7281           0 :         if (total_data < 20) {
    7282           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7283             :         }
    7284             : 
    7285           0 :         overwrite = (CVAL(pdata,0) ? true : false);
    7286           0 :         len = IVAL(pdata,16);
    7287             : 
    7288           0 :         if (len > (total_data - 20) || (len == 0)) {
    7289           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7290             :         }
    7291             : 
    7292           0 :         if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
    7293           0 :                 srvstr_get_path_posix(ctx,
    7294             :                                 pdata,
    7295           0 :                                 req->flags2,
    7296             :                                 &newname,
    7297             :                                 &pdata[20],
    7298             :                                 len,
    7299             :                                 STR_TERMINATE,
    7300             :                                 &status);
    7301           0 :                 ucf_flags |= UCF_POSIX_PATHNAMES;
    7302             :         } else {
    7303           0 :                 srvstr_get_path(ctx,
    7304             :                                 pdata,
    7305           0 :                                 req->flags2,
    7306             :                                 &newname,
    7307             :                                 &pdata[20],
    7308             :                                 len,
    7309             :                                 STR_TERMINATE,
    7310             :                                 &status);
    7311             :         }
    7312           0 :         if (!NT_STATUS_IS_OK(status)) {
    7313           0 :                 return status;
    7314             :         }
    7315             : 
    7316           0 :         DEBUG(10,("smb_file_link_information: got name |%s|\n",
    7317             :                                 newname));
    7318             : 
    7319           0 :         status = filename_convert(ctx,
    7320             :                                 conn,
    7321             :                                 newname,
    7322             :                                 ucf_flags,
    7323             :                                 0,
    7324             :                                 &smb_fname_dst);
    7325           0 :         if (!NT_STATUS_IS_OK(status)) {
    7326           0 :                 return status;
    7327             :         }
    7328             : 
    7329           0 :         if (fsp->base_fsp) {
    7330             :                 /* No stream names. */
    7331           0 :                 return NT_STATUS_NOT_SUPPORTED;
    7332             :         }
    7333             : 
    7334           0 :         DEBUG(10,("smb_file_link_information: "
    7335             :                   "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
    7336             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    7337             :                   smb_fname_str_dbg(smb_fname_dst)));
    7338           0 :         status = hardlink_internals(ctx,
    7339             :                                 conn,
    7340             :                                 req,
    7341             :                                 overwrite,
    7342           0 :                                 fsp->fsp_name,
    7343             :                                 smb_fname_dst);
    7344             : 
    7345           0 :         TALLOC_FREE(smb_fname_dst);
    7346           0 :         return status;
    7347             : }
    7348             : 
    7349             : /****************************************************************************
    7350             :  Deal with SMB_FILE_RENAME_INFORMATION.
    7351             : ****************************************************************************/
    7352             : 
    7353         129 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
    7354             :                                             struct smb_request *req,
    7355             :                                             const char *pdata,
    7356             :                                             int total_data,
    7357             :                                             files_struct *fsp,
    7358             :                                             struct smb_filename *smb_fname_src)
    7359             : {
    7360             :         bool overwrite;
    7361             :         uint32_t root_fid;
    7362             :         uint32_t len;
    7363         129 :         char *newname = NULL;
    7364         129 :         struct smb_filename *smb_fname_dst = NULL;
    7365         129 :         const char *dst_original_lcomp = NULL;
    7366         129 :         NTSTATUS status = NT_STATUS_OK;
    7367             :         char *p;
    7368         129 :         TALLOC_CTX *ctx = talloc_tos();
    7369             : 
    7370         129 :         if (total_data < 13) {
    7371           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7372             :         }
    7373             : 
    7374         129 :         overwrite = (CVAL(pdata,0) ? True : False);
    7375         129 :         root_fid = IVAL(pdata,4);
    7376         129 :         len = IVAL(pdata,8);
    7377             : 
    7378         129 :         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
    7379          12 :                 return NT_STATUS_INVALID_PARAMETER;
    7380             :         }
    7381             : 
    7382         117 :         if (req->posix_pathnames) {
    7383           0 :                 srvstr_get_path_posix(ctx,
    7384             :                                 pdata,
    7385           0 :                                 req->flags2,
    7386             :                                 &newname,
    7387             :                                 &pdata[12],
    7388             :                                 len,
    7389             :                                 0,
    7390             :                                 &status);
    7391             :         } else {
    7392         234 :                 srvstr_get_path(ctx,
    7393             :                                 pdata,
    7394         117 :                                 req->flags2,
    7395             :                                 &newname,
    7396             :                                 &pdata[12],
    7397             :                                 len,
    7398             :                                 0,
    7399             :                                 &status);
    7400             :         }
    7401         117 :         if (!NT_STATUS_IS_OK(status)) {
    7402           0 :                 return status;
    7403             :         }
    7404             : 
    7405         117 :         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
    7406             :                                 newname));
    7407             : 
    7408             :         /* Check the new name has no '/' characters. */
    7409         117 :         if (strchr_m(newname, '/')) {
    7410           8 :                 return NT_STATUS_NOT_SUPPORTED;
    7411             :         }
    7412             : 
    7413         109 :         if (fsp && fsp->base_fsp) {
    7414             :                 /* newname must be a stream name. */
    7415          28 :                 if (newname[0] != ':') {
    7416           0 :                         return NT_STATUS_NOT_SUPPORTED;
    7417             :                 }
    7418             : 
    7419             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    7420          84 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    7421          28 :                                         fsp->base_fsp->fsp_name->base_name,
    7422             :                                         newname,
    7423             :                                         NULL,
    7424          28 :                                         fsp->base_fsp->fsp_name->twrp,
    7425          28 :                                         fsp->base_fsp->fsp_name->flags);
    7426          28 :                 if (smb_fname_dst == NULL) {
    7427           0 :                         status = NT_STATUS_NO_MEMORY;
    7428           0 :                         goto out;
    7429             :                 }
    7430             : 
    7431             :                 /*
    7432             :                  * Get the original last component, since
    7433             :                  * rename_internals_fsp() requires it.
    7434             :                  */
    7435          28 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    7436             :                                         conn,
    7437             :                                         newname,
    7438             :                                         0);
    7439          56 :                 if (dst_original_lcomp == NULL) {
    7440           0 :                         status = NT_STATUS_NO_MEMORY;
    7441           0 :                         goto out;
    7442             :                 }
    7443             : 
    7444             :         } else {
    7445             :                 /*
    7446             :                  * Build up an smb_fname_dst based on the filename passed in.
    7447             :                  * We basically just strip off the last component, and put on
    7448             :                  * the newname instead.
    7449             :                  */
    7450          81 :                 char *base_name = NULL;
    7451          81 :                 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP|
    7452          81 :                                 ucf_flags_from_smb_request(req);
    7453             : 
    7454             :                 /* newname must *not* be a stream name. */
    7455          81 :                 if (newname[0] == ':') {
    7456           0 :                         return NT_STATUS_NOT_SUPPORTED;
    7457             :                 }
    7458             : 
    7459             :                 /*
    7460             :                  * Strip off the last component (filename) of the path passed
    7461             :                  * in.
    7462             :                  */
    7463          81 :                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
    7464          81 :                 if (!base_name) {
    7465           0 :                         return NT_STATUS_NO_MEMORY;
    7466             :                 }
    7467          81 :                 p = strrchr_m(base_name, '/');
    7468          81 :                 if (p) {
    7469          76 :                         p[1] = '\0';
    7470             :                 } else {
    7471           5 :                         base_name = talloc_strdup(ctx, "");
    7472           5 :                         if (!base_name) {
    7473           0 :                                 return NT_STATUS_NO_MEMORY;
    7474             :                         }
    7475             :                 }
    7476             :                 /* Append the new name. */
    7477          81 :                 base_name = talloc_asprintf_append(base_name,
    7478             :                                 "%s",
    7479             :                                 newname);
    7480          81 :                 if (!base_name) {
    7481           0 :                         return NT_STATUS_NO_MEMORY;
    7482             :                 }
    7483             : 
    7484          81 :                 status = filename_convert(ctx,
    7485             :                                           conn,
    7486             :                                           base_name,
    7487             :                                           ucf_flags,
    7488             :                                           0,
    7489             :                                           &smb_fname_dst);
    7490             : 
    7491             :                 /* If an error we expect this to be
    7492             :                  * NT_STATUS_OBJECT_PATH_NOT_FOUND */
    7493             : 
    7494          81 :                 if (!NT_STATUS_IS_OK(status)) {
    7495           0 :                         if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
    7496             :                                             status)) {
    7497           0 :                                 goto out;
    7498             :                         }
    7499             :                         /* Create an smb_fname to call rename_internals_fsp() */
    7500           0 :                         smb_fname_dst = synthetic_smb_fname(ctx,
    7501             :                                                 base_name,
    7502             :                                                 NULL,
    7503             :                                                 NULL,
    7504             :                                                 smb_fname_src->twrp,
    7505             :                                                 smb_fname_src->flags);
    7506           0 :                         if (smb_fname_dst == NULL) {
    7507           0 :                                 status = NT_STATUS_NO_MEMORY;
    7508           0 :                                 goto out;
    7509             :                         }
    7510             :                 }
    7511          81 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    7512             :                                         conn,
    7513             :                                         newname,
    7514             :                                         ucf_flags);
    7515          81 :                 if (dst_original_lcomp == NULL) {
    7516           0 :                         status = NT_STATUS_NO_MEMORY;
    7517           0 :                         goto out;
    7518             :                 }
    7519             :         }
    7520             : 
    7521         109 :         if (fsp != NULL && fsp->fsp_flags.is_fsa) {
    7522          80 :                 DEBUG(10,("smb_file_rename_information: "
    7523             :                           "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    7524             :                           fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    7525             :                           smb_fname_str_dbg(smb_fname_dst)));
    7526          80 :                 status = rename_internals_fsp(conn,
    7527             :                                         fsp,
    7528             :                                         smb_fname_dst,
    7529             :                                         dst_original_lcomp,
    7530             :                                         0,
    7531             :                                         overwrite);
    7532             :         } else {
    7533          29 :                 DEBUG(10,("smb_file_rename_information: "
    7534             :                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
    7535             :                           smb_fname_str_dbg(smb_fname_src),
    7536             :                           smb_fname_str_dbg(smb_fname_dst)));
    7537          29 :                 status = rename_internals(ctx,
    7538             :                                         conn,
    7539             :                                         req,
    7540             :                                         smb_fname_src,
    7541             :                                         NULL,
    7542             :                                         smb_fname_dst,
    7543             :                                         dst_original_lcomp,
    7544             :                                         0,
    7545             :                                         overwrite,
    7546             :                                         FILE_WRITE_ATTRIBUTES);
    7547             :         }
    7548         109 :  out:
    7549         109 :         TALLOC_FREE(smb_fname_dst);
    7550         109 :         return status;
    7551             : }
    7552             : 
    7553             : /****************************************************************************
    7554             :  Deal with SMB_SET_POSIX_ACL.
    7555             : ****************************************************************************/
    7556             : 
    7557             : #if defined(HAVE_POSIX_ACLS)
    7558          16 : static NTSTATUS smb_set_posix_acl(connection_struct *conn,
    7559             :                                 struct smb_request *req,
    7560             :                                 const char *pdata,
    7561             :                                 int total_data_in,
    7562             :                                 files_struct *fsp,
    7563             :                                 struct smb_filename *smb_fname)
    7564             : {
    7565             :         uint16_t posix_acl_version;
    7566             :         uint16_t num_file_acls;
    7567             :         uint16_t num_def_acls;
    7568          16 :         bool valid_file_acls = true;
    7569          16 :         bool valid_def_acls = true;
    7570             :         NTSTATUS status;
    7571             :         unsigned int size_needed;
    7572             :         unsigned int total_data;
    7573          16 :         bool close_fsp = false;
    7574             : 
    7575          16 :         if (total_data_in < 0) {
    7576           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    7577           0 :                 goto out;
    7578             :         }
    7579             : 
    7580          16 :         total_data = total_data_in;
    7581             : 
    7582          16 :         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
    7583           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    7584           0 :                 goto out;
    7585             :         }
    7586          16 :         posix_acl_version = SVAL(pdata,0);
    7587          16 :         num_file_acls = SVAL(pdata,2);
    7588          16 :         num_def_acls = SVAL(pdata,4);
    7589             : 
    7590          16 :         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    7591           4 :                 valid_file_acls = false;
    7592           4 :                 num_file_acls = 0;
    7593             :         }
    7594             : 
    7595          16 :         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    7596           0 :                 valid_def_acls = false;
    7597           0 :                 num_def_acls = 0;
    7598             :         }
    7599             : 
    7600          16 :         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
    7601           8 :                 status = NT_STATUS_INVALID_PARAMETER;
    7602           8 :                 goto out;
    7603             :         }
    7604             : 
    7605             :         /* Wrap checks. */
    7606           8 :         if (num_file_acls + num_def_acls < num_file_acls) {
    7607           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    7608           0 :                 goto out;
    7609             :         }
    7610             : 
    7611           8 :         size_needed = num_file_acls + num_def_acls;
    7612             : 
    7613             :         /*
    7614             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    7615             :          * than UINT_MAX, so check by division.
    7616             :          */
    7617           8 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    7618           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    7619           0 :                 goto out;
    7620             :         }
    7621             : 
    7622           8 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    7623           8 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    7624           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    7625           0 :                 goto out;
    7626             :         }
    7627           8 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    7628             : 
    7629           8 :         if (total_data < size_needed) {
    7630           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    7631           0 :                 goto out;
    7632             :         }
    7633             : 
    7634             :         /*
    7635             :          * Ensure we always operate on a file descriptor, not just
    7636             :          * the filename.
    7637             :          */
    7638           8 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    7639           8 :                 uint32_t access_mask = SEC_STD_WRITE_OWNER|
    7640             :                                         SEC_STD_WRITE_DAC|
    7641             :                                         SEC_STD_READ_CONTROL|
    7642             :                                         FILE_READ_ATTRIBUTES|
    7643             :                                         FILE_WRITE_ATTRIBUTES;
    7644             : 
    7645           8 :                 status = get_posix_fsp(conn,
    7646             :                                         req,
    7647             :                                         smb_fname,
    7648             :                                         access_mask,
    7649             :                                         &fsp);
    7650             : 
    7651           8 :                 if (!NT_STATUS_IS_OK(status)) {
    7652           4 :                         goto out;
    7653             :                 }
    7654           4 :                 close_fsp = true;
    7655             :         }
    7656             : 
    7657             :         /* Here we know fsp != NULL */
    7658           4 :         SMB_ASSERT(fsp != NULL);
    7659             : 
    7660           4 :         status = refuse_symlink_fsp(fsp);
    7661           4 :         if (!NT_STATUS_IS_OK(status)) {
    7662           0 :                 goto out;
    7663             :         }
    7664             : 
    7665             :         /* If we have a default acl, this *must* be a directory. */
    7666           4 :         if (valid_def_acls && !fsp->fsp_flags.is_directory) {
    7667           0 :                 DBG_INFO("Can't set default acls on "
    7668             :                          "non-directory %s\n",
    7669             :                          fsp_str_dbg(fsp));
    7670           0 :                 return NT_STATUS_INVALID_HANDLE;
    7671             :         }
    7672             : 
    7673           4 :         DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
    7674             :                   "num_def_acls = %"PRIu16"\n",
    7675             :                   fsp_str_dbg(fsp),
    7676             :                   num_file_acls,
    7677             :                   num_def_acls);
    7678             : 
    7679             :         /* Move pdata to the start of the file ACL entries. */
    7680           4 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    7681             : 
    7682           4 :         if (valid_file_acls) {
    7683           0 :                 status = set_unix_posix_acl(conn,
    7684             :                                         fsp,
    7685             :                                         num_file_acls,
    7686             :                                         pdata);
    7687           0 :                 if (!NT_STATUS_IS_OK(status)) {
    7688           0 :                         goto out;
    7689             :                 }
    7690             :         }
    7691             : 
    7692             :         /* Move pdata to the start of the default ACL entries. */
    7693           4 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    7694             : 
    7695           4 :         if (valid_def_acls) {
    7696           4 :                 status = set_unix_posix_default_acl(conn,
    7697             :                                         fsp,
    7698             :                                         num_def_acls,
    7699             :                                         pdata);
    7700           4 :                 if (!NT_STATUS_IS_OK(status)) {
    7701           0 :                         goto out;
    7702             :                 }
    7703             :         }
    7704             : 
    7705           4 :         status = NT_STATUS_OK;
    7706             : 
    7707          16 :   out:
    7708             : 
    7709          16 :         if (close_fsp) {
    7710           4 :                 (void)close_file(req, fsp, NORMAL_CLOSE);
    7711           4 :                 fsp = NULL;
    7712             :         }
    7713          16 :         return status;
    7714             : }
    7715             : #endif
    7716             : 
    7717             : /****************************************************************************
    7718             :  Deal with SMB_SET_POSIX_LOCK.
    7719             : ****************************************************************************/
    7720             : 
    7721             : static void smb_set_posix_lock_done(struct tevent_req *subreq);
    7722             : 
    7723          36 : static NTSTATUS smb_set_posix_lock(connection_struct *conn,
    7724             :                                 struct smb_request *req,
    7725             :                                 const char *pdata,
    7726             :                                 int total_data,
    7727             :                                 files_struct *fsp)
    7728             : {
    7729          36 :         struct tevent_req *subreq = NULL;
    7730          36 :         struct smbd_lock_element *lck = NULL;
    7731             :         uint64_t count;
    7732             :         uint64_t offset;
    7733             :         uint64_t smblctx;
    7734          36 :         bool blocking_lock = False;
    7735             :         enum brl_type lock_type;
    7736             : 
    7737          36 :         NTSTATUS status = NT_STATUS_OK;
    7738             : 
    7739          36 :         if (fsp == NULL ||
    7740          36 :             fsp->fsp_flags.is_pathref ||
    7741          36 :             fsp_get_io_fd(fsp) == -1)
    7742             :         {
    7743           0 :                 return NT_STATUS_INVALID_HANDLE;
    7744             :         }
    7745             : 
    7746          36 :         if (total_data != POSIX_LOCK_DATA_SIZE) {
    7747           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7748             :         }
    7749             : 
    7750          36 :         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
    7751           4 :                 case POSIX_LOCK_TYPE_READ:
    7752           4 :                         lock_type = READ_LOCK;
    7753           4 :                         break;
    7754          24 :                 case POSIX_LOCK_TYPE_WRITE:
    7755             :                         /* Return the right POSIX-mappable error code for files opened read-only. */
    7756          24 :                         if (!fsp->fsp_flags.can_write) {
    7757           0 :                                 return NT_STATUS_INVALID_HANDLE;
    7758             :                         }
    7759          24 :                         lock_type = WRITE_LOCK;
    7760          24 :                         break;
    7761           8 :                 case POSIX_LOCK_TYPE_UNLOCK:
    7762           8 :                         lock_type = UNLOCK_LOCK;
    7763           8 :                         break;
    7764           0 :                 default:
    7765           0 :                         return NT_STATUS_INVALID_PARAMETER;
    7766             :         }
    7767             : 
    7768          36 :         switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
    7769          28 :         case POSIX_LOCK_FLAG_NOWAIT:
    7770          28 :                 blocking_lock = false;
    7771          28 :                 break;
    7772           8 :         case POSIX_LOCK_FLAG_WAIT:
    7773           8 :                 blocking_lock = true;
    7774           8 :                 break;
    7775           0 :         default:
    7776           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7777             :         }
    7778             : 
    7779          36 :         if (!lp_blocking_locks(SNUM(conn))) { 
    7780           0 :                 blocking_lock = False;
    7781             :         }
    7782             : 
    7783          36 :         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
    7784          72 :         offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
    7785          36 :                         ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
    7786          72 :         count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
    7787          36 :                         ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
    7788             : 
    7789          36 :         DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
    7790             :                   "count = %"PRIu64", offset = %"PRIu64"\n",
    7791             :                   fsp_str_dbg(fsp),
    7792             :                   (unsigned int)lock_type,
    7793             :                   smblctx,
    7794             :                   count,
    7795             :                   offset);
    7796             : 
    7797          36 :         if (lock_type == UNLOCK_LOCK) {
    7798           8 :                 struct smbd_lock_element l = {
    7799           8 :                         .req_guid = smbd_request_guid(req, 0),
    7800             :                         .smblctx = smblctx,
    7801             :                         .brltype = UNLOCK_LOCK,
    7802             :                         .offset = offset,
    7803             :                         .count = count,
    7804             :                 };
    7805           8 :                 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
    7806           8 :                 return status;
    7807             :         }
    7808             : 
    7809          28 :         lck = talloc(req, struct smbd_lock_element);
    7810          28 :         if (lck == NULL) {
    7811           0 :                 return NT_STATUS_NO_MEMORY;
    7812             :         }
    7813             : 
    7814          28 :         *lck = (struct smbd_lock_element) {
    7815          28 :                 .req_guid = smbd_request_guid(req, 0),
    7816             :                 .smblctx = smblctx,
    7817             :                 .brltype = lock_type,
    7818             :                 .count = count,
    7819             :                 .offset = offset,
    7820             :         };
    7821             : 
    7822          56 :         subreq = smbd_smb1_do_locks_send(
    7823             :                 fsp,
    7824          28 :                 req->sconn->ev_ctx,
    7825             :                 &req,
    7826             :                 fsp,
    7827             :                 blocking_lock ? UINT32_MAX : 0,
    7828             :                 true,           /* large_offset */
    7829             :                 POSIX_LOCK,
    7830             :                 1,
    7831             :                 lck);
    7832          28 :         if (subreq == NULL) {
    7833           0 :                 TALLOC_FREE(lck);
    7834           0 :                 return NT_STATUS_NO_MEMORY;
    7835             :         }
    7836          28 :         tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
    7837          28 :         return NT_STATUS_EVENT_PENDING;
    7838             : }
    7839             : 
    7840          28 : static void smb_set_posix_lock_done(struct tevent_req *subreq)
    7841             : {
    7842          28 :         struct smb_request *req = NULL;
    7843             :         NTSTATUS status;
    7844             :         bool ok;
    7845             : 
    7846          28 :         ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
    7847          28 :         SMB_ASSERT(ok);
    7848             : 
    7849          28 :         status = smbd_smb1_do_locks_recv(subreq);
    7850          28 :         TALLOC_FREE(subreq);
    7851             : 
    7852          28 :         if (NT_STATUS_IS_OK(status)) {
    7853          24 :                 char params[2] = {0};
    7854             :                 /* Fake up max_data_bytes here - we know it fits. */
    7855          48 :                 send_trans2_replies(
    7856          24 :                         req->conn,
    7857             :                         req,
    7858          24 :                         NT_STATUS_OK,
    7859             :                         params,
    7860             :                         2,
    7861             :                         NULL,
    7862             :                         0,
    7863             :                         0xffff);
    7864             :         } else {
    7865           4 :                 reply_nterror(req, status);
    7866          12 :                 ok = srv_send_smb(
    7867           4 :                         req->xconn,
    7868           4 :                         (char *)req->outbuf,
    7869             :                         true,
    7870           4 :                         req->seqnum+1,
    7871           4 :                         IS_CONN_ENCRYPTED(req->conn),
    7872             :                         NULL);
    7873           4 :                 if (!ok) {
    7874           0 :                         exit_server_cleanly("smb_set_posix_lock_done: "
    7875             :                                             "srv_send_smb failed.");
    7876             :                 }
    7877             :         }
    7878             : 
    7879          28 :         TALLOC_FREE(req);
    7880          28 :         return;
    7881             : }
    7882             : 
    7883             : /****************************************************************************
    7884             :  Deal with SMB_SET_FILE_BASIC_INFO.
    7885             : ****************************************************************************/
    7886             : 
    7887        2766 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
    7888             :                                         const char *pdata,
    7889             :                                         int total_data,
    7890             :                                         files_struct *fsp,
    7891             :                                         struct smb_filename *smb_fname)
    7892             : {
    7893             :         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
    7894             :         struct smb_file_time ft;
    7895        2766 :         uint32_t dosmode = 0;
    7896        2766 :         NTSTATUS status = NT_STATUS_OK;
    7897             : 
    7898        2766 :         init_smb_file_time(&ft);
    7899             : 
    7900        2766 :         if (total_data < 36) {
    7901           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7902             :         }
    7903             : 
    7904        2766 :         if (fsp == NULL) {
    7905           8 :                 return NT_STATUS_INVALID_HANDLE;
    7906             :         }
    7907             : 
    7908        2758 :         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    7909        2758 :         if (!NT_STATUS_IS_OK(status)) {
    7910           0 :                 return status;
    7911             :         }
    7912             : 
    7913             :         /* Set the attributes */
    7914        2758 :         dosmode = IVAL(pdata,32);
    7915        2758 :         status = smb_set_file_dosmode(conn, fsp, smb_fname, dosmode);
    7916        2758 :         if (!NT_STATUS_IS_OK(status)) {
    7917           0 :                 return status;
    7918             :         }
    7919             : 
    7920             :         /* create time */
    7921        2758 :         ft.create_time = pull_long_date_full_timespec(pdata);
    7922             : 
    7923             :         /* access time */
    7924        2758 :         ft.atime = pull_long_date_full_timespec(pdata+8);
    7925             : 
    7926             :         /* write time. */
    7927        2758 :         ft.mtime = pull_long_date_full_timespec(pdata+16);
    7928             : 
    7929             :         /* change time. */
    7930        2758 :         ft.ctime = pull_long_date_full_timespec(pdata+24);
    7931             : 
    7932        2758 :         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
    7933             :                    smb_fname_str_dbg(smb_fname)));
    7934             : 
    7935        2758 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    7936        2758 :         if (!NT_STATUS_IS_OK(status)) {
    7937           0 :                 return status;
    7938             :         }
    7939             : 
    7940        2758 :         if (fsp->fsp_flags.modified) {
    7941        1072 :                 trigger_write_time_update_immediate(fsp);
    7942             :         }
    7943        2758 :         return NT_STATUS_OK;
    7944             : }
    7945             : 
    7946             : /****************************************************************************
    7947             :  Deal with SMB_INFO_STANDARD.
    7948             : ****************************************************************************/
    7949             : 
    7950           8 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
    7951             :                                         const char *pdata,
    7952             :                                         int total_data,
    7953             :                                         files_struct *fsp,
    7954             :                                         struct smb_filename *smb_fname)
    7955             : {
    7956             :         NTSTATUS status;
    7957             :         struct smb_file_time ft;
    7958             : 
    7959           8 :         init_smb_file_time(&ft);
    7960             : 
    7961           8 :         if (total_data < 12) {
    7962           0 :                 return NT_STATUS_INVALID_PARAMETER;
    7963             :         }
    7964             : 
    7965           8 :         if (fsp == NULL) {
    7966           8 :                 return NT_STATUS_INVALID_HANDLE;
    7967             :         }
    7968             : 
    7969             :         /* create time */
    7970           0 :         ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
    7971             :         /* access time */
    7972           0 :         ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
    7973             :         /* write time */
    7974           0 :         ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
    7975             : 
    7976           0 :         DEBUG(10,("smb_set_info_standard: file %s\n",
    7977             :                 smb_fname_str_dbg(smb_fname)));
    7978             : 
    7979           0 :         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    7980           0 :         if (!NT_STATUS_IS_OK(status)) {
    7981           0 :                 return status;
    7982             :         }
    7983             : 
    7984           0 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    7985           0 :         if (!NT_STATUS_IS_OK(status)) {
    7986           0 :                 return status;
    7987             :         }
    7988             : 
    7989           0 :         if (fsp->fsp_flags.modified) {
    7990           0 :                 trigger_write_time_update_immediate(fsp);
    7991             :         }
    7992           0 :         return NT_STATUS_OK;
    7993             : }
    7994             : 
    7995             : /****************************************************************************
    7996             :  Deal with SMB_SET_FILE_ALLOCATION_INFO.
    7997             : ****************************************************************************/
    7998             : 
    7999          16 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
    8000             :                                              struct smb_request *req,
    8001             :                                         const char *pdata,
    8002             :                                         int total_data,
    8003             :                                         files_struct *fsp,
    8004             :                                         struct smb_filename *smb_fname)
    8005             : {
    8006          16 :         uint64_t allocation_size = 0;
    8007          16 :         NTSTATUS status = NT_STATUS_OK;
    8008          16 :         files_struct *new_fsp = NULL;
    8009             : 
    8010          16 :         if (!VALID_STAT(smb_fname->st)) {
    8011           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    8012             :         }
    8013             : 
    8014          16 :         if (total_data < 8) {
    8015           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8016             :         }
    8017             : 
    8018          16 :         allocation_size = (uint64_t)IVAL(pdata,0);
    8019          16 :         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
    8020          16 :         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
    8021             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    8022             :                   (double)allocation_size));
    8023             : 
    8024          16 :         if (allocation_size) {
    8025           6 :                 allocation_size = smb_roundup(conn, allocation_size);
    8026             :         }
    8027             : 
    8028          16 :         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
    8029             :                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
    8030             :                   (double)allocation_size));
    8031             : 
    8032          24 :         if (fsp &&
    8033          12 :             !fsp->fsp_flags.is_pathref &&
    8034           4 :             fsp_get_io_fd(fsp) != -1)
    8035             :         {
    8036             :                 /* Open file handle. */
    8037           4 :                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
    8038           0 :                         return NT_STATUS_ACCESS_DENIED;
    8039             :                 }
    8040             : 
    8041             :                 /* Only change if needed. */
    8042           4 :                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    8043           4 :                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
    8044           0 :                                 return map_nt_error_from_unix(errno);
    8045             :                         }
    8046             :                 }
    8047             :                 /* But always update the time. */
    8048             :                 /*
    8049             :                  * This is equivalent to a write. Ensure it's seen immediately
    8050             :                  * if there are no pending writes.
    8051             :                  */
    8052           4 :                 trigger_write_time_update_immediate(fsp);
    8053           4 :                 return NT_STATUS_OK;
    8054             :         }
    8055             : 
    8056             :         /* Pathname or stat or directory file. */
    8057          12 :         status = SMB_VFS_CREATE_FILE(
    8058             :                 conn,                                   /* conn */
    8059             :                 req,                                    /* req */
    8060             :                 smb_fname,                              /* fname */
    8061             :                 FILE_WRITE_DATA,                        /* access_mask */
    8062             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    8063             :                     FILE_SHARE_DELETE),
    8064             :                 FILE_OPEN,                              /* create_disposition*/
    8065             :                 0,                                      /* create_options */
    8066             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    8067             :                 0,                                      /* oplock_request */
    8068             :                 NULL,                                   /* lease */
    8069             :                 0,                                      /* allocation_size */
    8070             :                 0,                                      /* private_flags */
    8071             :                 NULL,                                   /* sd */
    8072             :                 NULL,                                   /* ea_list */
    8073             :                 &new_fsp,                           /* result */
    8074             :                 NULL,                                   /* pinfo */
    8075             :                 NULL, NULL);                            /* create context */
    8076             : 
    8077          12 :         if (!NT_STATUS_IS_OK(status)) {
    8078             :                 /* NB. We check for open_was_deferred in the caller. */
    8079          10 :                 return status;
    8080             :         }
    8081             : 
    8082             :         /* Only change if needed. */
    8083           2 :         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    8084           2 :                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
    8085           0 :                         status = map_nt_error_from_unix(errno);
    8086           0 :                         close_file(req, new_fsp, NORMAL_CLOSE);
    8087           0 :                         return status;
    8088             :                 }
    8089             :         }
    8090             : 
    8091             :         /* Changing the allocation size should set the last mod time. */
    8092             :         /*
    8093             :          * This is equivalent to a write. Ensure it's seen immediately
    8094             :          * if there are no pending writes.
    8095             :          */
    8096           2 :         trigger_write_time_update_immediate(new_fsp);
    8097           2 :         close_file(req, new_fsp, NORMAL_CLOSE);
    8098           2 :         return NT_STATUS_OK;
    8099             : }
    8100             : 
    8101             : /****************************************************************************
    8102             :  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
    8103             : ****************************************************************************/
    8104             : 
    8105         329 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
    8106             :                                               struct smb_request *req,
    8107             :                                         const char *pdata,
    8108             :                                         int total_data,
    8109             :                                         files_struct *fsp,
    8110             :                                         struct smb_filename *smb_fname,
    8111             :                                         bool fail_after_createfile)
    8112             : {
    8113             :         off_t size;
    8114             : 
    8115         329 :         if (total_data < 8) {
    8116           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8117             :         }
    8118             : 
    8119         329 :         size = IVAL(pdata,0);
    8120         329 :         size |= (((off_t)IVAL(pdata,4)) << 32);
    8121         329 :         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
    8122             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    8123             :                   (double)size));
    8124             : 
    8125         658 :         return smb_set_file_size(conn, req,
    8126             :                                 fsp,
    8127             :                                 smb_fname,
    8128         329 :                                 &smb_fname->st,
    8129             :                                 size,
    8130             :                                 fail_after_createfile);
    8131             : }
    8132             : 
    8133             : /****************************************************************************
    8134             :  Allow a UNIX info mknod.
    8135             : ****************************************************************************/
    8136             : 
    8137           0 : static NTSTATUS smb_unix_mknod(connection_struct *conn,
    8138             :                                         const char *pdata,
    8139             :                                         int total_data,
    8140             :                                         const struct smb_filename *smb_fname)
    8141             : {
    8142           0 :         uint32_t file_type = IVAL(pdata,56);
    8143             : #if defined(HAVE_MAKEDEV)
    8144           0 :         uint32_t dev_major = IVAL(pdata,60);
    8145           0 :         uint32_t dev_minor = IVAL(pdata,68);
    8146             : #endif
    8147           0 :         SMB_DEV_T dev = (SMB_DEV_T)0;
    8148           0 :         uint32_t raw_unixmode = IVAL(pdata,84);
    8149             :         NTSTATUS status;
    8150             :         mode_t unixmode;
    8151             :         int ret;
    8152           0 :         struct smb_filename *parent_fname = NULL;
    8153           0 :         struct smb_filename *base_name = NULL;
    8154             : 
    8155           0 :         if (total_data < 100) {
    8156           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8157             :         }
    8158             : 
    8159           0 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    8160             :                                       PERM_NEW_FILE, &unixmode);
    8161           0 :         if (!NT_STATUS_IS_OK(status)) {
    8162           0 :                 return status;
    8163             :         }
    8164             : 
    8165             : #if defined(HAVE_MAKEDEV)
    8166           0 :         dev = makedev(dev_major, dev_minor);
    8167             : #endif
    8168             : 
    8169           0 :         switch (file_type) {
    8170             :                 /* We can't create other objects here. */
    8171           0 :                 case UNIX_TYPE_FILE:
    8172             :                 case UNIX_TYPE_DIR:
    8173             :                 case UNIX_TYPE_SYMLINK:
    8174           0 :                         return NT_STATUS_ACCESS_DENIED;
    8175             : #if defined(S_IFIFO)
    8176           0 :                 case UNIX_TYPE_FIFO:
    8177           0 :                         unixmode |= S_IFIFO;
    8178           0 :                         break;
    8179             : #endif
    8180             : #if defined(S_IFSOCK)
    8181           0 :                 case UNIX_TYPE_SOCKET:
    8182           0 :                         unixmode |= S_IFSOCK;
    8183           0 :                         break;
    8184             : #endif
    8185             : #if defined(S_IFCHR)
    8186           0 :                 case UNIX_TYPE_CHARDEV:
    8187             :                         /* This is only allowed for root. */
    8188           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    8189           0 :                                 return NT_STATUS_ACCESS_DENIED;
    8190             :                         }
    8191           0 :                         unixmode |= S_IFCHR;
    8192           0 :                         break;
    8193             : #endif
    8194             : #if defined(S_IFBLK)
    8195           0 :                 case UNIX_TYPE_BLKDEV:
    8196           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    8197           0 :                                 return NT_STATUS_ACCESS_DENIED;
    8198             :                         }
    8199           0 :                         unixmode |= S_IFBLK;
    8200           0 :                         break;
    8201             : #endif
    8202           0 :                 default:
    8203           0 :                         return NT_STATUS_INVALID_PARAMETER;
    8204             :         }
    8205             : 
    8206           0 :         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
    8207             :                   "%.0f mode 0%o for file %s\n", (double)dev,
    8208             :                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
    8209             : 
    8210           0 :         status = parent_pathref(talloc_tos(),
    8211             :                                 conn->cwd_fsp,
    8212             :                                 smb_fname,
    8213             :                                 &parent_fname,
    8214             :                                 &base_name);
    8215           0 :         if (!NT_STATUS_IS_OK(status)) {
    8216           0 :                 return status;
    8217             :         }
    8218             : 
    8219             :         /* Ok - do the mknod. */
    8220           0 :         ret = SMB_VFS_MKNODAT(conn,
    8221             :                         parent_fname->fsp,
    8222             :                         base_name,
    8223             :                         unixmode,
    8224             :                         dev);
    8225             : 
    8226           0 :         if (ret != 0) {
    8227           0 :                 TALLOC_FREE(parent_fname);
    8228           0 :                 return map_nt_error_from_unix(errno);
    8229             :         }
    8230             : 
    8231             :         /* If any of the other "set" calls fail we
    8232             :          * don't want to end up with a half-constructed mknod.
    8233             :          */
    8234             : 
    8235           0 :         if (lp_inherit_permissions(SNUM(conn))) {
    8236           0 :                 inherit_access_posix_acl(conn,
    8237             :                                          parent_fname,
    8238             :                                          smb_fname,
    8239             :                                          unixmode);
    8240             :         }
    8241           0 :         TALLOC_FREE(parent_fname);
    8242             : 
    8243           0 :         return NT_STATUS_OK;
    8244             : }
    8245             : 
    8246             : /****************************************************************************
    8247             :  Deal with SMB_SET_FILE_UNIX_BASIC.
    8248             : ****************************************************************************/
    8249             : 
    8250         180 : static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
    8251             :                                         struct smb_request *req,
    8252             :                                         const char *pdata,
    8253             :                                         int total_data,
    8254             :                                         files_struct *fsp,
    8255             :                                         struct smb_filename *smb_fname)
    8256             : {
    8257             :         struct smb_file_time ft;
    8258             :         uint32_t raw_unixmode;
    8259             :         mode_t unixmode;
    8260         180 :         off_t size = 0;
    8261         180 :         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
    8262         180 :         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
    8263         180 :         NTSTATUS status = NT_STATUS_OK;
    8264             :         enum perm_type ptype;
    8265         180 :         files_struct *all_fsps = NULL;
    8266         180 :         bool modify_mtime = true;
    8267             :         struct file_id id;
    8268             :         SMB_STRUCT_STAT sbuf;
    8269             : 
    8270         180 :         init_smb_file_time(&ft);
    8271             : 
    8272         180 :         if (total_data < 100) {
    8273           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8274             :         }
    8275             : 
    8276         196 :         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
    8277          16 :            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
    8278          16 :                 size=IVAL(pdata,0); /* first 8 Bytes are size */
    8279          16 :                 size |= (((off_t)IVAL(pdata,4)) << 32);
    8280             :         }
    8281             : 
    8282         180 :         ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
    8283         180 :         ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
    8284         180 :         set_owner = (uid_t)IVAL(pdata,40);
    8285         180 :         set_grp = (gid_t)IVAL(pdata,48);
    8286         180 :         raw_unixmode = IVAL(pdata,84);
    8287             : 
    8288         180 :         if (VALID_STAT(smb_fname->st)) {
    8289         180 :                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    8290          16 :                         ptype = PERM_EXISTING_DIR;
    8291             :                 } else {
    8292         164 :                         ptype = PERM_EXISTING_FILE;
    8293             :                 }
    8294             :         } else {
    8295           0 :                 ptype = PERM_NEW_FILE;
    8296             :         }
    8297             : 
    8298         180 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    8299             :                                       ptype, &unixmode);
    8300         180 :         if (!NT_STATUS_IS_OK(status)) {
    8301           0 :                 return status;
    8302             :         }
    8303             : 
    8304         180 :         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
    8305             :                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
    8306             :                   smb_fname_str_dbg(smb_fname), (double)size,
    8307             :                   (unsigned int)set_owner, (unsigned int)set_grp,
    8308             :                   (int)raw_unixmode));
    8309             : 
    8310         180 :         sbuf = smb_fname->st;
    8311             : 
    8312         180 :         if (!VALID_STAT(sbuf)) {
    8313             :                 /*
    8314             :                  * The only valid use of this is to create character and block
    8315             :                  * devices, and named pipes. This is deprecated (IMHO) and 
    8316             :                  * a new info level should be used for mknod. JRA.
    8317             :                  */
    8318             : 
    8319           0 :                 return smb_unix_mknod(conn,
    8320             :                                         pdata,
    8321             :                                         total_data,
    8322             :                                         smb_fname);
    8323             :         }
    8324             : 
    8325             : #if 1
    8326             :         /* Horrible backwards compatibility hack as an old server bug
    8327             :          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
    8328             :          * */
    8329             : 
    8330         180 :         if (!size) {
    8331         180 :                 size = get_file_size_stat(&sbuf);
    8332             :         }
    8333             : #endif
    8334             : 
    8335             :         /*
    8336             :          * Deal with the UNIX specific mode set.
    8337             :          */
    8338             : 
    8339         180 :         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
    8340             :                 int ret;
    8341             : 
    8342          48 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    8343          24 :                         DBG_WARNING("Can't set mode on symlink %s\n",
    8344             :                                 smb_fname_str_dbg(smb_fname));
    8345          24 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    8346             :                 }
    8347             : 
    8348          24 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    8349             :                           "setting mode 0%o for file %s\n",
    8350             :                           (unsigned int)unixmode,
    8351             :                           smb_fname_str_dbg(smb_fname)));
    8352          24 :                 ret = SMB_VFS_FCHMOD(fsp, unixmode);
    8353          24 :                 if (ret != 0) {
    8354           0 :                         return map_nt_error_from_unix(errno);
    8355             :                 }
    8356             :         }
    8357             : 
    8358             :         /*
    8359             :          * Deal with the UNIX specific uid set.
    8360             :          */
    8361             : 
    8362         156 :         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
    8363           0 :             (sbuf.st_ex_uid != set_owner)) {
    8364             :                 int ret;
    8365             : 
    8366           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    8367             :                           "changing owner %u for path %s\n",
    8368             :                           (unsigned int)set_owner,
    8369             :                           smb_fname_str_dbg(smb_fname)));
    8370             : 
    8371           0 :                 if (fsp &&
    8372           0 :                     !fsp->fsp_flags.is_pathref &&
    8373           0 :                     fsp_get_io_fd(fsp) != -1)
    8374             :                 {
    8375           0 :                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
    8376             :                 } else {
    8377             :                         /*
    8378             :                          * UNIX extensions calls must always operate
    8379             :                          * on symlinks.
    8380             :                          */
    8381           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname,
    8382             :                                              set_owner, (gid_t)-1);
    8383             :                 }
    8384             : 
    8385           0 :                 if (ret != 0) {
    8386           0 :                         status = map_nt_error_from_unix(errno);
    8387           0 :                         return status;
    8388             :                 }
    8389             :         }
    8390             : 
    8391             :         /*
    8392             :          * Deal with the UNIX specific gid set.
    8393             :          */
    8394             : 
    8395         156 :         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
    8396           0 :             (sbuf.st_ex_gid != set_grp)) {
    8397             :                 int ret;
    8398             : 
    8399           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    8400             :                           "changing group %u for file %s\n",
    8401             :                           (unsigned int)set_grp,
    8402             :                           smb_fname_str_dbg(smb_fname)));
    8403           0 :                 if (fsp &&
    8404           0 :                     !fsp->fsp_flags.is_pathref &&
    8405           0 :                     fsp_get_io_fd(fsp) != -1)
    8406             :                 {
    8407           0 :                         ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
    8408             :                 } else {
    8409             :                         /*
    8410             :                          * UNIX extensions calls must always operate
    8411             :                          * on symlinks.
    8412             :                          */
    8413           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
    8414             :                                   set_grp);
    8415             :                 }
    8416           0 :                 if (ret != 0) {
    8417           0 :                         status = map_nt_error_from_unix(errno);
    8418           0 :                         return status;
    8419             :                 }
    8420             :         }
    8421             : 
    8422             :         /* Deal with any size changes. */
    8423             : 
    8424         156 :         if (S_ISREG(sbuf.st_ex_mode)) {
    8425         140 :                 status = smb_set_file_size(conn, req,
    8426             :                                            fsp,
    8427             :                                            smb_fname,
    8428             :                                            &sbuf,
    8429             :                                            size,
    8430             :                                            false);
    8431         140 :                 if (!NT_STATUS_IS_OK(status)) {
    8432           0 :                         return status;
    8433             :                 }
    8434             :         }
    8435             : 
    8436             :         /* Deal with any time changes. */
    8437         156 :         if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
    8438             :                 /* No change, don't cancel anything. */
    8439         156 :                 return status;
    8440             :         }
    8441             : 
    8442           0 :         id = vfs_file_id_from_sbuf(conn, &sbuf);
    8443           0 :         for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
    8444           0 :                         all_fsps = file_find_di_next(all_fsps, true)) {
    8445             :                 /*
    8446             :                  * We're setting the time explicitly for UNIX.
    8447             :                  * Cancel any pending changes over all handles.
    8448             :                  */
    8449           0 :                 all_fsps->fsp_flags.update_write_time_on_close = false;
    8450           0 :                 TALLOC_FREE(all_fsps->update_write_time_event);
    8451             :         }
    8452             : 
    8453             :         /*
    8454             :          * Override the "setting_write_time"
    8455             :          * parameter here as it almost does what
    8456             :          * we need. Just remember if we modified
    8457             :          * mtime and send the notify ourselves.
    8458             :          */
    8459           0 :         if (is_omit_timespec(&ft.mtime)) {
    8460           0 :                 modify_mtime = false;
    8461             :         }
    8462             : 
    8463           0 :         status = smb_set_file_time(conn,
    8464             :                                 fsp,
    8465             :                                 smb_fname,
    8466             :                                 &ft,
    8467             :                                 false);
    8468           0 :         if (modify_mtime) {
    8469           0 :                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
    8470           0 :                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
    8471             :         }
    8472           0 :         return status;
    8473             : }
    8474             : 
    8475             : /****************************************************************************
    8476             :  Deal with SMB_SET_FILE_UNIX_INFO2.
    8477             : ****************************************************************************/
    8478             : 
    8479         140 : static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
    8480             :                                         struct smb_request *req,
    8481             :                                         const char *pdata,
    8482             :                                         int total_data,
    8483             :                                         files_struct *fsp,
    8484             :                                         struct smb_filename *smb_fname)
    8485             : {
    8486             :         NTSTATUS status;
    8487             :         uint32_t smb_fflags;
    8488             :         uint32_t smb_fmask;
    8489             : 
    8490         140 :         if (total_data < 116) {
    8491           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8492             :         }
    8493             : 
    8494             :         /* Start by setting all the fields that are common between UNIX_BASIC
    8495             :          * and UNIX_INFO2.
    8496             :          */
    8497         140 :         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
    8498             :                                          fsp, smb_fname);
    8499         140 :         if (!NT_STATUS_IS_OK(status)) {
    8500           8 :                 return status;
    8501             :         }
    8502             : 
    8503         132 :         smb_fflags = IVAL(pdata, 108);
    8504         132 :         smb_fmask = IVAL(pdata, 112);
    8505             : 
    8506             :         /* NB: We should only attempt to alter the file flags if the client
    8507             :          * sends a non-zero mask.
    8508             :          */
    8509         132 :         if (smb_fmask != 0) {
    8510         128 :                 int stat_fflags = 0;
    8511             : 
    8512         128 :                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
    8513             :                                              smb_fmask, &stat_fflags)) {
    8514             :                         /* Client asked to alter a flag we don't understand. */
    8515         256 :                         return NT_STATUS_INVALID_PARAMETER;
    8516             :                 }
    8517             : 
    8518           0 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    8519           0 :                         DBG_WARNING("Can't change flags on symlink %s\n",
    8520             :                                 smb_fname_str_dbg(smb_fname));
    8521           0 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    8522             :                 }
    8523           0 :                 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
    8524           0 :                         return map_nt_error_from_unix(errno);
    8525             :                 }
    8526             :         }
    8527             : 
    8528             :         /* XXX: need to add support for changing the create_time here. You
    8529             :          * can do this for paths on Darwin with setattrlist(2). The right way
    8530             :          * to hook this up is probably by extending the VFS utimes interface.
    8531             :          */
    8532             : 
    8533           4 :         return NT_STATUS_OK;
    8534             : }
    8535             : 
    8536             : /****************************************************************************
    8537             :  Create a directory with POSIX semantics.
    8538             : ****************************************************************************/
    8539             : 
    8540          48 : static NTSTATUS smb_posix_mkdir(connection_struct *conn,
    8541             :                                 struct smb_request *req,
    8542             :                                 char **ppdata,
    8543             :                                 int total_data,
    8544             :                                 struct smb_filename *smb_fname,
    8545             :                                 int *pdata_return_size)
    8546             : {
    8547          48 :         NTSTATUS status = NT_STATUS_OK;
    8548          48 :         uint32_t raw_unixmode = 0;
    8549          48 :         mode_t unixmode = (mode_t)0;
    8550          48 :         files_struct *fsp = NULL;
    8551          48 :         uint16_t info_level_return = 0;
    8552             :         int info;
    8553          48 :         char *pdata = *ppdata;
    8554          48 :         struct smb2_create_blobs *posx = NULL;
    8555             : 
    8556          48 :         if (total_data < 18) {
    8557           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8558             :         }
    8559             : 
    8560          48 :         raw_unixmode = IVAL(pdata,8);
    8561             :         /* Next 4 bytes are not yet defined. */
    8562             : 
    8563          48 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    8564             :                                       PERM_NEW_DIR, &unixmode);
    8565          48 :         if (!NT_STATUS_IS_OK(status)) {
    8566           0 :                 return status;
    8567             :         }
    8568             : 
    8569          48 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    8570          48 :         if (!NT_STATUS_IS_OK(status)) {
    8571           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    8572             :                             nt_errstr(status));
    8573           0 :                 return status;
    8574             :         }
    8575             : 
    8576          48 :         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
    8577             :                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
    8578             : 
    8579          48 :         status = SMB_VFS_CREATE_FILE(
    8580             :                 conn,                                   /* conn */
    8581             :                 req,                                    /* req */
    8582             :                 smb_fname,                              /* fname */
    8583             :                 FILE_READ_ATTRIBUTES,                   /* access_mask */
    8584             :                 FILE_SHARE_NONE,                        /* share_access */
    8585             :                 FILE_CREATE,                            /* create_disposition*/
    8586             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    8587             :                 0,                                      /* file_attributes */
    8588             :                 0,                                      /* oplock_request */
    8589             :                 NULL,                                   /* lease */
    8590             :                 0,                                      /* allocation_size */
    8591             :                 0,                                      /* private_flags */
    8592             :                 NULL,                                   /* sd */
    8593             :                 NULL,                                   /* ea_list */
    8594             :                 &fsp,                                       /* result */
    8595             :                 &info,                                      /* pinfo */
    8596             :                 posx,                                   /* in_context_blobs */
    8597             :                 NULL);                                  /* out_context_blobs */
    8598             : 
    8599          48 :         TALLOC_FREE(posx);
    8600             : 
    8601          48 :         if (NT_STATUS_IS_OK(status)) {
    8602          48 :                 close_file(req, fsp, NORMAL_CLOSE);
    8603             :         }
    8604             : 
    8605          48 :         info_level_return = SVAL(pdata,16);
    8606             :  
    8607          48 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    8608           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    8609          48 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    8610           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    8611             :         } else {
    8612          48 :                 *pdata_return_size = 12;
    8613             :         }
    8614             : 
    8615             :         /* Realloc the data size */
    8616          48 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    8617          48 :         if (*ppdata == NULL) {
    8618           0 :                 *pdata_return_size = 0;
    8619           0 :                 return NT_STATUS_NO_MEMORY;
    8620             :         }
    8621          48 :         pdata = *ppdata;
    8622             : 
    8623          48 :         SSVAL(pdata,0,NO_OPLOCK_RETURN);
    8624          48 :         SSVAL(pdata,2,0); /* No fnum. */
    8625          48 :         SIVAL(pdata,4,info); /* Was directory created. */
    8626             : 
    8627          48 :         switch (info_level_return) {
    8628           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    8629           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    8630           0 :                         SSVAL(pdata,10,0); /* Padding. */
    8631           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    8632           0 :                                               &smb_fname->st);
    8633           0 :                         break;
    8634           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    8635           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    8636           0 :                         SSVAL(pdata,10,0); /* Padding. */
    8637           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    8638           0 :                                                     &smb_fname->st);
    8639           0 :                         break;
    8640          48 :                 default:
    8641          48 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    8642          48 :                         SSVAL(pdata,10,0); /* Padding. */
    8643          48 :                         break;
    8644             :         }
    8645             : 
    8646          48 :         return status;
    8647             : }
    8648             : 
    8649             : /****************************************************************************
    8650             :  Open/Create a file with POSIX semantics.
    8651             : ****************************************************************************/
    8652             : 
    8653             : #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
    8654             : #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
    8655             : 
    8656         174 : static NTSTATUS smb_posix_open(connection_struct *conn,
    8657             :                                struct smb_request *req,
    8658             :                                 char **ppdata,
    8659             :                                 int total_data,
    8660             :                                 struct smb_filename *smb_fname,
    8661             :                                 int *pdata_return_size)
    8662             : {
    8663         174 :         bool extended_oplock_granted = False;
    8664         174 :         char *pdata = *ppdata;
    8665         174 :         uint32_t flags = 0;
    8666         174 :         uint32_t wire_open_mode = 0;
    8667         174 :         uint32_t raw_unixmode = 0;
    8668         174 :         uint32_t attributes = 0;
    8669         174 :         uint32_t create_disp = 0;
    8670         174 :         uint32_t access_mask = 0;
    8671         174 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
    8672         174 :         NTSTATUS status = NT_STATUS_OK;
    8673         174 :         mode_t unixmode = (mode_t)0;
    8674         174 :         files_struct *fsp = NULL;
    8675         174 :         int oplock_request = 0;
    8676         174 :         int info = 0;
    8677         174 :         uint16_t info_level_return = 0;
    8678         174 :         struct smb2_create_blobs *posx = NULL;
    8679             : 
    8680         174 :         if (total_data < 18) {
    8681           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8682             :         }
    8683             : 
    8684         174 :         flags = IVAL(pdata,0);
    8685         174 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
    8686         174 :         if (oplock_request) {
    8687           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
    8688             :         }
    8689             : 
    8690         174 :         wire_open_mode = IVAL(pdata,4);
    8691             : 
    8692         174 :         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
    8693          48 :                 return smb_posix_mkdir(conn, req,
    8694             :                                         ppdata,
    8695             :                                         total_data,
    8696             :                                         smb_fname,
    8697             :                                         pdata_return_size);
    8698             :         }
    8699             : 
    8700         126 :         switch (wire_open_mode & SMB_ACCMODE) {
    8701          28 :                 case SMB_O_RDONLY:
    8702          28 :                         access_mask = SMB_O_RDONLY_MAPPING;
    8703          28 :                         break;
    8704           4 :                 case SMB_O_WRONLY:
    8705           4 :                         access_mask = SMB_O_WRONLY_MAPPING;
    8706           4 :                         break;
    8707          94 :                 case SMB_O_RDWR:
    8708          94 :                         access_mask = (SMB_O_RDONLY_MAPPING|
    8709             :                                         SMB_O_WRONLY_MAPPING);
    8710          94 :                         break;
    8711           0 :                 default:
    8712           0 :                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
    8713             :                                 (unsigned int)wire_open_mode ));
    8714           0 :                         return NT_STATUS_INVALID_PARAMETER;
    8715             :         }
    8716             : 
    8717         126 :         wire_open_mode &= ~SMB_ACCMODE;
    8718             : 
    8719             :         /* First take care of O_CREAT|O_EXCL interactions. */
    8720         126 :         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
    8721          38 :                 case (SMB_O_CREAT | SMB_O_EXCL):
    8722             :                         /* File exists fail. File not exist create. */
    8723          38 :                         create_disp = FILE_CREATE;
    8724          38 :                         break;
    8725          40 :                 case SMB_O_CREAT:
    8726             :                         /* File exists open. File not exist create. */
    8727          40 :                         create_disp = FILE_OPEN_IF;
    8728          40 :                         break;
    8729          48 :                 case SMB_O_EXCL:
    8730             :                         /* O_EXCL on its own without O_CREAT is undefined.
    8731             :                            We deliberately ignore it as some versions of
    8732             :                            Linux CIFSFS can send a bare O_EXCL on the
    8733             :                            wire which other filesystems in the kernel
    8734             :                            ignore. See bug 9519 for details. */
    8735             : 
    8736             :                         /* Fallthrough. */
    8737             : 
    8738             :                 case 0:
    8739             :                         /* File exists open. File not exist fail. */
    8740          48 :                         create_disp = FILE_OPEN;
    8741          48 :                         break;
    8742           0 :                 default:
    8743           0 :                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
    8744             :                                 (unsigned int)wire_open_mode ));
    8745           0 :                         return NT_STATUS_INVALID_PARAMETER;
    8746             :         }
    8747             : 
    8748             :         /* Next factor in the effects of O_TRUNC. */
    8749         126 :         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
    8750             : 
    8751         126 :         if (wire_open_mode & SMB_O_TRUNC) {
    8752           4 :                 switch (create_disp) {
    8753           0 :                         case FILE_CREATE:
    8754             :                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
    8755             :                                 /* Leave create_disp alone as
    8756             :                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
    8757             :                                 */
    8758             :                                 /* File exists fail. File not exist create. */
    8759           0 :                                 break;
    8760           0 :                         case FILE_OPEN_IF:
    8761             :                                 /* SMB_O_CREAT | SMB_O_TRUNC */
    8762             :                                 /* File exists overwrite. File not exist create. */
    8763           0 :                                 create_disp = FILE_OVERWRITE_IF;
    8764           0 :                                 break;
    8765           4 :                         case FILE_OPEN:
    8766             :                                 /* SMB_O_TRUNC */
    8767             :                                 /* File exists overwrite. File not exist fail. */
    8768           4 :                                 create_disp = FILE_OVERWRITE;
    8769           4 :                                 break;
    8770           0 :                         default:
    8771             :                                 /* Cannot get here. */
    8772           0 :                                 smb_panic("smb_posix_open: logic error");
    8773             :                                 return NT_STATUS_INVALID_PARAMETER;
    8774             :                 }
    8775         122 :         }
    8776             : 
    8777         126 :         raw_unixmode = IVAL(pdata,8);
    8778             :         /* Next 4 bytes are not yet defined. */
    8779             : 
    8780         126 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    8781         126 :                                       (VALID_STAT(smb_fname->st) ?
    8782             :                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
    8783             :                                       &unixmode);
    8784             : 
    8785         126 :         if (!NT_STATUS_IS_OK(status)) {
    8786           0 :                 return status;
    8787             :         }
    8788             : 
    8789         126 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    8790         126 :         if (!NT_STATUS_IS_OK(status)) {
    8791           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    8792             :                             nt_errstr(status));
    8793           0 :                 return status;
    8794             :         }
    8795             : 
    8796         126 :         if (wire_open_mode & SMB_O_SYNC) {
    8797           0 :                 create_options |= FILE_WRITE_THROUGH;
    8798             :         }
    8799         126 :         if (wire_open_mode & SMB_O_APPEND) {
    8800           0 :                 access_mask |= FILE_APPEND_DATA;
    8801             :         }
    8802         126 :         if (wire_open_mode & SMB_O_DIRECT) {
    8803           0 :                 attributes |= FILE_FLAG_NO_BUFFERING;
    8804             :         }
    8805             : 
    8806         252 :         if ((wire_open_mode & SMB_O_DIRECTORY) ||
    8807         170 :                         VALID_STAT_OF_DIR(smb_fname->st)) {
    8808           8 :                 if (access_mask != SMB_O_RDONLY_MAPPING) {
    8809           4 :                         return NT_STATUS_FILE_IS_A_DIRECTORY;
    8810             :                 }
    8811           4 :                 create_options &= ~FILE_NON_DIRECTORY_FILE;
    8812           4 :                 create_options |= FILE_DIRECTORY_FILE;
    8813             :         }
    8814             : 
    8815         122 :         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
    8816             :                 smb_fname_str_dbg(smb_fname),
    8817             :                 (unsigned int)wire_open_mode,
    8818             :                 (unsigned int)unixmode ));
    8819             : 
    8820         122 :         status = SMB_VFS_CREATE_FILE(
    8821             :                 conn,                                   /* conn */
    8822             :                 req,                                    /* req */
    8823             :                 smb_fname,                              /* fname */
    8824             :                 access_mask,                            /* access_mask */
    8825             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    8826             :                     FILE_SHARE_DELETE),
    8827             :                 create_disp,                            /* create_disposition*/
    8828             :                 create_options,                         /* create_options */
    8829             :                 attributes,                             /* file_attributes */
    8830             :                 oplock_request,                         /* oplock_request */
    8831             :                 NULL,                                   /* lease */
    8832             :                 0,                                      /* allocation_size */
    8833             :                 0,                                      /* private_flags */
    8834             :                 NULL,                                   /* sd */
    8835             :                 NULL,                                   /* ea_list */
    8836             :                 &fsp,                                       /* result */
    8837             :                 &info,                                      /* pinfo */
    8838             :                 posx,                                   /* in_context_blobs */
    8839             :                 NULL);                                  /* out_context_blobs */
    8840             : 
    8841         122 :         TALLOC_FREE(posx);
    8842             : 
    8843         122 :         if (!NT_STATUS_IS_OK(status)) {
    8844           8 :                 return status;
    8845             :         }
    8846             : 
    8847         114 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    8848           0 :                 extended_oplock_granted = True;
    8849             :         }
    8850             : 
    8851         114 :         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    8852           0 :                 extended_oplock_granted = True;
    8853             :         }
    8854             : 
    8855         114 :         info_level_return = SVAL(pdata,16);
    8856             :  
    8857             :         /* Allocate the correct return size. */
    8858             : 
    8859         114 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    8860           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    8861         114 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    8862           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    8863             :         } else {
    8864         114 :                 *pdata_return_size = 12;
    8865             :         }
    8866             : 
    8867             :         /* Realloc the data size */
    8868         114 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    8869         114 :         if (*ppdata == NULL) {
    8870           0 :                 close_file(req, fsp, ERROR_CLOSE);
    8871           0 :                 *pdata_return_size = 0;
    8872           0 :                 return NT_STATUS_NO_MEMORY;
    8873             :         }
    8874         114 :         pdata = *ppdata;
    8875             : 
    8876         114 :         if (extended_oplock_granted) {
    8877           0 :                 if (flags & REQUEST_BATCH_OPLOCK) {
    8878           0 :                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
    8879             :                 } else {
    8880           0 :                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
    8881             :                 }
    8882         114 :         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
    8883           0 :                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
    8884             :         } else {
    8885         114 :                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
    8886             :         }
    8887             : 
    8888         114 :         SSVAL(pdata,2,fsp->fnum);
    8889         114 :         SIVAL(pdata,4,info); /* Was file created etc. */
    8890             : 
    8891         114 :         switch (info_level_return) {
    8892           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    8893           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    8894           0 :                         SSVAL(pdata,10,0); /* padding. */
    8895           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    8896           0 :                                               &smb_fname->st);
    8897           0 :                         break;
    8898           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    8899           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    8900           0 :                         SSVAL(pdata,10,0); /* padding. */
    8901           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    8902           0 :                                                     &smb_fname->st);
    8903           0 :                         break;
    8904         114 :                 default:
    8905         114 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    8906         114 :                         SSVAL(pdata,10,0); /* padding. */
    8907         114 :                         break;
    8908             :         }
    8909         114 :         return NT_STATUS_OK;
    8910             : }
    8911             : 
    8912             : /****************************************************************************
    8913             :  Delete a file with POSIX semantics.
    8914             : ****************************************************************************/
    8915             : 
    8916         540 : static NTSTATUS smb_posix_unlink(connection_struct *conn,
    8917             :                                  struct smb_request *req,
    8918             :                                 const char *pdata,
    8919             :                                 int total_data,
    8920             :                                 struct smb_filename *smb_fname)
    8921             : {
    8922         540 :         NTSTATUS status = NT_STATUS_OK;
    8923         540 :         files_struct *fsp = NULL;
    8924         540 :         uint16_t flags = 0;
    8925         540 :         char del = 1;
    8926         540 :         int info = 0;
    8927         540 :         int create_options = 0;
    8928         540 :         struct share_mode_lock *lck = NULL;
    8929             :         bool other_nonposix_opens;
    8930         540 :         struct smb2_create_blobs *posx = NULL;
    8931             : 
    8932         540 :         if (total_data < 2) {
    8933           0 :                 return NT_STATUS_INVALID_PARAMETER;
    8934             :         }
    8935             : 
    8936         540 :         flags = SVAL(pdata,0);
    8937             : 
    8938         540 :         if (!VALID_STAT(smb_fname->st)) {
    8939         280 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    8940             :         }
    8941             : 
    8942         304 :         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
    8943          88 :                         !VALID_STAT_OF_DIR(smb_fname->st)) {
    8944           0 :                 return NT_STATUS_NOT_A_DIRECTORY;
    8945             :         }
    8946             : 
    8947         260 :         DEBUG(10,("smb_posix_unlink: %s %s\n",
    8948             :                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
    8949             :                 smb_fname_str_dbg(smb_fname)));
    8950             : 
    8951         260 :         if (VALID_STAT_OF_DIR(smb_fname->st)) {
    8952          48 :                 create_options |= FILE_DIRECTORY_FILE;
    8953             :         }
    8954             : 
    8955         260 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
    8956         260 :         if (!NT_STATUS_IS_OK(status)) {
    8957           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    8958             :                             nt_errstr(status));
    8959           0 :                 return status;
    8960             :         }
    8961             : 
    8962         260 :         status = SMB_VFS_CREATE_FILE(
    8963             :                 conn,                                   /* conn */
    8964             :                 req,                                    /* req */
    8965             :                 smb_fname,                              /* fname */
    8966             :                 DELETE_ACCESS,                          /* access_mask */
    8967             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    8968             :                     FILE_SHARE_DELETE),
    8969             :                 FILE_OPEN,                              /* create_disposition*/
    8970             :                 create_options,                         /* create_options */
    8971             :                 0,                                      /* file_attributes */
    8972             :                 0,                                      /* oplock_request */
    8973             :                 NULL,                                   /* lease */
    8974             :                 0,                                      /* allocation_size */
    8975             :                 0,                                      /* private_flags */
    8976             :                 NULL,                                   /* sd */
    8977             :                 NULL,                                   /* ea_list */
    8978             :                 &fsp,                                       /* result */
    8979             :                 &info,                                      /* pinfo */
    8980             :                 posx,                                   /* in_context_blobs */
    8981             :                 NULL);                                  /* out_context_blobs */
    8982             : 
    8983         260 :         TALLOC_FREE(posx);
    8984             : 
    8985         260 :         if (!NT_STATUS_IS_OK(status)) {
    8986           8 :                 return status;
    8987             :         }
    8988             : 
    8989             :         /*
    8990             :          * Don't lie to client. If we can't really delete due to
    8991             :          * non-POSIX opens return SHARING_VIOLATION.
    8992             :          */
    8993             : 
    8994         252 :         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
    8995         252 :         if (lck == NULL) {
    8996           0 :                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
    8997             :                           "lock for file %s\n", fsp_str_dbg(fsp)));
    8998           0 :                 close_file(req, fsp, NORMAL_CLOSE);
    8999           0 :                 return NT_STATUS_INVALID_PARAMETER;
    9000             :         }
    9001             : 
    9002         252 :         other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
    9003         252 :         if (other_nonposix_opens) {
    9004             :                 /* Fail with sharing violation. */
    9005           8 :                 TALLOC_FREE(lck);
    9006           8 :                 close_file(req, fsp, NORMAL_CLOSE);
    9007           8 :                 return NT_STATUS_SHARING_VIOLATION;
    9008             :         }
    9009             : 
    9010             :         /*
    9011             :          * Set the delete on close.
    9012             :          */
    9013         244 :         status = smb_set_file_disposition_info(conn,
    9014             :                                                 &del,
    9015             :                                                 1,
    9016             :                                                 fsp,
    9017             :                                                 smb_fname);
    9018             : 
    9019         244 :         TALLOC_FREE(lck);
    9020             : 
    9021         244 :         if (!NT_STATUS_IS_OK(status)) {
    9022           0 :                 close_file(req, fsp, NORMAL_CLOSE);
    9023           0 :                 return status;
    9024             :         }
    9025         244 :         return close_file(req, fsp, NORMAL_CLOSE);
    9026             : }
    9027             : 
    9028        1088 : static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
    9029             :                                               struct smb_request *req,
    9030             :                                               TALLOC_CTX *mem_ctx,
    9031             :                                               uint16_t info_level,
    9032             :                                               struct smb_filename *smb_fname,
    9033             :                                               files_struct *fsp,
    9034             :                                               char **ppdata,
    9035             :                                               int total_data,
    9036             :                                               int *ret_data_size)
    9037             : {
    9038        1088 :         char *pdata = *ppdata;
    9039        1088 :         NTSTATUS status = NT_STATUS_OK;
    9040        1088 :         int data_return_size = 0;
    9041             : 
    9042        1088 :         *ret_data_size = 0;
    9043             : 
    9044        1088 :         if (!CAN_WRITE(conn)) {
    9045             :                 /* Allow POSIX opens. The open path will deny
    9046             :                  * any non-readonly opens. */
    9047           0 :                 if (info_level != SMB_POSIX_PATH_OPEN) {
    9048           0 :                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
    9049             :                 }
    9050             :         }
    9051             : 
    9052        1088 :         DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
    9053             :                   smb_fname_str_dbg(smb_fname),
    9054             :                   fsp_fnum_dbg(fsp),
    9055             :                   info_level,
    9056             :                   total_data);
    9057             : 
    9058        1088 :         switch (info_level) {
    9059          40 :                 case SMB_SET_FILE_UNIX_BASIC:
    9060             :                 {
    9061          40 :                         status = smb_set_file_unix_basic(conn, req,
    9062             :                                                         pdata,
    9063             :                                                         total_data,
    9064             :                                                         fsp,
    9065             :                                                         smb_fname);
    9066          40 :                         break;
    9067             :                 }
    9068             : 
    9069         140 :                 case SMB_SET_FILE_UNIX_INFO2:
    9070             :                 {
    9071         140 :                         status = smb_set_file_unix_info2(conn, req,
    9072             :                                                         pdata,
    9073             :                                                         total_data,
    9074             :                                                         fsp,
    9075             :                                                         smb_fname);
    9076         140 :                         break;
    9077             :                 }
    9078             : 
    9079         118 :                 case SMB_SET_FILE_UNIX_LINK:
    9080             :                 {
    9081         118 :                         if (smb_fname == NULL) {
    9082             :                                 /* We must have a pathname for this. */
    9083           0 :                                 return NT_STATUS_INVALID_LEVEL;
    9084             :                         }
    9085         118 :                         status = smb_set_file_unix_link(conn, req, pdata,
    9086             :                                                         total_data, smb_fname);
    9087         118 :                         break;
    9088             :                 }
    9089             : 
    9090          16 :                 case SMB_SET_FILE_UNIX_HLINK:
    9091             :                 {
    9092          16 :                         if (smb_fname == NULL) {
    9093             :                                 /* We must have a pathname for this. */
    9094           0 :                                 return NT_STATUS_INVALID_LEVEL;
    9095             :                         }
    9096          16 :                         status = smb_set_file_unix_hlink(conn, req,
    9097             :                                                          pdata, total_data,
    9098             :                                                          smb_fname);
    9099          16 :                         break;
    9100             :                 }
    9101             : 
    9102             : #if defined(HAVE_POSIX_ACLS)
    9103          16 :                 case SMB_SET_POSIX_ACL:
    9104             :                 {
    9105          16 :                         status = smb_set_posix_acl(conn,
    9106             :                                                 req,
    9107             :                                                 pdata,
    9108             :                                                 total_data,
    9109             :                                                 fsp,
    9110             :                                                 smb_fname);
    9111          16 :                         break;
    9112             :                 }
    9113             : #endif
    9114             : 
    9115          44 :                 case SMB_SET_POSIX_LOCK:
    9116             :                 {
    9117          44 :                         if (fsp == NULL) {
    9118           8 :                                 return NT_STATUS_INVALID_LEVEL;
    9119             :                         }
    9120          36 :                         status = smb_set_posix_lock(conn, req,
    9121             :                                                     pdata, total_data, fsp);
    9122          36 :                         break;
    9123             :                 }
    9124             : 
    9125         174 :                 case SMB_POSIX_PATH_OPEN:
    9126             :                 {
    9127         174 :                         if (smb_fname == NULL) {
    9128             :                                 /* We must have a pathname for this. */
    9129           0 :                                 return NT_STATUS_INVALID_LEVEL;
    9130             :                         }
    9131             : 
    9132         174 :                         status = smb_posix_open(conn, req,
    9133             :                                                 ppdata,
    9134             :                                                 total_data,
    9135             :                                                 smb_fname,
    9136             :                                                 &data_return_size);
    9137         174 :                         break;
    9138             :                 }
    9139             : 
    9140         540 :                 case SMB_POSIX_PATH_UNLINK:
    9141             :                 {
    9142         540 :                         if (smb_fname == NULL) {
    9143             :                                 /* We must have a pathname for this. */
    9144           0 :                                 return NT_STATUS_INVALID_LEVEL;
    9145             :                         }
    9146             : 
    9147         540 :                         status = smb_posix_unlink(conn, req,
    9148             :                                                 pdata,
    9149             :                                                 total_data,
    9150             :                                                 smb_fname);
    9151         540 :                         break;
    9152             :                 }
    9153             : 
    9154           0 :                 default:
    9155           0 :                         return NT_STATUS_INVALID_LEVEL;
    9156             :         }
    9157             : 
    9158        1080 :         if (!NT_STATUS_IS_OK(status)) {
    9159         516 :                 return status;
    9160             :         }
    9161             : 
    9162         564 :         *ret_data_size = data_return_size;
    9163         564 :         return NT_STATUS_OK;
    9164             : }
    9165             : 
    9166       10038 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
    9167             :                                 struct smb_request *req,
    9168             :                                 TALLOC_CTX *mem_ctx,
    9169             :                                 uint16_t info_level,
    9170             :                                 files_struct *fsp,
    9171             :                                 struct smb_filename *smb_fname,
    9172             :                                 char **ppdata, int total_data,
    9173             :                                 int *ret_data_size)
    9174             : {
    9175       10038 :         char *pdata = *ppdata;
    9176       10038 :         NTSTATUS status = NT_STATUS_OK;
    9177       10038 :         int data_return_size = 0;
    9178             : 
    9179       10038 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    9180        1088 :                 if (!lp_unix_extensions()) {
    9181           0 :                         return NT_STATUS_INVALID_LEVEL;
    9182             :                 }
    9183             : 
    9184        1088 :                 status = smbd_do_posix_setfilepathinfo(conn,
    9185             :                                                        req,
    9186             :                                                        req,
    9187             :                                                        info_level,
    9188             :                                                        smb_fname,
    9189             :                                                        fsp,
    9190             :                                                        ppdata,
    9191             :                                                        total_data,
    9192             :                                                        &data_return_size);
    9193        1088 :                 if (!NT_STATUS_IS_OK(status)) {
    9194         524 :                         return status;
    9195             :                 }
    9196         564 :                 *ret_data_size = data_return_size;
    9197         564 :                 return NT_STATUS_OK;
    9198             :         }
    9199             : 
    9200        8950 :         *ret_data_size = 0;
    9201             : 
    9202        8950 :         DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
    9203             :                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
    9204             :                  fsp_fnum_dbg(fsp),
    9205             :                  info_level, total_data));
    9206             : 
    9207        8950 :         switch (info_level) {
    9208             : 
    9209           8 :                 case SMB_INFO_STANDARD:
    9210             :                 {
    9211           8 :                         status = smb_set_info_standard(conn,
    9212             :                                         pdata,
    9213             :                                         total_data,
    9214             :                                         fsp,
    9215             :                                         smb_fname);
    9216           8 :                         break;
    9217             :                 }
    9218             : 
    9219        2939 :                 case SMB_INFO_SET_EA:
    9220             :                 {
    9221        2939 :                         status = smb_info_set_ea(conn,
    9222             :                                                 pdata,
    9223             :                                                 total_data,
    9224             :                                                 fsp,
    9225             :                                                 smb_fname);
    9226        2939 :                         break;
    9227             :                 }
    9228             : 
    9229        2766 :                 case SMB_SET_FILE_BASIC_INFO:
    9230             :                 case SMB_FILE_BASIC_INFORMATION:
    9231             :                 {
    9232        2766 :                         status = smb_set_file_basic_info(conn,
    9233             :                                                         pdata,
    9234             :                                                         total_data,
    9235             :                                                         fsp,
    9236             :                                                         smb_fname);
    9237        2766 :                         break;
    9238             :                 }
    9239             : 
    9240          16 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    9241             :                 case SMB_SET_FILE_ALLOCATION_INFO:
    9242             :                 {
    9243          16 :                         status = smb_set_file_allocation_info(conn, req,
    9244             :                                                                 pdata,
    9245             :                                                                 total_data,
    9246             :                                                                 fsp,
    9247             :                                                                 smb_fname);
    9248          16 :                         break;
    9249             :                 }
    9250             : 
    9251         329 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    9252             :                 case SMB_SET_FILE_END_OF_FILE_INFO:
    9253             :                 {
    9254             :                         /*
    9255             :                          * XP/Win7 both fail after the createfile with
    9256             :                          * SMB_SET_FILE_END_OF_FILE_INFO but not
    9257             :                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
    9258             :                          * The level is known here, so pass it down
    9259             :                          * appropriately.
    9260             :                          */
    9261         329 :                         bool should_fail =
    9262             :                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
    9263             : 
    9264         329 :                         status = smb_set_file_end_of_file_info(conn, req,
    9265             :                                                                 pdata,
    9266             :                                                                 total_data,
    9267             :                                                                 fsp,
    9268             :                                                                 smb_fname,
    9269             :                                                                 should_fail);
    9270         329 :                         break;
    9271             :                 }
    9272             : 
    9273        2356 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    9274             :                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
    9275             :                 {
    9276             : #if 0
    9277             :                         /* JRA - We used to just ignore this on a path ? 
    9278             :                          * Shouldn't this be invalid level on a pathname
    9279             :                          * based call ?
    9280             :                          */
    9281             :                         if (tran_call != TRANSACT2_SETFILEINFO) {
    9282             :                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
    9283             :                         }
    9284             : #endif
    9285        2356 :                         status = smb_set_file_disposition_info(conn,
    9286             :                                                 pdata,
    9287             :                                                 total_data,
    9288             :                                                 fsp,
    9289             :                                                 smb_fname);
    9290        2356 :                         break;
    9291             :                 }
    9292             : 
    9293          94 :                 case SMB_FILE_POSITION_INFORMATION:
    9294             :                 {
    9295          94 :                         status = smb_file_position_information(conn,
    9296             :                                                 pdata,
    9297             :                                                 total_data,
    9298             :                                                 fsp);
    9299          94 :                         break;
    9300             :                 }
    9301             : 
    9302           8 :                 case SMB_FILE_FULL_EA_INFORMATION:
    9303             :                 {
    9304           8 :                         status = smb_set_file_full_ea_info(conn,
    9305             :                                                 pdata,
    9306             :                                                 total_data,
    9307             :                                                 fsp);
    9308           8 :                         break;
    9309             :                 }
    9310             : 
    9311             :                 /* From tridge Samba4 : 
    9312             :                  * MODE_INFORMATION in setfileinfo (I have no
    9313             :                  * idea what "mode information" on a file is - it takes a value of 0,
    9314             :                  * 2, 4 or 6. What could it be?).
    9315             :                  */
    9316             : 
    9317           8 :                 case SMB_FILE_MODE_INFORMATION:
    9318             :                 {
    9319           8 :                         status = smb_file_mode_information(conn,
    9320             :                                                 pdata,
    9321             :                                                 total_data);
    9322           8 :                         break;
    9323             :                 }
    9324             : 
    9325             :                 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
    9326           8 :                 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
    9327             :                 case SMB_FILE_SHORT_NAME_INFORMATION:
    9328           8 :                         return NT_STATUS_NOT_SUPPORTED;
    9329             : 
    9330         129 :                 case SMB_FILE_RENAME_INFORMATION:
    9331             :                 {
    9332         129 :                         status = smb_file_rename_information(conn, req,
    9333             :                                                              pdata, total_data,
    9334             :                                                              fsp, smb_fname);
    9335         129 :                         break;
    9336             :                 }
    9337             : 
    9338         281 :                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
    9339             :                 {
    9340             :                         /* SMB2 rename information. */
    9341         281 :                         status = smb2_file_rename_information(conn, req,
    9342             :                                                              pdata, total_data,
    9343             :                                                              fsp, smb_fname);
    9344         281 :                         break;
    9345             :                 }
    9346             : 
    9347           8 :                 case SMB_FILE_LINK_INFORMATION:
    9348             :                 {
    9349           8 :                         status = smb_file_link_information(conn, req,
    9350             :                                                         pdata, total_data,
    9351             :                                                         fsp, smb_fname);
    9352           8 :                         break;
    9353             :                 }
    9354             : 
    9355           0 :                 default:
    9356           0 :                         return NT_STATUS_INVALID_LEVEL;
    9357             :         }
    9358             : 
    9359        8942 :         if (!NT_STATUS_IS_OK(status)) {
    9360         490 :                 return status;
    9361             :         }
    9362             : 
    9363        8452 :         *ret_data_size = data_return_size;
    9364        8452 :         return NT_STATUS_OK;
    9365             : }
    9366             : 
    9367             : /****************************************************************************
    9368             :  Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
    9369             : ****************************************************************************/
    9370             : 
    9371        5684 : static void call_trans2setfilepathinfo(connection_struct *conn,
    9372             :                                        struct smb_request *req,
    9373             :                                        unsigned int tran_call,
    9374             :                                        char **pparams, int total_params,
    9375             :                                        char **ppdata, int total_data,
    9376             :                                        unsigned int max_data_bytes)
    9377             : {
    9378        5684 :         char *params = *pparams;
    9379        5684 :         char *pdata = *ppdata;
    9380             :         uint16_t info_level;
    9381        5684 :         struct smb_filename *smb_fname = NULL;
    9382        5684 :         files_struct *fsp = NULL;
    9383        5684 :         NTSTATUS status = NT_STATUS_OK;
    9384        5684 :         int data_return_size = 0;
    9385             : 
    9386        5684 :         if (!params) {
    9387           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9388           0 :                 return;
    9389             :         }
    9390             : 
    9391        5684 :         if (tran_call == TRANSACT2_SETFILEINFO) {
    9392        4271 :                 if (total_params < 4) {
    9393           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9394           0 :                         return;
    9395             :                 }
    9396             : 
    9397        4271 :                 fsp = file_fsp(req, SVAL(params,0));
    9398             :                 /* Basic check for non-null fsp. */
    9399        4271 :                 if (!check_fsp_open(conn, req, fsp)) {
    9400           0 :                         return;
    9401             :                 }
    9402        4271 :                 info_level = SVAL(params,2);
    9403             : 
    9404        4271 :                 smb_fname = fsp->fsp_name;
    9405             : 
    9406        4271 :                 if (fsp_get_pathref_fd(fsp) == -1) {
    9407             :                         /*
    9408             :                          * This is actually a SETFILEINFO on a directory
    9409             :                          * handle (returned from an NT SMB). NT5.0 seems
    9410             :                          * to do this call. JRA.
    9411             :                          */
    9412           0 :                         if (INFO_LEVEL_IS_UNIX(info_level)) {
    9413             :                                 /* Always do lstat for UNIX calls. */
    9414           0 :                                 if (SMB_VFS_LSTAT(conn, smb_fname)) {
    9415           0 :                                         DEBUG(3,("call_trans2setfilepathinfo: "
    9416             :                                                  "SMB_VFS_LSTAT of %s failed "
    9417             :                                                  "(%s)\n",
    9418             :                                                  smb_fname_str_dbg(smb_fname),
    9419             :                                                  strerror(errno)));
    9420           0 :                                         reply_nterror(req, map_nt_error_from_unix(errno));
    9421           0 :                                         return;
    9422             :                                 }
    9423             :                         } else {
    9424           0 :                                 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
    9425           0 :                                         DEBUG(3,("call_trans2setfilepathinfo: "
    9426             :                                                  "fileinfo of %s failed (%s)\n",
    9427             :                                                  smb_fname_str_dbg(smb_fname),
    9428             :                                                  strerror(errno)));
    9429           0 :                                         reply_nterror(req, map_nt_error_from_unix(errno));
    9430           0 :                                         return;
    9431             :                                 }
    9432             :                         }
    9433        4271 :                 } else if (fsp->print_file) {
    9434             :                         /*
    9435             :                          * Doing a DELETE_ON_CLOSE should cancel a print job.
    9436             :                          */
    9437           2 :                         if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
    9438           2 :                                 uint32_t new_private_options =
    9439           2 :                                         fh_get_private_options(fsp->fh);
    9440           2 :                                 new_private_options |=
    9441             :                                         NTCREATEX_FLAG_DELETE_ON_CLOSE;
    9442           2 :                                 fh_set_private_options(fsp->fh,
    9443             :                                                        new_private_options);
    9444             : 
    9445           2 :                                 DEBUG(3,("call_trans2setfilepathinfo: "
    9446             :                                          "Cancelling print job (%s)\n",
    9447             :                                          fsp_str_dbg(fsp)));
    9448             : 
    9449           2 :                                 SSVAL(params,0,0);
    9450           2 :                                 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
    9451             :                                                     *ppdata, 0,
    9452             :                                                     max_data_bytes);
    9453           2 :                                 return;
    9454             :                         } else {
    9455           0 :                                 reply_nterror(req,
    9456             :                                         NT_STATUS_OBJECT_PATH_NOT_FOUND);
    9457           0 :                                 return;
    9458             :                         }
    9459             :                 } else {
    9460             :                         /*
    9461             :                          * Original code - this is an open file.
    9462             :                          */
    9463        4269 :                         if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
    9464           0 :                                 DEBUG(3,("call_trans2setfilepathinfo: fstat "
    9465             :                                          "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
    9466             :                                          strerror(errno)));
    9467           0 :                                 reply_nterror(req, map_nt_error_from_unix(errno));
    9468           0 :                                 return;
    9469             :                         }
    9470             :                 }
    9471             :         } else {
    9472        1413 :                 char *fname = NULL;
    9473        1413 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    9474             : 
    9475             :                 /* set path info */
    9476        1413 :                 if (total_params < 7) {
    9477           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9478           0 :                         return;
    9479             :                 }
    9480             : 
    9481        1413 :                 info_level = SVAL(params,0);
    9482        1413 :                 if (req->posix_pathnames) {
    9483        2136 :                         srvstr_get_path_posix(req,
    9484             :                                 params,
    9485        1068 :                                 req->flags2,
    9486             :                                 &fname,
    9487        1068 :                                 &params[6],
    9488        1068 :                                 total_params - 6,
    9489             :                                 STR_TERMINATE,
    9490             :                                 &status);
    9491             :                 } else {
    9492         690 :                         srvstr_get_path(req,
    9493             :                                 params,
    9494         345 :                                 req->flags2,
    9495             :                                 &fname,
    9496         345 :                                 &params[6],
    9497         345 :                                 total_params - 6,
    9498             :                                 STR_TERMINATE,
    9499             :                                 &status);
    9500             :                 }
    9501        1413 :                 if (!NT_STATUS_IS_OK(status)) {
    9502           0 :                         reply_nterror(req, status);
    9503           0 :                         return;
    9504             :                 }
    9505             : 
    9506        1413 :                 status = filename_convert(req, conn,
    9507             :                                          fname,
    9508             :                                          ucf_flags,
    9509             :                                          0,
    9510             :                                          &smb_fname);
    9511        1413 :                 if (!NT_STATUS_IS_OK(status)) {
    9512          60 :                         if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    9513           0 :                                 reply_botherror(req,
    9514             :                                                 NT_STATUS_PATH_NOT_COVERED,
    9515             :                                                 ERRSRV, ERRbadpath);
    9516           0 :                                 return;
    9517             :                         }
    9518          60 :                         reply_nterror(req, status);
    9519          60 :                         return;
    9520             :                 }
    9521             : 
    9522             :                 /*
    9523             :                  * smb_fname->fsp may be NULL if smb_fname points at a symlink
    9524             :                  * and we're in POSIX context, so be careful when using fsp
    9525             :                  * below, it can still be NULL.
    9526             :                  */
    9527        1353 :                 fsp = smb_fname->fsp;
    9528             : 
    9529        1353 :                 if (INFO_LEVEL_IS_UNIX(info_level)) {
    9530             :                         /*
    9531             :                          * For CIFS UNIX extensions the target name may not exist.
    9532             :                          */
    9533             : 
    9534             :                         /* Always do lstat for UNIX calls. */
    9535        1052 :                         SMB_VFS_LSTAT(conn, smb_fname);
    9536             : 
    9537         305 :                 } else if (!VALID_STAT(smb_fname->st) &&
    9538           4 :                            SMB_VFS_STAT(conn, smb_fname)) {
    9539           4 :                         DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
    9540             :                                  "%s failed (%s)\n",
    9541             :                                  smb_fname_str_dbg(smb_fname),
    9542             :                                  strerror(errno)));
    9543           4 :                         reply_nterror(req, map_nt_error_from_unix(errno));
    9544           4 :                         return;
    9545             :                 }
    9546             :         }
    9547             : 
    9548        5618 :         DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
    9549             :                  "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
    9550             :                  fsp_fnum_dbg(fsp),
    9551             :                  info_level,total_data));
    9552             : 
    9553             :         /* Realloc the parameter size */
    9554        5618 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    9555        5618 :         if (*pparams == NULL) {
    9556           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    9557           0 :                 return;
    9558             :         }
    9559        5618 :         params = *pparams;
    9560             : 
    9561        5618 :         SSVAL(params,0,0);
    9562             : 
    9563        5618 :         status = smbd_do_setfilepathinfo(conn, req, req,
    9564             :                                          info_level,
    9565             :                                          fsp,
    9566             :                                          smb_fname,
    9567             :                                          ppdata, total_data,
    9568             :                                          &data_return_size);
    9569        5618 :         if (!NT_STATUS_IS_OK(status)) {
    9570         933 :                 if (open_was_deferred(req->xconn, req->mid)) {
    9571             :                         /* We have re-scheduled this call. */
    9572           6 :                         return;
    9573             :                 }
    9574         927 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
    9575          32 :                         bool ok = defer_smb1_sharing_violation(req);
    9576          32 :                         if (ok) {
    9577          16 :                                 return;
    9578             :                         }
    9579             :                 }
    9580         911 :                 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
    9581             :                         /* We have re-scheduled this call. */
    9582          28 :                         return;
    9583             :                 }
    9584         883 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    9585           0 :                         reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
    9586             :                                         ERRSRV, ERRbadpath);
    9587           0 :                         return;
    9588             :                 }
    9589         883 :                 if (info_level == SMB_POSIX_PATH_OPEN) {
    9590          12 :                         reply_openerror(req, status);
    9591          12 :                         return;
    9592             :                 }
    9593             : 
    9594             :                 /*
    9595             :                  * Invalid EA name needs to return 2 param bytes,
    9596             :                  * not a zero-length error packet.
    9597             :                  */
    9598         871 :                 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
    9599         235 :                         send_trans2_replies(conn, req, status, params, 2, NULL, 0,
    9600             :                                         max_data_bytes);
    9601             :                 } else {
    9602         636 :                         reply_nterror(req, status);
    9603             :                 }
    9604         820 :                 return;
    9605             :         }
    9606             : 
    9607        4685 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
    9608             :                             max_data_bytes);
    9609             : 
    9610        4685 :         return;
    9611             : }
    9612             : 
    9613             : /****************************************************************************
    9614             :  Reply to a TRANS2_MKDIR (make directory with extended attributes).
    9615             : ****************************************************************************/
    9616             : 
    9617          23 : static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
    9618             :                              char **pparams, int total_params,
    9619             :                              char **ppdata, int total_data,
    9620             :                              unsigned int max_data_bytes)
    9621             : {
    9622          23 :         struct files_struct *fsp = NULL;
    9623          23 :         struct smb_filename *smb_dname = NULL;
    9624          23 :         char *params = *pparams;
    9625          23 :         char *pdata = *ppdata;
    9626          23 :         char *directory = NULL;
    9627          23 :         NTSTATUS status = NT_STATUS_OK;
    9628          23 :         struct ea_list *ea_list = NULL;
    9629          23 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    9630          23 :         TALLOC_CTX *ctx = talloc_tos();
    9631             : 
    9632          23 :         if (!CAN_WRITE(conn)) {
    9633           0 :                 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    9634           0 :                 return;
    9635             :         }
    9636             : 
    9637          23 :         if (total_params < 5) {
    9638           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9639           0 :                 return;
    9640             :         }
    9641             : 
    9642          23 :         if (req->posix_pathnames) {
    9643           0 :                 srvstr_get_path_posix(ctx,
    9644             :                         params,
    9645           0 :                         req->flags2,
    9646             :                         &directory,
    9647           0 :                         &params[4],
    9648           0 :                         total_params - 4,
    9649             :                         STR_TERMINATE,
    9650             :                         &status);
    9651             :         } else {
    9652          46 :                 srvstr_get_path(ctx,
    9653             :                         params,
    9654          23 :                         req->flags2,
    9655             :                         &directory,
    9656          23 :                         &params[4],
    9657          23 :                         total_params - 4,
    9658             :                         STR_TERMINATE,
    9659             :                         &status);
    9660             :         }
    9661          23 :         if (!NT_STATUS_IS_OK(status)) {
    9662           0 :                 reply_nterror(req, status);
    9663           0 :                 return;
    9664             :         }
    9665             : 
    9666          23 :         DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
    9667             : 
    9668          23 :         status = filename_convert(ctx,
    9669             :                                 conn,
    9670             :                                 directory,
    9671             :                                 ucf_flags,
    9672             :                                 0,
    9673             :                                 &smb_dname);
    9674             : 
    9675          23 :         if (!NT_STATUS_IS_OK(status)) {
    9676           5 :                 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
    9677           0 :                         reply_botherror(req,
    9678             :                                 NT_STATUS_PATH_NOT_COVERED,
    9679             :                                 ERRSRV, ERRbadpath);
    9680           0 :                         return;
    9681             :                 }
    9682           5 :                 reply_nterror(req, status);
    9683           5 :                 return;
    9684             :         }
    9685             : 
    9686             :         /*
    9687             :          * OS/2 workplace shell seems to send SET_EA requests of "null"
    9688             :          * length (4 bytes containing IVAL 4).
    9689             :          * They seem to have no effect. Bug #3212. JRA.
    9690             :          */
    9691             : 
    9692          18 :         if (total_data && (total_data != 4)) {
    9693             :                 /* Any data in this call is an EA list. */
    9694           5 :                 if (total_data < 10) {
    9695           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9696           0 :                         goto out;
    9697             :                 }
    9698             : 
    9699           5 :                 if (IVAL(pdata,0) > total_data) {
    9700           0 :                         DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
    9701             :                                 IVAL(pdata,0), (unsigned int)total_data));
    9702           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9703           0 :                         goto out;
    9704             :                 }
    9705             : 
    9706           5 :                 ea_list = read_ea_list(talloc_tos(), pdata + 4,
    9707           5 :                                        total_data - 4);
    9708           5 :                 if (!ea_list) {
    9709           0 :                         reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9710           0 :                         goto out;
    9711             :                 }
    9712             : 
    9713           5 :                 if (!lp_ea_support(SNUM(conn))) {
    9714           0 :                         reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
    9715           0 :                         goto out;
    9716             :                 }
    9717             :         }
    9718             :         /* If total_data == 4 Windows doesn't care what values
    9719             :          * are placed in that field, it just ignores them.
    9720             :          * The System i QNTC IBM SMB client puts bad values here,
    9721             :          * so ignore them. */
    9722             : 
    9723          18 :         status = SMB_VFS_CREATE_FILE(
    9724             :                 conn,                                   /* conn */
    9725             :                 req,                                    /* req */
    9726             :                 smb_dname,                              /* fname */
    9727             :                 MAXIMUM_ALLOWED_ACCESS,                 /* access_mask */
    9728             :                 FILE_SHARE_NONE,                        /* share_access */
    9729             :                 FILE_CREATE,                            /* create_disposition*/
    9730             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    9731             :                 FILE_ATTRIBUTE_DIRECTORY,               /* file_attributes */
    9732             :                 0,                                      /* oplock_request */
    9733             :                 NULL,                                   /* lease */
    9734             :                 0,                                      /* allocation_size */
    9735             :                 0,                                      /* private_flags */
    9736             :                 NULL,                                   /* sd */
    9737             :                 NULL,                                   /* ea_list */
    9738             :                 &fsp,                                       /* result */
    9739             :                 NULL,                                   /* pinfo */
    9740             :                 NULL, NULL);                            /* create context */
    9741          18 :         if (!NT_STATUS_IS_OK(status)) {
    9742           8 :                 reply_nterror(req, status);
    9743           8 :                 goto out;
    9744             :         }
    9745             : 
    9746             :         /* Try and set any given EA. */
    9747          10 :         if (ea_list) {
    9748           5 :                 status = set_ea(conn, fsp, ea_list);
    9749           5 :                 if (!NT_STATUS_IS_OK(status)) {
    9750           0 :                         reply_nterror(req, status);
    9751           0 :                         goto out;
    9752             :                 }
    9753             :         }
    9754             : 
    9755             :         /* Realloc the parameter and data sizes */
    9756          10 :         *pparams = (char *)SMB_REALLOC(*pparams,2);
    9757          10 :         if(*pparams == NULL) {
    9758           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    9759           0 :                 goto out;
    9760             :         }
    9761          10 :         params = *pparams;
    9762             : 
    9763          10 :         SSVAL(params,0,0);
    9764             : 
    9765          10 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
    9766             : 
    9767          18 :  out:
    9768          18 :         if (fsp != NULL) {
    9769          10 :                 close_file(NULL, fsp, NORMAL_CLOSE);
    9770          10 :                 fsp = NULL;
    9771             :         }
    9772          18 :         TALLOC_FREE(smb_dname);
    9773          16 :         return;
    9774             : }
    9775             : 
    9776             : /****************************************************************************
    9777             :  Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
    9778             :  We don't actually do this - we just send a null response.
    9779             : ****************************************************************************/
    9780             : 
    9781           0 : static void call_trans2findnotifyfirst(connection_struct *conn,
    9782             :                                        struct smb_request *req,
    9783             :                                        char **pparams, int total_params,
    9784             :                                        char **ppdata, int total_data,
    9785             :                                        unsigned int max_data_bytes)
    9786             : {
    9787           0 :         char *params = *pparams;
    9788             :         uint16_t info_level;
    9789             : 
    9790           0 :         if (total_params < 6) {
    9791           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    9792           0 :                 return;
    9793             :         }
    9794             : 
    9795           0 :         info_level = SVAL(params,4);
    9796           0 :         DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
    9797             : 
    9798           0 :         switch (info_level) {
    9799           0 :                 case 1:
    9800             :                 case 2:
    9801           0 :                         break;
    9802           0 :                 default:
    9803           0 :                         reply_nterror(req, NT_STATUS_INVALID_LEVEL);
    9804           0 :                         return;
    9805             :         }
    9806             : 
    9807             :         /* Realloc the parameter and data sizes */
    9808           0 :         *pparams = (char *)SMB_REALLOC(*pparams,6);
    9809           0 :         if (*pparams == NULL) {
    9810           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    9811           0 :                 return;
    9812             :         }
    9813           0 :         params = *pparams;
    9814             : 
    9815           0 :         SSVAL(params,0,fnf_handle);
    9816           0 :         SSVAL(params,2,0); /* No changes */
    9817           0 :         SSVAL(params,4,0); /* No EA errors */
    9818             : 
    9819           0 :         fnf_handle++;
    9820             : 
    9821           0 :         if(fnf_handle == 0)
    9822           0 :                 fnf_handle = 257;
    9823             : 
    9824           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
    9825             : 
    9826           0 :         return;
    9827             : }
    9828             : 
    9829             : /****************************************************************************
    9830             :  Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for 
    9831             :  changes). Currently this does nothing.
    9832             : ****************************************************************************/
    9833             : 
    9834           0 : static void call_trans2findnotifynext(connection_struct *conn,
    9835             :                                       struct smb_request *req,
    9836             :                                       char **pparams, int total_params,
    9837             :                                       char **ppdata, int total_data,
    9838             :                                       unsigned int max_data_bytes)
    9839             : {
    9840           0 :         char *params = *pparams;
    9841             : 
    9842           0 :         DEBUG(3,("call_trans2findnotifynext\n"));
    9843             : 
    9844             :         /* Realloc the parameter and data sizes */
    9845           0 :         *pparams = (char *)SMB_REALLOC(*pparams,4);
    9846           0 :         if (*pparams == NULL) {
    9847           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    9848           0 :                 return;
    9849             :         }
    9850           0 :         params = *pparams;
    9851             : 
    9852           0 :         SSVAL(params,0,0); /* No changes */
    9853           0 :         SSVAL(params,2,0); /* No EA errors */
    9854             : 
    9855           0 :         send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
    9856             : 
    9857           0 :         return;
    9858             : }
    9859             : 
    9860             : /****************************************************************************
    9861             :  Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
    9862             : ****************************************************************************/
    9863             : 
    9864        2412 : static void call_trans2getdfsreferral(connection_struct *conn,
    9865             :                                       struct smb_request *req,
    9866             :                                       char **pparams, int total_params,
    9867             :                                       char **ppdata, int total_data,
    9868             :                                       unsigned int max_data_bytes)
    9869             : {
    9870        2412 :         char *params