smbd: use check_any_access_fsp() for all access checks
[Samba.git] / source3 / smbd / smb2_trans2.c
blob22e0f2f30200209cbd03cf90c0909d485fad27fd
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
10 Extensively modified by Andrew Tridgell, 1995
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.
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.
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/>.
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"
52 #define DIR_ENTRY_SAFETY_MARGIN 4096
54 static uint32_t generate_volume_serial_number(
55 const struct loadparm_substitution *lp_sub,
56 int snum);
58 /****************************************************************************
59 Check if an open file handle is a symlink.
60 ****************************************************************************/
62 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
65 if (!VALID_STAT(fsp->fsp_name->st)) {
66 return NT_STATUS_ACCESS_DENIED;
68 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
69 return NT_STATUS_ACCESS_DENIED;
71 if (fsp_get_pathref_fd(fsp) == -1) {
72 return NT_STATUS_ACCESS_DENIED;
74 return NT_STATUS_OK;
77 /**
78 * Check that one or more of the rights in access mask are
79 * allowed. Iow, access_requested can contain more then one right and
80 * it is sufficient having only one of those granted to pass.
81 **/
82 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
83 uint32_t access_requested)
85 uint32_t access_granted = 0;
86 NTSTATUS status;
88 if (fsp->fsp_flags.is_fsa) {
89 access_granted = fsp->access_mask;
90 } else {
91 uint32_t mask = 1;
93 while (mask != 0) {
94 if (!(mask & access_requested)) {
95 mask <<= 1;
96 continue;
99 status = smbd_check_access_rights_fsp(
100 fsp->conn->cwd_fsp,
101 fsp,
102 false,
103 mask);
104 if (NT_STATUS_IS_OK(status)) {
105 break;
107 mask <<= 1;
109 access_granted = mask;
111 if ((access_granted & access_requested) == 0) {
112 return NT_STATUS_ACCESS_DENIED;
114 return NT_STATUS_OK;
117 /********************************************************************
118 Roundup a value to the nearest allocation roundup size boundary.
119 Only do this for Windows clients.
120 ********************************************************************/
122 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
124 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
126 /* Only roundup for Windows clients. */
127 enum remote_arch_types ra_type = get_remote_arch();
128 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
129 val = SMB_ROUNDUP(val,rval);
131 return val;
134 /****************************************************************************
135 Utility functions for dealing with extended attributes.
136 ****************************************************************************/
138 /****************************************************************************
139 Refuse to allow clients to overwrite our private xattrs.
140 ****************************************************************************/
142 bool samba_private_attr_name(const char *unix_ea_name)
144 bool prohibited = false;
146 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
147 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
148 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
149 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
150 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
152 if (prohibited) {
153 return true;
156 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
157 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
158 return true;
160 return false;
163 /****************************************************************************
164 Get one EA value. Fill in a struct ea_struct.
165 ****************************************************************************/
167 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
168 files_struct *fsp,
169 const char *ea_name,
170 struct ea_struct *pea)
172 /* Get the value of this xattr. Max size is 64k. */
173 size_t attr_size = 256;
174 char *val = NULL;
175 ssize_t sizeret;
176 size_t max_xattr_size = 0;
177 NTSTATUS status;
179 if (fsp == NULL) {
180 return NT_STATUS_INVALID_HANDLE;
182 status = refuse_symlink_fsp(fsp);
183 if (!NT_STATUS_IS_OK(status)) {
184 return status;
187 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
189 again:
191 val = talloc_realloc(mem_ctx, val, char, attr_size);
192 if (!val) {
193 return NT_STATUS_NO_MEMORY;
196 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
197 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
198 attr_size = max_xattr_size;
199 goto again;
202 if (sizeret == -1) {
203 return map_nt_error_from_unix(errno);
206 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
207 dump_data(10, (uint8_t *)val, sizeret);
209 pea->flags = 0;
210 if (strnequal(ea_name, "user.", 5)) {
211 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
212 } else {
213 pea->name = talloc_strdup(mem_ctx, ea_name);
215 if (pea->name == NULL) {
216 TALLOC_FREE(val);
217 return NT_STATUS_NO_MEMORY;
219 pea->value.data = (unsigned char *)val;
220 pea->value.length = (size_t)sizeret;
221 return NT_STATUS_OK;
224 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
225 files_struct *fsp,
226 char ***pnames,
227 size_t *pnum_names)
229 char smallbuf[1024];
230 /* Get a list of all xattrs. Max namesize is 64k. */
231 size_t ea_namelist_size = 1024;
232 char *ea_namelist = smallbuf;
233 char *to_free = NULL;
235 char *p;
236 char **names;
237 size_t num_names;
238 ssize_t sizeret = -1;
239 NTSTATUS status;
241 if (pnames) {
242 *pnames = NULL;
244 *pnum_names = 0;
246 if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
248 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
249 * symlink. This is ok, handle it here, by just return no EA's
250 * on a symlink.
252 return NT_STATUS_OK;
255 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
256 ea_namelist_size);
258 if ((sizeret == -1) && (errno == ERANGE)) {
259 ea_namelist_size = 65536;
260 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
261 if (ea_namelist == NULL) {
262 return NT_STATUS_NO_MEMORY;
264 to_free = ea_namelist;
266 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
267 ea_namelist_size);
270 if (sizeret == -1) {
271 status = map_nt_error_from_unix(errno);
272 TALLOC_FREE(to_free);
273 return status;
276 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
278 if (sizeret == 0) {
279 TALLOC_FREE(to_free);
280 return NT_STATUS_OK;
284 * Ensure the result is 0-terminated
287 if (ea_namelist[sizeret-1] != '\0') {
288 TALLOC_FREE(to_free);
289 return NT_STATUS_INTERNAL_ERROR;
293 * count the names
295 num_names = 0;
297 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
298 num_names += 1;
301 *pnum_names = num_names;
303 if (pnames == NULL) {
304 TALLOC_FREE(to_free);
305 return NT_STATUS_OK;
308 names = talloc_array(mem_ctx, char *, num_names);
309 if (names == NULL) {
310 DEBUG(0, ("talloc failed\n"));
311 TALLOC_FREE(to_free);
312 return NT_STATUS_NO_MEMORY;
315 if (ea_namelist == smallbuf) {
316 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
317 if (ea_namelist == NULL) {
318 TALLOC_FREE(names);
319 return NT_STATUS_NO_MEMORY;
321 } else {
322 talloc_steal(names, ea_namelist);
324 ea_namelist = talloc_realloc(names, ea_namelist, char,
325 sizeret);
326 if (ea_namelist == NULL) {
327 TALLOC_FREE(names);
328 return NT_STATUS_NO_MEMORY;
332 num_names = 0;
334 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
335 names[num_names++] = p;
338 *pnames = names;
340 return NT_STATUS_OK;
343 /****************************************************************************
344 Return a linked list of the total EA's. Plus the total size
345 ****************************************************************************/
347 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
348 files_struct *fsp,
349 size_t *pea_total_len,
350 struct ea_list **ea_list)
352 /* Get a list of all xattrs. Max namesize is 64k. */
353 size_t i, num_names;
354 char **names;
355 struct ea_list *ea_list_head = NULL;
356 bool posix_pathnames = false;
357 NTSTATUS status;
359 *pea_total_len = 0;
360 *ea_list = NULL;
362 /* symlink */
363 if (fsp == NULL) {
364 return NT_STATUS_OK;
367 if (!lp_ea_support(SNUM(fsp->conn))) {
368 return NT_STATUS_OK;
371 if (fsp_is_alternate_stream(fsp)) {
372 return NT_STATUS_INVALID_PARAMETER;
375 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
377 status = get_ea_names_from_fsp(talloc_tos(),
378 fsp,
379 &names,
380 &num_names);
382 if (!NT_STATUS_IS_OK(status)) {
383 return status;
386 if (num_names == 0) {
387 return NT_STATUS_OK;
390 for (i=0; i<num_names; i++) {
391 struct ea_list *listp;
392 fstring dos_ea_name;
395 * POSIX EA names are divided into several namespaces by
396 * means of string prefixes. Usually, the system controls
397 * semantics for each namespace, but the 'user' namespace is
398 * available for arbitrary use, which comes closest to
399 * Windows EA semantics. Hence, we map POSIX EAs from the
400 * 'user' namespace to Windows EAs, and just ignore all the
401 * other namespaces. Also, a few specific names in the 'user'
402 * namespace are used by Samba internally. Filter them out as
403 * well, and only present the EAs that are available for
404 * arbitrary use.
406 if (!strnequal(names[i], "user.", 5)
407 || samba_private_attr_name(names[i]))
408 continue;
411 * Filter out any underlying POSIX EA names
412 * that a Windows client can't handle.
414 if (!posix_pathnames &&
415 is_invalid_windows_ea_name(names[i])) {
416 continue;
419 listp = talloc(mem_ctx, struct ea_list);
420 if (listp == NULL) {
421 return NT_STATUS_NO_MEMORY;
424 status = get_ea_value_fsp(listp,
425 fsp,
426 names[i],
427 &listp->ea);
429 if (!NT_STATUS_IS_OK(status)) {
430 TALLOC_FREE(listp);
431 return status;
434 if (listp->ea.value.length == 0) {
436 * We can never return a zero length EA.
437 * Windows reports the EA's as corrupted.
439 TALLOC_FREE(listp);
440 continue;
441 } else if (listp->ea.value.length > 65536) {
443 * SMB clients may report error with file
444 * if large EA is presented to them.
446 DBG_ERR("EA [%s] on file [%s] exceeds "
447 "maximum permitted EA size of 64KiB: %zu\n.",
448 listp->ea.name, fsp_str_dbg(fsp),
449 listp->ea.value.length);
450 TALLOC_FREE(listp);
451 continue;
454 push_ascii_fstring(dos_ea_name, listp->ea.name);
456 *pea_total_len +=
457 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
459 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
460 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
461 (unsigned int)listp->ea.value.length));
463 DLIST_ADD_END(ea_list_head, listp);
467 /* Add on 4 for total length. */
468 if (*pea_total_len) {
469 *pea_total_len += 4;
472 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
473 (unsigned int)*pea_total_len));
475 *ea_list = ea_list_head;
476 return NT_STATUS_OK;
479 /****************************************************************************
480 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
481 that was filled.
482 ****************************************************************************/
484 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
485 connection_struct *conn, struct ea_list *ea_list)
487 unsigned int ret_data_size = 4;
488 char *p = pdata;
490 SMB_ASSERT(total_data_size >= 4);
492 if (!lp_ea_support(SNUM(conn))) {
493 SIVAL(pdata,4,0);
494 return 4;
497 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
498 size_t dos_namelen;
499 fstring dos_ea_name;
500 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
501 dos_namelen = strlen(dos_ea_name);
502 if (dos_namelen > 255 || dos_namelen == 0) {
503 break;
505 if (ea_list->ea.value.length > 65535) {
506 break;
508 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
509 break;
512 /* We know we have room. */
513 SCVAL(p,0,ea_list->ea.flags);
514 SCVAL(p,1,dos_namelen);
515 SSVAL(p,2,ea_list->ea.value.length);
516 strlcpy(p+4, dos_ea_name, dos_namelen+1);
517 if (ea_list->ea.value.length > 0) {
518 memcpy(p + 4 + dos_namelen + 1,
519 ea_list->ea.value.data,
520 ea_list->ea.value.length);
523 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
524 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
527 ret_data_size = PTR_DIFF(p, pdata);
528 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
529 SIVAL(pdata,0,ret_data_size);
530 return ret_data_size;
533 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
534 char *pdata,
535 unsigned int total_data_size,
536 unsigned int *ret_data_size,
537 connection_struct *conn,
538 struct ea_list *ea_list)
540 uint8_t *p = (uint8_t *)pdata;
541 uint8_t *last_start = NULL;
542 bool do_store_data = (pdata != NULL);
544 *ret_data_size = 0;
546 if (!lp_ea_support(SNUM(conn))) {
547 return NT_STATUS_NO_EAS_ON_FILE;
550 for (; ea_list; ea_list = ea_list->next) {
551 size_t dos_namelen;
552 fstring dos_ea_name;
553 size_t this_size;
554 size_t pad = 0;
556 if (last_start != NULL && do_store_data) {
557 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
559 last_start = p;
561 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
562 dos_namelen = strlen(dos_ea_name);
563 if (dos_namelen > 255 || dos_namelen == 0) {
564 return NT_STATUS_INTERNAL_ERROR;
566 if (ea_list->ea.value.length > 65535) {
567 return NT_STATUS_INTERNAL_ERROR;
570 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
572 if (ea_list->next) {
573 pad = (4 - (this_size % 4)) % 4;
574 this_size += pad;
577 if (do_store_data) {
578 if (this_size > total_data_size) {
579 return NT_STATUS_INFO_LENGTH_MISMATCH;
582 /* We know we have room. */
583 SIVAL(p, 0x00, 0); /* next offset */
584 SCVAL(p, 0x04, ea_list->ea.flags);
585 SCVAL(p, 0x05, dos_namelen);
586 SSVAL(p, 0x06, ea_list->ea.value.length);
587 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
588 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
589 if (pad) {
590 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
591 '\0',
592 pad);
594 total_data_size -= this_size;
597 p += this_size;
600 *ret_data_size = PTR_DIFF(p, pdata);
601 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
602 return NT_STATUS_OK;
605 unsigned int estimate_ea_size(files_struct *fsp)
607 size_t total_ea_len = 0;
608 TALLOC_CTX *mem_ctx;
609 struct ea_list *ea_list = NULL;
610 NTSTATUS status;
612 /* symlink */
613 if (fsp == NULL) {
614 return 0;
617 if (!lp_ea_support(SNUM(fsp->conn))) {
618 return 0;
621 mem_ctx = talloc_stackframe();
623 /* If this is a stream fsp, then we need to instead find the
624 * estimated ea len from the main file, not the stream
625 * (streams cannot have EAs), but the estimate isn't just 0 in
626 * this case! */
627 fsp = metadata_fsp(fsp);
628 (void)get_ea_list_from_fsp(mem_ctx,
629 fsp,
630 &total_ea_len,
631 &ea_list);
633 if(fsp->conn->sconn->using_smb2) {
634 unsigned int ret_data_size;
636 * We're going to be using fill_ea_chained_buffer() to
637 * marshall EA's - this size is significantly larger
638 * than the SMB1 buffer. Re-calculate the size without
639 * marshalling.
641 status = fill_ea_chained_buffer(mem_ctx,
642 NULL,
644 &ret_data_size,
645 fsp->conn,
646 ea_list);
647 if (!NT_STATUS_IS_OK(status)) {
648 ret_data_size = 0;
650 total_ea_len = ret_data_size;
652 TALLOC_FREE(mem_ctx);
653 return total_ea_len;
656 /****************************************************************************
657 Ensure the EA name is case insensitive by matching any existing EA name.
658 ****************************************************************************/
660 static void canonicalize_ea_name(files_struct *fsp,
661 fstring unix_ea_name)
663 size_t total_ea_len;
664 TALLOC_CTX *mem_ctx = talloc_tos();
665 struct ea_list *ea_list;
666 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
667 fsp,
668 &total_ea_len,
669 &ea_list);
670 if (!NT_STATUS_IS_OK(status)) {
671 return;
674 for (; ea_list; ea_list = ea_list->next) {
675 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
676 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
677 &unix_ea_name[5], ea_list->ea.name));
678 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
679 break;
684 /****************************************************************************
685 Set or delete an extended attribute.
686 ****************************************************************************/
688 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
689 struct ea_list *ea_list)
691 NTSTATUS status;
692 bool posix_pathnames = false;
694 if (!lp_ea_support(SNUM(conn))) {
695 return NT_STATUS_EAS_NOT_SUPPORTED;
698 if (fsp == NULL) {
699 return NT_STATUS_INVALID_HANDLE;
702 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
704 status = refuse_symlink_fsp(fsp);
705 if (!NT_STATUS_IS_OK(status)) {
706 return status;
709 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
710 if (!NT_STATUS_IS_OK(status)) {
711 return status;
714 /* Setting EAs on streams isn't supported. */
715 if (fsp_is_alternate_stream(fsp)) {
716 return NT_STATUS_INVALID_PARAMETER;
720 * Filter out invalid Windows EA names - before
721 * we set *any* of them.
724 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
725 return STATUS_INVALID_EA_NAME;
728 for (;ea_list; ea_list = ea_list->next) {
729 int ret;
730 fstring unix_ea_name;
733 * Complementing the forward mapping from POSIX EAs to
734 * Windows EAs in get_ea_list_from_fsp(), here we map in the
735 * opposite direction from Windows EAs to the 'user' namespace
736 * of POSIX EAs. Hence, all POSIX EA names the we set here must
737 * start with a 'user.' prefix.
739 fstrcpy(unix_ea_name, "user.");
740 fstrcat(unix_ea_name, ea_list->ea.name);
742 canonicalize_ea_name(fsp, unix_ea_name);
744 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
746 if (samba_private_attr_name(unix_ea_name)) {
747 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
748 return NT_STATUS_ACCESS_DENIED;
751 if (ea_list->ea.value.length == 0) {
752 /* Remove the attribute. */
753 DBG_DEBUG("deleting ea name %s on "
754 "file %s by file descriptor.\n",
755 unix_ea_name, fsp_str_dbg(fsp));
756 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
757 #ifdef ENOATTR
758 /* Removing a non existent attribute always succeeds. */
759 if (ret == -1 && errno == ENOATTR) {
760 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
761 unix_ea_name));
762 ret = 0;
764 #endif
765 } else {
766 DEBUG(10,("set_ea: setting ea name %s on file "
767 "%s by file descriptor.\n",
768 unix_ea_name, fsp_str_dbg(fsp)));
769 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
770 ea_list->ea.value.data, ea_list->ea.value.length, 0);
773 if (ret == -1) {
774 #ifdef ENOTSUP
775 if (errno == ENOTSUP) {
776 return NT_STATUS_EAS_NOT_SUPPORTED;
778 #endif
779 return map_nt_error_from_unix(errno);
783 return NT_STATUS_OK;
786 /****************************************************************************
787 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
788 ****************************************************************************/
790 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
792 struct ea_list *ea_list_head = NULL;
793 size_t offset = 0;
794 size_t bytes_used = 0;
796 while (offset < data_size) {
797 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
799 if (!eal) {
800 return NULL;
803 DLIST_ADD_END(ea_list_head, eal);
804 offset += bytes_used;
807 return ea_list_head;
810 /****************************************************************************
811 Count the total EA size needed.
812 ****************************************************************************/
814 static size_t ea_list_size(struct ea_list *ealist)
816 fstring dos_ea_name;
817 struct ea_list *listp;
818 size_t ret = 0;
820 for (listp = ealist; listp; listp = listp->next) {
821 push_ascii_fstring(dos_ea_name, listp->ea.name);
822 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
824 /* Add on 4 for total length. */
825 if (ret) {
826 ret += 4;
829 return ret;
832 /****************************************************************************
833 Return a union of EA's from a file list and a list of names.
834 The TALLOC context for the two lists *MUST* be identical as we steal
835 memory from one list to add to another. JRA.
836 ****************************************************************************/
838 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
840 struct ea_list *nlistp, *flistp;
842 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
843 for (flistp = file_list; flistp; flistp = flistp->next) {
844 if (strequal(nlistp->ea.name, flistp->ea.name)) {
845 break;
849 if (flistp) {
850 /* Copy the data from this entry. */
851 nlistp->ea.flags = flistp->ea.flags;
852 nlistp->ea.value = flistp->ea.value;
853 } else {
854 /* Null entry. */
855 nlistp->ea.flags = 0;
856 ZERO_STRUCT(nlistp->ea.value);
860 *total_ea_len = ea_list_size(name_list);
861 return name_list;
864 /****************************************************************************
865 Return the filetype for UNIX extensions.
866 ****************************************************************************/
868 static uint32_t unix_filetype(mode_t mode)
870 if(S_ISREG(mode))
871 return UNIX_TYPE_FILE;
872 else if(S_ISDIR(mode))
873 return UNIX_TYPE_DIR;
874 #ifdef S_ISLNK
875 else if(S_ISLNK(mode))
876 return UNIX_TYPE_SYMLINK;
877 #endif
878 #ifdef S_ISCHR
879 else if(S_ISCHR(mode))
880 return UNIX_TYPE_CHARDEV;
881 #endif
882 #ifdef S_ISBLK
883 else if(S_ISBLK(mode))
884 return UNIX_TYPE_BLKDEV;
885 #endif
886 #ifdef S_ISFIFO
887 else if(S_ISFIFO(mode))
888 return UNIX_TYPE_FIFO;
889 #endif
890 #ifdef S_ISSOCK
891 else if(S_ISSOCK(mode))
892 return UNIX_TYPE_SOCKET;
893 #endif
895 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
896 return UNIX_TYPE_UNKNOWN;
899 /****************************************************************************
900 Map wire perms onto standard UNIX permissions. Obey share restrictions.
901 ****************************************************************************/
903 NTSTATUS unix_perms_from_wire(connection_struct *conn,
904 const SMB_STRUCT_STAT *psbuf,
905 uint32_t perms,
906 enum perm_type ptype,
907 mode_t *ret_perms)
909 mode_t ret = 0;
911 if (perms == SMB_MODE_NO_CHANGE) {
912 if (!VALID_STAT(*psbuf)) {
913 return NT_STATUS_INVALID_PARAMETER;
914 } else {
915 *ret_perms = psbuf->st_ex_mode;
916 return NT_STATUS_OK;
920 ret = wire_perms_to_unix(perms);
922 if (ptype == PERM_NEW_FILE) {
924 * "create mask"/"force create mode" are
925 * only applied to new files, not existing ones.
927 ret &= lp_create_mask(SNUM(conn));
928 /* Add in force bits */
929 ret |= lp_force_create_mode(SNUM(conn));
930 } else if (ptype == PERM_NEW_DIR) {
932 * "directory mask"/"force directory mode" are
933 * only applied to new directories, not existing ones.
935 ret &= lp_directory_mask(SNUM(conn));
936 /* Add in force bits */
937 ret |= lp_force_directory_mode(SNUM(conn));
940 *ret_perms = ret;
941 return NT_STATUS_OK;
944 /****************************************************************************
945 Get a level dependent lanman2 dir entry.
946 ****************************************************************************/
948 struct smbd_dirptr_lanman2_state {
949 connection_struct *conn;
950 uint32_t info_level;
951 bool check_mangled_names;
952 bool case_sensitive;
955 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
956 void *private_data,
957 const char *dname,
958 const char *mask,
959 char **_fname)
961 struct smbd_dirptr_lanman2_state *state =
962 (struct smbd_dirptr_lanman2_state *)private_data;
963 bool ok;
964 char mangled_name[13]; /* mangled 8.3 name. */
965 bool got_match;
966 const char *fname;
968 /* Mangle fname if it's an illegal name. */
969 if (mangle_must_mangle(dname, state->conn->params)) {
971 * Slow path - ensure we can push the original name as UCS2. If
972 * not, then just don't return this name.
974 NTSTATUS status;
975 size_t ret_len = 0;
976 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
977 uint8_t *tmp = talloc_array(talloc_tos(),
978 uint8_t,
979 len);
981 status = srvstr_push(NULL,
982 FLAGS2_UNICODE_STRINGS,
983 tmp,
984 dname,
985 len,
986 STR_TERMINATE,
987 &ret_len);
989 TALLOC_FREE(tmp);
991 if (!NT_STATUS_IS_OK(status)) {
992 return false;
995 ok = name_to_8_3(dname, mangled_name,
996 true, state->conn->params);
997 if (!ok) {
998 return false;
1000 fname = mangled_name;
1001 } else {
1002 fname = dname;
1005 got_match = mask_match(fname, mask,
1006 state->case_sensitive);
1008 if(!got_match && state->check_mangled_names &&
1009 !mangle_is_8_3(fname, false, state->conn->params)) {
1011 * It turns out that NT matches wildcards against
1012 * both long *and* short names. This may explain some
1013 * of the wildcard weirdness from old DOS clients
1014 * that some people have been seeing.... JRA.
1016 /* Force the mangling into 8.3. */
1017 ok = name_to_8_3(fname, mangled_name,
1018 false, state->conn->params);
1019 if (!ok) {
1020 return false;
1023 got_match = mask_match(mangled_name, mask,
1024 state->case_sensitive);
1027 if (!got_match) {
1028 return false;
1031 *_fname = talloc_strdup(ctx, fname);
1032 if (*_fname == NULL) {
1033 return false;
1036 return true;
1039 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1041 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1042 unsigned ea_size = estimate_ea_size(fsp);
1043 return ea_size;
1045 return IO_REPARSE_TAG_DFS;
1048 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1049 connection_struct *conn,
1050 uint16_t flags2,
1051 uint32_t info_level,
1052 struct ea_list *name_list,
1053 bool check_mangled_names,
1054 bool requires_resume_key,
1055 uint32_t mode,
1056 const char *fname,
1057 const struct smb_filename *smb_fname,
1058 int space_remaining,
1059 uint8_t align,
1060 bool do_pad,
1061 char *base_data,
1062 char **ppdata,
1063 char *end_data,
1064 uint64_t *last_entry_off)
1066 char *p, *q, *pdata = *ppdata;
1067 uint32_t reskey=0;
1068 uint64_t file_size = 0;
1069 uint64_t allocation_size = 0;
1070 uint64_t file_id = 0;
1071 size_t len = 0;
1072 struct timespec mdate_ts = {0};
1073 struct timespec adate_ts = {0};
1074 struct timespec cdate_ts = {0};
1075 struct timespec create_date_ts = {0};
1076 char *nameptr;
1077 char *last_entry_ptr;
1078 bool was_8_3;
1079 int off;
1080 int pad = 0;
1081 NTSTATUS status;
1082 struct readdir_attr_data *readdir_attr_data = NULL;
1083 uint32_t ea_size;
1085 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1086 file_size = get_file_size_stat(&smb_fname->st);
1088 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1091 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1092 * a DFS symlink.
1094 if (smb_fname->fsp != NULL &&
1095 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1096 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1097 ctx,
1098 &readdir_attr_data);
1099 if (!NT_STATUS_IS_OK(status)) {
1100 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1101 status)) {
1102 return status;
1107 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1109 mdate_ts = smb_fname->st.st_ex_mtime;
1110 adate_ts = smb_fname->st.st_ex_atime;
1111 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1112 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1114 if (lp_dos_filetime_resolution(SNUM(conn))) {
1115 dos_filetime_timespec(&create_date_ts);
1116 dos_filetime_timespec(&mdate_ts);
1117 dos_filetime_timespec(&adate_ts);
1118 dos_filetime_timespec(&cdate_ts);
1121 /* align the record */
1122 SMB_ASSERT(align >= 1);
1124 off = (int)PTR_DIFF(pdata, base_data);
1125 pad = (off + (align-1)) & ~(align-1);
1126 pad -= off;
1128 if (pad && pad > space_remaining) {
1129 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1130 "for padding (wanted %u, had %d)\n",
1131 (unsigned int)pad,
1132 space_remaining ));
1133 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1136 off += pad;
1137 /* initialize padding to 0 */
1138 if (pad) {
1139 memset(pdata, 0, pad);
1141 space_remaining -= pad;
1143 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1144 space_remaining ));
1146 pdata += pad;
1147 p = pdata;
1148 last_entry_ptr = p;
1150 pad = 0;
1151 off = 0;
1153 switch (info_level) {
1154 case SMB_FIND_INFO_STANDARD:
1155 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1156 if(requires_resume_key) {
1157 SIVAL(p,0,reskey);
1158 p += 4;
1160 srv_put_dos_date2_ts(p, 0, create_date_ts);
1161 srv_put_dos_date2_ts(p, 4, adate_ts);
1162 srv_put_dos_date2_ts(p, 8, mdate_ts);
1163 SIVAL(p,12,(uint32_t)file_size);
1164 SIVAL(p,16,(uint32_t)allocation_size);
1165 SSVAL(p,20,mode);
1166 p += 23;
1167 nameptr = p;
1168 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1169 p += ucs2_align(base_data, p, 0);
1171 status = srvstr_push(base_data, flags2, p,
1172 fname, PTR_DIFF(end_data, p),
1173 STR_TERMINATE, &len);
1174 if (!NT_STATUS_IS_OK(status)) {
1175 return status;
1177 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1178 if (len > 2) {
1179 SCVAL(nameptr, -1, len - 2);
1180 } else {
1181 SCVAL(nameptr, -1, 0);
1183 } else {
1184 if (len > 1) {
1185 SCVAL(nameptr, -1, len - 1);
1186 } else {
1187 SCVAL(nameptr, -1, 0);
1190 p += len;
1191 break;
1193 case SMB_FIND_EA_SIZE:
1194 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1195 if (requires_resume_key) {
1196 SIVAL(p,0,reskey);
1197 p += 4;
1199 srv_put_dos_date2_ts(p, 0, create_date_ts);
1200 srv_put_dos_date2_ts(p, 4, adate_ts);
1201 srv_put_dos_date2_ts(p, 8, mdate_ts);
1202 SIVAL(p,12,(uint32_t)file_size);
1203 SIVAL(p,16,(uint32_t)allocation_size);
1204 SSVAL(p,20,mode);
1206 ea_size = estimate_ea_size(smb_fname->fsp);
1207 SIVAL(p,22,ea_size); /* Extended attributes */
1209 p += 27;
1210 nameptr = p - 1;
1211 status = srvstr_push(base_data, flags2,
1212 p, fname, PTR_DIFF(end_data, p),
1213 STR_TERMINATE | STR_NOALIGN, &len);
1214 if (!NT_STATUS_IS_OK(status)) {
1215 return status;
1217 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1218 if (len > 2) {
1219 len -= 2;
1220 } else {
1221 len = 0;
1223 } else {
1224 if (len > 1) {
1225 len -= 1;
1226 } else {
1227 len = 0;
1230 SCVAL(nameptr,0,len);
1231 p += len;
1232 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1233 break;
1235 case SMB_FIND_EA_LIST:
1237 struct ea_list *file_list = NULL;
1238 size_t ea_len = 0;
1240 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1241 if (!name_list) {
1242 return NT_STATUS_INVALID_PARAMETER;
1244 if (requires_resume_key) {
1245 SIVAL(p,0,reskey);
1246 p += 4;
1248 srv_put_dos_date2_ts(p, 0, create_date_ts);
1249 srv_put_dos_date2_ts(p, 4, adate_ts);
1250 srv_put_dos_date2_ts(p, 8, mdate_ts);
1251 SIVAL(p,12,(uint32_t)file_size);
1252 SIVAL(p,16,(uint32_t)allocation_size);
1253 SSVAL(p,20,mode);
1254 p += 22; /* p now points to the EA area. */
1256 status = get_ea_list_from_fsp(ctx,
1257 smb_fname->fsp,
1258 &ea_len, &file_list);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 file_list = NULL;
1262 name_list = ea_list_union(name_list, file_list, &ea_len);
1264 /* We need to determine if this entry will fit in the space available. */
1265 /* Max string size is 255 bytes. */
1266 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1267 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1268 "(wanted %u, had %d)\n",
1269 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1270 space_remaining ));
1271 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1274 /* Push the ea_data followed by the name. */
1275 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1276 nameptr = p;
1277 status = srvstr_push(base_data, flags2,
1278 p + 1, fname, PTR_DIFF(end_data, p+1),
1279 STR_TERMINATE | STR_NOALIGN, &len);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 return status;
1283 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1284 if (len > 2) {
1285 len -= 2;
1286 } else {
1287 len = 0;
1289 } else {
1290 if (len > 1) {
1291 len -= 1;
1292 } else {
1293 len = 0;
1296 SCVAL(nameptr,0,len);
1297 p += len + 1;
1298 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1299 break;
1302 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1303 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1304 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1305 p += 4;
1306 SIVAL(p,0,reskey); p += 4;
1307 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1308 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1309 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1310 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1311 SOFF_T(p,0,file_size); p += 8;
1312 SOFF_T(p,0,allocation_size); p += 8;
1313 SIVAL(p,0,mode); p += 4;
1314 q = p; p += 4; /* q is placeholder for name length. */
1315 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1316 SIVAL(p, 0, ea_size);
1317 p += 4;
1318 /* Clear the short name buffer. This is
1319 * IMPORTANT as not doing so will trigger
1320 * a Win2k client bug. JRA.
1322 if (!was_8_3 && check_mangled_names) {
1323 char mangled_name[13]; /* mangled 8.3 name. */
1324 if (!name_to_8_3(fname,mangled_name,True,
1325 conn->params)) {
1326 /* Error - mangle failed ! */
1327 memset(mangled_name,'\0',12);
1329 mangled_name[12] = 0;
1330 status = srvstr_push(base_data, flags2,
1331 p+2, mangled_name, 24,
1332 STR_UPPER|STR_UNICODE, &len);
1333 if (!NT_STATUS_IS_OK(status)) {
1334 return status;
1336 if (len < 24) {
1337 memset(p + 2 + len,'\0',24 - len);
1339 SSVAL(p, 0, len);
1340 } else {
1341 memset(p,'\0',26);
1343 p += 2 + 24;
1344 status = srvstr_push(base_data, flags2, p,
1345 fname, PTR_DIFF(end_data, p),
1346 STR_TERMINATE_ASCII, &len);
1347 if (!NT_STATUS_IS_OK(status)) {
1348 return status;
1350 SIVAL(q,0,len);
1351 p += len;
1353 len = PTR_DIFF(p, pdata);
1354 pad = (len + (align-1)) & ~(align-1);
1356 * offset to the next entry, the caller
1357 * will overwrite it for the last entry
1358 * that's why we always include the padding
1360 SIVAL(pdata,0,pad);
1362 * set padding to zero
1364 if (do_pad) {
1365 memset(p, 0, pad - len);
1366 p = pdata + pad;
1367 } else {
1368 p = pdata + len;
1370 break;
1372 case SMB_FIND_FILE_DIRECTORY_INFO:
1373 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1374 p += 4;
1375 SIVAL(p,0,reskey); p += 4;
1376 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1377 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1378 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1379 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1380 SOFF_T(p,0,file_size); p += 8;
1381 SOFF_T(p,0,allocation_size); p += 8;
1382 SIVAL(p,0,mode); p += 4;
1383 status = srvstr_push(base_data, flags2,
1384 p + 4, fname, PTR_DIFF(end_data, p+4),
1385 STR_TERMINATE_ASCII, &len);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 return status;
1389 SIVAL(p,0,len);
1390 p += 4 + len;
1392 len = PTR_DIFF(p, pdata);
1393 pad = (len + (align-1)) & ~(align-1);
1395 * offset to the next entry, the caller
1396 * will overwrite it for the last entry
1397 * that's why we always include the padding
1399 SIVAL(pdata,0,pad);
1401 * set padding to zero
1403 if (do_pad) {
1404 memset(p, 0, pad - len);
1405 p = pdata + pad;
1406 } else {
1407 p = pdata + len;
1409 break;
1411 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1412 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1413 p += 4;
1414 SIVAL(p,0,reskey); p += 4;
1415 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1416 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1417 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1418 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1419 SOFF_T(p,0,file_size); p += 8;
1420 SOFF_T(p,0,allocation_size); p += 8;
1421 SIVAL(p,0,mode); p += 4;
1422 q = p; p += 4; /* q is placeholder for name length. */
1423 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1424 SIVAL(p, 0, ea_size);
1425 p +=4;
1426 status = srvstr_push(base_data, flags2, p,
1427 fname, PTR_DIFF(end_data, p),
1428 STR_TERMINATE_ASCII, &len);
1429 if (!NT_STATUS_IS_OK(status)) {
1430 return status;
1432 SIVAL(q, 0, len);
1433 p += len;
1435 len = PTR_DIFF(p, pdata);
1436 pad = (len + (align-1)) & ~(align-1);
1438 * offset to the next entry, the caller
1439 * will overwrite it for the last entry
1440 * that's why we always include the padding
1442 SIVAL(pdata,0,pad);
1444 * set padding to zero
1446 if (do_pad) {
1447 memset(p, 0, pad - len);
1448 p = pdata + pad;
1449 } else {
1450 p = pdata + len;
1452 break;
1454 case SMB_FIND_FILE_NAMES_INFO:
1455 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1456 p += 4;
1457 SIVAL(p,0,reskey); p += 4;
1458 p += 4;
1459 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1460 acl on a dir (tridge) */
1461 status = srvstr_push(base_data, flags2, p,
1462 fname, PTR_DIFF(end_data, p),
1463 STR_TERMINATE_ASCII, &len);
1464 if (!NT_STATUS_IS_OK(status)) {
1465 return status;
1467 SIVAL(p, -4, len);
1468 p += len;
1470 len = PTR_DIFF(p, pdata);
1471 pad = (len + (align-1)) & ~(align-1);
1473 * offset to the next entry, the caller
1474 * will overwrite it for the last entry
1475 * that's why we always include the padding
1477 SIVAL(pdata,0,pad);
1479 * set padding to zero
1481 if (do_pad) {
1482 memset(p, 0, pad - len);
1483 p = pdata + pad;
1484 } else {
1485 p = pdata + len;
1487 break;
1489 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1490 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1491 p += 4;
1492 SIVAL(p,0,reskey); p += 4;
1493 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1494 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1495 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1496 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1497 SOFF_T(p,0,file_size); p += 8;
1498 SOFF_T(p,0,allocation_size); p += 8;
1499 SIVAL(p,0,mode); p += 4;
1500 q = p; p += 4; /* q is placeholder for name length. */
1501 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1502 SIVAL(p, 0, ea_size);
1503 p += 4;
1504 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1505 SBVAL(p,0,file_id); p += 8;
1506 status = srvstr_push(base_data, flags2, p,
1507 fname, PTR_DIFF(end_data, p),
1508 STR_TERMINATE_ASCII, &len);
1509 if (!NT_STATUS_IS_OK(status)) {
1510 return status;
1512 SIVAL(q, 0, len);
1513 p += len;
1515 len = PTR_DIFF(p, pdata);
1516 pad = (len + (align-1)) & ~(align-1);
1518 * offset to the next entry, the caller
1519 * will overwrite it for the last entry
1520 * that's why we always include the padding
1522 SIVAL(pdata,0,pad);
1524 * set padding to zero
1526 if (do_pad) {
1527 memset(p, 0, pad - len);
1528 p = pdata + pad;
1529 } else {
1530 p = pdata + len;
1532 break;
1534 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1535 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1536 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1537 p += 4;
1538 SIVAL(p,0,reskey); p += 4;
1539 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1540 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1541 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1542 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1543 SOFF_T(p,0,file_size); p += 8;
1544 SOFF_T(p,0,allocation_size); p += 8;
1545 SIVAL(p,0,mode); p += 4;
1546 q = p; p += 4; /* q is placeholder for name length */
1547 if (readdir_attr_data &&
1548 readdir_attr_data->type == RDATTR_AAPL) {
1550 * OS X specific SMB2 extension negotiated via
1551 * AAPL create context: return max_access in
1552 * ea_size field.
1554 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1555 } else {
1556 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1558 SIVAL(p,0,ea_size); /* Extended attributes */
1559 p += 4;
1561 if (readdir_attr_data &&
1562 readdir_attr_data->type == RDATTR_AAPL) {
1564 * OS X specific SMB2 extension negotiated via
1565 * AAPL create context: return resource fork
1566 * length and compressed FinderInfo in
1567 * shortname field.
1569 * According to documentation short_name_len
1570 * should be 0, but on the wire behaviour
1571 * shows its set to 24 by clients.
1573 SSVAL(p, 0, 24);
1575 /* Resourefork length */
1576 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1578 /* Compressed FinderInfo */
1579 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1580 } else if (!was_8_3 && check_mangled_names) {
1581 char mangled_name[13]; /* mangled 8.3 name. */
1582 if (!name_to_8_3(fname,mangled_name,True,
1583 conn->params)) {
1584 /* Error - mangle failed ! */
1585 memset(mangled_name,'\0',12);
1587 mangled_name[12] = 0;
1588 status = srvstr_push(base_data, flags2,
1589 p+2, mangled_name, 24,
1590 STR_UPPER|STR_UNICODE, &len);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 return status;
1594 SSVAL(p, 0, len);
1595 if (len < 24) {
1596 memset(p + 2 + len,'\0',24 - len);
1598 SSVAL(p, 0, len);
1599 } else {
1600 /* Clear the short name buffer. This is
1601 * IMPORTANT as not doing so will trigger
1602 * a Win2k client bug. JRA.
1604 memset(p,'\0',26);
1606 p += 26;
1608 /* Reserved ? */
1609 if (readdir_attr_data &&
1610 readdir_attr_data->type == RDATTR_AAPL) {
1612 * OS X specific SMB2 extension negotiated via
1613 * AAPL create context: return UNIX mode in
1614 * reserved field.
1616 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1617 SSVAL(p, 0, aapl_mode);
1618 } else {
1619 SSVAL(p, 0, 0);
1621 p += 2;
1623 SBVAL(p,0,file_id); p += 8;
1624 status = srvstr_push(base_data, flags2, p,
1625 fname, PTR_DIFF(end_data, p),
1626 STR_TERMINATE_ASCII, &len);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 return status;
1630 SIVAL(q,0,len);
1631 p += len;
1633 len = PTR_DIFF(p, pdata);
1634 pad = (len + (align-1)) & ~(align-1);
1636 * offset to the next entry, the caller
1637 * will overwrite it for the last entry
1638 * that's why we always include the padding
1640 SIVAL(pdata,0,pad);
1642 * set padding to zero
1644 if (do_pad) {
1645 memset(p, 0, pad - len);
1646 p = pdata + pad;
1647 } else {
1648 p = pdata + len;
1650 break;
1652 /* CIFS UNIX Extension. */
1654 case SMB_FIND_FILE_UNIX:
1655 case SMB_FIND_FILE_UNIX_INFO2:
1656 p+= 4;
1657 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1659 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1661 if (info_level == SMB_FIND_FILE_UNIX) {
1662 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1663 p = store_file_unix_basic(conn, p,
1664 NULL, &smb_fname->st);
1665 status = srvstr_push(base_data, flags2, p,
1666 fname, PTR_DIFF(end_data, p),
1667 STR_TERMINATE, &len);
1668 if (!NT_STATUS_IS_OK(status)) {
1669 return status;
1671 } else {
1672 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1673 p = store_file_unix_basic_info2(conn, p,
1674 NULL, &smb_fname->st);
1675 nameptr = p;
1676 p += 4;
1677 status = srvstr_push(base_data, flags2, p, fname,
1678 PTR_DIFF(end_data, p), 0, &len);
1679 if (!NT_STATUS_IS_OK(status)) {
1680 return status;
1682 SIVAL(nameptr, 0, len);
1685 p += len;
1687 len = PTR_DIFF(p, pdata);
1688 pad = (len + (align-1)) & ~(align-1);
1690 * offset to the next entry, the caller
1691 * will overwrite it for the last entry
1692 * that's why we always include the padding
1694 SIVAL(pdata,0,pad);
1696 * set padding to zero
1698 if (do_pad) {
1699 memset(p, 0, pad - len);
1700 p = pdata + pad;
1701 } else {
1702 p = pdata + len;
1704 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1706 break;
1708 /* SMB2 UNIX Extension. */
1710 case SMB2_FILE_POSIX_INFORMATION:
1712 struct smb3_file_posix_information info = {};
1713 uint8_t buf[sizeof(info)];
1714 struct ndr_push ndr = {
1715 .data = buf,
1716 .alloc_size = sizeof(buf),
1717 .fixed_buf_size = true,
1719 enum ndr_err_code ndr_err;
1721 p+= 4;
1722 SIVAL(p,0,reskey); p+= 4;
1724 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1726 if (!(conn->sconn->using_smb2)) {
1727 return NT_STATUS_INVALID_LEVEL;
1730 smb3_file_posix_information_init(
1731 conn, &smb_fname->st, 0, mode, &info);
1733 ndr_err = ndr_push_smb3_file_posix_information(
1734 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1735 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1736 return NT_STATUS_INSUFFICIENT_RESOURCES;
1739 memcpy(p, buf, ndr.offset);
1740 p += ndr.offset;
1742 nameptr = p;
1743 p += 4;
1744 status = srvstr_push(base_data, flags2, p, fname,
1745 PTR_DIFF(end_data, p), 0, &len);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 return status;
1749 SIVAL(nameptr, 0, len);
1751 p += len;
1753 len = PTR_DIFF(p, pdata);
1754 pad = (len + (align-1)) & ~(align-1);
1756 * offset to the next entry, the caller
1757 * will overwrite it for the last entry
1758 * that's why we always include the padding
1760 SIVAL(pdata,0,pad);
1761 break;
1764 default:
1765 return NT_STATUS_INVALID_LEVEL;
1768 if (PTR_DIFF(p,pdata) > space_remaining) {
1769 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1770 "(wanted %u, had %d)\n",
1771 (unsigned int)PTR_DIFF(p,pdata),
1772 space_remaining ));
1773 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1776 /* Setup the last entry pointer, as an offset from base_data */
1777 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1778 /* Advance the data pointer to the next slot */
1779 *ppdata = p;
1781 return NT_STATUS_OK;
1784 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1785 connection_struct *conn,
1786 struct dptr_struct *dirptr,
1787 uint16_t flags2,
1788 const char *path_mask,
1789 uint32_t dirtype,
1790 int info_level,
1791 int requires_resume_key,
1792 bool dont_descend,
1793 bool ask_sharemode,
1794 bool get_dosmode,
1795 uint8_t align,
1796 bool do_pad,
1797 char **ppdata,
1798 char *base_data,
1799 char *end_data,
1800 int space_remaining,
1801 struct smb_filename **_smb_fname,
1802 int *_last_entry_off,
1803 struct ea_list *name_list,
1804 struct file_id *file_id)
1806 const char *p;
1807 const char *mask = NULL;
1808 uint32_t mode = 0;
1809 char *fname = NULL;
1810 struct smb_filename *smb_fname = NULL;
1811 struct smbd_dirptr_lanman2_state state;
1812 bool ok;
1813 uint64_t last_entry_off = 0;
1814 NTSTATUS status;
1815 enum mangled_names_options mangled_names;
1816 bool marshall_with_83_names;
1818 mangled_names = lp_mangled_names(conn->params);
1820 ZERO_STRUCT(state);
1821 state.conn = conn;
1822 state.info_level = info_level;
1823 if (mangled_names != MANGLED_NAMES_NO) {
1824 state.check_mangled_names = true;
1826 state.case_sensitive = dptr_case_sensitive(dirptr);
1828 p = strrchr_m(path_mask,'/');
1829 if(p != NULL) {
1830 if(p[1] == '\0') {
1831 mask = "*.*";
1832 } else {
1833 mask = p+1;
1835 } else {
1836 mask = path_mask;
1839 ok = smbd_dirptr_get_entry(ctx,
1840 dirptr,
1841 mask,
1842 dirtype,
1843 dont_descend,
1844 ask_sharemode,
1845 get_dosmode,
1846 smbd_dirptr_lanman2_match_fn,
1847 &state,
1848 &fname,
1849 &smb_fname,
1850 &mode);
1851 if (!ok) {
1852 return NT_STATUS_END_OF_FILE;
1855 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1857 status = smbd_marshall_dir_entry(ctx,
1858 conn,
1859 flags2,
1860 info_level,
1861 name_list,
1862 marshall_with_83_names,
1863 requires_resume_key,
1864 mode,
1865 fname,
1866 smb_fname,
1867 space_remaining,
1868 align,
1869 do_pad,
1870 base_data,
1871 ppdata,
1872 end_data,
1873 &last_entry_off);
1874 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1875 DEBUG(1,("Conversion error: illegal character: %s\n",
1876 smb_fname_str_dbg(smb_fname)));
1879 if (file_id != NULL) {
1880 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1883 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1884 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1887 if (!NT_STATUS_IS_OK(status)) {
1888 TALLOC_FREE(smb_fname);
1889 TALLOC_FREE(fname);
1890 return status;
1893 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1895 if (_smb_fname != NULL) {
1897 * smb_fname is already talloc'ed off ctx.
1898 * We just need to make sure we don't return
1899 * any stream_name, and replace base_name
1900 * with fname in case base_name got mangled.
1901 * This allows us to preserve any smb_fname->fsp
1902 * for asynchronous handle lookups.
1904 TALLOC_FREE(smb_fname->stream_name);
1907 * smbd_dirptr_set_last_name_sent() above consumed
1908 * base_name
1910 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1912 if (smb_fname->base_name == NULL) {
1913 TALLOC_FREE(smb_fname);
1914 TALLOC_FREE(fname);
1915 return NT_STATUS_NO_MEMORY;
1917 *_smb_fname = smb_fname;
1918 } else {
1919 TALLOC_FREE(smb_fname);
1921 TALLOC_FREE(fname);
1923 *_last_entry_off = last_entry_off;
1924 return NT_STATUS_OK;
1927 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1929 const struct loadparm_substitution *lp_sub =
1930 loadparm_s3_global_substitution();
1932 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1933 return objid;
1936 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1938 SMB_ASSERT(extended_info != NULL);
1940 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1941 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1942 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1943 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1944 #ifdef SAMBA_VERSION_REVISION
1945 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1946 #endif
1947 extended_info->samba_subversion = 0;
1948 #ifdef SAMBA_VERSION_RC_RELEASE
1949 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1950 #else
1951 #ifdef SAMBA_VERSION_PRE_RELEASE
1952 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1953 #endif
1954 #endif
1955 #ifdef SAMBA_VERSION_VENDOR_PATCH
1956 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1957 #endif
1958 extended_info->samba_gitcommitdate = 0;
1959 #ifdef SAMBA_VERSION_COMMIT_TIME
1960 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1961 #endif
1963 memset(extended_info->samba_version_string, 0,
1964 sizeof(extended_info->samba_version_string));
1966 snprintf (extended_info->samba_version_string,
1967 sizeof(extended_info->samba_version_string),
1968 "%s", samba_version_string());
1971 static bool fsinfo_unix_valid_level(connection_struct *conn,
1972 struct files_struct *fsp,
1973 uint16_t info_level)
1975 if (conn->sconn->using_smb2 &&
1976 fsp->posix_flags == FSP_POSIX_FLAGS_OPEN &&
1977 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
1979 return true;
1981 #if defined(SMB1SERVER)
1982 if (lp_smb1_unix_extensions() &&
1983 info_level == SMB_QUERY_POSIX_FS_INFO) {
1984 return true;
1986 #endif
1987 return false;
1991 * fsp is only valid for SMB2.
1993 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1994 connection_struct *conn,
1995 TALLOC_CTX *mem_ctx,
1996 uint16_t info_level,
1997 uint16_t flags2,
1998 unsigned int max_data_bytes,
1999 size_t *fixed_portion,
2000 struct files_struct *fsp,
2001 struct smb_filename *fname,
2002 char **ppdata,
2003 int *ret_data_len)
2005 const struct loadparm_substitution *lp_sub =
2006 loadparm_s3_global_substitution();
2007 char *pdata, *end_data;
2008 int data_len = 0;
2009 size_t len = 0;
2010 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2011 int snum = SNUM(conn);
2012 const char *fstype = lp_fstype(SNUM(conn));
2013 const char *filename = NULL;
2014 const uint64_t bytes_per_sector = 512;
2015 uint32_t additional_flags = 0;
2016 struct smb_filename smb_fname;
2017 SMB_STRUCT_STAT st;
2018 NTSTATUS status = NT_STATUS_OK;
2019 uint64_t df_ret;
2020 uint32_t serial;
2022 if (fname == NULL || fname->base_name == NULL) {
2023 filename = ".";
2024 } else {
2025 filename = fname->base_name;
2028 if (IS_IPC(conn)) {
2029 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2030 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2031 "info level (0x%x) on IPC$.\n",
2032 (unsigned int)info_level));
2033 return NT_STATUS_ACCESS_DENIED;
2037 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2039 smb_fname = (struct smb_filename) {
2040 .base_name = discard_const_p(char, filename),
2041 .flags = fname ? fname->flags : 0,
2042 .twrp = fname ? fname->twrp : 0,
2045 if(info_level != SMB_FS_QUOTA_INFORMATION
2046 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2047 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2048 return map_nt_error_from_unix(errno);
2051 st = smb_fname.st;
2053 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2054 return NT_STATUS_INVALID_PARAMETER;
2057 *ppdata = (char *)SMB_REALLOC(
2058 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2059 if (*ppdata == NULL) {
2060 return NT_STATUS_NO_MEMORY;
2063 pdata = *ppdata;
2064 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2065 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2067 *fixed_portion = 0;
2069 switch (info_level) {
2070 case SMB_INFO_ALLOCATION:
2072 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2073 data_len = 18;
2074 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2075 &dfree, &dsize);
2076 if (df_ret == (uint64_t)-1) {
2077 return map_nt_error_from_unix(errno);
2080 block_size = lp_block_size(snum);
2081 if (bsize < block_size) {
2082 uint64_t factor = block_size/bsize;
2083 bsize = block_size;
2084 dsize /= factor;
2085 dfree /= factor;
2087 if (bsize > block_size) {
2088 uint64_t factor = bsize/block_size;
2089 bsize = block_size;
2090 dsize *= factor;
2091 dfree *= factor;
2093 sectors_per_unit = bsize/bytes_per_sector;
2095 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2096 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2097 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2100 * For large drives, return max values and not modulo.
2102 dsize = MIN(dsize, UINT32_MAX);
2103 dfree = MIN(dfree, UINT32_MAX);
2105 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2106 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2107 SIVAL(pdata,l1_cUnit,dsize);
2108 SIVAL(pdata,l1_cUnitAvail,dfree);
2109 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2110 break;
2113 case SMB_INFO_VOLUME:
2114 /* Return volume name */
2116 * Add volume serial number - hash of a combination of
2117 * the called hostname and the service name.
2119 serial = generate_volume_serial_number(lp_sub, snum);
2120 SIVAL(pdata,0,serial);
2122 * Win2k3 and previous mess this up by sending a name length
2123 * one byte short. I believe only older clients (OS/2 Win9x) use
2124 * this call so try fixing this by adding a terminating null to
2125 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2127 status = srvstr_push(
2128 pdata, flags2,
2129 pdata+l2_vol_szVolLabel, vname,
2130 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2131 STR_NOALIGN|STR_TERMINATE, &len);
2132 if (!NT_STATUS_IS_OK(status)) {
2133 return status;
2135 SCVAL(pdata,l2_vol_cch,len);
2136 data_len = l2_vol_szVolLabel + len;
2137 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2138 "name = %s serial = 0x%04"PRIx32"\n",
2139 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2140 (unsigned)len, vname, serial));
2141 break;
2143 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2144 case SMB_FS_ATTRIBUTE_INFORMATION:
2146 additional_flags = 0;
2147 #if defined(HAVE_SYS_QUOTAS)
2148 additional_flags |= FILE_VOLUME_QUOTAS;
2149 #endif
2151 if(lp_nt_acl_support(SNUM(conn))) {
2152 additional_flags |= FILE_PERSISTENT_ACLS;
2155 /* Capabilities are filled in at connection time through STATVFS call */
2156 additional_flags |= conn->fs_capabilities;
2157 additional_flags |= lp_parm_int(conn->params->service,
2158 "share", "fake_fscaps",
2161 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2162 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2163 additional_flags); /* FS ATTRIBUTES */
2165 SIVAL(pdata,4,255); /* Max filename component length */
2166 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2167 and will think we can't do long filenames */
2168 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2169 PTR_DIFF(end_data, pdata+12),
2170 STR_UNICODE, &len);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 return status;
2174 SIVAL(pdata,8,len);
2175 data_len = 12 + len;
2176 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2177 /* the client only requested a portion of the
2178 file system name */
2179 data_len = max_data_bytes;
2180 status = STATUS_BUFFER_OVERFLOW;
2182 *fixed_portion = 16;
2183 break;
2185 case SMB_QUERY_FS_LABEL_INFO:
2186 case SMB_FS_LABEL_INFORMATION:
2187 status = srvstr_push(pdata, flags2, pdata+4, vname,
2188 PTR_DIFF(end_data, pdata+4), 0, &len);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return status;
2192 data_len = 4 + len;
2193 SIVAL(pdata,0,len);
2194 break;
2196 case SMB_QUERY_FS_VOLUME_INFO:
2197 case SMB_FS_VOLUME_INFORMATION:
2198 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2199 pdata, &st.st_ex_btime);
2201 * Add volume serial number - hash of a combination of
2202 * the called hostname and the service name.
2204 serial = generate_volume_serial_number(lp_sub, snum);
2205 SIVAL(pdata,8,serial);
2207 /* Max label len is 32 characters. */
2208 status = srvstr_push(pdata, flags2, pdata+18, vname,
2209 PTR_DIFF(end_data, pdata+18),
2210 STR_UNICODE, &len);
2211 if (!NT_STATUS_IS_OK(status)) {
2212 return status;
2214 SIVAL(pdata,12,len);
2215 data_len = 18+len;
2217 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2218 "namelen = %d, vol=%s serv=%s "
2219 "serial=0x%04"PRIx32"\n",
2220 (int)strlen(vname),vname,
2221 lp_servicename(talloc_tos(), lp_sub, snum),
2222 serial));
2223 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2224 /* the client only requested a portion of the
2225 volume label */
2226 data_len = max_data_bytes;
2227 status = STATUS_BUFFER_OVERFLOW;
2229 *fixed_portion = 24;
2230 break;
2232 case SMB_QUERY_FS_SIZE_INFO:
2233 case SMB_FS_SIZE_INFORMATION:
2235 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2236 data_len = 24;
2237 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2238 &dfree, &dsize);
2239 if (df_ret == (uint64_t)-1) {
2240 return map_nt_error_from_unix(errno);
2242 block_size = lp_block_size(snum);
2243 if (bsize < block_size) {
2244 uint64_t factor = block_size/bsize;
2245 bsize = block_size;
2246 dsize /= factor;
2247 dfree /= factor;
2249 if (bsize > block_size) {
2250 uint64_t factor = bsize/block_size;
2251 bsize = block_size;
2252 dsize *= factor;
2253 dfree *= factor;
2255 sectors_per_unit = bsize/bytes_per_sector;
2256 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2257 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2258 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2259 SBIG_UINT(pdata,0,dsize);
2260 SBIG_UINT(pdata,8,dfree);
2261 SIVAL(pdata,16,sectors_per_unit);
2262 SIVAL(pdata,20,bytes_per_sector);
2263 *fixed_portion = 24;
2264 break;
2267 case SMB_FS_FULL_SIZE_INFORMATION:
2269 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2270 data_len = 32;
2271 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2272 &dfree, &dsize);
2273 if (df_ret == (uint64_t)-1) {
2274 return map_nt_error_from_unix(errno);
2276 block_size = lp_block_size(snum);
2277 if (bsize < block_size) {
2278 uint64_t factor = block_size/bsize;
2279 bsize = block_size;
2280 dsize /= factor;
2281 dfree /= factor;
2283 if (bsize > block_size) {
2284 uint64_t factor = bsize/block_size;
2285 bsize = block_size;
2286 dsize *= factor;
2287 dfree *= factor;
2289 sectors_per_unit = bsize/bytes_per_sector;
2290 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2291 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2292 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2293 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2294 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2295 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2296 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2297 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2298 *fixed_portion = 32;
2299 break;
2302 case SMB_QUERY_FS_DEVICE_INFO:
2303 case SMB_FS_DEVICE_INFORMATION:
2305 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2307 if (!CAN_WRITE(conn)) {
2308 characteristics |= FILE_READ_ONLY_DEVICE;
2310 data_len = 8;
2311 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2312 SIVAL(pdata,4,characteristics);
2313 *fixed_portion = 8;
2314 break;
2317 #ifdef HAVE_SYS_QUOTAS
2318 case SMB_FS_QUOTA_INFORMATION:
2320 * what we have to send --metze:
2322 * Unknown1: 24 NULL bytes
2323 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2324 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2325 * Quota Flags: 2 byte :
2326 * Unknown3: 6 NULL bytes
2328 * 48 bytes total
2330 * details for Quota Flags:
2332 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2333 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2334 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2335 * 0x0001 Enable Quotas: enable quota for this fs
2339 /* we need to fake up a fsp here,
2340 * because its not send in this call
2342 files_struct tmpfsp;
2343 SMB_NTQUOTA_STRUCT quotas;
2345 ZERO_STRUCT(tmpfsp);
2346 ZERO_STRUCT(quotas);
2348 tmpfsp.conn = conn;
2349 tmpfsp.fnum = FNUM_FIELD_INVALID;
2351 /* access check */
2352 if (get_current_uid(conn) != 0) {
2353 DEBUG(0,("get_user_quota: access_denied "
2354 "service [%s] user [%s]\n",
2355 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2356 conn->session_info->unix_info->unix_name));
2357 return NT_STATUS_ACCESS_DENIED;
2360 status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2361 NULL, &quotas);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2364 return status;
2367 data_len = 48;
2369 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2370 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2372 /* Unknown1 24 NULL bytes*/
2373 SBIG_UINT(pdata,0,(uint64_t)0);
2374 SBIG_UINT(pdata,8,(uint64_t)0);
2375 SBIG_UINT(pdata,16,(uint64_t)0);
2377 /* Default Soft Quota 8 bytes */
2378 SBIG_UINT(pdata,24,quotas.softlim);
2380 /* Default Hard Quota 8 bytes */
2381 SBIG_UINT(pdata,32,quotas.hardlim);
2383 /* Quota flag 2 bytes */
2384 SSVAL(pdata,40,quotas.qflags);
2386 /* Unknown3 6 NULL bytes */
2387 SSVAL(pdata,42,0);
2388 SIVAL(pdata,44,0);
2390 break;
2392 #endif /* HAVE_SYS_QUOTAS */
2393 case SMB_FS_OBJECTID_INFORMATION:
2395 unsigned char objid[16];
2396 struct smb_extended_info extended_info;
2397 memcpy(pdata,create_volume_objectid(conn, objid),16);
2398 samba_extended_info_version (&extended_info);
2399 SIVAL(pdata,16,extended_info.samba_magic);
2400 SIVAL(pdata,20,extended_info.samba_version);
2401 SIVAL(pdata,24,extended_info.samba_subversion);
2402 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2403 memcpy(pdata+36,extended_info.samba_version_string,28);
2404 data_len = 64;
2405 break;
2408 case SMB_FS_SECTOR_SIZE_INFORMATION:
2410 data_len = 28;
2412 * These values match a physical Windows Server 2012
2413 * share backed by NTFS atop spinning rust.
2415 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2416 /* logical_bytes_per_sector */
2417 SIVAL(pdata, 0, bytes_per_sector);
2418 /* phys_bytes_per_sector_atomic */
2419 SIVAL(pdata, 4, bytes_per_sector);
2420 /* phys_bytes_per_sector_perf */
2421 SIVAL(pdata, 8, bytes_per_sector);
2422 /* fs_effective_phys_bytes_per_sector_atomic */
2423 SIVAL(pdata, 12, bytes_per_sector);
2424 /* flags */
2425 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2426 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2427 /* byte_off_sector_align */
2428 SIVAL(pdata, 20, 0);
2429 /* byte_off_partition_align */
2430 SIVAL(pdata, 24, 0);
2431 *fixed_portion = 28;
2432 break;
2436 #if defined(WITH_SMB1SERVER)
2438 * Query the version and capabilities of the CIFS UNIX extensions
2439 * in use.
2442 case SMB_QUERY_CIFS_UNIX_INFO:
2444 bool large_write = lp_min_receive_file_size() &&
2445 !smb1_srv_is_signing_active(xconn);
2446 bool large_read = !smb1_srv_is_signing_active(xconn);
2447 int encrypt_caps = 0;
2449 if (!lp_smb1_unix_extensions()) {
2450 return NT_STATUS_INVALID_LEVEL;
2453 switch (conn->encrypt_level) {
2454 case SMB_SIGNING_OFF:
2455 encrypt_caps = 0;
2456 break;
2457 case SMB_SIGNING_DESIRED:
2458 case SMB_SIGNING_IF_REQUIRED:
2459 case SMB_SIGNING_DEFAULT:
2460 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2461 break;
2462 case SMB_SIGNING_REQUIRED:
2463 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2464 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2465 large_write = false;
2466 large_read = false;
2467 break;
2470 data_len = 12;
2471 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2472 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2474 /* We have POSIX ACLs, pathname, encryption,
2475 * large read/write, and locking capability. */
2477 SBIG_UINT(pdata,4,((uint64_t)(
2478 CIFS_UNIX_POSIX_ACLS_CAP|
2479 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2480 CIFS_UNIX_FCNTL_LOCKS_CAP|
2481 CIFS_UNIX_EXTATTR_CAP|
2482 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2483 encrypt_caps|
2484 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2485 (large_write ?
2486 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2487 break;
2489 #endif
2491 case SMB_QUERY_POSIX_FS_INFO:
2492 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2494 int rc;
2495 struct vfs_statvfs_struct svfs;
2497 if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2498 return NT_STATUS_INVALID_LEVEL;
2501 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2503 if (!rc) {
2504 data_len = 56;
2505 SIVAL(pdata,0,svfs.OptimalTransferSize);
2506 SIVAL(pdata,4,svfs.BlockSize);
2507 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2508 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2509 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2510 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2511 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2512 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2513 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2514 #ifdef EOPNOTSUPP
2515 } else if (rc == EOPNOTSUPP) {
2516 return NT_STATUS_INVALID_LEVEL;
2517 #endif /* EOPNOTSUPP */
2518 } else {
2519 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2520 return NT_STATUS_DOS(ERRSRV, ERRerror);
2522 break;
2525 case SMB_QUERY_POSIX_WHOAMI:
2527 uint32_t flags = 0;
2528 uint32_t sid_bytes;
2529 uint32_t i;
2531 if (!lp_smb1_unix_extensions()) {
2532 return NT_STATUS_INVALID_LEVEL;
2535 if (max_data_bytes < 40) {
2536 return NT_STATUS_BUFFER_TOO_SMALL;
2539 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2540 flags |= SMB_WHOAMI_GUEST;
2543 /* NOTE: 8 bytes for UID/GID, irrespective of native
2544 * platform size. This matches
2545 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2547 data_len = 4 /* flags */
2548 + 4 /* flag mask */
2549 + 8 /* uid */
2550 + 8 /* gid */
2551 + 4 /* ngroups */
2552 + 4 /* num_sids */
2553 + 4 /* SID bytes */
2554 + 4 /* pad/reserved */
2555 + (conn->session_info->unix_token->ngroups * 8)
2556 /* groups list */
2557 + (conn->session_info->security_token->num_sids *
2558 SID_MAX_SIZE)
2559 /* SID list */;
2561 SIVAL(pdata, 0, flags);
2562 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2563 SBIG_UINT(pdata, 8,
2564 (uint64_t)conn->session_info->unix_token->uid);
2565 SBIG_UINT(pdata, 16,
2566 (uint64_t)conn->session_info->unix_token->gid);
2569 if (data_len >= max_data_bytes) {
2570 /* Potential overflow, skip the GIDs and SIDs. */
2572 SIVAL(pdata, 24, 0); /* num_groups */
2573 SIVAL(pdata, 28, 0); /* num_sids */
2574 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2575 SIVAL(pdata, 36, 0); /* reserved */
2577 data_len = 40;
2578 break;
2581 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2582 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2584 /* We walk the SID list twice, but this call is fairly
2585 * infrequent, and I don't expect that it's performance
2586 * sensitive -- jpeach
2588 for (i = 0, sid_bytes = 0;
2589 i < conn->session_info->security_token->num_sids; ++i) {
2590 sid_bytes += ndr_size_dom_sid(
2591 &conn->session_info->security_token->sids[i],
2595 /* SID list byte count */
2596 SIVAL(pdata, 32, sid_bytes);
2598 /* 4 bytes pad/reserved - must be zero */
2599 SIVAL(pdata, 36, 0);
2600 data_len = 40;
2602 /* GID list */
2603 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2604 SBIG_UINT(pdata, data_len,
2605 (uint64_t)conn->session_info->unix_token->groups[i]);
2606 data_len += 8;
2609 /* SID list */
2610 for (i = 0;
2611 i < conn->session_info->security_token->num_sids; ++i) {
2612 int sid_len = ndr_size_dom_sid(
2613 &conn->session_info->security_token->sids[i],
2616 sid_linearize((uint8_t *)(pdata + data_len),
2617 sid_len,
2618 &conn->session_info->security_token->sids[i]);
2619 data_len += sid_len;
2622 break;
2625 case SMB_MAC_QUERY_FS_INFO:
2627 * Thursby MAC extension... ONLY on NTFS filesystems
2628 * once we do streams then we don't need this
2630 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2631 data_len = 88;
2632 SIVAL(pdata,84,0x100); /* Don't support mac... */
2633 break;
2636 FALL_THROUGH;
2637 default:
2638 return NT_STATUS_INVALID_LEVEL;
2641 *ret_data_len = data_len;
2642 return status;
2645 NTSTATUS smb_set_fsquota(connection_struct *conn,
2646 struct smb_request *req,
2647 files_struct *fsp,
2648 const DATA_BLOB *qdata)
2650 const struct loadparm_substitution *lp_sub =
2651 loadparm_s3_global_substitution();
2652 NTSTATUS status;
2653 SMB_NTQUOTA_STRUCT quotas;
2655 ZERO_STRUCT(quotas);
2657 /* access check */
2658 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2659 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2660 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2661 conn->session_info->unix_info->unix_name);
2662 return NT_STATUS_ACCESS_DENIED;
2665 if (!check_fsp_ntquota_handle(conn, req,
2666 fsp)) {
2667 DBG_WARNING("no valid QUOTA HANDLE\n");
2668 return NT_STATUS_INVALID_HANDLE;
2671 /* note: normally there're 48 bytes,
2672 * but we didn't use the last 6 bytes for now
2673 * --metze
2675 if (qdata->length < 42) {
2676 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2677 qdata->length);
2678 return NT_STATUS_INVALID_PARAMETER;
2681 /* unknown_1 24 NULL bytes in pdata*/
2683 /* the soft quotas 8 bytes (uint64_t)*/
2684 quotas.softlim = BVAL(qdata->data,24);
2686 /* the hard quotas 8 bytes (uint64_t)*/
2687 quotas.hardlim = BVAL(qdata->data,32);
2689 /* quota_flags 2 bytes **/
2690 quotas.qflags = SVAL(qdata->data,40);
2692 /* unknown_2 6 NULL bytes follow*/
2694 /* now set the quotas */
2695 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2696 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2697 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2698 status = map_nt_error_from_unix(errno);
2699 } else {
2700 status = NT_STATUS_OK;
2702 return status;
2705 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2706 struct smb_request *req,
2707 TALLOC_CTX *mem_ctx,
2708 uint16_t info_level,
2709 files_struct *fsp,
2710 const DATA_BLOB *pdata)
2712 switch (info_level) {
2713 case SMB_FS_QUOTA_INFORMATION:
2715 return smb_set_fsquota(conn,
2716 req,
2717 fsp,
2718 pdata);
2721 default:
2722 break;
2724 return NT_STATUS_INVALID_LEVEL;
2727 /****************************************************************************
2728 Store the FILE_UNIX_BASIC info.
2729 ****************************************************************************/
2731 char *store_file_unix_basic(connection_struct *conn,
2732 char *pdata,
2733 files_struct *fsp,
2734 const SMB_STRUCT_STAT *psbuf)
2736 dev_t devno;
2738 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2739 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2741 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2742 pdata += 8;
2744 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2745 pdata += 8;
2747 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2748 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2749 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2750 pdata += 24;
2752 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2753 SIVAL(pdata,4,0);
2754 pdata += 8;
2756 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2757 SIVAL(pdata,4,0);
2758 pdata += 8;
2760 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2761 pdata += 4;
2763 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2764 devno = psbuf->st_ex_rdev;
2765 } else {
2766 devno = psbuf->st_ex_dev;
2769 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2770 SIVAL(pdata,4,0);
2771 pdata += 8;
2773 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2774 SIVAL(pdata,4,0);
2775 pdata += 8;
2777 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2778 pdata += 8;
2780 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2781 SIVAL(pdata,4,0);
2782 pdata += 8;
2784 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2785 SIVAL(pdata,4,0);
2786 pdata += 8;
2788 return pdata;
2791 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2792 * the chflags(2) (or equivalent) flags.
2794 * XXX: this really should be behind the VFS interface. To do this, we would
2795 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2796 * Each VFS module could then implement its own mapping as appropriate for the
2797 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2799 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2800 info2_flags_map[] =
2802 #ifdef UF_NODUMP
2803 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2804 #endif
2806 #ifdef UF_IMMUTABLE
2807 { UF_IMMUTABLE, EXT_IMMUTABLE },
2808 #endif
2810 #ifdef UF_APPEND
2811 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2812 #endif
2814 #ifdef UF_HIDDEN
2815 { UF_HIDDEN, EXT_HIDDEN },
2816 #endif
2818 /* Do not remove. We need to guarantee that this array has at least one
2819 * entry to build on HP-UX.
2821 { 0, 0 }
2825 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2826 uint32_t *smb_fflags, uint32_t *smb_fmask)
2828 size_t i;
2830 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2831 *smb_fmask |= info2_flags_map[i].smb_fflag;
2832 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2833 *smb_fflags |= info2_flags_map[i].smb_fflag;
2838 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2839 const uint32_t smb_fflags,
2840 const uint32_t smb_fmask,
2841 int *stat_fflags)
2843 uint32_t max_fmask = 0;
2844 size_t i;
2846 *stat_fflags = psbuf->st_ex_flags;
2848 /* For each flags requested in smb_fmask, check the state of the
2849 * corresponding flag in smb_fflags and set or clear the matching
2850 * stat flag.
2853 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2854 max_fmask |= info2_flags_map[i].smb_fflag;
2855 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2856 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2857 *stat_fflags |= info2_flags_map[i].stat_fflag;
2858 } else {
2859 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2864 /* If smb_fmask is asking to set any bits that are not supported by
2865 * our flag mappings, we should fail.
2867 if ((smb_fmask & max_fmask) != smb_fmask) {
2868 return False;
2871 return True;
2875 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2876 * of file flags and birth (create) time.
2878 char *store_file_unix_basic_info2(connection_struct *conn,
2879 char *pdata,
2880 files_struct *fsp,
2881 const SMB_STRUCT_STAT *psbuf)
2883 uint32_t file_flags = 0;
2884 uint32_t flags_mask = 0;
2886 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2888 /* Create (birth) time 64 bit */
2889 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2890 pdata += 8;
2892 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2893 SIVAL(pdata, 0, file_flags); /* flags */
2894 SIVAL(pdata, 4, flags_mask); /* mask */
2895 pdata += 8;
2897 return pdata;
2900 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2901 const struct stream_struct *streams,
2902 char *data,
2903 unsigned int max_data_bytes,
2904 unsigned int *data_size)
2906 unsigned int i;
2907 unsigned int ofs = 0;
2909 if (max_data_bytes < 32) {
2910 return NT_STATUS_INFO_LENGTH_MISMATCH;
2913 for (i = 0; i < num_streams; i++) {
2914 unsigned int next_offset;
2915 size_t namelen;
2916 smb_ucs2_t *namebuf;
2918 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2919 streams[i].name, &namelen) ||
2920 namelen <= 2)
2922 return NT_STATUS_INVALID_PARAMETER;
2926 * name_buf is now null-terminated, we need to marshall as not
2927 * terminated
2930 namelen -= 2;
2933 * We cannot overflow ...
2935 if ((ofs + 24 + namelen) > max_data_bytes) {
2936 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2937 i));
2938 TALLOC_FREE(namebuf);
2939 return STATUS_BUFFER_OVERFLOW;
2942 SIVAL(data, ofs+4, namelen);
2943 SOFF_T(data, ofs+8, streams[i].size);
2944 SOFF_T(data, ofs+16, streams[i].alloc_size);
2945 memcpy(data+ofs+24, namebuf, namelen);
2946 TALLOC_FREE(namebuf);
2948 next_offset = ofs + 24 + namelen;
2950 if (i == num_streams-1) {
2951 SIVAL(data, ofs, 0);
2953 else {
2954 unsigned int align = ndr_align_size(next_offset, 8);
2956 if ((next_offset + align) > max_data_bytes) {
2957 DEBUG(10, ("refusing to overflow align "
2958 "reply at stream %u\n",
2959 i));
2960 TALLOC_FREE(namebuf);
2961 return STATUS_BUFFER_OVERFLOW;
2964 memset(data+next_offset, 0, align);
2965 next_offset += align;
2967 SIVAL(data, ofs, next_offset - ofs);
2968 ofs = next_offset;
2971 ofs = next_offset;
2974 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2976 *data_size = ofs;
2978 return NT_STATUS_OK;
2981 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2982 TALLOC_CTX *mem_ctx,
2983 struct smb_request *req,
2984 uint16_t info_level,
2985 files_struct *fsp,
2986 struct smb_filename *smb_fname,
2987 bool delete_pending,
2988 struct timespec write_time_ts,
2989 struct ea_list *ea_list,
2990 uint16_t flags2,
2991 unsigned int max_data_bytes,
2992 size_t *fixed_portion,
2993 char **ppdata,
2994 unsigned int *pdata_size)
2996 char *pdata = *ppdata;
2997 char *dstart, *dend;
2998 unsigned int data_size;
2999 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3000 SMB_STRUCT_STAT *psbuf = NULL;
3001 SMB_STRUCT_STAT *base_sp = NULL;
3002 char *p;
3003 char *base_name;
3004 char *dos_fname;
3005 int mode;
3006 int nlink;
3007 NTSTATUS status;
3008 uint64_t file_size = 0;
3009 uint64_t pos = 0;
3010 uint64_t allocation_size = 0;
3011 uint64_t file_id = 0;
3012 uint32_t access_mask = 0;
3013 size_t len = 0;
3015 if (INFO_LEVEL_IS_UNIX(info_level)) {
3016 bool ok = false;
3018 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3019 DBG_DEBUG("SMB1 unix extensions activated\n");
3020 ok = true;
3023 if (conn->sconn->using_smb2 &&
3024 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN))
3026 DBG_DEBUG("SMB2 posix open\n");
3027 ok = true;
3030 if (!ok) {
3031 return NT_STATUS_INVALID_LEVEL;
3035 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3036 smb_fname_str_dbg(smb_fname),
3037 fsp_fnum_dbg(fsp),
3038 info_level, max_data_bytes);
3041 * In case of querying a symlink in POSIX context,
3042 * fsp will be NULL. fdos_mode() deals with it.
3044 if (fsp != NULL) {
3045 smb_fname = fsp->fsp_name;
3047 mode = fdos_mode(fsp);
3048 psbuf = &smb_fname->st;
3050 if (fsp != NULL) {
3051 base_sp = fsp->base_fsp ?
3052 &fsp->base_fsp->fsp_name->st :
3053 &fsp->fsp_name->st;
3054 } else {
3055 base_sp = &smb_fname->st;
3058 nlink = psbuf->st_ex_nlink;
3060 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3061 nlink = 1;
3064 if ((nlink > 0) && delete_pending) {
3065 nlink -= 1;
3068 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3069 return NT_STATUS_INVALID_PARAMETER;
3072 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3073 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3074 if (*ppdata == NULL) {
3075 return NT_STATUS_NO_MEMORY;
3077 pdata = *ppdata;
3078 dstart = pdata;
3079 dend = dstart + data_size - 1;
3081 if (!is_omit_timespec(&write_time_ts) &&
3082 !INFO_LEVEL_IS_UNIX(info_level))
3084 update_stat_ex_mtime(psbuf, write_time_ts);
3087 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3088 mtime_ts = psbuf->st_ex_mtime;
3089 atime_ts = psbuf->st_ex_atime;
3090 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3092 if (lp_dos_filetime_resolution(SNUM(conn))) {
3093 dos_filetime_timespec(&create_time_ts);
3094 dos_filetime_timespec(&mtime_ts);
3095 dos_filetime_timespec(&atime_ts);
3096 dos_filetime_timespec(&ctime_ts);
3099 p = strrchr_m(smb_fname->base_name,'/');
3100 if (!p)
3101 base_name = smb_fname->base_name;
3102 else
3103 base_name = p+1;
3105 /* NT expects the name to be in an exact form of the *full*
3106 filename. See the trans2 torture test */
3107 if (ISDOT(base_name)) {
3108 dos_fname = talloc_strdup(mem_ctx, "\\");
3109 if (!dos_fname) {
3110 return NT_STATUS_NO_MEMORY;
3112 } else {
3113 dos_fname = talloc_asprintf(mem_ctx,
3114 "\\%s",
3115 smb_fname->base_name);
3116 if (!dos_fname) {
3117 return NT_STATUS_NO_MEMORY;
3119 if (is_named_stream(smb_fname)) {
3120 dos_fname = talloc_asprintf(dos_fname, "%s",
3121 smb_fname->stream_name);
3122 if (!dos_fname) {
3123 return NT_STATUS_NO_MEMORY;
3127 string_replace(dos_fname, '/', '\\');
3130 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3132 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3133 /* Do we have this path open ? */
3134 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3135 files_struct *fsp1 = file_find_di_first(
3136 conn->sconn, fileid, true);
3137 if (fsp1 && fsp1->initial_allocation_size) {
3138 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3142 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3143 file_size = get_file_size_stat(psbuf);
3146 if (fsp) {
3147 pos = fh_get_position_information(fsp->fh);
3150 if (fsp) {
3151 access_mask = fsp->access_mask;
3152 } else {
3153 /* GENERIC_EXECUTE mapping from Windows */
3154 access_mask = 0x12019F;
3157 /* This should be an index number - looks like
3158 dev/ino to me :-)
3160 I think this causes us to fail the IFSKIT
3161 BasicFileInformationTest. -tpot */
3162 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3164 *fixed_portion = 0;
3166 switch (info_level) {
3167 case SMB_INFO_STANDARD:
3168 DBG_DEBUG("SMB_INFO_STANDARD\n");
3169 data_size = 22;
3170 srv_put_dos_date2_ts(pdata,
3171 l1_fdateCreation,
3172 create_time_ts);
3173 srv_put_dos_date2_ts(pdata,
3174 l1_fdateLastAccess,
3175 atime_ts);
3176 srv_put_dos_date2_ts(pdata,
3177 l1_fdateLastWrite,
3178 mtime_ts); /* write time */
3179 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3180 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3181 SSVAL(pdata,l1_attrFile,mode);
3182 break;
3184 case SMB_INFO_QUERY_EA_SIZE:
3186 unsigned int ea_size =
3187 estimate_ea_size(smb_fname->fsp);
3188 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3189 data_size = 26;
3190 srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3191 srv_put_dos_date2_ts(pdata, 4, atime_ts);
3192 srv_put_dos_date2_ts(pdata,
3194 mtime_ts); /* write time */
3195 SIVAL(pdata,12,(uint32_t)file_size);
3196 SIVAL(pdata,16,(uint32_t)allocation_size);
3197 SSVAL(pdata,20,mode);
3198 SIVAL(pdata,22,ea_size);
3199 break;
3202 case SMB_INFO_IS_NAME_VALID:
3203 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3204 if (fsp) {
3205 /* os/2 needs this ? really ?*/
3206 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3208 /* This is only reached for qpathinfo */
3209 data_size = 0;
3210 break;
3212 case SMB_INFO_QUERY_EAS_FROM_LIST:
3214 size_t total_ea_len = 0;
3215 struct ea_list *ea_file_list = NULL;
3216 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3218 status =
3219 get_ea_list_from_fsp(mem_ctx,
3220 smb_fname->fsp,
3221 &total_ea_len, &ea_file_list);
3222 if (!NT_STATUS_IS_OK(status)) {
3223 return status;
3226 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3228 if (!ea_list || (total_ea_len > data_size)) {
3229 data_size = 4;
3230 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3231 break;
3234 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3235 break;
3238 case SMB_INFO_QUERY_ALL_EAS:
3240 /* We have data_size bytes to put EA's into. */
3241 size_t total_ea_len = 0;
3242 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3244 status = get_ea_list_from_fsp(mem_ctx,
3245 smb_fname->fsp,
3246 &total_ea_len, &ea_list);
3247 if (!NT_STATUS_IS_OK(status)) {
3248 return status;
3251 if (!ea_list || (total_ea_len > data_size)) {
3252 data_size = 4;
3253 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3254 break;
3257 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3258 break;
3261 case SMB2_FILE_FULL_EA_INFORMATION:
3263 /* We have data_size bytes to put EA's into. */
3264 size_t total_ea_len = 0;
3265 struct ea_list *ea_file_list = NULL;
3267 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3269 /*TODO: add filtering and index handling */
3271 status =
3272 get_ea_list_from_fsp(mem_ctx,
3273 smb_fname->fsp,
3274 &total_ea_len, &ea_file_list);
3275 if (!NT_STATUS_IS_OK(status)) {
3276 return status;
3278 if (!ea_file_list) {
3279 return NT_STATUS_NO_EAS_ON_FILE;
3282 status = fill_ea_chained_buffer(mem_ctx,
3283 pdata,
3284 data_size,
3285 &data_size,
3286 conn, ea_file_list);
3287 if (!NT_STATUS_IS_OK(status)) {
3288 return status;
3290 break;
3293 case SMB_FILE_BASIC_INFORMATION:
3294 case SMB_QUERY_FILE_BASIC_INFO:
3296 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3297 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3298 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3299 } else {
3300 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3301 data_size = 40;
3302 SIVAL(pdata,36,0);
3304 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3305 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3306 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3307 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3308 SIVAL(pdata,32,mode);
3310 DBG_INFO("SMB_QFBI - create: %s access: %s "
3311 "write: %s change: %s mode: %x\n",
3312 ctime(&create_time_ts.tv_sec),
3313 ctime(&atime_ts.tv_sec),
3314 ctime(&mtime_ts.tv_sec),
3315 ctime(&ctime_ts.tv_sec),
3316 mode);
3317 *fixed_portion = data_size;
3318 break;
3320 case SMB_FILE_STANDARD_INFORMATION:
3321 case SMB_QUERY_FILE_STANDARD_INFO:
3323 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3324 data_size = 24;
3325 SOFF_T(pdata,0,allocation_size);
3326 SOFF_T(pdata,8,file_size);
3327 SIVAL(pdata,16,nlink);
3328 SCVAL(pdata,20,delete_pending?1:0);
3329 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3330 SSVAL(pdata,22,0); /* Padding. */
3331 *fixed_portion = 24;
3332 break;
3334 case SMB_FILE_EA_INFORMATION:
3335 case SMB_QUERY_FILE_EA_INFO:
3337 unsigned int ea_size =
3338 estimate_ea_size(smb_fname->fsp);
3339 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3340 data_size = 4;
3341 *fixed_portion = 4;
3342 SIVAL(pdata,0,ea_size);
3343 break;
3346 /* Get the 8.3 name - used if NT SMB was negotiated. */
3347 case SMB_QUERY_FILE_ALT_NAME_INFO:
3348 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3350 char mangled_name[13];
3351 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3352 if (!name_to_8_3(base_name,mangled_name,
3353 True,conn->params)) {
3354 return NT_STATUS_NO_MEMORY;
3356 status = srvstr_push(dstart, flags2,
3357 pdata+4, mangled_name,
3358 PTR_DIFF(dend, pdata+4),
3359 STR_UNICODE, &len);
3360 if (!NT_STATUS_IS_OK(status)) {
3361 return status;
3363 data_size = 4 + len;
3364 SIVAL(pdata,0,len);
3365 *fixed_portion = 8;
3366 break;
3369 case SMB_QUERY_FILE_NAME_INFO:
3372 this must be *exactly* right for ACLs on mapped drives to work
3374 status = srvstr_push(dstart, flags2,
3375 pdata+4, dos_fname,
3376 PTR_DIFF(dend, pdata+4),
3377 STR_UNICODE, &len);
3378 if (!NT_STATUS_IS_OK(status)) {
3379 return status;
3381 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3382 data_size = 4 + len;
3383 SIVAL(pdata,0,len);
3384 break;
3387 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3389 char *nfname = NULL;
3391 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3392 return NT_STATUS_INVALID_LEVEL;
3395 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3396 if (nfname == NULL) {
3397 return NT_STATUS_NO_MEMORY;
3400 if (ISDOT(nfname)) {
3401 nfname[0] = '\0';
3403 string_replace(nfname, '/', '\\');
3405 if (fsp_is_alternate_stream(fsp)) {
3406 const char *s = smb_fname->stream_name;
3407 const char *e = NULL;
3408 size_t n;
3410 SMB_ASSERT(s[0] != '\0');
3413 * smb_fname->stream_name is in form
3414 * of ':StrEam:$DATA', but we should only
3415 * append ':StrEam' here.
3418 e = strchr(&s[1], ':');
3419 if (e == NULL) {
3420 n = strlen(s);
3421 } else {
3422 n = PTR_DIFF(e, s);
3424 nfname = talloc_strndup_append(nfname, s, n);
3425 if (nfname == NULL) {
3426 return NT_STATUS_NO_MEMORY;
3430 status = srvstr_push(dstart, flags2,
3431 pdata+4, nfname,
3432 PTR_DIFF(dend, pdata+4),
3433 STR_UNICODE, &len);
3434 if (!NT_STATUS_IS_OK(status)) {
3435 return status;
3437 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3438 data_size = 4 + len;
3439 SIVAL(pdata,0,len);
3440 *fixed_portion = 8;
3441 break;
3444 case SMB_FILE_ALLOCATION_INFORMATION:
3445 case SMB_QUERY_FILE_ALLOCATION_INFO:
3446 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3447 data_size = 8;
3448 SOFF_T(pdata,0,allocation_size);
3449 break;
3451 case SMB_FILE_END_OF_FILE_INFORMATION:
3452 case SMB_QUERY_FILE_END_OF_FILEINFO:
3453 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3454 data_size = 8;
3455 SOFF_T(pdata,0,file_size);
3456 break;
3458 case SMB_QUERY_FILE_ALL_INFO:
3459 case SMB_FILE_ALL_INFORMATION:
3461 unsigned int ea_size =
3462 estimate_ea_size(smb_fname->fsp);
3463 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3464 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3465 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3466 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3467 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3468 SIVAL(pdata,32,mode);
3469 SIVAL(pdata,36,0); /* padding. */
3470 pdata += 40;
3471 SOFF_T(pdata,0,allocation_size);
3472 SOFF_T(pdata,8,file_size);
3473 SIVAL(pdata,16,nlink);
3474 SCVAL(pdata,20,delete_pending);
3475 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3476 SSVAL(pdata,22,0);
3477 pdata += 24;
3478 SIVAL(pdata,0,ea_size);
3479 pdata += 4; /* EA info */
3480 status = srvstr_push(dstart, flags2,
3481 pdata+4, dos_fname,
3482 PTR_DIFF(dend, pdata+4),
3483 STR_UNICODE, &len);
3484 if (!NT_STATUS_IS_OK(status)) {
3485 return status;
3487 SIVAL(pdata,0,len);
3488 pdata += 4 + len;
3489 data_size = PTR_DIFF(pdata,(*ppdata));
3490 *fixed_portion = 10;
3491 break;
3494 case SMB2_FILE_ALL_INFORMATION:
3496 unsigned int ea_size =
3497 estimate_ea_size(smb_fname->fsp);
3498 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3499 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3500 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3501 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3502 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3503 SIVAL(pdata, 0x20, mode);
3504 SIVAL(pdata, 0x24, 0); /* padding. */
3505 SBVAL(pdata, 0x28, allocation_size);
3506 SBVAL(pdata, 0x30, file_size);
3507 SIVAL(pdata, 0x38, nlink);
3508 SCVAL(pdata, 0x3C, delete_pending);
3509 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3510 SSVAL(pdata, 0x3E, 0); /* padding */
3511 SBVAL(pdata, 0x40, file_id);
3512 SIVAL(pdata, 0x48, ea_size);
3513 SIVAL(pdata, 0x4C, access_mask);
3514 SBVAL(pdata, 0x50, pos);
3515 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3516 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3518 pdata += 0x60;
3520 status = srvstr_push(dstart, flags2,
3521 pdata+4, dos_fname,
3522 PTR_DIFF(dend, pdata+4),
3523 STR_UNICODE, &len);
3524 if (!NT_STATUS_IS_OK(status)) {
3525 return status;
3527 SIVAL(pdata,0,len);
3528 pdata += 4 + len;
3529 data_size = PTR_DIFF(pdata,(*ppdata));
3530 *fixed_portion = 104;
3531 break;
3533 case SMB_FILE_INTERNAL_INFORMATION:
3535 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3536 SBVAL(pdata, 0, file_id);
3537 data_size = 8;
3538 *fixed_portion = 8;
3539 break;
3541 case SMB_FILE_ACCESS_INFORMATION:
3542 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3543 SIVAL(pdata, 0, access_mask);
3544 data_size = 4;
3545 *fixed_portion = 4;
3546 break;
3548 case SMB_FILE_NAME_INFORMATION:
3549 /* Pathname with leading '\'. */
3551 size_t byte_len;
3552 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3553 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3554 SIVAL(pdata,0,byte_len);
3555 data_size = 4 + byte_len;
3556 break;
3559 case SMB_FILE_DISPOSITION_INFORMATION:
3560 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3561 data_size = 1;
3562 SCVAL(pdata,0,delete_pending);
3563 *fixed_portion = 1;
3564 break;
3566 case SMB_FILE_POSITION_INFORMATION:
3567 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3568 data_size = 8;
3569 SOFF_T(pdata,0,pos);
3570 *fixed_portion = 8;
3571 break;
3573 case SMB_FILE_MODE_INFORMATION:
3574 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3575 SIVAL(pdata,0,mode);
3576 data_size = 4;
3577 *fixed_portion = 4;
3578 break;
3580 case SMB_FILE_ALIGNMENT_INFORMATION:
3581 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3582 SIVAL(pdata,0,0); /* No alignment needed. */
3583 data_size = 4;
3584 *fixed_portion = 4;
3585 break;
3588 * NT4 server just returns "invalid query" to this - if we try
3589 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3590 * want this. JRA.
3592 /* The first statement above is false - verified using Thursby
3593 * client against NT4 -- gcolley.
3595 case SMB_QUERY_FILE_STREAM_INFO:
3596 case SMB_FILE_STREAM_INFORMATION: {
3597 unsigned int num_streams = 0;
3598 struct stream_struct *streams = NULL;
3600 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3602 if (is_ntfs_stream_smb_fname(smb_fname)) {
3603 return NT_STATUS_INVALID_PARAMETER;
3606 status = vfs_fstreaminfo(fsp,
3607 mem_ctx,
3608 &num_streams,
3609 &streams);
3611 if (!NT_STATUS_IS_OK(status)) {
3612 DBG_DEBUG("could not get stream info: %s\n",
3613 nt_errstr(status));
3614 return status;
3617 status = marshall_stream_info(num_streams, streams,
3618 pdata, max_data_bytes,
3619 &data_size);
3621 if (!NT_STATUS_IS_OK(status)) {
3622 DBG_DEBUG("marshall_stream_info failed: %s\n",
3623 nt_errstr(status));
3624 TALLOC_FREE(streams);
3625 return status;
3628 TALLOC_FREE(streams);
3630 *fixed_portion = 32;
3632 break;
3634 case SMB_QUERY_COMPRESSION_INFO:
3635 case SMB_FILE_COMPRESSION_INFORMATION:
3636 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3637 SOFF_T(pdata,0,file_size);
3638 SIVAL(pdata,8,0); /* ??? */
3639 SIVAL(pdata,12,0); /* ??? */
3640 data_size = 16;
3641 *fixed_portion = 16;
3642 break;
3644 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3645 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3646 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3647 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3648 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3649 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3650 SOFF_T(pdata,32,allocation_size);
3651 SOFF_T(pdata,40,file_size);
3652 SIVAL(pdata,48,mode);
3653 SIVAL(pdata,52,0); /* ??? */
3654 data_size = 56;
3655 *fixed_portion = 56;
3656 break;
3658 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3659 DBG_DEBUG(" SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3660 SIVAL(pdata,0,mode);
3661 SIVAL(pdata,4,0);
3662 data_size = 8;
3663 *fixed_portion = 8;
3664 break;
3667 * SMB2 UNIX Extensions.
3669 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3671 struct smb3_file_posix_information info = {};
3672 uint8_t buf[sizeof(info)];
3673 struct ndr_push ndr = {
3674 .data = buf,
3675 .alloc_size = sizeof(buf),
3676 .fixed_buf_size = true,
3678 enum ndr_err_code ndr_err;
3680 if (!(conn->sconn->using_smb2)) {
3681 return NT_STATUS_INVALID_LEVEL;
3683 if (fsp == NULL) {
3684 return NT_STATUS_INVALID_HANDLE;
3686 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3687 return NT_STATUS_INVALID_LEVEL;
3690 smb3_file_posix_information_init(
3691 conn, &smb_fname->st, 0, mode, &info);
3693 ndr_err = ndr_push_smb3_file_posix_information(
3694 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3695 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3696 return NT_STATUS_INSUFFICIENT_RESOURCES;
3699 memcpy(pdata, buf, ndr.offset);
3700 data_size = ndr.offset;
3701 break;
3704 default:
3705 return NT_STATUS_INVALID_LEVEL;
3708 *pdata_size = data_size;
3709 return NT_STATUS_OK;
3712 /****************************************************************************
3713 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3714 code.
3715 ****************************************************************************/
3717 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3718 connection_struct *conn,
3719 struct smb_request *req,
3720 bool overwrite_if_exists,
3721 const struct smb_filename *smb_fname_old,
3722 struct smb_filename *smb_fname_new)
3724 NTSTATUS status = NT_STATUS_OK;
3725 int ret;
3726 bool ok;
3727 struct smb_filename *parent_fname_old = NULL;
3728 struct smb_filename *base_name_old = NULL;
3729 struct smb_filename *parent_fname_new = NULL;
3730 struct smb_filename *base_name_new = NULL;
3732 /* source must already exist. */
3733 if (!VALID_STAT(smb_fname_old->st)) {
3734 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3735 goto out;
3738 /* No links from a directory. */
3739 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3740 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3741 goto out;
3744 /* Setting a hardlink to/from a stream isn't currently supported. */
3745 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3746 if (ok) {
3747 DBG_DEBUG("Old name has streams\n");
3748 status = NT_STATUS_INVALID_PARAMETER;
3749 goto out;
3751 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3752 if (ok) {
3753 DBG_DEBUG("New name has streams\n");
3754 status = NT_STATUS_INVALID_PARAMETER;
3755 goto out;
3758 if (smb_fname_old->twrp != 0) {
3759 status = NT_STATUS_NOT_SAME_DEVICE;
3760 goto out;
3763 status = parent_pathref(talloc_tos(),
3764 conn->cwd_fsp,
3765 smb_fname_old,
3766 &parent_fname_old,
3767 &base_name_old);
3768 if (!NT_STATUS_IS_OK(status)) {
3769 goto out;
3772 status = parent_pathref(talloc_tos(),
3773 conn->cwd_fsp,
3774 smb_fname_new,
3775 &parent_fname_new,
3776 &base_name_new);
3777 if (!NT_STATUS_IS_OK(status)) {
3778 goto out;
3781 if (VALID_STAT(smb_fname_new->st)) {
3782 if (overwrite_if_exists) {
3783 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3784 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3785 goto out;
3787 status = unlink_internals(conn,
3788 req,
3789 FILE_ATTRIBUTE_NORMAL,
3790 NULL, /* new_dirfsp */
3791 smb_fname_new);
3792 if (!NT_STATUS_IS_OK(status)) {
3793 goto out;
3795 } else {
3796 /* Disallow if newname already exists. */
3797 status = NT_STATUS_OBJECT_NAME_COLLISION;
3798 goto out;
3802 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3803 smb_fname_old->base_name, smb_fname_new->base_name));
3805 ret = SMB_VFS_LINKAT(conn,
3806 parent_fname_old->fsp,
3807 base_name_old,
3808 parent_fname_new->fsp,
3809 base_name_new,
3812 if (ret != 0) {
3813 status = map_nt_error_from_unix(errno);
3814 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3815 nt_errstr(status), smb_fname_old->base_name,
3816 smb_fname_new->base_name));
3819 out:
3821 TALLOC_FREE(parent_fname_old);
3822 TALLOC_FREE(parent_fname_new);
3823 return status;
3826 /****************************************************************************
3827 Deal with setting the time from any of the setfilepathinfo functions.
3828 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3829 calling this function.
3830 ****************************************************************************/
3832 NTSTATUS smb_set_file_time(connection_struct *conn,
3833 files_struct *fsp,
3834 struct smb_filename *smb_fname,
3835 struct smb_file_time *ft,
3836 bool setting_write_time)
3838 struct files_struct *set_fsp = NULL;
3839 struct timeval_buf tbuf[4];
3840 uint32_t action =
3841 FILE_NOTIFY_CHANGE_LAST_ACCESS
3842 |FILE_NOTIFY_CHANGE_LAST_WRITE
3843 |FILE_NOTIFY_CHANGE_CREATION;
3844 int ret;
3846 if (!VALID_STAT(smb_fname->st)) {
3847 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3850 if (fsp == NULL) {
3851 /* A symlink */
3852 return NT_STATUS_OK;
3855 set_fsp = metadata_fsp(fsp);
3857 /* get some defaults (no modifications) if any info is zero or -1. */
3858 if (is_omit_timespec(&ft->create_time)) {
3859 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3862 if (is_omit_timespec(&ft->atime)) {
3863 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3866 if (is_omit_timespec(&ft->mtime)) {
3867 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3870 if (!setting_write_time) {
3871 /* ft->mtime comes from change time, not write time. */
3872 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3875 /* Ensure the resolution is the correct for
3876 * what we can store on this filesystem. */
3878 round_timespec(conn->ts_res, &ft->create_time);
3879 round_timespec(conn->ts_res, &ft->ctime);
3880 round_timespec(conn->ts_res, &ft->atime);
3881 round_timespec(conn->ts_res, &ft->mtime);
3883 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3884 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3885 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3886 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3887 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3888 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3889 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3890 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3892 if (setting_write_time) {
3894 * This was a Windows setfileinfo on an open file.
3895 * NT does this a lot. We also need to
3896 * set the time here, as it can be read by
3897 * FindFirst/FindNext and with the patch for bug #2045
3898 * in smbd/fileio.c it ensures that this timestamp is
3899 * kept sticky even after a write. We save the request
3900 * away and will set it on file close and after a write. JRA.
3903 DBG_DEBUG("setting pending modtime to %s\n",
3904 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3906 if (set_fsp != NULL) {
3907 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3908 } else {
3909 set_sticky_write_time_path(
3910 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3911 ft->mtime);
3915 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3917 ret = file_ntimes(conn, set_fsp, ft);
3918 if (ret != 0) {
3919 return map_nt_error_from_unix(errno);
3922 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3923 smb_fname->base_name);
3924 return NT_STATUS_OK;
3927 /****************************************************************************
3928 Deal with setting the dosmode from any of the setfilepathinfo functions.
3929 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3930 done before calling this function.
3931 ****************************************************************************/
3933 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3934 struct files_struct *fsp,
3935 uint32_t dosmode)
3937 struct files_struct *dos_fsp = NULL;
3938 uint32_t current_dosmode;
3939 int ret;
3941 if (!VALID_STAT(fsp->fsp_name->st)) {
3942 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3945 dos_fsp = metadata_fsp(fsp);
3947 if (dosmode != 0) {
3948 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3949 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3950 } else {
3951 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3955 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3957 /* check the mode isn't different, before changing it */
3958 if (dosmode == 0) {
3959 return NT_STATUS_OK;
3961 current_dosmode = fdos_mode(dos_fsp);
3962 if (dosmode == current_dosmode) {
3963 return NT_STATUS_OK;
3966 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3967 fsp_str_dbg(dos_fsp), dosmode);
3969 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3970 if (ret != 0) {
3971 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3972 fsp_str_dbg(dos_fsp), strerror(errno));
3973 return map_nt_error_from_unix(errno);
3976 return NT_STATUS_OK;
3979 /****************************************************************************
3980 Deal with setting the size from any of the setfilepathinfo functions.
3981 ****************************************************************************/
3983 NTSTATUS smb_set_file_size(connection_struct *conn,
3984 struct smb_request *req,
3985 files_struct *fsp,
3986 struct smb_filename *smb_fname,
3987 const SMB_STRUCT_STAT *psbuf,
3988 off_t size,
3989 bool fail_after_createfile)
3991 NTSTATUS status = NT_STATUS_OK;
3992 files_struct *new_fsp = NULL;
3994 if (!VALID_STAT(*psbuf)) {
3995 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3998 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
3999 (uint64_t)size,
4000 get_file_size_stat(psbuf));
4002 if (size == get_file_size_stat(psbuf)) {
4003 if (fsp == NULL) {
4004 return NT_STATUS_OK;
4006 if (!fsp->fsp_flags.modified) {
4007 return NT_STATUS_OK;
4009 trigger_write_time_update_immediate(fsp);
4010 return NT_STATUS_OK;
4013 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4014 smb_fname_str_dbg(smb_fname), (double)size));
4016 if (fsp &&
4017 !fsp->fsp_flags.is_pathref &&
4018 fsp_get_io_fd(fsp) != -1)
4020 /* Handle based call. */
4021 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4022 if (!NT_STATUS_IS_OK(status)) {
4023 return status;
4026 if (vfs_set_filelen(fsp, size) == -1) {
4027 return map_nt_error_from_unix(errno);
4029 trigger_write_time_update_immediate(fsp);
4030 return NT_STATUS_OK;
4033 status = SMB_VFS_CREATE_FILE(
4034 conn, /* conn */
4035 req, /* req */
4036 NULL, /* dirfsp */
4037 smb_fname, /* fname */
4038 FILE_WRITE_DATA, /* access_mask */
4039 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4040 FILE_SHARE_DELETE),
4041 FILE_OPEN, /* create_disposition*/
4042 0, /* create_options */
4043 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4044 0, /* oplock_request */
4045 NULL, /* lease */
4046 0, /* allocation_size */
4047 0, /* private_flags */
4048 NULL, /* sd */
4049 NULL, /* ea_list */
4050 &new_fsp, /* result */
4051 NULL, /* pinfo */
4052 NULL, NULL); /* create context */
4054 if (!NT_STATUS_IS_OK(status)) {
4055 /* NB. We check for open_was_deferred in the caller. */
4056 return status;
4059 /* See RAW-SFILEINFO-END-OF-FILE */
4060 if (fail_after_createfile) {
4061 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4062 return NT_STATUS_INVALID_LEVEL;
4065 if (vfs_set_filelen(new_fsp, size) == -1) {
4066 status = map_nt_error_from_unix(errno);
4067 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4068 return status;
4071 trigger_write_time_update_immediate(new_fsp);
4072 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4073 return NT_STATUS_OK;
4076 /****************************************************************************
4077 Deal with SMB_INFO_SET_EA.
4078 ****************************************************************************/
4080 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4081 const char *pdata,
4082 int total_data,
4083 files_struct *fsp,
4084 struct smb_filename *smb_fname)
4086 struct ea_list *ea_list = NULL;
4087 TALLOC_CTX *ctx = NULL;
4088 NTSTATUS status = NT_STATUS_OK;
4090 if (total_data < 10) {
4092 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4093 length. They seem to have no effect. Bug #3212. JRA */
4095 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4096 /* We're done. We only get EA info in this call. */
4097 return NT_STATUS_OK;
4100 return NT_STATUS_INVALID_PARAMETER;
4103 if (IVAL(pdata,0) > total_data) {
4104 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4105 IVAL(pdata,0), (unsigned int)total_data));
4106 return NT_STATUS_INVALID_PARAMETER;
4109 ctx = talloc_tos();
4110 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4111 if (!ea_list) {
4112 return NT_STATUS_INVALID_PARAMETER;
4115 if (fsp == NULL) {
4117 * The only way fsp can be NULL here is if
4118 * smb_fname points at a symlink and
4119 * and we're in POSIX context.
4120 * Ensure this is the case.
4122 * In this case we cannot set the EA.
4124 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4125 return NT_STATUS_ACCESS_DENIED;
4128 status = set_ea(conn, fsp, ea_list);
4130 return status;
4133 /****************************************************************************
4134 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4135 ****************************************************************************/
4137 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4138 const char *pdata,
4139 int total_data,
4140 files_struct *fsp)
4142 struct ea_list *ea_list = NULL;
4143 NTSTATUS status;
4145 if (fsp == NULL) {
4146 return NT_STATUS_INVALID_HANDLE;
4149 if (!lp_ea_support(SNUM(conn))) {
4150 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4151 "EA's not supported.\n",
4152 (unsigned int)total_data));
4153 return NT_STATUS_EAS_NOT_SUPPORTED;
4156 if (total_data < 10) {
4157 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4158 "too small.\n",
4159 (unsigned int)total_data));
4160 return NT_STATUS_INVALID_PARAMETER;
4163 ea_list = read_nttrans_ea_list(talloc_tos(),
4164 pdata,
4165 total_data);
4167 if (!ea_list) {
4168 return NT_STATUS_INVALID_PARAMETER;
4171 status = set_ea(conn, fsp, ea_list);
4173 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4174 smb_fname_str_dbg(fsp->fsp_name),
4175 nt_errstr(status) ));
4177 return status;
4181 /****************************************************************************
4182 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4183 ****************************************************************************/
4185 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4186 const char *pdata,
4187 int total_data,
4188 files_struct *fsp,
4189 struct smb_filename *smb_fname)
4191 NTSTATUS status = NT_STATUS_OK;
4192 bool delete_on_close;
4193 uint32_t dosmode = 0;
4195 if (total_data < 1) {
4196 return NT_STATUS_INVALID_PARAMETER;
4199 if (fsp == NULL) {
4200 return NT_STATUS_INVALID_HANDLE;
4203 delete_on_close = (CVAL(pdata,0) ? True : False);
4204 dosmode = fdos_mode(fsp);
4206 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4207 "delete_on_close = %u\n",
4208 smb_fname_str_dbg(smb_fname),
4209 (unsigned int)dosmode,
4210 (unsigned int)delete_on_close ));
4212 if (delete_on_close) {
4213 status = can_set_delete_on_close(fsp, dosmode);
4214 if (!NT_STATUS_IS_OK(status)) {
4215 return status;
4219 /* The set is across all open files on this dev/inode pair. */
4220 if (!set_delete_on_close(fsp, delete_on_close,
4221 conn->session_info->security_token,
4222 conn->session_info->unix_token)) {
4223 return NT_STATUS_ACCESS_DENIED;
4225 return NT_STATUS_OK;
4228 /****************************************************************************
4229 Deal with SMB_FILE_POSITION_INFORMATION.
4230 ****************************************************************************/
4232 static NTSTATUS smb_file_position_information(connection_struct *conn,
4233 const char *pdata,
4234 int total_data,
4235 files_struct *fsp)
4237 uint64_t position_information;
4239 if (total_data < 8) {
4240 return NT_STATUS_INVALID_PARAMETER;
4243 if (fsp == NULL) {
4244 /* Ignore on pathname based set. */
4245 return NT_STATUS_OK;
4248 position_information = (uint64_t)IVAL(pdata,0);
4249 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4251 DEBUG(10,("smb_file_position_information: Set file position "
4252 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4253 (double)position_information));
4254 fh_set_position_information(fsp->fh, position_information);
4255 return NT_STATUS_OK;
4258 /****************************************************************************
4259 Deal with SMB_FILE_MODE_INFORMATION.
4260 ****************************************************************************/
4262 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4263 const char *pdata,
4264 int total_data)
4266 uint32_t mode;
4268 if (total_data < 4) {
4269 return NT_STATUS_INVALID_PARAMETER;
4271 mode = IVAL(pdata,0);
4272 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4273 return NT_STATUS_INVALID_PARAMETER;
4275 return NT_STATUS_OK;
4278 /****************************************************************************
4279 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4280 ****************************************************************************/
4282 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4283 struct smb_request *req,
4284 const char *pdata,
4285 int total_data,
4286 files_struct *fsp,
4287 struct smb_filename *smb_fname_src)
4289 bool overwrite;
4290 uint32_t len;
4291 char *newname = NULL;
4292 struct files_struct *dst_dirfsp = NULL;
4293 struct smb_filename *smb_fname_dst = NULL;
4294 const char *dst_original_lcomp = NULL;
4295 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4296 NTSTATUS status = NT_STATUS_OK;
4297 TALLOC_CTX *ctx = talloc_tos();
4299 if (!fsp) {
4300 return NT_STATUS_INVALID_HANDLE;
4303 if (total_data < 20) {
4304 return NT_STATUS_INVALID_PARAMETER;
4307 overwrite = (CVAL(pdata,0) ? True : False);
4308 len = IVAL(pdata,16);
4310 if (len > (total_data - 20) || (len == 0)) {
4311 return NT_STATUS_INVALID_PARAMETER;
4314 (void)srvstr_pull_talloc(ctx,
4315 pdata,
4316 req->flags2,
4317 &newname,
4318 &pdata[20],
4319 len,
4320 STR_TERMINATE);
4322 if (newname == NULL) {
4323 return NT_STATUS_INVALID_PARAMETER;
4326 /* SMB2 rename paths are never DFS. */
4327 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4328 ucf_flags &= ~UCF_DFS_PATHNAME;
4330 status = check_path_syntax(newname,
4331 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4332 if (!NT_STATUS_IS_OK(status)) {
4333 return status;
4336 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4337 newname));
4339 if (newname[0] == ':') {
4340 /* Create an smb_fname to call rename_internals_fsp() with. */
4341 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4342 fsp->base_fsp->fsp_name->base_name,
4343 newname,
4344 NULL,
4345 fsp->base_fsp->fsp_name->twrp,
4346 fsp->base_fsp->fsp_name->flags);
4347 if (smb_fname_dst == NULL) {
4348 status = NT_STATUS_NO_MEMORY;
4349 goto out;
4351 } else {
4352 status = filename_convert_dirfsp(ctx,
4353 conn,
4354 newname,
4355 ucf_flags,
4356 0, /* Never a TWRP. */
4357 &dst_dirfsp,
4358 &smb_fname_dst);
4359 if (!NT_STATUS_IS_OK(status)) {
4360 goto out;
4365 * Set the original last component, since
4366 * rename_internals_fsp() requires it.
4368 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4369 conn,
4370 newname,
4371 ucf_flags);
4372 if (dst_original_lcomp == NULL) {
4373 status = NT_STATUS_NO_MEMORY;
4374 goto out;
4377 DEBUG(10,("smb2_file_rename_information: "
4378 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4379 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4380 smb_fname_str_dbg(smb_fname_dst)));
4381 status = rename_internals_fsp(conn,
4382 fsp,
4383 smb_fname_dst,
4384 dst_original_lcomp,
4385 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4386 overwrite);
4388 out:
4389 TALLOC_FREE(smb_fname_dst);
4390 return status;
4393 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4394 struct smb_request *req,
4395 const char *pdata,
4396 int total_data,
4397 files_struct *fsp,
4398 struct smb_filename *smb_fname_src)
4400 bool overwrite;
4401 uint32_t len;
4402 char *newname = NULL;
4403 struct files_struct *dst_dirfsp = NULL;
4404 struct smb_filename *smb_fname_dst = NULL;
4405 NTSTATUS status = NT_STATUS_OK;
4406 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4407 size_t ret;
4408 TALLOC_CTX *ctx = talloc_tos();
4410 if (!fsp) {
4411 return NT_STATUS_INVALID_HANDLE;
4414 if (total_data < 20) {
4415 return NT_STATUS_INVALID_PARAMETER;
4418 overwrite = (CVAL(pdata,0) ? true : false);
4419 len = IVAL(pdata,16);
4421 if (len > (total_data - 20) || (len == 0)) {
4422 return NT_STATUS_INVALID_PARAMETER;
4425 ret = srvstr_pull_talloc(ctx,
4426 pdata,
4427 req->flags2,
4428 &newname,
4429 &pdata[20],
4430 len,
4431 STR_TERMINATE);
4433 if (ret == (size_t)-1 || newname == NULL) {
4434 return NT_STATUS_INVALID_PARAMETER;
4437 /* SMB2 hardlink paths are never DFS. */
4438 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4439 ucf_flags &= ~UCF_DFS_PATHNAME;
4441 status = check_path_syntax(newname,
4442 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 return status;
4447 DBG_DEBUG("got name |%s|\n", newname);
4449 status = filename_convert_dirfsp(ctx,
4450 conn,
4451 newname,
4452 ucf_flags,
4453 0, /* No TWRP. */
4454 &dst_dirfsp,
4455 &smb_fname_dst);
4456 if (!NT_STATUS_IS_OK(status)) {
4457 return status;
4460 if (fsp->base_fsp) {
4461 /* No stream names. */
4462 return NT_STATUS_NOT_SUPPORTED;
4465 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4466 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4467 smb_fname_str_dbg(smb_fname_dst));
4468 status = hardlink_internals(ctx,
4469 conn,
4470 req,
4471 overwrite,
4472 fsp->fsp_name,
4473 smb_fname_dst);
4475 TALLOC_FREE(smb_fname_dst);
4476 return status;
4479 static NTSTATUS smb_file_link_information(connection_struct *conn,
4480 struct smb_request *req,
4481 const char *pdata,
4482 int total_data,
4483 files_struct *fsp,
4484 struct smb_filename *smb_fname_src)
4486 bool overwrite;
4487 uint32_t len;
4488 char *newname = NULL;
4489 struct files_struct *dst_dirfsp = NULL;
4490 struct smb_filename *smb_fname_dst = NULL;
4491 NTSTATUS status = NT_STATUS_OK;
4492 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4493 NTTIME dst_twrp = 0;
4494 TALLOC_CTX *ctx = talloc_tos();
4496 if (!fsp) {
4497 return NT_STATUS_INVALID_HANDLE;
4500 if (total_data < 20) {
4501 return NT_STATUS_INVALID_PARAMETER;
4504 overwrite = (CVAL(pdata,0) ? true : false);
4505 len = IVAL(pdata,16);
4507 if (len > (total_data - 20) || (len == 0)) {
4508 return NT_STATUS_INVALID_PARAMETER;
4511 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4512 srvstr_get_path_posix(ctx,
4513 pdata,
4514 req->flags2,
4515 &newname,
4516 &pdata[20],
4517 len,
4518 STR_TERMINATE,
4519 &status);
4520 ucf_flags |= UCF_POSIX_PATHNAMES;
4521 } else {
4522 srvstr_get_path(ctx,
4523 pdata,
4524 req->flags2,
4525 &newname,
4526 &pdata[20],
4527 len,
4528 STR_TERMINATE,
4529 &status);
4531 if (!NT_STATUS_IS_OK(status)) {
4532 return status;
4535 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4536 newname));
4538 if (ucf_flags & UCF_GMT_PATHNAME) {
4539 extract_snapshot_token(newname, &dst_twrp);
4541 /* hardlink paths are never DFS. */
4542 ucf_flags &= ~UCF_DFS_PATHNAME;
4544 status = filename_convert_dirfsp(ctx,
4545 conn,
4546 newname,
4547 ucf_flags,
4548 dst_twrp,
4549 &dst_dirfsp,
4550 &smb_fname_dst);
4551 if (!NT_STATUS_IS_OK(status)) {
4552 return status;
4555 if (fsp->base_fsp) {
4556 /* No stream names. */
4557 return NT_STATUS_NOT_SUPPORTED;
4560 DEBUG(10,("smb_file_link_information: "
4561 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4562 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4563 smb_fname_str_dbg(smb_fname_dst)));
4564 status = hardlink_internals(ctx,
4565 conn,
4566 req,
4567 overwrite,
4568 fsp->fsp_name,
4569 smb_fname_dst);
4571 TALLOC_FREE(smb_fname_dst);
4572 return status;
4576 /****************************************************************************
4577 Deal with SMB_FILE_RENAME_INFORMATION.
4578 ****************************************************************************/
4580 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4581 struct smb_request *req,
4582 const char *pdata,
4583 int total_data,
4584 files_struct *fsp,
4585 struct smb_filename *smb_fname_src)
4587 bool overwrite;
4588 uint32_t root_fid;
4589 uint32_t len;
4590 char *newname = NULL;
4591 struct files_struct *dst_dirfsp = NULL;
4592 struct smb_filename *smb_fname_dst = NULL;
4593 const char *dst_original_lcomp = NULL;
4594 NTSTATUS status = NT_STATUS_OK;
4595 char *p;
4596 TALLOC_CTX *ctx = talloc_tos();
4598 if (total_data < 13) {
4599 return NT_STATUS_INVALID_PARAMETER;
4602 overwrite = (CVAL(pdata,0) != 0);
4603 root_fid = IVAL(pdata,4);
4604 len = IVAL(pdata,8);
4606 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4607 return NT_STATUS_INVALID_PARAMETER;
4610 if (req->posix_pathnames) {
4611 srvstr_get_path_posix(ctx,
4612 pdata,
4613 req->flags2,
4614 &newname,
4615 &pdata[12],
4616 len,
4618 &status);
4619 } else {
4620 srvstr_get_path(ctx,
4621 pdata,
4622 req->flags2,
4623 &newname,
4624 &pdata[12],
4625 len,
4627 &status);
4629 if (!NT_STATUS_IS_OK(status)) {
4630 return status;
4633 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4634 newname));
4636 /* Check the new name has no '/' characters. */
4637 if (strchr_m(newname, '/')) {
4638 return NT_STATUS_NOT_SUPPORTED;
4641 if (fsp && fsp->base_fsp) {
4642 /* newname must be a stream name. */
4643 if (newname[0] != ':') {
4644 return NT_STATUS_NOT_SUPPORTED;
4647 /* Create an smb_fname to call rename_internals_fsp() with. */
4648 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4649 fsp->base_fsp->fsp_name->base_name,
4650 newname,
4651 NULL,
4652 fsp->base_fsp->fsp_name->twrp,
4653 fsp->base_fsp->fsp_name->flags);
4654 if (smb_fname_dst == NULL) {
4655 status = NT_STATUS_NO_MEMORY;
4656 goto out;
4660 * Get the original last component, since
4661 * rename_internals_fsp() requires it.
4663 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4664 conn,
4665 newname,
4667 if (dst_original_lcomp == NULL) {
4668 status = NT_STATUS_NO_MEMORY;
4669 goto out;
4672 } else {
4674 * Build up an smb_fname_dst based on the filename passed in.
4675 * We basically just strip off the last component, and put on
4676 * the newname instead.
4678 char *base_name = NULL;
4679 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4680 NTTIME dst_twrp = 0;
4682 /* newname must *not* be a stream name. */
4683 if (newname[0] == ':') {
4684 return NT_STATUS_NOT_SUPPORTED;
4688 * Strip off the last component (filename) of the path passed
4689 * in.
4691 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4692 if (!base_name) {
4693 return NT_STATUS_NO_MEMORY;
4695 p = strrchr_m(base_name, '/');
4696 if (p) {
4697 p[1] = '\0';
4698 } else {
4699 base_name = talloc_strdup(ctx, "");
4700 if (!base_name) {
4701 return NT_STATUS_NO_MEMORY;
4704 /* Append the new name. */
4705 base_name = talloc_asprintf_append(base_name,
4706 "%s",
4707 newname);
4708 if (!base_name) {
4709 return NT_STATUS_NO_MEMORY;
4712 if (ucf_flags & UCF_GMT_PATHNAME) {
4713 extract_snapshot_token(base_name, &dst_twrp);
4716 /* The newname is *not* a DFS path. */
4717 ucf_flags &= ~UCF_DFS_PATHNAME;
4719 status = filename_convert_dirfsp(ctx,
4720 conn,
4721 base_name,
4722 ucf_flags,
4723 dst_twrp,
4724 &dst_dirfsp,
4725 &smb_fname_dst);
4727 if (!NT_STATUS_IS_OK(status)) {
4728 goto out;
4730 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4731 conn,
4732 newname,
4733 ucf_flags);
4734 if (dst_original_lcomp == NULL) {
4735 status = NT_STATUS_NO_MEMORY;
4736 goto out;
4740 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4741 DEBUG(10,("smb_file_rename_information: "
4742 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4743 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4744 smb_fname_str_dbg(smb_fname_dst)));
4745 status = rename_internals_fsp(conn,
4746 fsp,
4747 smb_fname_dst,
4748 dst_original_lcomp,
4750 overwrite);
4751 } else {
4752 DEBUG(10,("smb_file_rename_information: "
4753 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4754 smb_fname_str_dbg(smb_fname_src),
4755 smb_fname_str_dbg(smb_fname_dst)));
4756 status = rename_internals(ctx,
4757 conn,
4758 req,
4759 NULL, /* src_dirfsp */
4760 smb_fname_src,
4761 smb_fname_dst,
4762 dst_original_lcomp,
4764 overwrite,
4765 FILE_WRITE_ATTRIBUTES);
4767 out:
4768 TALLOC_FREE(smb_fname_dst);
4769 return status;
4772 /****************************************************************************
4773 Deal with SMB_SET_FILE_BASIC_INFO.
4774 ****************************************************************************/
4776 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4777 const char *pdata,
4778 int total_data,
4779 files_struct *fsp,
4780 struct smb_filename *smb_fname)
4782 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4783 struct smb_file_time ft;
4784 uint32_t dosmode = 0;
4785 NTSTATUS status = NT_STATUS_OK;
4787 init_smb_file_time(&ft);
4789 if (total_data < 36) {
4790 return NT_STATUS_INVALID_PARAMETER;
4793 if (fsp == NULL) {
4794 return NT_STATUS_INVALID_HANDLE;
4797 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 return status;
4802 /* Set the attributes */
4803 dosmode = IVAL(pdata,32);
4804 status = smb_set_file_dosmode(conn, fsp, dosmode);
4805 if (!NT_STATUS_IS_OK(status)) {
4806 return status;
4809 /* create time */
4810 ft.create_time = pull_long_date_full_timespec(pdata);
4812 /* access time */
4813 ft.atime = pull_long_date_full_timespec(pdata+8);
4815 /* write time. */
4816 ft.mtime = pull_long_date_full_timespec(pdata+16);
4818 /* change time. */
4819 ft.ctime = pull_long_date_full_timespec(pdata+24);
4821 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4822 smb_fname_str_dbg(smb_fname)));
4824 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4825 if (!NT_STATUS_IS_OK(status)) {
4826 return status;
4829 if (fsp->fsp_flags.modified) {
4830 trigger_write_time_update_immediate(fsp);
4832 return NT_STATUS_OK;
4835 /****************************************************************************
4836 Deal with SMB_INFO_STANDARD.
4837 ****************************************************************************/
4839 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4840 const char *pdata,
4841 int total_data,
4842 files_struct *fsp,
4843 struct smb_filename *smb_fname)
4845 NTSTATUS status;
4846 struct smb_file_time ft;
4848 init_smb_file_time(&ft);
4850 if (total_data < 12) {
4851 return NT_STATUS_INVALID_PARAMETER;
4854 if (fsp == NULL) {
4855 return NT_STATUS_INVALID_HANDLE;
4858 /* create time */
4859 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4860 /* access time */
4861 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4862 /* write time */
4863 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4865 DEBUG(10,("smb_set_info_standard: file %s\n",
4866 smb_fname_str_dbg(smb_fname)));
4868 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4869 if (!NT_STATUS_IS_OK(status)) {
4870 return status;
4873 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4874 if (!NT_STATUS_IS_OK(status)) {
4875 return status;
4878 if (fsp->fsp_flags.modified) {
4879 trigger_write_time_update_immediate(fsp);
4881 return NT_STATUS_OK;
4884 /****************************************************************************
4885 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4886 ****************************************************************************/
4888 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4889 struct smb_request *req,
4890 const char *pdata,
4891 int total_data,
4892 files_struct *fsp,
4893 struct smb_filename *smb_fname)
4895 uint64_t allocation_size = 0;
4896 NTSTATUS status = NT_STATUS_OK;
4897 files_struct *new_fsp = NULL;
4899 if (!VALID_STAT(smb_fname->st)) {
4900 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4903 if (total_data < 8) {
4904 return NT_STATUS_INVALID_PARAMETER;
4907 allocation_size = (uint64_t)IVAL(pdata,0);
4908 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4909 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4910 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4911 (double)allocation_size));
4913 if (allocation_size) {
4914 allocation_size = smb_roundup(conn, allocation_size);
4917 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4918 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4919 (double)allocation_size));
4921 if (fsp &&
4922 !fsp->fsp_flags.is_pathref &&
4923 fsp_get_io_fd(fsp) != -1)
4925 /* Open file handle. */
4926 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4927 if (!NT_STATUS_IS_OK(status)) {
4928 return status;
4931 /* Only change if needed. */
4932 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4933 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4934 return map_nt_error_from_unix(errno);
4937 /* But always update the time. */
4939 * This is equivalent to a write. Ensure it's seen immediately
4940 * if there are no pending writes.
4942 trigger_write_time_update_immediate(fsp);
4943 return NT_STATUS_OK;
4946 /* Pathname or stat or directory file. */
4947 status = SMB_VFS_CREATE_FILE(
4948 conn, /* conn */
4949 req, /* req */
4950 NULL, /* dirfsp */
4951 smb_fname, /* fname */
4952 FILE_WRITE_DATA, /* access_mask */
4953 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4954 FILE_SHARE_DELETE),
4955 FILE_OPEN, /* create_disposition*/
4956 0, /* create_options */
4957 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4958 0, /* oplock_request */
4959 NULL, /* lease */
4960 0, /* allocation_size */
4961 0, /* private_flags */
4962 NULL, /* sd */
4963 NULL, /* ea_list */
4964 &new_fsp, /* result */
4965 NULL, /* pinfo */
4966 NULL, NULL); /* create context */
4968 if (!NT_STATUS_IS_OK(status)) {
4969 /* NB. We check for open_was_deferred in the caller. */
4970 return status;
4973 /* Only change if needed. */
4974 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4975 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
4976 status = map_nt_error_from_unix(errno);
4977 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4978 return status;
4982 /* Changing the allocation size should set the last mod time. */
4984 * This is equivalent to a write. Ensure it's seen immediately
4985 * if there are no pending writes.
4987 trigger_write_time_update_immediate(new_fsp);
4988 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4989 return NT_STATUS_OK;
4992 /****************************************************************************
4993 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
4994 ****************************************************************************/
4996 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
4997 struct smb_request *req,
4998 const char *pdata,
4999 int total_data,
5000 files_struct *fsp,
5001 struct smb_filename *smb_fname,
5002 bool fail_after_createfile)
5004 off_t size;
5006 if (total_data < 8) {
5007 return NT_STATUS_INVALID_PARAMETER;
5010 size = IVAL(pdata,0);
5011 size |= (((off_t)IVAL(pdata,4)) << 32);
5012 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5013 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5014 (double)size));
5016 return smb_set_file_size(conn, req,
5017 fsp,
5018 smb_fname,
5019 &smb_fname->st,
5020 size,
5021 fail_after_createfile);
5024 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5025 struct smb_request *req,
5026 TALLOC_CTX *mem_ctx,
5027 uint16_t info_level,
5028 files_struct *fsp,
5029 struct smb_filename *smb_fname,
5030 char **ppdata, int total_data,
5031 int *ret_data_size)
5033 char *pdata = *ppdata;
5034 NTSTATUS status = NT_STATUS_OK;
5035 int data_return_size = 0;
5037 *ret_data_size = 0;
5039 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5040 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5041 fsp_fnum_dbg(fsp),
5042 info_level, total_data));
5044 switch (info_level) {
5046 case SMB_INFO_STANDARD:
5048 status = smb_set_info_standard(conn,
5049 pdata,
5050 total_data,
5051 fsp,
5052 smb_fname);
5053 break;
5056 case SMB_INFO_SET_EA:
5058 status = smb_info_set_ea(conn,
5059 pdata,
5060 total_data,
5061 fsp,
5062 smb_fname);
5063 break;
5066 case SMB_SET_FILE_BASIC_INFO:
5067 case SMB_FILE_BASIC_INFORMATION:
5069 status = smb_set_file_basic_info(conn,
5070 pdata,
5071 total_data,
5072 fsp,
5073 smb_fname);
5074 break;
5077 case SMB_FILE_ALLOCATION_INFORMATION:
5078 case SMB_SET_FILE_ALLOCATION_INFO:
5080 status = smb_set_file_allocation_info(conn, req,
5081 pdata,
5082 total_data,
5083 fsp,
5084 smb_fname);
5085 break;
5088 case SMB_FILE_END_OF_FILE_INFORMATION:
5089 case SMB_SET_FILE_END_OF_FILE_INFO:
5092 * XP/Win7 both fail after the createfile with
5093 * SMB_SET_FILE_END_OF_FILE_INFO but not
5094 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5095 * The level is known here, so pass it down
5096 * appropriately.
5098 bool should_fail =
5099 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5101 status = smb_set_file_end_of_file_info(conn, req,
5102 pdata,
5103 total_data,
5104 fsp,
5105 smb_fname,
5106 should_fail);
5107 break;
5110 case SMB_FILE_DISPOSITION_INFORMATION:
5111 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5113 #if 0
5114 /* JRA - We used to just ignore this on a path ?
5115 * Shouldn't this be invalid level on a pathname
5116 * based call ?
5118 if (tran_call != TRANSACT2_SETFILEINFO) {
5119 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5121 #endif
5122 status = smb_set_file_disposition_info(conn,
5123 pdata,
5124 total_data,
5125 fsp,
5126 smb_fname);
5127 break;
5130 case SMB_FILE_POSITION_INFORMATION:
5132 status = smb_file_position_information(conn,
5133 pdata,
5134 total_data,
5135 fsp);
5136 break;
5139 case SMB_FILE_FULL_EA_INFORMATION:
5141 status = smb_set_file_full_ea_info(conn,
5142 pdata,
5143 total_data,
5144 fsp);
5145 break;
5148 /* From tridge Samba4 :
5149 * MODE_INFORMATION in setfileinfo (I have no
5150 * idea what "mode information" on a file is - it takes a value of 0,
5151 * 2, 4 or 6. What could it be?).
5154 case SMB_FILE_MODE_INFORMATION:
5156 status = smb_file_mode_information(conn,
5157 pdata,
5158 total_data);
5159 break;
5162 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5163 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5164 case SMB_FILE_SHORT_NAME_INFORMATION:
5165 return NT_STATUS_NOT_SUPPORTED;
5167 case SMB_FILE_RENAME_INFORMATION:
5169 status = smb_file_rename_information(conn, req,
5170 pdata, total_data,
5171 fsp, smb_fname);
5172 break;
5175 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5177 /* SMB2 rename information. */
5178 status = smb2_file_rename_information(conn, req,
5179 pdata, total_data,
5180 fsp, smb_fname);
5181 break;
5184 case SMB_FILE_LINK_INFORMATION:
5186 if (conn->sconn->using_smb2) {
5187 status = smb2_file_link_information(conn,
5188 req,
5189 pdata,
5190 total_data,
5191 fsp,
5192 smb_fname);
5193 } else {
5194 status = smb_file_link_information(conn,
5195 req,
5196 pdata,
5197 total_data,
5198 fsp,
5199 smb_fname);
5201 break;
5204 default:
5205 return NT_STATUS_INVALID_LEVEL;
5208 if (!NT_STATUS_IS_OK(status)) {
5209 return status;
5212 *ret_data_size = data_return_size;
5213 return NT_STATUS_OK;
5216 static uint32_t generate_volume_serial_number(
5217 const struct loadparm_substitution *lp_sub,
5218 int snum)
5220 int serial = lp_volume_serial_number(snum);
5221 return serial != -1 ? serial:
5222 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5223 (str_checksum(get_local_machine_name())<<16);