LCOV - code coverage report
Current view: top level - source3/smbd - smb2_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 1942 2430 79.9 %
Date: 2024-02-28 12:06:22 Functions: 49 52 94.2 %

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

Generated by: LCOV version 1.14