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

Generated by: LCOV version 1.13