LCOV - code coverage report
Current view: top level - source3/smbd - smb2_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 886 2348 37.7 %
Date: 2024-02-14 10:14:15 Functions: 30 54 55.6 %

          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 "libcli/smb/smb2_posix.h"
      46             : #include "lib/util/string_wrappers.h"
      47             : #include "source3/lib/substitute.h"
      48             : #include "source3/lib/adouble.h"
      49             : 
      50             : #define DIR_ENTRY_SAFETY_MARGIN 4096
      51             : 
      52             : static uint32_t generate_volume_serial_number(
      53             :                                 const struct loadparm_substitution *lp_sub,
      54             :                                 int snum);
      55             : 
      56             : /****************************************************************************
      57             :  Check if an open file handle is a symlink.
      58             : ****************************************************************************/
      59             : 
      60         464 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
      61             : {
      62             : 
      63         464 :         if (!VALID_STAT(fsp->fsp_name->st)) {
      64           0 :                 return NT_STATUS_ACCESS_DENIED;
      65             :         }
      66         464 :         if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
      67           0 :                 return NT_STATUS_ACCESS_DENIED;
      68             :         }
      69         464 :         if (fsp_get_pathref_fd(fsp) == -1) {
      70           0 :                 return NT_STATUS_ACCESS_DENIED;
      71             :         }
      72         464 :         return NT_STATUS_OK;
      73             : }
      74             : 
      75             : /**
      76             :  * Check that one or more of the rights in access mask are
      77             :  * allowed. Iow, access_requested can contain more then one right and
      78             :  * it is sufficient having only one of those granted to pass.
      79             :  **/
      80        5641 : NTSTATUS check_any_access_fsp(struct files_struct *fsp,
      81             :                               uint32_t access_requested)
      82             : {
      83        5641 :         const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
      84        5641 :         uint32_t ro_access_granted = 0;
      85        5641 :         uint32_t access_granted = 0;
      86             :         NTSTATUS status;
      87             : 
      88        5641 :         if (fsp->fsp_flags.is_fsa) {
      89        5073 :                 access_granted = fsp->access_mask;
      90             :         } else {
      91         568 :                 uint32_t mask = 1;
      92             : 
      93        9656 :                 while (mask != 0) {
      94        9656 :                         if (!(mask & access_requested)) {
      95        9088 :                                 mask <<= 1;
      96        9088 :                                 continue;
      97             :                         }
      98             : 
      99         568 :                         status = smbd_check_access_rights_fsp(
     100         568 :                                                         fsp->conn->cwd_fsp,
     101             :                                                         fsp,
     102             :                                                         false,
     103             :                                                         mask);
     104         568 :                         if (NT_STATUS_IS_OK(status)) {
     105         568 :                                 access_granted |= mask;
     106         568 :                                 if (fsp->fsp_name->twrp == 0) {
     107             :                                         /*
     108             :                                          * We can only optimize
     109             :                                          * the non-snapshot case
     110             :                                          */
     111         568 :                                         break;
     112             :                                 }
     113             :                         }
     114           0 :                         mask <<= 1;
     115             :                 }
     116             :         }
     117        5641 :         if ((access_granted & access_requested) == 0) {
     118           0 :                 return NT_STATUS_ACCESS_DENIED;
     119             :         }
     120             : 
     121        5641 :         if (fsp->fsp_name->twrp == 0) {
     122        5641 :                 return NT_STATUS_OK;
     123             :         }
     124             : 
     125           0 :         ro_access_granted = access_granted & ro_access;
     126           0 :         if ((ro_access_granted & access_requested) == 0) {
     127           0 :                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
     128             :         }
     129             : 
     130           0 :         return NT_STATUS_OK;
     131             : }
     132             : 
     133             : /********************************************************************
     134             :  Roundup a value to the nearest allocation roundup size boundary.
     135             :  Only do this for Windows clients.
     136             : ********************************************************************/
     137             : 
     138        9681 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
     139             : {
     140        9681 :         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
     141             : 
     142             :         /* Only roundup for Windows clients. */
     143        9681 :         enum remote_arch_types ra_type = get_remote_arch();
     144        9681 :         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
     145           0 :                 val = SMB_ROUNDUP(val,rval);
     146             :         }
     147        9681 :         return val;
     148             : }
     149             : 
     150             : /****************************************************************************
     151             :  Utility functions for dealing with extended attributes.
     152             : ****************************************************************************/
     153             : 
     154             : /****************************************************************************
     155             :  Refuse to allow clients to overwrite our private xattrs.
     156             : ****************************************************************************/
     157             : 
     158        4576 : bool samba_private_attr_name(const char *unix_ea_name)
     159             : {
     160        4576 :         bool prohibited = false;
     161             : 
     162        4576 :         prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
     163        4576 :         prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
     164        4576 :         prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
     165        4576 :         prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
     166        4576 :         prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
     167             : 
     168        4576 :         if (prohibited) {
     169        4547 :                 return true;
     170             :         }
     171             : 
     172          29 :         if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
     173             :                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
     174          24 :                 return true;
     175             :         }
     176           5 :         return false;
     177             : }
     178             : 
     179             : /****************************************************************************
     180             :  Get one EA value. Fill in a struct ea_struct.
     181             : ****************************************************************************/
     182             : 
     183          79 : NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
     184             :                           files_struct *fsp,
     185             :                           const char *ea_name,
     186             :                           struct ea_struct *pea)
     187             : {
     188             :         /* Get the value of this xattr. Max size is 64k. */
     189          79 :         size_t attr_size = 256;
     190          79 :         char *val = NULL;
     191             :         ssize_t sizeret;
     192          79 :         size_t max_xattr_size = 0;
     193             : 
     194          79 :         if (fsp == NULL) {
     195           0 :                 return NT_STATUS_INVALID_HANDLE;
     196             :         }
     197             : 
     198          79 :         max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
     199             : 
     200          79 :  again:
     201             : 
     202          79 :         val = talloc_realloc(mem_ctx, val, char, attr_size);
     203          79 :         if (!val) {
     204           0 :                 return NT_STATUS_NO_MEMORY;
     205             :         }
     206             : 
     207          79 :         sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
     208          79 :         if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
     209           0 :                 attr_size = max_xattr_size;
     210           0 :                 goto again;
     211             :         }
     212             : 
     213          79 :         if (sizeret == -1) {
     214           8 :                 return map_nt_error_from_unix(errno);
     215             :         }
     216             : 
     217          71 :         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
     218          71 :         dump_data(10, (uint8_t *)val, sizeret);
     219             : 
     220          71 :         pea->flags = 0;
     221          71 :         if (strnequal(ea_name, "user.", 5)) {
     222          71 :                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
     223             :         } else {
     224           0 :                 pea->name = talloc_strdup(mem_ctx, ea_name);
     225             :         }
     226          71 :         if (pea->name == NULL) {
     227           0 :                 TALLOC_FREE(val);
     228           0 :                 return NT_STATUS_NO_MEMORY;
     229             :         }
     230          71 :         pea->value.data = (unsigned char *)val;
     231          71 :         pea->value.length = (size_t)sizeret;
     232          71 :         return NT_STATUS_OK;
     233             : }
     234             : 
     235       10665 : NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
     236             :                                 files_struct *fsp,
     237             :                                 char ***pnames,
     238             :                                 size_t *pnum_names)
     239             : {
     240             :         char smallbuf[1024];
     241             :         /* Get a list of all xattrs. Max namesize is 64k. */
     242       10665 :         size_t ea_namelist_size = 1024;
     243       10665 :         char *ea_namelist = smallbuf;
     244       10665 :         char *to_free = NULL;
     245             : 
     246             :         char *p;
     247             :         char **names;
     248             :         size_t num_names;
     249       10665 :         ssize_t sizeret = -1;
     250             :         NTSTATUS status;
     251             : 
     252       10665 :         if (pnames) {
     253       10665 :                 *pnames = NULL;
     254             :         }
     255       10665 :         *pnum_names = 0;
     256             : 
     257       10665 :         if (fsp == NULL) {
     258             :                 /*
     259             :                  * Callers may pass fsp == NULL when passing smb_fname->fsp of a
     260             :                  * symlink. This is ok, handle it here, by just return no EA's
     261             :                  * on a symlink.
     262             :                  */
     263           0 :                 return NT_STATUS_OK;
     264             :         }
     265             : 
     266             :         /* should be the case that fsp != NULL */
     267       10665 :         SMB_ASSERT(fsp != NULL);
     268             : 
     269       10665 :         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     270             :                                      ea_namelist_size);
     271             : 
     272       10665 :         if ((sizeret == -1) && (errno == ERANGE)) {
     273           0 :                 ea_namelist_size = 65536;
     274           0 :                 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
     275           0 :                 if (ea_namelist == NULL) {
     276           0 :                         return NT_STATUS_NO_MEMORY;
     277             :                 }
     278           0 :                 to_free = ea_namelist;
     279             : 
     280           0 :                 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     281             :                                              ea_namelist_size);
     282             :         }
     283             : 
     284       10665 :         if (sizeret == -1) {
     285           0 :                 status = map_nt_error_from_unix(errno);
     286           0 :                 TALLOC_FREE(to_free);
     287           0 :                 return status;
     288             :         }
     289             : 
     290       10665 :         DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
     291             : 
     292       10665 :         if (sizeret == 0) {
     293        5618 :                 TALLOC_FREE(to_free);
     294        5618 :                 return NT_STATUS_OK;
     295             :         }
     296             : 
     297             :         /*
     298             :          * Ensure the result is 0-terminated
     299             :          */
     300             : 
     301        5047 :         if (ea_namelist[sizeret-1] != '\0') {
     302           0 :                 TALLOC_FREE(to_free);
     303           0 :                 return NT_STATUS_INTERNAL_ERROR;
     304             :         }
     305             : 
     306             :         /*
     307             :          * count the names
     308             :          */
     309        5047 :         num_names = 0;
     310             : 
     311       26957 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     312       21910 :                 num_names += 1;
     313             :         }
     314             : 
     315        5047 :         *pnum_names = num_names;
     316             : 
     317        5047 :         if (pnames == NULL) {
     318           0 :                 TALLOC_FREE(to_free);
     319           0 :                 return NT_STATUS_OK;
     320             :         }
     321             : 
     322        5047 :         names = talloc_array(mem_ctx, char *, num_names);
     323        5047 :         if (names == NULL) {
     324           0 :                 DEBUG(0, ("talloc failed\n"));
     325           0 :                 TALLOC_FREE(to_free);
     326           0 :                 return NT_STATUS_NO_MEMORY;
     327             :         }
     328             : 
     329        5047 :         if (ea_namelist == smallbuf) {
     330        5047 :                 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
     331        5047 :                 if (ea_namelist == NULL) {
     332           0 :                         TALLOC_FREE(names);
     333           0 :                         return NT_STATUS_NO_MEMORY;
     334             :                 }
     335             :         } else {
     336           0 :                 talloc_steal(names, ea_namelist);
     337             : 
     338           0 :                 ea_namelist = talloc_realloc(names, ea_namelist, char,
     339             :                                              sizeret);
     340           0 :                 if (ea_namelist == NULL) {
     341           0 :                         TALLOC_FREE(names);
     342           0 :                         return NT_STATUS_NO_MEMORY;
     343             :                 }
     344             :         }
     345             : 
     346        5047 :         num_names = 0;
     347             : 
     348       26957 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     349       21910 :                 names[num_names++] = p;
     350             :         }
     351             : 
     352        5047 :         *pnames = names;
     353             : 
     354        5047 :         return NT_STATUS_OK;
     355             : }
     356             : 
     357             : /****************************************************************************
     358             :  Return a linked list of the total EA's. Plus the total size
     359             : ****************************************************************************/
     360             : 
     361       10653 : static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
     362             :                                 files_struct *fsp,
     363             :                                 size_t *pea_total_len,
     364             :                                 struct ea_list **ea_list)
     365             : {
     366             :         /* Get a list of all xattrs. Max namesize is 64k. */
     367             :         size_t i, num_names;
     368             :         char **names;
     369       10653 :         struct ea_list *ea_list_head = NULL;
     370       10653 :         bool posix_pathnames = false;
     371             :         NTSTATUS status;
     372             : 
     373       10653 :         *pea_total_len = 0;
     374       10653 :         *ea_list = NULL;
     375             : 
     376             :         /* symlink */
     377       10653 :         if (fsp == NULL) {
     378           0 :                 return NT_STATUS_OK;
     379             :         }
     380             : 
     381       10653 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     382           0 :                 return NT_STATUS_OK;
     383             :         }
     384             : 
     385       10653 :         if (fsp_is_alternate_stream(fsp)) {
     386           0 :                 return NT_STATUS_INVALID_PARAMETER;
     387             :         }
     388             : 
     389       10653 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     390             : 
     391       10653 :         status = get_ea_names_from_fsp(talloc_tos(),
     392             :                                 fsp,
     393             :                                 &names,
     394             :                                 &num_names);
     395             : 
     396       10653 :         if (!NT_STATUS_IS_OK(status)) {
     397           0 :                 return status;
     398             :         }
     399             : 
     400       10653 :         if (num_names == 0) {
     401        5618 :                 return NT_STATUS_OK;
     402             :         }
     403             : 
     404       26925 :         for (i=0; i<num_names; i++) {
     405             :                 struct ea_list *listp;
     406             :                 fstring dos_ea_name;
     407             : 
     408             :                 /*
     409             :                  * POSIX EA names are divided into several namespaces by
     410             :                  * means of string prefixes. Usually, the system controls
     411             :                  * semantics for each namespace, but the 'user' namespace is
     412             :                  * available for arbitrary use, which comes closest to
     413             :                  * Windows EA semantics. Hence, we map POSIX EAs from the
     414             :                  * 'user' namespace to Windows EAs, and just ignore all the
     415             :                  * other namespaces. Also, a few specific names in the 'user'
     416             :                  * namespace are used by Samba internally. Filter them out as
     417             :                  * well, and only present the EAs that are available for
     418             :                  * arbitrary use.
     419             :                  */
     420       21890 :                 if (!strnequal(names[i], "user.", 5)
     421        4562 :                     || samba_private_attr_name(names[i]))
     422       21887 :                         continue;
     423             : 
     424             :                 /*
     425             :                  * Filter out any underlying POSIX EA names
     426             :                  * that a Windows client can't handle.
     427             :                  */
     428           6 :                 if (!posix_pathnames &&
     429           3 :                                 is_invalid_windows_ea_name(names[i])) {
     430           0 :                         continue;
     431             :                 }
     432             : 
     433           3 :                 listp = talloc(mem_ctx, struct ea_list);
     434           3 :                 if (listp == NULL) {
     435           0 :                         return NT_STATUS_NO_MEMORY;
     436             :                 }
     437             : 
     438           3 :                 status = get_ea_value_fsp(listp,
     439             :                                           fsp,
     440           3 :                                           names[i],
     441             :                                           &listp->ea);
     442             : 
     443           3 :                 if (!NT_STATUS_IS_OK(status)) {
     444           0 :                         TALLOC_FREE(listp);
     445           0 :                         return status;
     446             :                 }
     447             : 
     448           3 :                 if (listp->ea.value.length == 0) {
     449             :                         /*
     450             :                          * We can never return a zero length EA.
     451             :                          * Windows reports the EA's as corrupted.
     452             :                          */
     453           0 :                         TALLOC_FREE(listp);
     454           0 :                         continue;
     455           3 :                 } else if (listp->ea.value.length > 65536) {
     456             :                         /*
     457             :                          * SMB clients may report error with file
     458             :                          * if large EA is presented to them.
     459             :                          */
     460           0 :                         DBG_ERR("EA [%s] on file [%s] exceeds "
     461             :                                 "maximum permitted EA size of 64KiB: %zu\n.",
     462             :                                 listp->ea.name, fsp_str_dbg(fsp),
     463             :                                 listp->ea.value.length);
     464           0 :                         TALLOC_FREE(listp);
     465           0 :                         continue;
     466             :                 }
     467             : 
     468           3 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     469             : 
     470           3 :                 *pea_total_len +=
     471           3 :                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     472             : 
     473           3 :                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
     474             :                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
     475             :                           (unsigned int)listp->ea.value.length));
     476             : 
     477           3 :                 DLIST_ADD_END(ea_list_head, listp);
     478             : 
     479             :         }
     480             : 
     481             :         /* Add on 4 for total length. */
     482        5035 :         if (*pea_total_len) {
     483           2 :                 *pea_total_len += 4;
     484             :         }
     485             : 
     486        5035 :         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
     487             :                    (unsigned int)*pea_total_len));
     488             : 
     489        5035 :         *ea_list = ea_list_head;
     490        5035 :         return NT_STATUS_OK;
     491             : }
     492             : 
     493             : /****************************************************************************
     494             :  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
     495             :  that was filled.
     496             : ****************************************************************************/
     497             : 
     498           0 : static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
     499             :         connection_struct *conn, struct ea_list *ea_list)
     500             : {
     501           0 :         unsigned int ret_data_size = 4;
     502           0 :         char *p = pdata;
     503             : 
     504           0 :         SMB_ASSERT(total_data_size >= 4);
     505             : 
     506           0 :         if (!lp_ea_support(SNUM(conn))) {
     507           0 :                 SIVAL(pdata,4,0);
     508           0 :                 return 4;
     509             :         }
     510             : 
     511           0 :         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
     512             :                 size_t dos_namelen;
     513             :                 fstring dos_ea_name;
     514           0 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     515           0 :                 dos_namelen = strlen(dos_ea_name);
     516           0 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     517             :                         break;
     518             :                 }
     519           0 :                 if (ea_list->ea.value.length > 65535) {
     520           0 :                         break;
     521             :                 }
     522           0 :                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
     523           0 :                         break;
     524             :                 }
     525             : 
     526             :                 /* We know we have room. */
     527           0 :                 SCVAL(p,0,ea_list->ea.flags);
     528           0 :                 SCVAL(p,1,dos_namelen);
     529           0 :                 SSVAL(p,2,ea_list->ea.value.length);
     530           0 :                 strlcpy(p+4, dos_ea_name, dos_namelen+1);
     531           0 :                 if (ea_list->ea.value.length > 0) {
     532           0 :                         memcpy(p + 4 + dos_namelen + 1,
     533           0 :                                ea_list->ea.value.data,
     534             :                                ea_list->ea.value.length);
     535             :                 }
     536             : 
     537           0 :                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
     538           0 :                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
     539             :         }
     540             : 
     541           0 :         ret_data_size = PTR_DIFF(p, pdata);
     542           0 :         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
     543           0 :         SIVAL(pdata,0,ret_data_size);
     544           0 :         return ret_data_size;
     545             : }
     546             : 
     547       10651 : static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
     548             :                                        char *pdata,
     549             :                                        unsigned int total_data_size,
     550             :                                        unsigned int *ret_data_size,
     551             :                                        connection_struct *conn,
     552             :                                        struct ea_list *ea_list)
     553             : {
     554       10651 :         uint8_t *p = (uint8_t *)pdata;
     555       10651 :         uint8_t *last_start = NULL;
     556       10651 :         bool do_store_data = (pdata != NULL);
     557             : 
     558       10651 :         *ret_data_size = 0;
     559             : 
     560       10651 :         if (!lp_ea_support(SNUM(conn))) {
     561           0 :                 return NT_STATUS_NO_EAS_ON_FILE;
     562             :         }
     563             : 
     564       10653 :         for (; ea_list; ea_list = ea_list->next) {
     565             :                 size_t dos_namelen;
     566             :                 fstring dos_ea_name;
     567             :                 size_t this_size;
     568           2 :                 size_t pad = 0;
     569             : 
     570           2 :                 if (last_start != NULL && do_store_data) {
     571           0 :                         SIVAL(last_start, 0, PTR_DIFF(p, last_start));
     572             :                 }
     573           2 :                 last_start = p;
     574             : 
     575           2 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     576           2 :                 dos_namelen = strlen(dos_ea_name);
     577           2 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     578           0 :                         return NT_STATUS_INTERNAL_ERROR;
     579             :                 }
     580           2 :                 if (ea_list->ea.value.length > 65535) {
     581           0 :                         return NT_STATUS_INTERNAL_ERROR;
     582             :                 }
     583             : 
     584           2 :                 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
     585             : 
     586           2 :                 if (ea_list->next) {
     587           1 :                         pad = (4 - (this_size % 4)) % 4;
     588           1 :                         this_size += pad;
     589             :                 }
     590             : 
     591           2 :                 if (do_store_data) {
     592           0 :                         if (this_size > total_data_size) {
     593           0 :                                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     594             :                         }
     595             : 
     596             :                         /* We know we have room. */
     597           0 :                         SIVAL(p, 0x00, 0); /* next offset */
     598           0 :                         SCVAL(p, 0x04, ea_list->ea.flags);
     599           0 :                         SCVAL(p, 0x05, dos_namelen);
     600           0 :                         SSVAL(p, 0x06, ea_list->ea.value.length);
     601           0 :                         strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
     602           0 :                         memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
     603           0 :                         if (pad) {
     604           0 :                                 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
     605             :                                         '\0',
     606             :                                         pad);
     607             :                         }
     608           0 :                         total_data_size -= this_size;
     609             :                 }
     610             : 
     611           2 :                 p += this_size;
     612             :         }
     613             : 
     614       10651 :         *ret_data_size = PTR_DIFF(p, pdata);
     615       10651 :         DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
     616       10651 :         return NT_STATUS_OK;
     617             : }
     618             : 
     619       11073 : unsigned int estimate_ea_size(files_struct *fsp)
     620             : {
     621       11073 :         size_t total_ea_len = 0;
     622             :         TALLOC_CTX *mem_ctx;
     623       11073 :         struct ea_list *ea_list = NULL;
     624             :         NTSTATUS status;
     625             : 
     626             :         /* symlink */
     627       11073 :         if (fsp == NULL) {
     628         422 :                 return 0;
     629             :         }
     630             : 
     631       10651 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     632           0 :                 return 0;
     633             :         }
     634             : 
     635       10651 :         mem_ctx = talloc_stackframe();
     636             : 
     637             :         /* If this is a stream fsp, then we need to instead find the
     638             :          * estimated ea len from the main file, not the stream
     639             :          * (streams cannot have EAs), but the estimate isn't just 0 in
     640             :          * this case! */
     641       10651 :         fsp = metadata_fsp(fsp);
     642       10651 :         (void)get_ea_list_from_fsp(mem_ctx,
     643             :                                    fsp,
     644             :                                    &total_ea_len,
     645             :                                    &ea_list);
     646             : 
     647       10651 :         if(fsp->conn->sconn->using_smb2) {
     648             :                 unsigned int ret_data_size;
     649             :                 /*
     650             :                  * We're going to be using fill_ea_chained_buffer() to
     651             :                  * marshall EA's - this size is significantly larger
     652             :                  * than the SMB1 buffer. Re-calculate the size without
     653             :                  * marshalling.
     654             :                  */
     655       10651 :                 status = fill_ea_chained_buffer(mem_ctx,
     656             :                                                 NULL,
     657             :                                                 0,
     658             :                                                 &ret_data_size,
     659       10651 :                                                 fsp->conn,
     660             :                                                 ea_list);
     661       10651 :                 if (!NT_STATUS_IS_OK(status)) {
     662           0 :                         ret_data_size = 0;
     663             :                 }
     664       10651 :                 total_ea_len = ret_data_size;
     665             :         }
     666       10651 :         TALLOC_FREE(mem_ctx);
     667       10651 :         return total_ea_len;
     668             : }
     669             : 
     670             : /****************************************************************************
     671             :  Ensure the EA name is case insensitive by matching any existing EA name.
     672             : ****************************************************************************/
     673             : 
     674           2 : static void canonicalize_ea_name(files_struct *fsp,
     675             :                         fstring unix_ea_name)
     676             : {
     677             :         size_t total_ea_len;
     678           2 :         TALLOC_CTX *mem_ctx = talloc_tos();
     679             :         struct ea_list *ea_list;
     680           2 :         NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
     681             :                                                fsp,
     682             :                                                &total_ea_len,
     683             :                                                &ea_list);
     684           2 :         if (!NT_STATUS_IS_OK(status)) {
     685           0 :                 return;
     686             :         }
     687             : 
     688           3 :         for (; ea_list; ea_list = ea_list->next) {
     689           1 :                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
     690           0 :                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
     691             :                                 &unix_ea_name[5], ea_list->ea.name));
     692           0 :                         strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
     693           0 :                         break;
     694             :                 }
     695             :         }
     696             : }
     697             : 
     698             : /****************************************************************************
     699             :  Set or delete an extended attribute.
     700             : ****************************************************************************/
     701             : 
     702           1 : NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
     703             :                 struct ea_list *ea_list)
     704             : {
     705             :         NTSTATUS status;
     706           1 :         bool posix_pathnames = false;
     707             : 
     708           1 :         if (!lp_ea_support(SNUM(conn))) {
     709           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
     710             :         }
     711             : 
     712           1 :         if (fsp == NULL) {
     713           0 :                 return NT_STATUS_INVALID_HANDLE;
     714             :         }
     715             : 
     716           1 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     717             : 
     718           1 :         status = refuse_symlink_fsp(fsp);
     719           1 :         if (!NT_STATUS_IS_OK(status)) {
     720           0 :                 return status;
     721             :         }
     722             : 
     723           1 :         status = check_any_access_fsp(fsp, FILE_WRITE_EA);
     724           1 :         if (!NT_STATUS_IS_OK(status)) {
     725           0 :                 return status;
     726             :         }
     727             : 
     728             :         /* Setting EAs on streams isn't supported. */
     729           1 :         if (fsp_is_alternate_stream(fsp)) {
     730           0 :                 return NT_STATUS_INVALID_PARAMETER;
     731             :         }
     732             : 
     733             :         /*
     734             :          * Filter out invalid Windows EA names - before
     735             :          * we set *any* of them.
     736             :          */
     737             : 
     738           1 :         if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
     739           0 :                 return STATUS_INVALID_EA_NAME;
     740             :         }
     741             : 
     742           3 :         for (;ea_list; ea_list = ea_list->next) {
     743             :                 int ret;
     744             :                 fstring unix_ea_name;
     745             : 
     746             :                 /*
     747             :                  * Complementing the forward mapping from POSIX EAs to
     748             :                  * Windows EAs in get_ea_list_from_fsp(), here we map in the
     749             :                  * opposite direction from Windows EAs to the 'user' namespace
     750             :                  * of POSIX EAs. Hence, all POSIX EA names the we set here must
     751             :                  * start with a 'user.' prefix.
     752             :                  */
     753           2 :                 fstrcpy(unix_ea_name, "user.");
     754           2 :                 fstrcat(unix_ea_name, ea_list->ea.name);
     755             : 
     756           2 :                 canonicalize_ea_name(fsp, unix_ea_name);
     757             : 
     758           2 :                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
     759             : 
     760           2 :                 if (samba_private_attr_name(unix_ea_name)) {
     761           0 :                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
     762           0 :                         return NT_STATUS_ACCESS_DENIED;
     763             :                 }
     764             : 
     765           2 :                 if (ea_list->ea.value.length == 0) {
     766             :                         /* Remove the attribute. */
     767           0 :                         DBG_DEBUG("deleting ea name %s on "
     768             :                                   "file %s by file descriptor.\n",
     769             :                                   unix_ea_name, fsp_str_dbg(fsp));
     770           0 :                         ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
     771             : #ifdef ENOATTR
     772             :                         /* Removing a non existent attribute always succeeds. */
     773           0 :                         if (ret == -1 && errno == ENOATTR) {
     774           0 :                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
     775             :                                                 unix_ea_name));
     776           0 :                                 ret = 0;
     777             :                         }
     778             : #endif
     779             :                 } else {
     780           2 :                         DEBUG(10,("set_ea: setting ea name %s on file "
     781             :                                   "%s by file descriptor.\n",
     782             :                                   unix_ea_name, fsp_str_dbg(fsp)));
     783           2 :                         ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
     784             :                                                 ea_list->ea.value.data, ea_list->ea.value.length, 0);
     785             :                 }
     786             : 
     787           2 :                 if (ret == -1) {
     788             : #ifdef ENOTSUP
     789           0 :                         if (errno == ENOTSUP) {
     790           0 :                                 return NT_STATUS_EAS_NOT_SUPPORTED;
     791             :                         }
     792             : #endif
     793           0 :                         return map_nt_error_from_unix(errno);
     794             :                 }
     795             : 
     796             :         }
     797           1 :         return NT_STATUS_OK;
     798             : }
     799             : 
     800             : /****************************************************************************
     801             :  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
     802             : ****************************************************************************/
     803             : 
     804           0 : struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     805             : {
     806           0 :         struct ea_list *ea_list_head = NULL;
     807           0 :         size_t offset = 0;
     808           0 :         size_t bytes_used = 0;
     809             : 
     810           0 :         while (offset < data_size) {
     811           0 :                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
     812             : 
     813           0 :                 if (!eal) {
     814           0 :                         return NULL;
     815             :                 }
     816             : 
     817           0 :                 DLIST_ADD_END(ea_list_head, eal);
     818           0 :                 offset += bytes_used;
     819             :         }
     820             : 
     821           0 :         return ea_list_head;
     822             : }
     823             : 
     824             : /****************************************************************************
     825             :  Count the total EA size needed.
     826             : ****************************************************************************/
     827             : 
     828           0 : static size_t ea_list_size(struct ea_list *ealist)
     829             : {
     830             :         fstring dos_ea_name;
     831             :         struct ea_list *listp;
     832           0 :         size_t ret = 0;
     833             : 
     834           0 :         for (listp = ealist; listp; listp = listp->next) {
     835           0 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     836           0 :                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     837             :         }
     838             :         /* Add on 4 for total length. */
     839           0 :         if (ret) {
     840           0 :                 ret += 4;
     841             :         }
     842             : 
     843           0 :         return ret;
     844             : }
     845             : 
     846             : /****************************************************************************
     847             :  Return a union of EA's from a file list and a list of names.
     848             :  The TALLOC context for the two lists *MUST* be identical as we steal
     849             :  memory from one list to add to another. JRA.
     850             : ****************************************************************************/
     851             : 
     852           0 : static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
     853             : {
     854             :         struct ea_list *nlistp, *flistp;
     855             : 
     856           0 :         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
     857           0 :                 for (flistp = file_list; flistp; flistp = flistp->next) {
     858           0 :                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
     859           0 :                                 break;
     860             :                         }
     861             :                 }
     862             : 
     863           0 :                 if (flistp) {
     864             :                         /* Copy the data from this entry. */
     865           0 :                         nlistp->ea.flags = flistp->ea.flags;
     866           0 :                         nlistp->ea.value = flistp->ea.value;
     867             :                 } else {
     868             :                         /* Null entry. */
     869           0 :                         nlistp->ea.flags = 0;
     870           0 :                         ZERO_STRUCT(nlistp->ea.value);
     871             :                 }
     872             :         }
     873             : 
     874           0 :         *total_ea_len = ea_list_size(name_list);
     875           0 :         return name_list;
     876             : }
     877             : 
     878             : /*********************************************************
     879             :  Routine to check if a given string matches exactly.
     880             :  as a special case a mask of "." does NOT match. That
     881             :  is required for correct wildcard semantics
     882             :  Case can be significant or not.
     883             : **********************************************************/
     884             : 
     885       12253 : static bool exact_match(bool has_wild,
     886             :                         bool case_sensitive,
     887             :                         const char *str,
     888             :                         const char *mask)
     889             : {
     890       12253 :         if (mask[0] == '.' && mask[1] == 0) {
     891           0 :                 return false;
     892             :         }
     893             : 
     894       12253 :         if (has_wild) {
     895       10872 :                 return false;
     896             :         }
     897             : 
     898        1381 :         if (case_sensitive) {
     899           0 :                 return strcmp(str,mask)==0;
     900             :         } else {
     901        1381 :                 return strcasecmp_m(str,mask) == 0;
     902             :         }
     903             : }
     904             : 
     905             : /****************************************************************************
     906             :  Return the filetype for UNIX extensions.
     907             : ****************************************************************************/
     908             : 
     909           0 : static uint32_t unix_filetype(mode_t mode)
     910             : {
     911           0 :         if(S_ISREG(mode))
     912           0 :                 return UNIX_TYPE_FILE;
     913           0 :         else if(S_ISDIR(mode))
     914           0 :                 return UNIX_TYPE_DIR;
     915             : #ifdef S_ISLNK
     916           0 :         else if(S_ISLNK(mode))
     917           0 :                 return UNIX_TYPE_SYMLINK;
     918             : #endif
     919             : #ifdef S_ISCHR
     920           0 :         else if(S_ISCHR(mode))
     921           0 :                 return UNIX_TYPE_CHARDEV;
     922             : #endif
     923             : #ifdef S_ISBLK
     924           0 :         else if(S_ISBLK(mode))
     925           0 :                 return UNIX_TYPE_BLKDEV;
     926             : #endif
     927             : #ifdef S_ISFIFO
     928           0 :         else if(S_ISFIFO(mode))
     929           0 :                 return UNIX_TYPE_FIFO;
     930             : #endif
     931             : #ifdef S_ISSOCK
     932           0 :         else if(S_ISSOCK(mode))
     933           0 :                 return UNIX_TYPE_SOCKET;
     934             : #endif
     935             : 
     936           0 :         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
     937           0 :         return UNIX_TYPE_UNKNOWN;
     938             : }
     939             : 
     940             : /****************************************************************************
     941             :  Map wire perms onto standard UNIX permissions. Obey share restrictions.
     942             : ****************************************************************************/
     943             : 
     944           0 : NTSTATUS unix_perms_from_wire(connection_struct *conn,
     945             :                               const SMB_STRUCT_STAT *psbuf,
     946             :                               uint32_t perms,
     947             :                               enum perm_type ptype,
     948             :                               mode_t *ret_perms)
     949             : {
     950           0 :         mode_t ret = 0;
     951             : 
     952           0 :         if (perms == SMB_MODE_NO_CHANGE) {
     953           0 :                 if (!VALID_STAT(*psbuf)) {
     954           0 :                         return NT_STATUS_INVALID_PARAMETER;
     955             :                 } else {
     956           0 :                         *ret_perms = psbuf->st_ex_mode;
     957           0 :                         return NT_STATUS_OK;
     958             :                 }
     959             :         }
     960             : 
     961           0 :         ret = wire_perms_to_unix(perms);
     962             : 
     963           0 :         if (ptype == PERM_NEW_FILE) {
     964             :                 /*
     965             :                  * "create mask"/"force create mode" are
     966             :                  * only applied to new files, not existing ones.
     967             :                  */
     968           0 :                 ret &= lp_create_mask(SNUM(conn));
     969             :                 /* Add in force bits */
     970           0 :                 ret |= lp_force_create_mode(SNUM(conn));
     971           0 :         } else if (ptype == PERM_NEW_DIR) {
     972             :                 /*
     973             :                  * "directory mask"/"force directory mode" are
     974             :                  * only applied to new directories, not existing ones.
     975             :                  */
     976           0 :                 ret &= lp_directory_mask(SNUM(conn));
     977             :                 /* Add in force bits */
     978           0 :                 ret |= lp_force_directory_mode(SNUM(conn));
     979             :         }
     980             : 
     981           0 :         *ret_perms = ret;
     982           0 :         return NT_STATUS_OK;
     983             : }
     984             : 
     985             : /****************************************************************************
     986             :  Needed to show the msdfs symlinks as directories. Modifies psbuf
     987             :  to be a directory if it's a msdfs link.
     988             : ****************************************************************************/
     989             : 
     990          76 : static bool check_msdfs_link(struct files_struct *dirfsp,
     991             :                              struct smb_filename *atname,
     992             :                              struct smb_filename *smb_fname)
     993             : {
     994          76 :         int saved_errno = errno;
     995         152 :         if(lp_host_msdfs() &&
     996         132 :                 lp_msdfs_root(SNUM(dirfsp->conn)) &&
     997          56 :                 is_msdfs_link(dirfsp, atname)) {
     998             : 
     999             :                 /*
    1000             :                  * Copy the returned stat struct from the relative
    1001             :                  * to the full pathname.
    1002             :                  */
    1003          56 :                 smb_fname->st = atname->st;
    1004             : 
    1005          56 :                 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
    1006             :                         "as a directory\n",
    1007             :                         smb_fname->base_name));
    1008          56 :                 smb_fname->st.st_ex_mode =
    1009          56 :                         (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
    1010          56 :                 errno = saved_errno;
    1011          56 :                 return true;
    1012             :         }
    1013          20 :         errno = saved_errno;
    1014          20 :         return false;
    1015             : }
    1016             : 
    1017             : 
    1018             : /****************************************************************************
    1019             :  Get a level dependent lanman2 dir entry.
    1020             : ****************************************************************************/
    1021             : 
    1022             : struct smbd_dirptr_lanman2_state {
    1023             :         connection_struct *conn;
    1024             :         uint32_t info_level;
    1025             :         bool check_mangled_names;
    1026             :         bool has_wild;
    1027             :         bool got_exact_match;
    1028             :         bool case_sensitive;
    1029             : };
    1030             : 
    1031       11648 : static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
    1032             :                                          void *private_data,
    1033             :                                          const char *dname,
    1034             :                                          const char *mask,
    1035             :                                          char **_fname)
    1036             : {
    1037       11648 :         struct smbd_dirptr_lanman2_state *state =
    1038             :                 (struct smbd_dirptr_lanman2_state *)private_data;
    1039             :         bool ok;
    1040             :         char mangled_name[13]; /* mangled 8.3 name. */
    1041             :         bool got_match;
    1042             :         const char *fname;
    1043             : 
    1044             :         /* Mangle fname if it's an illegal name. */
    1045       11648 :         if (mangle_must_mangle(dname, state->conn->params)) {
    1046             :                 /*
    1047             :                  * Slow path - ensure we can push the original name as UCS2. If
    1048             :                  * not, then just don't return this name.
    1049             :                  */
    1050             :                 NTSTATUS status;
    1051          20 :                 size_t ret_len = 0;
    1052          20 :                 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
    1053          20 :                 uint8_t *tmp = talloc_array(talloc_tos(),
    1054             :                                         uint8_t,
    1055             :                                         len);
    1056             : 
    1057          20 :                 status = srvstr_push(NULL,
    1058             :                         FLAGS2_UNICODE_STRINGS,
    1059             :                         tmp,
    1060             :                         dname,
    1061             :                         len,
    1062             :                         STR_TERMINATE,
    1063             :                         &ret_len);
    1064             : 
    1065          20 :                 TALLOC_FREE(tmp);
    1066             : 
    1067          20 :                 if (!NT_STATUS_IS_OK(status)) {
    1068           8 :                         return false;
    1069             :                 }
    1070             : 
    1071          12 :                 ok = name_to_8_3(dname, mangled_name,
    1072          12 :                                  true, state->conn->params);
    1073          12 :                 if (!ok) {
    1074           0 :                         return false;
    1075             :                 }
    1076          12 :                 fname = mangled_name;
    1077             :         } else {
    1078       11628 :                 fname = dname;
    1079             :         }
    1080             : 
    1081       11640 :         got_match = exact_match(state->has_wild,
    1082       11640 :                                 state->case_sensitive,
    1083             :                                 fname, mask);
    1084       11640 :         state->got_exact_match = got_match;
    1085       11640 :         if (!got_match) {
    1086       11526 :                 got_match = mask_match(fname, mask,
    1087       11526 :                                        state->case_sensitive);
    1088             :         }
    1089             : 
    1090       11640 :         if(!got_match && state->check_mangled_names &&
    1091         995 :            !mangle_is_8_3(fname, false, state->conn->params)) {
    1092             :                 /*
    1093             :                  * It turns out that NT matches wildcards against
    1094             :                  * both long *and* short names. This may explain some
    1095             :                  * of the wildcard wierdness from old DOS clients
    1096             :                  * that some people have been seeing.... JRA.
    1097             :                  */
    1098             :                 /* Force the mangling into 8.3. */
    1099         613 :                 ok = name_to_8_3(fname, mangled_name,
    1100         613 :                                  false, state->conn->params);
    1101         613 :                 if (!ok) {
    1102           0 :                         return false;
    1103             :                 }
    1104             : 
    1105         613 :                 got_match = exact_match(state->has_wild,
    1106         613 :                                         state->case_sensitive,
    1107             :                                         mangled_name, mask);
    1108         613 :                 state->got_exact_match = got_match;
    1109         613 :                 if (!got_match) {
    1110         613 :                         got_match = mask_match(mangled_name, mask,
    1111         613 :                                                state->case_sensitive);
    1112             :                 }
    1113             :         }
    1114             : 
    1115       11640 :         if (!got_match) {
    1116         995 :                 return false;
    1117             :         }
    1118             : 
    1119       10645 :         *_fname = talloc_strdup(ctx, fname);
    1120       10645 :         if (*_fname == NULL) {
    1121           0 :                 return false;
    1122             :         }
    1123             : 
    1124       10645 :         return true;
    1125             : }
    1126             : 
    1127       10645 : static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
    1128             :                                         void *private_data,
    1129             :                                         struct files_struct *dirfsp,
    1130             :                                         struct smb_filename *atname,
    1131             :                                         struct smb_filename *smb_fname,
    1132             :                                         bool get_dosmode,
    1133             :                                         uint32_t *_mode)
    1134             : {
    1135       10645 :         struct smbd_dirptr_lanman2_state *state =
    1136             :                 (struct smbd_dirptr_lanman2_state *)private_data;
    1137       10645 :         bool ms_dfs_link = false;
    1138             : 
    1139       10645 :         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
    1140           0 :                 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
    1141           0 :                         DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
    1142             :                                  "Couldn't lstat [%s] (%s)\n",
    1143             :                                  smb_fname_str_dbg(smb_fname),
    1144             :                                  strerror(errno)));
    1145           0 :                         return false;
    1146             :                 }
    1147           0 :                 return true;
    1148             :         }
    1149             : 
    1150       10721 :         if (!VALID_STAT(smb_fname->st) &&
    1151          76 :             SMB_VFS_STAT(state->conn, smb_fname) != 0) {
    1152             :                 /* Needed to show the msdfs symlinks as
    1153             :                  * directories */
    1154             : 
    1155          76 :                 ms_dfs_link = check_msdfs_link(dirfsp,
    1156             :                                                atname,
    1157             :                                                smb_fname);
    1158          76 :                 if (!ms_dfs_link) {
    1159          20 :                         DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
    1160             :                                  "Couldn't stat [%s] (%s)\n",
    1161             :                                  smb_fname_str_dbg(smb_fname),
    1162             :                                  strerror(errno)));
    1163          20 :                         return false;
    1164             :                 }
    1165             : 
    1166          56 :                 *_mode = dos_mode_msdfs(state->conn, smb_fname);
    1167          56 :                 return true;
    1168             :         }
    1169             : 
    1170       10569 :         if (!get_dosmode) {
    1171         426 :                 return true;
    1172             :         }
    1173             : 
    1174       10143 :         *_mode = fdos_mode(smb_fname->fsp);
    1175       10143 :         smb_fname->st = smb_fname->fsp->fsp_name->st;
    1176             : 
    1177       10143 :         return true;
    1178             : }
    1179             : 
    1180       10604 : static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
    1181             : {
    1182       10604 :         if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
    1183       10548 :                 unsigned ea_size = estimate_ea_size(fsp);
    1184       10548 :                 return ea_size;
    1185             :         }
    1186          56 :         return IO_REPARSE_TAG_DFS;
    1187             : }
    1188             : 
    1189       10621 : static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
    1190             :                                     connection_struct *conn,
    1191             :                                     uint16_t flags2,
    1192             :                                     uint32_t info_level,
    1193             :                                     struct ea_list *name_list,
    1194             :                                     bool check_mangled_names,
    1195             :                                     bool requires_resume_key,
    1196             :                                     uint32_t mode,
    1197             :                                     const char *fname,
    1198             :                                     const struct smb_filename *smb_fname,
    1199             :                                     int space_remaining,
    1200             :                                     uint8_t align,
    1201             :                                     bool do_pad,
    1202             :                                     char *base_data,
    1203             :                                     char **ppdata,
    1204             :                                     char *end_data,
    1205             :                                     uint64_t *last_entry_off)
    1206             : {
    1207       10621 :         char *p, *q, *pdata = *ppdata;
    1208       10621 :         uint32_t reskey=0;
    1209       10621 :         uint64_t file_size = 0;
    1210       10621 :         uint64_t allocation_size = 0;
    1211       10621 :         uint64_t file_id = 0;
    1212       10621 :         size_t len = 0;
    1213       10621 :         struct timespec mdate_ts = {0};
    1214       10621 :         struct timespec adate_ts = {0};
    1215       10621 :         struct timespec cdate_ts = {0};
    1216       10621 :         struct timespec create_date_ts = {0};
    1217       10621 :         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
    1218             :         char *nameptr;
    1219             :         char *last_entry_ptr;
    1220             :         bool was_8_3;
    1221             :         int off;
    1222       10621 :         int pad = 0;
    1223             :         NTSTATUS status;
    1224       10621 :         struct readdir_attr_data *readdir_attr_data = NULL;
    1225             :         uint32_t ea_size;
    1226             : 
    1227       10621 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    1228         918 :                 file_size = get_file_size_stat(&smb_fname->st);
    1229             :         }
    1230       10621 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
    1231             : 
    1232             :         /*
    1233             :          * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
    1234             :          * a DFS symlink.
    1235             :          */
    1236       10621 :         if (smb_fname->fsp != NULL &&
    1237       10143 :             !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
    1238       10143 :                 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
    1239             :                                                ctx,
    1240             :                                                &readdir_attr_data);
    1241       10143 :                 if (!NT_STATUS_IS_OK(status)) {
    1242       10143 :                         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
    1243             :                                              status)) {
    1244           0 :                                 return status;
    1245             :                         }
    1246             :                 }
    1247             :         }
    1248             : 
    1249       10621 :         file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
    1250             : 
    1251       10621 :         mdate_ts = smb_fname->st.st_ex_mtime;
    1252       10621 :         adate_ts = smb_fname->st.st_ex_atime;
    1253       10621 :         create_date_ts = get_create_timespec(conn, NULL, smb_fname);
    1254       10621 :         cdate_ts = get_change_timespec(conn, NULL, smb_fname);
    1255             : 
    1256       10621 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    1257           0 :                 dos_filetime_timespec(&create_date_ts);
    1258           0 :                 dos_filetime_timespec(&mdate_ts);
    1259           0 :                 dos_filetime_timespec(&adate_ts);
    1260           0 :                 dos_filetime_timespec(&cdate_ts);
    1261             :         }
    1262             : 
    1263       10621 :         create_date = convert_timespec_to_time_t(create_date_ts);
    1264       10621 :         mdate = convert_timespec_to_time_t(mdate_ts);
    1265       10621 :         adate = convert_timespec_to_time_t(adate_ts);
    1266             : 
    1267             :         /* align the record */
    1268       10621 :         SMB_ASSERT(align >= 1);
    1269             : 
    1270       10621 :         off = (int)PTR_DIFF(pdata, base_data);
    1271       10621 :         pad = (off + (align-1)) & ~(align-1);
    1272       10621 :         pad -= off;
    1273             : 
    1274       10621 :         if (pad && pad > space_remaining) {
    1275           0 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1276             :                         "for padding (wanted %u, had %d)\n",
    1277             :                         (unsigned int)pad,
    1278             :                         space_remaining ));
    1279           0 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1280             :         }
    1281             : 
    1282       10621 :         off += pad;
    1283             :         /* initialize padding to 0 */
    1284       10621 :         if (pad) {
    1285        7463 :                 memset(pdata, 0, pad);
    1286             :         }
    1287       10621 :         space_remaining -= pad;
    1288             : 
    1289       10621 :         DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
    1290             :                 space_remaining ));
    1291             : 
    1292       10621 :         pdata += pad;
    1293       10621 :         p = pdata;
    1294       10621 :         last_entry_ptr = p;
    1295             : 
    1296       10621 :         pad = 0;
    1297       10621 :         off = 0;
    1298             : 
    1299       10621 :         switch (info_level) {
    1300           0 :         case SMB_FIND_INFO_STANDARD:
    1301           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
    1302           0 :                 if(requires_resume_key) {
    1303           0 :                         SIVAL(p,0,reskey);
    1304           0 :                         p += 4;
    1305             :                 }
    1306           0 :                 srv_put_dos_date2(p,0,create_date);
    1307           0 :                 srv_put_dos_date2(p,4,adate);
    1308           0 :                 srv_put_dos_date2(p,8,mdate);
    1309           0 :                 SIVAL(p,12,(uint32_t)file_size);
    1310           0 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1311           0 :                 SSVAL(p,20,mode);
    1312           0 :                 p += 23;
    1313           0 :                 nameptr = p;
    1314           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1315           0 :                         p += ucs2_align(base_data, p, 0);
    1316             :                 }
    1317           0 :                 status = srvstr_push(base_data, flags2, p,
    1318             :                                   fname, PTR_DIFF(end_data, p),
    1319             :                                   STR_TERMINATE, &len);
    1320           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1321           8 :                         return status;
    1322             :                 }
    1323           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1324           0 :                         if (len > 2) {
    1325           0 :                                 SCVAL(nameptr, -1, len - 2);
    1326             :                         } else {
    1327           0 :                                 SCVAL(nameptr, -1, 0);
    1328             :                         }
    1329             :                 } else {
    1330           0 :                         if (len > 1) {
    1331           0 :                                 SCVAL(nameptr, -1, len - 1);
    1332             :                         } else {
    1333           0 :                                 SCVAL(nameptr, -1, 0);
    1334             :                         }
    1335             :                 }
    1336           0 :                 p += len;
    1337           0 :                 break;
    1338             : 
    1339           0 :         case SMB_FIND_EA_SIZE:
    1340           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
    1341           0 :                 if (requires_resume_key) {
    1342           0 :                         SIVAL(p,0,reskey);
    1343           0 :                         p += 4;
    1344             :                 }
    1345           0 :                 srv_put_dos_date2(p,0,create_date);
    1346           0 :                 srv_put_dos_date2(p,4,adate);
    1347           0 :                 srv_put_dos_date2(p,8,mdate);
    1348           0 :                 SIVAL(p,12,(uint32_t)file_size);
    1349           0 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1350           0 :                 SSVAL(p,20,mode);
    1351             :                 {
    1352           0 :                         ea_size = estimate_ea_size(smb_fname->fsp);
    1353           0 :                         SIVAL(p,22,ea_size); /* Extended attributes */
    1354             :                 }
    1355           0 :                 p += 27;
    1356           0 :                 nameptr = p - 1;
    1357           0 :                 status = srvstr_push(base_data, flags2,
    1358             :                                   p, fname, PTR_DIFF(end_data, p),
    1359             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1360           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1361           0 :                         return status;
    1362             :                 }
    1363           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1364           0 :                         if (len > 2) {
    1365           0 :                                 len -= 2;
    1366             :                         } else {
    1367           0 :                                 len = 0;
    1368             :                         }
    1369             :                 } else {
    1370           0 :                         if (len > 1) {
    1371           0 :                                 len -= 1;
    1372             :                         } else {
    1373           0 :                                 len = 0;
    1374             :                         }
    1375             :                 }
    1376           0 :                 SCVAL(nameptr,0,len);
    1377           0 :                 p += len;
    1378           0 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1379           0 :                 break;
    1380             : 
    1381           0 :         case SMB_FIND_EA_LIST:
    1382             :         {
    1383           0 :                 struct ea_list *file_list = NULL;
    1384           0 :                 size_t ea_len = 0;
    1385             : 
    1386           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
    1387           0 :                 if (!name_list) {
    1388           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1389             :                 }
    1390           0 :                 if (requires_resume_key) {
    1391           0 :                         SIVAL(p,0,reskey);
    1392           0 :                         p += 4;
    1393             :                 }
    1394           0 :                 srv_put_dos_date2(p,0,create_date);
    1395           0 :                 srv_put_dos_date2(p,4,adate);
    1396           0 :                 srv_put_dos_date2(p,8,mdate);
    1397           0 :                 SIVAL(p,12,(uint32_t)file_size);
    1398           0 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1399           0 :                 SSVAL(p,20,mode);
    1400           0 :                 p += 22; /* p now points to the EA area. */
    1401             : 
    1402           0 :                 status = get_ea_list_from_fsp(ctx,
    1403           0 :                                                smb_fname->fsp,
    1404             :                                                &ea_len, &file_list);
    1405           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1406           0 :                         file_list = NULL;
    1407             :                 }
    1408           0 :                 name_list = ea_list_union(name_list, file_list, &ea_len);
    1409             : 
    1410             :                 /* We need to determine if this entry will fit in the space available. */
    1411             :                 /* Max string size is 255 bytes. */
    1412           0 :                 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
    1413           0 :                         DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1414             :                                 "(wanted %u, had %d)\n",
    1415             :                                 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
    1416             :                                 space_remaining ));
    1417           0 :                         return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1418             :                 }
    1419             : 
    1420             :                 /* Push the ea_data followed by the name. */
    1421           0 :                 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
    1422           0 :                 nameptr = p;
    1423           0 :                 status = srvstr_push(base_data, flags2,
    1424             :                                   p + 1, fname, PTR_DIFF(end_data, p+1),
    1425             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1426           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1427           0 :                         return status;
    1428             :                 }
    1429           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1430           0 :                         if (len > 2) {
    1431           0 :                                 len -= 2;
    1432             :                         } else {
    1433           0 :                                 len = 0;
    1434             :                         }
    1435             :                 } else {
    1436           0 :                         if (len > 1) {
    1437           0 :                                 len -= 1;
    1438             :                         } else {
    1439           0 :                                 len = 0;
    1440             :                         }
    1441             :                 }
    1442           0 :                 SCVAL(nameptr,0,len);
    1443           0 :                 p += len + 1;
    1444           0 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1445           0 :                 break;
    1446             :         }
    1447             : 
    1448           0 :         case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    1449           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
    1450           0 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    1451           0 :                 p += 4;
    1452           0 :                 SIVAL(p,0,reskey); p += 4;
    1453           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1454           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1455           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1456           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1457           0 :                 SOFF_T(p,0,file_size); p += 8;
    1458           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1459           0 :                 SIVAL(p,0,mode); p += 4;
    1460           0 :                 q = p; p += 4; /* q is placeholder for name length. */
    1461           0 :                 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1462           0 :                 SIVAL(p, 0, ea_size);
    1463           0 :                 p += 4;
    1464             :                 /* Clear the short name buffer. This is
    1465             :                  * IMPORTANT as not doing so will trigger
    1466             :                  * a Win2k client bug. JRA.
    1467             :                  */
    1468           0 :                 if (!was_8_3 && check_mangled_names) {
    1469             :                         char mangled_name[13]; /* mangled 8.3 name. */
    1470           0 :                         if (!name_to_8_3(fname,mangled_name,True,
    1471           0 :                                            conn->params)) {
    1472             :                                 /* Error - mangle failed ! */
    1473           0 :                                 memset(mangled_name,'\0',12);
    1474             :                         }
    1475           0 :                         mangled_name[12] = 0;
    1476           0 :                         status = srvstr_push(base_data, flags2,
    1477             :                                           p+2, mangled_name, 24,
    1478             :                                           STR_UPPER|STR_UNICODE, &len);
    1479           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1480           0 :                                 return status;
    1481             :                         }
    1482           0 :                         if (len < 24) {
    1483           0 :                                 memset(p + 2 + len,'\0',24 - len);
    1484             :                         }
    1485           0 :                         SSVAL(p, 0, len);
    1486             :                 } else {
    1487           0 :                         memset(p,'\0',26);
    1488             :                 }
    1489           0 :                 p += 2 + 24;
    1490           0 :                 status = srvstr_push(base_data, flags2, p,
    1491             :                                   fname, PTR_DIFF(end_data, p),
    1492             :                                   STR_TERMINATE_ASCII, &len);
    1493           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1494           0 :                         return status;
    1495             :                 }
    1496           0 :                 SIVAL(q,0,len);
    1497           0 :                 p += len;
    1498             : 
    1499           0 :                 len = PTR_DIFF(p, pdata);
    1500           0 :                 pad = (len + (align-1)) & ~(align-1);
    1501             :                 /*
    1502             :                  * offset to the next entry, the caller
    1503             :                  * will overwrite it for the last entry
    1504             :                  * that's why we always include the padding
    1505             :                  */
    1506           0 :                 SIVAL(pdata,0,pad);
    1507             :                 /*
    1508             :                  * set padding to zero
    1509             :                  */
    1510           0 :                 if (do_pad) {
    1511           0 :                         memset(p, 0, pad - len);
    1512           0 :                         p = pdata + pad;
    1513             :                 } else {
    1514           0 :                         p = pdata + len;
    1515             :                 }
    1516           0 :                 break;
    1517             : 
    1518           0 :         case SMB_FIND_FILE_DIRECTORY_INFO:
    1519           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
    1520           0 :                 p += 4;
    1521           0 :                 SIVAL(p,0,reskey); p += 4;
    1522           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1523           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1524           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1525           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1526           0 :                 SOFF_T(p,0,file_size); p += 8;
    1527           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1528           0 :                 SIVAL(p,0,mode); p += 4;
    1529           0 :                 status = srvstr_push(base_data, flags2,
    1530             :                                   p + 4, fname, PTR_DIFF(end_data, p+4),
    1531             :                                   STR_TERMINATE_ASCII, &len);
    1532           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1533           0 :                         return status;
    1534             :                 }
    1535           0 :                 SIVAL(p,0,len);
    1536           0 :                 p += 4 + len;
    1537             : 
    1538           0 :                 len = PTR_DIFF(p, pdata);
    1539           0 :                 pad = (len + (align-1)) & ~(align-1);
    1540             :                 /*
    1541             :                  * offset to the next entry, the caller
    1542             :                  * will overwrite it for the last entry
    1543             :                  * that's why we always include the padding
    1544             :                  */
    1545           0 :                 SIVAL(pdata,0,pad);
    1546             :                 /*
    1547             :                  * set padding to zero
    1548             :                  */
    1549           0 :                 if (do_pad) {
    1550           0 :                         memset(p, 0, pad - len);
    1551           0 :                         p = pdata + pad;
    1552             :                 } else {
    1553           0 :                         p = pdata + len;
    1554             :                 }
    1555           0 :                 break;
    1556             : 
    1557           0 :         case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    1558           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
    1559           0 :                 p += 4;
    1560           0 :                 SIVAL(p,0,reskey); p += 4;
    1561           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1562           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1563           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1564           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1565           0 :                 SOFF_T(p,0,file_size); p += 8;
    1566           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1567           0 :                 SIVAL(p,0,mode); p += 4;
    1568           0 :                 q = p; p += 4; /* q is placeholder for name length. */
    1569           0 :                 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1570           0 :                 SIVAL(p, 0, ea_size);
    1571           0 :                 p +=4;
    1572           0 :                 status = srvstr_push(base_data, flags2, p,
    1573             :                                   fname, PTR_DIFF(end_data, p),
    1574             :                                   STR_TERMINATE_ASCII, &len);
    1575           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1576           0 :                         return status;
    1577             :                 }
    1578           0 :                 SIVAL(q, 0, len);
    1579           0 :                 p += len;
    1580             : 
    1581           0 :                 len = PTR_DIFF(p, pdata);
    1582           0 :                 pad = (len + (align-1)) & ~(align-1);
    1583             :                 /*
    1584             :                  * offset to the next entry, the caller
    1585             :                  * will overwrite it for the last entry
    1586             :                  * that's why we always include the padding
    1587             :                  */
    1588           0 :                 SIVAL(pdata,0,pad);
    1589             :                 /*
    1590             :                  * set padding to zero
    1591             :                  */
    1592           0 :                 if (do_pad) {
    1593           0 :                         memset(p, 0, pad - len);
    1594           0 :                         p = pdata + pad;
    1595             :                 } else {
    1596           0 :                         p = pdata + len;
    1597             :                 }
    1598           0 :                 break;
    1599             : 
    1600          17 :         case SMB_FIND_FILE_NAMES_INFO:
    1601          17 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
    1602          17 :                 p += 4;
    1603          17 :                 SIVAL(p,0,reskey); p += 4;
    1604          17 :                 p += 4;
    1605             :                 /* this must *not* be null terminated or w2k gets in a loop trying to set an
    1606             :                    acl on a dir (tridge) */
    1607          17 :                 status = srvstr_push(base_data, flags2, p,
    1608             :                                   fname, PTR_DIFF(end_data, p),
    1609             :                                   STR_TERMINATE_ASCII, &len);
    1610          17 :                 if (!NT_STATUS_IS_OK(status)) {
    1611           0 :                         return status;
    1612             :                 }
    1613          17 :                 SIVAL(p, -4, len);
    1614          17 :                 p += len;
    1615             : 
    1616          17 :                 len = PTR_DIFF(p, pdata);
    1617          17 :                 pad = (len + (align-1)) & ~(align-1);
    1618             :                 /*
    1619             :                  * offset to the next entry, the caller
    1620             :                  * will overwrite it for the last entry
    1621             :                  * that's why we always include the padding
    1622             :                  */
    1623          17 :                 SIVAL(pdata,0,pad);
    1624             :                 /*
    1625             :                  * set padding to zero
    1626             :                  */
    1627          17 :                 if (do_pad) {
    1628           0 :                         memset(p, 0, pad - len);
    1629           0 :                         p = pdata + pad;
    1630             :                 } else {
    1631          17 :                         p = pdata + len;
    1632             :                 }
    1633          17 :                 break;
    1634             : 
    1635           0 :         case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    1636           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
    1637           0 :                 p += 4;
    1638           0 :                 SIVAL(p,0,reskey); p += 4;
    1639           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1640           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1641           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1642           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1643           0 :                 SOFF_T(p,0,file_size); p += 8;
    1644           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1645           0 :                 SIVAL(p,0,mode); p += 4;
    1646           0 :                 q = p; p += 4; /* q is placeholder for name length. */
    1647           0 :                 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1648           0 :                 SIVAL(p, 0, ea_size);
    1649           0 :                 p += 4;
    1650           0 :                 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
    1651           0 :                 SBVAL(p,0,file_id); p += 8;
    1652           0 :                 status = srvstr_push(base_data, flags2, p,
    1653             :                                   fname, PTR_DIFF(end_data, p),
    1654             :                                   STR_TERMINATE_ASCII, &len);
    1655           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1656           0 :                         return status;
    1657             :                 }
    1658           0 :                 SIVAL(q, 0, len);
    1659           0 :                 p += len;
    1660             : 
    1661           0 :                 len = PTR_DIFF(p, pdata);
    1662           0 :                 pad = (len + (align-1)) & ~(align-1);
    1663             :                 /*
    1664             :                  * offset to the next entry, the caller
    1665             :                  * will overwrite it for the last entry
    1666             :                  * that's why we always include the padding
    1667             :                  */
    1668           0 :                 SIVAL(pdata,0,pad);
    1669             :                 /*
    1670             :                  * set padding to zero
    1671             :                  */
    1672           0 :                 if (do_pad) {
    1673           0 :                         memset(p, 0, pad - len);
    1674           0 :                         p = pdata + pad;
    1675             :                 } else {
    1676           0 :                         p = pdata + len;
    1677             :                 }
    1678           0 :                 break;
    1679             : 
    1680       10604 :         case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    1681       10604 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
    1682       10604 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    1683       10604 :                 p += 4;
    1684       10604 :                 SIVAL(p,0,reskey); p += 4;
    1685       10604 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1686       10604 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1687       10604 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1688       10604 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1689       10604 :                 SOFF_T(p,0,file_size); p += 8;
    1690       10604 :                 SOFF_T(p,0,allocation_size); p += 8;
    1691       10604 :                 SIVAL(p,0,mode); p += 4;
    1692       10604 :                 q = p; p += 4; /* q is placeholder for name length */
    1693       10604 :                 if (readdir_attr_data &&
    1694           0 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1695             :                         /*
    1696             :                          * OS X specific SMB2 extension negotiated via
    1697             :                          * AAPL create context: return max_access in
    1698             :                          * ea_size field.
    1699             :                          */
    1700           0 :                         ea_size = readdir_attr_data->attr_data.aapl.max_access;
    1701             :                 } else {
    1702       10604 :                         ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
    1703             :                 }
    1704       10604 :                 SIVAL(p,0,ea_size); /* Extended attributes */
    1705       10604 :                 p += 4;
    1706             : 
    1707       10604 :                 if (readdir_attr_data &&
    1708           0 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1709             :                         /*
    1710             :                          * OS X specific SMB2 extension negotiated via
    1711             :                          * AAPL create context: return resource fork
    1712             :                          * length and compressed FinderInfo in
    1713             :                          * shortname field.
    1714             :                          *
    1715             :                          * According to documentation short_name_len
    1716             :                          * should be 0, but on the wire behaviour
    1717             :                          * shows its set to 24 by clients.
    1718             :                          */
    1719           0 :                         SSVAL(p, 0, 24);
    1720             : 
    1721             :                         /* Resourefork length */
    1722           0 :                         SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
    1723             : 
    1724             :                         /* Compressed FinderInfo */
    1725           0 :                         memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
    1726       10604 :                 } else if (!was_8_3 && check_mangled_names) {
    1727             :                         char mangled_name[13]; /* mangled 8.3 name. */
    1728        2506 :                         if (!name_to_8_3(fname,mangled_name,True,
    1729        2506 :                                         conn->params)) {
    1730             :                                 /* Error - mangle failed ! */
    1731           0 :                                 memset(mangled_name,'\0',12);
    1732             :                         }
    1733        2506 :                         mangled_name[12] = 0;
    1734        2506 :                         status = srvstr_push(base_data, flags2,
    1735             :                                           p+2, mangled_name, 24,
    1736             :                                           STR_UPPER|STR_UNICODE, &len);
    1737        2506 :                         if (!NT_STATUS_IS_OK(status)) {
    1738           0 :                                 return status;
    1739             :                         }
    1740        2506 :                         SSVAL(p, 0, len);
    1741        2506 :                         if (len < 24) {
    1742        2445 :                                 memset(p + 2 + len,'\0',24 - len);
    1743             :                         }
    1744        2506 :                         SSVAL(p, 0, len);
    1745             :                 } else {
    1746             :                         /* Clear the short name buffer. This is
    1747             :                          * IMPORTANT as not doing so will trigger
    1748             :                          * a Win2k client bug. JRA.
    1749             :                          */
    1750        8098 :                         memset(p,'\0',26);
    1751             :                 }
    1752       10604 :                 p += 26;
    1753             : 
    1754             :                 /* Reserved ? */
    1755       10604 :                 if (readdir_attr_data &&
    1756           0 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1757             :                         /*
    1758             :                          * OS X specific SMB2 extension negotiated via
    1759             :                          * AAPL create context: return UNIX mode in
    1760             :                          * reserved field.
    1761             :                          */
    1762           0 :                         uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
    1763           0 :                         SSVAL(p, 0, aapl_mode);
    1764             :                 } else {
    1765       10604 :                         SSVAL(p, 0, 0);
    1766             :                 }
    1767       10604 :                 p += 2;
    1768             : 
    1769       10604 :                 SBVAL(p,0,file_id); p += 8;
    1770       10604 :                 status = srvstr_push(base_data, flags2, p,
    1771             :                                   fname, PTR_DIFF(end_data, p),
    1772             :                                   STR_TERMINATE_ASCII, &len);
    1773       10604 :                 if (!NT_STATUS_IS_OK(status)) {
    1774           8 :                         return status;
    1775             :                 }
    1776       10596 :                 SIVAL(q,0,len);
    1777       10596 :                 p += len;
    1778             : 
    1779       10596 :                 len = PTR_DIFF(p, pdata);
    1780       10596 :                 pad = (len + (align-1)) & ~(align-1);
    1781             :                 /*
    1782             :                  * offset to the next entry, the caller
    1783             :                  * will overwrite it for the last entry
    1784             :                  * that's why we always include the padding
    1785             :                  */
    1786       10596 :                 SIVAL(pdata,0,pad);
    1787             :                 /*
    1788             :                  * set padding to zero
    1789             :                  */
    1790       10596 :                 if (do_pad) {
    1791           0 :                         memset(p, 0, pad - len);
    1792           0 :                         p = pdata + pad;
    1793             :                 } else {
    1794       10596 :                         p = pdata + len;
    1795             :                 }
    1796       10596 :                 break;
    1797             : 
    1798             :         /* CIFS UNIX Extension. */
    1799             : 
    1800           0 :         case SMB_FIND_FILE_UNIX:
    1801             :         case SMB_FIND_FILE_UNIX_INFO2:
    1802           0 :                 p+= 4;
    1803           0 :                 SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
    1804             : 
    1805             :                 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
    1806             : 
    1807           0 :                 if (info_level == SMB_FIND_FILE_UNIX) {
    1808           0 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
    1809           0 :                         p = store_file_unix_basic(conn, p,
    1810             :                                                 NULL, &smb_fname->st);
    1811           0 :                         status = srvstr_push(base_data, flags2, p,
    1812             :                                           fname, PTR_DIFF(end_data, p),
    1813             :                                           STR_TERMINATE, &len);
    1814           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1815           0 :                                 return status;
    1816             :                         }
    1817             :                 } else {
    1818           0 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
    1819           0 :                         p = store_file_unix_basic_info2(conn, p,
    1820             :                                                 NULL, &smb_fname->st);
    1821           0 :                         nameptr = p;
    1822           0 :                         p += 4;
    1823           0 :                         status = srvstr_push(base_data, flags2, p, fname,
    1824             :                                           PTR_DIFF(end_data, p), 0, &len);
    1825           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1826           0 :                                 return status;
    1827             :                         }
    1828           0 :                         SIVAL(nameptr, 0, len);
    1829             :                 }
    1830             : 
    1831           0 :                 p += len;
    1832             : 
    1833           0 :                 len = PTR_DIFF(p, pdata);
    1834           0 :                 pad = (len + (align-1)) & ~(align-1);
    1835             :                 /*
    1836             :                  * offset to the next entry, the caller
    1837             :                  * will overwrite it for the last entry
    1838             :                  * that's why we always include the padding
    1839             :                  */
    1840           0 :                 SIVAL(pdata,0,pad);
    1841             :                 /*
    1842             :                  * set padding to zero
    1843             :                  */
    1844           0 :                 if (do_pad) {
    1845           0 :                         memset(p, 0, pad - len);
    1846           0 :                         p = pdata + pad;
    1847             :                 } else {
    1848           0 :                         p = pdata + len;
    1849             :                 }
    1850             :                 /* End of SMB_QUERY_FILE_UNIX_BASIC */
    1851             : 
    1852           0 :                 break;
    1853             : 
    1854             :         /* SMB2 UNIX Extension. */
    1855             : 
    1856           0 :         case SMB2_FILE_POSIX_INFORMATION:
    1857             :                 {
    1858           0 :                         uint8_t *buf = NULL;
    1859           0 :                         ssize_t plen = 0;
    1860           0 :                         p+= 4;
    1861           0 :                         SIVAL(p,0,reskey); p+= 4;
    1862             : 
    1863           0 :                         DEBUG(10,("smbd_marshall_dir_entry: "
    1864             :                                   "SMB2_FILE_POSIX_INFORMATION\n"));
    1865           0 :                         if (!(conn->sconn->using_smb2)) {
    1866           0 :                                 return NT_STATUS_INVALID_LEVEL;
    1867             :                         }
    1868           0 :                         if (!lp_smb3_unix_extensions()) {
    1869           0 :                                 return NT_STATUS_INVALID_LEVEL;
    1870             :                         }
    1871             : 
    1872             :                         /* Determine the size of the posix info context */
    1873           0 :                         plen = store_smb2_posix_info(conn,
    1874             :                                                      &smb_fname->st,
    1875             :                                                      0,
    1876             :                                                      mode,
    1877             :                                                      NULL,
    1878             :                                                      0);
    1879           0 :                         if (plen == -1) {
    1880           0 :                                 return NT_STATUS_INVALID_PARAMETER;
    1881             :                         }
    1882           0 :                         buf = talloc_zero_size(ctx, plen);
    1883           0 :                         if (buf == NULL) {
    1884           0 :                                 return NT_STATUS_NO_MEMORY;
    1885             :                         }
    1886             : 
    1887             :                         /* Store the context in buf */
    1888           0 :                         store_smb2_posix_info(conn,
    1889             :                                               &smb_fname->st,
    1890             :                                               0,
    1891             :                                               mode,
    1892             :                                               buf,
    1893             :                                               plen);
    1894           0 :                         memcpy(p, buf, plen);
    1895           0 :                         p += plen;
    1896           0 :                         TALLOC_FREE(buf);
    1897             : 
    1898           0 :                         nameptr = p;
    1899           0 :                         p += 4;
    1900           0 :                         status = srvstr_push(base_data, flags2, p, fname,
    1901             :                                         PTR_DIFF(end_data, p), 0, &len);
    1902           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1903           0 :                                 return status;
    1904             :                         }
    1905           0 :                         SIVAL(nameptr, 0, len);
    1906             : 
    1907           0 :                         p += len;
    1908             : 
    1909           0 :                         len = PTR_DIFF(p, pdata);
    1910           0 :                         pad = (len + (align-1)) & ~(align-1);
    1911             :                         /*
    1912             :                          * offset to the next entry, the caller
    1913             :                          * will overwrite it for the last entry
    1914             :                          * that's why we always include the padding
    1915             :                          */
    1916           0 :                         SIVAL(pdata,0,pad);
    1917           0 :                         break;
    1918             :                 }
    1919             : 
    1920           0 :         default:
    1921           0 :                 return NT_STATUS_INVALID_LEVEL;
    1922             :         }
    1923             : 
    1924       10613 :         if (PTR_DIFF(p,pdata) > space_remaining) {
    1925           0 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1926             :                         "(wanted %u, had %d)\n",
    1927             :                         (unsigned int)PTR_DIFF(p,pdata),
    1928             :                         space_remaining ));
    1929           0 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1930             :         }
    1931             : 
    1932             :         /* Setup the last entry pointer, as an offset from base_data */
    1933       10613 :         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
    1934             :         /* Advance the data pointer to the next slot */
    1935       10613 :         *ppdata = p;
    1936             : 
    1937       10613 :         return NT_STATUS_OK;
    1938             : }
    1939             : 
    1940       14920 : NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
    1941             :                                connection_struct *conn,
    1942             :                                struct dptr_struct *dirptr,
    1943             :                                uint16_t flags2,
    1944             :                                const char *path_mask,
    1945             :                                uint32_t dirtype,
    1946             :                                int info_level,
    1947             :                                int requires_resume_key,
    1948             :                                bool dont_descend,
    1949             :                                bool ask_sharemode,
    1950             :                                bool get_dosmode,
    1951             :                                uint8_t align,
    1952             :                                bool do_pad,
    1953             :                                char **ppdata,
    1954             :                                char *base_data,
    1955             :                                char *end_data,
    1956             :                                int space_remaining,
    1957             :                                struct smb_filename **_smb_fname,
    1958             :                                bool *got_exact_match,
    1959             :                                int *_last_entry_off,
    1960             :                                struct ea_list *name_list,
    1961             :                                struct file_id *file_id)
    1962             : {
    1963             :         const char *p;
    1964       14920 :         const char *mask = NULL;
    1965       14920 :         long prev_dirpos = 0;
    1966       14920 :         uint32_t mode = 0;
    1967       14920 :         char *fname = NULL;
    1968       14920 :         struct smb_filename *smb_fname = NULL;
    1969             :         struct smbd_dirptr_lanman2_state state;
    1970             :         bool ok;
    1971       14920 :         uint64_t last_entry_off = 0;
    1972             :         NTSTATUS status;
    1973             :         enum mangled_names_options mangled_names;
    1974             :         bool marshall_with_83_names;
    1975             : 
    1976       14920 :         mangled_names = lp_mangled_names(conn->params);
    1977             : 
    1978       14920 :         ZERO_STRUCT(state);
    1979       14920 :         state.conn = conn;
    1980       14920 :         state.info_level = info_level;
    1981       14920 :         if (mangled_names != MANGLED_NAMES_NO) {
    1982       14920 :                 state.check_mangled_names = true;
    1983             :         }
    1984       14920 :         state.has_wild = dptr_has_wild(dirptr);
    1985       14920 :         state.got_exact_match = false;
    1986       14920 :         state.case_sensitive = dptr_case_sensitive(dirptr);
    1987             : 
    1988       14920 :         *got_exact_match = false;
    1989             : 
    1990       14920 :         p = strrchr_m(path_mask,'/');
    1991       14920 :         if(p != NULL) {
    1992           0 :                 if(p[1] == '\0') {
    1993           0 :                         mask = "*.*";
    1994             :                 } else {
    1995           0 :                         mask = p+1;
    1996             :                 }
    1997             :         } else {
    1998       14920 :                 mask = path_mask;
    1999             :         }
    2000             : 
    2001       14920 :         ok = smbd_dirptr_get_entry(ctx,
    2002             :                                    dirptr,
    2003             :                                    mask,
    2004             :                                    dirtype,
    2005             :                                    dont_descend,
    2006             :                                    ask_sharemode,
    2007             :                                    get_dosmode,
    2008             :                                    smbd_dirptr_lanman2_match_fn,
    2009             :                                    smbd_dirptr_lanman2_mode_fn,
    2010             :                                    &state,
    2011             :                                    &fname,
    2012             :                                    &smb_fname,
    2013             :                                    &mode,
    2014             :                                    &prev_dirpos);
    2015       14920 :         if (!ok) {
    2016        4299 :                 return NT_STATUS_END_OF_FILE;
    2017             :         }
    2018             : 
    2019       10621 :         *got_exact_match = state.got_exact_match;
    2020             : 
    2021       10621 :         marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
    2022             : 
    2023       10621 :         status = smbd_marshall_dir_entry(ctx,
    2024             :                                      conn,
    2025             :                                      flags2,
    2026             :                                      info_level,
    2027             :                                      name_list,
    2028             :                                      marshall_with_83_names,
    2029             :                                      requires_resume_key,
    2030             :                                      mode,
    2031             :                                      fname,
    2032             :                                      smb_fname,
    2033             :                                      space_remaining,
    2034             :                                      align,
    2035             :                                      do_pad,
    2036             :                                      base_data,
    2037             :                                      ppdata,
    2038             :                                      end_data,
    2039             :                                      &last_entry_off);
    2040       10621 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
    2041           8 :                 DEBUG(1,("Conversion error: illegal character: %s\n",
    2042             :                          smb_fname_str_dbg(smb_fname)));
    2043             :         }
    2044             : 
    2045       10621 :         if (file_id != NULL) {
    2046       10621 :                 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    2047             :         }
    2048             : 
    2049       10621 :         if (!NT_STATUS_IS_OK(status) &&
    2050           8 :             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
    2051             :         {
    2052           8 :                 TALLOC_FREE(smb_fname);
    2053           8 :                 TALLOC_FREE(fname);
    2054           8 :                 return status;
    2055             :         }
    2056             : 
    2057       10613 :         if (_smb_fname != NULL) {
    2058             :                 /*
    2059             :                  * smb_fname is already talloc'ed off ctx.
    2060             :                  * We just need to make sure we don't return
    2061             :                  * any stream_name, and replace base_name
    2062             :                  * with fname in case base_name got mangled.
    2063             :                  * This allows us to preserve any smb_fname->fsp
    2064             :                  * for asynchronous handle lookups.
    2065             :                  */
    2066       10613 :                 TALLOC_FREE(smb_fname->stream_name);
    2067       10613 :                 TALLOC_FREE(smb_fname->base_name);
    2068       10613 :                 smb_fname->base_name = talloc_strdup(smb_fname, fname);
    2069             : 
    2070       10613 :                 if (smb_fname->base_name == NULL) {
    2071           0 :                         TALLOC_FREE(smb_fname);
    2072           0 :                         TALLOC_FREE(fname);
    2073           0 :                         return NT_STATUS_NO_MEMORY;
    2074             :                 }
    2075       10613 :                 *_smb_fname = smb_fname;
    2076             :         } else {
    2077           0 :                 TALLOC_FREE(smb_fname);
    2078             :         }
    2079       10613 :         TALLOC_FREE(fname);
    2080             : 
    2081       10613 :         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
    2082           0 :                 dptr_SeekDir(dirptr, prev_dirpos);
    2083           0 :                 return status;
    2084             :         }
    2085             : 
    2086       10613 :         *_last_entry_off = last_entry_off;
    2087       10613 :         return NT_STATUS_OK;
    2088             : }
    2089             : 
    2090           0 : unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
    2091             : {
    2092             :         const struct loadparm_substitution *lp_sub =
    2093           0 :                 loadparm_s3_global_substitution();
    2094             : 
    2095           0 :         E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
    2096           0 :         return objid;
    2097             : }
    2098             : 
    2099           0 : static void samba_extended_info_version(struct smb_extended_info *extended_info)
    2100             : {
    2101           0 :         SMB_ASSERT(extended_info != NULL);
    2102             : 
    2103           0 :         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
    2104           0 :         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
    2105             :                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
    2106             :                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
    2107             : #ifdef SAMBA_VERSION_REVISION
    2108             :         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
    2109             : #endif
    2110           0 :         extended_info->samba_subversion = 0;
    2111             : #ifdef SAMBA_VERSION_RC_RELEASE
    2112             :         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
    2113             : #else
    2114             : #ifdef SAMBA_VERSION_PRE_RELEASE
    2115             :         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
    2116             : #endif
    2117             : #endif
    2118             : #ifdef SAMBA_VERSION_VENDOR_PATCH
    2119             :         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
    2120             : #endif
    2121           0 :         extended_info->samba_gitcommitdate = 0;
    2122             : #ifdef SAMBA_VERSION_COMMIT_TIME
    2123             :         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
    2124             : #endif
    2125             : 
    2126           0 :         memset(extended_info->samba_version_string, 0,
    2127             :                sizeof(extended_info->samba_version_string));
    2128             : 
    2129           0 :         snprintf (extended_info->samba_version_string,
    2130             :                   sizeof(extended_info->samba_version_string),
    2131             :                   "%s", samba_version_string());
    2132           0 : }
    2133             : 
    2134           0 : static bool fsinfo_unix_valid_level(connection_struct *conn,
    2135             :                                     uint16_t info_level)
    2136             : {
    2137           0 :         if (conn->sconn->using_smb2 &&
    2138           0 :                         lp_smb3_unix_extensions() &&
    2139             :                         info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
    2140           0 :                 return true;
    2141             :         }
    2142             : #if defined(SMB1SERVER)
    2143             :         if (lp_smb1_unix_extensions() &&
    2144             :                         info_level == SMB_QUERY_POSIX_FS_INFO) {
    2145             :                 return true;
    2146             :         }
    2147             : #endif
    2148           0 :         return false;
    2149             : }
    2150             : 
    2151         387 : NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
    2152             :                          connection_struct *conn,
    2153             :                          TALLOC_CTX *mem_ctx,
    2154             :                          uint16_t info_level,
    2155             :                          uint16_t flags2,
    2156             :                          unsigned int max_data_bytes,
    2157             :                          size_t *fixed_portion,
    2158             :                          struct smb_filename *fname,
    2159             :                          char **ppdata,
    2160             :                          int *ret_data_len)
    2161             : {
    2162             :         const struct loadparm_substitution *lp_sub =
    2163         387 :                 loadparm_s3_global_substitution();
    2164             :         char *pdata, *end_data;
    2165         387 :         int data_len = 0;
    2166         387 :         size_t len = 0;
    2167         387 :         const char *vname = volume_label(talloc_tos(), SNUM(conn));
    2168         387 :         int snum = SNUM(conn);
    2169         387 :         const char *fstype = lp_fstype(SNUM(conn));
    2170         387 :         const char *filename = NULL;
    2171         387 :         const uint64_t bytes_per_sector = 512;
    2172         387 :         uint32_t additional_flags = 0;
    2173             :         struct smb_filename smb_fname;
    2174             :         SMB_STRUCT_STAT st;
    2175         387 :         NTSTATUS status = NT_STATUS_OK;
    2176             :         uint64_t df_ret;
    2177             :         uint32_t serial;
    2178             : 
    2179         387 :         if (fname == NULL || fname->base_name == NULL) {
    2180           8 :                 filename = ".";
    2181             :         } else {
    2182         379 :                 filename = fname->base_name;
    2183             :         }
    2184             : 
    2185         387 :         if (IS_IPC(conn)) {
    2186           0 :                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
    2187           0 :                         DEBUG(0,("smbd_do_qfsinfo: not an allowed "
    2188             :                                 "info level (0x%x) on IPC$.\n",
    2189             :                                 (unsigned int)info_level));
    2190           0 :                         return NT_STATUS_ACCESS_DENIED;
    2191             :                 }
    2192             :         }
    2193             : 
    2194         387 :         DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
    2195             : 
    2196         387 :         smb_fname = (struct smb_filename) {
    2197             :                 .base_name = discard_const_p(char, filename),
    2198         387 :                 .flags = fname ? fname->flags : 0,
    2199         387 :                 .twrp = fname ? fname->twrp : 0,
    2200             :         };
    2201             : 
    2202         387 :         if(info_level != SMB_FS_QUOTA_INFORMATION
    2203         387 :            && SMB_VFS_STAT(conn, &smb_fname) != 0) {
    2204           0 :                 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
    2205           0 :                 return map_nt_error_from_unix(errno);
    2206             :         }
    2207             : 
    2208         387 :         st = smb_fname.st;
    2209             : 
    2210         387 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    2211           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2212             :         }
    2213             : 
    2214         387 :         *ppdata = (char *)SMB_REALLOC(
    2215             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2216         387 :         if (*ppdata == NULL) {
    2217           0 :                 return NT_STATUS_NO_MEMORY;
    2218             :         }
    2219             : 
    2220         387 :         pdata = *ppdata;
    2221         387 :         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2222         387 :         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    2223             : 
    2224         387 :         *fixed_portion = 0;
    2225             : 
    2226         387 :         switch (info_level) {
    2227           0 :                 case SMB_INFO_ALLOCATION:
    2228             :                 {
    2229             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2230           0 :                         data_len = 18;
    2231           0 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2232             :                                                 &dfree, &dsize);
    2233           0 :                         if (df_ret == (uint64_t)-1) {
    2234           0 :                                 return map_nt_error_from_unix(errno);
    2235             :                         }
    2236             : 
    2237           0 :                         block_size = lp_block_size(snum);
    2238           0 :                         if (bsize < block_size) {
    2239           0 :                                 uint64_t factor = block_size/bsize;
    2240           0 :                                 bsize = block_size;
    2241           0 :                                 dsize /= factor;
    2242           0 :                                 dfree /= factor;
    2243             :                         }
    2244           0 :                         if (bsize > block_size) {
    2245           0 :                                 uint64_t factor = bsize/block_size;
    2246           0 :                                 bsize = block_size;
    2247           0 :                                 dsize *= factor;
    2248           0 :                                 dfree *= factor;
    2249             :                         }
    2250           0 :                         sectors_per_unit = bsize/bytes_per_sector;
    2251             : 
    2252           0 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
    2253             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2254             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2255             : 
    2256             :                         /*
    2257             :                          * For large drives, return max values and not modulo.
    2258             :                          */
    2259           0 :                         dsize = MIN(dsize, UINT32_MAX);
    2260           0 :                         dfree = MIN(dfree, UINT32_MAX);
    2261             : 
    2262           0 :                         SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
    2263           0 :                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
    2264           0 :                         SIVAL(pdata,l1_cUnit,dsize);
    2265           0 :                         SIVAL(pdata,l1_cUnitAvail,dfree);
    2266           0 :                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
    2267           0 :                         break;
    2268             :                 }
    2269             : 
    2270           0 :                 case SMB_INFO_VOLUME:
    2271             :                         /* Return volume name */
    2272             :                         /*
    2273             :                          * Add volume serial number - hash of a combination of
    2274             :                          * the called hostname and the service name.
    2275             :                          */
    2276           0 :                         serial = generate_volume_serial_number(lp_sub, snum);
    2277           0 :                         SIVAL(pdata,0,serial);
    2278             :                         /*
    2279             :                          * Win2k3 and previous mess this up by sending a name length
    2280             :                          * one byte short. I believe only older clients (OS/2 Win9x) use
    2281             :                          * this call so try fixing this by adding a terminating null to
    2282             :                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
    2283             :                          */
    2284           0 :                         status = srvstr_push(
    2285             :                                 pdata, flags2,
    2286             :                                 pdata+l2_vol_szVolLabel, vname,
    2287             :                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
    2288             :                                 STR_NOALIGN|STR_TERMINATE, &len);
    2289           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2290           0 :                                 return status;
    2291             :                         }
    2292           0 :                         SCVAL(pdata,l2_vol_cch,len);
    2293           0 :                         data_len = l2_vol_szVolLabel + len;
    2294           0 :                         DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
    2295             :                                  "name = %s serial = 0x%04"PRIx32"\n",
    2296             :                                  (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
    2297             :                                  (unsigned)len, vname, serial));
    2298           0 :                         break;
    2299             : 
    2300           0 :                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
    2301             :                 case SMB_FS_ATTRIBUTE_INFORMATION:
    2302             : 
    2303           0 :                         additional_flags = 0;
    2304             : #if defined(HAVE_SYS_QUOTAS)
    2305           0 :                         additional_flags |= FILE_VOLUME_QUOTAS;
    2306             : #endif
    2307             : 
    2308           0 :                         if(lp_nt_acl_support(SNUM(conn))) {
    2309           0 :                                 additional_flags |= FILE_PERSISTENT_ACLS;
    2310             :                         }
    2311             : 
    2312             :                         /* Capabilities are filled in at connection time through STATVFS call */
    2313           0 :                         additional_flags |= conn->fs_capabilities;
    2314           0 :                         additional_flags |= lp_parm_int(conn->params->service,
    2315             :                                                         "share", "fake_fscaps",
    2316             :                                                         0);
    2317             : 
    2318           0 :                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
    2319             :                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
    2320             :                                 additional_flags); /* FS ATTRIBUTES */
    2321             : 
    2322           0 :                         SIVAL(pdata,4,255); /* Max filename component length */
    2323             :                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
    2324             :                                 and will think we can't do long filenames */
    2325           0 :                         status = srvstr_push(pdata, flags2, pdata+12, fstype,
    2326             :                                           PTR_DIFF(end_data, pdata+12),
    2327             :                                           STR_UNICODE, &len);
    2328           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2329           0 :                                 return status;
    2330             :                         }
    2331           0 :                         SIVAL(pdata,8,len);
    2332           0 :                         data_len = 12 + len;
    2333           0 :                         if (max_data_bytes >= 16 && data_len > max_data_bytes) {
    2334             :                                 /* the client only requested a portion of the
    2335             :                                    file system name */
    2336           0 :                                 data_len = max_data_bytes;
    2337           0 :                                 status = STATUS_BUFFER_OVERFLOW;
    2338             :                         }
    2339           0 :                         *fixed_portion = 16;
    2340           0 :                         break;
    2341             : 
    2342           0 :                 case SMB_QUERY_FS_LABEL_INFO:
    2343             :                 case SMB_FS_LABEL_INFORMATION:
    2344           0 :                         status = srvstr_push(pdata, flags2, pdata+4, vname,
    2345             :                                           PTR_DIFF(end_data, pdata+4), 0, &len);
    2346           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2347           0 :                                 return status;
    2348             :                         }
    2349           0 :                         data_len = 4 + len;
    2350           0 :                         SIVAL(pdata,0,len);
    2351           0 :                         break;
    2352             : 
    2353           4 :                 case SMB_QUERY_FS_VOLUME_INFO:
    2354             :                 case SMB_FS_VOLUME_INFORMATION:
    2355           4 :                         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
    2356             :                                                     pdata, &st.st_ex_btime);
    2357             :                         /*
    2358             :                          * Add volume serial number - hash of a combination of
    2359             :                          * the called hostname and the service name.
    2360             :                          */
    2361           4 :                         serial = generate_volume_serial_number(lp_sub, snum);
    2362           4 :                         SIVAL(pdata,8,serial);
    2363             : 
    2364             :                         /* Max label len is 32 characters. */
    2365           4 :                         status = srvstr_push(pdata, flags2, pdata+18, vname,
    2366             :                                           PTR_DIFF(end_data, pdata+18),
    2367             :                                           STR_UNICODE, &len);
    2368           4 :                         if (!NT_STATUS_IS_OK(status)) {
    2369           0 :                                 return status;
    2370             :                         }
    2371           4 :                         SIVAL(pdata,12,len);
    2372           4 :                         data_len = 18+len;
    2373             : 
    2374           4 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
    2375             :                                  "namelen = %d, vol=%s serv=%s "
    2376             :                                  "serial=0x%04"PRIx32"\n",
    2377             :                                  (int)strlen(vname),vname,
    2378             :                                  lp_servicename(talloc_tos(), lp_sub, snum),
    2379             :                                  serial));
    2380           4 :                         if (max_data_bytes >= 24 && data_len > max_data_bytes) {
    2381             :                                 /* the client only requested a portion of the
    2382             :                                    volume label */
    2383           0 :                                 data_len = max_data_bytes;
    2384           0 :                                 status = STATUS_BUFFER_OVERFLOW;
    2385             :                         }
    2386           4 :                         *fixed_portion = 24;
    2387           4 :                         break;
    2388             : 
    2389         375 :                 case SMB_QUERY_FS_SIZE_INFO:
    2390             :                 case SMB_FS_SIZE_INFORMATION:
    2391             :                 {
    2392             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2393         375 :                         data_len = 24;
    2394         375 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2395             :                                                 &dfree, &dsize);
    2396         375 :                         if (df_ret == (uint64_t)-1) {
    2397           0 :                                 return map_nt_error_from_unix(errno);
    2398             :                         }
    2399         375 :                         block_size = lp_block_size(snum);
    2400         375 :                         if (bsize < block_size) {
    2401         375 :                                 uint64_t factor = block_size/bsize;
    2402         375 :                                 bsize = block_size;
    2403         375 :                                 dsize /= factor;
    2404         375 :                                 dfree /= factor;
    2405             :                         }
    2406         375 :                         if (bsize > block_size) {
    2407           0 :                                 uint64_t factor = bsize/block_size;
    2408           0 :                                 bsize = block_size;
    2409           0 :                                 dsize *= factor;
    2410           0 :                                 dfree *= factor;
    2411             :                         }
    2412         375 :                         sectors_per_unit = bsize/bytes_per_sector;
    2413         375 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    2414             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2415             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2416         375 :                         SBIG_UINT(pdata,0,dsize);
    2417         375 :                         SBIG_UINT(pdata,8,dfree);
    2418         375 :                         SIVAL(pdata,16,sectors_per_unit);
    2419         375 :                         SIVAL(pdata,20,bytes_per_sector);
    2420         375 :                         *fixed_portion = 24;
    2421         375 :                         break;
    2422             :                 }
    2423             : 
    2424           0 :                 case SMB_FS_FULL_SIZE_INFORMATION:
    2425             :                 {
    2426             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2427           0 :                         data_len = 32;
    2428           0 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2429             :                                                 &dfree, &dsize);
    2430           0 :                         if (df_ret == (uint64_t)-1) {
    2431           0 :                                 return map_nt_error_from_unix(errno);
    2432             :                         }
    2433           0 :                         block_size = lp_block_size(snum);
    2434           0 :                         if (bsize < block_size) {
    2435           0 :                                 uint64_t factor = block_size/bsize;
    2436           0 :                                 bsize = block_size;
    2437           0 :                                 dsize /= factor;
    2438           0 :                                 dfree /= factor;
    2439             :                         }
    2440           0 :                         if (bsize > block_size) {
    2441           0 :                                 uint64_t factor = bsize/block_size;
    2442           0 :                                 bsize = block_size;
    2443           0 :                                 dsize *= factor;
    2444           0 :                                 dfree *= factor;
    2445             :                         }
    2446           0 :                         sectors_per_unit = bsize/bytes_per_sector;
    2447           0 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    2448             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2449             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2450           0 :                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
    2451           0 :                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
    2452           0 :                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
    2453           0 :                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
    2454           0 :                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
    2455           0 :                         *fixed_portion = 32;
    2456           0 :                         break;
    2457             :                 }
    2458             : 
    2459           0 :                 case SMB_QUERY_FS_DEVICE_INFO:
    2460             :                 case SMB_FS_DEVICE_INFORMATION:
    2461             :                 {
    2462           0 :                         uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
    2463             : 
    2464           0 :                         if (!CAN_WRITE(conn)) {
    2465           0 :                                 characteristics |= FILE_READ_ONLY_DEVICE;
    2466             :                         }
    2467           0 :                         data_len = 8;
    2468           0 :                         SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
    2469           0 :                         SIVAL(pdata,4,characteristics);
    2470           0 :                         *fixed_portion = 8;
    2471           0 :                         break;
    2472             :                 }
    2473             : 
    2474             : #ifdef HAVE_SYS_QUOTAS
    2475           0 :                 case SMB_FS_QUOTA_INFORMATION:
    2476             :                 /*
    2477             :                  * what we have to send --metze:
    2478             :                  *
    2479             :                  * Unknown1:            24 NULL bytes
    2480             :                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
    2481             :                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
    2482             :                  * Quota Flags:         2 byte :
    2483             :                  * Unknown3:            6 NULL bytes
    2484             :                  *
    2485             :                  * 48 bytes total
    2486             :                  *
    2487             :                  * details for Quota Flags:
    2488             :                  *
    2489             :                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
    2490             :                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
    2491             :                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
    2492             :                  * 0x0001 Enable Quotas: enable quota for this fs
    2493             :                  *
    2494             :                  */
    2495             :                 {
    2496             :                         /* we need to fake up a fsp here,
    2497             :                          * because its not send in this call
    2498             :                          */
    2499             :                         files_struct fsp;
    2500             :                         SMB_NTQUOTA_STRUCT quotas;
    2501             : 
    2502           0 :                         ZERO_STRUCT(fsp);
    2503           0 :                         ZERO_STRUCT(quotas);
    2504             : 
    2505           0 :                         fsp.conn = conn;
    2506           0 :                         fsp.fnum = FNUM_FIELD_INVALID;
    2507             : 
    2508             :                         /* access check */
    2509           0 :                         if (get_current_uid(conn) != 0) {
    2510           0 :                                 DEBUG(0,("get_user_quota: access_denied "
    2511             :                                          "service [%s] user [%s]\n",
    2512             :                                          lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2513             :                                          conn->session_info->unix_info->unix_name));
    2514           0 :                                 return NT_STATUS_ACCESS_DENIED;
    2515             :                         }
    2516             : 
    2517           0 :                         status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
    2518             :                                                  NULL, &quotas);
    2519           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2520           0 :                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2521           0 :                                 return status;
    2522             :                         }
    2523             : 
    2524           0 :                         data_len = 48;
    2525             : 
    2526           0 :                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
    2527             :                                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2528             : 
    2529             :                         /* Unknown1 24 NULL bytes*/
    2530           0 :                         SBIG_UINT(pdata,0,(uint64_t)0);
    2531           0 :                         SBIG_UINT(pdata,8,(uint64_t)0);
    2532           0 :                         SBIG_UINT(pdata,16,(uint64_t)0);
    2533             : 
    2534             :                         /* Default Soft Quota 8 bytes */
    2535           0 :                         SBIG_UINT(pdata,24,quotas.softlim);
    2536             : 
    2537             :                         /* Default Hard Quota 8 bytes */
    2538           0 :                         SBIG_UINT(pdata,32,quotas.hardlim);
    2539             : 
    2540             :                         /* Quota flag 2 bytes */
    2541           0 :                         SSVAL(pdata,40,quotas.qflags);
    2542             : 
    2543             :                         /* Unknown3 6 NULL bytes */
    2544           0 :                         SSVAL(pdata,42,0);
    2545           0 :                         SIVAL(pdata,44,0);
    2546             : 
    2547           0 :                         break;
    2548             :                 }
    2549             : #endif /* HAVE_SYS_QUOTAS */
    2550           0 :                 case SMB_FS_OBJECTID_INFORMATION:
    2551             :                 {
    2552             :                         unsigned char objid[16];
    2553             :                         struct smb_extended_info extended_info;
    2554           0 :                         memcpy(pdata,create_volume_objectid(conn, objid),16);
    2555           0 :                         samba_extended_info_version (&extended_info);
    2556           0 :                         SIVAL(pdata,16,extended_info.samba_magic);
    2557           0 :                         SIVAL(pdata,20,extended_info.samba_version);
    2558           0 :                         SIVAL(pdata,24,extended_info.samba_subversion);
    2559           0 :                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
    2560           0 :                         memcpy(pdata+36,extended_info.samba_version_string,28);
    2561           0 :                         data_len = 64;
    2562           0 :                         break;
    2563             :                 }
    2564             : 
    2565           0 :                 case SMB_FS_SECTOR_SIZE_INFORMATION:
    2566             :                 {
    2567           0 :                         data_len = 28;
    2568             :                         /*
    2569             :                          * These values match a physical Windows Server 2012
    2570             :                          * share backed by NTFS atop spinning rust.
    2571             :                          */
    2572           0 :                         DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
    2573             :                         /* logical_bytes_per_sector */
    2574           0 :                         SIVAL(pdata, 0, bytes_per_sector);
    2575             :                         /* phys_bytes_per_sector_atomic */
    2576           0 :                         SIVAL(pdata, 4, bytes_per_sector);
    2577             :                         /* phys_bytes_per_sector_perf */
    2578           0 :                         SIVAL(pdata, 8, bytes_per_sector);
    2579             :                         /* fs_effective_phys_bytes_per_sector_atomic */
    2580           0 :                         SIVAL(pdata, 12, bytes_per_sector);
    2581             :                         /* flags */
    2582           0 :                         SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
    2583             :                                 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
    2584             :                         /* byte_off_sector_align */
    2585           0 :                         SIVAL(pdata, 20, 0);
    2586             :                         /* byte_off_partition_align */
    2587           0 :                         SIVAL(pdata, 24, 0);
    2588           0 :                         *fixed_portion = 28;
    2589           0 :                         break;
    2590             :                 }
    2591             : 
    2592             : 
    2593             : #if defined(WITH_SMB1SERVER)
    2594             :                 /*
    2595             :                  * Query the version and capabilities of the CIFS UNIX extensions
    2596             :                  * in use.
    2597             :                  */
    2598             : 
    2599           0 :                 case SMB_QUERY_CIFS_UNIX_INFO:
    2600             :                 {
    2601           0 :                         bool large_write = lp_min_receive_file_size() &&
    2602           0 :                                         !smb1_srv_is_signing_active(xconn);
    2603           0 :                         bool large_read = !smb1_srv_is_signing_active(xconn);
    2604           0 :                         int encrypt_caps = 0;
    2605             : 
    2606           0 :                         if (!lp_smb1_unix_extensions()) {
    2607           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2608             :                         }
    2609             : 
    2610           0 :                         switch (conn->encrypt_level) {
    2611           0 :                         case SMB_SIGNING_OFF:
    2612           0 :                                 encrypt_caps = 0;
    2613           0 :                                 break;
    2614           0 :                         case SMB_SIGNING_DESIRED:
    2615             :                         case SMB_SIGNING_IF_REQUIRED:
    2616             :                         case SMB_SIGNING_DEFAULT:
    2617           0 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
    2618           0 :                                 break;
    2619           0 :                         case SMB_SIGNING_REQUIRED:
    2620           0 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
    2621             :                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
    2622           0 :                                 large_write = false;
    2623           0 :                                 large_read = false;
    2624           0 :                                 break;
    2625             :                         }
    2626             : 
    2627           0 :                         data_len = 12;
    2628           0 :                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
    2629           0 :                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
    2630             : 
    2631             :                         /* We have POSIX ACLs, pathname, encryption,
    2632             :                          * large read/write, and locking capability. */
    2633             : 
    2634           0 :                         SBIG_UINT(pdata,4,((uint64_t)(
    2635             :                                         CIFS_UNIX_POSIX_ACLS_CAP|
    2636             :                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
    2637             :                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
    2638             :                                         CIFS_UNIX_EXTATTR_CAP|
    2639             :                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
    2640             :                                         encrypt_caps|
    2641             :                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
    2642             :                                         (large_write ?
    2643             :                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
    2644           0 :                         break;
    2645             :                 }
    2646             : #endif
    2647             : 
    2648           0 :                 case SMB_QUERY_POSIX_FS_INFO:
    2649             :                 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
    2650             :                 {
    2651             :                         int rc;
    2652             :                         struct vfs_statvfs_struct svfs;
    2653             : 
    2654           0 :                         if (!fsinfo_unix_valid_level(conn, info_level)) {
    2655           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2656             :                         }
    2657             : 
    2658           0 :                         rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
    2659             : 
    2660           0 :                         if (!rc) {
    2661           0 :                                 data_len = 56;
    2662           0 :                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
    2663           0 :                                 SIVAL(pdata,4,svfs.BlockSize);
    2664           0 :                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
    2665           0 :                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
    2666           0 :                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
    2667           0 :                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
    2668           0 :                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
    2669           0 :                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
    2670           0 :                                 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
    2671             : #ifdef EOPNOTSUPP
    2672           0 :                         } else if (rc == EOPNOTSUPP) {
    2673           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2674             : #endif /* EOPNOTSUPP */
    2675             :                         } else {
    2676           0 :                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2677           0 :                                 return NT_STATUS_DOS(ERRSRV, ERRerror);
    2678             :                         }
    2679           0 :                         break;
    2680             :                 }
    2681             : 
    2682           8 :                 case SMB_QUERY_POSIX_WHOAMI:
    2683             :                 {
    2684           8 :                         uint32_t flags = 0;
    2685             :                         uint32_t sid_bytes;
    2686             :                         uint32_t i;
    2687             : 
    2688           8 :                         if (!lp_smb1_unix_extensions()) {
    2689           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2690             :                         }
    2691             : 
    2692           8 :                         if (max_data_bytes < 40) {
    2693           0 :                                 return NT_STATUS_BUFFER_TOO_SMALL;
    2694             :                         }
    2695             : 
    2696           8 :                         if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
    2697           0 :                                 flags |= SMB_WHOAMI_GUEST;
    2698             :                         }
    2699             : 
    2700             :                         /* NOTE: 8 bytes for UID/GID, irrespective of native
    2701             :                          * platform size. This matches
    2702             :                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
    2703             :                          */
    2704           8 :                         data_len = 4 /* flags */
    2705             :                             + 4 /* flag mask */
    2706             :                             + 8 /* uid */
    2707             :                             + 8 /* gid */
    2708             :                             + 4 /* ngroups */
    2709             :                             + 4 /* num_sids */
    2710             :                             + 4 /* SID bytes */
    2711             :                             + 4 /* pad/reserved */
    2712           8 :                             + (conn->session_info->unix_token->ngroups * 8)
    2713             :                                 /* groups list */
    2714           8 :                             + (conn->session_info->security_token->num_sids *
    2715             :                                     SID_MAX_SIZE)
    2716             :                                 /* SID list */;
    2717             : 
    2718           8 :                         SIVAL(pdata, 0, flags);
    2719           8 :                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
    2720           8 :                         SBIG_UINT(pdata, 8,
    2721             :                                   (uint64_t)conn->session_info->unix_token->uid);
    2722           8 :                         SBIG_UINT(pdata, 16,
    2723             :                                   (uint64_t)conn->session_info->unix_token->gid);
    2724             : 
    2725             : 
    2726           8 :                         if (data_len >= max_data_bytes) {
    2727             :                                 /* Potential overflow, skip the GIDs and SIDs. */
    2728             : 
    2729           0 :                                 SIVAL(pdata, 24, 0); /* num_groups */
    2730           0 :                                 SIVAL(pdata, 28, 0); /* num_sids */
    2731           0 :                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
    2732           0 :                                 SIVAL(pdata, 36, 0); /* reserved */
    2733             : 
    2734           0 :                                 data_len = 40;
    2735           0 :                                 break;
    2736             :                         }
    2737             : 
    2738           8 :                         SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
    2739           8 :                         SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
    2740             : 
    2741             :                         /* We walk the SID list twice, but this call is fairly
    2742             :                          * infrequent, and I don't expect that it's performance
    2743             :                          * sensitive -- jpeach
    2744             :                          */
    2745           8 :                         for (i = 0, sid_bytes = 0;
    2746          98 :                              i < conn->session_info->security_token->num_sids; ++i) {
    2747          90 :                                 sid_bytes += ndr_size_dom_sid(
    2748          90 :                                         &conn->session_info->security_token->sids[i],
    2749             :                                         0);
    2750             :                         }
    2751             : 
    2752             :                         /* SID list byte count */
    2753           8 :                         SIVAL(pdata, 32, sid_bytes);
    2754             : 
    2755             :                         /* 4 bytes pad/reserved - must be zero */
    2756           8 :                         SIVAL(pdata, 36, 0);
    2757           8 :                         data_len = 40;
    2758             : 
    2759             :                         /* GID list */
    2760          44 :                         for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
    2761          36 :                                 SBIG_UINT(pdata, data_len,
    2762             :                                           (uint64_t)conn->session_info->unix_token->groups[i]);
    2763          36 :                                 data_len += 8;
    2764             :                         }
    2765             : 
    2766             :                         /* SID list */
    2767           8 :                         for (i = 0;
    2768          98 :                             i < conn->session_info->security_token->num_sids; ++i) {
    2769         180 :                                 int sid_len = ndr_size_dom_sid(
    2770          90 :                                         &conn->session_info->security_token->sids[i],
    2771             :                                         0);
    2772             : 
    2773          90 :                                 sid_linearize((uint8_t *)(pdata + data_len),
    2774             :                                               sid_len,
    2775          90 :                                     &conn->session_info->security_token->sids[i]);
    2776          90 :                                 data_len += sid_len;
    2777             :                         }
    2778             : 
    2779           8 :                         break;
    2780             :                 }
    2781             : 
    2782           0 :                 case SMB_MAC_QUERY_FS_INFO:
    2783             :                         /*
    2784             :                          * Thursby MAC extension... ONLY on NTFS filesystems
    2785             :                          * once we do streams then we don't need this
    2786             :                          */
    2787           0 :                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
    2788           0 :                                 data_len = 88;
    2789           0 :                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
    2790           0 :                                 break;
    2791             :                         }
    2792             : 
    2793             :                         FALL_THROUGH;
    2794             :                 default:
    2795           0 :                         return NT_STATUS_INVALID_LEVEL;
    2796             :         }
    2797             : 
    2798         387 :         *ret_data_len = data_len;
    2799         387 :         return status;
    2800             : }
    2801             : 
    2802           0 : NTSTATUS smb_set_fsquota(connection_struct *conn,
    2803             :                          struct smb_request *req,
    2804             :                          files_struct *fsp,
    2805             :                          const DATA_BLOB *qdata)
    2806             : {
    2807             :         const struct loadparm_substitution *lp_sub =
    2808           0 :                 loadparm_s3_global_substitution();
    2809             :         NTSTATUS status;
    2810             :         SMB_NTQUOTA_STRUCT quotas;
    2811             : 
    2812           0 :         ZERO_STRUCT(quotas);
    2813             : 
    2814             :         /* access check */
    2815           0 :         if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
    2816           0 :                 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
    2817             :                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2818             :                           conn->session_info->unix_info->unix_name));
    2819           0 :                 return NT_STATUS_ACCESS_DENIED;
    2820             :         }
    2821             : 
    2822           0 :         if (!check_fsp_ntquota_handle(conn, req,
    2823             :                                       fsp)) {
    2824           0 :                 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
    2825           0 :                 return NT_STATUS_INVALID_HANDLE;
    2826             :         }
    2827             : 
    2828             :         /* note: normally there're 48 bytes,
    2829             :          * but we didn't use the last 6 bytes for now
    2830             :          * --metze
    2831             :          */
    2832           0 :         if (qdata->length < 42) {
    2833           0 :                 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
    2834             :                         (unsigned int)qdata->length));
    2835           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2836             :         }
    2837             : 
    2838             :         /* unknown_1 24 NULL bytes in pdata*/
    2839             : 
    2840             :         /* the soft quotas 8 bytes (uint64_t)*/
    2841           0 :         quotas.softlim = BVAL(qdata->data,24);
    2842             : 
    2843             :         /* the hard quotas 8 bytes (uint64_t)*/
    2844           0 :         quotas.hardlim = BVAL(qdata->data,32);
    2845             : 
    2846             :         /* quota_flags 2 bytes **/
    2847           0 :         quotas.qflags = SVAL(qdata->data,40);
    2848             : 
    2849             :         /* unknown_2 6 NULL bytes follow*/
    2850             : 
    2851             :         /* now set the quotas */
    2852           0 :         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
    2853           0 :                 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
    2854             :                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2855           0 :                 status =  map_nt_error_from_unix(errno);
    2856             :         } else {
    2857           0 :                 status = NT_STATUS_OK;
    2858             :         }
    2859           0 :         return status;
    2860             : }
    2861             : 
    2862           0 : NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
    2863             :                                 struct smb_request *req,
    2864             :                                 TALLOC_CTX *mem_ctx,
    2865             :                                 uint16_t info_level,
    2866             :                                 files_struct *fsp,
    2867             :                                 const DATA_BLOB *pdata)
    2868             : {
    2869           0 :         switch (info_level) {
    2870           0 :                 case SMB_FS_QUOTA_INFORMATION:
    2871             :                 {
    2872           0 :                         return smb_set_fsquota(conn,
    2873             :                                                 req,
    2874             :                                                 fsp,
    2875             :                                                 pdata);
    2876             :                 }
    2877             : 
    2878           0 :                 default:
    2879           0 :                         break;
    2880             :         }
    2881           0 :         return NT_STATUS_INVALID_LEVEL;
    2882             : }
    2883             : 
    2884             : /****************************************************************************
    2885             :  Store the FILE_UNIX_BASIC info.
    2886             : ****************************************************************************/
    2887             : 
    2888           0 : char *store_file_unix_basic(connection_struct *conn,
    2889             :                             char *pdata,
    2890             :                             files_struct *fsp,
    2891             :                             const SMB_STRUCT_STAT *psbuf)
    2892             : {
    2893             :         dev_t devno;
    2894             : 
    2895           0 :         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
    2896           0 :         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
    2897             : 
    2898           0 :         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
    2899           0 :         pdata += 8;
    2900             : 
    2901           0 :         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
    2902           0 :         pdata += 8;
    2903             : 
    2904           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime);       /* Change Time 64 Bit */
    2905           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime);     /* Last access time 64 Bit */
    2906           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
    2907           0 :         pdata += 24;
    2908             : 
    2909           0 :         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
    2910           0 :         SIVAL(pdata,4,0);
    2911           0 :         pdata += 8;
    2912             : 
    2913           0 :         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
    2914           0 :         SIVAL(pdata,4,0);
    2915           0 :         pdata += 8;
    2916             : 
    2917           0 :         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
    2918           0 :         pdata += 4;
    2919             : 
    2920           0 :         if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
    2921           0 :                 devno = psbuf->st_ex_rdev;
    2922             :         } else {
    2923           0 :                 devno = psbuf->st_ex_dev;
    2924             :         }
    2925             : 
    2926           0 :         SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
    2927           0 :         SIVAL(pdata,4,0);
    2928           0 :         pdata += 8;
    2929             : 
    2930           0 :         SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
    2931           0 :         SIVAL(pdata,4,0);
    2932           0 :         pdata += 8;
    2933             : 
    2934           0 :         SINO_T_VAL(pdata, 0, psbuf->st_ex_ino);   /* inode number */
    2935           0 :         pdata += 8;
    2936             : 
    2937           0 :         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
    2938           0 :         SIVAL(pdata,4,0);
    2939           0 :         pdata += 8;
    2940             : 
    2941           0 :         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
    2942           0 :         SIVAL(pdata,4,0);
    2943           0 :         pdata += 8;
    2944             : 
    2945           0 :         return pdata;
    2946             : }
    2947             : 
    2948             : /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
    2949             :  * the chflags(2) (or equivalent) flags.
    2950             :  *
    2951             :  * XXX: this really should be behind the VFS interface. To do this, we would
    2952             :  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
    2953             :  * Each VFS module could then implement its own mapping as appropriate for the
    2954             :  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
    2955             :  */
    2956             : static const struct {unsigned stat_fflag; unsigned smb_fflag;}
    2957             :         info2_flags_map[] =
    2958             : {
    2959             : #ifdef UF_NODUMP
    2960             :     { UF_NODUMP, EXT_DO_NOT_BACKUP },
    2961             : #endif
    2962             : 
    2963             : #ifdef UF_IMMUTABLE
    2964             :     { UF_IMMUTABLE, EXT_IMMUTABLE },
    2965             : #endif
    2966             : 
    2967             : #ifdef UF_APPEND
    2968             :     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
    2969             : #endif
    2970             : 
    2971             : #ifdef UF_HIDDEN
    2972             :     { UF_HIDDEN, EXT_HIDDEN },
    2973             : #endif
    2974             : 
    2975             :     /* Do not remove. We need to guarantee that this array has at least one
    2976             :      * entry to build on HP-UX.
    2977             :      */
    2978             :     { 0, 0 }
    2979             : 
    2980             : };
    2981             : 
    2982           0 : static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
    2983             :                                 uint32_t *smb_fflags, uint32_t *smb_fmask)
    2984             : {
    2985             :         size_t i;
    2986             : 
    2987           0 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    2988           0 :             *smb_fmask |= info2_flags_map[i].smb_fflag;
    2989           0 :             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
    2990           0 :                     *smb_fflags |= info2_flags_map[i].smb_fflag;
    2991             :             }
    2992             :         }
    2993           0 : }
    2994             : 
    2995           0 : bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
    2996             :                              const uint32_t smb_fflags,
    2997             :                              const uint32_t smb_fmask,
    2998             :                              int *stat_fflags)
    2999             : {
    3000           0 :         uint32_t max_fmask = 0;
    3001             :         size_t i;
    3002             : 
    3003           0 :         *stat_fflags = psbuf->st_ex_flags;
    3004             : 
    3005             :         /* For each flags requested in smb_fmask, check the state of the
    3006             :          * corresponding flag in smb_fflags and set or clear the matching
    3007             :          * stat flag.
    3008             :          */
    3009             : 
    3010           0 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    3011           0 :             max_fmask |= info2_flags_map[i].smb_fflag;
    3012           0 :             if (smb_fmask & info2_flags_map[i].smb_fflag) {
    3013           0 :                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
    3014           0 :                             *stat_fflags |= info2_flags_map[i].stat_fflag;
    3015             :                     } else {
    3016           0 :                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
    3017             :                     }
    3018             :             }
    3019             :         }
    3020             : 
    3021             :         /* If smb_fmask is asking to set any bits that are not supported by
    3022             :          * our flag mappings, we should fail.
    3023             :          */
    3024           0 :         if ((smb_fmask & max_fmask) != smb_fmask) {
    3025           0 :                 return False;
    3026             :         }
    3027             : 
    3028           0 :         return True;
    3029             : }
    3030             : 
    3031             : 
    3032             : /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
    3033             :  * of file flags and birth (create) time.
    3034             :  */
    3035           0 : char *store_file_unix_basic_info2(connection_struct *conn,
    3036             :                                   char *pdata,
    3037             :                                   files_struct *fsp,
    3038             :                                   const SMB_STRUCT_STAT *psbuf)
    3039             : {
    3040           0 :         uint32_t file_flags = 0;
    3041           0 :         uint32_t flags_mask = 0;
    3042             : 
    3043           0 :         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
    3044             : 
    3045             :         /* Create (birth) time 64 bit */
    3046           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
    3047           0 :         pdata += 8;
    3048             : 
    3049           0 :         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
    3050           0 :         SIVAL(pdata, 0, file_flags); /* flags */
    3051           0 :         SIVAL(pdata, 4, flags_mask); /* mask */
    3052           0 :         pdata += 8;
    3053             : 
    3054           0 :         return pdata;
    3055             : }
    3056             : 
    3057          44 : static NTSTATUS marshall_stream_info(unsigned int num_streams,
    3058             :                                      const struct stream_struct *streams,
    3059             :                                      char *data,
    3060             :                                      unsigned int max_data_bytes,
    3061             :                                      unsigned int *data_size)
    3062             : {
    3063             :         unsigned int i;
    3064          44 :         unsigned int ofs = 0;
    3065             : 
    3066          44 :         if (max_data_bytes < 32) {
    3067           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
    3068             :         }
    3069             : 
    3070          80 :         for (i = 0; i < num_streams; i++) {
    3071             :                 unsigned int next_offset;
    3072             :                 size_t namelen;
    3073             :                 smb_ucs2_t *namebuf;
    3074             : 
    3075          36 :                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
    3076          36 :                                       streams[i].name, &namelen) ||
    3077          36 :                     namelen <= 2)
    3078             :                 {
    3079           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3080             :                 }
    3081             : 
    3082             :                 /*
    3083             :                  * name_buf is now null-terminated, we need to marshall as not
    3084             :                  * terminated
    3085             :                  */
    3086             : 
    3087          36 :                 namelen -= 2;
    3088             : 
    3089             :                 /*
    3090             :                  * We cannot overflow ...
    3091             :                  */
    3092          36 :                 if ((ofs + 24 + namelen) > max_data_bytes) {
    3093           0 :                         DEBUG(10, ("refusing to overflow reply at stream %u\n",
    3094             :                                 i));
    3095           0 :                         TALLOC_FREE(namebuf);
    3096           0 :                         return STATUS_BUFFER_OVERFLOW;
    3097             :                 }
    3098             : 
    3099          36 :                 SIVAL(data, ofs+4, namelen);
    3100          36 :                 SOFF_T(data, ofs+8, streams[i].size);
    3101          36 :                 SOFF_T(data, ofs+16, streams[i].alloc_size);
    3102          36 :                 memcpy(data+ofs+24, namebuf, namelen);
    3103          36 :                 TALLOC_FREE(namebuf);
    3104             : 
    3105          36 :                 next_offset = ofs + 24 + namelen;
    3106             : 
    3107          36 :                 if (i == num_streams-1) {
    3108          36 :                         SIVAL(data, ofs, 0);
    3109             :                 }
    3110             :                 else {
    3111           0 :                         unsigned int align = ndr_align_size(next_offset, 8);
    3112             : 
    3113           0 :                         if ((next_offset + align) > max_data_bytes) {
    3114           0 :                                 DEBUG(10, ("refusing to overflow align "
    3115             :                                         "reply at stream %u\n",
    3116             :                                         i));
    3117           0 :                                 TALLOC_FREE(namebuf);
    3118           0 :                                 return STATUS_BUFFER_OVERFLOW;
    3119             :                         }
    3120             : 
    3121           0 :                         memset(data+next_offset, 0, align);
    3122           0 :                         next_offset += align;
    3123             : 
    3124           0 :                         SIVAL(data, ofs, next_offset - ofs);
    3125           0 :                         ofs = next_offset;
    3126             :                 }
    3127             : 
    3128          36 :                 ofs = next_offset;
    3129             :         }
    3130             : 
    3131          44 :         DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
    3132             : 
    3133          44 :         *data_size = ofs;
    3134             : 
    3135          44 :         return NT_STATUS_OK;
    3136             : }
    3137             : 
    3138         937 : NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
    3139             :                                TALLOC_CTX *mem_ctx,
    3140             :                                struct smb_request *req,
    3141             :                                uint16_t info_level,
    3142             :                                files_struct *fsp,
    3143             :                                struct smb_filename *smb_fname,
    3144             :                                bool delete_pending,
    3145             :                                struct timespec write_time_ts,
    3146             :                                struct ea_list *ea_list,
    3147             :                                uint16_t flags2,
    3148             :                                unsigned int max_data_bytes,
    3149             :                                size_t *fixed_portion,
    3150             :                                char **ppdata,
    3151             :                                unsigned int *pdata_size)
    3152             : {
    3153         937 :         char *pdata = *ppdata;
    3154             :         char *dstart, *dend;
    3155             :         unsigned int data_size;
    3156             :         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
    3157             :         time_t create_time, mtime, atime, c_time;
    3158         937 :         SMB_STRUCT_STAT *psbuf = NULL;
    3159         937 :         SMB_STRUCT_STAT *base_sp = NULL;
    3160             :         char *p;
    3161             :         char *base_name;
    3162             :         char *dos_fname;
    3163             :         int mode;
    3164             :         int nlink;
    3165             :         NTSTATUS status;
    3166         937 :         uint64_t file_size = 0;
    3167         937 :         uint64_t pos = 0;
    3168         937 :         uint64_t allocation_size = 0;
    3169         937 :         uint64_t file_id = 0;
    3170         937 :         uint32_t access_mask = 0;
    3171         937 :         size_t len = 0;
    3172             : 
    3173         937 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    3174           0 :                 bool ok = false;
    3175             : 
    3176           0 :                 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
    3177           0 :                         DBG_DEBUG("SMB1 unix extensions activated\n");
    3178           0 :                         ok = true;
    3179             :                 }
    3180             : 
    3181           0 :                 if (lp_smb3_unix_extensions() &&
    3182           0 :                     (fsp != NULL) &&
    3183           0 :                     (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
    3184           0 :                         DBG_DEBUG("SMB2 posix open\n");
    3185           0 :                         ok = true;
    3186             :                 }
    3187             : 
    3188           0 :                 if (!ok) {
    3189           0 :                         return NT_STATUS_INVALID_LEVEL;
    3190             :                 }
    3191             :         }
    3192             : 
    3193         937 :         DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
    3194             :                  smb_fname_str_dbg(smb_fname),
    3195             :                  fsp_fnum_dbg(fsp),
    3196             :                  info_level, max_data_bytes));
    3197             : 
    3198             :         /*
    3199             :          * In case of querying a symlink in POSIX context,
    3200             :          * fsp will be NULL. fdos_mode() deals with it.
    3201             :          */
    3202         937 :         if (fsp != NULL) {
    3203         937 :                 smb_fname = fsp->fsp_name;
    3204             :         }
    3205         937 :         mode = fdos_mode(fsp);
    3206         937 :         psbuf = &smb_fname->st;
    3207             : 
    3208         937 :         if (fsp != NULL) {
    3209         937 :                 base_sp = fsp->base_fsp ?
    3210         937 :                         &fsp->base_fsp->fsp_name->st :
    3211         913 :                         &fsp->fsp_name->st;
    3212             :         } else {
    3213           0 :                 base_sp = &smb_fname->st;
    3214             :         }
    3215             : 
    3216         937 :         nlink = psbuf->st_ex_nlink;
    3217             : 
    3218         937 :         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
    3219          83 :                 nlink = 1;
    3220             :         }
    3221             : 
    3222         937 :         if ((nlink > 0) && delete_pending) {
    3223           0 :                 nlink -= 1;
    3224             :         }
    3225             : 
    3226         937 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    3227           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3228             :         }
    3229             : 
    3230         937 :         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
    3231         937 :         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
    3232         937 :         if (*ppdata == NULL) {
    3233           0 :                 return NT_STATUS_NO_MEMORY;
    3234             :         }
    3235         937 :         pdata = *ppdata;
    3236         937 :         dstart = pdata;
    3237         937 :         dend = dstart + data_size - 1;
    3238             : 
    3239         937 :         if (!is_omit_timespec(&write_time_ts) &&
    3240         854 :             !INFO_LEVEL_IS_UNIX(info_level))
    3241             :         {
    3242         854 :                 update_stat_ex_mtime(psbuf, write_time_ts);
    3243             :         }
    3244             : 
    3245         937 :         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
    3246         937 :         mtime_ts = psbuf->st_ex_mtime;
    3247         937 :         atime_ts = psbuf->st_ex_atime;
    3248         937 :         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
    3249             : 
    3250         937 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    3251           0 :                 dos_filetime_timespec(&create_time_ts);
    3252           0 :                 dos_filetime_timespec(&mtime_ts);
    3253           0 :                 dos_filetime_timespec(&atime_ts);
    3254           0 :                 dos_filetime_timespec(&ctime_ts);
    3255             :         }
    3256             : 
    3257         937 :         create_time = convert_timespec_to_time_t(create_time_ts);
    3258         937 :         mtime = convert_timespec_to_time_t(mtime_ts);
    3259         937 :         atime = convert_timespec_to_time_t(atime_ts);
    3260         937 :         c_time = convert_timespec_to_time_t(ctime_ts);
    3261             : 
    3262         937 :         p = strrchr_m(smb_fname->base_name,'/');
    3263         937 :         if (!p)
    3264         527 :                 base_name = smb_fname->base_name;
    3265             :         else
    3266         410 :                 base_name = p+1;
    3267             : 
    3268             :         /* NT expects the name to be in an exact form of the *full*
    3269             :            filename. See the trans2 torture test */
    3270         937 :         if (ISDOT(base_name)) {
    3271          40 :                 dos_fname = talloc_strdup(mem_ctx, "\\");
    3272          40 :                 if (!dos_fname) {
    3273           0 :                         return NT_STATUS_NO_MEMORY;
    3274             :                 }
    3275             :         } else {
    3276         897 :                 dos_fname = talloc_asprintf(mem_ctx,
    3277             :                                 "\\%s",
    3278             :                                 smb_fname->base_name);
    3279         897 :                 if (!dos_fname) {
    3280           0 :                         return NT_STATUS_NO_MEMORY;
    3281             :                 }
    3282         897 :                 if (is_named_stream(smb_fname)) {
    3283          24 :                         dos_fname = talloc_asprintf(dos_fname, "%s",
    3284             :                                                     smb_fname->stream_name);
    3285          24 :                         if (!dos_fname) {
    3286           0 :                                 return NT_STATUS_NO_MEMORY;
    3287             :                         }
    3288             :                 }
    3289             : 
    3290         897 :                 string_replace(dos_fname, '/', '\\');
    3291             :         }
    3292             : 
    3293         937 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
    3294             : 
    3295         937 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    3296             :                 /* Do we have this path open ? */
    3297             :                 files_struct *fsp1;
    3298           0 :                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
    3299           0 :                 fsp1 = file_find_di_first(conn->sconn, fileid, true);
    3300           0 :                 if (fsp1 && fsp1->initial_allocation_size) {
    3301           0 :                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
    3302             :                 }
    3303             :         }
    3304             : 
    3305         937 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    3306         854 :                 file_size = get_file_size_stat(psbuf);
    3307             :         }
    3308             : 
    3309         937 :         if (fsp) {
    3310         937 :                 pos = fh_get_position_information(fsp->fh);
    3311             :         }
    3312             : 
    3313         937 :         if (fsp) {
    3314         937 :                 access_mask = fsp->access_mask;
    3315             :         } else {
    3316             :                 /* GENERIC_EXECUTE mapping from Windows */
    3317           0 :                 access_mask = 0x12019F;
    3318             :         }
    3319             : 
    3320             :         /* This should be an index number - looks like
    3321             :            dev/ino to me :-)
    3322             : 
    3323             :            I think this causes us to fail the IFSKIT
    3324             :            BasicFileInformationTest. -tpot */
    3325         937 :         file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
    3326             : 
    3327         937 :         *fixed_portion = 0;
    3328             : 
    3329         937 :         switch (info_level) {
    3330           0 :                 case SMB_INFO_STANDARD:
    3331           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
    3332           0 :                         data_size = 22;
    3333           0 :                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
    3334           0 :                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
    3335           0 :                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
    3336           0 :                         SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
    3337           0 :                         SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
    3338           0 :                         SSVAL(pdata,l1_attrFile,mode);
    3339           0 :                         break;
    3340             : 
    3341           0 :                 case SMB_INFO_QUERY_EA_SIZE:
    3342             :                 {
    3343             :                         unsigned int ea_size =
    3344           0 :                             estimate_ea_size(smb_fname->fsp);
    3345           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
    3346           0 :                         data_size = 26;
    3347           0 :                         srv_put_dos_date2(pdata,0,create_time);
    3348           0 :                         srv_put_dos_date2(pdata,4,atime);
    3349           0 :                         srv_put_dos_date2(pdata,8,mtime); /* write time */
    3350           0 :                         SIVAL(pdata,12,(uint32_t)file_size);
    3351           0 :                         SIVAL(pdata,16,(uint32_t)allocation_size);
    3352           0 :                         SSVAL(pdata,20,mode);
    3353           0 :                         SIVAL(pdata,22,ea_size);
    3354           0 :                         break;
    3355             :                 }
    3356             : 
    3357           0 :                 case SMB_INFO_IS_NAME_VALID:
    3358           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
    3359           0 :                         if (fsp) {
    3360             :                                 /* os/2 needs this ? really ?*/
    3361           0 :                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
    3362             :                         }
    3363             :                         /* This is only reached for qpathinfo */
    3364           0 :                         data_size = 0;
    3365           0 :                         break;
    3366             : 
    3367           0 :                 case SMB_INFO_QUERY_EAS_FROM_LIST:
    3368             :                 {
    3369           0 :                         size_t total_ea_len = 0;
    3370           0 :                         struct ea_list *ea_file_list = NULL;
    3371           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
    3372             : 
    3373             :                         status =
    3374           0 :                             get_ea_list_from_fsp(mem_ctx,
    3375           0 :                                                   smb_fname->fsp,
    3376             :                                                   &total_ea_len, &ea_file_list);
    3377           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3378           0 :                                 return status;
    3379             :                         }
    3380             : 
    3381           0 :                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
    3382             : 
    3383           0 :                         if (!ea_list || (total_ea_len > data_size)) {
    3384           0 :                                 data_size = 4;
    3385           0 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    3386           0 :                                 break;
    3387             :                         }
    3388             : 
    3389           0 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    3390           0 :                         break;
    3391             :                 }
    3392             : 
    3393           0 :                 case SMB_INFO_QUERY_ALL_EAS:
    3394             :                 {
    3395             :                         /* We have data_size bytes to put EA's into. */
    3396           0 :                         size_t total_ea_len = 0;
    3397           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
    3398             : 
    3399           0 :                         status = get_ea_list_from_fsp(mem_ctx,
    3400           0 :                                                         smb_fname->fsp,
    3401             :                                                         &total_ea_len, &ea_list);
    3402           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3403           0 :                                 return status;
    3404             :                         }
    3405             : 
    3406           0 :                         if (!ea_list || (total_ea_len > data_size)) {
    3407           0 :                                 data_size = 4;
    3408           0 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    3409           0 :                                 break;
    3410             :                         }
    3411             : 
    3412           0 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    3413           0 :                         break;
    3414             :                 }
    3415             : 
    3416           0 :                 case SMB2_FILE_FULL_EA_INFORMATION:
    3417             :                 {
    3418             :                         /* We have data_size bytes to put EA's into. */
    3419           0 :                         size_t total_ea_len = 0;
    3420           0 :                         struct ea_list *ea_file_list = NULL;
    3421             : 
    3422           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
    3423             : 
    3424             :                         /*TODO: add filtering and index handling */
    3425             : 
    3426             :                         status  =
    3427           0 :                                 get_ea_list_from_fsp(mem_ctx,
    3428           0 :                                                   smb_fname->fsp,
    3429             :                                                   &total_ea_len, &ea_file_list);
    3430           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3431           0 :                                 return status;
    3432             :                         }
    3433           0 :                         if (!ea_file_list) {
    3434           0 :                                 return NT_STATUS_NO_EAS_ON_FILE;
    3435             :                         }
    3436             : 
    3437           0 :                         status = fill_ea_chained_buffer(mem_ctx,
    3438             :                                                         pdata,
    3439             :                                                         data_size,
    3440             :                                                         &data_size,
    3441             :                                                         conn, ea_file_list);
    3442           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3443           0 :                                 return status;
    3444             :                         }
    3445           0 :                         break;
    3446             :                 }
    3447             : 
    3448           0 :                 case SMB_FILE_BASIC_INFORMATION:
    3449             :                 case SMB_QUERY_FILE_BASIC_INFO:
    3450             : 
    3451           0 :                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
    3452           0 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
    3453           0 :                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
    3454             :                         } else {
    3455           0 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
    3456           0 :                                 data_size = 40;
    3457           0 :                                 SIVAL(pdata,36,0);
    3458             :                         }
    3459           0 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3460           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3461           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3462           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3463           0 :                         SIVAL(pdata,32,mode);
    3464             : 
    3465           0 :                         DEBUG(5,("SMB_QFBI - "));
    3466           0 :                         DEBUG(5,("create: %s ", ctime(&create_time)));
    3467           0 :                         DEBUG(5,("access: %s ", ctime(&atime)));
    3468           0 :                         DEBUG(5,("write: %s ", ctime(&mtime)));
    3469           0 :                         DEBUG(5,("change: %s ", ctime(&c_time)));
    3470           0 :                         DEBUG(5,("mode: %x\n", mode));
    3471           0 :                         *fixed_portion = data_size;
    3472           0 :                         break;
    3473             : 
    3474           0 :                 case SMB_FILE_STANDARD_INFORMATION:
    3475             :                 case SMB_QUERY_FILE_STANDARD_INFO:
    3476             : 
    3477           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
    3478           0 :                         data_size = 24;
    3479           0 :                         SOFF_T(pdata,0,allocation_size);
    3480           0 :                         SOFF_T(pdata,8,file_size);
    3481           0 :                         SIVAL(pdata,16,nlink);
    3482           0 :                         SCVAL(pdata,20,delete_pending?1:0);
    3483           0 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3484           0 :                         SSVAL(pdata,22,0); /* Padding. */
    3485           0 :                         *fixed_portion = 24;
    3486           0 :                         break;
    3487             : 
    3488           0 :                 case SMB_FILE_EA_INFORMATION:
    3489             :                 case SMB_QUERY_FILE_EA_INFO:
    3490             :                 {
    3491             :                         unsigned int ea_size =
    3492           0 :                             estimate_ea_size(smb_fname->fsp);
    3493           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
    3494           0 :                         data_size = 4;
    3495           0 :                         *fixed_portion = 4;
    3496           0 :                         SIVAL(pdata,0,ea_size);
    3497           0 :                         break;
    3498             :                 }
    3499             : 
    3500             :                 /* Get the 8.3 name - used if NT SMB was negotiated. */
    3501          52 :                 case SMB_QUERY_FILE_ALT_NAME_INFO:
    3502             :                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
    3503             :                 {
    3504             :                         char mangled_name[13];
    3505          52 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
    3506          52 :                         if (!name_to_8_3(base_name,mangled_name,
    3507          52 :                                                 True,conn->params)) {
    3508           0 :                                 return NT_STATUS_NO_MEMORY;
    3509             :                         }
    3510          52 :                         status = srvstr_push(dstart, flags2,
    3511             :                                           pdata+4, mangled_name,
    3512             :                                           PTR_DIFF(dend, pdata+4),
    3513             :                                           STR_UNICODE, &len);
    3514          52 :                         if (!NT_STATUS_IS_OK(status)) {
    3515           0 :                                 return status;
    3516             :                         }
    3517          52 :                         data_size = 4 + len;
    3518          52 :                         SIVAL(pdata,0,len);
    3519          52 :                         *fixed_portion = 8;
    3520          52 :                         break;
    3521             :                 }
    3522             : 
    3523           0 :                 case SMB_QUERY_FILE_NAME_INFO:
    3524             :                 {
    3525             :                         /*
    3526             :                           this must be *exactly* right for ACLs on mapped drives to work
    3527             :                          */
    3528           0 :                         status = srvstr_push(dstart, flags2,
    3529             :                                           pdata+4, dos_fname,
    3530             :                                           PTR_DIFF(dend, pdata+4),
    3531             :                                           STR_UNICODE, &len);
    3532           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3533           0 :                                 return status;
    3534             :                         }
    3535           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
    3536           0 :                         data_size = 4 + len;
    3537           0 :                         SIVAL(pdata,0,len);
    3538           0 :                         break;
    3539             :                 }
    3540             : 
    3541           0 :                 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
    3542             :                 {
    3543           0 :                         char *nfname = NULL;
    3544             : 
    3545           0 :                         if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
    3546           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3547             :                         }
    3548             : 
    3549           0 :                         nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
    3550           0 :                         if (nfname == NULL) {
    3551           0 :                                 return NT_STATUS_NO_MEMORY;
    3552             :                         }
    3553             : 
    3554           0 :                         if (ISDOT(nfname)) {
    3555           0 :                                 nfname[0] = '\0';
    3556             :                         }
    3557           0 :                         string_replace(nfname, '/', '\\');
    3558             : 
    3559           0 :                         if (fsp_is_alternate_stream(fsp)) {
    3560           0 :                                 const char *s = smb_fname->stream_name;
    3561           0 :                                 const char *e = NULL;
    3562             :                                 size_t n;
    3563             : 
    3564           0 :                                 SMB_ASSERT(s[0] != '\0');
    3565             : 
    3566             :                                 /*
    3567             :                                  * smb_fname->stream_name is in form
    3568             :                                  * of ':StrEam:$DATA', but we should only
    3569             :                                  * append ':StrEam' here.
    3570             :                                  */
    3571             : 
    3572           0 :                                 e = strchr(&s[1], ':');
    3573           0 :                                 if (e == NULL) {
    3574           0 :                                         n = strlen(s);
    3575             :                                 } else {
    3576           0 :                                         n = PTR_DIFF(e, s);
    3577             :                                 }
    3578           0 :                                 nfname = talloc_strndup_append(nfname, s, n);
    3579           0 :                                 if (nfname == NULL) {
    3580           0 :                                         return NT_STATUS_NO_MEMORY;
    3581             :                                 }
    3582             :                         }
    3583             : 
    3584           0 :                         status = srvstr_push(dstart, flags2,
    3585             :                                           pdata+4, nfname,
    3586             :                                           PTR_DIFF(dend, pdata+4),
    3587             :                                           STR_UNICODE, &len);
    3588           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3589           0 :                                 return status;
    3590             :                         }
    3591           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
    3592           0 :                         data_size = 4 + len;
    3593           0 :                         SIVAL(pdata,0,len);
    3594           0 :                         *fixed_portion = 8;
    3595           0 :                         break;
    3596             :                 }
    3597             : 
    3598           0 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    3599             :                 case SMB_QUERY_FILE_ALLOCATION_INFO:
    3600           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
    3601           0 :                         data_size = 8;
    3602           0 :                         SOFF_T(pdata,0,allocation_size);
    3603           0 :                         break;
    3604             : 
    3605           0 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    3606             :                 case SMB_QUERY_FILE_END_OF_FILEINFO:
    3607           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
    3608           0 :                         data_size = 8;
    3609           0 :                         SOFF_T(pdata,0,file_size);
    3610           0 :                         break;
    3611             : 
    3612           0 :                 case SMB_QUERY_FILE_ALL_INFO:
    3613             :                 case SMB_FILE_ALL_INFORMATION:
    3614             :                 {
    3615             :                         unsigned int ea_size =
    3616           0 :                             estimate_ea_size(smb_fname->fsp);
    3617           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
    3618           0 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3619           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3620           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3621           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3622           0 :                         SIVAL(pdata,32,mode);
    3623           0 :                         SIVAL(pdata,36,0); /* padding. */
    3624           0 :                         pdata += 40;
    3625           0 :                         SOFF_T(pdata,0,allocation_size);
    3626           0 :                         SOFF_T(pdata,8,file_size);
    3627           0 :                         SIVAL(pdata,16,nlink);
    3628           0 :                         SCVAL(pdata,20,delete_pending);
    3629           0 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3630           0 :                         SSVAL(pdata,22,0);
    3631           0 :                         pdata += 24;
    3632           0 :                         SIVAL(pdata,0,ea_size);
    3633           0 :                         pdata += 4; /* EA info */
    3634           0 :                         status = srvstr_push(dstart, flags2,
    3635             :                                           pdata+4, dos_fname,
    3636             :                                           PTR_DIFF(dend, pdata+4),
    3637             :                                           STR_UNICODE, &len);
    3638           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3639           0 :                                 return status;
    3640             :                         }
    3641           0 :                         SIVAL(pdata,0,len);
    3642           0 :                         pdata += 4 + len;
    3643           0 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    3644           0 :                         *fixed_portion = 10;
    3645           0 :                         break;
    3646             :                 }
    3647             : 
    3648         525 :                 case SMB2_FILE_ALL_INFORMATION:
    3649             :                 {
    3650             :                         unsigned int ea_size =
    3651         525 :                             estimate_ea_size(smb_fname->fsp);
    3652         525 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
    3653         525 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
    3654         525 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
    3655         525 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
    3656         525 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
    3657         525 :                         SIVAL(pdata,    0x20, mode);
    3658         525 :                         SIVAL(pdata,    0x24, 0); /* padding. */
    3659         525 :                         SBVAL(pdata,    0x28, allocation_size);
    3660         525 :                         SBVAL(pdata,    0x30, file_size);
    3661         525 :                         SIVAL(pdata,    0x38, nlink);
    3662         525 :                         SCVAL(pdata,    0x3C, delete_pending);
    3663         525 :                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3664         525 :                         SSVAL(pdata,    0x3E, 0); /* padding */
    3665         525 :                         SBVAL(pdata,    0x40, file_id);
    3666         525 :                         SIVAL(pdata,    0x48, ea_size);
    3667         525 :                         SIVAL(pdata,    0x4C, access_mask);
    3668         525 :                         SBVAL(pdata,    0x50, pos);
    3669         525 :                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
    3670         525 :                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
    3671             : 
    3672         525 :                         pdata += 0x60;
    3673             : 
    3674         525 :                         status = srvstr_push(dstart, flags2,
    3675             :                                           pdata+4, dos_fname,
    3676             :                                           PTR_DIFF(dend, pdata+4),
    3677             :                                           STR_UNICODE, &len);
    3678         525 :                         if (!NT_STATUS_IS_OK(status)) {
    3679           0 :                                 return status;
    3680             :                         }
    3681         525 :                         SIVAL(pdata,0,len);
    3682         525 :                         pdata += 4 + len;
    3683         525 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    3684         525 :                         *fixed_portion = 104;
    3685         525 :                         break;
    3686             :                 }
    3687           0 :                 case SMB_FILE_INTERNAL_INFORMATION:
    3688             : 
    3689           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
    3690           0 :                         SBVAL(pdata, 0, file_id);
    3691           0 :                         data_size = 8;
    3692           0 :                         *fixed_portion = 8;
    3693           0 :                         break;
    3694             : 
    3695          30 :                 case SMB_FILE_ACCESS_INFORMATION:
    3696          30 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
    3697          30 :                         SIVAL(pdata, 0, access_mask);
    3698          30 :                         data_size = 4;
    3699          30 :                         *fixed_portion = 4;
    3700          30 :                         break;
    3701             : 
    3702           0 :                 case SMB_FILE_NAME_INFORMATION:
    3703             :                         /* Pathname with leading '\'. */
    3704             :                         {
    3705             :                                 size_t byte_len;
    3706           0 :                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
    3707           0 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
    3708           0 :                                 SIVAL(pdata,0,byte_len);
    3709           0 :                                 data_size = 4 + byte_len;
    3710           0 :                                 break;
    3711             :                         }
    3712             : 
    3713           0 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    3714           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
    3715           0 :                         data_size = 1;
    3716           0 :                         SCVAL(pdata,0,delete_pending);
    3717           0 :                         *fixed_portion = 1;
    3718           0 :                         break;
    3719             : 
    3720         278 :                 case SMB_FILE_POSITION_INFORMATION:
    3721         278 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
    3722         278 :                         data_size = 8;
    3723         278 :                         SOFF_T(pdata,0,pos);
    3724         278 :                         *fixed_portion = 8;
    3725         278 :                         break;
    3726             : 
    3727           0 :                 case SMB_FILE_MODE_INFORMATION:
    3728           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
    3729           0 :                         SIVAL(pdata,0,mode);
    3730           0 :                         data_size = 4;
    3731           0 :                         *fixed_portion = 4;
    3732           0 :                         break;
    3733             : 
    3734           0 :                 case SMB_FILE_ALIGNMENT_INFORMATION:
    3735           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
    3736           0 :                         SIVAL(pdata,0,0); /* No alignment needed. */
    3737           0 :                         data_size = 4;
    3738           0 :                         *fixed_portion = 4;
    3739           0 :                         break;
    3740             : 
    3741             :                 /*
    3742             :                  * NT4 server just returns "invalid query" to this - if we try
    3743             :                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
    3744             :                  * want this. JRA.
    3745             :                  */
    3746             :                 /* The first statement above is false - verified using Thursby
    3747             :                  * client against NT4 -- gcolley.
    3748             :                  */
    3749          52 :                 case SMB_QUERY_FILE_STREAM_INFO:
    3750             :                 case SMB_FILE_STREAM_INFORMATION: {
    3751          52 :                         unsigned int num_streams = 0;
    3752          52 :                         struct stream_struct *streams = NULL;
    3753             : 
    3754          52 :                         DEBUG(10,("smbd_do_qfilepathinfo: "
    3755             :                                   "SMB_FILE_STREAM_INFORMATION\n"));
    3756             : 
    3757          52 :                         if (is_ntfs_stream_smb_fname(smb_fname)) {
    3758           8 :                                 return NT_STATUS_INVALID_PARAMETER;
    3759             :                         }
    3760             : 
    3761          44 :                         status = vfs_fstreaminfo(fsp,
    3762             :                                                 mem_ctx,
    3763             :                                                 &num_streams,
    3764             :                                                 &streams);
    3765             : 
    3766          44 :                         if (!NT_STATUS_IS_OK(status)) {
    3767           0 :                                 DEBUG(10, ("could not get stream info: %s\n",
    3768             :                                            nt_errstr(status)));
    3769           0 :                                 return status;
    3770             :                         }
    3771             : 
    3772          44 :                         status = marshall_stream_info(num_streams, streams,
    3773             :                                                       pdata, max_data_bytes,
    3774             :                                                       &data_size);
    3775             : 
    3776          44 :                         if (!NT_STATUS_IS_OK(status)) {
    3777           0 :                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
    3778             :                                            nt_errstr(status)));
    3779           0 :                                 TALLOC_FREE(streams);
    3780           0 :                                 return status;
    3781             :                         }
    3782             : 
    3783          44 :                         TALLOC_FREE(streams);
    3784             : 
    3785          44 :                         *fixed_portion = 32;
    3786             : 
    3787          44 :                         break;
    3788             :                 }
    3789           0 :                 case SMB_QUERY_COMPRESSION_INFO:
    3790             :                 case SMB_FILE_COMPRESSION_INFORMATION:
    3791           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
    3792           0 :                         SOFF_T(pdata,0,file_size);
    3793           0 :                         SIVAL(pdata,8,0); /* ??? */
    3794           0 :                         SIVAL(pdata,12,0); /* ??? */
    3795           0 :                         data_size = 16;
    3796           0 :                         *fixed_portion = 16;
    3797           0 :                         break;
    3798             : 
    3799           0 :                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
    3800           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
    3801           0 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3802           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3803           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3804           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3805           0 :                         SOFF_T(pdata,32,allocation_size);
    3806           0 :                         SOFF_T(pdata,40,file_size);
    3807           0 :                         SIVAL(pdata,48,mode);
    3808           0 :                         SIVAL(pdata,52,0); /* ??? */
    3809           0 :                         data_size = 56;
    3810           0 :                         *fixed_portion = 56;
    3811           0 :                         break;
    3812             : 
    3813           0 :                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
    3814           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
    3815           0 :                         SIVAL(pdata,0,mode);
    3816           0 :                         SIVAL(pdata,4,0);
    3817           0 :                         data_size = 8;
    3818           0 :                         *fixed_portion = 8;
    3819           0 :                         break;
    3820             : 
    3821             :                 /*
    3822             :                  * SMB2 UNIX Extensions.
    3823             :                  */
    3824           0 :                 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
    3825             :                 {
    3826           0 :                         uint8_t *buf = NULL;
    3827           0 :                         ssize_t plen = 0;
    3828             : 
    3829           0 :                         if (!(conn->sconn->using_smb2)) {
    3830           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3831             :                         }
    3832           0 :                         if (!lp_smb3_unix_extensions()) {
    3833           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3834             :                         }
    3835           0 :                         if (fsp == NULL) {
    3836           0 :                                 return NT_STATUS_INVALID_HANDLE;
    3837             :                         }
    3838           0 :                         if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
    3839           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3840             :                         }
    3841             : 
    3842             :                         /* Determine the size of the posix info context */
    3843           0 :                         plen = store_smb2_posix_info(conn,
    3844           0 :                                                      &smb_fname->st,
    3845             :                                                      0,
    3846             :                                                      mode,
    3847             :                                                      NULL,
    3848             :                                                      0);
    3849           0 :                         if (plen == -1 || data_size < plen) {
    3850           0 :                                 return NT_STATUS_INVALID_PARAMETER;
    3851             :                         }
    3852           0 :                         buf = talloc_zero_size(mem_ctx, plen);
    3853           0 :                         if (buf == NULL) {
    3854           0 :                                 return NT_STATUS_NO_MEMORY;
    3855             :                         }
    3856             : 
    3857             :                         /* Store the context in buf */
    3858           0 :                         store_smb2_posix_info(conn,
    3859           0 :                                               &smb_fname->st,
    3860             :                                               0,
    3861             :                                               mode,
    3862             :                                               buf,
    3863             :                                               plen);
    3864           0 :                         memcpy(pdata, buf, plen);
    3865           0 :                         data_size = plen;
    3866           0 :                         break;
    3867             :                 }
    3868             : 
    3869           0 :                 default:
    3870           0 :                         return NT_STATUS_INVALID_LEVEL;
    3871             :         }
    3872             : 
    3873         929 :         *pdata_size = data_size;
    3874         929 :         return NT_STATUS_OK;
    3875             : }
    3876             : 
    3877             : /****************************************************************************
    3878             :  Set a hard link (called by UNIX extensions and by NT rename with HARD link
    3879             :  code.
    3880             : ****************************************************************************/
    3881             : 
    3882           4 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
    3883             :                 connection_struct *conn,
    3884             :                 struct smb_request *req,
    3885             :                 bool overwrite_if_exists,
    3886             :                 struct files_struct *old_dirfsp,
    3887             :                 const struct smb_filename *smb_fname_old,
    3888             :                 struct files_struct *new_dirfsp,
    3889             :                 struct smb_filename *smb_fname_new)
    3890             : {
    3891           4 :         NTSTATUS status = NT_STATUS_OK;
    3892             :         int ret;
    3893             :         bool ok;
    3894           4 :         struct smb_filename *parent_fname_old = NULL;
    3895           4 :         struct smb_filename *base_name_old = NULL;
    3896           4 :         struct smb_filename *parent_fname_new = NULL;
    3897           4 :         struct smb_filename *base_name_new = NULL;
    3898             : 
    3899             :         /* source must already exist. */
    3900           4 :         if (!VALID_STAT(smb_fname_old->st)) {
    3901           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    3902           0 :                 goto out;
    3903             :         }
    3904             : 
    3905             :         /* No links from a directory. */
    3906           4 :         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
    3907           0 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    3908           0 :                 goto out;
    3909             :         }
    3910             : 
    3911             :         /* Setting a hardlink to/from a stream isn't currently supported. */
    3912           4 :         ok = is_ntfs_stream_smb_fname(smb_fname_old);
    3913           4 :         if (ok) {
    3914           0 :                 DBG_DEBUG("Old name has streams\n");
    3915           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3916           0 :                 goto out;
    3917             :         }
    3918           4 :         ok = is_ntfs_stream_smb_fname(smb_fname_new);
    3919           4 :         if (ok) {
    3920           0 :                 DBG_DEBUG("New name has streams\n");
    3921           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3922           0 :                 goto out;
    3923             :         }
    3924             : 
    3925           4 :         if (smb_fname_old->twrp != 0) {
    3926           0 :                 status = NT_STATUS_NOT_SAME_DEVICE;
    3927           0 :                 goto out;
    3928             :         }
    3929             : 
    3930           4 :         status = parent_pathref(talloc_tos(),
    3931             :                                 conn->cwd_fsp,
    3932             :                                 smb_fname_old,
    3933             :                                 &parent_fname_old,
    3934             :                                 &base_name_old);
    3935           4 :         if (!NT_STATUS_IS_OK(status)) {
    3936           0 :                 goto out;
    3937             :         }
    3938             : 
    3939           4 :         status = parent_pathref(talloc_tos(),
    3940             :                                 conn->cwd_fsp,
    3941             :                                 smb_fname_new,
    3942             :                                 &parent_fname_new,
    3943             :                                 &base_name_new);
    3944           4 :         if (!NT_STATUS_IS_OK(status)) {
    3945           0 :                 goto out;
    3946             :         }
    3947             : 
    3948           4 :         if (VALID_STAT(smb_fname_new->st)) {
    3949           0 :                 if (overwrite_if_exists) {
    3950           0 :                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
    3951           0 :                                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    3952           0 :                                 goto out;
    3953             :                         }
    3954           0 :                         status = unlink_internals(conn,
    3955             :                                                 req,
    3956             :                                                 FILE_ATTRIBUTE_NORMAL,
    3957             :                                                 NULL, /* new_dirfsp */
    3958             :                                                 smb_fname_new);
    3959           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3960           0 :                                 goto out;
    3961             :                         }
    3962             :                 } else {
    3963             :                         /* Disallow if newname already exists. */
    3964           0 :                         status = NT_STATUS_OBJECT_NAME_COLLISION;
    3965           0 :                         goto out;
    3966             :                 }
    3967             :         }
    3968             : 
    3969           4 :         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
    3970             :                   smb_fname_old->base_name, smb_fname_new->base_name));
    3971             : 
    3972           4 :         ret = SMB_VFS_LINKAT(conn,
    3973             :                         parent_fname_old->fsp,
    3974             :                         base_name_old,
    3975             :                         parent_fname_new->fsp,
    3976             :                         base_name_new,
    3977             :                         0);
    3978             : 
    3979           4 :         if (ret != 0) {
    3980           0 :                 status = map_nt_error_from_unix(errno);
    3981           0 :                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
    3982             :                          nt_errstr(status), smb_fname_old->base_name,
    3983             :                          smb_fname_new->base_name));
    3984             :         }
    3985             : 
    3986           4 :   out:
    3987             : 
    3988           4 :         TALLOC_FREE(parent_fname_old);
    3989           4 :         TALLOC_FREE(parent_fname_new);
    3990           4 :         return status;
    3991             : }
    3992             : 
    3993             : /****************************************************************************
    3994             :  Deal with setting the time from any of the setfilepathinfo functions.
    3995             :  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
    3996             :  calling this function.
    3997             : ****************************************************************************/
    3998             : 
    3999         502 : NTSTATUS smb_set_file_time(connection_struct *conn,
    4000             :                            files_struct *fsp,
    4001             :                            struct smb_filename *smb_fname,
    4002             :                            struct smb_file_time *ft,
    4003             :                            bool setting_write_time)
    4004             : {
    4005         502 :         struct files_struct *set_fsp = NULL;
    4006             :         struct timeval_buf tbuf[4];
    4007         502 :         uint32_t action =
    4008             :                 FILE_NOTIFY_CHANGE_LAST_ACCESS
    4009             :                 |FILE_NOTIFY_CHANGE_LAST_WRITE
    4010             :                 |FILE_NOTIFY_CHANGE_CREATION;
    4011             :         int ret;
    4012             : 
    4013         502 :         if (!VALID_STAT(smb_fname->st)) {
    4014           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4015             :         }
    4016             : 
    4017         502 :         if (fsp == NULL) {
    4018             :                 /* A symlink */
    4019           0 :                 return NT_STATUS_OK;
    4020             :         }
    4021             : 
    4022         502 :         set_fsp = metadata_fsp(fsp);
    4023             : 
    4024             :         /* get some defaults (no modifications) if any info is zero or -1. */
    4025         502 :         if (is_omit_timespec(&ft->create_time)) {
    4026         497 :                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
    4027             :         }
    4028             : 
    4029         502 :         if (is_omit_timespec(&ft->atime)) {
    4030         497 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
    4031             :         }
    4032             : 
    4033         502 :         if (is_omit_timespec(&ft->mtime)) {
    4034          61 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    4035             :         }
    4036             : 
    4037         502 :         if (!setting_write_time) {
    4038             :                 /* ft->mtime comes from change time, not write time. */
    4039         440 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    4040             :         }
    4041             : 
    4042             :         /* Ensure the resolution is the correct for
    4043             :          * what we can store on this filesystem. */
    4044             : 
    4045         502 :         round_timespec(conn->ts_res, &ft->create_time);
    4046         502 :         round_timespec(conn->ts_res, &ft->ctime);
    4047         502 :         round_timespec(conn->ts_res, &ft->atime);
    4048         502 :         round_timespec(conn->ts_res, &ft->mtime);
    4049             : 
    4050         502 :         DBG_DEBUG("smb_set_filetime: actime: %s\n ",
    4051             :                   timespec_string_buf(&ft->atime, true, &tbuf[0]));
    4052         502 :         DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
    4053             :                   timespec_string_buf(&ft->mtime, true, &tbuf[1]));
    4054         502 :         DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
    4055             :                   timespec_string_buf(&ft->ctime, true, &tbuf[2]));
    4056         502 :         DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
    4057             :                   timespec_string_buf(&ft->create_time, true, &tbuf[3]));
    4058             : 
    4059         502 :         if (setting_write_time) {
    4060             :                 /*
    4061             :                  * This was a Windows setfileinfo on an open file.
    4062             :                  * NT does this a lot. We also need to
    4063             :                  * set the time here, as it can be read by
    4064             :                  * FindFirst/FindNext and with the patch for bug #2045
    4065             :                  * in smbd/fileio.c it ensures that this timestamp is
    4066             :                  * kept sticky even after a write. We save the request
    4067             :                  * away and will set it on file close and after a write. JRA.
    4068             :                  */
    4069             : 
    4070          62 :                 DBG_DEBUG("setting pending modtime to %s\n",
    4071             :                           timespec_string_buf(&ft->mtime, true, &tbuf[0]));
    4072             : 
    4073          62 :                 if (set_fsp != NULL) {
    4074          62 :                         set_sticky_write_time_fsp(set_fsp, ft->mtime);
    4075             :                 } else {
    4076           0 :                         set_sticky_write_time_path(
    4077           0 :                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
    4078             :                                 ft->mtime);
    4079             :                 }
    4080             :         }
    4081             : 
    4082         502 :         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
    4083             : 
    4084         502 :         ret = file_ntimes(conn, set_fsp, ft);
    4085         502 :         if (ret != 0) {
    4086           0 :                 return map_nt_error_from_unix(errno);
    4087             :         }
    4088             : 
    4089         502 :         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
    4090         502 :                      smb_fname->base_name);
    4091         502 :         return NT_STATUS_OK;
    4092             : }
    4093             : 
    4094             : /****************************************************************************
    4095             :  Deal with setting the dosmode from any of the setfilepathinfo functions.
    4096             :  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
    4097             :  done before calling this function.
    4098             : ****************************************************************************/
    4099             : 
    4100          63 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
    4101             :                                      struct files_struct *fsp,
    4102             :                                      uint32_t dosmode)
    4103             : {
    4104          63 :         struct files_struct *dos_fsp = NULL;
    4105             :         uint32_t current_dosmode;
    4106             :         int ret;
    4107             : 
    4108          63 :         if (!VALID_STAT(fsp->fsp_name->st)) {
    4109           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4110             :         }
    4111             : 
    4112          63 :         dos_fsp = metadata_fsp(fsp);
    4113             : 
    4114          63 :         if (dosmode != 0) {
    4115          59 :                 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
    4116          33 :                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
    4117             :                 } else {
    4118          26 :                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
    4119             :                 }
    4120             :         }
    4121             : 
    4122          63 :         DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
    4123             : 
    4124             :         /* check the mode isn't different, before changing it */
    4125          63 :         if (dosmode == 0) {
    4126           4 :                 return NT_STATUS_OK;
    4127             :         }
    4128          59 :         current_dosmode = fdos_mode(dos_fsp);
    4129          59 :         if (dosmode == current_dosmode) {
    4130          28 :                 return NT_STATUS_OK;
    4131             :         }
    4132             : 
    4133          31 :         DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
    4134             :                   fsp_str_dbg(dos_fsp), dosmode);
    4135             : 
    4136          31 :         ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
    4137          31 :         if (ret != 0) {
    4138           1 :                 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
    4139             :                             fsp_str_dbg(dos_fsp), strerror(errno));
    4140           1 :                 return map_nt_error_from_unix(errno);
    4141             :         }
    4142             : 
    4143          30 :         return NT_STATUS_OK;
    4144             : }
    4145             : 
    4146             : /****************************************************************************
    4147             :  Deal with setting the size from any of the setfilepathinfo functions.
    4148             : ****************************************************************************/
    4149             : 
    4150           0 : NTSTATUS smb_set_file_size(connection_struct *conn,
    4151             :                            struct smb_request *req,
    4152             :                            files_struct *fsp,
    4153             :                            struct smb_filename *smb_fname,
    4154             :                            const SMB_STRUCT_STAT *psbuf,
    4155             :                            off_t size,
    4156             :                            bool fail_after_createfile)
    4157             : {
    4158           0 :         NTSTATUS status = NT_STATUS_OK;
    4159           0 :         files_struct *new_fsp = NULL;
    4160             : 
    4161           0 :         if (!VALID_STAT(*psbuf)) {
    4162           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4163             :         }
    4164             : 
    4165           0 :         DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
    4166             :                  (uint64_t)size,
    4167             :                  get_file_size_stat(psbuf));
    4168             : 
    4169           0 :         if (size == get_file_size_stat(psbuf)) {
    4170           0 :                 if (fsp == NULL) {
    4171           0 :                         return NT_STATUS_OK;
    4172             :                 }
    4173           0 :                 if (!fsp->fsp_flags.modified) {
    4174           0 :                         return NT_STATUS_OK;
    4175             :                 }
    4176           0 :                 trigger_write_time_update_immediate(fsp);
    4177           0 :                 return NT_STATUS_OK;
    4178             :         }
    4179             : 
    4180           0 :         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
    4181             :                   smb_fname_str_dbg(smb_fname), (double)size));
    4182             : 
    4183           0 :         if (fsp &&
    4184           0 :             !fsp->fsp_flags.is_pathref &&
    4185           0 :             fsp_get_io_fd(fsp) != -1)
    4186             :         {
    4187             :                 /* Handle based call. */
    4188           0 :                 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
    4189           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4190           0 :                         return status;
    4191             :                 }
    4192             : 
    4193           0 :                 if (vfs_set_filelen(fsp, size) == -1) {
    4194           0 :                         return map_nt_error_from_unix(errno);
    4195             :                 }
    4196           0 :                 trigger_write_time_update_immediate(fsp);
    4197           0 :                 return NT_STATUS_OK;
    4198             :         }
    4199             : 
    4200           0 :         status = SMB_VFS_CREATE_FILE(
    4201             :                 conn,                                   /* conn */
    4202             :                 req,                                    /* req */
    4203             :                 NULL,                                   /* dirfsp */
    4204             :                 smb_fname,                              /* fname */
    4205             :                 FILE_WRITE_DATA,                        /* access_mask */
    4206             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    4207             :                     FILE_SHARE_DELETE),
    4208             :                 FILE_OPEN,                              /* create_disposition*/
    4209             :                 0,                                      /* create_options */
    4210             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    4211             :                 0,                                      /* oplock_request */
    4212             :                 NULL,                                   /* lease */
    4213             :                 0,                                      /* allocation_size */
    4214             :                 0,                                      /* private_flags */
    4215             :                 NULL,                                   /* sd */
    4216             :                 NULL,                                   /* ea_list */
    4217             :                 &new_fsp,                           /* result */
    4218             :                 NULL,                                   /* pinfo */
    4219             :                 NULL, NULL);                            /* create context */
    4220             : 
    4221           0 :         if (!NT_STATUS_IS_OK(status)) {
    4222             :                 /* NB. We check for open_was_deferred in the caller. */
    4223           0 :                 return status;
    4224             :         }
    4225             : 
    4226             :         /* See RAW-SFILEINFO-END-OF-FILE */
    4227           0 :         if (fail_after_createfile) {
    4228           0 :                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4229           0 :                 return NT_STATUS_INVALID_LEVEL;
    4230             :         }
    4231             : 
    4232           0 :         if (vfs_set_filelen(new_fsp, size) == -1) {
    4233           0 :                 status = map_nt_error_from_unix(errno);
    4234           0 :                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4235           0 :                 return status;
    4236             :         }
    4237             : 
    4238           0 :         trigger_write_time_update_immediate(new_fsp);
    4239           0 :         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4240           0 :         return NT_STATUS_OK;
    4241             : }
    4242             : 
    4243             : /****************************************************************************
    4244             :  Deal with SMB_INFO_SET_EA.
    4245             : ****************************************************************************/
    4246             : 
    4247           0 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
    4248             :                                 const char *pdata,
    4249             :                                 int total_data,
    4250             :                                 files_struct *fsp,
    4251             :                                 struct smb_filename *smb_fname)
    4252             : {
    4253           0 :         struct ea_list *ea_list = NULL;
    4254           0 :         TALLOC_CTX *ctx = NULL;
    4255           0 :         NTSTATUS status = NT_STATUS_OK;
    4256             : 
    4257           0 :         if (total_data < 10) {
    4258             : 
    4259             :                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
    4260             :                    length. They seem to have no effect. Bug #3212. JRA */
    4261             : 
    4262           0 :                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
    4263             :                         /* We're done. We only get EA info in this call. */
    4264           0 :                         return NT_STATUS_OK;
    4265             :                 }
    4266             : 
    4267           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4268             :         }
    4269             : 
    4270           0 :         if (IVAL(pdata,0) > total_data) {
    4271           0 :                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
    4272             :                         IVAL(pdata,0), (unsigned int)total_data));
    4273           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4274             :         }
    4275             : 
    4276           0 :         ctx = talloc_tos();
    4277           0 :         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
    4278           0 :         if (!ea_list) {
    4279           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4280             :         }
    4281             : 
    4282           0 :         if (fsp == NULL) {
    4283             :                 /*
    4284             :                  * The only way fsp can be NULL here is if
    4285             :                  * smb_fname points at a symlink and
    4286             :                  * and we're in POSIX context.
    4287             :                  * Ensure this is the case.
    4288             :                  *
    4289             :                  * In this case we cannot set the EA.
    4290             :                  */
    4291           0 :                 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
    4292           0 :                 return NT_STATUS_ACCESS_DENIED;
    4293             :         }
    4294             : 
    4295           0 :         status = set_ea(conn, fsp, ea_list);
    4296             : 
    4297           0 :         return status;
    4298             : }
    4299             : 
    4300             : /****************************************************************************
    4301             :  Deal with SMB_FILE_FULL_EA_INFORMATION set.
    4302             : ****************************************************************************/
    4303             : 
    4304           0 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
    4305             :                                 const char *pdata,
    4306             :                                 int total_data,
    4307             :                                 files_struct *fsp)
    4308             : {
    4309           0 :         struct ea_list *ea_list = NULL;
    4310             :         NTSTATUS status;
    4311             : 
    4312           0 :         if (fsp == NULL) {
    4313           0 :                 return NT_STATUS_INVALID_HANDLE;
    4314             :         }
    4315             : 
    4316           0 :         if (!lp_ea_support(SNUM(conn))) {
    4317           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
    4318             :                         "EA's not supported.\n",
    4319             :                         (unsigned int)total_data));
    4320           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
    4321             :         }
    4322             : 
    4323           0 :         if (total_data < 10) {
    4324           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
    4325             :                         "too small.\n",
    4326             :                         (unsigned int)total_data));
    4327           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4328             :         }
    4329             : 
    4330           0 :         ea_list = read_nttrans_ea_list(talloc_tos(),
    4331             :                                 pdata,
    4332             :                                 total_data);
    4333             : 
    4334           0 :         if (!ea_list) {
    4335           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4336             :         }
    4337             : 
    4338           0 :         status = set_ea(conn, fsp, ea_list);
    4339             : 
    4340           0 :         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
    4341             :                 smb_fname_str_dbg(fsp->fsp_name),
    4342             :                 nt_errstr(status) ));
    4343             : 
    4344           0 :         return status;
    4345             : }
    4346             : 
    4347             : 
    4348             : /****************************************************************************
    4349             :  Deal with SMB_SET_FILE_DISPOSITION_INFO.
    4350             : ****************************************************************************/
    4351             : 
    4352         806 : NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
    4353             :                                        const char *pdata,
    4354             :                                        int total_data,
    4355             :                                        files_struct *fsp,
    4356             :                                        struct smb_filename *smb_fname)
    4357             : {
    4358         806 :         NTSTATUS status = NT_STATUS_OK;
    4359             :         bool delete_on_close;
    4360         806 :         uint32_t dosmode = 0;
    4361             : 
    4362         806 :         if (total_data < 1) {
    4363           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4364             :         }
    4365             : 
    4366         806 :         if (fsp == NULL) {
    4367           0 :                 return NT_STATUS_INVALID_HANDLE;
    4368             :         }
    4369             : 
    4370         806 :         delete_on_close = (CVAL(pdata,0) ? True : False);
    4371         806 :         dosmode = fdos_mode(fsp);
    4372             : 
    4373         806 :         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
    4374             :                 "delete_on_close = %u\n",
    4375             :                 smb_fname_str_dbg(smb_fname),
    4376             :                 (unsigned int)dosmode,
    4377             :                 (unsigned int)delete_on_close ));
    4378             : 
    4379         806 :         if (delete_on_close) {
    4380         806 :                 status = can_set_delete_on_close(fsp, dosmode);
    4381         806 :                 if (!NT_STATUS_IS_OK(status)) {
    4382           4 :                         return status;
    4383             :                 }
    4384             :         }
    4385             : 
    4386             :         /* The set is across all open files on this dev/inode pair. */
    4387         802 :         if (!set_delete_on_close(fsp, delete_on_close,
    4388         802 :                                  conn->session_info->security_token,
    4389         802 :                                  conn->session_info->unix_token)) {
    4390           0 :                 return NT_STATUS_ACCESS_DENIED;
    4391             :         }
    4392         802 :         return NT_STATUS_OK;
    4393             : }
    4394             : 
    4395             : /****************************************************************************
    4396             :  Deal with SMB_FILE_POSITION_INFORMATION.
    4397             : ****************************************************************************/
    4398             : 
    4399           0 : static NTSTATUS smb_file_position_information(connection_struct *conn,
    4400             :                                 const char *pdata,
    4401             :                                 int total_data,
    4402             :                                 files_struct *fsp)
    4403             : {
    4404             :         uint64_t position_information;
    4405             : 
    4406           0 :         if (total_data < 8) {
    4407           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4408             :         }
    4409             : 
    4410           0 :         if (fsp == NULL) {
    4411             :                 /* Ignore on pathname based set. */
    4412           0 :                 return NT_STATUS_OK;
    4413             :         }
    4414             : 
    4415           0 :         position_information = (uint64_t)IVAL(pdata,0);
    4416           0 :         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
    4417             : 
    4418           0 :         DEBUG(10,("smb_file_position_information: Set file position "
    4419             :                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
    4420             :                   (double)position_information));
    4421           0 :         fh_set_position_information(fsp->fh, position_information);
    4422           0 :         return NT_STATUS_OK;
    4423             : }
    4424             : 
    4425             : /****************************************************************************
    4426             :  Deal with SMB_FILE_MODE_INFORMATION.
    4427             : ****************************************************************************/
    4428             : 
    4429           0 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
    4430             :                                 const char *pdata,
    4431             :                                 int total_data)
    4432             : {
    4433             :         uint32_t mode;
    4434             : 
    4435           0 :         if (total_data < 4) {
    4436           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4437             :         }
    4438           0 :         mode = IVAL(pdata,0);
    4439           0 :         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
    4440           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4441             :         }
    4442           0 :         return NT_STATUS_OK;
    4443             : }
    4444             : 
    4445             : /****************************************************************************
    4446             :  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
    4447             : ****************************************************************************/
    4448             : 
    4449          21 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
    4450             :                                             struct smb_request *req,
    4451             :                                             const char *pdata,
    4452             :                                             int total_data,
    4453             :                                             files_struct *fsp,
    4454             :                                             struct smb_filename *smb_fname_src)
    4455             : {
    4456             :         bool overwrite;
    4457             :         uint32_t len;
    4458          21 :         char *newname = NULL;
    4459          21 :         struct files_struct *dst_dirfsp = NULL;
    4460          21 :         struct smb_filename *smb_fname_dst = NULL;
    4461          21 :         const char *dst_original_lcomp = NULL;
    4462          21 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4463          21 :         NTTIME dst_twrp = 0;
    4464          21 :         NTSTATUS status = NT_STATUS_OK;
    4465          21 :         bool is_dfs = (req->flags2 & FLAGS2_DFS_PATHNAMES);
    4466          21 :         TALLOC_CTX *ctx = talloc_tos();
    4467             : 
    4468          21 :         if (!fsp) {
    4469           0 :                 return NT_STATUS_INVALID_HANDLE;
    4470             :         }
    4471             : 
    4472          21 :         if (total_data < 20) {
    4473           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4474             :         }
    4475             : 
    4476          21 :         overwrite = (CVAL(pdata,0) ? True : False);
    4477          21 :         len = IVAL(pdata,16);
    4478             : 
    4479          21 :         if (len > (total_data - 20) || (len == 0)) {
    4480           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4481             :         }
    4482             : 
    4483          21 :         (void)srvstr_pull_talloc(ctx,
    4484             :                                  pdata,
    4485             :                                  req->flags2,
    4486             :                                  &newname,
    4487             :                                  &pdata[20],
    4488             :                                  len,
    4489             :                                  STR_TERMINATE);
    4490             : 
    4491          21 :         if (newname == NULL) {
    4492           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4493             :         }
    4494          21 :         status = check_path_syntax_smb2(newname, is_dfs);
    4495          21 :         if (!NT_STATUS_IS_OK(status)) {
    4496           0 :                 return status;
    4497             :         }
    4498             : 
    4499          21 :         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
    4500             :                                 newname));
    4501             : 
    4502          21 :         if (newname[0] == ':') {
    4503             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    4504           0 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    4505           0 :                                         fsp->base_fsp->fsp_name->base_name,
    4506             :                                         newname,
    4507             :                                         NULL,
    4508           0 :                                         fsp->base_fsp->fsp_name->twrp,
    4509           0 :                                         fsp->base_fsp->fsp_name->flags);
    4510           0 :                 if (smb_fname_dst == NULL) {
    4511           0 :                         status = NT_STATUS_NO_MEMORY;
    4512           0 :                         goto out;
    4513             :                 }
    4514             :         } else {
    4515          21 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
    4516           0 :                         extract_snapshot_token(newname, &dst_twrp);
    4517             :                 }
    4518          21 :                 status = filename_convert_dirfsp(ctx,
    4519             :                                                  conn,
    4520             :                                                  newname,
    4521             :                                                  ucf_flags,
    4522             :                                                  dst_twrp,
    4523             :                                                  &dst_dirfsp,
    4524             :                                                  &smb_fname_dst);
    4525          21 :                 if (!NT_STATUS_IS_OK(status)) {
    4526           0 :                         goto out;
    4527             :                 }
    4528             :         }
    4529             : 
    4530             :         /*
    4531             :          * Set the original last component, since
    4532             :          * rename_internals_fsp() requires it.
    4533             :          */
    4534          21 :         dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    4535             :                                         conn,
    4536             :                                         newname,
    4537             :                                         ucf_flags);
    4538          21 :         if (dst_original_lcomp == NULL) {
    4539           0 :                 status = NT_STATUS_NO_MEMORY;
    4540           0 :                 goto out;
    4541             :         }
    4542             : 
    4543          21 :         DEBUG(10,("smb2_file_rename_information: "
    4544             :                   "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    4545             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4546             :                   smb_fname_str_dbg(smb_fname_dst)));
    4547          21 :         status = rename_internals_fsp(conn,
    4548             :                                 fsp,
    4549             :                                 NULL, /* dst_dirfsp */
    4550             :                                 smb_fname_dst,
    4551             :                                 dst_original_lcomp,
    4552             :                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
    4553             :                                 overwrite);
    4554             : 
    4555          21 :  out:
    4556          21 :         TALLOC_FREE(smb_fname_dst);
    4557          21 :         return status;
    4558             : }
    4559             : 
    4560           4 : static NTSTATUS smb_file_link_information(connection_struct *conn,
    4561             :                                             struct smb_request *req,
    4562             :                                             const char *pdata,
    4563             :                                             int total_data,
    4564             :                                             files_struct *fsp,
    4565             :                                             struct smb_filename *smb_fname_src)
    4566             : {
    4567             :         bool overwrite;
    4568             :         uint32_t len;
    4569           4 :         char *newname = NULL;
    4570           4 :         struct files_struct *dst_dirfsp = NULL;
    4571           4 :         struct smb_filename *smb_fname_dst = NULL;
    4572           4 :         NTSTATUS status = NT_STATUS_OK;
    4573           4 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4574           4 :         NTTIME dst_twrp = 0;
    4575           4 :         TALLOC_CTX *ctx = talloc_tos();
    4576             : 
    4577           4 :         if (!fsp) {
    4578           0 :                 return NT_STATUS_INVALID_HANDLE;
    4579             :         }
    4580             : 
    4581           4 :         if (total_data < 20) {
    4582           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4583             :         }
    4584             : 
    4585           4 :         overwrite = (CVAL(pdata,0) ? true : false);
    4586           4 :         len = IVAL(pdata,16);
    4587             : 
    4588           4 :         if (len > (total_data - 20) || (len == 0)) {
    4589           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4590             :         }
    4591             : 
    4592           4 :         if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
    4593           0 :                 srvstr_get_path_posix(ctx,
    4594             :                                 pdata,
    4595           0 :                                 req->flags2,
    4596             :                                 &newname,
    4597             :                                 &pdata[20],
    4598             :                                 len,
    4599             :                                 STR_TERMINATE,
    4600             :                                 &status);
    4601           0 :                 ucf_flags |= UCF_POSIX_PATHNAMES;
    4602             :         } else {
    4603           4 :                 srvstr_get_path(ctx,
    4604             :                                 pdata,
    4605           4 :                                 req->flags2,
    4606             :                                 &newname,
    4607             :                                 &pdata[20],
    4608             :                                 len,
    4609             :                                 STR_TERMINATE,
    4610             :                                 &status);
    4611             :         }
    4612           4 :         if (!NT_STATUS_IS_OK(status)) {
    4613           0 :                 return status;
    4614             :         }
    4615             : 
    4616           4 :         DEBUG(10,("smb_file_link_information: got name |%s|\n",
    4617             :                                 newname));
    4618             : 
    4619           4 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4620           0 :                 extract_snapshot_token(newname, &dst_twrp);
    4621             :         }
    4622           4 :         status = filename_convert_dirfsp(ctx,
    4623             :                                          conn,
    4624             :                                          newname,
    4625             :                                          ucf_flags,
    4626             :                                          dst_twrp,
    4627             :                                          &dst_dirfsp,
    4628             :                                          &smb_fname_dst);
    4629           4 :         if (!NT_STATUS_IS_OK(status)) {
    4630           0 :                 return status;
    4631             :         }
    4632             : 
    4633           4 :         if (fsp->base_fsp) {
    4634             :                 /* No stream names. */
    4635           0 :                 return NT_STATUS_NOT_SUPPORTED;
    4636             :         }
    4637             : 
    4638           4 :         DEBUG(10,("smb_file_link_information: "
    4639             :                   "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
    4640             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4641             :                   smb_fname_str_dbg(smb_fname_dst)));
    4642           4 :         status = hardlink_internals(ctx,
    4643             :                                 conn,
    4644             :                                 req,
    4645             :                                 overwrite,
    4646             :                                 NULL, /* src_dirfsp */
    4647           4 :                                 fsp->fsp_name,
    4648             :                                 dst_dirfsp, /* dst_dirfsp */
    4649             :                                 smb_fname_dst);
    4650             : 
    4651           4 :         TALLOC_FREE(smb_fname_dst);
    4652           4 :         return status;
    4653             : }
    4654             : 
    4655             : /****************************************************************************
    4656             :  Deal with SMB_FILE_RENAME_INFORMATION.
    4657             : ****************************************************************************/
    4658             : 
    4659           0 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
    4660             :                                             struct smb_request *req,
    4661             :                                             const char *pdata,
    4662             :                                             int total_data,
    4663             :                                             files_struct *fsp,
    4664             :                                             struct smb_filename *smb_fname_src)
    4665             : {
    4666             :         bool overwrite;
    4667             :         uint32_t root_fid;
    4668             :         uint32_t len;
    4669           0 :         char *newname = NULL;
    4670           0 :         struct files_struct *dst_dirfsp = NULL;
    4671           0 :         struct smb_filename *smb_fname_dst = NULL;
    4672           0 :         const char *dst_original_lcomp = NULL;
    4673           0 :         NTSTATUS status = NT_STATUS_OK;
    4674             :         char *p;
    4675           0 :         TALLOC_CTX *ctx = talloc_tos();
    4676             : 
    4677           0 :         if (total_data < 13) {
    4678           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4679             :         }
    4680             : 
    4681           0 :         overwrite = (CVAL(pdata,0) != 0);
    4682           0 :         root_fid = IVAL(pdata,4);
    4683           0 :         len = IVAL(pdata,8);
    4684             : 
    4685           0 :         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
    4686           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4687             :         }
    4688             : 
    4689           0 :         if (req->posix_pathnames) {
    4690           0 :                 srvstr_get_path_posix(ctx,
    4691             :                                 pdata,
    4692           0 :                                 req->flags2,
    4693             :                                 &newname,
    4694             :                                 &pdata[12],
    4695             :                                 len,
    4696             :                                 0,
    4697             :                                 &status);
    4698             :         } else {
    4699           0 :                 srvstr_get_path(ctx,
    4700             :                                 pdata,
    4701           0 :                                 req->flags2,
    4702             :                                 &newname,
    4703             :                                 &pdata[12],
    4704             :                                 len,
    4705             :                                 0,
    4706             :                                 &status);
    4707             :         }
    4708           0 :         if (!NT_STATUS_IS_OK(status)) {
    4709           0 :                 return status;
    4710             :         }
    4711             : 
    4712           0 :         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
    4713             :                                 newname));
    4714             : 
    4715             :         /* Check the new name has no '/' characters. */
    4716           0 :         if (strchr_m(newname, '/')) {
    4717           0 :                 return NT_STATUS_NOT_SUPPORTED;
    4718             :         }
    4719             : 
    4720           0 :         if (fsp && fsp->base_fsp) {
    4721             :                 /* newname must be a stream name. */
    4722           0 :                 if (newname[0] != ':') {
    4723           0 :                         return NT_STATUS_NOT_SUPPORTED;
    4724             :                 }
    4725             : 
    4726             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    4727           0 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    4728           0 :                                         fsp->base_fsp->fsp_name->base_name,
    4729             :                                         newname,
    4730             :                                         NULL,
    4731           0 :                                         fsp->base_fsp->fsp_name->twrp,
    4732           0 :                                         fsp->base_fsp->fsp_name->flags);
    4733           0 :                 if (smb_fname_dst == NULL) {
    4734           0 :                         status = NT_STATUS_NO_MEMORY;
    4735           0 :                         goto out;
    4736             :                 }
    4737             : 
    4738             :                 /*
    4739             :                  * Get the original last component, since
    4740             :                  * rename_internals_fsp() requires it.
    4741             :                  */
    4742           0 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    4743             :                                         conn,
    4744             :                                         newname,
    4745             :                                         0);
    4746           0 :                 if (dst_original_lcomp == NULL) {
    4747           0 :                         status = NT_STATUS_NO_MEMORY;
    4748           0 :                         goto out;
    4749             :                 }
    4750             : 
    4751             :         } else {
    4752             :                 /*
    4753             :                  * Build up an smb_fname_dst based on the filename passed in.
    4754             :                  * We basically just strip off the last component, and put on
    4755             :                  * the newname instead.
    4756             :                  */
    4757           0 :                 char *base_name = NULL;
    4758           0 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4759           0 :                 NTTIME dst_twrp = 0;
    4760             : 
    4761             :                 /* newname must *not* be a stream name. */
    4762           0 :                 if (newname[0] == ':') {
    4763           0 :                         return NT_STATUS_NOT_SUPPORTED;
    4764             :                 }
    4765             : 
    4766             :                 /*
    4767             :                  * Strip off the last component (filename) of the path passed
    4768             :                  * in.
    4769             :                  */
    4770           0 :                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
    4771           0 :                 if (!base_name) {
    4772           0 :                         return NT_STATUS_NO_MEMORY;
    4773             :                 }
    4774           0 :                 p = strrchr_m(base_name, '/');
    4775           0 :                 if (p) {
    4776           0 :                         p[1] = '\0';
    4777             :                 } else {
    4778           0 :                         base_name = talloc_strdup(ctx, "");
    4779           0 :                         if (!base_name) {
    4780           0 :                                 return NT_STATUS_NO_MEMORY;
    4781             :                         }
    4782             :                 }
    4783             :                 /* Append the new name. */
    4784           0 :                 base_name = talloc_asprintf_append(base_name,
    4785             :                                 "%s",
    4786             :                                 newname);
    4787           0 :                 if (!base_name) {
    4788           0 :                         return NT_STATUS_NO_MEMORY;
    4789             :                 }
    4790             : 
    4791           0 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
    4792           0 :                         extract_snapshot_token(base_name, &dst_twrp);
    4793             :                 }
    4794           0 :                 status = filename_convert_dirfsp(ctx,
    4795             :                                          conn,
    4796             :                                          base_name,
    4797             :                                          ucf_flags,
    4798             :                                          dst_twrp,
    4799             :                                          &dst_dirfsp,
    4800             :                                          &smb_fname_dst);
    4801             : 
    4802           0 :                 if (!NT_STATUS_IS_OK(status)) {
    4803           0 :                         goto out;
    4804             :                 }
    4805           0 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    4806             :                                         conn,
    4807             :                                         newname,
    4808             :                                         ucf_flags);
    4809           0 :                 if (dst_original_lcomp == NULL) {
    4810           0 :                         status = NT_STATUS_NO_MEMORY;
    4811           0 :                         goto out;
    4812             :                 }
    4813             :         }
    4814             : 
    4815           0 :         if (fsp != NULL && fsp->fsp_flags.is_fsa) {
    4816           0 :                 DEBUG(10,("smb_file_rename_information: "
    4817             :                           "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    4818             :                           fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    4819             :                           smb_fname_str_dbg(smb_fname_dst)));
    4820           0 :                 status = rename_internals_fsp(conn,
    4821             :                                         fsp,
    4822             :                                         dst_dirfsp,
    4823             :                                         smb_fname_dst,
    4824             :                                         dst_original_lcomp,
    4825             :                                         0,
    4826             :                                         overwrite);
    4827             :         } else {
    4828           0 :                 DEBUG(10,("smb_file_rename_information: "
    4829             :                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
    4830             :                           smb_fname_str_dbg(smb_fname_src),
    4831             :                           smb_fname_str_dbg(smb_fname_dst)));
    4832           0 :                 status = rename_internals(ctx,
    4833             :                                         conn,
    4834             :                                         req,
    4835             :                                         NULL, /* src_dirfsp */
    4836             :                                         smb_fname_src,
    4837             :                                         dst_dirfsp,
    4838             :                                         smb_fname_dst,
    4839             :                                         dst_original_lcomp,
    4840             :                                         0,
    4841             :                                         overwrite,
    4842             :                                         FILE_WRITE_ATTRIBUTES);
    4843             :         }
    4844           0 :  out:
    4845           0 :         TALLOC_FREE(smb_fname_dst);
    4846           0 :         return status;
    4847             : }
    4848             : 
    4849             : /****************************************************************************
    4850             :  Deal with SMB_SET_FILE_BASIC_INFO.
    4851             : ****************************************************************************/
    4852             : 
    4853          63 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
    4854             :                                         const char *pdata,
    4855             :                                         int total_data,
    4856             :                                         files_struct *fsp,
    4857             :                                         struct smb_filename *smb_fname)
    4858             : {
    4859             :         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
    4860             :         struct smb_file_time ft;
    4861          63 :         uint32_t dosmode = 0;
    4862          63 :         NTSTATUS status = NT_STATUS_OK;
    4863             : 
    4864          63 :         init_smb_file_time(&ft);
    4865             : 
    4866          63 :         if (total_data < 36) {
    4867           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4868             :         }
    4869             : 
    4870          63 :         if (fsp == NULL) {
    4871           0 :                 return NT_STATUS_INVALID_HANDLE;
    4872             :         }
    4873             : 
    4874          63 :         status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    4875          63 :         if (!NT_STATUS_IS_OK(status)) {
    4876           0 :                 return status;
    4877             :         }
    4878             : 
    4879             :         /* Set the attributes */
    4880          63 :         dosmode = IVAL(pdata,32);
    4881          63 :         status = smb_set_file_dosmode(conn, fsp, dosmode);
    4882          63 :         if (!NT_STATUS_IS_OK(status)) {
    4883           1 :                 return status;
    4884             :         }
    4885             : 
    4886             :         /* create time */
    4887          62 :         ft.create_time = pull_long_date_full_timespec(pdata);
    4888             : 
    4889             :         /* access time */
    4890          62 :         ft.atime = pull_long_date_full_timespec(pdata+8);
    4891             : 
    4892             :         /* write time. */
    4893          62 :         ft.mtime = pull_long_date_full_timespec(pdata+16);
    4894             : 
    4895             :         /* change time. */
    4896          62 :         ft.ctime = pull_long_date_full_timespec(pdata+24);
    4897             : 
    4898          62 :         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
    4899             :                    smb_fname_str_dbg(smb_fname)));
    4900             : 
    4901          62 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    4902          62 :         if (!NT_STATUS_IS_OK(status)) {
    4903           0 :                 return status;
    4904             :         }
    4905             : 
    4906          62 :         if (fsp->fsp_flags.modified) {
    4907           1 :                 trigger_write_time_update_immediate(fsp);
    4908             :         }
    4909          62 :         return NT_STATUS_OK;
    4910             : }
    4911             : 
    4912             : /****************************************************************************
    4913             :  Deal with SMB_INFO_STANDARD.
    4914             : ****************************************************************************/
    4915             : 
    4916           0 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
    4917             :                                         const char *pdata,
    4918             :                                         int total_data,
    4919             :                                         files_struct *fsp,
    4920             :                                         struct smb_filename *smb_fname)
    4921             : {
    4922             :         NTSTATUS status;
    4923             :         struct smb_file_time ft;
    4924             : 
    4925           0 :         init_smb_file_time(&ft);
    4926             : 
    4927           0 :         if (total_data < 12) {
    4928           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4929             :         }
    4930             : 
    4931           0 :         if (fsp == NULL) {
    4932           0 :                 return NT_STATUS_INVALID_HANDLE;
    4933             :         }
    4934             : 
    4935             :         /* create time */
    4936           0 :         ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
    4937             :         /* access time */
    4938           0 :         ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
    4939             :         /* write time */
    4940           0 :         ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
    4941             : 
    4942           0 :         DEBUG(10,("smb_set_info_standard: file %s\n",
    4943             :                 smb_fname_str_dbg(smb_fname)));
    4944             : 
    4945           0 :         status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    4946           0 :         if (!NT_STATUS_IS_OK(status)) {
    4947           0 :                 return status;
    4948             :         }
    4949             : 
    4950           0 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    4951           0 :         if (!NT_STATUS_IS_OK(status)) {
    4952           0 :                 return status;
    4953             :         }
    4954             : 
    4955           0 :         if (fsp->fsp_flags.modified) {
    4956           0 :                 trigger_write_time_update_immediate(fsp);
    4957             :         }
    4958           0 :         return NT_STATUS_OK;
    4959             : }
    4960             : 
    4961             : /****************************************************************************
    4962             :  Deal with SMB_SET_FILE_ALLOCATION_INFO.
    4963             : ****************************************************************************/
    4964             : 
    4965           0 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
    4966             :                                              struct smb_request *req,
    4967             :                                         const char *pdata,
    4968             :                                         int total_data,
    4969             :                                         files_struct *fsp,
    4970             :                                         struct smb_filename *smb_fname)
    4971             : {
    4972           0 :         uint64_t allocation_size = 0;
    4973           0 :         NTSTATUS status = NT_STATUS_OK;
    4974           0 :         files_struct *new_fsp = NULL;
    4975             : 
    4976           0 :         if (!VALID_STAT(smb_fname->st)) {
    4977           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4978             :         }
    4979             : 
    4980           0 :         if (total_data < 8) {
    4981           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4982             :         }
    4983             : 
    4984           0 :         allocation_size = (uint64_t)IVAL(pdata,0);
    4985           0 :         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
    4986           0 :         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
    4987             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    4988             :                   (double)allocation_size));
    4989             : 
    4990           0 :         if (allocation_size) {
    4991           0 :                 allocation_size = smb_roundup(conn, allocation_size);
    4992             :         }
    4993             : 
    4994           0 :         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
    4995             :                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
    4996             :                   (double)allocation_size));
    4997             : 
    4998           0 :         if (fsp &&
    4999           0 :             !fsp->fsp_flags.is_pathref &&
    5000           0 :             fsp_get_io_fd(fsp) != -1)
    5001             :         {
    5002             :                 /* Open file handle. */
    5003           0 :                 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
    5004           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5005           0 :                         return status;
    5006             :                 }
    5007             : 
    5008             :                 /* Only change if needed. */
    5009           0 :                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    5010           0 :                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
    5011           0 :                                 return map_nt_error_from_unix(errno);
    5012             :                         }
    5013             :                 }
    5014             :                 /* But always update the time. */
    5015             :                 /*
    5016             :                  * This is equivalent to a write. Ensure it's seen immediately
    5017             :                  * if there are no pending writes.
    5018             :                  */
    5019           0 :                 trigger_write_time_update_immediate(fsp);
    5020           0 :                 return NT_STATUS_OK;
    5021             :         }
    5022             : 
    5023             :         /* Pathname or stat or directory file. */
    5024           0 :         status = SMB_VFS_CREATE_FILE(
    5025             :                 conn,                                   /* conn */
    5026             :                 req,                                    /* req */
    5027             :                 NULL,                                   /* dirfsp */
    5028             :                 smb_fname,                              /* fname */
    5029             :                 FILE_WRITE_DATA,                        /* access_mask */
    5030             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    5031             :                     FILE_SHARE_DELETE),
    5032             :                 FILE_OPEN,                              /* create_disposition*/
    5033             :                 0,                                      /* create_options */
    5034             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    5035             :                 0,                                      /* oplock_request */
    5036             :                 NULL,                                   /* lease */
    5037             :                 0,                                      /* allocation_size */
    5038             :                 0,                                      /* private_flags */
    5039             :                 NULL,                                   /* sd */
    5040             :                 NULL,                                   /* ea_list */
    5041             :                 &new_fsp,                           /* result */
    5042             :                 NULL,                                   /* pinfo */
    5043             :                 NULL, NULL);                            /* create context */
    5044             : 
    5045           0 :         if (!NT_STATUS_IS_OK(status)) {
    5046             :                 /* NB. We check for open_was_deferred in the caller. */
    5047           0 :                 return status;
    5048             :         }
    5049             : 
    5050             :         /* Only change if needed. */
    5051           0 :         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    5052           0 :                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
    5053           0 :                         status = map_nt_error_from_unix(errno);
    5054           0 :                         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    5055           0 :                         return status;
    5056             :                 }
    5057             :         }
    5058             : 
    5059             :         /* Changing the allocation size should set the last mod time. */
    5060             :         /*
    5061             :          * This is equivalent to a write. Ensure it's seen immediately
    5062             :          * if there are no pending writes.
    5063             :          */
    5064           0 :         trigger_write_time_update_immediate(new_fsp);
    5065           0 :         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    5066           0 :         return NT_STATUS_OK;
    5067             : }
    5068             : 
    5069             : /****************************************************************************
    5070             :  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
    5071             : ****************************************************************************/
    5072             : 
    5073           0 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
    5074             :                                               struct smb_request *req,
    5075             :                                         const char *pdata,
    5076             :                                         int total_data,
    5077             :                                         files_struct *fsp,
    5078             :                                         struct smb_filename *smb_fname,
    5079             :                                         bool fail_after_createfile)
    5080             : {
    5081             :         off_t size;
    5082             : 
    5083           0 :         if (total_data < 8) {
    5084           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5085             :         }
    5086             : 
    5087           0 :         size = IVAL(pdata,0);
    5088           0 :         size |= (((off_t)IVAL(pdata,4)) << 32);
    5089           0 :         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
    5090             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    5091             :                   (double)size));
    5092             : 
    5093           0 :         return smb_set_file_size(conn, req,
    5094             :                                 fsp,
    5095             :                                 smb_fname,
    5096           0 :                                 &smb_fname->st,
    5097             :                                 size,
    5098             :                                 fail_after_createfile);
    5099             : }
    5100             : 
    5101         894 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
    5102             :                                 struct smb_request *req,
    5103             :                                 TALLOC_CTX *mem_ctx,
    5104             :                                 uint16_t info_level,
    5105             :                                 files_struct *fsp,
    5106             :                                 struct smb_filename *smb_fname,
    5107             :                                 char **ppdata, int total_data,
    5108             :                                 int *ret_data_size)
    5109             : {
    5110         894 :         char *pdata = *ppdata;
    5111         894 :         NTSTATUS status = NT_STATUS_OK;
    5112         894 :         int data_return_size = 0;
    5113             : 
    5114         894 :         *ret_data_size = 0;
    5115             : 
    5116         894 :         DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
    5117             :                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
    5118             :                  fsp_fnum_dbg(fsp),
    5119             :                  info_level, total_data));
    5120             : 
    5121         894 :         switch (info_level) {
    5122             : 
    5123           0 :                 case SMB_INFO_STANDARD:
    5124             :                 {
    5125           0 :                         status = smb_set_info_standard(conn,
    5126             :                                         pdata,
    5127             :                                         total_data,
    5128             :                                         fsp,
    5129             :                                         smb_fname);
    5130           0 :                         break;
    5131             :                 }
    5132             : 
    5133           0 :                 case SMB_INFO_SET_EA:
    5134             :                 {
    5135           0 :                         status = smb_info_set_ea(conn,
    5136             :                                                 pdata,
    5137             :                                                 total_data,
    5138             :                                                 fsp,
    5139             :                                                 smb_fname);
    5140           0 :                         break;
    5141             :                 }
    5142             : 
    5143          63 :                 case SMB_SET_FILE_BASIC_INFO:
    5144             :                 case SMB_FILE_BASIC_INFORMATION:
    5145             :                 {
    5146          63 :                         status = smb_set_file_basic_info(conn,
    5147             :                                                         pdata,
    5148             :                                                         total_data,
    5149             :                                                         fsp,
    5150             :                                                         smb_fname);
    5151          63 :                         break;
    5152             :                 }
    5153             : 
    5154           0 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    5155             :                 case SMB_SET_FILE_ALLOCATION_INFO:
    5156             :                 {
    5157           0 :                         status = smb_set_file_allocation_info(conn, req,
    5158             :                                                                 pdata,
    5159             :                                                                 total_data,
    5160             :                                                                 fsp,
    5161             :                                                                 smb_fname);
    5162           0 :                         break;
    5163             :                 }
    5164             : 
    5165           0 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    5166             :                 case SMB_SET_FILE_END_OF_FILE_INFO:
    5167             :                 {
    5168             :                         /*
    5169             :                          * XP/Win7 both fail after the createfile with
    5170             :                          * SMB_SET_FILE_END_OF_FILE_INFO but not
    5171             :                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
    5172             :                          * The level is known here, so pass it down
    5173             :                          * appropriately.
    5174             :                          */
    5175           0 :                         bool should_fail =
    5176             :                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
    5177             : 
    5178           0 :                         status = smb_set_file_end_of_file_info(conn, req,
    5179             :                                                                 pdata,
    5180             :                                                                 total_data,
    5181             :                                                                 fsp,
    5182             :                                                                 smb_fname,
    5183             :                                                                 should_fail);
    5184           0 :                         break;
    5185             :                 }
    5186             : 
    5187         806 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    5188             :                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
    5189             :                 {
    5190             : #if 0
    5191             :                         /* JRA - We used to just ignore this on a path ?
    5192             :                          * Shouldn't this be invalid level on a pathname
    5193             :                          * based call ?
    5194             :                          */
    5195             :                         if (tran_call != TRANSACT2_SETFILEINFO) {
    5196             :                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
    5197             :                         }
    5198             : #endif
    5199         806 :                         status = smb_set_file_disposition_info(conn,
    5200             :                                                 pdata,
    5201             :                                                 total_data,
    5202             :                                                 fsp,
    5203             :                                                 smb_fname);
    5204         806 :                         break;
    5205             :                 }
    5206             : 
    5207           0 :                 case SMB_FILE_POSITION_INFORMATION:
    5208             :                 {
    5209           0 :                         status = smb_file_position_information(conn,
    5210             :                                                 pdata,
    5211             :                                                 total_data,
    5212             :                                                 fsp);
    5213           0 :                         break;
    5214             :                 }
    5215             : 
    5216           0 :                 case SMB_FILE_FULL_EA_INFORMATION:
    5217             :                 {
    5218           0 :                         status = smb_set_file_full_ea_info(conn,
    5219             :                                                 pdata,
    5220             :                                                 total_data,
    5221             :                                                 fsp);
    5222           0 :                         break;
    5223             :                 }
    5224             : 
    5225             :                 /* From tridge Samba4 :
    5226             :                  * MODE_INFORMATION in setfileinfo (I have no
    5227             :                  * idea what "mode information" on a file is - it takes a value of 0,
    5228             :                  * 2, 4 or 6. What could it be?).
    5229             :                  */
    5230             : 
    5231           0 :                 case SMB_FILE_MODE_INFORMATION:
    5232             :                 {
    5233           0 :                         status = smb_file_mode_information(conn,
    5234             :                                                 pdata,
    5235             :                                                 total_data);
    5236           0 :                         break;
    5237             :                 }
    5238             : 
    5239             :                 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
    5240           0 :                 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
    5241             :                 case SMB_FILE_SHORT_NAME_INFORMATION:
    5242           0 :                         return NT_STATUS_NOT_SUPPORTED;
    5243             : 
    5244           0 :                 case SMB_FILE_RENAME_INFORMATION:
    5245             :                 {
    5246           0 :                         status = smb_file_rename_information(conn, req,
    5247             :                                                              pdata, total_data,
    5248             :                                                              fsp, smb_fname);
    5249           0 :                         break;
    5250             :                 }
    5251             : 
    5252          21 :                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
    5253             :                 {
    5254             :                         /* SMB2 rename information. */
    5255          21 :                         status = smb2_file_rename_information(conn, req,
    5256             :                                                              pdata, total_data,
    5257             :                                                              fsp, smb_fname);
    5258          21 :                         break;
    5259             :                 }
    5260             : 
    5261           4 :                 case SMB_FILE_LINK_INFORMATION:
    5262             :                 {
    5263           4 :                         status = smb_file_link_information(conn, req,
    5264             :                                                         pdata, total_data,
    5265             :                                                         fsp, smb_fname);
    5266           4 :                         break;
    5267             :                 }
    5268             : 
    5269           0 :                 default:
    5270           0 :                         return NT_STATUS_INVALID_LEVEL;
    5271             :         }
    5272             : 
    5273         894 :         if (!NT_STATUS_IS_OK(status)) {
    5274           6 :                 return status;
    5275             :         }
    5276             : 
    5277         888 :         *ret_data_size = data_return_size;
    5278         888 :         return NT_STATUS_OK;
    5279             : }
    5280             : 
    5281           4 : static uint32_t generate_volume_serial_number(
    5282             :                         const struct loadparm_substitution *lp_sub,
    5283             :                         int snum)
    5284             : {
    5285           4 :         int serial = lp_volume_serial_number(snum);
    5286           8 :         return serial != -1 ? serial:
    5287           4 :                 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
    5288           4 :                 (str_checksum(get_local_machine_name())<<16);
    5289             : }

Generated by: LCOV version 1.14