LCOV - code coverage report
Current view: top level - source3/smbd - smb2_trans2.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 864 3073 28.1 %
Date: 2024-06-13 04:01:37 Functions: 29 67 43.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB transaction2 handling
       4             :    Copyright (C) Jeremy Allison                 1994-2007
       5             :    Copyright (C) Stefan (metze) Metzmacher      2003
       6             :    Copyright (C) Volker Lendecke                2005-2007
       7             :    Copyright (C) Steve French                   2005
       8             :    Copyright (C) James Peach                    2006-2007
       9             : 
      10             :    Extensively modified by Andrew Tridgell, 1995
      11             : 
      12             :    This program is free software; you can redistribute it and/or modify
      13             :    it under the terms of the GNU General Public License as published by
      14             :    the Free Software Foundation; either version 3 of the License, or
      15             :    (at your option) any later version.
      16             : 
      17             :    This program is distributed in the hope that it will be useful,
      18             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      19             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      20             :    GNU General Public License for more details.
      21             : 
      22             :    You should have received a copy of the GNU General Public License
      23             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      24             : */
      25             : 
      26             : #include "includes.h"
      27             : #include "ntioctl.h"
      28             : #include "system/filesys.h"
      29             : #include "lib/util/time_basic.h"
      30             : #include "version.h"
      31             : #include "smbd/smbd.h"
      32             : #include "smbd/globals.h"
      33             : #include "../libcli/auth/libcli_auth.h"
      34             : #include "../librpc/gen_ndr/xattr.h"
      35             : #include "../librpc/gen_ndr/ndr_security.h"
      36             : #include "libcli/security/security.h"
      37             : #include "trans2.h"
      38             : #include "auth.h"
      39             : #include "smbprofile.h"
      40             : #include "rpc_server/srv_pipe_hnd.h"
      41             : #include "printing.h"
      42             : #include "lib/util_ea.h"
      43             : #include "lib/readdir_attr.h"
      44             : #include "messages.h"
      45             : #include "libcli/smb/smb2_posix.h"
      46             : #include "lib/util/string_wrappers.h"
      47             : #include "source3/lib/substitute.h"
      48             : #include "source3/lib/adouble.h"
      49             : 
      50             : #define DIR_ENTRY_SAFETY_MARGIN 4096
      51             : 
      52             : static char *store_file_unix_basic(connection_struct *conn,
      53             :                                 char *pdata,
      54             :                                 files_struct *fsp,
      55             :                                 const SMB_STRUCT_STAT *psbuf);
      56             : 
      57             : static char *store_file_unix_basic_info2(connection_struct *conn,
      58             :                                 char *pdata,
      59             :                                 files_struct *fsp,
      60             :                                 const SMB_STRUCT_STAT *psbuf);
      61             : 
      62             : static uint32_t generate_volume_serial_number(
      63             :                                 const struct loadparm_substitution *lp_sub,
      64             :                                 int snum);
      65             : 
      66             : /****************************************************************************
      67             :  Check if an open file handle is a symlink.
      68             : ****************************************************************************/
      69             : 
      70         464 : NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
      71             : {
      72             : 
      73         464 :         if (!VALID_STAT(fsp->fsp_name->st)) {
      74           0 :                 return NT_STATUS_ACCESS_DENIED;
      75             :         }
      76         464 :         if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
      77           0 :                 return NT_STATUS_ACCESS_DENIED;
      78             :         }
      79         464 :         if (fsp_get_pathref_fd(fsp) == -1) {
      80           0 :                 return NT_STATUS_ACCESS_DENIED;
      81             :         }
      82         464 :         return NT_STATUS_OK;
      83             : }
      84             : 
      85          64 : NTSTATUS check_access_fsp(struct files_struct *fsp,
      86             :                           uint32_t access_mask)
      87             : {
      88          64 :         if (!fsp->fsp_flags.is_fsa) {
      89           0 :                 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
      90             :                                                     fsp,
      91             :                                                     false,
      92             :                                                     access_mask);
      93             :         }
      94          64 :         if (!(fsp->access_mask & access_mask)) {
      95           0 :                 return NT_STATUS_ACCESS_DENIED;
      96             :         }
      97          64 :         return NT_STATUS_OK;
      98             : }
      99             : 
     100             : #if defined(HAVE_POSIX_ACLS)
     101             : /****************************************************************************
     102             :  Utility function to open a fsp for a POSIX handle operation.
     103             : ****************************************************************************/
     104             : 
     105           0 : static NTSTATUS get_posix_fsp(connection_struct *conn,
     106             :                         struct smb_request *req,
     107             :                         struct smb_filename *smb_fname,
     108             :                         uint32_t access_mask,
     109             :                         files_struct **ret_fsp)
     110             : {
     111             :         NTSTATUS status;
     112           0 :         uint32_t create_disposition = FILE_OPEN;
     113           0 :         uint32_t share_access = FILE_SHARE_READ|
     114             :                                 FILE_SHARE_WRITE|
     115             :                                 FILE_SHARE_DELETE;
     116           0 :         struct smb2_create_blobs *posx = NULL;
     117             : 
     118             :         /*
     119             :          * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
     120             :          * but set reasonable defaults.
     121             :          */
     122           0 :         uint32_t file_attributes = 0664;
     123           0 :         uint32_t oplock = NO_OPLOCK;
     124           0 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
     125             : 
     126             :         /* File or directory must exist. */
     127           0 :         if (!VALID_STAT(smb_fname->st)) {
     128           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
     129             :         }
     130             :         /* Cannot be a symlink. */
     131           0 :         if (S_ISLNK(smb_fname->st.st_ex_mode)) {
     132           0 :                 return NT_STATUS_ACCESS_DENIED;
     133             :         }
     134             :         /* Set options correctly for directory open. */
     135           0 :         if (S_ISDIR(smb_fname->st.st_ex_mode)) {
     136             :                 /*
     137             :                  * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
     138             :                  * directories, but set reasonable defaults.
     139             :                  */
     140           0 :                 file_attributes = 0775;
     141           0 :                 create_options = FILE_DIRECTORY_FILE;
     142             :         }
     143             : 
     144           0 :         status = make_smb2_posix_create_ctx(
     145             :                 talloc_tos(), &posx, file_attributes);
     146           0 :         if (!NT_STATUS_IS_OK(status)) {
     147           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
     148             :                             nt_errstr(status));
     149           0 :                 goto done;
     150             :         }
     151             : 
     152           0 :         status = SMB_VFS_CREATE_FILE(
     153             :                 conn,           /* conn */
     154             :                 req,            /* req */
     155             :                 NULL,           /* dirfsp */
     156             :                 smb_fname,      /* fname */
     157             :                 access_mask,    /* access_mask */
     158             :                 share_access,   /* share_access */
     159             :                 create_disposition,/* create_disposition*/
     160             :                 create_options, /* create_options */
     161             :                 file_attributes,/* file_attributes */
     162             :                 oplock,         /* oplock_request */
     163             :                 NULL,           /* lease */
     164             :                 0,              /* allocation_size */
     165             :                 0,              /* private_flags */
     166             :                 NULL,           /* sd */
     167             :                 NULL,           /* ea_list */
     168             :                 ret_fsp,        /* result */
     169             :                 NULL,           /* pinfo */
     170             :                 posx,           /* in_context */
     171             :                 NULL);          /* out_context */
     172             : 
     173           0 : done:
     174           0 :         TALLOC_FREE(posx);
     175           0 :         return status;
     176             : }
     177             : #endif
     178             : 
     179             : /********************************************************************
     180             :  Roundup a value to the nearest allocation roundup size boundary.
     181             :  Only do this for Windows clients.
     182             : ********************************************************************/
     183             : 
     184        9637 : uint64_t smb_roundup(connection_struct *conn, uint64_t val)
     185             : {
     186        9637 :         uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
     187             : 
     188             :         /* Only roundup for Windows clients. */
     189        9637 :         enum remote_arch_types ra_type = get_remote_arch();
     190        9637 :         if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
     191           0 :                 val = SMB_ROUNDUP(val,rval);
     192             :         }
     193        9637 :         return val;
     194             : }
     195             : 
     196             : /****************************************************************************
     197             :  Utility functions for dealing with extended attributes.
     198             : ****************************************************************************/
     199             : 
     200             : /****************************************************************************
     201             :  Refuse to allow clients to overwrite our private xattrs.
     202             : ****************************************************************************/
     203             : 
     204        4543 : bool samba_private_attr_name(const char *unix_ea_name)
     205             : {
     206             :         static const char * const prohibited_ea_names[] = {
     207             :                 SAMBA_POSIX_INHERITANCE_EA_NAME,
     208             :                 SAMBA_XATTR_DOS_ATTRIB,
     209             :                 SAMBA_XATTR_MARKER,
     210             :                 XATTR_NTACL_NAME,
     211             :                 AFPINFO_EA_NETATALK,
     212             :                 NULL
     213             :         };
     214             : 
     215             :         int i;
     216             : 
     217        9630 :         for (i = 0; prohibited_ea_names[i]; i++) {
     218        9601 :                 if (strequal( prohibited_ea_names[i], unix_ea_name))
     219        4514 :                         return true;
     220             :         }
     221          29 :         if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
     222             :                         strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
     223          24 :                 return true;
     224             :         }
     225           5 :         return false;
     226             : }
     227             : 
     228             : /****************************************************************************
     229             :  Get one EA value. Fill in a struct ea_struct.
     230             : ****************************************************************************/
     231             : 
     232          79 : NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
     233             :                           files_struct *fsp,
     234             :                           const char *ea_name,
     235             :                           struct ea_struct *pea)
     236             : {
     237             :         /* Get the value of this xattr. Max size is 64k. */
     238          79 :         size_t attr_size = 256;
     239          79 :         char *val = NULL;
     240             :         ssize_t sizeret;
     241          79 :         size_t max_xattr_size = 0;
     242             : 
     243          79 :         if (fsp == NULL) {
     244           0 :                 return NT_STATUS_INVALID_HANDLE;
     245             :         }
     246             : 
     247          79 :         max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
     248             : 
     249          79 :  again:
     250             : 
     251          79 :         val = talloc_realloc(mem_ctx, val, char, attr_size);
     252          79 :         if (!val) {
     253           0 :                 return NT_STATUS_NO_MEMORY;
     254             :         }
     255             : 
     256          79 :         sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
     257          79 :         if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
     258           0 :                 attr_size = max_xattr_size;
     259           0 :                 goto again;
     260             :         }
     261             : 
     262          79 :         if (sizeret == -1) {
     263           8 :                 return map_nt_error_from_unix(errno);
     264             :         }
     265             : 
     266          71 :         DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
     267          71 :         dump_data(10, (uint8_t *)val, sizeret);
     268             : 
     269          71 :         pea->flags = 0;
     270          71 :         if (strnequal(ea_name, "user.", 5)) {
     271          71 :                 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
     272             :         } else {
     273           0 :                 pea->name = talloc_strdup(mem_ctx, ea_name);
     274             :         }
     275          71 :         if (pea->name == NULL) {
     276           0 :                 TALLOC_FREE(val);
     277           0 :                 return NT_STATUS_NO_MEMORY;
     278             :         }
     279          71 :         pea->value.data = (unsigned char *)val;
     280          71 :         pea->value.length = (size_t)sizeret;
     281          71 :         return NT_STATUS_OK;
     282             : }
     283             : 
     284       10360 : NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
     285             :                                 files_struct *fsp,
     286             :                                 char ***pnames,
     287             :                                 size_t *pnum_names)
     288             : {
     289             :         char smallbuf[1024];
     290             :         /* Get a list of all xattrs. Max namesize is 64k. */
     291       10360 :         size_t ea_namelist_size = 1024;
     292       10360 :         char *ea_namelist = smallbuf;
     293       10360 :         char *to_free = NULL;
     294             : 
     295             :         char *p;
     296             :         char **names;
     297             :         size_t num_names;
     298       10360 :         ssize_t sizeret = -1;
     299             :         NTSTATUS status;
     300             : 
     301       10360 :         if (pnames) {
     302       10360 :                 *pnames = NULL;
     303             :         }
     304       10360 :         *pnum_names = 0;
     305             : 
     306       10360 :         if (fsp == NULL) {
     307             :                 /*
     308             :                  * Callers may pass fsp == NULL when passing smb_fname->fsp of a
     309             :                  * symlink. This is ok, handle it here, by just return no EA's
     310             :                  * on a symlink.
     311             :                  */
     312           0 :                 return NT_STATUS_OK;
     313             :         }
     314             : 
     315             :         /* should be the case that fsp != NULL */
     316       10360 :         SMB_ASSERT(fsp != NULL);
     317             : 
     318       10360 :         sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     319             :                                      ea_namelist_size);
     320             : 
     321       10360 :         if ((sizeret == -1) && (errno == ERANGE)) {
     322           0 :                 ea_namelist_size = 65536;
     323           0 :                 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
     324           0 :                 if (ea_namelist == NULL) {
     325           0 :                         return NT_STATUS_NO_MEMORY;
     326             :                 }
     327           0 :                 to_free = ea_namelist;
     328             : 
     329           0 :                 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
     330             :                                              ea_namelist_size);
     331             :         }
     332             : 
     333       10360 :         if (sizeret == -1) {
     334           0 :                 status = map_nt_error_from_unix(errno);
     335           0 :                 TALLOC_FREE(to_free);
     336           0 :                 return status;
     337             :         }
     338             : 
     339       10360 :         DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
     340             : 
     341       10360 :         if (sizeret == 0) {
     342        5338 :                 TALLOC_FREE(to_free);
     343        5338 :                 return NT_STATUS_OK;
     344             :         }
     345             : 
     346             :         /*
     347             :          * Ensure the result is 0-terminated
     348             :          */
     349             : 
     350        5022 :         if (ea_namelist[sizeret-1] != '\0') {
     351           0 :                 TALLOC_FREE(to_free);
     352           0 :                 return NT_STATUS_INTERNAL_ERROR;
     353             :         }
     354             : 
     355             :         /*
     356             :          * count the names
     357             :          */
     358        5022 :         num_names = 0;
     359             : 
     360       26875 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     361       21853 :                 num_names += 1;
     362             :         }
     363             : 
     364        5022 :         *pnum_names = num_names;
     365             : 
     366        5022 :         if (pnames == NULL) {
     367           0 :                 TALLOC_FREE(to_free);
     368           0 :                 return NT_STATUS_OK;
     369             :         }
     370             : 
     371        5022 :         names = talloc_array(mem_ctx, char *, num_names);
     372        5022 :         if (names == NULL) {
     373           0 :                 DEBUG(0, ("talloc failed\n"));
     374           0 :                 TALLOC_FREE(to_free);
     375           0 :                 return NT_STATUS_NO_MEMORY;
     376             :         }
     377             : 
     378        5022 :         if (ea_namelist == smallbuf) {
     379        5022 :                 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
     380        5022 :                 if (ea_namelist == NULL) {
     381           0 :                         TALLOC_FREE(names);
     382           0 :                         return NT_STATUS_NO_MEMORY;
     383             :                 }
     384             :         } else {
     385           0 :                 talloc_steal(names, ea_namelist);
     386             : 
     387           0 :                 ea_namelist = talloc_realloc(names, ea_namelist, char,
     388             :                                              sizeret);
     389           0 :                 if (ea_namelist == NULL) {
     390           0 :                         TALLOC_FREE(names);
     391           0 :                         return NT_STATUS_NO_MEMORY;
     392             :                 }
     393             :         }
     394             : 
     395        5022 :         num_names = 0;
     396             : 
     397       26875 :         for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
     398       21853 :                 names[num_names++] = p;
     399             :         }
     400             : 
     401        5022 :         *pnames = names;
     402             : 
     403        5022 :         return NT_STATUS_OK;
     404             : }
     405             : 
     406             : /****************************************************************************
     407             :  Return a linked list of the total EA's. Plus the total size
     408             : ****************************************************************************/
     409             : 
     410       10348 : static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
     411             :                                 files_struct *fsp,
     412             :                                 size_t *pea_total_len,
     413             :                                 struct ea_list **ea_list)
     414             : {
     415             :         /* Get a list of all xattrs. Max namesize is 64k. */
     416             :         size_t i, num_names;
     417             :         char **names;
     418       10348 :         struct ea_list *ea_list_head = NULL;
     419       10348 :         bool posix_pathnames = false;
     420             :         NTSTATUS status;
     421             : 
     422       10348 :         *pea_total_len = 0;
     423       10348 :         *ea_list = NULL;
     424             : 
     425             :         /* symlink */
     426       10348 :         if (fsp == NULL) {
     427           0 :                 return NT_STATUS_OK;
     428             :         }
     429             : 
     430       10348 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     431           0 :                 return NT_STATUS_OK;
     432             :         }
     433             : 
     434       10348 :         if (fsp_is_alternate_stream(fsp)) {
     435           0 :                 return NT_STATUS_INVALID_PARAMETER;
     436             :         }
     437             : 
     438       10348 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     439             : 
     440       10348 :         status = get_ea_names_from_fsp(talloc_tos(),
     441             :                                 fsp,
     442             :                                 &names,
     443             :                                 &num_names);
     444             : 
     445       10348 :         if (!NT_STATUS_IS_OK(status)) {
     446           0 :                 return status;
     447             :         }
     448             : 
     449       10348 :         if (num_names == 0) {
     450        5338 :                 return NT_STATUS_OK;
     451             :         }
     452             : 
     453       26843 :         for (i=0; i<num_names; i++) {
     454             :                 struct ea_list *listp;
     455             :                 fstring dos_ea_name;
     456             : 
     457             :                 /*
     458             :                  * POSIX EA names are divided into several namespaces by
     459             :                  * means of string prefixes. Usually, the system controls
     460             :                  * semantics for each namespace, but the 'user' namespace is
     461             :                  * available for arbitrary use, which comes closest to
     462             :                  * Windows EA semantics. Hence, we map POSIX EAs from the
     463             :                  * 'user' namespace to Windows EAs, and just ignore all the
     464             :                  * other namespaces. Also, a few specific names in the 'user'
     465             :                  * namespace are used by Samba internally. Filter them out as
     466             :                  * well, and only present the EAs that are available for
     467             :                  * arbitrary use.
     468             :                  */
     469       21833 :                 if (!strnequal(names[i], "user.", 5)
     470        4529 :                     || samba_private_attr_name(names[i]))
     471       41652 :                         continue;
     472             : 
     473             :                 /*
     474             :                  * Filter out any underlying POSIX EA names
     475             :                  * that a Windows client can't handle.
     476             :                  */
     477           6 :                 if (!posix_pathnames &&
     478           3 :                                 is_invalid_windows_ea_name(names[i])) {
     479           0 :                         continue;
     480             :                 }
     481             : 
     482           3 :                 listp = talloc(mem_ctx, struct ea_list);
     483           3 :                 if (listp == NULL) {
     484           0 :                         return NT_STATUS_NO_MEMORY;
     485             :                 }
     486             : 
     487           6 :                 status = get_ea_value_fsp(listp,
     488             :                                           fsp,
     489           3 :                                           names[i],
     490             :                                           &listp->ea);
     491             : 
     492           3 :                 if (!NT_STATUS_IS_OK(status)) {
     493           0 :                         TALLOC_FREE(listp);
     494           0 :                         return status;
     495             :                 }
     496             : 
     497           3 :                 if (listp->ea.value.length == 0) {
     498             :                         /*
     499             :                          * We can never return a zero length EA.
     500             :                          * Windows reports the EA's as corrupted.
     501             :                          */
     502           0 :                         TALLOC_FREE(listp);
     503           0 :                         continue;
     504           3 :                 } else if (listp->ea.value.length > 65536) {
     505             :                         /*
     506             :                          * SMB clients may report error with file
     507             :                          * if large EA is presented to them.
     508             :                          */
     509           0 :                         DBG_ERR("EA [%s] on file [%s] exceeds "
     510             :                                 "maximum permitted EA size of 64KiB: %zu\n.",
     511             :                                 listp->ea.name, fsp_str_dbg(fsp),
     512             :                                 listp->ea.value.length);
     513           0 :                         TALLOC_FREE(listp);
     514           0 :                         continue;
     515             :                 }
     516             : 
     517           3 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     518             : 
     519           6 :                 *pea_total_len +=
     520           3 :                         4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     521             : 
     522           3 :                 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
     523             :                           "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
     524             :                           (unsigned int)listp->ea.value.length));
     525             : 
     526           3 :                 DLIST_ADD_END(ea_list_head, listp);
     527             : 
     528             :         }
     529             : 
     530             :         /* Add on 4 for total length. */
     531        5010 :         if (*pea_total_len) {
     532           2 :                 *pea_total_len += 4;
     533             :         }
     534             : 
     535        5010 :         DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
     536             :                    (unsigned int)*pea_total_len));
     537             : 
     538        5010 :         *ea_list = ea_list_head;
     539        5010 :         return NT_STATUS_OK;
     540             : }
     541             : 
     542             : /****************************************************************************
     543             :  Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
     544             :  that was filled.
     545             : ****************************************************************************/
     546             : 
     547           0 : static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
     548             :         connection_struct *conn, struct ea_list *ea_list)
     549             : {
     550           0 :         unsigned int ret_data_size = 4;
     551           0 :         char *p = pdata;
     552             : 
     553           0 :         SMB_ASSERT(total_data_size >= 4);
     554             : 
     555           0 :         if (!lp_ea_support(SNUM(conn))) {
     556           0 :                 SIVAL(pdata,4,0);
     557           0 :                 return 4;
     558             :         }
     559             : 
     560           0 :         for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
     561             :                 size_t dos_namelen;
     562             :                 fstring dos_ea_name;
     563           0 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     564           0 :                 dos_namelen = strlen(dos_ea_name);
     565           0 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     566             :                         break;
     567             :                 }
     568           0 :                 if (ea_list->ea.value.length > 65535) {
     569           0 :                         break;
     570             :                 }
     571           0 :                 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
     572           0 :                         break;
     573             :                 }
     574             : 
     575             :                 /* We know we have room. */
     576           0 :                 SCVAL(p,0,ea_list->ea.flags);
     577           0 :                 SCVAL(p,1,dos_namelen);
     578           0 :                 SSVAL(p,2,ea_list->ea.value.length);
     579           0 :                 strlcpy(p+4, dos_ea_name, dos_namelen+1);
     580           0 :                 if (ea_list->ea.value.length > 0) {
     581           0 :                         memcpy(p + 4 + dos_namelen + 1,
     582           0 :                                ea_list->ea.value.data,
     583             :                                ea_list->ea.value.length);
     584             :                 }
     585             : 
     586           0 :                 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
     587           0 :                 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
     588             :         }
     589             : 
     590           0 :         ret_data_size = PTR_DIFF(p, pdata);
     591           0 :         DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
     592           0 :         SIVAL(pdata,0,ret_data_size);
     593           0 :         return ret_data_size;
     594             : }
     595             : 
     596       10346 : static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
     597             :                                        char *pdata,
     598             :                                        unsigned int total_data_size,
     599             :                                        unsigned int *ret_data_size,
     600             :                                        connection_struct *conn,
     601             :                                        struct ea_list *ea_list)
     602             : {
     603       10346 :         uint8_t *p = (uint8_t *)pdata;
     604       10346 :         uint8_t *last_start = NULL;
     605       10346 :         bool do_store_data = (pdata != NULL);
     606             : 
     607       10346 :         *ret_data_size = 0;
     608             : 
     609       10346 :         if (!lp_ea_support(SNUM(conn))) {
     610           0 :                 return NT_STATUS_NO_EAS_ON_FILE;
     611             :         }
     612             : 
     613       17781 :         for (; ea_list; ea_list = ea_list->next) {
     614             :                 size_t dos_namelen;
     615             :                 fstring dos_ea_name;
     616             :                 size_t this_size;
     617           2 :                 size_t pad = 0;
     618             : 
     619           2 :                 if (last_start != NULL && do_store_data) {
     620           0 :                         SIVAL(last_start, 0, PTR_DIFF(p, last_start));
     621             :                 }
     622           2 :                 last_start = p;
     623             : 
     624           2 :                 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
     625           2 :                 dos_namelen = strlen(dos_ea_name);
     626           2 :                 if (dos_namelen > 255 || dos_namelen == 0) {
     627           0 :                         return NT_STATUS_INTERNAL_ERROR;
     628             :                 }
     629           2 :                 if (ea_list->ea.value.length > 65535) {
     630           0 :                         return NT_STATUS_INTERNAL_ERROR;
     631             :                 }
     632             : 
     633           2 :                 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
     634             : 
     635           2 :                 if (ea_list->next) {
     636           1 :                         pad = (4 - (this_size % 4)) % 4;
     637           1 :                         this_size += pad;
     638             :                 }
     639             : 
     640           2 :                 if (do_store_data) {
     641           0 :                         if (this_size > total_data_size) {
     642           0 :                                 return NT_STATUS_INFO_LENGTH_MISMATCH;
     643             :                         }
     644             : 
     645             :                         /* We know we have room. */
     646           0 :                         SIVAL(p, 0x00, 0); /* next offset */
     647           0 :                         SCVAL(p, 0x04, ea_list->ea.flags);
     648           0 :                         SCVAL(p, 0x05, dos_namelen);
     649           0 :                         SSVAL(p, 0x06, ea_list->ea.value.length);
     650           0 :                         strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
     651           0 :                         memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
     652           0 :                         if (pad) {
     653           0 :                                 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
     654             :                                         '\0',
     655             :                                         pad);
     656             :                         }
     657           0 :                         total_data_size -= this_size;
     658             :                 }
     659             : 
     660           2 :                 p += this_size;
     661             :         }
     662             : 
     663       10346 :         *ret_data_size = PTR_DIFF(p, pdata);
     664       10346 :         DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
     665       10346 :         return NT_STATUS_OK;
     666             : }
     667             : 
     668       10768 : unsigned int estimate_ea_size(files_struct *fsp)
     669             : {
     670       10768 :         size_t total_ea_len = 0;
     671             :         TALLOC_CTX *mem_ctx;
     672       10768 :         struct ea_list *ea_list = NULL;
     673             :         NTSTATUS status;
     674             : 
     675             :         /* symlink */
     676       10768 :         if (fsp == NULL) {
     677         422 :                 return 0;
     678             :         }
     679             : 
     680       10346 :         if (!lp_ea_support(SNUM(fsp->conn))) {
     681           0 :                 return 0;
     682             :         }
     683             : 
     684       10346 :         mem_ctx = talloc_stackframe();
     685             : 
     686             :         /* If this is a stream fsp, then we need to instead find the
     687             :          * estimated ea len from the main file, not the stream
     688             :          * (streams cannot have EAs), but the estimate isn't just 0 in
     689             :          * this case! */
     690       10346 :         fsp = metadata_fsp(fsp);
     691       10346 :         (void)get_ea_list_from_fsp(mem_ctx,
     692             :                                    fsp,
     693             :                                    &total_ea_len,
     694             :                                    &ea_list);
     695             : 
     696       10346 :         if(fsp->conn->sconn->using_smb2) {
     697             :                 unsigned int ret_data_size;
     698             :                 /*
     699             :                  * We're going to be using fill_ea_chained_buffer() to
     700             :                  * marshall EA's - this size is significantly larger
     701             :                  * than the SMB1 buffer. Re-calculate the size without
     702             :                  * marshalling.
     703             :                  */
     704       17777 :                 status = fill_ea_chained_buffer(mem_ctx,
     705             :                                                 NULL,
     706             :                                                 0,
     707             :                                                 &ret_data_size,
     708       10346 :                                                 fsp->conn,
     709             :                                                 ea_list);
     710       10346 :                 if (!NT_STATUS_IS_OK(status)) {
     711           0 :                         ret_data_size = 0;
     712             :                 }
     713       10346 :                 total_ea_len = ret_data_size;
     714             :         }
     715       10346 :         TALLOC_FREE(mem_ctx);
     716       10346 :         return total_ea_len;
     717             : }
     718             : 
     719             : /****************************************************************************
     720             :  Ensure the EA name is case insensitive by matching any existing EA name.
     721             : ****************************************************************************/
     722             : 
     723           2 : static void canonicalize_ea_name(files_struct *fsp,
     724             :                         fstring unix_ea_name)
     725             : {
     726             :         size_t total_ea_len;
     727           2 :         TALLOC_CTX *mem_ctx = talloc_tos();
     728             :         struct ea_list *ea_list;
     729           2 :         NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
     730             :                                                fsp,
     731             :                                                &total_ea_len,
     732             :                                                &ea_list);
     733           2 :         if (!NT_STATUS_IS_OK(status)) {
     734           0 :                 return;
     735             :         }
     736             : 
     737           3 :         for (; ea_list; ea_list = ea_list->next) {
     738           1 :                 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
     739           0 :                         DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
     740             :                                 &unix_ea_name[5], ea_list->ea.name));
     741           0 :                         strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
     742           0 :                         break;
     743             :                 }
     744             :         }
     745             : }
     746             : 
     747             : /****************************************************************************
     748             :  Set or delete an extended attribute.
     749             : ****************************************************************************/
     750             : 
     751           1 : NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
     752             :                 struct ea_list *ea_list)
     753             : {
     754             :         NTSTATUS status;
     755           1 :         bool posix_pathnames = false;
     756             : 
     757           1 :         if (!lp_ea_support(SNUM(conn))) {
     758           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
     759             :         }
     760             : 
     761           1 :         if (fsp == NULL) {
     762           0 :                 return NT_STATUS_INVALID_HANDLE;
     763             :         }
     764             : 
     765           1 :         posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
     766             : 
     767           1 :         status = refuse_symlink_fsp(fsp);
     768           1 :         if (!NT_STATUS_IS_OK(status)) {
     769           0 :                 return status;
     770             :         }
     771             : 
     772           1 :         status = check_access_fsp(fsp, FILE_WRITE_EA);
     773           1 :         if (!NT_STATUS_IS_OK(status)) {
     774           0 :                 return status;
     775             :         }
     776             : 
     777             :         /* Setting EAs on streams isn't supported. */
     778           1 :         if (fsp_is_alternate_stream(fsp)) {
     779           0 :                 return NT_STATUS_INVALID_PARAMETER;
     780             :         }
     781             : 
     782             :         /*
     783             :          * Filter out invalid Windows EA names - before
     784             :          * we set *any* of them.
     785             :          */
     786             : 
     787           1 :         if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
     788           0 :                 return STATUS_INVALID_EA_NAME;
     789             :         }
     790             : 
     791           6 :         for (;ea_list; ea_list = ea_list->next) {
     792             :                 int ret;
     793             :                 fstring unix_ea_name;
     794             : 
     795             :                 /*
     796             :                  * Complementing the forward mapping from POSIX EAs to
     797             :                  * Windows EAs in get_ea_list_from_fsp(), here we map in the
     798             :                  * opposite direction from Windows EAs to the 'user' namespace
     799             :                  * of POSIX EAs. Hence, all POSIX EA names the we set here must
     800             :                  * start with a 'user.' prefix.
     801             :                  */
     802           2 :                 fstrcpy(unix_ea_name, "user.");
     803           2 :                 fstrcat(unix_ea_name, ea_list->ea.name);
     804             : 
     805           2 :                 canonicalize_ea_name(fsp, unix_ea_name);
     806             : 
     807           2 :                 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
     808             : 
     809           2 :                 if (samba_private_attr_name(unix_ea_name)) {
     810           0 :                         DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
     811           0 :                         return NT_STATUS_ACCESS_DENIED;
     812             :                 }
     813             : 
     814           2 :                 if (ea_list->ea.value.length == 0) {
     815             :                         /* Remove the attribute. */
     816           0 :                         DBG_DEBUG("deleting ea name %s on "
     817             :                                   "file %s by file descriptor.\n",
     818             :                                   unix_ea_name, fsp_str_dbg(fsp));
     819           0 :                         ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
     820             : #ifdef ENOATTR
     821             :                         /* Removing a non existent attribute always succeeds. */
     822           0 :                         if (ret == -1 && errno == ENOATTR) {
     823           0 :                                 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
     824             :                                                 unix_ea_name));
     825           0 :                                 ret = 0;
     826             :                         }
     827             : #endif
     828             :                 } else {
     829           2 :                         DEBUG(10,("set_ea: setting ea name %s on file "
     830             :                                   "%s by file descriptor.\n",
     831             :                                   unix_ea_name, fsp_str_dbg(fsp)));
     832           2 :                         ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
     833             :                                                 ea_list->ea.value.data, ea_list->ea.value.length, 0);
     834             :                 }
     835             : 
     836           2 :                 if (ret == -1) {
     837             : #ifdef ENOTSUP
     838           0 :                         if (errno == ENOTSUP) {
     839           0 :                                 return NT_STATUS_EAS_NOT_SUPPORTED;
     840             :                         }
     841             : #endif
     842           0 :                         return map_nt_error_from_unix(errno);
     843             :                 }
     844             : 
     845             :         }
     846           1 :         return NT_STATUS_OK;
     847             : }
     848             : 
     849             : /****************************************************************************
     850             :  Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
     851             : ****************************************************************************/
     852             : 
     853           0 : struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
     854             : {
     855           0 :         struct ea_list *ea_list_head = NULL;
     856           0 :         size_t offset = 0;
     857           0 :         size_t bytes_used = 0;
     858             : 
     859           0 :         while (offset < data_size) {
     860           0 :                 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
     861             : 
     862           0 :                 if (!eal) {
     863           0 :                         return NULL;
     864             :                 }
     865             : 
     866           0 :                 DLIST_ADD_END(ea_list_head, eal);
     867           0 :                 offset += bytes_used;
     868             :         }
     869             : 
     870           0 :         return ea_list_head;
     871             : }
     872             : 
     873             : /****************************************************************************
     874             :  Count the total EA size needed.
     875             : ****************************************************************************/
     876             : 
     877           0 : static size_t ea_list_size(struct ea_list *ealist)
     878             : {
     879             :         fstring dos_ea_name;
     880             :         struct ea_list *listp;
     881           0 :         size_t ret = 0;
     882             : 
     883           0 :         for (listp = ealist; listp; listp = listp->next) {
     884           0 :                 push_ascii_fstring(dos_ea_name, listp->ea.name);
     885           0 :                 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
     886             :         }
     887             :         /* Add on 4 for total length. */
     888           0 :         if (ret) {
     889           0 :                 ret += 4;
     890             :         }
     891             : 
     892           0 :         return ret;
     893             : }
     894             : 
     895             : /****************************************************************************
     896             :  Return a union of EA's from a file list and a list of names.
     897             :  The TALLOC context for the two lists *MUST* be identical as we steal
     898             :  memory from one list to add to another. JRA.
     899             : ****************************************************************************/
     900             : 
     901           0 : static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
     902             : {
     903             :         struct ea_list *nlistp, *flistp;
     904             : 
     905           0 :         for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
     906           0 :                 for (flistp = file_list; flistp; flistp = flistp->next) {
     907           0 :                         if (strequal(nlistp->ea.name, flistp->ea.name)) {
     908           0 :                                 break;
     909             :                         }
     910             :                 }
     911             : 
     912           0 :                 if (flistp) {
     913             :                         /* Copy the data from this entry. */
     914           0 :                         nlistp->ea.flags = flistp->ea.flags;
     915           0 :                         nlistp->ea.value = flistp->ea.value;
     916             :                 } else {
     917             :                         /* Null entry. */
     918           0 :                         nlistp->ea.flags = 0;
     919           0 :                         ZERO_STRUCT(nlistp->ea.value);
     920             :                 }
     921             :         }
     922             : 
     923           0 :         *total_ea_len = ea_list_size(name_list);
     924           0 :         return name_list;
     925             : }
     926             : 
     927             : /*********************************************************
     928             :  Routine to check if a given string matches exactly.
     929             :  as a special case a mask of "." does NOT match. That
     930             :  is required for correct wildcard semantics
     931             :  Case can be significant or not.
     932             : **********************************************************/
     933             : 
     934       11827 : static bool exact_match(bool has_wild,
     935             :                         bool case_sensitive,
     936             :                         const char *str,
     937             :                         const char *mask)
     938             : {
     939       11827 :         if (mask[0] == '.' && mask[1] == 0) {
     940           0 :                 return false;
     941             :         }
     942             : 
     943       11827 :         if (has_wild) {
     944       10562 :                 return false;
     945             :         }
     946             : 
     947        1265 :         if (case_sensitive) {
     948           0 :                 return strcmp(str,mask)==0;
     949             :         } else {
     950        1265 :                 return strcasecmp_m(str,mask) == 0;
     951             :         }
     952             : }
     953             : 
     954             : /****************************************************************************
     955             :  Return the filetype for UNIX extensions.
     956             : ****************************************************************************/
     957             : 
     958           0 : static uint32_t unix_filetype(mode_t mode)
     959             : {
     960           0 :         if(S_ISREG(mode))
     961           0 :                 return UNIX_TYPE_FILE;
     962           0 :         else if(S_ISDIR(mode))
     963           0 :                 return UNIX_TYPE_DIR;
     964             : #ifdef S_ISLNK
     965           0 :         else if(S_ISLNK(mode))
     966           0 :                 return UNIX_TYPE_SYMLINK;
     967             : #endif
     968             : #ifdef S_ISCHR
     969           0 :         else if(S_ISCHR(mode))
     970           0 :                 return UNIX_TYPE_CHARDEV;
     971             : #endif
     972             : #ifdef S_ISBLK
     973           0 :         else if(S_ISBLK(mode))
     974           0 :                 return UNIX_TYPE_BLKDEV;
     975             : #endif
     976             : #ifdef S_ISFIFO
     977           0 :         else if(S_ISFIFO(mode))
     978           0 :                 return UNIX_TYPE_FIFO;
     979             : #endif
     980             : #ifdef S_ISSOCK
     981           0 :         else if(S_ISSOCK(mode))
     982           0 :                 return UNIX_TYPE_SOCKET;
     983             : #endif
     984             : 
     985           0 :         DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
     986           0 :         return UNIX_TYPE_UNKNOWN;
     987             : }
     988             : 
     989             : /****************************************************************************
     990             :  Map wire perms onto standard UNIX permissions. Obey share restrictions.
     991             : ****************************************************************************/
     992             : 
     993           0 : NTSTATUS unix_perms_from_wire(connection_struct *conn,
     994             :                               const SMB_STRUCT_STAT *psbuf,
     995             :                               uint32_t perms,
     996             :                               enum perm_type ptype,
     997             :                               mode_t *ret_perms)
     998             : {
     999           0 :         mode_t ret = 0;
    1000             : 
    1001           0 :         if (perms == SMB_MODE_NO_CHANGE) {
    1002           0 :                 if (!VALID_STAT(*psbuf)) {
    1003           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1004             :                 } else {
    1005           0 :                         *ret_perms = psbuf->st_ex_mode;
    1006           0 :                         return NT_STATUS_OK;
    1007             :                 }
    1008             :         }
    1009             : 
    1010           0 :         ret = wire_perms_to_unix(perms);
    1011             : 
    1012           0 :         if (ptype == PERM_NEW_FILE) {
    1013             :                 /*
    1014             :                  * "create mask"/"force create mode" are
    1015             :                  * only applied to new files, not existing ones.
    1016             :                  */
    1017           0 :                 ret &= lp_create_mask(SNUM(conn));
    1018             :                 /* Add in force bits */
    1019           0 :                 ret |= lp_force_create_mode(SNUM(conn));
    1020           0 :         } else if (ptype == PERM_NEW_DIR) {
    1021             :                 /*
    1022             :                  * "directory mask"/"force directory mode" are
    1023             :                  * only applied to new directories, not existing ones.
    1024             :                  */
    1025           0 :                 ret &= lp_directory_mask(SNUM(conn));
    1026             :                 /* Add in force bits */
    1027           0 :                 ret |= lp_force_directory_mode(SNUM(conn));
    1028             :         }
    1029             : 
    1030           0 :         *ret_perms = ret;
    1031           0 :         return NT_STATUS_OK;
    1032             : }
    1033             : 
    1034             : /****************************************************************************
    1035             :  Needed to show the msdfs symlinks as directories. Modifies psbuf
    1036             :  to be a directory if it's a msdfs link.
    1037             : ****************************************************************************/
    1038             : 
    1039          76 : static bool check_msdfs_link(struct files_struct *dirfsp,
    1040             :                              struct smb_filename *atname,
    1041             :                              struct smb_filename *smb_fname)
    1042             : {
    1043          76 :         int saved_errno = errno;
    1044         152 :         if(lp_host_msdfs() &&
    1045         132 :                 lp_msdfs_root(SNUM(dirfsp->conn)) &&
    1046          56 :                 is_msdfs_link(dirfsp, atname)) {
    1047             : 
    1048             :                 /*
    1049             :                  * Copy the returned stat struct from the relative
    1050             :                  * to the full pathname.
    1051             :                  */
    1052          56 :                 smb_fname->st = atname->st;
    1053             : 
    1054          56 :                 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
    1055             :                         "as a directory\n",
    1056             :                         smb_fname->base_name));
    1057          56 :                 smb_fname->st.st_ex_mode =
    1058          56 :                         (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
    1059          56 :                 errno = saved_errno;
    1060          56 :                 return true;
    1061             :         }
    1062          20 :         errno = saved_errno;
    1063          20 :         return false;
    1064             : }
    1065             : 
    1066             : 
    1067             : /****************************************************************************
    1068             :  Get a level dependent lanman2 dir entry.
    1069             : ****************************************************************************/
    1070             : 
    1071             : struct smbd_dirptr_lanman2_state {
    1072             :         connection_struct *conn;
    1073             :         uint32_t info_level;
    1074             :         bool check_mangled_names;
    1075             :         bool has_wild;
    1076             :         bool got_exact_match;
    1077             :         bool case_sensitive;
    1078             : };
    1079             : 
    1080       11296 : static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
    1081             :                                          void *private_data,
    1082             :                                          const char *dname,
    1083             :                                          const char *mask,
    1084             :                                          char **_fname)
    1085             : {
    1086       11296 :         struct smbd_dirptr_lanman2_state *state =
    1087             :                 (struct smbd_dirptr_lanman2_state *)private_data;
    1088             :         bool ok;
    1089             :         char mangled_name[13]; /* mangled 8.3 name. */
    1090             :         bool got_match;
    1091             :         const char *fname;
    1092             : 
    1093             :         /* Mangle fname if it's an illegal name. */
    1094       11296 :         if (mangle_must_mangle(dname, state->conn->params)) {
    1095             :                 /*
    1096             :                  * Slow path - ensure we can push the original name as UCS2. If
    1097             :                  * not, then just don't return this name.
    1098             :                  */
    1099             :                 NTSTATUS status;
    1100          20 :                 size_t ret_len = 0;
    1101          20 :                 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
    1102          20 :                 uint8_t *tmp = talloc_array(talloc_tos(),
    1103             :                                         uint8_t,
    1104             :                                         len);
    1105             : 
    1106          20 :                 status = srvstr_push(NULL,
    1107             :                         FLAGS2_UNICODE_STRINGS,
    1108             :                         tmp,
    1109             :                         dname,
    1110             :                         len,
    1111             :                         STR_TERMINATE,
    1112             :                         &ret_len);
    1113             : 
    1114          20 :                 TALLOC_FREE(tmp);
    1115             : 
    1116          20 :                 if (!NT_STATUS_IS_OK(status)) {
    1117          12 :                         return false;
    1118             :                 }
    1119             : 
    1120          12 :                 ok = name_to_8_3(dname, mangled_name,
    1121          12 :                                  true, state->conn->params);
    1122          12 :                 if (!ok) {
    1123           0 :                         return false;
    1124             :                 }
    1125          12 :                 fname = mangled_name;
    1126             :         } else {
    1127       11276 :                 fname = dname;
    1128             :         }
    1129             : 
    1130       11288 :         got_match = exact_match(state->has_wild,
    1131       11288 :                                 state->case_sensitive,
    1132             :                                 fname, mask);
    1133       11288 :         state->got_exact_match = got_match;
    1134       11288 :         if (!got_match) {
    1135       11174 :                 got_match = mask_match(fname, mask,
    1136       11174 :                                        state->case_sensitive);
    1137             :         }
    1138             : 
    1139       11770 :         if(!got_match && state->check_mangled_names &&
    1140         921 :            !mangle_is_8_3(fname, false, state->conn->params)) {
    1141             :                 /*
    1142             :                  * It turns out that NT matches wildcards against
    1143             :                  * both long *and* short names. This may explain some
    1144             :                  * of the wildcard wierdness from old DOS clients
    1145             :                  * that some people have been seeing.... JRA.
    1146             :                  */
    1147             :                 /* Force the mangling into 8.3. */
    1148         539 :                 ok = name_to_8_3(fname, mangled_name,
    1149         539 :                                  false, state->conn->params);
    1150         539 :                 if (!ok) {
    1151           0 :                         return false;
    1152             :                 }
    1153             : 
    1154         539 :                 got_match = exact_match(state->has_wild,
    1155         539 :                                         state->case_sensitive,
    1156             :                                         mangled_name, mask);
    1157         539 :                 state->got_exact_match = got_match;
    1158         539 :                 if (!got_match) {
    1159         539 :                         got_match = mask_match(mangled_name, mask,
    1160         539 :                                                state->case_sensitive);
    1161             :                 }
    1162             :         }
    1163             : 
    1164       11288 :         if (!got_match) {
    1165         921 :                 return false;
    1166             :         }
    1167             : 
    1168       10367 :         *_fname = talloc_strdup(ctx, fname);
    1169       10367 :         if (*_fname == NULL) {
    1170           0 :                 return false;
    1171             :         }
    1172             : 
    1173       10367 :         return true;
    1174             : }
    1175             : 
    1176       10367 : static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
    1177             :                                         void *private_data,
    1178             :                                         struct files_struct *dirfsp,
    1179             :                                         struct smb_filename *atname,
    1180             :                                         struct smb_filename *smb_fname,
    1181             :                                         bool get_dosmode,
    1182             :                                         uint32_t *_mode)
    1183             : {
    1184       10367 :         struct smbd_dirptr_lanman2_state *state =
    1185             :                 (struct smbd_dirptr_lanman2_state *)private_data;
    1186       10367 :         bool ms_dfs_link = false;
    1187             : 
    1188       10367 :         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
    1189           0 :                 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
    1190           0 :                         DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
    1191             :                                  "Couldn't lstat [%s] (%s)\n",
    1192             :                                  smb_fname_str_dbg(smb_fname),
    1193             :                                  strerror(errno)));
    1194           0 :                         return false;
    1195             :                 }
    1196           0 :                 return true;
    1197             :         }
    1198             : 
    1199       10443 :         if (!VALID_STAT(smb_fname->st) &&
    1200          76 :             SMB_VFS_STAT(state->conn, smb_fname) != 0) {
    1201             :                 /* Needed to show the msdfs symlinks as
    1202             :                  * directories */
    1203             : 
    1204          76 :                 ms_dfs_link = check_msdfs_link(dirfsp,
    1205             :                                                atname,
    1206             :                                                smb_fname);
    1207          76 :                 if (!ms_dfs_link) {
    1208          20 :                         DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
    1209             :                                  "Couldn't stat [%s] (%s)\n",
    1210             :                                  smb_fname_str_dbg(smb_fname),
    1211             :                                  strerror(errno)));
    1212          20 :                         return false;
    1213             :                 }
    1214             : 
    1215          56 :                 *_mode = dos_mode_msdfs(state->conn, smb_fname);
    1216          56 :                 return true;
    1217             :         }
    1218             : 
    1219       10291 :         if (!get_dosmode) {
    1220         426 :                 return true;
    1221             :         }
    1222             : 
    1223        9865 :         *_mode = fdos_mode(smb_fname->fsp);
    1224        9865 :         smb_fname->st = smb_fname->fsp->fsp_name->st;
    1225             : 
    1226        9865 :         return true;
    1227             : }
    1228             : 
    1229       10343 : static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
    1230             :                                     connection_struct *conn,
    1231             :                                     uint16_t flags2,
    1232             :                                     uint32_t info_level,
    1233             :                                     struct ea_list *name_list,
    1234             :                                     bool check_mangled_names,
    1235             :                                     bool requires_resume_key,
    1236             :                                     uint32_t mode,
    1237             :                                     const char *fname,
    1238             :                                     const struct smb_filename *smb_fname,
    1239             :                                     int space_remaining,
    1240             :                                     uint8_t align,
    1241             :                                     bool do_pad,
    1242             :                                     char *base_data,
    1243             :                                     char **ppdata,
    1244             :                                     char *end_data,
    1245             :                                     uint64_t *last_entry_off)
    1246             : {
    1247       10343 :         char *p, *q, *pdata = *ppdata;
    1248       10343 :         uint32_t reskey=0;
    1249       10343 :         uint64_t file_size = 0;
    1250       10343 :         uint64_t allocation_size = 0;
    1251       10343 :         uint64_t file_id = 0;
    1252       10343 :         size_t len = 0;
    1253       10343 :         struct timespec mdate_ts = {0};
    1254       10343 :         struct timespec adate_ts = {0};
    1255       10343 :         struct timespec cdate_ts = {0};
    1256       10343 :         struct timespec create_date_ts = {0};
    1257       10343 :         time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
    1258             :         char *nameptr;
    1259             :         char *last_entry_ptr;
    1260             :         bool was_8_3;
    1261             :         int off;
    1262       10343 :         int pad = 0;
    1263             :         NTSTATUS status;
    1264       10343 :         struct readdir_attr_data *readdir_attr_data = NULL;
    1265             : 
    1266       10343 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    1267         918 :                 file_size = get_file_size_stat(&smb_fname->st);
    1268             :         }
    1269       10343 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
    1270             : 
    1271             :         /*
    1272             :          * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
    1273             :          * a DFS symlink.
    1274             :          */
    1275       17348 :         if (smb_fname->fsp != NULL &&
    1276        9865 :             !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
    1277        9865 :                 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
    1278             :                                                ctx,
    1279             :                                                &readdir_attr_data);
    1280        9865 :                 if (!NT_STATUS_IS_OK(status)) {
    1281        9865 :                         if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
    1282             :                                              status)) {
    1283           0 :                                 return status;
    1284             :                         }
    1285             :                 }
    1286             :         }
    1287             : 
    1288       10343 :         file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
    1289             : 
    1290       10343 :         mdate_ts = smb_fname->st.st_ex_mtime;
    1291       10343 :         adate_ts = smb_fname->st.st_ex_atime;
    1292       10343 :         create_date_ts = get_create_timespec(conn, NULL, smb_fname);
    1293       10343 :         cdate_ts = get_change_timespec(conn, NULL, smb_fname);
    1294             : 
    1295       10343 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    1296           0 :                 dos_filetime_timespec(&create_date_ts);
    1297           0 :                 dos_filetime_timespec(&mdate_ts);
    1298           0 :                 dos_filetime_timespec(&adate_ts);
    1299           0 :                 dos_filetime_timespec(&cdate_ts);
    1300             :         }
    1301             : 
    1302       10343 :         create_date = convert_timespec_to_time_t(create_date_ts);
    1303       10343 :         mdate = convert_timespec_to_time_t(mdate_ts);
    1304       10343 :         adate = convert_timespec_to_time_t(adate_ts);
    1305             : 
    1306             :         /* align the record */
    1307       10343 :         SMB_ASSERT(align >= 1);
    1308             : 
    1309       10343 :         off = (int)PTR_DIFF(pdata, base_data);
    1310       10343 :         pad = (off + (align-1)) & ~(align-1);
    1311       10343 :         pad -= off;
    1312             : 
    1313       10343 :         if (pad && pad > space_remaining) {
    1314           0 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1315             :                         "for padding (wanted %u, had %d)\n",
    1316             :                         (unsigned int)pad,
    1317             :                         space_remaining ));
    1318           0 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1319             :         }
    1320             : 
    1321       10343 :         off += pad;
    1322             :         /* initialize padding to 0 */
    1323       10343 :         if (pad) {
    1324        7582 :                 memset(pdata, 0, pad);
    1325             :         }
    1326       10343 :         space_remaining -= pad;
    1327             : 
    1328       10343 :         DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
    1329             :                 space_remaining ));
    1330             : 
    1331       10343 :         pdata += pad;
    1332       10343 :         p = pdata;
    1333       10343 :         last_entry_ptr = p;
    1334             : 
    1335       10343 :         pad = 0;
    1336       10343 :         off = 0;
    1337             : 
    1338       10343 :         switch (info_level) {
    1339           0 :         case SMB_FIND_INFO_STANDARD:
    1340           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
    1341           0 :                 if(requires_resume_key) {
    1342           0 :                         SIVAL(p,0,reskey);
    1343           0 :                         p += 4;
    1344             :                 }
    1345           0 :                 srv_put_dos_date2(p,0,create_date);
    1346           0 :                 srv_put_dos_date2(p,4,adate);
    1347           0 :                 srv_put_dos_date2(p,8,mdate);
    1348           0 :                 SIVAL(p,12,(uint32_t)file_size);
    1349           0 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1350           0 :                 SSVAL(p,20,mode);
    1351           0 :                 p += 23;
    1352           0 :                 nameptr = p;
    1353           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1354           0 :                         p += ucs2_align(base_data, p, 0);
    1355             :                 }
    1356           0 :                 status = srvstr_push(base_data, flags2, p,
    1357             :                                   fname, PTR_DIFF(end_data, p),
    1358             :                                   STR_TERMINATE, &len);
    1359           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1360           4 :                         return status;
    1361             :                 }
    1362           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1363           0 :                         if (len > 2) {
    1364           0 :                                 SCVAL(nameptr, -1, len - 2);
    1365             :                         } else {
    1366           0 :                                 SCVAL(nameptr, -1, 0);
    1367             :                         }
    1368             :                 } else {
    1369           0 :                         if (len > 1) {
    1370           0 :                                 SCVAL(nameptr, -1, len - 1);
    1371             :                         } else {
    1372           0 :                                 SCVAL(nameptr, -1, 0);
    1373             :                         }
    1374             :                 }
    1375           0 :                 p += len;
    1376           0 :                 break;
    1377             : 
    1378           0 :         case SMB_FIND_EA_SIZE:
    1379           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
    1380           0 :                 if (requires_resume_key) {
    1381           0 :                         SIVAL(p,0,reskey);
    1382           0 :                         p += 4;
    1383             :                 }
    1384           0 :                 srv_put_dos_date2(p,0,create_date);
    1385           0 :                 srv_put_dos_date2(p,4,adate);
    1386           0 :                 srv_put_dos_date2(p,8,mdate);
    1387           0 :                 SIVAL(p,12,(uint32_t)file_size);
    1388           0 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1389           0 :                 SSVAL(p,20,mode);
    1390             :                 {
    1391           0 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    1392           0 :                         SIVAL(p,22,ea_size); /* Extended attributes */
    1393             :                 }
    1394           0 :                 p += 27;
    1395           0 :                 nameptr = p - 1;
    1396           0 :                 status = srvstr_push(base_data, flags2,
    1397             :                                   p, fname, PTR_DIFF(end_data, p),
    1398             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1399           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1400           0 :                         return status;
    1401             :                 }
    1402           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1403           0 :                         if (len > 2) {
    1404           0 :                                 len -= 2;
    1405             :                         } else {
    1406           0 :                                 len = 0;
    1407             :                         }
    1408             :                 } else {
    1409           0 :                         if (len > 1) {
    1410           0 :                                 len -= 1;
    1411             :                         } else {
    1412           0 :                                 len = 0;
    1413             :                         }
    1414             :                 }
    1415           0 :                 SCVAL(nameptr,0,len);
    1416           0 :                 p += len;
    1417           0 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1418           0 :                 break;
    1419             : 
    1420           0 :         case SMB_FIND_EA_LIST:
    1421             :         {
    1422           0 :                 struct ea_list *file_list = NULL;
    1423           0 :                 size_t ea_len = 0;
    1424             : 
    1425           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
    1426           0 :                 if (!name_list) {
    1427           0 :                         return NT_STATUS_INVALID_PARAMETER;
    1428             :                 }
    1429           0 :                 if (requires_resume_key) {
    1430           0 :                         SIVAL(p,0,reskey);
    1431           0 :                         p += 4;
    1432             :                 }
    1433           0 :                 srv_put_dos_date2(p,0,create_date);
    1434           0 :                 srv_put_dos_date2(p,4,adate);
    1435           0 :                 srv_put_dos_date2(p,8,mdate);
    1436           0 :                 SIVAL(p,12,(uint32_t)file_size);
    1437           0 :                 SIVAL(p,16,(uint32_t)allocation_size);
    1438           0 :                 SSVAL(p,20,mode);
    1439           0 :                 p += 22; /* p now points to the EA area. */
    1440             : 
    1441           0 :                 status = get_ea_list_from_fsp(ctx,
    1442           0 :                                                smb_fname->fsp,
    1443             :                                                &ea_len, &file_list);
    1444           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1445           0 :                         file_list = NULL;
    1446             :                 }
    1447           0 :                 name_list = ea_list_union(name_list, file_list, &ea_len);
    1448             : 
    1449             :                 /* We need to determine if this entry will fit in the space available. */
    1450             :                 /* Max string size is 255 bytes. */
    1451           0 :                 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
    1452           0 :                         DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1453             :                                 "(wanted %u, had %d)\n",
    1454             :                                 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
    1455             :                                 space_remaining ));
    1456           0 :                         return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1457             :                 }
    1458             : 
    1459             :                 /* Push the ea_data followed by the name. */
    1460           0 :                 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
    1461           0 :                 nameptr = p;
    1462           0 :                 status = srvstr_push(base_data, flags2,
    1463             :                                   p + 1, fname, PTR_DIFF(end_data, p+1),
    1464             :                                   STR_TERMINATE | STR_NOALIGN, &len);
    1465           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1466           0 :                         return status;
    1467             :                 }
    1468           0 :                 if (flags2 & FLAGS2_UNICODE_STRINGS) {
    1469           0 :                         if (len > 2) {
    1470           0 :                                 len -= 2;
    1471             :                         } else {
    1472           0 :                                 len = 0;
    1473             :                         }
    1474             :                 } else {
    1475           0 :                         if (len > 1) {
    1476           0 :                                 len -= 1;
    1477             :                         } else {
    1478           0 :                                 len = 0;
    1479             :                         }
    1480             :                 }
    1481           0 :                 SCVAL(nameptr,0,len);
    1482           0 :                 p += len + 1;
    1483           0 :                 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
    1484           0 :                 break;
    1485             :         }
    1486             : 
    1487           0 :         case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
    1488           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
    1489           0 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    1490           0 :                 p += 4;
    1491           0 :                 SIVAL(p,0,reskey); p += 4;
    1492           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1493           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1494           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1495           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1496           0 :                 SOFF_T(p,0,file_size); p += 8;
    1497           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1498           0 :                 SIVAL(p,0,mode); p += 4;
    1499           0 :                 q = p; p += 4; /* q is placeholder for name length. */
    1500           0 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    1501           0 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    1502             :                 } else {
    1503           0 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    1504           0 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    1505             :                 }
    1506           0 :                 p += 4;
    1507             :                 /* Clear the short name buffer. This is
    1508             :                  * IMPORTANT as not doing so will trigger
    1509             :                  * a Win2k client bug. JRA.
    1510             :                  */
    1511           0 :                 if (!was_8_3 && check_mangled_names) {
    1512             :                         char mangled_name[13]; /* mangled 8.3 name. */
    1513           0 :                         if (!name_to_8_3(fname,mangled_name,True,
    1514           0 :                                            conn->params)) {
    1515             :                                 /* Error - mangle failed ! */
    1516           0 :                                 memset(mangled_name,'\0',12);
    1517             :                         }
    1518           0 :                         mangled_name[12] = 0;
    1519           0 :                         status = srvstr_push(base_data, flags2,
    1520             :                                           p+2, mangled_name, 24,
    1521             :                                           STR_UPPER|STR_UNICODE, &len);
    1522           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1523           0 :                                 return status;
    1524             :                         }
    1525           0 :                         if (len < 24) {
    1526           0 :                                 memset(p + 2 + len,'\0',24 - len);
    1527             :                         }
    1528           0 :                         SSVAL(p, 0, len);
    1529             :                 } else {
    1530           0 :                         memset(p,'\0',26);
    1531             :                 }
    1532           0 :                 p += 2 + 24;
    1533           0 :                 status = srvstr_push(base_data, flags2, p,
    1534             :                                   fname, PTR_DIFF(end_data, p),
    1535             :                                   STR_TERMINATE_ASCII, &len);
    1536           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1537           0 :                         return status;
    1538             :                 }
    1539           0 :                 SIVAL(q,0,len);
    1540           0 :                 p += len;
    1541             : 
    1542           0 :                 len = PTR_DIFF(p, pdata);
    1543           0 :                 pad = (len + (align-1)) & ~(align-1);
    1544             :                 /*
    1545             :                  * offset to the next entry, the caller
    1546             :                  * will overwrite it for the last entry
    1547             :                  * that's why we always include the padding
    1548             :                  */
    1549           0 :                 SIVAL(pdata,0,pad);
    1550             :                 /*
    1551             :                  * set padding to zero
    1552             :                  */
    1553           0 :                 if (do_pad) {
    1554           0 :                         memset(p, 0, pad - len);
    1555           0 :                         p = pdata + pad;
    1556             :                 } else {
    1557           0 :                         p = pdata + len;
    1558             :                 }
    1559           0 :                 break;
    1560             : 
    1561           0 :         case SMB_FIND_FILE_DIRECTORY_INFO:
    1562           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
    1563           0 :                 p += 4;
    1564           0 :                 SIVAL(p,0,reskey); p += 4;
    1565           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1566           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1567           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1568           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1569           0 :                 SOFF_T(p,0,file_size); p += 8;
    1570           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1571           0 :                 SIVAL(p,0,mode); p += 4;
    1572           0 :                 status = srvstr_push(base_data, flags2,
    1573             :                                   p + 4, fname, PTR_DIFF(end_data, p+4),
    1574             :                                   STR_TERMINATE_ASCII, &len);
    1575           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1576           0 :                         return status;
    1577             :                 }
    1578           0 :                 SIVAL(p,0,len);
    1579           0 :                 p += 4 + len;
    1580             : 
    1581           0 :                 len = PTR_DIFF(p, pdata);
    1582           0 :                 pad = (len + (align-1)) & ~(align-1);
    1583             :                 /*
    1584             :                  * offset to the next entry, the caller
    1585             :                  * will overwrite it for the last entry
    1586             :                  * that's why we always include the padding
    1587             :                  */
    1588           0 :                 SIVAL(pdata,0,pad);
    1589             :                 /*
    1590             :                  * set padding to zero
    1591             :                  */
    1592           0 :                 if (do_pad) {
    1593           0 :                         memset(p, 0, pad - len);
    1594           0 :                         p = pdata + pad;
    1595             :                 } else {
    1596           0 :                         p = pdata + len;
    1597             :                 }
    1598           0 :                 break;
    1599             : 
    1600           0 :         case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
    1601           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
    1602           0 :                 p += 4;
    1603           0 :                 SIVAL(p,0,reskey); p += 4;
    1604           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1605           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1606           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1607           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1608           0 :                 SOFF_T(p,0,file_size); p += 8;
    1609           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1610           0 :                 SIVAL(p,0,mode); p += 4;
    1611           0 :                 q = p; p += 4; /* q is placeholder for name length. */
    1612           0 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    1613           0 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    1614             :                 } else {
    1615           0 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    1616           0 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    1617             :                 }
    1618           0 :                 p +=4;
    1619           0 :                 status = srvstr_push(base_data, flags2, p,
    1620             :                                   fname, PTR_DIFF(end_data, p),
    1621             :                                   STR_TERMINATE_ASCII, &len);
    1622           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1623           0 :                         return status;
    1624             :                 }
    1625           0 :                 SIVAL(q, 0, len);
    1626           0 :                 p += len;
    1627             : 
    1628           0 :                 len = PTR_DIFF(p, pdata);
    1629           0 :                 pad = (len + (align-1)) & ~(align-1);
    1630             :                 /*
    1631             :                  * offset to the next entry, the caller
    1632             :                  * will overwrite it for the last entry
    1633             :                  * that's why we always include the padding
    1634             :                  */
    1635           0 :                 SIVAL(pdata,0,pad);
    1636             :                 /*
    1637             :                  * set padding to zero
    1638             :                  */
    1639           0 :                 if (do_pad) {
    1640           0 :                         memset(p, 0, pad - len);
    1641           0 :                         p = pdata + pad;
    1642             :                 } else {
    1643           0 :                         p = pdata + len;
    1644             :                 }
    1645           0 :                 break;
    1646             : 
    1647          17 :         case SMB_FIND_FILE_NAMES_INFO:
    1648          17 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
    1649          17 :                 p += 4;
    1650          17 :                 SIVAL(p,0,reskey); p += 4;
    1651          17 :                 p += 4;
    1652             :                 /* this must *not* be null terminated or w2k gets in a loop trying to set an
    1653             :                    acl on a dir (tridge) */
    1654          17 :                 status = srvstr_push(base_data, flags2, p,
    1655             :                                   fname, PTR_DIFF(end_data, p),
    1656             :                                   STR_TERMINATE_ASCII, &len);
    1657          17 :                 if (!NT_STATUS_IS_OK(status)) {
    1658           0 :                         return status;
    1659             :                 }
    1660          17 :                 SIVAL(p, -4, len);
    1661          17 :                 p += len;
    1662             : 
    1663          17 :                 len = PTR_DIFF(p, pdata);
    1664          17 :                 pad = (len + (align-1)) & ~(align-1);
    1665             :                 /*
    1666             :                  * offset to the next entry, the caller
    1667             :                  * will overwrite it for the last entry
    1668             :                  * that's why we always include the padding
    1669             :                  */
    1670          17 :                 SIVAL(pdata,0,pad);
    1671             :                 /*
    1672             :                  * set padding to zero
    1673             :                  */
    1674          17 :                 if (do_pad) {
    1675           0 :                         memset(p, 0, pad - len);
    1676           0 :                         p = pdata + pad;
    1677             :                 } else {
    1678          17 :                         p = pdata + len;
    1679             :                 }
    1680          17 :                 break;
    1681             : 
    1682           0 :         case SMB_FIND_ID_FULL_DIRECTORY_INFO:
    1683           0 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
    1684           0 :                 p += 4;
    1685           0 :                 SIVAL(p,0,reskey); p += 4;
    1686           0 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1687           0 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1688           0 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1689           0 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1690           0 :                 SOFF_T(p,0,file_size); p += 8;
    1691           0 :                 SOFF_T(p,0,allocation_size); p += 8;
    1692           0 :                 SIVAL(p,0,mode); p += 4;
    1693           0 :                 q = p; p += 4; /* q is placeholder for name length. */
    1694           0 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    1695           0 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    1696             :                 } else {
    1697           0 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    1698           0 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    1699             :                 }
    1700           0 :                 p += 4;
    1701           0 :                 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
    1702           0 :                 SBVAL(p,0,file_id); p += 8;
    1703           0 :                 status = srvstr_push(base_data, flags2, p,
    1704             :                                   fname, PTR_DIFF(end_data, p),
    1705             :                                   STR_TERMINATE_ASCII, &len);
    1706           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1707           0 :                         return status;
    1708             :                 }
    1709           0 :                 SIVAL(q, 0, len);
    1710           0 :                 p += len;
    1711             : 
    1712           0 :                 len = PTR_DIFF(p, pdata);
    1713           0 :                 pad = (len + (align-1)) & ~(align-1);
    1714             :                 /*
    1715             :                  * offset to the next entry, the caller
    1716             :                  * will overwrite it for the last entry
    1717             :                  * that's why we always include the padding
    1718             :                  */
    1719           0 :                 SIVAL(pdata,0,pad);
    1720             :                 /*
    1721             :                  * set padding to zero
    1722             :                  */
    1723           0 :                 if (do_pad) {
    1724           0 :                         memset(p, 0, pad - len);
    1725           0 :                         p = pdata + pad;
    1726             :                 } else {
    1727           0 :                         p = pdata + len;
    1728             :                 }
    1729           0 :                 break;
    1730             : 
    1731       10326 :         case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
    1732       10326 :                 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
    1733       10326 :                 was_8_3 = mangle_is_8_3(fname, True, conn->params);
    1734       10326 :                 p += 4;
    1735       10326 :                 SIVAL(p,0,reskey); p += 4;
    1736       10326 :                 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
    1737       10326 :                 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
    1738       10326 :                 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
    1739       10326 :                 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
    1740       10326 :                 SOFF_T(p,0,file_size); p += 8;
    1741       10326 :                 SOFF_T(p,0,allocation_size); p += 8;
    1742       10326 :                 SIVAL(p,0,mode); p += 4;
    1743       10326 :                 q = p; p += 4; /* q is placeholder for name length */
    1744       10326 :                 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
    1745          56 :                         SIVAL(p, 0, IO_REPARSE_TAG_DFS);
    1746       10270 :                 } else if (readdir_attr_data &&
    1747           0 :                            readdir_attr_data->type == RDATTR_AAPL) {
    1748             :                         /*
    1749             :                          * OS X specific SMB2 extension negotiated via
    1750             :                          * AAPL create context: return max_access in
    1751             :                          * ea_size field.
    1752             :                          */
    1753           0 :                         SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
    1754             :                 } else {
    1755       10270 :                         unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
    1756       10270 :                         SIVAL(p,0,ea_size); /* Extended attributes */
    1757             :                 }
    1758       10326 :                 p += 4;
    1759             : 
    1760       10326 :                 if (readdir_attr_data &&
    1761           0 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1762             :                         /*
    1763             :                          * OS X specific SMB2 extension negotiated via
    1764             :                          * AAPL create context: return resource fork
    1765             :                          * length and compressed FinderInfo in
    1766             :                          * shortname field.
    1767             :                          *
    1768             :                          * According to documentation short_name_len
    1769             :                          * should be 0, but on the wire behaviour
    1770             :                          * shows its set to 24 by clients.
    1771             :                          */
    1772           0 :                         SSVAL(p, 0, 24);
    1773             : 
    1774             :                         /* Resourefork length */
    1775           0 :                         SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
    1776             : 
    1777             :                         /* Compressed FinderInfo */
    1778           0 :                         memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
    1779       11570 :                 } else if (!was_8_3 && check_mangled_names) {
    1780             :                         char mangled_name[13]; /* mangled 8.3 name. */
    1781        2238 :                         if (!name_to_8_3(fname,mangled_name,True,
    1782        2238 :                                         conn->params)) {
    1783             :                                 /* Error - mangle failed ! */
    1784           0 :                                 memset(mangled_name,'\0',12);
    1785             :                         }
    1786        2238 :                         mangled_name[12] = 0;
    1787        2238 :                         status = srvstr_push(base_data, flags2,
    1788             :                                           p+2, mangled_name, 24,
    1789             :                                           STR_UPPER|STR_UNICODE, &len);
    1790        2238 :                         if (!NT_STATUS_IS_OK(status)) {
    1791           0 :                                 return status;
    1792             :                         }
    1793        2238 :                         SSVAL(p, 0, len);
    1794        2238 :                         if (len < 24) {
    1795        2177 :                                 memset(p + 2 + len,'\0',24 - len);
    1796             :                         }
    1797        2238 :                         SSVAL(p, 0, len);
    1798             :                 } else {
    1799             :                         /* Clear the short name buffer. This is
    1800             :                          * IMPORTANT as not doing so will trigger
    1801             :                          * a Win2k client bug. JRA.
    1802             :                          */
    1803        8088 :                         memset(p,'\0',26);
    1804             :                 }
    1805       10326 :                 p += 26;
    1806             : 
    1807             :                 /* Reserved ? */
    1808       10326 :                 if (readdir_attr_data &&
    1809           0 :                     readdir_attr_data->type == RDATTR_AAPL) {
    1810             :                         /*
    1811             :                          * OS X specific SMB2 extension negotiated via
    1812             :                          * AAPL create context: return UNIX mode in
    1813             :                          * reserved field.
    1814             :                          */
    1815           0 :                         uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
    1816           0 :                         SSVAL(p, 0, aapl_mode);
    1817             :                 } else {
    1818       10326 :                         SSVAL(p, 0, 0);
    1819             :                 }
    1820       10326 :                 p += 2;
    1821             : 
    1822       10326 :                 SBVAL(p,0,file_id); p += 8;
    1823       10326 :                 status = srvstr_push(base_data, flags2, p,
    1824             :                                   fname, PTR_DIFF(end_data, p),
    1825             :                                   STR_TERMINATE_ASCII, &len);
    1826       10326 :                 if (!NT_STATUS_IS_OK(status)) {
    1827           8 :                         return status;
    1828             :                 }
    1829       10318 :                 SIVAL(q,0,len);
    1830       10318 :                 p += len;
    1831             : 
    1832       10318 :                 len = PTR_DIFF(p, pdata);
    1833       10318 :                 pad = (len + (align-1)) & ~(align-1);
    1834             :                 /*
    1835             :                  * offset to the next entry, the caller
    1836             :                  * will overwrite it for the last entry
    1837             :                  * that's why we always include the padding
    1838             :                  */
    1839       10318 :                 SIVAL(pdata,0,pad);
    1840             :                 /*
    1841             :                  * set padding to zero
    1842             :                  */
    1843       10318 :                 if (do_pad) {
    1844           0 :                         memset(p, 0, pad - len);
    1845           0 :                         p = pdata + pad;
    1846             :                 } else {
    1847       10318 :                         p = pdata + len;
    1848             :                 }
    1849       10318 :                 break;
    1850             : 
    1851             :         /* CIFS UNIX Extension. */
    1852             : 
    1853           0 :         case SMB_FIND_FILE_UNIX:
    1854             :         case SMB_FIND_FILE_UNIX_INFO2:
    1855           0 :                 p+= 4;
    1856           0 :                 SIVAL(p,0,reskey); p+= 4;    /* Used for continuing search. */
    1857             : 
    1858             :                 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
    1859             : 
    1860           0 :                 if (info_level == SMB_FIND_FILE_UNIX) {
    1861           0 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
    1862           0 :                         p = store_file_unix_basic(conn, p,
    1863             :                                                 NULL, &smb_fname->st);
    1864           0 :                         status = srvstr_push(base_data, flags2, p,
    1865             :                                           fname, PTR_DIFF(end_data, p),
    1866             :                                           STR_TERMINATE, &len);
    1867           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1868           0 :                                 return status;
    1869             :                         }
    1870             :                 } else {
    1871           0 :                         DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
    1872           0 :                         p = store_file_unix_basic_info2(conn, p,
    1873             :                                                 NULL, &smb_fname->st);
    1874           0 :                         nameptr = p;
    1875           0 :                         p += 4;
    1876           0 :                         status = srvstr_push(base_data, flags2, p, fname,
    1877             :                                           PTR_DIFF(end_data, p), 0, &len);
    1878           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1879           0 :                                 return status;
    1880             :                         }
    1881           0 :                         SIVAL(nameptr, 0, len);
    1882             :                 }
    1883             : 
    1884           0 :                 p += len;
    1885             : 
    1886           0 :                 len = PTR_DIFF(p, pdata);
    1887           0 :                 pad = (len + (align-1)) & ~(align-1);
    1888             :                 /*
    1889             :                  * offset to the next entry, the caller
    1890             :                  * will overwrite it for the last entry
    1891             :                  * that's why we always include the padding
    1892             :                  */
    1893           0 :                 SIVAL(pdata,0,pad);
    1894             :                 /*
    1895             :                  * set padding to zero
    1896             :                  */
    1897           0 :                 if (do_pad) {
    1898           0 :                         memset(p, 0, pad - len);
    1899           0 :                         p = pdata + pad;
    1900             :                 } else {
    1901           0 :                         p = pdata + len;
    1902             :                 }
    1903             :                 /* End of SMB_QUERY_FILE_UNIX_BASIC */
    1904             : 
    1905           0 :                 break;
    1906             : 
    1907           0 :         default:
    1908           0 :                 return NT_STATUS_INVALID_LEVEL;
    1909             :         }
    1910             : 
    1911       10335 :         if (PTR_DIFF(p,pdata) > space_remaining) {
    1912           0 :                 DEBUG(9,("smbd_marshall_dir_entry: out of space "
    1913             :                         "(wanted %u, had %d)\n",
    1914             :                         (unsigned int)PTR_DIFF(p,pdata),
    1915             :                         space_remaining ));
    1916           0 :                 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
    1917             :         }
    1918             : 
    1919             :         /* Setup the last entry pointer, as an offset from base_data */
    1920       10335 :         *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
    1921             :         /* Advance the data pointer to the next slot */
    1922       10335 :         *ppdata = p;
    1923             : 
    1924       10335 :         return NT_STATUS_OK;
    1925             : }
    1926             : 
    1927       14630 : NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
    1928             :                                connection_struct *conn,
    1929             :                                struct dptr_struct *dirptr,
    1930             :                                uint16_t flags2,
    1931             :                                const char *path_mask,
    1932             :                                uint32_t dirtype,
    1933             :                                int info_level,
    1934             :                                int requires_resume_key,
    1935             :                                bool dont_descend,
    1936             :                                bool ask_sharemode,
    1937             :                                bool get_dosmode,
    1938             :                                uint8_t align,
    1939             :                                bool do_pad,
    1940             :                                char **ppdata,
    1941             :                                char *base_data,
    1942             :                                char *end_data,
    1943             :                                int space_remaining,
    1944             :                                struct smb_filename **_smb_fname,
    1945             :                                bool *got_exact_match,
    1946             :                                int *_last_entry_off,
    1947             :                                struct ea_list *name_list,
    1948             :                                struct file_id *file_id)
    1949             : {
    1950             :         const char *p;
    1951       14630 :         const char *mask = NULL;
    1952       14630 :         long prev_dirpos = 0;
    1953       14630 :         uint32_t mode = 0;
    1954       14630 :         char *fname = NULL;
    1955       14630 :         struct smb_filename *smb_fname = NULL;
    1956             :         struct smbd_dirptr_lanman2_state state;
    1957             :         bool ok;
    1958       14630 :         uint64_t last_entry_off = 0;
    1959             :         NTSTATUS status;
    1960             :         enum mangled_names_options mangled_names;
    1961             :         bool marshall_with_83_names;
    1962             : 
    1963       14630 :         mangled_names = lp_mangled_names(conn->params);
    1964             : 
    1965       14630 :         ZERO_STRUCT(state);
    1966       14630 :         state.conn = conn;
    1967       14630 :         state.info_level = info_level;
    1968       14630 :         if (mangled_names != MANGLED_NAMES_NO) {
    1969       14630 :                 state.check_mangled_names = true;
    1970             :         }
    1971       14630 :         state.has_wild = dptr_has_wild(dirptr);
    1972       14630 :         state.got_exact_match = false;
    1973       14630 :         state.case_sensitive = dptr_case_sensitive(dirptr);
    1974             : 
    1975       14630 :         *got_exact_match = false;
    1976             : 
    1977       14630 :         p = strrchr_m(path_mask,'/');
    1978       14630 :         if(p != NULL) {
    1979           0 :                 if(p[1] == '\0') {
    1980           0 :                         mask = "*.*";
    1981             :                 } else {
    1982           0 :                         mask = p+1;
    1983             :                 }
    1984             :         } else {
    1985       14630 :                 mask = path_mask;
    1986             :         }
    1987             : 
    1988       14630 :         ok = smbd_dirptr_get_entry(ctx,
    1989             :                                    dirptr,
    1990             :                                    mask,
    1991             :                                    dirtype,
    1992             :                                    dont_descend,
    1993             :                                    ask_sharemode,
    1994             :                                    get_dosmode,
    1995             :                                    smbd_dirptr_lanman2_match_fn,
    1996             :                                    smbd_dirptr_lanman2_mode_fn,
    1997             :                                    &state,
    1998             :                                    &fname,
    1999             :                                    &smb_fname,
    2000             :                                    &mode,
    2001             :                                    &prev_dirpos);
    2002       14630 :         if (!ok) {
    2003        4287 :                 return NT_STATUS_END_OF_FILE;
    2004             :         }
    2005             : 
    2006       10343 :         *got_exact_match = state.got_exact_match;
    2007             : 
    2008       10343 :         marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
    2009             : 
    2010       10343 :         status = smbd_marshall_dir_entry(ctx,
    2011             :                                      conn,
    2012             :                                      flags2,
    2013             :                                      info_level,
    2014             :                                      name_list,
    2015             :                                      marshall_with_83_names,
    2016             :                                      requires_resume_key,
    2017             :                                      mode,
    2018             :                                      fname,
    2019             :                                      smb_fname,
    2020             :                                      space_remaining,
    2021             :                                      align,
    2022             :                                      do_pad,
    2023             :                                      base_data,
    2024             :                                      ppdata,
    2025             :                                      end_data,
    2026             :                                      &last_entry_off);
    2027       10343 :         if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
    2028           8 :                 DEBUG(1,("Conversion error: illegal character: %s\n",
    2029             :                          smb_fname_str_dbg(smb_fname)));
    2030             :         }
    2031             : 
    2032       10343 :         if (file_id != NULL) {
    2033       10343 :                 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
    2034             :         }
    2035             : 
    2036       10347 :         if (!NT_STATUS_IS_OK(status) &&
    2037           8 :             !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
    2038             :         {
    2039           8 :                 TALLOC_FREE(smb_fname);
    2040           8 :                 TALLOC_FREE(fname);
    2041           8 :                 return status;
    2042             :         }
    2043             : 
    2044       10335 :         if (_smb_fname != NULL) {
    2045             :                 /*
    2046             :                  * smb_fname is already talloc'ed off ctx.
    2047             :                  * We just need to make sure we don't return
    2048             :                  * any stream_name, and replace base_name
    2049             :                  * with fname in case base_name got mangled.
    2050             :                  * This allows us to preserve any smb_fname->fsp
    2051             :                  * for asynchronous handle lookups.
    2052             :                  */
    2053       10335 :                 TALLOC_FREE(smb_fname->stream_name);
    2054       10335 :                 TALLOC_FREE(smb_fname->base_name);
    2055       10335 :                 smb_fname->base_name = talloc_strdup(smb_fname, fname);
    2056             : 
    2057       10335 :                 if (smb_fname->base_name == NULL) {
    2058           0 :                         TALLOC_FREE(smb_fname);
    2059           0 :                         TALLOC_FREE(fname);
    2060           0 :                         return NT_STATUS_NO_MEMORY;
    2061             :                 }
    2062       10335 :                 *_smb_fname = smb_fname;
    2063             :         } else {
    2064           0 :                 TALLOC_FREE(smb_fname);
    2065             :         }
    2066       10335 :         TALLOC_FREE(fname);
    2067             : 
    2068       10335 :         if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
    2069           0 :                 dptr_SeekDir(dirptr, prev_dirpos);
    2070           0 :                 return status;
    2071             :         }
    2072             : 
    2073       10335 :         *_last_entry_off = last_entry_off;
    2074       10335 :         return NT_STATUS_OK;
    2075             : }
    2076             : 
    2077           0 : unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
    2078             : {
    2079           0 :         const struct loadparm_substitution *lp_sub =
    2080           0 :                 loadparm_s3_global_substitution();
    2081             : 
    2082           0 :         E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
    2083           0 :         return objid;
    2084             : }
    2085             : 
    2086           0 : static void samba_extended_info_version(struct smb_extended_info *extended_info)
    2087             : {
    2088           0 :         SMB_ASSERT(extended_info != NULL);
    2089             : 
    2090           0 :         extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
    2091           0 :         extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
    2092             :                                        | ((SAMBA_VERSION_MINOR & 0xff) << 16)
    2093             :                                        | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
    2094             : #ifdef SAMBA_VERSION_REVISION
    2095             :         extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
    2096             : #endif
    2097           0 :         extended_info->samba_subversion = 0;
    2098             : #ifdef SAMBA_VERSION_RC_RELEASE
    2099             :         extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
    2100             : #else
    2101             : #ifdef SAMBA_VERSION_PRE_RELEASE
    2102             :         extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
    2103             : #endif
    2104             : #endif
    2105             : #ifdef SAMBA_VERSION_VENDOR_PATCH
    2106             :         extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
    2107             : #endif
    2108           0 :         extended_info->samba_gitcommitdate = 0;
    2109             : #ifdef SAMBA_VERSION_COMMIT_TIME
    2110             :         unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
    2111             : #endif
    2112             : 
    2113           0 :         memset(extended_info->samba_version_string, 0,
    2114             :                sizeof(extended_info->samba_version_string));
    2115             : 
    2116           0 :         snprintf (extended_info->samba_version_string,
    2117             :                   sizeof(extended_info->samba_version_string),
    2118             :                   "%s", samba_version_string());
    2119           0 : }
    2120             : 
    2121         387 : NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
    2122             :                          connection_struct *conn,
    2123             :                          TALLOC_CTX *mem_ctx,
    2124             :                          uint16_t info_level,
    2125             :                          uint16_t flags2,
    2126             :                          unsigned int max_data_bytes,
    2127             :                          size_t *fixed_portion,
    2128             :                          struct smb_filename *fname,
    2129             :                          char **ppdata,
    2130             :                          int *ret_data_len)
    2131             : {
    2132         208 :         const struct loadparm_substitution *lp_sub =
    2133         179 :                 loadparm_s3_global_substitution();
    2134             :         char *pdata, *end_data;
    2135         387 :         int data_len = 0;
    2136         387 :         size_t len = 0;
    2137         387 :         const char *vname = volume_label(talloc_tos(), SNUM(conn));
    2138         387 :         int snum = SNUM(conn);
    2139         387 :         const char *fstype = lp_fstype(SNUM(conn));
    2140         387 :         const char *filename = NULL;
    2141         387 :         const uint64_t bytes_per_sector = 512;
    2142         387 :         uint32_t additional_flags = 0;
    2143             :         struct smb_filename smb_fname;
    2144             :         SMB_STRUCT_STAT st;
    2145         387 :         NTSTATUS status = NT_STATUS_OK;
    2146             :         uint64_t df_ret;
    2147             :         uint32_t serial;
    2148             : 
    2149         387 :         if (fname == NULL || fname->base_name == NULL) {
    2150           8 :                 filename = ".";
    2151             :         } else {
    2152         379 :                 filename = fname->base_name;
    2153             :         }
    2154             : 
    2155         387 :         if (IS_IPC(conn)) {
    2156           0 :                 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
    2157           0 :                         DEBUG(0,("smbd_do_qfsinfo: not an allowed "
    2158             :                                 "info level (0x%x) on IPC$.\n",
    2159             :                                 (unsigned int)info_level));
    2160           0 :                         return NT_STATUS_ACCESS_DENIED;
    2161             :                 }
    2162             :         }
    2163             : 
    2164         387 :         DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
    2165             : 
    2166         387 :         smb_fname = (struct smb_filename) {
    2167             :                 .base_name = discard_const_p(char, filename),
    2168         387 :                 .flags = fname ? fname->flags : 0,
    2169         387 :                 .twrp = fname ? fname->twrp : 0,
    2170             :         };
    2171             : 
    2172         387 :         if(info_level != SMB_FS_QUOTA_INFORMATION
    2173         387 :            && SMB_VFS_STAT(conn, &smb_fname) != 0) {
    2174           0 :                 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
    2175           0 :                 return map_nt_error_from_unix(errno);
    2176             :         }
    2177             : 
    2178         387 :         st = smb_fname.st;
    2179             : 
    2180         387 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    2181           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2182             :         }
    2183             : 
    2184         387 :         *ppdata = (char *)SMB_REALLOC(
    2185             :                 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2186         387 :         if (*ppdata == NULL) {
    2187           0 :                 return NT_STATUS_NO_MEMORY;
    2188             :         }
    2189             : 
    2190         387 :         pdata = *ppdata;
    2191         387 :         memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
    2192         387 :         end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
    2193             : 
    2194         387 :         *fixed_portion = 0;
    2195             : 
    2196         387 :         switch (info_level) {
    2197           0 :                 case SMB_INFO_ALLOCATION:
    2198             :                 {
    2199             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2200           0 :                         data_len = 18;
    2201           0 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2202             :                                                 &dfree, &dsize);
    2203           0 :                         if (df_ret == (uint64_t)-1) {
    2204           0 :                                 return map_nt_error_from_unix(errno);
    2205             :                         }
    2206             : 
    2207           0 :                         block_size = lp_block_size(snum);
    2208           0 :                         if (bsize < block_size) {
    2209           0 :                                 uint64_t factor = block_size/bsize;
    2210           0 :                                 bsize = block_size;
    2211           0 :                                 dsize /= factor;
    2212           0 :                                 dfree /= factor;
    2213             :                         }
    2214           0 :                         if (bsize > block_size) {
    2215           0 :                                 uint64_t factor = bsize/block_size;
    2216           0 :                                 bsize = block_size;
    2217           0 :                                 dsize *= factor;
    2218           0 :                                 dfree *= factor;
    2219             :                         }
    2220           0 :                         sectors_per_unit = bsize/bytes_per_sector;
    2221             : 
    2222           0 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
    2223             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2224             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2225             : 
    2226             :                         /*
    2227             :                          * For large drives, return max values and not modulo.
    2228             :                          */
    2229           0 :                         dsize = MIN(dsize, UINT32_MAX);
    2230           0 :                         dfree = MIN(dfree, UINT32_MAX);
    2231             : 
    2232           0 :                         SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
    2233           0 :                         SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
    2234           0 :                         SIVAL(pdata,l1_cUnit,dsize);
    2235           0 :                         SIVAL(pdata,l1_cUnitAvail,dfree);
    2236           0 :                         SSVAL(pdata,l1_cbSector,bytes_per_sector);
    2237           0 :                         break;
    2238             :                 }
    2239             : 
    2240           0 :                 case SMB_INFO_VOLUME:
    2241             :                         /* Return volume name */
    2242             :                         /* 
    2243             :                          * Add volume serial number - hash of a combination of
    2244             :                          * the called hostname and the service name.
    2245             :                          */
    2246           0 :                         serial = generate_volume_serial_number(lp_sub, snum);
    2247           0 :                         SIVAL(pdata,0,serial);
    2248             :                         /*
    2249             :                          * Win2k3 and previous mess this up by sending a name length
    2250             :                          * one byte short. I believe only older clients (OS/2 Win9x) use
    2251             :                          * this call so try fixing this by adding a terminating null to
    2252             :                          * the pushed string. The change here was adding the STR_TERMINATE. JRA.
    2253             :                          */
    2254           0 :                         status = srvstr_push(
    2255             :                                 pdata, flags2,
    2256             :                                 pdata+l2_vol_szVolLabel, vname,
    2257             :                                 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
    2258             :                                 STR_NOALIGN|STR_TERMINATE, &len);
    2259           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2260           0 :                                 return status;
    2261             :                         }
    2262           0 :                         SCVAL(pdata,l2_vol_cch,len);
    2263           0 :                         data_len = l2_vol_szVolLabel + len;
    2264           0 :                         DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
    2265             :                                  "name = %s serial = 0x%04"PRIx32"\n",
    2266             :                                  (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
    2267             :                                  (unsigned)len, vname, serial));
    2268           0 :                         break;
    2269             : 
    2270           0 :                 case SMB_QUERY_FS_ATTRIBUTE_INFO:
    2271             :                 case SMB_FS_ATTRIBUTE_INFORMATION:
    2272             : 
    2273           0 :                         additional_flags = 0;
    2274             : #if defined(HAVE_SYS_QUOTAS)
    2275           0 :                         additional_flags |= FILE_VOLUME_QUOTAS;
    2276             : #endif
    2277             : 
    2278           0 :                         if(lp_nt_acl_support(SNUM(conn))) {
    2279           0 :                                 additional_flags |= FILE_PERSISTENT_ACLS;
    2280             :                         }
    2281             : 
    2282             :                         /* Capabilities are filled in at connection time through STATVFS call */
    2283           0 :                         additional_flags |= conn->fs_capabilities;
    2284           0 :                         additional_flags |= lp_parm_int(conn->params->service,
    2285             :                                                         "share", "fake_fscaps",
    2286             :                                                         0);
    2287             : 
    2288           0 :                         SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
    2289             :                                 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
    2290             :                                 additional_flags); /* FS ATTRIBUTES */
    2291             : 
    2292           0 :                         SIVAL(pdata,4,255); /* Max filename component length */
    2293             :                         /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
    2294             :                                 and will think we can't do long filenames */
    2295           0 :                         status = srvstr_push(pdata, flags2, pdata+12, fstype,
    2296             :                                           PTR_DIFF(end_data, pdata+12),
    2297             :                                           STR_UNICODE, &len);
    2298           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2299           0 :                                 return status;
    2300             :                         }
    2301           0 :                         SIVAL(pdata,8,len);
    2302           0 :                         data_len = 12 + len;
    2303           0 :                         if (max_data_bytes >= 16 && data_len > max_data_bytes) {
    2304             :                                 /* the client only requested a portion of the
    2305             :                                    file system name */
    2306           0 :                                 data_len = max_data_bytes;
    2307           0 :                                 status = STATUS_BUFFER_OVERFLOW;
    2308             :                         }
    2309           0 :                         *fixed_portion = 16;
    2310           0 :                         break;
    2311             : 
    2312           0 :                 case SMB_QUERY_FS_LABEL_INFO:
    2313             :                 case SMB_FS_LABEL_INFORMATION:
    2314           0 :                         status = srvstr_push(pdata, flags2, pdata+4, vname,
    2315             :                                           PTR_DIFF(end_data, pdata+4), 0, &len);
    2316           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2317           0 :                                 return status;
    2318             :                         }
    2319           0 :                         data_len = 4 + len;
    2320           0 :                         SIVAL(pdata,0,len);
    2321           0 :                         break;
    2322             : 
    2323           4 :                 case SMB_QUERY_FS_VOLUME_INFO:      
    2324             :                 case SMB_FS_VOLUME_INFORMATION:
    2325           4 :                         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
    2326             :                                                     pdata, &st.st_ex_btime);
    2327             :                         /* 
    2328             :                          * Add volume serial number - hash of a combination of
    2329             :                          * the called hostname and the service name.
    2330             :                          */
    2331           4 :                         serial = generate_volume_serial_number(lp_sub, snum);
    2332           4 :                         SIVAL(pdata,8,serial);
    2333             : 
    2334             :                         /* Max label len is 32 characters. */
    2335           4 :                         status = srvstr_push(pdata, flags2, pdata+18, vname,
    2336             :                                           PTR_DIFF(end_data, pdata+18),
    2337             :                                           STR_UNICODE, &len);
    2338           4 :                         if (!NT_STATUS_IS_OK(status)) {
    2339           0 :                                 return status;
    2340             :                         }
    2341           4 :                         SIVAL(pdata,12,len);
    2342           4 :                         data_len = 18+len;
    2343             : 
    2344           4 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
    2345             :                                  "namelen = %d, vol=%s serv=%s "
    2346             :                                  "serial=0x%04"PRIx32"\n",
    2347             :                                  (int)strlen(vname),vname,
    2348             :                                  lp_servicename(talloc_tos(), lp_sub, snum),
    2349             :                                  serial));
    2350           4 :                         if (max_data_bytes >= 24 && data_len > max_data_bytes) {
    2351             :                                 /* the client only requested a portion of the
    2352             :                                    volume label */
    2353           0 :                                 data_len = max_data_bytes;
    2354           0 :                                 status = STATUS_BUFFER_OVERFLOW;
    2355             :                         }
    2356           4 :                         *fixed_portion = 24;
    2357           4 :                         break;
    2358             : 
    2359         375 :                 case SMB_QUERY_FS_SIZE_INFO:
    2360             :                 case SMB_FS_SIZE_INFORMATION:
    2361             :                 {
    2362             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2363         375 :                         data_len = 24;
    2364         375 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2365             :                                                 &dfree, &dsize);
    2366         375 :                         if (df_ret == (uint64_t)-1) {
    2367           0 :                                 return map_nt_error_from_unix(errno);
    2368             :                         }
    2369         375 :                         block_size = lp_block_size(snum);
    2370         375 :                         if (bsize < block_size) {
    2371         375 :                                 uint64_t factor = block_size/bsize;
    2372         375 :                                 bsize = block_size;
    2373         375 :                                 dsize /= factor;
    2374         375 :                                 dfree /= factor;
    2375             :                         }
    2376         375 :                         if (bsize > block_size) {
    2377           0 :                                 uint64_t factor = bsize/block_size;
    2378           0 :                                 bsize = block_size;
    2379           0 :                                 dsize *= factor;
    2380           0 :                                 dfree *= factor;
    2381             :                         }
    2382         375 :                         sectors_per_unit = bsize/bytes_per_sector;
    2383         375 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    2384             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2385             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2386         375 :                         SBIG_UINT(pdata,0,dsize);
    2387         375 :                         SBIG_UINT(pdata,8,dfree);
    2388         375 :                         SIVAL(pdata,16,sectors_per_unit);
    2389         375 :                         SIVAL(pdata,20,bytes_per_sector);
    2390         375 :                         *fixed_portion = 24;
    2391         375 :                         break;
    2392             :                 }
    2393             : 
    2394           0 :                 case SMB_FS_FULL_SIZE_INFORMATION:
    2395             :                 {
    2396             :                         uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
    2397           0 :                         data_len = 32;
    2398           0 :                         df_ret = get_dfree_info(conn, &smb_fname, &bsize,
    2399             :                                                 &dfree, &dsize);
    2400           0 :                         if (df_ret == (uint64_t)-1) {
    2401           0 :                                 return map_nt_error_from_unix(errno);
    2402             :                         }
    2403           0 :                         block_size = lp_block_size(snum);
    2404           0 :                         if (bsize < block_size) {
    2405           0 :                                 uint64_t factor = block_size/bsize;
    2406           0 :                                 bsize = block_size;
    2407           0 :                                 dsize /= factor;
    2408           0 :                                 dfree /= factor;
    2409             :                         }
    2410           0 :                         if (bsize > block_size) {
    2411           0 :                                 uint64_t factor = bsize/block_size;
    2412           0 :                                 bsize = block_size;
    2413           0 :                                 dsize *= factor;
    2414           0 :                                 dfree *= factor;
    2415             :                         }
    2416           0 :                         sectors_per_unit = bsize/bytes_per_sector;
    2417           0 :                         DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
    2418             : cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
    2419             :                                 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
    2420           0 :                         SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
    2421           0 :                         SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
    2422           0 :                         SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
    2423           0 :                         SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
    2424           0 :                         SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
    2425           0 :                         *fixed_portion = 32;
    2426           0 :                         break;
    2427             :                 }
    2428             : 
    2429           0 :                 case SMB_QUERY_FS_DEVICE_INFO:
    2430             :                 case SMB_FS_DEVICE_INFORMATION:
    2431             :                 {
    2432           0 :                         uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
    2433             : 
    2434           0 :                         if (!CAN_WRITE(conn)) {
    2435           0 :                                 characteristics |= FILE_READ_ONLY_DEVICE;
    2436             :                         }
    2437           0 :                         data_len = 8;
    2438           0 :                         SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
    2439           0 :                         SIVAL(pdata,4,characteristics);
    2440           0 :                         *fixed_portion = 8;
    2441           0 :                         break;
    2442             :                 }
    2443             : 
    2444             : #ifdef HAVE_SYS_QUOTAS
    2445           0 :                 case SMB_FS_QUOTA_INFORMATION:
    2446             :                 /* 
    2447             :                  * what we have to send --metze:
    2448             :                  *
    2449             :                  * Unknown1:            24 NULL bytes
    2450             :                  * Soft Quota Treshold: 8 bytes seems like uint64_t or so
    2451             :                  * Hard Quota Limit:    8 bytes seems like uint64_t or so
    2452             :                  * Quota Flags:         2 byte :
    2453             :                  * Unknown3:            6 NULL bytes
    2454             :                  *
    2455             :                  * 48 bytes total
    2456             :                  * 
    2457             :                  * details for Quota Flags:
    2458             :                  * 
    2459             :                  * 0x0020 Log Limit: log if the user exceeds his Hard Quota
    2460             :                  * 0x0010 Log Warn:  log if the user exceeds his Soft Quota
    2461             :                  * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
    2462             :                  * 0x0001 Enable Quotas: enable quota for this fs
    2463             :                  *
    2464             :                  */
    2465             :                 {
    2466             :                         /* we need to fake up a fsp here,
    2467             :                          * because its not send in this call
    2468             :                          */
    2469             :                         files_struct fsp;
    2470             :                         SMB_NTQUOTA_STRUCT quotas;
    2471             : 
    2472           0 :                         ZERO_STRUCT(fsp);
    2473           0 :                         ZERO_STRUCT(quotas);
    2474             : 
    2475           0 :                         fsp.conn = conn;
    2476           0 :                         fsp.fnum = FNUM_FIELD_INVALID;
    2477             : 
    2478             :                         /* access check */
    2479           0 :                         if (get_current_uid(conn) != 0) {
    2480           0 :                                 DEBUG(0,("get_user_quota: access_denied "
    2481             :                                          "service [%s] user [%s]\n",
    2482             :                                          lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2483             :                                          conn->session_info->unix_info->unix_name));
    2484           0 :                                 return NT_STATUS_ACCESS_DENIED;
    2485             :                         }
    2486             : 
    2487           0 :                         status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
    2488             :                                                  NULL, &quotas);
    2489           0 :                         if (!NT_STATUS_IS_OK(status)) {
    2490           0 :                                 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2491           0 :                                 return status;
    2492             :                         }
    2493             : 
    2494           0 :                         data_len = 48;
    2495             : 
    2496           0 :                         DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
    2497             :                                   lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2498             : 
    2499             :                         /* Unknown1 24 NULL bytes*/
    2500           0 :                         SBIG_UINT(pdata,0,(uint64_t)0);
    2501           0 :                         SBIG_UINT(pdata,8,(uint64_t)0);
    2502           0 :                         SBIG_UINT(pdata,16,(uint64_t)0);
    2503             : 
    2504             :                         /* Default Soft Quota 8 bytes */
    2505           0 :                         SBIG_UINT(pdata,24,quotas.softlim);
    2506             : 
    2507             :                         /* Default Hard Quota 8 bytes */
    2508           0 :                         SBIG_UINT(pdata,32,quotas.hardlim);
    2509             : 
    2510             :                         /* Quota flag 2 bytes */
    2511           0 :                         SSVAL(pdata,40,quotas.qflags);
    2512             : 
    2513             :                         /* Unknown3 6 NULL bytes */
    2514           0 :                         SSVAL(pdata,42,0);
    2515           0 :                         SIVAL(pdata,44,0);
    2516             : 
    2517           0 :                         break;
    2518             :                 }
    2519             : #endif /* HAVE_SYS_QUOTAS */
    2520           0 :                 case SMB_FS_OBJECTID_INFORMATION:
    2521             :                 {
    2522             :                         unsigned char objid[16];
    2523             :                         struct smb_extended_info extended_info;
    2524           0 :                         memcpy(pdata,create_volume_objectid(conn, objid),16);
    2525           0 :                         samba_extended_info_version (&extended_info);
    2526           0 :                         SIVAL(pdata,16,extended_info.samba_magic);
    2527           0 :                         SIVAL(pdata,20,extended_info.samba_version);
    2528           0 :                         SIVAL(pdata,24,extended_info.samba_subversion);
    2529           0 :                         SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
    2530           0 :                         memcpy(pdata+36,extended_info.samba_version_string,28);
    2531           0 :                         data_len = 64;
    2532           0 :                         break;
    2533             :                 }
    2534             : 
    2535           0 :                 case SMB_FS_SECTOR_SIZE_INFORMATION:
    2536             :                 {
    2537           0 :                         data_len = 28;
    2538             :                         /*
    2539             :                          * These values match a physical Windows Server 2012
    2540             :                          * share backed by NTFS atop spinning rust.
    2541             :                          */
    2542           0 :                         DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
    2543             :                         /* logical_bytes_per_sector */
    2544           0 :                         SIVAL(pdata, 0, bytes_per_sector);
    2545             :                         /* phys_bytes_per_sector_atomic */
    2546           0 :                         SIVAL(pdata, 4, bytes_per_sector);
    2547             :                         /* phys_bytes_per_sector_perf */
    2548           0 :                         SIVAL(pdata, 8, bytes_per_sector);
    2549             :                         /* fs_effective_phys_bytes_per_sector_atomic */
    2550           0 :                         SIVAL(pdata, 12, bytes_per_sector);
    2551             :                         /* flags */
    2552           0 :                         SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
    2553             :                                 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
    2554             :                         /* byte_off_sector_align */
    2555           0 :                         SIVAL(pdata, 20, 0);
    2556             :                         /* byte_off_partition_align */
    2557           0 :                         SIVAL(pdata, 24, 0);
    2558           0 :                         *fixed_portion = 28;
    2559           0 :                         break;
    2560             :                 }
    2561             : 
    2562             : 
    2563             : #if defined(WITH_SMB1SERVER)
    2564             :                 /*
    2565             :                  * Query the version and capabilities of the CIFS UNIX extensions
    2566             :                  * in use.
    2567             :                  */
    2568             : 
    2569           0 :                 case SMB_QUERY_CIFS_UNIX_INFO:
    2570             :                 {
    2571           0 :                         bool large_write = lp_min_receive_file_size() &&
    2572           0 :                                         !smb1_srv_is_signing_active(xconn);
    2573           0 :                         bool large_read = !smb1_srv_is_signing_active(xconn);
    2574           0 :                         int encrypt_caps = 0;
    2575             : 
    2576           0 :                         if (!lp_smb1_unix_extensions()) {
    2577           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2578             :                         }
    2579             : 
    2580           0 :                         switch (conn->encrypt_level) {
    2581           0 :                         case SMB_SIGNING_OFF:
    2582           0 :                                 encrypt_caps = 0;
    2583           0 :                                 break;
    2584           0 :                         case SMB_SIGNING_DESIRED:
    2585             :                         case SMB_SIGNING_IF_REQUIRED:
    2586             :                         case SMB_SIGNING_DEFAULT:
    2587           0 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
    2588           0 :                                 break;
    2589           0 :                         case SMB_SIGNING_REQUIRED:
    2590           0 :                                 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
    2591             :                                                 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
    2592           0 :                                 large_write = false;
    2593           0 :                                 large_read = false;
    2594           0 :                                 break;
    2595             :                         }
    2596             : 
    2597           0 :                         data_len = 12;
    2598           0 :                         SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
    2599           0 :                         SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
    2600             : 
    2601             :                         /* We have POSIX ACLs, pathname, encryption, 
    2602             :                          * large read/write, and locking capability. */
    2603             : 
    2604           0 :                         SBIG_UINT(pdata,4,((uint64_t)(
    2605             :                                         CIFS_UNIX_POSIX_ACLS_CAP|
    2606             :                                         CIFS_UNIX_POSIX_PATHNAMES_CAP|
    2607             :                                         CIFS_UNIX_FCNTL_LOCKS_CAP|
    2608             :                                         CIFS_UNIX_EXTATTR_CAP|
    2609             :                                         CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
    2610             :                                         encrypt_caps|
    2611             :                                         (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
    2612             :                                         (large_write ?
    2613             :                                         CIFS_UNIX_LARGE_WRITE_CAP : 0))));
    2614           0 :                         break;
    2615             :                 }
    2616             : #endif
    2617             : 
    2618           0 :                 case SMB_QUERY_POSIX_FS_INFO:
    2619             :                 {
    2620             :                         int rc;
    2621             :                         struct vfs_statvfs_struct svfs;
    2622             : 
    2623           0 :                         if (!lp_smb1_unix_extensions()) {
    2624           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2625             :                         }
    2626             : 
    2627           0 :                         rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
    2628             : 
    2629           0 :                         if (!rc) {
    2630           0 :                                 data_len = 56;
    2631           0 :                                 SIVAL(pdata,0,svfs.OptimalTransferSize);
    2632           0 :                                 SIVAL(pdata,4,svfs.BlockSize);
    2633           0 :                                 SBIG_UINT(pdata,8,svfs.TotalBlocks);
    2634           0 :                                 SBIG_UINT(pdata,16,svfs.BlocksAvail);
    2635           0 :                                 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
    2636           0 :                                 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
    2637           0 :                                 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
    2638           0 :                                 SBIG_UINT(pdata,48,svfs.FsIdentifier);
    2639           0 :                                 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
    2640             : #ifdef EOPNOTSUPP
    2641           0 :                         } else if (rc == EOPNOTSUPP) {
    2642           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2643             : #endif /* EOPNOTSUPP */
    2644             :                         } else {
    2645           0 :                                 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2646           0 :                                 return NT_STATUS_DOS(ERRSRV, ERRerror);
    2647             :                         }
    2648           0 :                         break;
    2649             :                 }
    2650             : 
    2651           8 :                 case SMB_QUERY_POSIX_WHOAMI:
    2652             :                 {
    2653           8 :                         uint32_t flags = 0;
    2654             :                         uint32_t sid_bytes;
    2655             :                         uint32_t i;
    2656             : 
    2657           8 :                         if (!lp_smb1_unix_extensions()) {
    2658           0 :                                 return NT_STATUS_INVALID_LEVEL;
    2659             :                         }
    2660             : 
    2661           8 :                         if (max_data_bytes < 40) {
    2662           0 :                                 return NT_STATUS_BUFFER_TOO_SMALL;
    2663             :                         }
    2664             : 
    2665           8 :                         if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
    2666           0 :                                 flags |= SMB_WHOAMI_GUEST;
    2667             :                         }
    2668             : 
    2669             :                         /* NOTE: 8 bytes for UID/GID, irrespective of native
    2670             :                          * platform size. This matches
    2671             :                          * SMB_QUERY_FILE_UNIX_BASIC and friends.
    2672             :                          */
    2673           8 :                         data_len = 4 /* flags */
    2674             :                             + 4 /* flag mask */
    2675             :                             + 8 /* uid */
    2676             :                             + 8 /* gid */
    2677             :                             + 4 /* ngroups */
    2678             :                             + 4 /* num_sids */
    2679             :                             + 4 /* SID bytes */
    2680             :                             + 4 /* pad/reserved */
    2681           8 :                             + (conn->session_info->unix_token->ngroups * 8)
    2682             :                                 /* groups list */
    2683           8 :                             + (conn->session_info->security_token->num_sids *
    2684             :                                     SID_MAX_SIZE)
    2685             :                                 /* SID list */;
    2686             : 
    2687           8 :                         SIVAL(pdata, 0, flags);
    2688           8 :                         SIVAL(pdata, 4, SMB_WHOAMI_MASK);
    2689           8 :                         SBIG_UINT(pdata, 8,
    2690             :                                   (uint64_t)conn->session_info->unix_token->uid);
    2691           8 :                         SBIG_UINT(pdata, 16,
    2692             :                                   (uint64_t)conn->session_info->unix_token->gid);
    2693             : 
    2694             : 
    2695           8 :                         if (data_len >= max_data_bytes) {
    2696             :                                 /* Potential overflow, skip the GIDs and SIDs. */
    2697             : 
    2698           0 :                                 SIVAL(pdata, 24, 0); /* num_groups */
    2699           0 :                                 SIVAL(pdata, 28, 0); /* num_sids */
    2700           0 :                                 SIVAL(pdata, 32, 0); /* num_sid_bytes */
    2701           0 :                                 SIVAL(pdata, 36, 0); /* reserved */
    2702             : 
    2703           0 :                                 data_len = 40;
    2704           0 :                                 break;
    2705             :                         }
    2706             : 
    2707           8 :                         SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
    2708           8 :                         SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
    2709             : 
    2710             :                         /* We walk the SID list twice, but this call is fairly
    2711             :                          * infrequent, and I don't expect that it's performance
    2712             :                          * sensitive -- jpeach
    2713             :                          */
    2714          57 :                         for (i = 0, sid_bytes = 0;
    2715          94 :                              i < conn->session_info->security_token->num_sids; ++i) {
    2716          90 :                                 sid_bytes += ndr_size_dom_sid(
    2717          90 :                                         &conn->session_info->security_token->sids[i],
    2718             :                                         0);
    2719             :                         }
    2720             : 
    2721             :                         /* SID list byte count */
    2722           8 :                         SIVAL(pdata, 32, sid_bytes);
    2723             : 
    2724             :                         /* 4 bytes pad/reserved - must be zero */
    2725           8 :                         SIVAL(pdata, 36, 0);
    2726           8 :                         data_len = 40;
    2727             : 
    2728             :                         /* GID list */
    2729          44 :                         for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
    2730          36 :                                 SBIG_UINT(pdata, data_len,
    2731             :                                           (uint64_t)conn->session_info->unix_token->groups[i]);
    2732          36 :                                 data_len += 8;
    2733             :                         }
    2734             : 
    2735             :                         /* SID list */
    2736          57 :                         for (i = 0;
    2737          94 :                             i < conn->session_info->security_token->num_sids; ++i) {
    2738         135 :                                 int sid_len = ndr_size_dom_sid(
    2739          90 :                                         &conn->session_info->security_token->sids[i],
    2740             :                                         0);
    2741             : 
    2742          90 :                                 sid_linearize((uint8_t *)(pdata + data_len),
    2743             :                                               sid_len,
    2744          90 :                                     &conn->session_info->security_token->sids[i]);
    2745          90 :                                 data_len += sid_len;
    2746             :                         }
    2747             : 
    2748           8 :                         break;
    2749             :                 }
    2750             : 
    2751           0 :                 case SMB_MAC_QUERY_FS_INFO:
    2752             :                         /*
    2753             :                          * Thursby MAC extension... ONLY on NTFS filesystems
    2754             :                          * once we do streams then we don't need this
    2755             :                          */
    2756           0 :                         if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
    2757           0 :                                 data_len = 88;
    2758           0 :                                 SIVAL(pdata,84,0x100); /* Don't support mac... */
    2759           0 :                                 break;
    2760             :                         }
    2761             : 
    2762             :                         FALL_THROUGH;
    2763             :                 default:
    2764           0 :                         return NT_STATUS_INVALID_LEVEL;
    2765             :         }
    2766             : 
    2767         387 :         *ret_data_len = data_len;
    2768         387 :         return status;
    2769             : }
    2770             : 
    2771           0 : NTSTATUS smb_set_fsquota(connection_struct *conn,
    2772             :                          struct smb_request *req,
    2773             :                          files_struct *fsp,
    2774             :                          const DATA_BLOB *qdata)
    2775             : {
    2776           0 :         const struct loadparm_substitution *lp_sub =
    2777           0 :                 loadparm_s3_global_substitution();
    2778             :         NTSTATUS status;
    2779             :         SMB_NTQUOTA_STRUCT quotas;
    2780             : 
    2781           0 :         ZERO_STRUCT(quotas);
    2782             : 
    2783             :         /* access check */
    2784           0 :         if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
    2785           0 :                 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
    2786             :                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
    2787             :                           conn->session_info->unix_info->unix_name));
    2788           0 :                 return NT_STATUS_ACCESS_DENIED;
    2789             :         }
    2790             : 
    2791           0 :         if (!check_fsp_ntquota_handle(conn, req,
    2792             :                                       fsp)) {
    2793           0 :                 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
    2794           0 :                 return NT_STATUS_INVALID_HANDLE;
    2795             :         }
    2796             : 
    2797             :         /* note: normally there're 48 bytes,
    2798             :          * but we didn't use the last 6 bytes for now
    2799             :          * --metze
    2800             :          */
    2801           0 :         if (qdata->length < 42) {
    2802           0 :                 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
    2803             :                         (unsigned int)qdata->length));
    2804           0 :                 return NT_STATUS_INVALID_PARAMETER;
    2805             :         }
    2806             : 
    2807             :         /* unknown_1 24 NULL bytes in pdata*/
    2808             : 
    2809             :         /* the soft quotas 8 bytes (uint64_t)*/
    2810           0 :         quotas.softlim = BVAL(qdata->data,24);
    2811             : 
    2812             :         /* the hard quotas 8 bytes (uint64_t)*/
    2813           0 :         quotas.hardlim = BVAL(qdata->data,32);
    2814             : 
    2815             :         /* quota_flags 2 bytes **/
    2816           0 :         quotas.qflags = SVAL(qdata->data,40);
    2817             : 
    2818             :         /* unknown_2 6 NULL bytes follow*/
    2819             : 
    2820             :         /* now set the quotas */
    2821           0 :         if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
    2822           0 :                 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
    2823             :                           lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
    2824           0 :                 status =  map_nt_error_from_unix(errno);
    2825             :         } else {
    2826           0 :                 status = NT_STATUS_OK;
    2827             :         }
    2828           0 :         return status;
    2829             : }
    2830             : 
    2831           0 : NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
    2832             :                                 struct smb_request *req,
    2833             :                                 TALLOC_CTX *mem_ctx,
    2834             :                                 uint16_t info_level,
    2835             :                                 files_struct *fsp,
    2836             :                                 const DATA_BLOB *pdata)
    2837             : {
    2838           0 :         switch (info_level) {
    2839           0 :                 case SMB_FS_QUOTA_INFORMATION:
    2840             :                 {
    2841           0 :                         return smb_set_fsquota(conn,
    2842             :                                                 req,
    2843             :                                                 fsp,
    2844             :                                                 pdata);
    2845             :                 }
    2846             : 
    2847           0 :                 default:
    2848           0 :                         break;
    2849             :         }
    2850           0 :         return NT_STATUS_INVALID_LEVEL;
    2851             : }
    2852             : 
    2853             : #if defined(HAVE_POSIX_ACLS)
    2854             : /****************************************************************************
    2855             :  Utility function to count the number of entries in a POSIX acl.
    2856             : ****************************************************************************/
    2857             : 
    2858           0 : static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
    2859             : {
    2860           0 :         unsigned int ace_count = 0;
    2861           0 :         int entry_id = SMB_ACL_FIRST_ENTRY;
    2862             :         SMB_ACL_ENTRY_T entry;
    2863             : 
    2864           0 :         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
    2865             :                 /* get_next... */
    2866           0 :                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
    2867           0 :                         entry_id = SMB_ACL_NEXT_ENTRY;
    2868             :                 }
    2869           0 :                 ace_count++;
    2870             :         }
    2871           0 :         return ace_count;
    2872             : }
    2873             : 
    2874             : /****************************************************************************
    2875             :  Utility function to marshall a POSIX acl into wire format.
    2876             : ****************************************************************************/
    2877             : 
    2878           0 : static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
    2879             : {
    2880           0 :         int entry_id = SMB_ACL_FIRST_ENTRY;
    2881             :         SMB_ACL_ENTRY_T entry;
    2882             : 
    2883           0 :         while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
    2884             :                 SMB_ACL_TAG_T tagtype;
    2885             :                 SMB_ACL_PERMSET_T permset;
    2886           0 :                 unsigned char perms = 0;
    2887             :                 unsigned int own_grp;
    2888             : 
    2889             :                 /* get_next... */
    2890           0 :                 if (entry_id == SMB_ACL_FIRST_ENTRY) {
    2891           0 :                         entry_id = SMB_ACL_NEXT_ENTRY;
    2892             :                 }
    2893             : 
    2894           0 :                 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
    2895           0 :                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
    2896           0 :                         return False;
    2897             :                 }
    2898             : 
    2899           0 :                 if (sys_acl_get_permset(entry, &permset) == -1) {
    2900           0 :                         DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
    2901           0 :                         return False;
    2902             :                 }
    2903             : 
    2904           0 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
    2905           0 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
    2906           0 :                 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
    2907             : 
    2908           0 :                 SCVAL(pdata,1,perms);
    2909             : 
    2910           0 :                 switch (tagtype) {
    2911           0 :                         case SMB_ACL_USER_OBJ:
    2912           0 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
    2913           0 :                                 own_grp = (unsigned int)pst->st_ex_uid;
    2914           0 :                                 SIVAL(pdata,2,own_grp);
    2915           0 :                                 SIVAL(pdata,6,0);
    2916           0 :                                 break;
    2917           0 :                         case SMB_ACL_USER:
    2918             :                                 {
    2919           0 :                                         uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
    2920           0 :                                         if (!puid) {
    2921           0 :                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
    2922           0 :                                                 return False;
    2923             :                                         }
    2924           0 :                                         own_grp = (unsigned int)*puid;
    2925           0 :                                         SCVAL(pdata,0,SMB_POSIX_ACL_USER);
    2926           0 :                                         SIVAL(pdata,2,own_grp);
    2927           0 :                                         SIVAL(pdata,6,0);
    2928           0 :                                         break;
    2929             :                                 }
    2930           0 :                         case SMB_ACL_GROUP_OBJ:
    2931           0 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
    2932           0 :                                 own_grp = (unsigned int)pst->st_ex_gid;
    2933           0 :                                 SIVAL(pdata,2,own_grp);
    2934           0 :                                 SIVAL(pdata,6,0);
    2935           0 :                                 break;
    2936           0 :                         case SMB_ACL_GROUP:
    2937             :                                 {
    2938           0 :                                         gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
    2939           0 :                                         if (!pgid) {
    2940           0 :                                                 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
    2941           0 :                                                 return False;
    2942             :                                         }
    2943           0 :                                         own_grp = (unsigned int)*pgid;
    2944           0 :                                         SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
    2945           0 :                                         SIVAL(pdata,2,own_grp);
    2946           0 :                                         SIVAL(pdata,6,0);
    2947           0 :                                         break;
    2948             :                                 }
    2949           0 :                         case SMB_ACL_MASK:
    2950           0 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
    2951           0 :                                 SIVAL(pdata,2,0xFFFFFFFF);
    2952           0 :                                 SIVAL(pdata,6,0xFFFFFFFF);
    2953           0 :                                 break;
    2954           0 :                         case SMB_ACL_OTHER:
    2955           0 :                                 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
    2956           0 :                                 SIVAL(pdata,2,0xFFFFFFFF);
    2957           0 :                                 SIVAL(pdata,6,0xFFFFFFFF);
    2958           0 :                                 break;
    2959           0 :                         default:
    2960           0 :                                 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
    2961           0 :                                 return False;
    2962             :                 }
    2963           0 :                 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
    2964             :         }
    2965             : 
    2966           0 :         return True;
    2967             : }
    2968             : #endif
    2969             : 
    2970             : /****************************************************************************
    2971             :  Store the FILE_UNIX_BASIC info.
    2972             : ****************************************************************************/
    2973             : 
    2974           0 : static char *store_file_unix_basic(connection_struct *conn,
    2975             :                                 char *pdata,
    2976             :                                 files_struct *fsp,
    2977             :                                 const SMB_STRUCT_STAT *psbuf)
    2978             : {
    2979             :         dev_t devno;
    2980             : 
    2981           0 :         DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
    2982           0 :         DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
    2983             : 
    2984           0 :         SOFF_T(pdata,0,get_file_size_stat(psbuf));             /* File size 64 Bit */
    2985           0 :         pdata += 8;
    2986             : 
    2987           0 :         SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
    2988           0 :         pdata += 8;
    2989             : 
    2990           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime);       /* Change Time 64 Bit */
    2991           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime);     /* Last access time 64 Bit */
    2992           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime);    /* Last modification time 64 Bit */
    2993           0 :         pdata += 24;
    2994             : 
    2995           0 :         SIVAL(pdata,0,psbuf->st_ex_uid);               /* user id for the owner */
    2996           0 :         SIVAL(pdata,4,0);
    2997           0 :         pdata += 8;
    2998             : 
    2999           0 :         SIVAL(pdata,0,psbuf->st_ex_gid);               /* group id of owner */
    3000           0 :         SIVAL(pdata,4,0);
    3001           0 :         pdata += 8;
    3002             : 
    3003           0 :         SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
    3004           0 :         pdata += 4;
    3005             : 
    3006           0 :         if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
    3007           0 :                 devno = psbuf->st_ex_rdev;
    3008             :         } else {
    3009           0 :                 devno = psbuf->st_ex_dev;
    3010             :         }
    3011             : 
    3012           0 :         SIVAL(pdata,0,unix_dev_major(devno));   /* Major device number if type is device */
    3013           0 :         SIVAL(pdata,4,0);
    3014           0 :         pdata += 8;
    3015             : 
    3016           0 :         SIVAL(pdata,0,unix_dev_minor(devno));   /* Minor device number if type is device */
    3017           0 :         SIVAL(pdata,4,0);
    3018           0 :         pdata += 8;
    3019             : 
    3020           0 :         SINO_T_VAL(pdata, 0, psbuf->st_ex_ino);   /* inode number */
    3021           0 :         pdata += 8;
    3022             : 
    3023           0 :         SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode));     /* Standard UNIX file permissions */
    3024           0 :         SIVAL(pdata,4,0);
    3025           0 :         pdata += 8;
    3026             : 
    3027           0 :         SIVAL(pdata,0,psbuf->st_ex_nlink);             /* number of hard links */
    3028           0 :         SIVAL(pdata,4,0);
    3029           0 :         pdata += 8;
    3030             : 
    3031           0 :         return pdata;
    3032             : }
    3033             : 
    3034             : /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
    3035             :  * the chflags(2) (or equivalent) flags.
    3036             :  *
    3037             :  * XXX: this really should be behind the VFS interface. To do this, we would
    3038             :  * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
    3039             :  * Each VFS module could then implement its own mapping as appropriate for the
    3040             :  * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
    3041             :  */
    3042             : static const struct {unsigned stat_fflag; unsigned smb_fflag;}
    3043             :         info2_flags_map[] =
    3044             : {
    3045             : #ifdef UF_NODUMP
    3046             :     { UF_NODUMP, EXT_DO_NOT_BACKUP },
    3047             : #endif
    3048             : 
    3049             : #ifdef UF_IMMUTABLE
    3050             :     { UF_IMMUTABLE, EXT_IMMUTABLE },
    3051             : #endif
    3052             : 
    3053             : #ifdef UF_APPEND
    3054             :     { UF_APPEND, EXT_OPEN_APPEND_ONLY },
    3055             : #endif
    3056             : 
    3057             : #ifdef UF_HIDDEN
    3058             :     { UF_HIDDEN, EXT_HIDDEN },
    3059             : #endif
    3060             : 
    3061             :     /* Do not remove. We need to guarantee that this array has at least one
    3062             :      * entry to build on HP-UX.
    3063             :      */
    3064             :     { 0, 0 }
    3065             : 
    3066             : };
    3067             : 
    3068           0 : static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
    3069             :                                 uint32_t *smb_fflags, uint32_t *smb_fmask)
    3070             : {
    3071             :         size_t i;
    3072             : 
    3073           0 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    3074           0 :             *smb_fmask |= info2_flags_map[i].smb_fflag;
    3075           0 :             if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
    3076           0 :                     *smb_fflags |= info2_flags_map[i].smb_fflag;
    3077             :             }
    3078             :         }
    3079           0 : }
    3080             : 
    3081           0 : static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
    3082             :                                 const uint32_t smb_fflags,
    3083             :                                 const uint32_t smb_fmask,
    3084             :                                 int *stat_fflags)
    3085             : {
    3086           0 :         uint32_t max_fmask = 0;
    3087             :         size_t i;
    3088             : 
    3089           0 :         *stat_fflags = psbuf->st_ex_flags;
    3090             : 
    3091             :         /* For each flags requested in smb_fmask, check the state of the
    3092             :          * corresponding flag in smb_fflags and set or clear the matching
    3093             :          * stat flag.
    3094             :          */
    3095             : 
    3096           0 :         for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
    3097           0 :             max_fmask |= info2_flags_map[i].smb_fflag;
    3098           0 :             if (smb_fmask & info2_flags_map[i].smb_fflag) {
    3099           0 :                     if (smb_fflags & info2_flags_map[i].smb_fflag) {
    3100           0 :                             *stat_fflags |= info2_flags_map[i].stat_fflag;
    3101             :                     } else {
    3102           0 :                             *stat_fflags &= ~info2_flags_map[i].stat_fflag;
    3103             :                     }
    3104             :             }
    3105             :         }
    3106             : 
    3107             :         /* If smb_fmask is asking to set any bits that are not supported by
    3108             :          * our flag mappings, we should fail.
    3109             :          */
    3110           0 :         if ((smb_fmask & max_fmask) != smb_fmask) {
    3111           0 :                 return False;
    3112             :         }
    3113             : 
    3114           0 :         return True;
    3115             : }
    3116             : 
    3117             : 
    3118             : /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
    3119             :  * of file flags and birth (create) time.
    3120             :  */
    3121           0 : static char *store_file_unix_basic_info2(connection_struct *conn,
    3122             :                                 char *pdata,
    3123             :                                 files_struct *fsp,
    3124             :                                 const SMB_STRUCT_STAT *psbuf)
    3125             : {
    3126           0 :         uint32_t file_flags = 0;
    3127           0 :         uint32_t flags_mask = 0;
    3128             : 
    3129           0 :         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
    3130             : 
    3131             :         /* Create (birth) time 64 bit */
    3132           0 :         put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
    3133           0 :         pdata += 8;
    3134             : 
    3135           0 :         map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
    3136           0 :         SIVAL(pdata, 0, file_flags); /* flags */
    3137           0 :         SIVAL(pdata, 4, flags_mask); /* mask */
    3138           0 :         pdata += 8;
    3139             : 
    3140           0 :         return pdata;
    3141             : }
    3142             : 
    3143          44 : static NTSTATUS marshall_stream_info(unsigned int num_streams,
    3144             :                                      const struct stream_struct *streams,
    3145             :                                      char *data,
    3146             :                                      unsigned int max_data_bytes,
    3147             :                                      unsigned int *data_size)
    3148             : {
    3149             :         unsigned int i;
    3150          44 :         unsigned int ofs = 0;
    3151             : 
    3152          44 :         if (max_data_bytes < 32) {
    3153           0 :                 return NT_STATUS_INFO_LENGTH_MISMATCH;
    3154             :         }
    3155             : 
    3156         120 :         for (i = 0; i < num_streams; i++) {
    3157             :                 unsigned int next_offset;
    3158             :                 size_t namelen;
    3159             :                 smb_ucs2_t *namebuf;
    3160             : 
    3161          36 :                 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
    3162          54 :                                       streams[i].name, &namelen) ||
    3163          36 :                     namelen <= 2)
    3164             :                 {
    3165           0 :                         return NT_STATUS_INVALID_PARAMETER;
    3166             :                 }
    3167             : 
    3168             :                 /*
    3169             :                  * name_buf is now null-terminated, we need to marshall as not
    3170             :                  * terminated
    3171             :                  */
    3172             : 
    3173          36 :                 namelen -= 2;
    3174             : 
    3175             :                 /*
    3176             :                  * We cannot overflow ...
    3177             :                  */
    3178          36 :                 if ((ofs + 24 + namelen) > max_data_bytes) {
    3179           0 :                         DEBUG(10, ("refusing to overflow reply at stream %u\n",
    3180             :                                 i));
    3181           0 :                         TALLOC_FREE(namebuf);
    3182           0 :                         return STATUS_BUFFER_OVERFLOW;
    3183             :                 }
    3184             : 
    3185          36 :                 SIVAL(data, ofs+4, namelen);
    3186          36 :                 SOFF_T(data, ofs+8, streams[i].size);
    3187          36 :                 SOFF_T(data, ofs+16, streams[i].alloc_size);
    3188          36 :                 memcpy(data+ofs+24, namebuf, namelen);
    3189          36 :                 TALLOC_FREE(namebuf);
    3190             : 
    3191          36 :                 next_offset = ofs + 24 + namelen;
    3192             : 
    3193          36 :                 if (i == num_streams-1) {
    3194          36 :                         SIVAL(data, ofs, 0);
    3195             :                 }
    3196             :                 else {
    3197           0 :                         unsigned int align = ndr_align_size(next_offset, 8);
    3198             : 
    3199           0 :                         if ((next_offset + align) > max_data_bytes) {
    3200           0 :                                 DEBUG(10, ("refusing to overflow align "
    3201             :                                         "reply at stream %u\n",
    3202             :                                         i));
    3203           0 :                                 TALLOC_FREE(namebuf);
    3204           0 :                                 return STATUS_BUFFER_OVERFLOW;
    3205             :                         }
    3206             : 
    3207           0 :                         memset(data+next_offset, 0, align);
    3208           0 :                         next_offset += align;
    3209             : 
    3210           0 :                         SIVAL(data, ofs, next_offset - ofs);
    3211           0 :                         ofs = next_offset;
    3212             :                 }
    3213             : 
    3214          36 :                 ofs = next_offset;
    3215             :         }
    3216             : 
    3217          44 :         DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
    3218             : 
    3219          44 :         *data_size = ofs;
    3220             : 
    3221          44 :         return NT_STATUS_OK;
    3222             : }
    3223             : 
    3224           0 : static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
    3225             :                                 struct smb_request *req,
    3226             :                                 struct smb_filename *smb_fname,
    3227             :                                 char *pdata,
    3228             :                                 unsigned int data_size_in,
    3229             :                                 unsigned int *pdata_size_out)
    3230             : {
    3231             :         NTSTATUS status;
    3232           0 :         size_t len = 0;
    3233           0 :         int link_len = 0;
    3234           0 :         struct smb_filename *parent_fname = NULL;
    3235           0 :         struct smb_filename *base_name = NULL;
    3236             : 
    3237           0 :         char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
    3238             : 
    3239           0 :         if (!buffer) {
    3240           0 :                 return NT_STATUS_NO_MEMORY;
    3241             :         }
    3242             : 
    3243           0 :         DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
    3244             :                 smb_fname_str_dbg(smb_fname));
    3245             : 
    3246           0 :         if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
    3247           0 :                 TALLOC_FREE(buffer);
    3248           0 :                 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
    3249             :         }
    3250             : 
    3251           0 :         status = parent_pathref(talloc_tos(),
    3252             :                                 conn->cwd_fsp,
    3253             :                                 smb_fname,
    3254             :                                 &parent_fname,
    3255             :                                 &base_name);
    3256           0 :         if (!NT_STATUS_IS_OK(status)) {
    3257           0 :                 TALLOC_FREE(buffer);
    3258           0 :                 return status;
    3259             :         }
    3260             : 
    3261           0 :         link_len = SMB_VFS_READLINKAT(conn,
    3262             :                                 parent_fname->fsp,
    3263             :                                 base_name,
    3264             :                                 buffer,
    3265             :                                 PATH_MAX);
    3266             : 
    3267           0 :         TALLOC_FREE(parent_fname);
    3268             : 
    3269           0 :         if (link_len == -1) {
    3270           0 :                 TALLOC_FREE(buffer);
    3271           0 :                 return map_nt_error_from_unix(errno);
    3272             :         }
    3273             : 
    3274           0 :         buffer[link_len] = 0;
    3275           0 :         status = srvstr_push(pdata,
    3276             :                         req->flags2,
    3277             :                         pdata,
    3278             :                         buffer,
    3279             :                         data_size_in,
    3280             :                         STR_TERMINATE,
    3281             :                         &len);
    3282           0 :         TALLOC_FREE(buffer);
    3283           0 :         if (!NT_STATUS_IS_OK(status)) {
    3284           0 :                 return status;
    3285             :         }
    3286           0 :         *pdata_size_out = len;
    3287             : 
    3288           0 :         return NT_STATUS_OK;
    3289             : }
    3290             : 
    3291             : #if defined(HAVE_POSIX_ACLS)
    3292           0 : static NTSTATUS smb_query_posix_acl(connection_struct *conn,
    3293             :                                 struct smb_request *req,
    3294             :                                 files_struct *fsp,
    3295             :                                 struct smb_filename *smb_fname,
    3296             :                                 char *pdata,
    3297             :                                 unsigned int data_size_in,
    3298             :                                 unsigned int *pdata_size_out)
    3299             : {
    3300           0 :         SMB_ACL_T file_acl = NULL;
    3301           0 :         SMB_ACL_T def_acl = NULL;
    3302           0 :         uint16_t num_file_acls = 0;
    3303           0 :         uint16_t num_def_acls = 0;
    3304           0 :         unsigned int size_needed = 0;
    3305             :         NTSTATUS status;
    3306             :         bool ok;
    3307           0 :         bool close_fsp = false;
    3308             : 
    3309             :         /*
    3310             :          * Ensure we always operate on a file descriptor, not just
    3311             :          * the filename.
    3312             :          */
    3313           0 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    3314           0 :                 uint32_t access_mask = SEC_STD_READ_CONTROL|
    3315             :                                         FILE_READ_ATTRIBUTES|
    3316             :                                         FILE_WRITE_ATTRIBUTES;
    3317             : 
    3318           0 :                 status = get_posix_fsp(conn,
    3319             :                                         req,
    3320             :                                         smb_fname,
    3321             :                                         access_mask,
    3322             :                                         &fsp);
    3323             : 
    3324           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3325           0 :                         goto out;
    3326             :                 }
    3327           0 :                 close_fsp = true;
    3328             :         }
    3329             : 
    3330           0 :         SMB_ASSERT(fsp != NULL);
    3331             : 
    3332           0 :         status = refuse_symlink_fsp(fsp);
    3333           0 :         if (!NT_STATUS_IS_OK(status)) {
    3334           0 :                 goto out;
    3335             :         }
    3336             : 
    3337           0 :         file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
    3338             :                                         talloc_tos());
    3339             : 
    3340           0 :         if (file_acl == NULL && no_acl_syscall_error(errno)) {
    3341           0 :                 DBG_INFO("ACLs not implemented on "
    3342             :                         "filesystem containing %s\n",
    3343             :                         fsp_str_dbg(fsp));
    3344           0 :                 status = NT_STATUS_NOT_IMPLEMENTED;
    3345           0 :                 goto out;
    3346             :         }
    3347             : 
    3348           0 :         if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
    3349             :                 /*
    3350             :                  * We can only have default POSIX ACLs on
    3351             :                  * directories.
    3352             :                  */
    3353           0 :                 if (!fsp->fsp_flags.is_directory) {
    3354           0 :                         DBG_INFO("Non-directory open %s\n",
    3355             :                                 fsp_str_dbg(fsp));
    3356           0 :                         status = NT_STATUS_INVALID_HANDLE;
    3357           0 :                         goto out;
    3358             :                 }
    3359           0 :                 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
    3360             :                                         SMB_ACL_TYPE_DEFAULT,
    3361             :                                         talloc_tos());
    3362           0 :                 def_acl = free_empty_sys_acl(conn, def_acl);
    3363             :         }
    3364             : 
    3365           0 :         num_file_acls = count_acl_entries(conn, file_acl);
    3366           0 :         num_def_acls = count_acl_entries(conn, def_acl);
    3367             : 
    3368             :         /* Wrap checks. */
    3369           0 :         if (num_file_acls + num_def_acls < num_file_acls) {
    3370           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3371           0 :                 goto out;
    3372             :         }
    3373             : 
    3374           0 :         size_needed = num_file_acls + num_def_acls;
    3375             : 
    3376             :         /*
    3377             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    3378             :          * than UINT_MAX, so check by division.
    3379             :          */
    3380           0 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    3381           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3382           0 :                 goto out;
    3383             :         }
    3384             : 
    3385           0 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    3386           0 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    3387           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    3388           0 :                 goto out;
    3389             :         }
    3390           0 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    3391             : 
    3392           0 :         if ( data_size_in < size_needed) {
    3393           0 :                 DBG_INFO("data_size too small (%u) need %u\n",
    3394             :                         data_size_in,
    3395             :                         size_needed);
    3396           0 :                 status = NT_STATUS_BUFFER_TOO_SMALL;
    3397           0 :                 goto out;
    3398             :         }
    3399             : 
    3400           0 :         SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
    3401           0 :         SSVAL(pdata,2,num_file_acls);
    3402           0 :         SSVAL(pdata,4,num_def_acls);
    3403           0 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    3404             : 
    3405           0 :         ok = marshall_posix_acl(conn,
    3406             :                         pdata,
    3407           0 :                         &fsp->fsp_name->st,
    3408             :                         file_acl);
    3409           0 :         if (!ok) {
    3410           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    3411           0 :                 goto out;
    3412             :         }
    3413           0 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    3414             : 
    3415           0 :         ok = marshall_posix_acl(conn,
    3416             :                         pdata,
    3417           0 :                         &fsp->fsp_name->st,
    3418             :                         def_acl);
    3419           0 :         if (!ok) {
    3420           0 :                 status = NT_STATUS_INTERNAL_ERROR;
    3421           0 :                 goto out;
    3422             :         }
    3423             : 
    3424           0 :         *pdata_size_out = size_needed;
    3425           0 :         status = NT_STATUS_OK;
    3426             : 
    3427           0 :   out:
    3428             : 
    3429           0 :         if (close_fsp) {
    3430             :                 /*
    3431             :                  * Ensure the stat struct in smb_fname is up to
    3432             :                  * date. Structure copy.
    3433             :                  */
    3434           0 :                 smb_fname->st = fsp->fsp_name->st;
    3435           0 :                 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
    3436             :         }
    3437             : 
    3438           0 :         TALLOC_FREE(file_acl);
    3439           0 :         TALLOC_FREE(def_acl);
    3440           0 :         return status;
    3441             : }
    3442             : #endif
    3443             : 
    3444         910 : NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
    3445             :                                TALLOC_CTX *mem_ctx,
    3446             :                                struct smb_request *req,
    3447             :                                uint16_t info_level,
    3448             :                                files_struct *fsp,
    3449             :                                struct smb_filename *smb_fname,
    3450             :                                bool delete_pending,
    3451             :                                struct timespec write_time_ts,
    3452             :                                struct ea_list *ea_list,
    3453             :                                int lock_data_count,
    3454             :                                char *lock_data,
    3455             :                                uint16_t flags2,
    3456             :                                unsigned int max_data_bytes,
    3457             :                                size_t *fixed_portion,
    3458             :                                char **ppdata,
    3459             :                                unsigned int *pdata_size)
    3460             : {
    3461         910 :         char *pdata = *ppdata;
    3462             :         char *dstart, *dend;
    3463             :         unsigned int data_size;
    3464             :         struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
    3465             :         time_t create_time, mtime, atime, c_time;
    3466         910 :         SMB_STRUCT_STAT *psbuf = NULL;
    3467         910 :         SMB_STRUCT_STAT *base_sp = NULL;
    3468             :         char *p;
    3469             :         char *base_name;
    3470             :         char *dos_fname;
    3471             :         int mode;
    3472             :         int nlink;
    3473             :         NTSTATUS status;
    3474         910 :         uint64_t file_size = 0;
    3475         910 :         uint64_t pos = 0;
    3476         910 :         uint64_t allocation_size = 0;
    3477         910 :         uint64_t file_id = 0;
    3478         910 :         uint32_t access_mask = 0;
    3479         910 :         size_t len = 0;
    3480             : 
    3481         910 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    3482           0 :                 if (!lp_smb1_unix_extensions()) {
    3483           0 :                         return NT_STATUS_INVALID_LEVEL;
    3484             :                 }
    3485           0 :                 if (!req->posix_pathnames) {
    3486           0 :                         return NT_STATUS_INVALID_LEVEL;
    3487             :                 }
    3488             :         }
    3489             : 
    3490         910 :         DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
    3491             :                  smb_fname_str_dbg(smb_fname),
    3492             :                  fsp_fnum_dbg(fsp),
    3493             :                  info_level, max_data_bytes));
    3494             : 
    3495             :         /*
    3496             :          * In case of querying a symlink in POSIX context,
    3497             :          * fsp will be NULL. fdos_mode() deals with it.
    3498             :          */
    3499         910 :         if (fsp != NULL) {
    3500         910 :                 smb_fname = fsp->fsp_name;
    3501             :         }
    3502         910 :         mode = fdos_mode(fsp);
    3503         910 :         psbuf = &smb_fname->st;
    3504             : 
    3505         910 :         if (fsp != NULL) {
    3506        1559 :                 base_sp = fsp->base_fsp ?
    3507        1547 :                         &fsp->base_fsp->fsp_name->st :
    3508         886 :                         &fsp->fsp_name->st;
    3509             :         } else {
    3510           0 :                 base_sp = &smb_fname->st;
    3511             :         }
    3512             : 
    3513         910 :         nlink = psbuf->st_ex_nlink;
    3514             : 
    3515         910 :         if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
    3516          83 :                 nlink = 1;
    3517             :         }
    3518             : 
    3519         910 :         if ((nlink > 0) && delete_pending) {
    3520           0 :                 nlink -= 1;
    3521             :         }
    3522             : 
    3523         910 :         if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
    3524           0 :                 return NT_STATUS_INVALID_PARAMETER;
    3525             :         }
    3526             : 
    3527         910 :         data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
    3528         910 :         *ppdata = (char *)SMB_REALLOC(*ppdata, data_size); 
    3529         910 :         if (*ppdata == NULL) {
    3530           0 :                 return NT_STATUS_NO_MEMORY;
    3531             :         }
    3532         910 :         pdata = *ppdata;
    3533         910 :         dstart = pdata;
    3534         910 :         dend = dstart + data_size - 1;
    3535             : 
    3536         910 :         if (!is_omit_timespec(&write_time_ts) &&
    3537         827 :             !INFO_LEVEL_IS_UNIX(info_level))
    3538             :         {
    3539         827 :                 update_stat_ex_mtime(psbuf, write_time_ts);
    3540             :         }
    3541             : 
    3542         910 :         create_time_ts = get_create_timespec(conn, fsp, smb_fname);
    3543         910 :         mtime_ts = psbuf->st_ex_mtime;
    3544         910 :         atime_ts = psbuf->st_ex_atime;
    3545         910 :         ctime_ts = get_change_timespec(conn, fsp, smb_fname);
    3546             : 
    3547         910 :         if (lp_dos_filetime_resolution(SNUM(conn))) {
    3548           0 :                 dos_filetime_timespec(&create_time_ts);
    3549           0 :                 dos_filetime_timespec(&mtime_ts);
    3550           0 :                 dos_filetime_timespec(&atime_ts);
    3551           0 :                 dos_filetime_timespec(&ctime_ts);
    3552             :         }
    3553             : 
    3554         910 :         create_time = convert_timespec_to_time_t(create_time_ts);
    3555         910 :         mtime = convert_timespec_to_time_t(mtime_ts);
    3556         910 :         atime = convert_timespec_to_time_t(atime_ts);
    3557         910 :         c_time = convert_timespec_to_time_t(ctime_ts);
    3558             : 
    3559         910 :         p = strrchr_m(smb_fname->base_name,'/');
    3560         910 :         if (!p)
    3561         527 :                 base_name = smb_fname->base_name;
    3562             :         else
    3563         383 :                 base_name = p+1;
    3564             : 
    3565             :         /* NT expects the name to be in an exact form of the *full*
    3566             :            filename. See the trans2 torture test */
    3567         910 :         if (ISDOT(base_name)) {
    3568          40 :                 dos_fname = talloc_strdup(mem_ctx, "\\");
    3569          60 :                 if (!dos_fname) {
    3570           0 :                         return NT_STATUS_NO_MEMORY;
    3571             :                 }
    3572             :         } else {
    3573         870 :                 dos_fname = talloc_asprintf(mem_ctx,
    3574             :                                 "\\%s",
    3575             :                                 smb_fname->base_name);
    3576         870 :                 if (!dos_fname) {
    3577           0 :                         return NT_STATUS_NO_MEMORY;
    3578             :                 }
    3579         870 :                 if (is_named_stream(smb_fname)) {
    3580          24 :                         dos_fname = talloc_asprintf(dos_fname, "%s",
    3581             :                                                     smb_fname->stream_name);
    3582          24 :                         if (!dos_fname) {
    3583           0 :                                 return NT_STATUS_NO_MEMORY;
    3584             :                         }
    3585             :                 }
    3586             : 
    3587         870 :                 string_replace(dos_fname, '/', '\\');
    3588             :         }
    3589             : 
    3590         910 :         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
    3591             : 
    3592         910 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    3593             :                 /* Do we have this path open ? */
    3594             :                 files_struct *fsp1;
    3595           0 :                 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
    3596           0 :                 fsp1 = file_find_di_first(conn->sconn, fileid, true);
    3597           0 :                 if (fsp1 && fsp1->initial_allocation_size) {
    3598           0 :                         allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
    3599             :                 }
    3600             :         }
    3601             : 
    3602         910 :         if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
    3603         827 :                 file_size = get_file_size_stat(psbuf);
    3604             :         }
    3605             : 
    3606         910 :         if (fsp) {
    3607         910 :                 pos = fh_get_position_information(fsp->fh);
    3608             :         }
    3609             : 
    3610         910 :         if (fsp) {
    3611         910 :                 access_mask = fsp->access_mask;
    3612             :         } else {
    3613             :                 /* GENERIC_EXECUTE mapping from Windows */
    3614           0 :                 access_mask = 0x12019F;
    3615             :         }
    3616             : 
    3617             :         /* This should be an index number - looks like
    3618             :            dev/ino to me :-)
    3619             : 
    3620             :            I think this causes us to fail the IFSKIT
    3621             :            BasicFileInformationTest. -tpot */
    3622         910 :         file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
    3623             : 
    3624         910 :         *fixed_portion = 0;
    3625             : 
    3626         910 :         switch (info_level) {
    3627           0 :                 case SMB_INFO_STANDARD:
    3628           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
    3629           0 :                         data_size = 22;
    3630           0 :                         srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
    3631           0 :                         srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
    3632           0 :                         srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
    3633           0 :                         SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
    3634           0 :                         SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
    3635           0 :                         SSVAL(pdata,l1_attrFile,mode);
    3636           0 :                         break;
    3637             : 
    3638           0 :                 case SMB_INFO_QUERY_EA_SIZE:
    3639             :                 {
    3640           0 :                         unsigned int ea_size =
    3641           0 :                             estimate_ea_size(smb_fname->fsp);
    3642           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
    3643           0 :                         data_size = 26;
    3644           0 :                         srv_put_dos_date2(pdata,0,create_time);
    3645           0 :                         srv_put_dos_date2(pdata,4,atime);
    3646           0 :                         srv_put_dos_date2(pdata,8,mtime); /* write time */
    3647           0 :                         SIVAL(pdata,12,(uint32_t)file_size);
    3648           0 :                         SIVAL(pdata,16,(uint32_t)allocation_size);
    3649           0 :                         SSVAL(pdata,20,mode);
    3650           0 :                         SIVAL(pdata,22,ea_size);
    3651           0 :                         break;
    3652             :                 }
    3653             : 
    3654           0 :                 case SMB_INFO_IS_NAME_VALID:
    3655           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
    3656           0 :                         if (fsp) {
    3657             :                                 /* os/2 needs this ? really ?*/
    3658           0 :                                 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
    3659             :                         }
    3660             :                         /* This is only reached for qpathinfo */
    3661           0 :                         data_size = 0;
    3662           0 :                         break;
    3663             : 
    3664           0 :                 case SMB_INFO_QUERY_EAS_FROM_LIST:
    3665             :                 {
    3666           0 :                         size_t total_ea_len = 0;
    3667           0 :                         struct ea_list *ea_file_list = NULL;
    3668           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
    3669             : 
    3670           0 :                         status =
    3671           0 :                             get_ea_list_from_fsp(mem_ctx,
    3672           0 :                                                   smb_fname->fsp,
    3673             :                                                   &total_ea_len, &ea_file_list);
    3674           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3675           0 :                                 return status;
    3676             :                         }
    3677             : 
    3678           0 :                         ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
    3679             : 
    3680           0 :                         if (!ea_list || (total_ea_len > data_size)) {
    3681           0 :                                 data_size = 4;
    3682           0 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    3683           0 :                                 break;
    3684             :                         }
    3685             : 
    3686           0 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    3687           0 :                         break;
    3688             :                 }
    3689             : 
    3690           0 :                 case SMB_INFO_QUERY_ALL_EAS:
    3691             :                 {
    3692             :                         /* We have data_size bytes to put EA's into. */
    3693           0 :                         size_t total_ea_len = 0;
    3694           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
    3695             : 
    3696           0 :                         status = get_ea_list_from_fsp(mem_ctx,
    3697           0 :                                                         smb_fname->fsp,
    3698             :                                                         &total_ea_len, &ea_list);
    3699           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3700           0 :                                 return status;
    3701             :                         }
    3702             : 
    3703           0 :                         if (!ea_list || (total_ea_len > data_size)) {
    3704           0 :                                 data_size = 4;
    3705           0 :                                 SIVAL(pdata,0,4);   /* EA List Length must be set to 4 if no EA's. */
    3706           0 :                                 break;
    3707             :                         }
    3708             : 
    3709           0 :                         data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
    3710           0 :                         break;
    3711             :                 }
    3712             : 
    3713           0 :                 case SMB2_FILE_FULL_EA_INFORMATION:
    3714             :                 {
    3715             :                         /* We have data_size bytes to put EA's into. */
    3716           0 :                         size_t total_ea_len = 0;
    3717           0 :                         struct ea_list *ea_file_list = NULL;
    3718             : 
    3719           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
    3720             : 
    3721             :                         /*TODO: add filtering and index handling */
    3722             : 
    3723           0 :                         status  =
    3724           0 :                                 get_ea_list_from_fsp(mem_ctx,
    3725           0 :                                                   smb_fname->fsp,
    3726             :                                                   &total_ea_len, &ea_file_list);
    3727           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3728           0 :                                 return status;
    3729             :                         }
    3730           0 :                         if (!ea_file_list) {
    3731           0 :                                 return NT_STATUS_NO_EAS_ON_FILE;
    3732             :                         }
    3733             : 
    3734           0 :                         status = fill_ea_chained_buffer(mem_ctx,
    3735             :                                                         pdata,
    3736             :                                                         data_size,
    3737             :                                                         &data_size,
    3738             :                                                         conn, ea_file_list);
    3739           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3740           0 :                                 return status;
    3741             :                         }
    3742           0 :                         break;
    3743             :                 }
    3744             : 
    3745           0 :                 case SMB_FILE_BASIC_INFORMATION:
    3746             :                 case SMB_QUERY_FILE_BASIC_INFO:
    3747             : 
    3748           0 :                         if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
    3749           0 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
    3750           0 :                                 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
    3751             :                         } else {
    3752           0 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
    3753           0 :                                 data_size = 40;
    3754           0 :                                 SIVAL(pdata,36,0);
    3755             :                         }
    3756           0 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3757           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3758           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3759           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3760           0 :                         SIVAL(pdata,32,mode);
    3761             : 
    3762           0 :                         DEBUG(5,("SMB_QFBI - "));
    3763           0 :                         DEBUG(5,("create: %s ", ctime(&create_time)));
    3764           0 :                         DEBUG(5,("access: %s ", ctime(&atime)));
    3765           0 :                         DEBUG(5,("write: %s ", ctime(&mtime)));
    3766           0 :                         DEBUG(5,("change: %s ", ctime(&c_time)));
    3767           0 :                         DEBUG(5,("mode: %x\n", mode));
    3768           0 :                         *fixed_portion = data_size;
    3769           0 :                         break;
    3770             : 
    3771           0 :                 case SMB_FILE_STANDARD_INFORMATION:
    3772             :                 case SMB_QUERY_FILE_STANDARD_INFO:
    3773             : 
    3774           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
    3775           0 :                         data_size = 24;
    3776           0 :                         SOFF_T(pdata,0,allocation_size);
    3777           0 :                         SOFF_T(pdata,8,file_size);
    3778           0 :                         SIVAL(pdata,16,nlink);
    3779           0 :                         SCVAL(pdata,20,delete_pending?1:0);
    3780           0 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3781           0 :                         SSVAL(pdata,22,0); /* Padding. */
    3782           0 :                         *fixed_portion = 24;
    3783           0 :                         break;
    3784             : 
    3785           0 :                 case SMB_FILE_EA_INFORMATION:
    3786             :                 case SMB_QUERY_FILE_EA_INFO:
    3787             :                 {
    3788           0 :                         unsigned int ea_size =
    3789           0 :                             estimate_ea_size(smb_fname->fsp);
    3790           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
    3791           0 :                         data_size = 4;
    3792           0 :                         *fixed_portion = 4;
    3793           0 :                         SIVAL(pdata,0,ea_size);
    3794           0 :                         break;
    3795             :                 }
    3796             : 
    3797             :                 /* Get the 8.3 name - used if NT SMB was negotiated. */
    3798          52 :                 case SMB_QUERY_FILE_ALT_NAME_INFO:
    3799             :                 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
    3800             :                 {
    3801             :                         char mangled_name[13];
    3802          52 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
    3803          52 :                         if (!name_to_8_3(base_name,mangled_name,
    3804          52 :                                                 True,conn->params)) {
    3805           0 :                                 return NT_STATUS_NO_MEMORY;
    3806             :                         }
    3807          52 :                         status = srvstr_push(dstart, flags2,
    3808             :                                           pdata+4, mangled_name,
    3809             :                                           PTR_DIFF(dend, pdata+4),
    3810             :                                           STR_UNICODE, &len);
    3811          52 :                         if (!NT_STATUS_IS_OK(status)) {
    3812           0 :                                 return status;
    3813             :                         }
    3814          52 :                         data_size = 4 + len;
    3815          52 :                         SIVAL(pdata,0,len);
    3816          52 :                         *fixed_portion = 8;
    3817          52 :                         break;
    3818             :                 }
    3819             : 
    3820           0 :                 case SMB_QUERY_FILE_NAME_INFO:
    3821             :                 {
    3822             :                         /*
    3823             :                           this must be *exactly* right for ACLs on mapped drives to work
    3824             :                          */
    3825           0 :                         status = srvstr_push(dstart, flags2,
    3826             :                                           pdata+4, dos_fname,
    3827             :                                           PTR_DIFF(dend, pdata+4),
    3828             :                                           STR_UNICODE, &len);
    3829           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3830           0 :                                 return status;
    3831             :                         }
    3832           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
    3833           0 :                         data_size = 4 + len;
    3834           0 :                         SIVAL(pdata,0,len);
    3835           0 :                         break;
    3836             :                 }
    3837             : 
    3838           0 :                 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
    3839             :                 {
    3840           0 :                         char *nfname = NULL;
    3841             : 
    3842           0 :                         if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
    3843           0 :                                 return NT_STATUS_INVALID_LEVEL;
    3844             :                         }
    3845             : 
    3846           0 :                         nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
    3847           0 :                         if (nfname == NULL) {
    3848           0 :                                 return NT_STATUS_NO_MEMORY;
    3849             :                         }
    3850             : 
    3851           0 :                         if (ISDOT(nfname)) {
    3852           0 :                                 nfname[0] = '\0';
    3853             :                         }
    3854           0 :                         string_replace(nfname, '/', '\\');
    3855             : 
    3856           0 :                         if (fsp_is_alternate_stream(fsp)) {
    3857           0 :                                 const char *s = smb_fname->stream_name;
    3858           0 :                                 const char *e = NULL;
    3859             :                                 size_t n;
    3860             : 
    3861           0 :                                 SMB_ASSERT(s[0] != '\0');
    3862             : 
    3863             :                                 /*
    3864             :                                  * smb_fname->stream_name is in form
    3865             :                                  * of ':StrEam:$DATA', but we should only
    3866             :                                  * append ':StrEam' here.
    3867             :                                  */
    3868             : 
    3869           0 :                                 e = strchr(&s[1], ':');
    3870           0 :                                 if (e == NULL) {
    3871           0 :                                         n = strlen(s);
    3872             :                                 } else {
    3873           0 :                                         n = PTR_DIFF(e, s);
    3874             :                                 }
    3875           0 :                                 nfname = talloc_strndup_append(nfname, s, n);
    3876           0 :                                 if (nfname == NULL) {
    3877           0 :                                         return NT_STATUS_NO_MEMORY;
    3878             :                                 }
    3879             :                         }
    3880             : 
    3881           0 :                         status = srvstr_push(dstart, flags2,
    3882             :                                           pdata+4, nfname,
    3883             :                                           PTR_DIFF(dend, pdata+4),
    3884             :                                           STR_UNICODE, &len);
    3885           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3886           0 :                                 return status;
    3887             :                         }
    3888           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
    3889           0 :                         data_size = 4 + len;
    3890           0 :                         SIVAL(pdata,0,len);
    3891           0 :                         *fixed_portion = 8;
    3892           0 :                         break;
    3893             :                 }
    3894             : 
    3895           0 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    3896             :                 case SMB_QUERY_FILE_ALLOCATION_INFO:
    3897           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
    3898           0 :                         data_size = 8;
    3899           0 :                         SOFF_T(pdata,0,allocation_size);
    3900           0 :                         break;
    3901             : 
    3902           0 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    3903             :                 case SMB_QUERY_FILE_END_OF_FILEINFO:
    3904           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
    3905           0 :                         data_size = 8;
    3906           0 :                         SOFF_T(pdata,0,file_size);
    3907           0 :                         break;
    3908             : 
    3909           0 :                 case SMB_QUERY_FILE_ALL_INFO:
    3910             :                 case SMB_FILE_ALL_INFORMATION:
    3911             :                 {
    3912           0 :                         unsigned int ea_size =
    3913           0 :                             estimate_ea_size(smb_fname->fsp);
    3914           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
    3915           0 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    3916           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    3917           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    3918           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    3919           0 :                         SIVAL(pdata,32,mode);
    3920           0 :                         SIVAL(pdata,36,0); /* padding. */
    3921           0 :                         pdata += 40;
    3922           0 :                         SOFF_T(pdata,0,allocation_size);
    3923           0 :                         SOFF_T(pdata,8,file_size);
    3924           0 :                         SIVAL(pdata,16,nlink);
    3925           0 :                         SCVAL(pdata,20,delete_pending);
    3926           0 :                         SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3927           0 :                         SSVAL(pdata,22,0);
    3928           0 :                         pdata += 24;
    3929           0 :                         SIVAL(pdata,0,ea_size);
    3930           0 :                         pdata += 4; /* EA info */
    3931           0 :                         status = srvstr_push(dstart, flags2,
    3932             :                                           pdata+4, dos_fname,
    3933             :                                           PTR_DIFF(dend, pdata+4),
    3934             :                                           STR_UNICODE, &len);
    3935           0 :                         if (!NT_STATUS_IS_OK(status)) {
    3936           0 :                                 return status;
    3937             :                         }
    3938           0 :                         SIVAL(pdata,0,len);
    3939           0 :                         pdata += 4 + len;
    3940           0 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    3941           0 :                         *fixed_portion = 10;
    3942           0 :                         break;
    3943             :                 }
    3944             : 
    3945         498 :                 case SMB2_FILE_ALL_INFORMATION:
    3946             :                 {
    3947         440 :                         unsigned int ea_size =
    3948         498 :                             estimate_ea_size(smb_fname->fsp);
    3949         498 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
    3950         498 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
    3951         498 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
    3952         498 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
    3953         498 :                         put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
    3954         498 :                         SIVAL(pdata,    0x20, mode);
    3955         498 :                         SIVAL(pdata,    0x24, 0); /* padding. */
    3956         498 :                         SBVAL(pdata,    0x28, allocation_size);
    3957         498 :                         SBVAL(pdata,    0x30, file_size);
    3958         498 :                         SIVAL(pdata,    0x38, nlink);
    3959         498 :                         SCVAL(pdata,    0x3C, delete_pending);
    3960         498 :                         SCVAL(pdata,    0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
    3961         498 :                         SSVAL(pdata,    0x3E, 0); /* padding */
    3962         498 :                         SBVAL(pdata,    0x40, file_id);
    3963         498 :                         SIVAL(pdata,    0x48, ea_size);
    3964         498 :                         SIVAL(pdata,    0x4C, access_mask);
    3965         498 :                         SBVAL(pdata,    0x50, pos);
    3966         498 :                         SIVAL(pdata,    0x58, mode); /*TODO: mode != mode fix this!!! */
    3967         498 :                         SIVAL(pdata,    0x5C, 0); /* No alignment needed. */
    3968             : 
    3969         498 :                         pdata += 0x60;
    3970             : 
    3971         498 :                         status = srvstr_push(dstart, flags2,
    3972             :                                           pdata+4, dos_fname,
    3973             :                                           PTR_DIFF(dend, pdata+4),
    3974             :                                           STR_UNICODE, &len);
    3975         498 :                         if (!NT_STATUS_IS_OK(status)) {
    3976           0 :                                 return status;
    3977             :                         }
    3978         498 :                         SIVAL(pdata,0,len);
    3979         498 :                         pdata += 4 + len;
    3980         498 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    3981         498 :                         *fixed_portion = 104;
    3982         498 :                         break;
    3983             :                 }
    3984           0 :                 case SMB_FILE_INTERNAL_INFORMATION:
    3985             : 
    3986           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
    3987           0 :                         SBVAL(pdata, 0, file_id);
    3988           0 :                         data_size = 8;
    3989           0 :                         *fixed_portion = 8;
    3990           0 :                         break;
    3991             : 
    3992          30 :                 case SMB_FILE_ACCESS_INFORMATION:
    3993          30 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
    3994          30 :                         SIVAL(pdata, 0, access_mask);
    3995          30 :                         data_size = 4;
    3996          30 :                         *fixed_portion = 4;
    3997          30 :                         break;
    3998             : 
    3999           0 :                 case SMB_FILE_NAME_INFORMATION:
    4000             :                         /* Pathname with leading '\'. */
    4001             :                         {
    4002             :                                 size_t byte_len;
    4003           0 :                                 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
    4004           0 :                                 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
    4005           0 :                                 SIVAL(pdata,0,byte_len);
    4006           0 :                                 data_size = 4 + byte_len;
    4007           0 :                                 break;
    4008             :                         }
    4009             : 
    4010           0 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    4011           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
    4012           0 :                         data_size = 1;
    4013           0 :                         SCVAL(pdata,0,delete_pending);
    4014           0 :                         *fixed_portion = 1;
    4015           0 :                         break;
    4016             : 
    4017         278 :                 case SMB_FILE_POSITION_INFORMATION:
    4018         278 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
    4019         278 :                         data_size = 8;
    4020         278 :                         SOFF_T(pdata,0,pos);
    4021         278 :                         *fixed_portion = 8;
    4022         278 :                         break;
    4023             : 
    4024           0 :                 case SMB_FILE_MODE_INFORMATION:
    4025           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
    4026           0 :                         SIVAL(pdata,0,mode);
    4027           0 :                         data_size = 4;
    4028           0 :                         *fixed_portion = 4;
    4029           0 :                         break;
    4030             : 
    4031           0 :                 case SMB_FILE_ALIGNMENT_INFORMATION:
    4032           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
    4033           0 :                         SIVAL(pdata,0,0); /* No alignment needed. */
    4034           0 :                         data_size = 4;
    4035           0 :                         *fixed_portion = 4;
    4036           0 :                         break;
    4037             : 
    4038             :                 /*
    4039             :                  * NT4 server just returns "invalid query" to this - if we try
    4040             :                  * to answer it then NTws gets a BSOD! (tridge).  W2K seems to
    4041             :                  * want this. JRA.
    4042             :                  */
    4043             :                 /* The first statement above is false - verified using Thursby
    4044             :                  * client against NT4 -- gcolley.
    4045             :                  */
    4046          52 :                 case SMB_QUERY_FILE_STREAM_INFO:
    4047             :                 case SMB_FILE_STREAM_INFORMATION: {
    4048          52 :                         unsigned int num_streams = 0;
    4049          52 :                         struct stream_struct *streams = NULL;
    4050             : 
    4051          52 :                         DEBUG(10,("smbd_do_qfilepathinfo: "
    4052             :                                   "SMB_FILE_STREAM_INFORMATION\n"));
    4053             : 
    4054          52 :                         if (is_ntfs_stream_smb_fname(smb_fname)) {
    4055          12 :                                 return NT_STATUS_INVALID_PARAMETER;
    4056             :                         }
    4057             : 
    4058          44 :                         status = vfs_fstreaminfo(fsp,
    4059             :                                                 mem_ctx,
    4060             :                                                 &num_streams,
    4061             :                                                 &streams);
    4062             : 
    4063          44 :                         if (!NT_STATUS_IS_OK(status)) {
    4064           0 :                                 DEBUG(10, ("could not get stream info: %s\n",
    4065             :                                            nt_errstr(status)));
    4066           0 :                                 return status;
    4067             :                         }
    4068             : 
    4069          44 :                         status = marshall_stream_info(num_streams, streams,
    4070             :                                                       pdata, max_data_bytes,
    4071             :                                                       &data_size);
    4072             : 
    4073          44 :                         if (!NT_STATUS_IS_OK(status)) {
    4074           0 :                                 DEBUG(10, ("marshall_stream_info failed: %s\n",
    4075             :                                            nt_errstr(status)));
    4076           0 :                                 TALLOC_FREE(streams);
    4077           0 :                                 return status;
    4078             :                         }
    4079             : 
    4080          44 :                         TALLOC_FREE(streams);
    4081             : 
    4082          44 :                         *fixed_portion = 32;
    4083             : 
    4084          44 :                         break;
    4085             :                 }
    4086           0 :                 case SMB_QUERY_COMPRESSION_INFO:
    4087             :                 case SMB_FILE_COMPRESSION_INFORMATION:
    4088           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
    4089           0 :                         SOFF_T(pdata,0,file_size);
    4090           0 :                         SIVAL(pdata,8,0); /* ??? */
    4091           0 :                         SIVAL(pdata,12,0); /* ??? */
    4092           0 :                         data_size = 16;
    4093           0 :                         *fixed_portion = 16;
    4094           0 :                         break;
    4095             : 
    4096           0 :                 case SMB_FILE_NETWORK_OPEN_INFORMATION:
    4097           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
    4098           0 :                         put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
    4099           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
    4100           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
    4101           0 :                         put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
    4102           0 :                         SOFF_T(pdata,32,allocation_size);
    4103           0 :                         SOFF_T(pdata,40,file_size);
    4104           0 :                         SIVAL(pdata,48,mode);
    4105           0 :                         SIVAL(pdata,52,0); /* ??? */
    4106           0 :                         data_size = 56;
    4107           0 :                         *fixed_portion = 56;
    4108           0 :                         break;
    4109             : 
    4110           0 :                 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
    4111           0 :                         DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
    4112           0 :                         SIVAL(pdata,0,mode);
    4113           0 :                         SIVAL(pdata,4,0);
    4114           0 :                         data_size = 8;
    4115           0 :                         *fixed_portion = 8;
    4116           0 :                         break;
    4117             : 
    4118             :                 /*
    4119             :                  * CIFS UNIX Extensions.
    4120             :                  */
    4121             : 
    4122           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    4123             : 
    4124           0 :                         pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
    4125           0 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    4126             : 
    4127           0 :                         DEBUG(4,("smbd_do_qfilepathinfo: "
    4128             :                                  "SMB_QUERY_FILE_UNIX_BASIC\n"));
    4129           0 :                         dump_data(4, (uint8_t *)(*ppdata), data_size);
    4130             : 
    4131           0 :                         break;
    4132             : 
    4133           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    4134             : 
    4135           0 :                         pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
    4136           0 :                         data_size = PTR_DIFF(pdata,(*ppdata));
    4137             : 
    4138             :                         {
    4139             :                                 int i;
    4140           0 :                                 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
    4141             : 
    4142           0 :                                 for (i=0; i<100; i++)
    4143           0 :                                         DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
    4144           0 :                                 DEBUG(4,("\n"));
    4145             :                         }
    4146             : 
    4147           0 :                         break;
    4148             : 
    4149           0 :                 case SMB_QUERY_FILE_UNIX_LINK:
    4150             :                         {
    4151           0 :                                 status = smb_unix_read_symlink(conn,
    4152             :                                                         req,
    4153             :                                                         smb_fname,
    4154             :                                                         pdata,
    4155             :                                                         data_size,
    4156             :                                                         &data_size);
    4157           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    4158           0 :                                         return status;
    4159             :                                 }
    4160           0 :                                 break;
    4161             :                         }
    4162             : 
    4163             : #if defined(HAVE_POSIX_ACLS)
    4164           0 :                 case SMB_QUERY_POSIX_ACL:
    4165             :                         {
    4166           0 :                                 status = smb_query_posix_acl(conn,
    4167             :                                                         req,
    4168             :                                                         fsp,
    4169             :                                                         smb_fname,
    4170             :                                                         pdata,
    4171             :                                                         data_size,
    4172             :                                                         &data_size);
    4173           0 :                                 if (!NT_STATUS_IS_OK(status)) {
    4174           0 :                                         return status;
    4175             :                                 }
    4176           0 :                                 break;
    4177             :                         }
    4178             : #endif
    4179             : 
    4180             : 
    4181           0 :                 case SMB_QUERY_POSIX_LOCK:
    4182             :                 {
    4183             :                         uint64_t count;
    4184             :                         uint64_t offset;
    4185             :                         uint64_t smblctx;
    4186             :                         enum brl_type lock_type;
    4187             : 
    4188             :                         /* We need an open file with a real fd for this. */
    4189           0 :                         if (fsp == NULL ||
    4190           0 :                             fsp->fsp_flags.is_pathref ||
    4191           0 :                             fsp_get_io_fd(fsp) == -1)
    4192             :                         {
    4193           0 :                                 return NT_STATUS_INVALID_LEVEL;
    4194             :                         }
    4195             : 
    4196           0 :                         if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
    4197           0 :                                 return NT_STATUS_INVALID_PARAMETER;
    4198             :                         }
    4199             : 
    4200           0 :                         switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
    4201           0 :                                 case POSIX_LOCK_TYPE_READ:
    4202           0 :                                         lock_type = READ_LOCK;
    4203           0 :                                         break;
    4204           0 :                                 case POSIX_LOCK_TYPE_WRITE:
    4205           0 :                                         lock_type = WRITE_LOCK;
    4206           0 :                                         break;
    4207           0 :                                 case POSIX_LOCK_TYPE_UNLOCK:
    4208             :                                 default:
    4209             :                                         /* There's no point in asking for an unlock... */
    4210           0 :                                         return NT_STATUS_INVALID_PARAMETER;
    4211             :                         }
    4212             : 
    4213           0 :                         smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
    4214           0 :                         offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
    4215           0 :                         count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
    4216             : 
    4217           0 :                         status = query_lock(fsp,
    4218             :                                         &smblctx,
    4219             :                                         &count,
    4220             :                                         &offset,
    4221             :                                         &lock_type,
    4222             :                                         POSIX_LOCK);
    4223             : 
    4224           0 :                         if (ERROR_WAS_LOCK_DENIED(status)) {
    4225             :                                 /* Here we need to report who has it locked... */
    4226           0 :                                 data_size = POSIX_LOCK_DATA_SIZE;
    4227             : 
    4228           0 :                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
    4229           0 :                                 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
    4230           0 :                                 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
    4231           0 :                                 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
    4232           0 :                                 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
    4233             : 
    4234           0 :                         } else if (NT_STATUS_IS_OK(status)) {
    4235             :                                 /* For success we just return a copy of what we sent
    4236             :                                    with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
    4237           0 :                                 data_size = POSIX_LOCK_DATA_SIZE;
    4238           0 :                                 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
    4239           0 :                                 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
    4240             :                         } else {
    4241           0 :                                 return status;
    4242             :                         }
    4243           0 :                         break;
    4244             :                 }
    4245             : 
    4246           0 :                 default:
    4247           0 :                         return NT_STATUS_INVALID_LEVEL;
    4248             :         }
    4249             : 
    4250         902 :         *pdata_size = data_size;
    4251         902 :         return NT_STATUS_OK;
    4252             : }
    4253             : 
    4254             : /****************************************************************************
    4255             :  Set a hard link (called by UNIX extensions and by NT rename with HARD link
    4256             :  code.
    4257             : ****************************************************************************/
    4258             : 
    4259           4 : NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
    4260             :                 connection_struct *conn,
    4261             :                 struct smb_request *req,
    4262             :                 bool overwrite_if_exists,
    4263             :                 struct files_struct *old_dirfsp,
    4264             :                 const struct smb_filename *smb_fname_old,
    4265             :                 struct files_struct *new_dirfsp,
    4266             :                 struct smb_filename *smb_fname_new)
    4267             : {
    4268           4 :         NTSTATUS status = NT_STATUS_OK;
    4269             :         int ret;
    4270             :         bool ok;
    4271           4 :         struct smb_filename *parent_fname_old = NULL;
    4272           4 :         struct smb_filename *base_name_old = NULL;
    4273           4 :         struct smb_filename *parent_fname_new = NULL;
    4274           4 :         struct smb_filename *base_name_new = NULL;
    4275             : 
    4276             :         /* source must already exist. */
    4277           4 :         if (!VALID_STAT(smb_fname_old->st)) {
    4278           0 :                 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4279           0 :                 goto out;
    4280             :         }
    4281             : 
    4282             :         /* No links from a directory. */
    4283           4 :         if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
    4284           0 :                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    4285           0 :                 goto out;
    4286             :         }
    4287             : 
    4288             :         /* Setting a hardlink to/from a stream isn't currently supported. */
    4289           4 :         ok = is_ntfs_stream_smb_fname(smb_fname_old);
    4290           4 :         if (ok) {
    4291           0 :                 DBG_DEBUG("Old name has streams\n");
    4292           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4293           0 :                 goto out;
    4294             :         }
    4295           4 :         ok = is_ntfs_stream_smb_fname(smb_fname_new);
    4296           4 :         if (ok) {
    4297           0 :                 DBG_DEBUG("New name has streams\n");
    4298           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    4299           0 :                 goto out;
    4300             :         }
    4301             : 
    4302           4 :         status = parent_pathref(talloc_tos(),
    4303             :                                 conn->cwd_fsp,
    4304             :                                 smb_fname_old,
    4305             :                                 &parent_fname_old,
    4306             :                                 &base_name_old);
    4307           4 :         if (!NT_STATUS_IS_OK(status)) {
    4308           0 :                 goto out;
    4309             :         }
    4310             : 
    4311           4 :         status = parent_pathref(talloc_tos(),
    4312             :                                 conn->cwd_fsp,
    4313             :                                 smb_fname_new,
    4314             :                                 &parent_fname_new,
    4315             :                                 &base_name_new);
    4316           4 :         if (!NT_STATUS_IS_OK(status)) {
    4317           0 :                 goto out;
    4318             :         }
    4319             : 
    4320           4 :         if (VALID_STAT(smb_fname_new->st)) {
    4321           0 :                 if (overwrite_if_exists) {
    4322           0 :                         if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
    4323           0 :                                 status = NT_STATUS_FILE_IS_A_DIRECTORY;
    4324           0 :                                 goto out;
    4325             :                         }
    4326           0 :                         status = unlink_internals(conn,
    4327             :                                                 req,
    4328             :                                                 FILE_ATTRIBUTE_NORMAL,
    4329             :                                                 NULL, /* new_dirfsp */
    4330             :                                                 smb_fname_new);
    4331           0 :                         if (!NT_STATUS_IS_OK(status)) {
    4332           0 :                                 goto out;
    4333             :                         }
    4334             :                 } else {
    4335             :                         /* Disallow if newname already exists. */
    4336           0 :                         status = NT_STATUS_OBJECT_NAME_COLLISION;
    4337           0 :                         goto out;
    4338             :                 }
    4339             :         }
    4340             : 
    4341           4 :         DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
    4342             :                   smb_fname_old->base_name, smb_fname_new->base_name));
    4343             : 
    4344           4 :         ret = SMB_VFS_LINKAT(conn,
    4345             :                         parent_fname_old->fsp,
    4346             :                         base_name_old,
    4347             :                         parent_fname_new->fsp,
    4348             :                         base_name_new,
    4349             :                         0);
    4350             : 
    4351           4 :         if (ret != 0) {
    4352           0 :                 status = map_nt_error_from_unix(errno);
    4353           0 :                 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
    4354             :                          nt_errstr(status), smb_fname_old->base_name,
    4355             :                          smb_fname_new->base_name));
    4356             :         }
    4357             : 
    4358           6 :   out:
    4359             : 
    4360           4 :         TALLOC_FREE(parent_fname_old);
    4361           4 :         TALLOC_FREE(parent_fname_new);
    4362           4 :         return status;
    4363             : }
    4364             : 
    4365             : /****************************************************************************
    4366             :  Deal with setting the time from any of the setfilepathinfo functions.
    4367             :  NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
    4368             :  calling this function.
    4369             : ****************************************************************************/
    4370             : 
    4371         499 : NTSTATUS smb_set_file_time(connection_struct *conn,
    4372             :                            files_struct *fsp,
    4373             :                            struct smb_filename *smb_fname,
    4374             :                            struct smb_file_time *ft,
    4375             :                            bool setting_write_time)
    4376             : {
    4377         499 :         struct files_struct *set_fsp = NULL;
    4378             :         struct timeval_buf tbuf[4];
    4379         499 :         uint32_t action =
    4380             :                 FILE_NOTIFY_CHANGE_LAST_ACCESS
    4381             :                 |FILE_NOTIFY_CHANGE_LAST_WRITE
    4382             :                 |FILE_NOTIFY_CHANGE_CREATION;
    4383             :         int ret;
    4384             : 
    4385         499 :         if (!VALID_STAT(smb_fname->st)) {
    4386           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4387             :         }
    4388             : 
    4389         499 :         if (fsp == NULL) {
    4390             :                 /* A symlink */
    4391           0 :                 return NT_STATUS_OK;
    4392             :         }
    4393             : 
    4394         499 :         set_fsp = metadata_fsp(fsp);
    4395             : 
    4396             :         /* get some defaults (no modifications) if any info is zero or -1. */
    4397         499 :         if (is_omit_timespec(&ft->create_time)) {
    4398         494 :                 action &= ~FILE_NOTIFY_CHANGE_CREATION;
    4399             :         }
    4400             : 
    4401         499 :         if (is_omit_timespec(&ft->atime)) {
    4402         494 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
    4403             :         }
    4404             : 
    4405         499 :         if (is_omit_timespec(&ft->mtime)) {
    4406          61 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    4407             :         }
    4408             : 
    4409         499 :         if (!setting_write_time) {
    4410             :                 /* ft->mtime comes from change time, not write time. */
    4411         437 :                 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
    4412             :         }
    4413             : 
    4414             :         /* Ensure the resolution is the correct for
    4415             :          * what we can store on this filesystem. */
    4416             : 
    4417         499 :         round_timespec(conn->ts_res, &ft->create_time);
    4418         499 :         round_timespec(conn->ts_res, &ft->ctime);
    4419         499 :         round_timespec(conn->ts_res, &ft->atime);
    4420         499 :         round_timespec(conn->ts_res, &ft->mtime);
    4421             : 
    4422         499 :         DBG_DEBUG("smb_set_filetime: actime: %s\n ",
    4423             :                   timespec_string_buf(&ft->atime, true, &tbuf[0]));
    4424         499 :         DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
    4425             :                   timespec_string_buf(&ft->mtime, true, &tbuf[1]));
    4426         499 :         DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
    4427             :                   timespec_string_buf(&ft->ctime, true, &tbuf[2]));
    4428         499 :         DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
    4429             :                   timespec_string_buf(&ft->create_time, true, &tbuf[3]));
    4430             : 
    4431         499 :         if (setting_write_time) {
    4432             :                 /*
    4433             :                  * This was a Windows setfileinfo on an open file.
    4434             :                  * NT does this a lot. We also need to 
    4435             :                  * set the time here, as it can be read by 
    4436             :                  * FindFirst/FindNext and with the patch for bug #2045
    4437             :                  * in smbd/fileio.c it ensures that this timestamp is
    4438             :                  * kept sticky even after a write. We save the request
    4439             :                  * away and will set it on file close and after a write. JRA.
    4440             :                  */
    4441             : 
    4442          62 :                 DBG_DEBUG("setting pending modtime to %s\n",
    4443             :                           timespec_string_buf(&ft->mtime, true, &tbuf[0]));
    4444             : 
    4445          62 :                 if (set_fsp != NULL) {
    4446          62 :                         set_sticky_write_time_fsp(set_fsp, ft->mtime);
    4447             :                 } else {
    4448           0 :                         set_sticky_write_time_path(
    4449           0 :                                 vfs_file_id_from_sbuf(conn, &smb_fname->st),
    4450             :                                 ft->mtime);
    4451             :                 }
    4452             :         }
    4453             : 
    4454         499 :         DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
    4455             : 
    4456         499 :         ret = file_ntimes(conn, set_fsp, ft);
    4457         499 :         if (ret != 0) {
    4458           0 :                 return map_nt_error_from_unix(errno);
    4459             :         }
    4460             : 
    4461         499 :         notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
    4462         499 :                      smb_fname->base_name);
    4463         499 :         return NT_STATUS_OK;
    4464             : }
    4465             : 
    4466             : /****************************************************************************
    4467             :  Deal with setting the dosmode from any of the setfilepathinfo functions.
    4468             :  NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
    4469             :  done before calling this function.
    4470             : ****************************************************************************/
    4471             : 
    4472          63 : static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
    4473             :                                      struct files_struct *fsp,
    4474             :                                      uint32_t dosmode)
    4475             : {
    4476          63 :         struct files_struct *dos_fsp = NULL;
    4477             :         uint32_t current_dosmode;
    4478             :         int ret;
    4479             : 
    4480          63 :         if (!VALID_STAT(fsp->fsp_name->st)) {
    4481           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4482             :         }
    4483             : 
    4484          63 :         dos_fsp = metadata_fsp(fsp);
    4485             : 
    4486          63 :         if (dosmode != 0) {
    4487          59 :                 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
    4488          33 :                         dosmode |= FILE_ATTRIBUTE_DIRECTORY;
    4489             :                 } else {
    4490          26 :                         dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
    4491             :                 }
    4492             :         }
    4493             : 
    4494          63 :         DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
    4495             : 
    4496             :         /* check the mode isn't different, before changing it */
    4497          63 :         if (dosmode == 0) {
    4498           4 :                 return NT_STATUS_OK;
    4499             :         }
    4500          59 :         current_dosmode = fdos_mode(dos_fsp);
    4501          59 :         if (dosmode == current_dosmode) {
    4502          28 :                 return NT_STATUS_OK;
    4503             :         }
    4504             : 
    4505          31 :         DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
    4506             :                   fsp_str_dbg(dos_fsp), dosmode);
    4507             : 
    4508          31 :         ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
    4509          31 :         if (ret != 0) {
    4510           1 :                 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
    4511             :                             fsp_str_dbg(dos_fsp), strerror(errno));
    4512           1 :                 return map_nt_error_from_unix(errno);
    4513             :         }
    4514             : 
    4515          30 :         return NT_STATUS_OK;
    4516             : }
    4517             : 
    4518             : /****************************************************************************
    4519             :  Deal with setting the size from any of the setfilepathinfo functions.
    4520             : ****************************************************************************/
    4521             : 
    4522           0 : static NTSTATUS smb_set_file_size(connection_struct *conn,
    4523             :                                   struct smb_request *req,
    4524             :                                   files_struct *fsp,
    4525             :                                   struct smb_filename *smb_fname,
    4526             :                                   const SMB_STRUCT_STAT *psbuf,
    4527             :                                   off_t size,
    4528             :                                   bool fail_after_createfile)
    4529             : {
    4530           0 :         NTSTATUS status = NT_STATUS_OK;
    4531           0 :         files_struct *new_fsp = NULL;
    4532             : 
    4533           0 :         if (!VALID_STAT(*psbuf)) {
    4534           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    4535             :         }
    4536             : 
    4537           0 :         DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
    4538             :                  (uint64_t)size,
    4539             :                  get_file_size_stat(psbuf));
    4540             : 
    4541           0 :         if (size == get_file_size_stat(psbuf)) {
    4542           0 :                 if (fsp == NULL) {
    4543           0 :                         return NT_STATUS_OK;
    4544             :                 }
    4545           0 :                 if (!fsp->fsp_flags.modified) {
    4546           0 :                         return NT_STATUS_OK;
    4547             :                 }
    4548           0 :                 trigger_write_time_update_immediate(fsp);
    4549           0 :                 return NT_STATUS_OK;
    4550             :         }
    4551             : 
    4552           0 :         DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
    4553             :                   smb_fname_str_dbg(smb_fname), (double)size));
    4554             : 
    4555           0 :         if (fsp &&
    4556           0 :             !fsp->fsp_flags.is_pathref &&
    4557           0 :             fsp_get_io_fd(fsp) != -1)
    4558             :         {
    4559             :                 /* Handle based call. */
    4560           0 :                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
    4561           0 :                         return NT_STATUS_ACCESS_DENIED;
    4562             :                 }
    4563             : 
    4564           0 :                 if (vfs_set_filelen(fsp, size) == -1) {
    4565           0 :                         return map_nt_error_from_unix(errno);
    4566             :                 }
    4567           0 :                 trigger_write_time_update_immediate(fsp);
    4568           0 :                 return NT_STATUS_OK;
    4569             :         }
    4570             : 
    4571           0 :         status = SMB_VFS_CREATE_FILE(
    4572             :                 conn,                                   /* conn */
    4573             :                 req,                                    /* req */
    4574             :                 NULL,                                   /* dirfsp */
    4575             :                 smb_fname,                              /* fname */
    4576             :                 FILE_WRITE_DATA,                        /* access_mask */
    4577             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    4578             :                     FILE_SHARE_DELETE),
    4579             :                 FILE_OPEN,                              /* create_disposition*/
    4580             :                 0,                                      /* create_options */
    4581             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    4582             :                 0,                                      /* oplock_request */
    4583             :                 NULL,                                   /* lease */
    4584             :                 0,                                      /* allocation_size */
    4585             :                 0,                                      /* private_flags */
    4586             :                 NULL,                                   /* sd */
    4587             :                 NULL,                                   /* ea_list */
    4588             :                 &new_fsp,                           /* result */
    4589             :                 NULL,                                   /* pinfo */
    4590             :                 NULL, NULL);                            /* create context */
    4591             : 
    4592           0 :         if (!NT_STATUS_IS_OK(status)) {
    4593             :                 /* NB. We check for open_was_deferred in the caller. */
    4594           0 :                 return status;
    4595             :         }
    4596             : 
    4597             :         /* See RAW-SFILEINFO-END-OF-FILE */
    4598           0 :         if (fail_after_createfile) {
    4599           0 :                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4600           0 :                 return NT_STATUS_INVALID_LEVEL;
    4601             :         }
    4602             : 
    4603           0 :         if (vfs_set_filelen(new_fsp, size) == -1) {
    4604           0 :                 status = map_nt_error_from_unix(errno);
    4605           0 :                 close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4606           0 :                 return status;
    4607             :         }
    4608             : 
    4609           0 :         trigger_write_time_update_immediate(new_fsp);
    4610           0 :         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    4611           0 :         return NT_STATUS_OK;
    4612             : }
    4613             : 
    4614             : /****************************************************************************
    4615             :  Deal with SMB_INFO_SET_EA.
    4616             : ****************************************************************************/
    4617             : 
    4618           0 : static NTSTATUS smb_info_set_ea(connection_struct *conn,
    4619             :                                 const char *pdata,
    4620             :                                 int total_data,
    4621             :                                 files_struct *fsp,
    4622             :                                 struct smb_filename *smb_fname)
    4623             : {
    4624           0 :         struct ea_list *ea_list = NULL;
    4625           0 :         TALLOC_CTX *ctx = NULL;
    4626           0 :         NTSTATUS status = NT_STATUS_OK;
    4627             : 
    4628           0 :         if (total_data < 10) {
    4629             : 
    4630             :                 /* OS/2 workplace shell seems to send SET_EA requests of "null"
    4631             :                    length. They seem to have no effect. Bug #3212. JRA */
    4632             : 
    4633           0 :                 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
    4634             :                         /* We're done. We only get EA info in this call. */
    4635           0 :                         return NT_STATUS_OK;
    4636             :                 }
    4637             : 
    4638           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4639             :         }
    4640             : 
    4641           0 :         if (IVAL(pdata,0) > total_data) {
    4642           0 :                 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
    4643             :                         IVAL(pdata,0), (unsigned int)total_data));
    4644           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4645             :         }
    4646             : 
    4647           0 :         ctx = talloc_tos();
    4648           0 :         ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
    4649           0 :         if (!ea_list) {
    4650           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4651             :         }
    4652             : 
    4653           0 :         if (fsp == NULL) {
    4654             :                 /*
    4655             :                  * The only way fsp can be NULL here is if
    4656             :                  * smb_fname points at a symlink and
    4657             :                  * and we're in POSIX context.
    4658             :                  * Ensure this is the case.
    4659             :                  *
    4660             :                  * In this case we cannot set the EA.
    4661             :                  */
    4662           0 :                 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
    4663           0 :                 return NT_STATUS_ACCESS_DENIED;
    4664             :         }
    4665             : 
    4666           0 :         status = set_ea(conn, fsp, ea_list);
    4667             : 
    4668           0 :         return status;
    4669             : }
    4670             : 
    4671             : /****************************************************************************
    4672             :  Deal with SMB_FILE_FULL_EA_INFORMATION set.
    4673             : ****************************************************************************/
    4674             : 
    4675           0 : static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
    4676             :                                 const char *pdata,
    4677             :                                 int total_data,
    4678             :                                 files_struct *fsp)
    4679             : {
    4680           0 :         struct ea_list *ea_list = NULL;
    4681             :         NTSTATUS status;
    4682             : 
    4683           0 :         if (fsp == NULL) {
    4684           0 :                 return NT_STATUS_INVALID_HANDLE;
    4685             :         }
    4686             : 
    4687           0 :         if (!lp_ea_support(SNUM(conn))) {
    4688           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
    4689             :                         "EA's not supported.\n",
    4690             :                         (unsigned int)total_data));
    4691           0 :                 return NT_STATUS_EAS_NOT_SUPPORTED;
    4692             :         }
    4693             : 
    4694           0 :         if (total_data < 10) {
    4695           0 :                 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
    4696             :                         "too small.\n",
    4697             :                         (unsigned int)total_data));
    4698           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4699             :         }
    4700             : 
    4701           0 :         ea_list = read_nttrans_ea_list(talloc_tos(),
    4702             :                                 pdata,
    4703             :                                 total_data);
    4704             : 
    4705           0 :         if (!ea_list) {
    4706           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4707             :         }
    4708             : 
    4709           0 :         status = set_ea(conn, fsp, ea_list);
    4710             : 
    4711           0 :         DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
    4712             :                 smb_fname_str_dbg(fsp->fsp_name),
    4713             :                 nt_errstr(status) ));
    4714             : 
    4715           0 :         return status;
    4716             : }
    4717             : 
    4718             : 
    4719             : /****************************************************************************
    4720             :  Deal with SMB_SET_FILE_DISPOSITION_INFO.
    4721             : ****************************************************************************/
    4722             : 
    4723         806 : static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
    4724             :                                 const char *pdata,
    4725             :                                 int total_data,
    4726             :                                 files_struct *fsp,
    4727             :                                 struct smb_filename *smb_fname)
    4728             : {
    4729         806 :         NTSTATUS status = NT_STATUS_OK;
    4730             :         bool delete_on_close;
    4731         806 :         uint32_t dosmode = 0;
    4732             : 
    4733         806 :         if (total_data < 1) {
    4734           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4735             :         }
    4736             : 
    4737         806 :         if (fsp == NULL) {
    4738           0 :                 return NT_STATUS_INVALID_HANDLE;
    4739             :         }
    4740             : 
    4741         806 :         delete_on_close = (CVAL(pdata,0) ? True : False);
    4742         806 :         dosmode = fdos_mode(fsp);
    4743             : 
    4744         806 :         DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
    4745             :                 "delete_on_close = %u\n",
    4746             :                 smb_fname_str_dbg(smb_fname),
    4747             :                 (unsigned int)dosmode,
    4748             :                 (unsigned int)delete_on_close ));
    4749             : 
    4750         806 :         if (delete_on_close) {
    4751         806 :                 status = can_set_delete_on_close(fsp, dosmode);
    4752         806 :                 if (!NT_STATUS_IS_OK(status)) {
    4753           4 :                         return status;
    4754             :                 }
    4755             :         }
    4756             : 
    4757             :         /* The set is across all open files on this dev/inode pair. */
    4758         802 :         if (!set_delete_on_close(fsp, delete_on_close,
    4759         802 :                                  conn->session_info->security_token,
    4760         802 :                                  conn->session_info->unix_token)) {
    4761           0 :                 return NT_STATUS_ACCESS_DENIED;
    4762             :         }
    4763         802 :         return NT_STATUS_OK;
    4764             : }
    4765             : 
    4766             : /****************************************************************************
    4767             :  Deal with SMB_FILE_POSITION_INFORMATION.
    4768             : ****************************************************************************/
    4769             : 
    4770           0 : static NTSTATUS smb_file_position_information(connection_struct *conn,
    4771             :                                 const char *pdata,
    4772             :                                 int total_data,
    4773             :                                 files_struct *fsp)
    4774             : {
    4775             :         uint64_t position_information;
    4776             : 
    4777           0 :         if (total_data < 8) {
    4778           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4779             :         }
    4780             : 
    4781           0 :         if (fsp == NULL) {
    4782             :                 /* Ignore on pathname based set. */
    4783           0 :                 return NT_STATUS_OK;
    4784             :         }
    4785             : 
    4786           0 :         position_information = (uint64_t)IVAL(pdata,0);
    4787           0 :         position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
    4788             : 
    4789           0 :         DEBUG(10,("smb_file_position_information: Set file position "
    4790             :                   "information for file %s to %.0f\n", fsp_str_dbg(fsp),
    4791             :                   (double)position_information));
    4792           0 :         fh_set_position_information(fsp->fh, position_information);
    4793           0 :         return NT_STATUS_OK;
    4794             : }
    4795             : 
    4796             : /****************************************************************************
    4797             :  Deal with SMB_FILE_MODE_INFORMATION.
    4798             : ****************************************************************************/
    4799             : 
    4800           0 : static NTSTATUS smb_file_mode_information(connection_struct *conn,
    4801             :                                 const char *pdata,
    4802             :                                 int total_data)
    4803             : {
    4804             :         uint32_t mode;
    4805             : 
    4806           0 :         if (total_data < 4) {
    4807           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4808             :         }
    4809           0 :         mode = IVAL(pdata,0);
    4810           0 :         if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
    4811           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4812             :         }
    4813           0 :         return NT_STATUS_OK;
    4814             : }
    4815             : 
    4816             : /****************************************************************************
    4817             :  Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
    4818             : ****************************************************************************/
    4819             : 
    4820           0 : static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
    4821             :                                        struct smb_request *req,
    4822             :                                        const char *pdata,
    4823             :                                        int total_data,
    4824             :                                        struct smb_filename *new_smb_fname)
    4825             : {
    4826           0 :         char *link_target = NULL;
    4827             :         struct smb_filename target_fname;
    4828           0 :         TALLOC_CTX *ctx = talloc_tos();
    4829             :         NTSTATUS status;
    4830             :         int ret;
    4831           0 :         struct smb_filename *parent_fname = NULL;
    4832           0 :         struct smb_filename *base_name = NULL;
    4833             : 
    4834             :         /* Set a symbolic link. */
    4835             :         /* Don't allow this if follow links is false. */
    4836             : 
    4837           0 :         if (total_data == 0) {
    4838           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4839             :         }
    4840             : 
    4841           0 :         if (!lp_follow_symlinks(SNUM(conn))) {
    4842           0 :                 return NT_STATUS_ACCESS_DENIED;
    4843             :         }
    4844             : 
    4845           0 :         srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
    4846             :                     total_data, STR_TERMINATE);
    4847             : 
    4848           0 :         if (!link_target) {
    4849           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4850             :         }
    4851             : 
    4852           0 :         target_fname = (struct smb_filename) {
    4853             :                 .base_name = link_target,
    4854             :         };
    4855             : 
    4856             :         /* Removes @GMT tokens if any */
    4857           0 :         status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
    4858           0 :         if (!NT_STATUS_IS_OK(status)) {
    4859           0 :                 return status;
    4860             :         }
    4861             : 
    4862           0 :         DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
    4863             :                         new_smb_fname->base_name, link_target ));
    4864             : 
    4865           0 :         status = parent_pathref(talloc_tos(),
    4866             :                                 conn->cwd_fsp,
    4867             :                                 new_smb_fname,
    4868             :                                 &parent_fname,
    4869             :                                 &base_name);
    4870           0 :         if (!NT_STATUS_IS_OK(status)) {
    4871           0 :                 return status;
    4872             :         }
    4873             : 
    4874           0 :         ret = SMB_VFS_SYMLINKAT(conn,
    4875             :                         &target_fname,
    4876             :                         parent_fname->fsp,
    4877             :                         base_name);
    4878           0 :         if (ret != 0) {
    4879           0 :                 TALLOC_FREE(parent_fname);
    4880           0 :                 return map_nt_error_from_unix(errno);
    4881             :         }
    4882             : 
    4883           0 :         TALLOC_FREE(parent_fname);
    4884           0 :         return NT_STATUS_OK;
    4885             : }
    4886             : 
    4887             : /****************************************************************************
    4888             :  Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
    4889             : ****************************************************************************/
    4890             : 
    4891           0 : static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
    4892             :                                         struct smb_request *req,
    4893             :                                         const char *pdata, int total_data,
    4894             :                                         struct smb_filename *smb_fname_new)
    4895             : {
    4896           0 :         char *oldname = NULL;
    4897           0 :         struct files_struct *src_dirfsp = NULL;
    4898           0 :         struct smb_filename *smb_fname_old = NULL;
    4899           0 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4900           0 :         NTTIME old_twrp = 0;
    4901           0 :         TALLOC_CTX *ctx = talloc_tos();
    4902           0 :         NTSTATUS status = NT_STATUS_OK;
    4903             : 
    4904             :         /* Set a hard link. */
    4905           0 :         if (total_data == 0) {
    4906           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4907             :         }
    4908             : 
    4909           0 :         if (req->posix_pathnames) {
    4910           0 :                 srvstr_get_path_posix(ctx,
    4911             :                         pdata,
    4912           0 :                         req->flags2,
    4913             :                         &oldname,
    4914             :                         pdata,
    4915             :                         total_data,
    4916             :                         STR_TERMINATE,
    4917             :                         &status);
    4918             :         } else {
    4919           0 :                 srvstr_get_path(ctx,
    4920             :                         pdata,
    4921           0 :                         req->flags2,
    4922             :                         &oldname,
    4923             :                         pdata,
    4924             :                         total_data,
    4925             :                         STR_TERMINATE,
    4926             :                         &status);
    4927             :         }
    4928           0 :         if (!NT_STATUS_IS_OK(status)) {
    4929           0 :                 return status;
    4930             :         }
    4931             : 
    4932           0 :         DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
    4933             :                 smb_fname_str_dbg(smb_fname_new), oldname));
    4934             : 
    4935           0 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    4936           0 :                 extract_snapshot_token(oldname, &old_twrp);
    4937             :         }
    4938           0 :         status = filename_convert_dirfsp(ctx,
    4939             :                                          conn,
    4940             :                                          oldname,
    4941             :                                          ucf_flags,
    4942             :                                          old_twrp,
    4943             :                                          &src_dirfsp,
    4944             :                                          &smb_fname_old);
    4945           0 :         if (!NT_STATUS_IS_OK(status)) {
    4946           0 :                 return status;
    4947             :         }
    4948             : 
    4949           0 :         return hardlink_internals(ctx,
    4950             :                                   conn,
    4951             :                                   req,
    4952             :                                   false,
    4953             :                                   src_dirfsp,
    4954             :                                   smb_fname_old,
    4955             :                                   NULL, /* new_dirfsp */
    4956             :                                   smb_fname_new);
    4957             : }
    4958             : 
    4959             : /****************************************************************************
    4960             :  Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
    4961             : ****************************************************************************/
    4962             : 
    4963          21 : static NTSTATUS smb2_file_rename_information(connection_struct *conn,
    4964             :                                             struct smb_request *req,
    4965             :                                             const char *pdata,
    4966             :                                             int total_data,
    4967             :                                             files_struct *fsp,
    4968             :                                             struct smb_filename *smb_fname_src)
    4969             : {
    4970             :         bool overwrite;
    4971             :         uint32_t len;
    4972          21 :         char *newname = NULL;
    4973          21 :         struct files_struct *dst_dirfsp = NULL;
    4974          21 :         struct smb_filename *smb_fname_dst = NULL;
    4975          21 :         const char *dst_original_lcomp = NULL;
    4976          21 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    4977          21 :         NTTIME dst_twrp = 0;
    4978          21 :         NTSTATUS status = NT_STATUS_OK;
    4979          21 :         bool is_dfs = (req->flags2 & FLAGS2_DFS_PATHNAMES);
    4980          21 :         TALLOC_CTX *ctx = talloc_tos();
    4981             : 
    4982          21 :         if (!fsp) {
    4983           0 :                 return NT_STATUS_INVALID_HANDLE;
    4984             :         }
    4985             : 
    4986          21 :         if (total_data < 20) {
    4987           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4988             :         }
    4989             : 
    4990          21 :         overwrite = (CVAL(pdata,0) ? True : False);
    4991          21 :         len = IVAL(pdata,16);
    4992             : 
    4993          21 :         if (len > (total_data - 20) || (len == 0)) {
    4994           0 :                 return NT_STATUS_INVALID_PARAMETER;
    4995             :         }
    4996             : 
    4997          21 :         (void)srvstr_pull_talloc(ctx,
    4998             :                                  pdata,
    4999             :                                  req->flags2,
    5000             :                                  &newname,
    5001             :                                  &pdata[20],
    5002             :                                  len,
    5003             :                                  STR_TERMINATE);
    5004             : 
    5005          21 :         if (newname == NULL) {
    5006           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5007             :         }
    5008          21 :         status = check_path_syntax_smb2(newname, is_dfs);
    5009          21 :         if (!NT_STATUS_IS_OK(status)) {
    5010           0 :                 return status;
    5011             :         }
    5012             : 
    5013          21 :         DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
    5014             :                                 newname));
    5015             : 
    5016          21 :         if (newname[0] == ':') {
    5017             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    5018           0 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    5019           0 :                                         fsp->base_fsp->fsp_name->base_name,
    5020             :                                         newname,
    5021             :                                         NULL,
    5022           0 :                                         fsp->base_fsp->fsp_name->twrp,
    5023           0 :                                         fsp->base_fsp->fsp_name->flags);
    5024           0 :                 if (smb_fname_dst == NULL) {
    5025           0 :                         status = NT_STATUS_NO_MEMORY;
    5026           0 :                         goto out;
    5027             :                 }
    5028             :         } else {
    5029          21 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
    5030           0 :                         extract_snapshot_token(newname, &dst_twrp);
    5031             :                 }
    5032          21 :                 status = filename_convert_dirfsp(ctx,
    5033             :                                                  conn,
    5034             :                                                  newname,
    5035             :                                                  ucf_flags,
    5036             :                                                  dst_twrp,
    5037             :                                                  &dst_dirfsp,
    5038             :                                                  &smb_fname_dst);
    5039          21 :                 if (!NT_STATUS_IS_OK(status)) {
    5040           0 :                         goto out;
    5041             :                 }
    5042             :         }
    5043             : 
    5044             :         /*
    5045             :          * Set the original last component, since
    5046             :          * rename_internals_fsp() requires it.
    5047             :          */
    5048          21 :         dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    5049             :                                         conn,
    5050             :                                         newname,
    5051             :                                         ucf_flags);
    5052          21 :         if (dst_original_lcomp == NULL) {
    5053           0 :                 status = NT_STATUS_NO_MEMORY;
    5054           0 :                 goto out;
    5055             :         }
    5056             : 
    5057          21 :         DEBUG(10,("smb2_file_rename_information: "
    5058             :                   "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    5059             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    5060             :                   smb_fname_str_dbg(smb_fname_dst)));
    5061          21 :         status = rename_internals_fsp(conn,
    5062             :                                 fsp,
    5063             :                                 NULL, /* dst_dirfsp */
    5064             :                                 smb_fname_dst,
    5065             :                                 dst_original_lcomp,
    5066             :                                 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
    5067             :                                 overwrite);
    5068             : 
    5069          21 :  out:
    5070          21 :         TALLOC_FREE(smb_fname_dst);
    5071          21 :         return status;
    5072             : }
    5073             : 
    5074           4 : static NTSTATUS smb_file_link_information(connection_struct *conn,
    5075             :                                             struct smb_request *req,
    5076             :                                             const char *pdata,
    5077             :                                             int total_data,
    5078             :                                             files_struct *fsp,
    5079             :                                             struct smb_filename *smb_fname_src)
    5080             : {
    5081             :         bool overwrite;
    5082             :         uint32_t len;
    5083           4 :         char *newname = NULL;
    5084           4 :         struct files_struct *dst_dirfsp = NULL;
    5085           4 :         struct smb_filename *smb_fname_dst = NULL;
    5086           4 :         NTSTATUS status = NT_STATUS_OK;
    5087           4 :         uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    5088           4 :         NTTIME dst_twrp = 0;
    5089           4 :         TALLOC_CTX *ctx = talloc_tos();
    5090             : 
    5091           4 :         if (!fsp) {
    5092           0 :                 return NT_STATUS_INVALID_HANDLE;
    5093             :         }
    5094             : 
    5095           4 :         if (total_data < 20) {
    5096           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5097             :         }
    5098             : 
    5099           4 :         overwrite = (CVAL(pdata,0) ? true : false);
    5100           4 :         len = IVAL(pdata,16);
    5101             : 
    5102           4 :         if (len > (total_data - 20) || (len == 0)) {
    5103           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5104             :         }
    5105             : 
    5106           4 :         if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
    5107           0 :                 srvstr_get_path_posix(ctx,
    5108             :                                 pdata,
    5109           0 :                                 req->flags2,
    5110             :                                 &newname,
    5111             :                                 &pdata[20],
    5112             :                                 len,
    5113             :                                 STR_TERMINATE,
    5114             :                                 &status);
    5115           0 :                 ucf_flags |= UCF_POSIX_PATHNAMES;
    5116             :         } else {
    5117           6 :                 srvstr_get_path(ctx,
    5118             :                                 pdata,
    5119           4 :                                 req->flags2,
    5120             :                                 &newname,
    5121             :                                 &pdata[20],
    5122             :                                 len,
    5123             :                                 STR_TERMINATE,
    5124             :                                 &status);
    5125             :         }
    5126           4 :         if (!NT_STATUS_IS_OK(status)) {
    5127           0 :                 return status;
    5128             :         }
    5129             : 
    5130           4 :         DEBUG(10,("smb_file_link_information: got name |%s|\n",
    5131             :                                 newname));
    5132             : 
    5133           4 :         if (ucf_flags & UCF_GMT_PATHNAME) {
    5134           0 :                 extract_snapshot_token(newname, &dst_twrp);
    5135             :         }
    5136           4 :         status = filename_convert_dirfsp(ctx,
    5137             :                                          conn,
    5138             :                                          newname,
    5139             :                                          ucf_flags,
    5140             :                                          dst_twrp,
    5141             :                                          &dst_dirfsp,
    5142             :                                          &smb_fname_dst);
    5143           4 :         if (!NT_STATUS_IS_OK(status)) {
    5144           0 :                 return status;
    5145             :         }
    5146             : 
    5147           4 :         if (fsp->base_fsp) {
    5148             :                 /* No stream names. */
    5149           0 :                 return NT_STATUS_NOT_SUPPORTED;
    5150             :         }
    5151             : 
    5152           4 :         DEBUG(10,("smb_file_link_information: "
    5153             :                   "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
    5154             :                   fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    5155             :                   smb_fname_str_dbg(smb_fname_dst)));
    5156           6 :         status = hardlink_internals(ctx,
    5157             :                                 conn,
    5158             :                                 req,
    5159             :                                 overwrite,
    5160             :                                 NULL, /* src_dirfsp */
    5161           4 :                                 fsp->fsp_name,
    5162             :                                 dst_dirfsp, /* dst_dirfsp */
    5163             :                                 smb_fname_dst);
    5164             : 
    5165           4 :         TALLOC_FREE(smb_fname_dst);
    5166           4 :         return status;
    5167             : }
    5168             : 
    5169             : /****************************************************************************
    5170             :  Deal with SMB_FILE_RENAME_INFORMATION.
    5171             : ****************************************************************************/
    5172             : 
    5173           0 : static NTSTATUS smb_file_rename_information(connection_struct *conn,
    5174             :                                             struct smb_request *req,
    5175             :                                             const char *pdata,
    5176             :                                             int total_data,
    5177             :                                             files_struct *fsp,
    5178             :                                             struct smb_filename *smb_fname_src)
    5179             : {
    5180             :         bool overwrite;
    5181             :         uint32_t root_fid;
    5182             :         uint32_t len;
    5183           0 :         char *newname = NULL;
    5184           0 :         struct files_struct *dst_dirfsp = NULL;
    5185           0 :         struct smb_filename *smb_fname_dst = NULL;
    5186           0 :         const char *dst_original_lcomp = NULL;
    5187           0 :         NTSTATUS status = NT_STATUS_OK;
    5188             :         char *p;
    5189           0 :         TALLOC_CTX *ctx = talloc_tos();
    5190             : 
    5191           0 :         if (total_data < 13) {
    5192           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5193             :         }
    5194             : 
    5195           0 :         overwrite = (CVAL(pdata,0) != 0);
    5196           0 :         root_fid = IVAL(pdata,4);
    5197           0 :         len = IVAL(pdata,8);
    5198             : 
    5199           0 :         if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
    5200           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5201             :         }
    5202             : 
    5203           0 :         if (req->posix_pathnames) {
    5204           0 :                 srvstr_get_path_posix(ctx,
    5205             :                                 pdata,
    5206           0 :                                 req->flags2,
    5207             :                                 &newname,
    5208             :                                 &pdata[12],
    5209             :                                 len,
    5210             :                                 0,
    5211             :                                 &status);
    5212             :         } else {
    5213           0 :                 srvstr_get_path(ctx,
    5214             :                                 pdata,
    5215           0 :                                 req->flags2,
    5216             :                                 &newname,
    5217             :                                 &pdata[12],
    5218             :                                 len,
    5219             :                                 0,
    5220             :                                 &status);
    5221             :         }
    5222           0 :         if (!NT_STATUS_IS_OK(status)) {
    5223           0 :                 return status;
    5224             :         }
    5225             : 
    5226           0 :         DEBUG(10,("smb_file_rename_information: got name |%s|\n",
    5227             :                                 newname));
    5228             : 
    5229             :         /* Check the new name has no '/' characters. */
    5230           0 :         if (strchr_m(newname, '/')) {
    5231           0 :                 return NT_STATUS_NOT_SUPPORTED;
    5232             :         }
    5233             : 
    5234           0 :         if (fsp && fsp->base_fsp) {
    5235             :                 /* newname must be a stream name. */
    5236           0 :                 if (newname[0] != ':') {
    5237           0 :                         return NT_STATUS_NOT_SUPPORTED;
    5238             :                 }
    5239             : 
    5240             :                 /* Create an smb_fname to call rename_internals_fsp() with. */
    5241           0 :                 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
    5242           0 :                                         fsp->base_fsp->fsp_name->base_name,
    5243             :                                         newname,
    5244             :                                         NULL,
    5245           0 :                                         fsp->base_fsp->fsp_name->twrp,
    5246           0 :                                         fsp->base_fsp->fsp_name->flags);
    5247           0 :                 if (smb_fname_dst == NULL) {
    5248           0 :                         status = NT_STATUS_NO_MEMORY;
    5249           0 :                         goto out;
    5250             :                 }
    5251             : 
    5252             :                 /*
    5253             :                  * Get the original last component, since
    5254             :                  * rename_internals_fsp() requires it.
    5255             :                  */
    5256           0 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    5257             :                                         conn,
    5258             :                                         newname,
    5259             :                                         0);
    5260           0 :                 if (dst_original_lcomp == NULL) {
    5261           0 :                         status = NT_STATUS_NO_MEMORY;
    5262           0 :                         goto out;
    5263             :                 }
    5264             : 
    5265             :         } else {
    5266             :                 /*
    5267             :                  * Build up an smb_fname_dst based on the filename passed in.
    5268             :                  * We basically just strip off the last component, and put on
    5269             :                  * the newname instead.
    5270             :                  */
    5271           0 :                 char *base_name = NULL;
    5272           0 :                 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
    5273           0 :                 NTTIME dst_twrp = 0;
    5274             : 
    5275             :                 /* newname must *not* be a stream name. */
    5276           0 :                 if (newname[0] == ':') {
    5277           0 :                         return NT_STATUS_NOT_SUPPORTED;
    5278             :                 }
    5279             : 
    5280             :                 /*
    5281             :                  * Strip off the last component (filename) of the path passed
    5282             :                  * in.
    5283             :                  */
    5284           0 :                 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
    5285           0 :                 if (!base_name) {
    5286           0 :                         return NT_STATUS_NO_MEMORY;
    5287             :                 }
    5288           0 :                 p = strrchr_m(base_name, '/');
    5289           0 :                 if (p) {
    5290           0 :                         p[1] = '\0';
    5291             :                 } else {
    5292           0 :                         base_name = talloc_strdup(ctx, "");
    5293           0 :                         if (!base_name) {
    5294           0 :                                 return NT_STATUS_NO_MEMORY;
    5295             :                         }
    5296             :                 }
    5297             :                 /* Append the new name. */
    5298           0 :                 base_name = talloc_asprintf_append(base_name,
    5299             :                                 "%s",
    5300             :                                 newname);
    5301           0 :                 if (!base_name) {
    5302           0 :                         return NT_STATUS_NO_MEMORY;
    5303             :                 }
    5304             : 
    5305           0 :                 if (ucf_flags & UCF_GMT_PATHNAME) {
    5306           0 :                         extract_snapshot_token(base_name, &dst_twrp);
    5307             :                 }
    5308           0 :                 status = filename_convert_dirfsp(ctx,
    5309             :                                          conn,
    5310             :                                          base_name,
    5311             :                                          ucf_flags,
    5312             :                                          dst_twrp,
    5313             :                                          &dst_dirfsp,
    5314             :                                          &smb_fname_dst);
    5315             : 
    5316           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5317           0 :                         goto out;
    5318             :                 }
    5319           0 :                 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
    5320             :                                         conn,
    5321             :                                         newname,
    5322             :                                         ucf_flags);
    5323           0 :                 if (dst_original_lcomp == NULL) {
    5324           0 :                         status = NT_STATUS_NO_MEMORY;
    5325           0 :                         goto out;
    5326             :                 }
    5327             :         }
    5328             : 
    5329           0 :         if (fsp != NULL && fsp->fsp_flags.is_fsa) {
    5330           0 :                 DEBUG(10,("smb_file_rename_information: "
    5331             :                           "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
    5332             :                           fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
    5333             :                           smb_fname_str_dbg(smb_fname_dst)));
    5334           0 :                 status = rename_internals_fsp(conn,
    5335             :                                         fsp,
    5336             :                                         dst_dirfsp,
    5337             :                                         smb_fname_dst,
    5338             :                                         dst_original_lcomp,
    5339             :                                         0,
    5340             :                                         overwrite);
    5341             :         } else {
    5342           0 :                 DEBUG(10,("smb_file_rename_information: "
    5343             :                           "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
    5344             :                           smb_fname_str_dbg(smb_fname_src),
    5345             :                           smb_fname_str_dbg(smb_fname_dst)));
    5346           0 :                 status = rename_internals(ctx,
    5347             :                                         conn,
    5348             :                                         req,
    5349             :                                         NULL, /* src_dirfsp */
    5350             :                                         smb_fname_src,
    5351             :                                         dst_dirfsp,
    5352             :                                         smb_fname_dst,
    5353             :                                         dst_original_lcomp,
    5354             :                                         0,
    5355             :                                         overwrite,
    5356             :                                         FILE_WRITE_ATTRIBUTES);
    5357             :         }
    5358           0 :  out:
    5359           0 :         TALLOC_FREE(smb_fname_dst);
    5360           0 :         return status;
    5361             : }
    5362             : 
    5363             : /****************************************************************************
    5364             :  Deal with SMB_SET_POSIX_ACL.
    5365             : ****************************************************************************/
    5366             : 
    5367             : #if defined(HAVE_POSIX_ACLS)
    5368           0 : static NTSTATUS smb_set_posix_acl(connection_struct *conn,
    5369             :                                 struct smb_request *req,
    5370             :                                 const char *pdata,
    5371             :                                 int total_data_in,
    5372             :                                 files_struct *fsp,
    5373             :                                 struct smb_filename *smb_fname)
    5374             : {
    5375             :         uint16_t posix_acl_version;
    5376             :         uint16_t num_file_acls;
    5377             :         uint16_t num_def_acls;
    5378           0 :         bool valid_file_acls = true;
    5379           0 :         bool valid_def_acls = true;
    5380             :         NTSTATUS status;
    5381             :         unsigned int size_needed;
    5382             :         unsigned int total_data;
    5383           0 :         bool close_fsp = false;
    5384             : 
    5385           0 :         if (total_data_in < 0) {
    5386           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5387           0 :                 goto out;
    5388             :         }
    5389             : 
    5390           0 :         total_data = total_data_in;
    5391             : 
    5392           0 :         if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
    5393           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5394           0 :                 goto out;
    5395             :         }
    5396           0 :         posix_acl_version = SVAL(pdata,0);
    5397           0 :         num_file_acls = SVAL(pdata,2);
    5398           0 :         num_def_acls = SVAL(pdata,4);
    5399             : 
    5400           0 :         if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    5401           0 :                 valid_file_acls = false;
    5402           0 :                 num_file_acls = 0;
    5403             :         }
    5404             : 
    5405           0 :         if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
    5406           0 :                 valid_def_acls = false;
    5407           0 :                 num_def_acls = 0;
    5408             :         }
    5409             : 
    5410           0 :         if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
    5411           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5412           0 :                 goto out;
    5413             :         }
    5414             : 
    5415             :         /* Wrap checks. */
    5416           0 :         if (num_file_acls + num_def_acls < num_file_acls) {
    5417           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5418           0 :                 goto out;
    5419             :         }
    5420             : 
    5421           0 :         size_needed = num_file_acls + num_def_acls;
    5422             : 
    5423             :         /*
    5424             :          * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
    5425             :          * than UINT_MAX, so check by division.
    5426             :          */
    5427           0 :         if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
    5428           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5429           0 :                 goto out;
    5430             :         }
    5431             : 
    5432           0 :         size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
    5433           0 :         if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
    5434           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5435           0 :                 goto out;
    5436             :         }
    5437           0 :         size_needed += SMB_POSIX_ACL_HEADER_SIZE;
    5438             : 
    5439           0 :         if (total_data < size_needed) {
    5440           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    5441           0 :                 goto out;
    5442             :         }
    5443             : 
    5444             :         /*
    5445             :          * Ensure we always operate on a file descriptor, not just
    5446             :          * the filename.
    5447             :          */
    5448           0 :         if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
    5449           0 :                 uint32_t access_mask = SEC_STD_WRITE_OWNER|
    5450             :                                         SEC_STD_WRITE_DAC|
    5451             :                                         SEC_STD_READ_CONTROL|
    5452             :                                         FILE_READ_ATTRIBUTES|
    5453             :                                         FILE_WRITE_ATTRIBUTES;
    5454             : 
    5455           0 :                 status = get_posix_fsp(conn,
    5456             :                                         req,
    5457             :                                         smb_fname,
    5458             :                                         access_mask,
    5459             :                                         &fsp);
    5460             : 
    5461           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5462           0 :                         goto out;
    5463             :                 }
    5464           0 :                 close_fsp = true;
    5465             :         }
    5466             : 
    5467             :         /* Here we know fsp != NULL */
    5468           0 :         SMB_ASSERT(fsp != NULL);
    5469             : 
    5470           0 :         status = refuse_symlink_fsp(fsp);
    5471           0 :         if (!NT_STATUS_IS_OK(status)) {
    5472           0 :                 goto out;
    5473             :         }
    5474             : 
    5475             :         /* If we have a default acl, this *must* be a directory. */
    5476           0 :         if (valid_def_acls && !fsp->fsp_flags.is_directory) {
    5477           0 :                 DBG_INFO("Can't set default acls on "
    5478             :                          "non-directory %s\n",
    5479             :                          fsp_str_dbg(fsp));
    5480           0 :                 return NT_STATUS_INVALID_HANDLE;
    5481             :         }
    5482             : 
    5483           0 :         DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
    5484             :                   "num_def_acls = %"PRIu16"\n",
    5485             :                   fsp_str_dbg(fsp),
    5486             :                   num_file_acls,
    5487             :                   num_def_acls);
    5488             : 
    5489             :         /* Move pdata to the start of the file ACL entries. */
    5490           0 :         pdata += SMB_POSIX_ACL_HEADER_SIZE;
    5491             : 
    5492           0 :         if (valid_file_acls) {
    5493           0 :                 status = set_unix_posix_acl(conn,
    5494             :                                         fsp,
    5495             :                                         num_file_acls,
    5496             :                                         pdata);
    5497           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5498           0 :                         goto out;
    5499             :                 }
    5500             :         }
    5501             : 
    5502             :         /* Move pdata to the start of the default ACL entries. */
    5503           0 :         pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
    5504             : 
    5505           0 :         if (valid_def_acls) {
    5506           0 :                 status = set_unix_posix_default_acl(conn,
    5507             :                                         fsp,
    5508             :                                         num_def_acls,
    5509             :                                         pdata);
    5510           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5511           0 :                         goto out;
    5512             :                 }
    5513             :         }
    5514             : 
    5515           0 :         status = NT_STATUS_OK;
    5516             : 
    5517           0 :   out:
    5518             : 
    5519           0 :         if (close_fsp) {
    5520           0 :                 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
    5521             :         }
    5522           0 :         return status;
    5523             : }
    5524             : #endif
    5525             : 
    5526             : /****************************************************************************
    5527             :  Deal with SMB_SET_FILE_BASIC_INFO.
    5528             : ****************************************************************************/
    5529             : 
    5530          63 : static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
    5531             :                                         const char *pdata,
    5532             :                                         int total_data,
    5533             :                                         files_struct *fsp,
    5534             :                                         struct smb_filename *smb_fname)
    5535             : {
    5536             :         /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
    5537             :         struct smb_file_time ft;
    5538          63 :         uint32_t dosmode = 0;
    5539          63 :         NTSTATUS status = NT_STATUS_OK;
    5540             : 
    5541          63 :         init_smb_file_time(&ft);
    5542             : 
    5543          63 :         if (total_data < 36) {
    5544           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5545             :         }
    5546             : 
    5547          63 :         if (fsp == NULL) {
    5548           0 :                 return NT_STATUS_INVALID_HANDLE;
    5549             :         }
    5550             : 
    5551          63 :         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    5552          63 :         if (!NT_STATUS_IS_OK(status)) {
    5553           0 :                 return status;
    5554             :         }
    5555             : 
    5556             :         /* Set the attributes */
    5557          63 :         dosmode = IVAL(pdata,32);
    5558          63 :         status = smb_set_file_dosmode(conn, fsp, dosmode);
    5559          63 :         if (!NT_STATUS_IS_OK(status)) {
    5560           1 :                 return status;
    5561             :         }
    5562             : 
    5563             :         /* create time */
    5564          62 :         ft.create_time = pull_long_date_full_timespec(pdata);
    5565             : 
    5566             :         /* access time */
    5567          62 :         ft.atime = pull_long_date_full_timespec(pdata+8);
    5568             : 
    5569             :         /* write time. */
    5570          62 :         ft.mtime = pull_long_date_full_timespec(pdata+16);
    5571             : 
    5572             :         /* change time. */
    5573          62 :         ft.ctime = pull_long_date_full_timespec(pdata+24);
    5574             : 
    5575          62 :         DEBUG(10, ("smb_set_file_basic_info: file %s\n",
    5576             :                    smb_fname_str_dbg(smb_fname)));
    5577             : 
    5578          62 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    5579          62 :         if (!NT_STATUS_IS_OK(status)) {
    5580           0 :                 return status;
    5581             :         }
    5582             : 
    5583          62 :         if (fsp->fsp_flags.modified) {
    5584           1 :                 trigger_write_time_update_immediate(fsp);
    5585             :         }
    5586          62 :         return NT_STATUS_OK;
    5587             : }
    5588             : 
    5589             : /****************************************************************************
    5590             :  Deal with SMB_INFO_STANDARD.
    5591             : ****************************************************************************/
    5592             : 
    5593           0 : static NTSTATUS smb_set_info_standard(connection_struct *conn,
    5594             :                                         const char *pdata,
    5595             :                                         int total_data,
    5596             :                                         files_struct *fsp,
    5597             :                                         struct smb_filename *smb_fname)
    5598             : {
    5599             :         NTSTATUS status;
    5600             :         struct smb_file_time ft;
    5601             : 
    5602           0 :         init_smb_file_time(&ft);
    5603             : 
    5604           0 :         if (total_data < 12) {
    5605           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5606             :         }
    5607             : 
    5608           0 :         if (fsp == NULL) {
    5609           0 :                 return NT_STATUS_INVALID_HANDLE;
    5610             :         }
    5611             : 
    5612             :         /* create time */
    5613           0 :         ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
    5614             :         /* access time */
    5615           0 :         ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
    5616             :         /* write time */
    5617           0 :         ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
    5618             : 
    5619           0 :         DEBUG(10,("smb_set_info_standard: file %s\n",
    5620             :                 smb_fname_str_dbg(smb_fname)));
    5621             : 
    5622           0 :         status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
    5623           0 :         if (!NT_STATUS_IS_OK(status)) {
    5624           0 :                 return status;
    5625             :         }
    5626             : 
    5627           0 :         status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
    5628           0 :         if (!NT_STATUS_IS_OK(status)) {
    5629           0 :                 return status;
    5630             :         }
    5631             : 
    5632           0 :         if (fsp->fsp_flags.modified) {
    5633           0 :                 trigger_write_time_update_immediate(fsp);
    5634             :         }
    5635           0 :         return NT_STATUS_OK;
    5636             : }
    5637             : 
    5638             : /****************************************************************************
    5639             :  Deal with SMB_SET_FILE_ALLOCATION_INFO.
    5640             : ****************************************************************************/
    5641             : 
    5642           0 : static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
    5643             :                                              struct smb_request *req,
    5644             :                                         const char *pdata,
    5645             :                                         int total_data,
    5646             :                                         files_struct *fsp,
    5647             :                                         struct smb_filename *smb_fname)
    5648             : {
    5649           0 :         uint64_t allocation_size = 0;
    5650           0 :         NTSTATUS status = NT_STATUS_OK;
    5651           0 :         files_struct *new_fsp = NULL;
    5652             : 
    5653           0 :         if (!VALID_STAT(smb_fname->st)) {
    5654           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    5655             :         }
    5656             : 
    5657           0 :         if (total_data < 8) {
    5658           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5659             :         }
    5660             : 
    5661           0 :         allocation_size = (uint64_t)IVAL(pdata,0);
    5662           0 :         allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
    5663           0 :         DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
    5664             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    5665             :                   (double)allocation_size));
    5666             : 
    5667           0 :         if (allocation_size) {
    5668           0 :                 allocation_size = smb_roundup(conn, allocation_size);
    5669             :         }
    5670             : 
    5671           0 :         DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
    5672             :                   "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
    5673             :                   (double)allocation_size));
    5674             : 
    5675           0 :         if (fsp &&
    5676           0 :             !fsp->fsp_flags.is_pathref &&
    5677           0 :             fsp_get_io_fd(fsp) != -1)
    5678             :         {
    5679             :                 /* Open file handle. */
    5680           0 :                 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
    5681           0 :                         return NT_STATUS_ACCESS_DENIED;
    5682             :                 }
    5683             : 
    5684             :                 /* Only change if needed. */
    5685           0 :                 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    5686           0 :                         if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
    5687           0 :                                 return map_nt_error_from_unix(errno);
    5688             :                         }
    5689             :                 }
    5690             :                 /* But always update the time. */
    5691             :                 /*
    5692             :                  * This is equivalent to a write. Ensure it's seen immediately
    5693             :                  * if there are no pending writes.
    5694             :                  */
    5695           0 :                 trigger_write_time_update_immediate(fsp);
    5696           0 :                 return NT_STATUS_OK;
    5697             :         }
    5698             : 
    5699             :         /* Pathname or stat or directory file. */
    5700           0 :         status = SMB_VFS_CREATE_FILE(
    5701             :                 conn,                                   /* conn */
    5702             :                 req,                                    /* req */
    5703             :                 NULL,                                   /* dirfsp */
    5704             :                 smb_fname,                              /* fname */
    5705             :                 FILE_WRITE_DATA,                        /* access_mask */
    5706             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    5707             :                     FILE_SHARE_DELETE),
    5708             :                 FILE_OPEN,                              /* create_disposition*/
    5709             :                 0,                                      /* create_options */
    5710             :                 FILE_ATTRIBUTE_NORMAL,                  /* file_attributes */
    5711             :                 0,                                      /* oplock_request */
    5712             :                 NULL,                                   /* lease */
    5713             :                 0,                                      /* allocation_size */
    5714             :                 0,                                      /* private_flags */
    5715             :                 NULL,                                   /* sd */
    5716             :                 NULL,                                   /* ea_list */
    5717             :                 &new_fsp,                           /* result */
    5718             :                 NULL,                                   /* pinfo */
    5719             :                 NULL, NULL);                            /* create context */
    5720             : 
    5721           0 :         if (!NT_STATUS_IS_OK(status)) {
    5722             :                 /* NB. We check for open_was_deferred in the caller. */
    5723           0 :                 return status;
    5724             :         }
    5725             : 
    5726             :         /* Only change if needed. */
    5727           0 :         if (allocation_size != get_file_size_stat(&smb_fname->st)) {
    5728           0 :                 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
    5729           0 :                         status = map_nt_error_from_unix(errno);
    5730           0 :                         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    5731           0 :                         return status;
    5732             :                 }
    5733             :         }
    5734             : 
    5735             :         /* Changing the allocation size should set the last mod time. */
    5736             :         /*
    5737             :          * This is equivalent to a write. Ensure it's seen immediately
    5738             :          * if there are no pending writes.
    5739             :          */
    5740           0 :         trigger_write_time_update_immediate(new_fsp);
    5741           0 :         close_file_free(req, &new_fsp, NORMAL_CLOSE);
    5742           0 :         return NT_STATUS_OK;
    5743             : }
    5744             : 
    5745             : /****************************************************************************
    5746             :  Deal with SMB_SET_FILE_END_OF_FILE_INFO.
    5747             : ****************************************************************************/
    5748             : 
    5749           0 : static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
    5750             :                                               struct smb_request *req,
    5751             :                                         const char *pdata,
    5752             :                                         int total_data,
    5753             :                                         files_struct *fsp,
    5754             :                                         struct smb_filename *smb_fname,
    5755             :                                         bool fail_after_createfile)
    5756             : {
    5757             :         off_t size;
    5758             : 
    5759           0 :         if (total_data < 8) {
    5760           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5761             :         }
    5762             : 
    5763           0 :         size = IVAL(pdata,0);
    5764           0 :         size |= (((off_t)IVAL(pdata,4)) << 32);
    5765           0 :         DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
    5766             :                   "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
    5767             :                   (double)size));
    5768             : 
    5769           0 :         return smb_set_file_size(conn, req,
    5770             :                                 fsp,
    5771             :                                 smb_fname,
    5772           0 :                                 &smb_fname->st,
    5773             :                                 size,
    5774             :                                 fail_after_createfile);
    5775             : }
    5776             : 
    5777             : /****************************************************************************
    5778             :  Allow a UNIX info mknod.
    5779             : ****************************************************************************/
    5780             : 
    5781           0 : static NTSTATUS smb_unix_mknod(connection_struct *conn,
    5782             :                                         const char *pdata,
    5783             :                                         int total_data,
    5784             :                                         const struct smb_filename *smb_fname)
    5785             : {
    5786           0 :         uint32_t file_type = IVAL(pdata,56);
    5787             : #if defined(HAVE_MAKEDEV)
    5788           0 :         uint32_t dev_major = IVAL(pdata,60);
    5789           0 :         uint32_t dev_minor = IVAL(pdata,68);
    5790             : #endif
    5791           0 :         SMB_DEV_T dev = (SMB_DEV_T)0;
    5792           0 :         uint32_t raw_unixmode = IVAL(pdata,84);
    5793             :         NTSTATUS status;
    5794             :         mode_t unixmode;
    5795             :         int ret;
    5796           0 :         struct smb_filename *parent_fname = NULL;
    5797           0 :         struct smb_filename *base_name = NULL;
    5798             : 
    5799           0 :         if (total_data < 100) {
    5800           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5801             :         }
    5802             : 
    5803           0 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    5804             :                                       PERM_NEW_FILE, &unixmode);
    5805           0 :         if (!NT_STATUS_IS_OK(status)) {
    5806           0 :                 return status;
    5807             :         }
    5808             : 
    5809             : #if defined(HAVE_MAKEDEV)
    5810           0 :         dev = makedev(dev_major, dev_minor);
    5811             : #endif
    5812             : 
    5813           0 :         switch (file_type) {
    5814             :                 /* We can't create other objects here. */
    5815           0 :                 case UNIX_TYPE_FILE:
    5816             :                 case UNIX_TYPE_DIR:
    5817             :                 case UNIX_TYPE_SYMLINK:
    5818           0 :                         return NT_STATUS_ACCESS_DENIED;
    5819             : #if defined(S_IFIFO)
    5820           0 :                 case UNIX_TYPE_FIFO:
    5821           0 :                         unixmode |= S_IFIFO;
    5822           0 :                         break;
    5823             : #endif
    5824             : #if defined(S_IFSOCK)
    5825           0 :                 case UNIX_TYPE_SOCKET:
    5826           0 :                         unixmode |= S_IFSOCK;
    5827           0 :                         break;
    5828             : #endif
    5829             : #if defined(S_IFCHR)
    5830           0 :                 case UNIX_TYPE_CHARDEV:
    5831             :                         /* This is only allowed for root. */
    5832           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    5833           0 :                                 return NT_STATUS_ACCESS_DENIED;
    5834             :                         }
    5835           0 :                         unixmode |= S_IFCHR;
    5836           0 :                         break;
    5837             : #endif
    5838             : #if defined(S_IFBLK)
    5839           0 :                 case UNIX_TYPE_BLKDEV:
    5840           0 :                         if (get_current_uid(conn) != sec_initial_uid()) {
    5841           0 :                                 return NT_STATUS_ACCESS_DENIED;
    5842             :                         }
    5843           0 :                         unixmode |= S_IFBLK;
    5844           0 :                         break;
    5845             : #endif
    5846           0 :                 default:
    5847           0 :                         return NT_STATUS_INVALID_PARAMETER;
    5848             :         }
    5849             : 
    5850           0 :         DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
    5851             :                   "%.0f mode 0%o for file %s\n", (double)dev,
    5852             :                   (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
    5853             : 
    5854           0 :         status = parent_pathref(talloc_tos(),
    5855             :                                 conn->cwd_fsp,
    5856             :                                 smb_fname,
    5857             :                                 &parent_fname,
    5858             :                                 &base_name);
    5859           0 :         if (!NT_STATUS_IS_OK(status)) {
    5860           0 :                 return status;
    5861             :         }
    5862             : 
    5863             :         /* Ok - do the mknod. */
    5864           0 :         ret = SMB_VFS_MKNODAT(conn,
    5865             :                         parent_fname->fsp,
    5866             :                         base_name,
    5867             :                         unixmode,
    5868             :                         dev);
    5869             : 
    5870           0 :         if (ret != 0) {
    5871           0 :                 TALLOC_FREE(parent_fname);
    5872           0 :                 return map_nt_error_from_unix(errno);
    5873             :         }
    5874             : 
    5875             :         /* If any of the other "set" calls fail we
    5876             :          * don't want to end up with a half-constructed mknod.
    5877             :          */
    5878             : 
    5879           0 :         if (lp_inherit_permissions(SNUM(conn))) {
    5880           0 :                 inherit_access_posix_acl(conn,
    5881           0 :                                          parent_fname->fsp,
    5882             :                                          smb_fname,
    5883             :                                          unixmode);
    5884             :         }
    5885           0 :         TALLOC_FREE(parent_fname);
    5886             : 
    5887           0 :         return NT_STATUS_OK;
    5888             : }
    5889             : 
    5890             : /****************************************************************************
    5891             :  Deal with SMB_SET_FILE_UNIX_BASIC.
    5892             : ****************************************************************************/
    5893             : 
    5894           0 : static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
    5895             :                                         struct smb_request *req,
    5896             :                                         const char *pdata,
    5897             :                                         int total_data,
    5898             :                                         files_struct *fsp,
    5899             :                                         struct smb_filename *smb_fname)
    5900             : {
    5901             :         struct smb_file_time ft;
    5902             :         uint32_t raw_unixmode;
    5903             :         mode_t unixmode;
    5904           0 :         off_t size = 0;
    5905           0 :         uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
    5906           0 :         gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
    5907           0 :         NTSTATUS status = NT_STATUS_OK;
    5908             :         enum perm_type ptype;
    5909           0 :         files_struct *all_fsps = NULL;
    5910           0 :         bool modify_mtime = true;
    5911             :         struct file_id id;
    5912             :         SMB_STRUCT_STAT sbuf;
    5913             : 
    5914           0 :         init_smb_file_time(&ft);
    5915             : 
    5916           0 :         if (total_data < 100) {
    5917           0 :                 return NT_STATUS_INVALID_PARAMETER;
    5918             :         }
    5919             : 
    5920           0 :         if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
    5921           0 :            IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
    5922           0 :                 size=IVAL(pdata,0); /* first 8 Bytes are size */
    5923           0 :                 size |= (((off_t)IVAL(pdata,4)) << 32);
    5924             :         }
    5925             : 
    5926           0 :         ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
    5927           0 :         ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
    5928           0 :         set_owner = (uid_t)IVAL(pdata,40);
    5929           0 :         set_grp = (gid_t)IVAL(pdata,48);
    5930           0 :         raw_unixmode = IVAL(pdata,84);
    5931             : 
    5932           0 :         if (VALID_STAT(smb_fname->st)) {
    5933           0 :                 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
    5934           0 :                         ptype = PERM_EXISTING_DIR;
    5935             :                 } else {
    5936           0 :                         ptype = PERM_EXISTING_FILE;
    5937             :                 }
    5938             :         } else {
    5939           0 :                 ptype = PERM_NEW_FILE;
    5940             :         }
    5941             : 
    5942           0 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    5943             :                                       ptype, &unixmode);
    5944           0 :         if (!NT_STATUS_IS_OK(status)) {
    5945           0 :                 return status;
    5946             :         }
    5947             : 
    5948           0 :         DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
    5949             :                   "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
    5950             :                   smb_fname_str_dbg(smb_fname), (double)size,
    5951             :                   (unsigned int)set_owner, (unsigned int)set_grp,
    5952             :                   (int)raw_unixmode));
    5953             : 
    5954           0 :         sbuf = smb_fname->st;
    5955             : 
    5956           0 :         if (!VALID_STAT(sbuf)) {
    5957             :                 /*
    5958             :                  * The only valid use of this is to create character and block
    5959             :                  * devices, and named pipes. This is deprecated (IMHO) and 
    5960             :                  * a new info level should be used for mknod. JRA.
    5961             :                  */
    5962             : 
    5963           0 :                 return smb_unix_mknod(conn,
    5964             :                                         pdata,
    5965             :                                         total_data,
    5966             :                                         smb_fname);
    5967             :         }
    5968             : 
    5969             : #if 1
    5970             :         /* Horrible backwards compatibility hack as an old server bug
    5971             :          * allowed a CIFS client bug to remain unnoticed :-(. JRA.
    5972             :          * */
    5973             : 
    5974           0 :         if (!size) {
    5975           0 :                 size = get_file_size_stat(&sbuf);
    5976             :         }
    5977             : #endif
    5978             : 
    5979             :         /*
    5980             :          * Deal with the UNIX specific mode set.
    5981             :          */
    5982             : 
    5983           0 :         if (raw_unixmode != SMB_MODE_NO_CHANGE) {
    5984             :                 int ret;
    5985             : 
    5986           0 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    5987           0 :                         DBG_WARNING("Can't set mode on symlink %s\n",
    5988             :                                 smb_fname_str_dbg(smb_fname));
    5989           0 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    5990             :                 }
    5991             : 
    5992           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    5993             :                           "setting mode 0%o for file %s\n",
    5994             :                           (unsigned int)unixmode,
    5995             :                           smb_fname_str_dbg(smb_fname)));
    5996           0 :                 ret = SMB_VFS_FCHMOD(fsp, unixmode);
    5997           0 :                 if (ret != 0) {
    5998           0 :                         return map_nt_error_from_unix(errno);
    5999             :                 }
    6000             :         }
    6001             : 
    6002             :         /*
    6003             :          * Deal with the UNIX specific uid set.
    6004             :          */
    6005             : 
    6006           0 :         if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
    6007           0 :             (sbuf.st_ex_uid != set_owner)) {
    6008             :                 int ret;
    6009             : 
    6010           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    6011             :                           "changing owner %u for path %s\n",
    6012             :                           (unsigned int)set_owner,
    6013             :                           smb_fname_str_dbg(smb_fname)));
    6014             : 
    6015           0 :                 if (fsp &&
    6016           0 :                     !fsp->fsp_flags.is_pathref &&
    6017           0 :                     fsp_get_io_fd(fsp) != -1)
    6018             :                 {
    6019           0 :                         ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
    6020             :                 } else {
    6021             :                         /*
    6022             :                          * UNIX extensions calls must always operate
    6023             :                          * on symlinks.
    6024             :                          */
    6025           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname,
    6026             :                                              set_owner, (gid_t)-1);
    6027             :                 }
    6028             : 
    6029           0 :                 if (ret != 0) {
    6030           0 :                         status = map_nt_error_from_unix(errno);
    6031           0 :                         return status;
    6032             :                 }
    6033             :         }
    6034             : 
    6035             :         /*
    6036             :          * Deal with the UNIX specific gid set.
    6037             :          */
    6038             : 
    6039           0 :         if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
    6040           0 :             (sbuf.st_ex_gid != set_grp)) {
    6041             :                 int ret;
    6042             : 
    6043           0 :                 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
    6044             :                           "changing group %u for file %s\n",
    6045             :                           (unsigned int)set_grp,
    6046             :                           smb_fname_str_dbg(smb_fname)));
    6047           0 :                 if (fsp &&
    6048           0 :                     !fsp->fsp_flags.is_pathref &&
    6049           0 :                     fsp_get_io_fd(fsp) != -1)
    6050             :                 {
    6051           0 :                         ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
    6052             :                 } else {
    6053             :                         /*
    6054             :                          * UNIX extensions calls must always operate
    6055             :                          * on symlinks.
    6056             :                          */
    6057           0 :                         ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
    6058             :                                   set_grp);
    6059             :                 }
    6060           0 :                 if (ret != 0) {
    6061           0 :                         status = map_nt_error_from_unix(errno);
    6062           0 :                         return status;
    6063             :                 }
    6064             :         }
    6065             : 
    6066             :         /* Deal with any size changes. */
    6067             : 
    6068           0 :         if (S_ISREG(sbuf.st_ex_mode)) {
    6069           0 :                 status = smb_set_file_size(conn, req,
    6070             :                                            fsp,
    6071             :                                            smb_fname,
    6072             :                                            &sbuf,
    6073             :                                            size,
    6074             :                                            false);
    6075           0 :                 if (!NT_STATUS_IS_OK(status)) {
    6076           0 :                         return status;
    6077             :                 }
    6078             :         }
    6079             : 
    6080             :         /* Deal with any time changes. */
    6081           0 :         if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
    6082             :                 /* No change, don't cancel anything. */
    6083           0 :                 return status;
    6084             :         }
    6085             : 
    6086           0 :         id = vfs_file_id_from_sbuf(conn, &sbuf);
    6087           0 :         for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
    6088           0 :                         all_fsps = file_find_di_next(all_fsps, true)) {
    6089             :                 /*
    6090             :                  * We're setting the time explicitly for UNIX.
    6091             :                  * Cancel any pending changes over all handles.
    6092             :                  */
    6093           0 :                 all_fsps->fsp_flags.update_write_time_on_close = false;
    6094           0 :                 TALLOC_FREE(all_fsps->update_write_time_event);
    6095             :         }
    6096             : 
    6097             :         /*
    6098             :          * Override the "setting_write_time"
    6099             :          * parameter here as it almost does what
    6100             :          * we need. Just remember if we modified
    6101             :          * mtime and send the notify ourselves.
    6102             :          */
    6103           0 :         if (is_omit_timespec(&ft.mtime)) {
    6104           0 :                 modify_mtime = false;
    6105             :         }
    6106             : 
    6107           0 :         status = smb_set_file_time(conn,
    6108             :                                 fsp,
    6109             :                                 smb_fname,
    6110             :                                 &ft,
    6111             :                                 false);
    6112           0 :         if (modify_mtime) {
    6113           0 :                 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
    6114           0 :                         FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
    6115             :         }
    6116           0 :         return status;
    6117             : }
    6118             : 
    6119             : /****************************************************************************
    6120             :  Deal with SMB_SET_FILE_UNIX_INFO2.
    6121             : ****************************************************************************/
    6122             : 
    6123           0 : static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
    6124             :                                         struct smb_request *req,
    6125             :                                         const char *pdata,
    6126             :                                         int total_data,
    6127             :                                         files_struct *fsp,
    6128             :                                         struct smb_filename *smb_fname)
    6129             : {
    6130             :         NTSTATUS status;
    6131             :         uint32_t smb_fflags;
    6132             :         uint32_t smb_fmask;
    6133             : 
    6134           0 :         if (total_data < 116) {
    6135           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6136             :         }
    6137             : 
    6138             :         /* Start by setting all the fields that are common between UNIX_BASIC
    6139             :          * and UNIX_INFO2.
    6140             :          */
    6141           0 :         status = smb_set_file_unix_basic(conn, req, pdata, total_data,
    6142             :                                          fsp, smb_fname);
    6143           0 :         if (!NT_STATUS_IS_OK(status)) {
    6144           0 :                 return status;
    6145             :         }
    6146             : 
    6147           0 :         smb_fflags = IVAL(pdata, 108);
    6148           0 :         smb_fmask = IVAL(pdata, 112);
    6149             : 
    6150             :         /* NB: We should only attempt to alter the file flags if the client
    6151             :          * sends a non-zero mask.
    6152             :          */
    6153           0 :         if (smb_fmask != 0) {
    6154           0 :                 int stat_fflags = 0;
    6155             : 
    6156           0 :                 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
    6157             :                                              smb_fmask, &stat_fflags)) {
    6158             :                         /* Client asked to alter a flag we don't understand. */
    6159           0 :                         return NT_STATUS_INVALID_PARAMETER;
    6160             :                 }
    6161             : 
    6162           0 :                 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
    6163           0 :                         DBG_WARNING("Can't change flags on symlink %s\n",
    6164             :                                 smb_fname_str_dbg(smb_fname));
    6165           0 :                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    6166             :                 }
    6167           0 :                 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
    6168           0 :                         return map_nt_error_from_unix(errno);
    6169             :                 }
    6170             :         }
    6171             : 
    6172             :         /* XXX: need to add support for changing the create_time here. You
    6173             :          * can do this for paths on Darwin with setattrlist(2). The right way
    6174             :          * to hook this up is probably by extending the VFS utimes interface.
    6175             :          */
    6176             : 
    6177           0 :         return NT_STATUS_OK;
    6178             : }
    6179             : 
    6180             : /****************************************************************************
    6181             :  Create a directory with POSIX semantics.
    6182             : ****************************************************************************/
    6183             : 
    6184           0 : static NTSTATUS smb_posix_mkdir(connection_struct *conn,
    6185             :                                 struct smb_request *req,
    6186             :                                 char **ppdata,
    6187             :                                 int total_data,
    6188             :                                 struct smb_filename *smb_fname,
    6189             :                                 int *pdata_return_size)
    6190             : {
    6191           0 :         NTSTATUS status = NT_STATUS_OK;
    6192           0 :         uint32_t raw_unixmode = 0;
    6193           0 :         mode_t unixmode = (mode_t)0;
    6194           0 :         files_struct *fsp = NULL;
    6195           0 :         uint16_t info_level_return = 0;
    6196             :         int info;
    6197           0 :         char *pdata = *ppdata;
    6198           0 :         struct smb2_create_blobs *posx = NULL;
    6199             : 
    6200           0 :         if (total_data < 18) {
    6201           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6202             :         }
    6203             : 
    6204           0 :         raw_unixmode = IVAL(pdata,8);
    6205             :         /* Next 4 bytes are not yet defined. */
    6206             : 
    6207           0 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    6208             :                                       PERM_NEW_DIR, &unixmode);
    6209           0 :         if (!NT_STATUS_IS_OK(status)) {
    6210           0 :                 return status;
    6211             :         }
    6212             : 
    6213           0 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    6214           0 :         if (!NT_STATUS_IS_OK(status)) {
    6215           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    6216             :                             nt_errstr(status));
    6217           0 :                 return status;
    6218             :         }
    6219             : 
    6220           0 :         DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
    6221             :                   smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
    6222             : 
    6223           0 :         status = SMB_VFS_CREATE_FILE(
    6224             :                 conn,                                   /* conn */
    6225             :                 req,                                    /* req */
    6226             :                 NULL,                                   /* dirfsp */
    6227             :                 smb_fname,                              /* fname */
    6228             :                 FILE_READ_ATTRIBUTES,                   /* access_mask */
    6229             :                 FILE_SHARE_NONE,                        /* share_access */
    6230             :                 FILE_CREATE,                            /* create_disposition*/
    6231             :                 FILE_DIRECTORY_FILE,                    /* create_options */
    6232             :                 0,                                      /* file_attributes */
    6233             :                 0,                                      /* oplock_request */
    6234             :                 NULL,                                   /* lease */
    6235             :                 0,                                      /* allocation_size */
    6236             :                 0,                                      /* private_flags */
    6237             :                 NULL,                                   /* sd */
    6238             :                 NULL,                                   /* ea_list */
    6239             :                 &fsp,                                       /* result */
    6240             :                 &info,                                      /* pinfo */
    6241             :                 posx,                                   /* in_context_blobs */
    6242             :                 NULL);                                  /* out_context_blobs */
    6243             : 
    6244           0 :         TALLOC_FREE(posx);
    6245             : 
    6246           0 :         if (NT_STATUS_IS_OK(status)) {
    6247           0 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    6248             :         }
    6249             : 
    6250           0 :         info_level_return = SVAL(pdata,16);
    6251             :  
    6252           0 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    6253           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    6254           0 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    6255           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    6256             :         } else {
    6257           0 :                 *pdata_return_size = 12;
    6258             :         }
    6259             : 
    6260             :         /* Realloc the data size */
    6261           0 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    6262           0 :         if (*ppdata == NULL) {
    6263           0 :                 *pdata_return_size = 0;
    6264           0 :                 return NT_STATUS_NO_MEMORY;
    6265             :         }
    6266           0 :         pdata = *ppdata;
    6267             : 
    6268           0 :         SSVAL(pdata,0,NO_OPLOCK_RETURN);
    6269           0 :         SSVAL(pdata,2,0); /* No fnum. */
    6270           0 :         SIVAL(pdata,4,info); /* Was directory created. */
    6271             : 
    6272           0 :         switch (info_level_return) {
    6273           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    6274           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    6275           0 :                         SSVAL(pdata,10,0); /* Padding. */
    6276           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    6277           0 :                                               &smb_fname->st);
    6278           0 :                         break;
    6279           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    6280           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    6281           0 :                         SSVAL(pdata,10,0); /* Padding. */
    6282           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    6283           0 :                                                     &smb_fname->st);
    6284           0 :                         break;
    6285           0 :                 default:
    6286           0 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    6287           0 :                         SSVAL(pdata,10,0); /* Padding. */
    6288           0 :                         break;
    6289             :         }
    6290             : 
    6291           0 :         return status;
    6292             : }
    6293             : 
    6294             : /****************************************************************************
    6295             :  Open/Create a file with POSIX semantics.
    6296             : ****************************************************************************/
    6297             : 
    6298             : #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
    6299             : #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
    6300             : 
    6301           0 : static NTSTATUS smb_posix_open(connection_struct *conn,
    6302             :                                struct smb_request *req,
    6303             :                                 char **ppdata,
    6304             :                                 int total_data,
    6305             :                                 struct smb_filename *smb_fname,
    6306             :                                 int *pdata_return_size)
    6307             : {
    6308           0 :         bool extended_oplock_granted = False;
    6309           0 :         char *pdata = *ppdata;
    6310           0 :         uint32_t flags = 0;
    6311           0 :         uint32_t wire_open_mode = 0;
    6312           0 :         uint32_t raw_unixmode = 0;
    6313           0 :         uint32_t attributes = 0;
    6314           0 :         uint32_t create_disp = 0;
    6315           0 :         uint32_t access_mask = 0;
    6316           0 :         uint32_t create_options = FILE_NON_DIRECTORY_FILE;
    6317           0 :         NTSTATUS status = NT_STATUS_OK;
    6318           0 :         mode_t unixmode = (mode_t)0;
    6319           0 :         files_struct *fsp = NULL;
    6320           0 :         int oplock_request = 0;
    6321           0 :         int info = 0;
    6322           0 :         uint16_t info_level_return = 0;
    6323           0 :         struct smb2_create_blobs *posx = NULL;
    6324             : 
    6325           0 :         if (total_data < 18) {
    6326           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6327             :         }
    6328             : 
    6329           0 :         flags = IVAL(pdata,0);
    6330           0 :         oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
    6331           0 :         if (oplock_request) {
    6332           0 :                 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
    6333             :         }
    6334             : 
    6335           0 :         wire_open_mode = IVAL(pdata,4);
    6336             : 
    6337           0 :         if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
    6338           0 :                 return smb_posix_mkdir(conn, req,
    6339             :                                         ppdata,
    6340             :                                         total_data,
    6341             :                                         smb_fname,
    6342             :                                         pdata_return_size);
    6343             :         }
    6344             : 
    6345           0 :         switch (wire_open_mode & SMB_ACCMODE) {
    6346           0 :                 case SMB_O_RDONLY:
    6347           0 :                         access_mask = SMB_O_RDONLY_MAPPING;
    6348           0 :                         break;
    6349           0 :                 case SMB_O_WRONLY:
    6350           0 :                         access_mask = SMB_O_WRONLY_MAPPING;
    6351           0 :                         break;
    6352           0 :                 case SMB_O_RDWR:
    6353           0 :                         access_mask = (SMB_O_RDONLY_MAPPING|
    6354             :                                         SMB_O_WRONLY_MAPPING);
    6355           0 :                         break;
    6356           0 :                 default:
    6357           0 :                         DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
    6358             :                                 (unsigned int)wire_open_mode ));
    6359           0 :                         return NT_STATUS_INVALID_PARAMETER;
    6360             :         }
    6361             : 
    6362           0 :         wire_open_mode &= ~SMB_ACCMODE;
    6363             : 
    6364             :         /* First take care of O_CREAT|O_EXCL interactions. */
    6365           0 :         switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
    6366           0 :                 case (SMB_O_CREAT | SMB_O_EXCL):
    6367             :                         /* File exists fail. File not exist create. */
    6368           0 :                         create_disp = FILE_CREATE;
    6369           0 :                         break;
    6370           0 :                 case SMB_O_CREAT:
    6371             :                         /* File exists open. File not exist create. */
    6372           0 :                         create_disp = FILE_OPEN_IF;
    6373           0 :                         break;
    6374           0 :                 case SMB_O_EXCL:
    6375             :                         /* O_EXCL on its own without O_CREAT is undefined.
    6376             :                            We deliberately ignore it as some versions of
    6377             :                            Linux CIFSFS can send a bare O_EXCL on the
    6378             :                            wire which other filesystems in the kernel
    6379             :                            ignore. See bug 9519 for details. */
    6380             : 
    6381             :                         /* Fallthrough. */
    6382             : 
    6383             :                 case 0:
    6384             :                         /* File exists open. File not exist fail. */
    6385           0 :                         create_disp = FILE_OPEN;
    6386           0 :                         break;
    6387           0 :                 default:
    6388           0 :                         DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
    6389             :                                 (unsigned int)wire_open_mode ));
    6390           0 :                         return NT_STATUS_INVALID_PARAMETER;
    6391             :         }
    6392             : 
    6393             :         /* Next factor in the effects of O_TRUNC. */
    6394           0 :         wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
    6395             : 
    6396           0 :         if (wire_open_mode & SMB_O_TRUNC) {
    6397           0 :                 switch (create_disp) {
    6398           0 :                         case FILE_CREATE:
    6399             :                                 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
    6400             :                                 /* Leave create_disp alone as
    6401             :                                    (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
    6402             :                                 */
    6403             :                                 /* File exists fail. File not exist create. */
    6404           0 :                                 break;
    6405           0 :                         case FILE_OPEN_IF:
    6406             :                                 /* SMB_O_CREAT | SMB_O_TRUNC */
    6407             :                                 /* File exists overwrite. File not exist create. */
    6408           0 :                                 create_disp = FILE_OVERWRITE_IF;
    6409           0 :                                 break;
    6410           0 :                         case FILE_OPEN:
    6411             :                                 /* SMB_O_TRUNC */
    6412             :                                 /* File exists overwrite. File not exist fail. */
    6413           0 :                                 create_disp = FILE_OVERWRITE;
    6414           0 :                                 break;
    6415           0 :                         default:
    6416             :                                 /* Cannot get here. */
    6417           0 :                                 smb_panic("smb_posix_open: logic error");
    6418             :                                 return NT_STATUS_INVALID_PARAMETER;
    6419             :                 }
    6420           0 :         }
    6421             : 
    6422           0 :         raw_unixmode = IVAL(pdata,8);
    6423             :         /* Next 4 bytes are not yet defined. */
    6424             : 
    6425           0 :         status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
    6426           0 :                                       (VALID_STAT(smb_fname->st) ?
    6427             :                                           PERM_EXISTING_FILE : PERM_NEW_FILE),
    6428             :                                       &unixmode);
    6429             : 
    6430           0 :         if (!NT_STATUS_IS_OK(status)) {
    6431           0 :                 return status;
    6432             :         }
    6433             : 
    6434           0 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
    6435           0 :         if (!NT_STATUS_IS_OK(status)) {
    6436           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    6437             :                             nt_errstr(status));
    6438           0 :                 return status;
    6439             :         }
    6440             : 
    6441           0 :         if (wire_open_mode & SMB_O_SYNC) {
    6442           0 :                 create_options |= FILE_WRITE_THROUGH;
    6443             :         }
    6444           0 :         if (wire_open_mode & SMB_O_APPEND) {
    6445           0 :                 access_mask |= FILE_APPEND_DATA;
    6446             :         }
    6447           0 :         if (wire_open_mode & SMB_O_DIRECT) {
    6448           0 :                 attributes |= FILE_FLAG_NO_BUFFERING;
    6449             :         }
    6450             : 
    6451           0 :         if ((wire_open_mode & SMB_O_DIRECTORY) ||
    6452           0 :                         VALID_STAT_OF_DIR(smb_fname->st)) {
    6453           0 :                 if (access_mask != SMB_O_RDONLY_MAPPING) {
    6454           0 :                         return NT_STATUS_FILE_IS_A_DIRECTORY;
    6455             :                 }
    6456           0 :                 create_options &= ~FILE_NON_DIRECTORY_FILE;
    6457           0 :                 create_options |= FILE_DIRECTORY_FILE;
    6458             :         }
    6459             : 
    6460           0 :         DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
    6461             :                 smb_fname_str_dbg(smb_fname),
    6462             :                 (unsigned int)wire_open_mode,
    6463             :                 (unsigned int)unixmode ));
    6464             : 
    6465           0 :         status = SMB_VFS_CREATE_FILE(
    6466             :                 conn,                                   /* conn */
    6467             :                 req,                                    /* req */
    6468             :                 NULL,                                   /* dirfsp */
    6469             :                 smb_fname,                              /* fname */
    6470             :                 access_mask,                            /* access_mask */
    6471             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    6472             :                     FILE_SHARE_DELETE),
    6473             :                 create_disp,                            /* create_disposition*/
    6474             :                 create_options,                         /* create_options */
    6475             :                 attributes,                             /* file_attributes */
    6476             :                 oplock_request,                         /* oplock_request */
    6477             :                 NULL,                                   /* lease */
    6478             :                 0,                                      /* allocation_size */
    6479             :                 0,                                      /* private_flags */
    6480             :                 NULL,                                   /* sd */
    6481             :                 NULL,                                   /* ea_list */
    6482             :                 &fsp,                                       /* result */
    6483             :                 &info,                                      /* pinfo */
    6484             :                 posx,                                   /* in_context_blobs */
    6485             :                 NULL);                                  /* out_context_blobs */
    6486             : 
    6487           0 :         TALLOC_FREE(posx);
    6488             : 
    6489           0 :         if (!NT_STATUS_IS_OK(status)) {
    6490           0 :                 return status;
    6491             :         }
    6492             : 
    6493           0 :         if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
    6494           0 :                 extended_oplock_granted = True;
    6495             :         }
    6496             : 
    6497           0 :         if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
    6498           0 :                 extended_oplock_granted = True;
    6499             :         }
    6500             : 
    6501           0 :         info_level_return = SVAL(pdata,16);
    6502             :  
    6503             :         /* Allocate the correct return size. */
    6504             : 
    6505           0 :         if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
    6506           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
    6507           0 :         } else if (info_level_return ==  SMB_QUERY_FILE_UNIX_INFO2) {
    6508           0 :                 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
    6509             :         } else {
    6510           0 :                 *pdata_return_size = 12;
    6511             :         }
    6512             : 
    6513             :         /* Realloc the data size */
    6514           0 :         *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
    6515           0 :         if (*ppdata == NULL) {
    6516           0 :                 close_file_free(req, &fsp, ERROR_CLOSE);
    6517           0 :                 *pdata_return_size = 0;
    6518           0 :                 return NT_STATUS_NO_MEMORY;
    6519             :         }
    6520           0 :         pdata = *ppdata;
    6521             : 
    6522           0 :         if (extended_oplock_granted) {
    6523           0 :                 if (flags & REQUEST_BATCH_OPLOCK) {
    6524           0 :                         SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
    6525             :                 } else {
    6526           0 :                         SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
    6527             :                 }
    6528           0 :         } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
    6529           0 :                 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
    6530             :         } else {
    6531           0 :                 SSVAL(pdata,0,NO_OPLOCK_RETURN);
    6532             :         }
    6533             : 
    6534           0 :         SSVAL(pdata,2,fsp->fnum);
    6535           0 :         SIVAL(pdata,4,info); /* Was file created etc. */
    6536             : 
    6537           0 :         switch (info_level_return) {
    6538           0 :                 case SMB_QUERY_FILE_UNIX_BASIC:
    6539           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
    6540           0 :                         SSVAL(pdata,10,0); /* padding. */
    6541           0 :                         store_file_unix_basic(conn, pdata + 12, fsp,
    6542           0 :                                               &smb_fname->st);
    6543           0 :                         break;
    6544           0 :                 case SMB_QUERY_FILE_UNIX_INFO2:
    6545           0 :                         SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
    6546           0 :                         SSVAL(pdata,10,0); /* padding. */
    6547           0 :                         store_file_unix_basic_info2(conn, pdata + 12, fsp,
    6548           0 :                                                     &smb_fname->st);
    6549           0 :                         break;
    6550           0 :                 default:
    6551           0 :                         SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
    6552           0 :                         SSVAL(pdata,10,0); /* padding. */
    6553           0 :                         break;
    6554             :         }
    6555           0 :         return NT_STATUS_OK;
    6556             : }
    6557             : 
    6558             : /****************************************************************************
    6559             :  Delete a file with POSIX semantics.
    6560             : ****************************************************************************/
    6561             : 
    6562           0 : static NTSTATUS smb_posix_unlink(connection_struct *conn,
    6563             :                                  struct smb_request *req,
    6564             :                                 const char *pdata,
    6565             :                                 int total_data,
    6566             :                                 struct smb_filename *smb_fname)
    6567             : {
    6568           0 :         NTSTATUS status = NT_STATUS_OK;
    6569           0 :         files_struct *fsp = NULL;
    6570           0 :         uint16_t flags = 0;
    6571           0 :         char del = 1;
    6572           0 :         int info = 0;
    6573           0 :         int create_options = 0;
    6574           0 :         struct share_mode_lock *lck = NULL;
    6575             :         bool other_nonposix_opens;
    6576           0 :         struct smb2_create_blobs *posx = NULL;
    6577             : 
    6578           0 :         if (total_data < 2) {
    6579           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6580             :         }
    6581             : 
    6582           0 :         flags = SVAL(pdata,0);
    6583             : 
    6584           0 :         if (!VALID_STAT(smb_fname->st)) {
    6585           0 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    6586             :         }
    6587             : 
    6588           0 :         if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
    6589           0 :                         !VALID_STAT_OF_DIR(smb_fname->st)) {
    6590           0 :                 return NT_STATUS_NOT_A_DIRECTORY;
    6591             :         }
    6592             : 
    6593           0 :         DEBUG(10,("smb_posix_unlink: %s %s\n",
    6594             :                 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
    6595             :                 smb_fname_str_dbg(smb_fname)));
    6596             : 
    6597           0 :         if (VALID_STAT_OF_DIR(smb_fname->st)) {
    6598           0 :                 create_options |= FILE_DIRECTORY_FILE;
    6599             :         }
    6600             : 
    6601           0 :         status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
    6602           0 :         if (!NT_STATUS_IS_OK(status)) {
    6603           0 :                 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
    6604             :                             nt_errstr(status));
    6605           0 :                 return status;
    6606             :         }
    6607             : 
    6608           0 :         status = SMB_VFS_CREATE_FILE(
    6609             :                 conn,                                   /* conn */
    6610             :                 req,                                    /* req */
    6611             :                 NULL,                                   /* dirfsp */
    6612             :                 smb_fname,                              /* fname */
    6613             :                 DELETE_ACCESS,                          /* access_mask */
    6614             :                 (FILE_SHARE_READ | FILE_SHARE_WRITE |   /* share_access */
    6615             :                     FILE_SHARE_DELETE),
    6616             :                 FILE_OPEN,                              /* create_disposition*/
    6617             :                 create_options,                         /* create_options */
    6618             :                 0,                                      /* file_attributes */
    6619             :                 0,                                      /* oplock_request */
    6620             :                 NULL,                                   /* lease */
    6621             :                 0,                                      /* allocation_size */
    6622             :                 0,                                      /* private_flags */
    6623             :                 NULL,                                   /* sd */
    6624             :                 NULL,                                   /* ea_list */
    6625             :                 &fsp,                                       /* result */
    6626             :                 &info,                                      /* pinfo */
    6627             :                 posx,                                   /* in_context_blobs */
    6628             :                 NULL);                                  /* out_context_blobs */
    6629             : 
    6630           0 :         TALLOC_FREE(posx);
    6631             : 
    6632           0 :         if (!NT_STATUS_IS_OK(status)) {
    6633           0 :                 return status;
    6634             :         }
    6635             : 
    6636             :         /*
    6637             :          * Don't lie to client. If we can't really delete due to
    6638             :          * non-POSIX opens return SHARING_VIOLATION.
    6639             :          */
    6640             : 
    6641           0 :         lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
    6642           0 :         if (lck == NULL) {
    6643           0 :                 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
    6644             :                           "lock for file %s\n", fsp_str_dbg(fsp)));
    6645           0 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    6646           0 :                 return NT_STATUS_INVALID_PARAMETER;
    6647             :         }
    6648             : 
    6649           0 :         other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
    6650           0 :         if (other_nonposix_opens) {
    6651             :                 /* Fail with sharing violation. */
    6652           0 :                 TALLOC_FREE(lck);
    6653           0 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    6654           0 :                 return NT_STATUS_SHARING_VIOLATION;
    6655             :         }
    6656             : 
    6657             :         /*
    6658             :          * Set the delete on close.
    6659             :          */
    6660           0 :         status = smb_set_file_disposition_info(conn,
    6661             :                                                 &del,
    6662             :                                                 1,
    6663             :                                                 fsp,
    6664             :                                                 smb_fname);
    6665             : 
    6666           0 :         TALLOC_FREE(lck);
    6667             : 
    6668           0 :         if (!NT_STATUS_IS_OK(status)) {
    6669           0 :                 close_file_free(req, &fsp, NORMAL_CLOSE);
    6670           0 :                 return status;
    6671             :         }
    6672           0 :         return close_file_free(req, &fsp, NORMAL_CLOSE);
    6673             : }
    6674             : 
    6675           0 : static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
    6676             :                                               struct smb_request *req,
    6677             :                                               TALLOC_CTX *mem_ctx,
    6678             :                                               uint16_t info_level,
    6679             :                                               struct smb_filename *smb_fname,
    6680             :                                               files_struct *fsp,
    6681             :                                               char **ppdata,
    6682             :                                               int total_data,
    6683             :                                               int *ret_data_size)
    6684             : {
    6685           0 :         char *pdata = *ppdata;
    6686           0 :         NTSTATUS status = NT_STATUS_OK;
    6687           0 :         int data_return_size = 0;
    6688             : 
    6689           0 :         *ret_data_size = 0;
    6690             : 
    6691           0 :         if (!CAN_WRITE(conn)) {
    6692             :                 /* Allow POSIX opens. The open path will deny
    6693             :                  * any non-readonly opens. */
    6694           0 :                 if (info_level != SMB_POSIX_PATH_OPEN) {
    6695           0 :                         return NT_STATUS_DOS(ERRSRV, ERRaccess);
    6696             :                 }
    6697             :         }
    6698             : 
    6699           0 :         DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
    6700             :                   smb_fname_str_dbg(smb_fname),
    6701             :                   fsp_fnum_dbg(fsp),
    6702             :                   info_level,
    6703             :                   total_data);
    6704             : 
    6705           0 :         switch (info_level) {
    6706           0 :                 case SMB_SET_FILE_UNIX_BASIC:
    6707             :                 {
    6708           0 :                         status = smb_set_file_unix_basic(conn, req,
    6709             :                                                         pdata,
    6710             :                                                         total_data,
    6711             :                                                         fsp,
    6712             :                                                         smb_fname);
    6713           0 :                         break;
    6714             :                 }
    6715             : 
    6716           0 :                 case SMB_SET_FILE_UNIX_INFO2:
    6717             :                 {
    6718           0 :                         status = smb_set_file_unix_info2(conn, req,
    6719             :                                                         pdata,
    6720             :                                                         total_data,
    6721             :                                                         fsp,
    6722             :                                                         smb_fname);
    6723           0 :                         break;
    6724             :                 }
    6725             : 
    6726           0 :                 case SMB_SET_FILE_UNIX_LINK:
    6727             :                 {
    6728           0 :                         if (smb_fname == NULL) {
    6729             :                                 /* We must have a pathname for this. */
    6730           0 :                                 return NT_STATUS_INVALID_LEVEL;
    6731             :                         }
    6732           0 :                         status = smb_set_file_unix_link(conn, req, pdata,
    6733             :                                                         total_data, smb_fname);
    6734           0 :                         break;
    6735             :                 }
    6736             : 
    6737           0 :                 case SMB_SET_FILE_UNIX_HLINK:
    6738             :                 {
    6739           0 :                         if (smb_fname == NULL) {
    6740             :                                 /* We must have a pathname for this. */
    6741           0 :                                 return NT_STATUS_INVALID_LEVEL;
    6742             :                         }
    6743           0 :                         status = smb_set_file_unix_hlink(conn, req,
    6744             :                                                          pdata, total_data,
    6745             :                                                          smb_fname);
    6746           0 :                         break;
    6747             :                 }
    6748             : 
    6749             : #if defined(HAVE_POSIX_ACLS)
    6750           0 :                 case SMB_SET_POSIX_ACL:
    6751             :                 {
    6752           0 :                         status = smb_set_posix_acl(conn,
    6753             :                                                 req,
    6754             :                                                 pdata,
    6755             :                                                 total_data,
    6756             :                                                 fsp,
    6757             :                                                 smb_fname);
    6758           0 :                         break;
    6759             :                 }
    6760             : #endif
    6761             : 
    6762             : #if defined(WITH_SMB1SERVER)
    6763           0 :                 case SMB_SET_POSIX_LOCK:
    6764             :                 {
    6765           0 :                         if (fsp == NULL) {
    6766           0 :                                 return NT_STATUS_INVALID_LEVEL;
    6767             :                         }
    6768           0 :                         status = smb_set_posix_lock(conn, req,
    6769             :                                                     pdata, total_data, fsp);
    6770           0 :                         break;
    6771             :                 }
    6772             : #endif
    6773             : 
    6774           0 :                 case SMB_POSIX_PATH_OPEN:
    6775             :                 {
    6776           0 :                         if (smb_fname == NULL) {
    6777             :                                 /* We must have a pathname for this. */
    6778           0 :                                 return NT_STATUS_INVALID_LEVEL;
    6779             :                         }
    6780             : 
    6781           0 :                         status = smb_posix_open(conn, req,
    6782             :                                                 ppdata,
    6783             :                                                 total_data,
    6784             :                                                 smb_fname,
    6785             :                                                 &data_return_size);
    6786           0 :                         break;
    6787             :                 }
    6788             : 
    6789           0 :                 case SMB_POSIX_PATH_UNLINK:
    6790             :                 {
    6791           0 :                         if (smb_fname == NULL) {
    6792             :                                 /* We must have a pathname for this. */
    6793           0 :                                 return NT_STATUS_INVALID_LEVEL;
    6794             :                         }
    6795             : 
    6796           0 :                         status = smb_posix_unlink(conn, req,
    6797             :                                                 pdata,
    6798             :                                                 total_data,
    6799             :                                                 smb_fname);
    6800           0 :                         break;
    6801             :                 }
    6802             : 
    6803           0 :                 default:
    6804           0 :                         return NT_STATUS_INVALID_LEVEL;
    6805             :         }
    6806             : 
    6807           0 :         if (!NT_STATUS_IS_OK(status)) {
    6808           0 :                 return status;
    6809             :         }
    6810             : 
    6811           0 :         *ret_data_size = data_return_size;
    6812           0 :         return NT_STATUS_OK;
    6813             : }
    6814             : 
    6815         894 : NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
    6816             :                                 struct smb_request *req,
    6817             :                                 TALLOC_CTX *mem_ctx,
    6818             :                                 uint16_t info_level,
    6819             :                                 files_struct *fsp,
    6820             :                                 struct smb_filename *smb_fname,
    6821             :                                 char **ppdata, int total_data,
    6822             :                                 int *ret_data_size)
    6823             : {
    6824         894 :         char *pdata = *ppdata;
    6825         894 :         NTSTATUS status = NT_STATUS_OK;
    6826         894 :         int data_return_size = 0;
    6827             : 
    6828         894 :         if (INFO_LEVEL_IS_UNIX(info_level)) {
    6829           0 :                 if (!lp_smb1_unix_extensions()) {
    6830           0 :                         return NT_STATUS_INVALID_LEVEL;
    6831             :                 }
    6832           0 :                 if (!req->posix_pathnames) {
    6833           0 :                         return NT_STATUS_INVALID_LEVEL;
    6834             :                 }
    6835           0 :                 status = smbd_do_posix_setfilepathinfo(conn,
    6836             :                                                        req,
    6837             :                                                        req,
    6838             :                                                        info_level,
    6839             :                                                        smb_fname,
    6840             :                                                        fsp,
    6841             :                                                        ppdata,
    6842             :                                                        total_data,
    6843             :                                                        &data_return_size);
    6844           0 :                 if (!NT_STATUS_IS_OK(status)) {
    6845           0 :                         return status;
    6846             :                 }
    6847           0 :                 *ret_data_size = data_return_size;
    6848           0 :                 return NT_STATUS_OK;
    6849             :         }
    6850             : 
    6851         894 :         *ret_data_size = 0;
    6852             : 
    6853         894 :         DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
    6854             :                  "totdata=%d\n", smb_fname_str_dbg(smb_fname),
    6855             :                  fsp_fnum_dbg(fsp),
    6856             :                  info_level, total_data));
    6857             : 
    6858         894 :         switch (info_level) {
    6859             : 
    6860           0 :                 case SMB_INFO_STANDARD:
    6861             :                 {
    6862           0 :                         status = smb_set_info_standard(conn,
    6863             :                                         pdata,
    6864             :                                         total_data,
    6865             :                                         fsp,
    6866             :                                         smb_fname);
    6867           0 :                         break;
    6868             :                 }
    6869             : 
    6870           0 :                 case SMB_INFO_SET_EA:
    6871             :                 {
    6872           0 :                         status = smb_info_set_ea(conn,
    6873             :                                                 pdata,
    6874             :                                                 total_data,
    6875             :                                                 fsp,
    6876             :                                                 smb_fname);
    6877           0 :                         break;
    6878             :                 }
    6879             : 
    6880          63 :                 case SMB_SET_FILE_BASIC_INFO:
    6881             :                 case SMB_FILE_BASIC_INFORMATION:
    6882             :                 {
    6883          63 :                         status = smb_set_file_basic_info(conn,
    6884             :                                                         pdata,
    6885             :                                                         total_data,
    6886             :                                                         fsp,
    6887             :                                                         smb_fname);
    6888          63 :                         break;
    6889             :                 }
    6890             : 
    6891           0 :                 case SMB_FILE_ALLOCATION_INFORMATION:
    6892             :                 case SMB_SET_FILE_ALLOCATION_INFO:
    6893             :                 {
    6894           0 :                         status = smb_set_file_allocation_info(conn, req,
    6895             :                                                                 pdata,
    6896             :                                                                 total_data,
    6897             :                                                                 fsp,
    6898             :                                                                 smb_fname);
    6899           0 :                         break;
    6900             :                 }
    6901             : 
    6902           0 :                 case SMB_FILE_END_OF_FILE_INFORMATION:
    6903             :                 case SMB_SET_FILE_END_OF_FILE_INFO:
    6904             :                 {
    6905             :                         /*
    6906             :                          * XP/Win7 both fail after the createfile with
    6907             :                          * SMB_SET_FILE_END_OF_FILE_INFO but not
    6908             :                          * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
    6909             :                          * The level is known here, so pass it down
    6910             :                          * appropriately.
    6911             :                          */
    6912           0 :                         bool should_fail =
    6913             :                             (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
    6914             : 
    6915           0 :                         status = smb_set_file_end_of_file_info(conn, req,
    6916             :                                                                 pdata,
    6917             :                                                                 total_data,
    6918             :                                                                 fsp,
    6919             :                                                                 smb_fname,
    6920             :                                                                 should_fail);
    6921           0 :                         break;
    6922             :                 }
    6923             : 
    6924         806 :                 case SMB_FILE_DISPOSITION_INFORMATION:
    6925             :                 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
    6926             :                 {
    6927             : #if 0
    6928             :                         /* JRA - We used to just ignore this on a path ? 
    6929             :                          * Shouldn't this be invalid level on a pathname
    6930             :                          * based call ?
    6931             :                          */
    6932             :                         if (tran_call != TRANSACT2_SETFILEINFO) {
    6933             :                                 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
    6934             :                         }
    6935             : #endif
    6936         806 :                         status = smb_set_file_disposition_info(conn,
    6937             :                                                 pdata,
    6938             :                                                 total_data,
    6939             :                                                 fsp,
    6940             :                                                 smb_fname);
    6941         806 :                         break;
    6942             :                 }
    6943             : 
    6944           0 :                 case SMB_FILE_POSITION_INFORMATION:
    6945             :                 {
    6946           0 :                         status = smb_file_position_information(conn,
    6947             :                                                 pdata,
    6948             :                                                 total_data,
    6949             :                                                 fsp);
    6950           0 :                         break;
    6951             :                 }
    6952             : 
    6953           0 :                 case SMB_FILE_FULL_EA_INFORMATION:
    6954             :                 {
    6955           0 :                         status = smb_set_file_full_ea_info(conn,
    6956             :                                                 pdata,
    6957             :                                                 total_data,
    6958             :                                                 fsp);
    6959           0 :                         break;
    6960             :                 }
    6961             : 
    6962             :                 /* From tridge Samba4 : 
    6963             :                  * MODE_INFORMATION in setfileinfo (I have no
    6964             :                  * idea what "mode information" on a file is - it takes a value of 0,
    6965             :                  * 2, 4 or 6. What could it be?).
    6966             :                  */
    6967             : 
    6968           0 :                 case SMB_FILE_MODE_INFORMATION:
    6969             :                 {
    6970           0 :                         status = smb_file_mode_information(conn,
    6971             :                                                 pdata,
    6972             :                                                 total_data);
    6973           0 :                         break;
    6974             :                 }
    6975             : 
    6976             :                 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
    6977           0 :                 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
    6978             :                 case SMB_FILE_SHORT_NAME_INFORMATION:
    6979           0 :                         return NT_STATUS_NOT_SUPPORTED;
    6980             : 
    6981           0 :                 case SMB_FILE_RENAME_INFORMATION:
    6982             :                 {
    6983           0 :                         status = smb_file_rename_information(conn, req,
    6984             :                                                              pdata, total_data,
    6985             :                                                              fsp, smb_fname);
    6986           0 :                         break;
    6987             :                 }
    6988             : 
    6989          21 :                 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
    6990             :                 {
    6991             :                         /* SMB2 rename information. */
    6992          21 :                         status = smb2_file_rename_information(conn, req,
    6993             :                                                              pdata, total_data,
    6994             :                                                              fsp, smb_fname);
    6995          21 :                         break;
    6996             :                 }
    6997             : 
    6998           4 :                 case SMB_FILE_LINK_INFORMATION:
    6999             :                 {
    7000           4 :                         status = smb_file_link_information(conn, req,
    7001             :                                                         pdata, total_data,
    7002             :                                                         fsp, smb_fname);
    7003           4 :                         break;
    7004             :                 }
    7005             : 
    7006           0 :                 default:
    7007           0 :                         return NT_STATUS_INVALID_LEVEL;
    7008             :         }
    7009             : 
    7010         894 :         if (!NT_STATUS_IS_OK(status)) {
    7011           6 :                 return status;
    7012             :         }
    7013             : 
    7014         888 :         *ret_data_size = data_return_size;
    7015         888 :         return NT_STATUS_OK;
    7016             : }
    7017             : 
    7018           4 : static uint32_t generate_volume_serial_number(
    7019             :                         const struct loadparm_substitution *lp_sub,
    7020             :                         int snum)
    7021             : {
    7022           4 :         int serial = lp_volume_serial_number(snum);
    7023           8 :         return serial != -1 ? serial:
    7024           6 :                 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
    7025           4 :                 (str_checksum(get_local_machine_name())<<16);
    7026             : }

Generated by: LCOV version 1.13