LCOV - code coverage report
Current view: top level - source3/smbd - smb2_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for smb2.twrp.listdir_fix f886ca1c Lines: 1939 2424 80.0 %
Date: 2023-11-07 19:11:32 Functions: 50 53 94.3 %

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

Generated by: LCOV version 1.14