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