smbd: Convert refuse_symlink_fsp() to bool
[samba4-gss.git] / source3 / smbd / smb2_trans2.c
blobc9bd4c25e47bea5009fec9660b8a711afeeef73d
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"
51 #include "source3/modules/util_reparse.h"
53 #define DIR_ENTRY_SAFETY_MARGIN 4096
55 static uint32_t generate_volume_serial_number(
56 const struct loadparm_substitution *lp_sub,
57 int snum);
59 /****************************************************************************
60 Check if an open file handle is a symlink.
61 ****************************************************************************/
63 bool refuse_symlink_fsp(const files_struct *fsp)
66 if (!VALID_STAT(fsp->fsp_name->st)) {
67 return true;
69 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
70 return true;
72 if (fsp_get_pathref_fd(fsp) == -1) {
73 return true;
75 return false;
78 /**
79 * Check that one or more of the rights in access mask are
80 * allowed. Iow, access_requested can contain more then one right and
81 * it is sufficient having only one of those granted to pass.
82 **/
83 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
84 uint32_t access_requested)
86 const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
87 uint32_t ro_access_granted = 0;
88 uint32_t access_granted = 0;
89 NTSTATUS status;
91 if (fsp->fsp_flags.is_fsa) {
92 access_granted = fsp->access_mask;
93 } else {
94 uint32_t mask = 1;
96 while (mask != 0) {
97 if (!(mask & access_requested)) {
98 mask <<= 1;
99 continue;
102 status = smbd_check_access_rights_fsp(
103 fsp->conn->cwd_fsp,
104 fsp,
105 false,
106 mask);
107 if (NT_STATUS_IS_OK(status)) {
108 access_granted |= mask;
109 if (fsp->fsp_name->twrp == 0) {
111 * We can only optimize
112 * the non-snapshot case
114 break;
117 mask <<= 1;
120 if ((access_granted & access_requested) == 0) {
121 return NT_STATUS_ACCESS_DENIED;
124 if (fsp->fsp_name->twrp == 0) {
125 return NT_STATUS_OK;
128 ro_access_granted = access_granted & ro_access;
129 if ((ro_access_granted & access_requested) == 0) {
130 return NT_STATUS_MEDIA_WRITE_PROTECTED;
133 return NT_STATUS_OK;
136 /********************************************************************
137 Roundup a value to the nearest allocation roundup size boundary.
138 Only do this for Windows clients.
139 ********************************************************************/
141 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
143 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
145 /* Only roundup for Windows clients. */
146 enum remote_arch_types ra_type = get_remote_arch();
147 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
148 val = SMB_ROUNDUP(val,rval);
150 return val;
153 /****************************************************************************
154 Utility functions for dealing with extended attributes.
155 ****************************************************************************/
157 /****************************************************************************
158 Refuse to allow clients to overwrite our private xattrs.
159 ****************************************************************************/
161 bool samba_private_attr_name(const char *unix_ea_name)
163 bool prohibited = false;
165 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
166 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
167 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
168 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_REPARSE_ATTRIB);
169 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
170 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
172 if (prohibited) {
173 return true;
176 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
177 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
178 return true;
180 return false;
183 /****************************************************************************
184 Get one EA value. Fill in a struct ea_struct.
185 ****************************************************************************/
187 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
188 files_struct *fsp,
189 const char *ea_name,
190 struct ea_struct *pea)
192 /* Get the value of this xattr. Max size is 64k. */
193 size_t attr_size = 256;
194 char *val = NULL;
195 ssize_t sizeret;
196 size_t max_xattr_size = 0;
197 bool refuse;
199 if (fsp == NULL) {
200 return NT_STATUS_INVALID_HANDLE;
202 refuse = refuse_symlink_fsp(fsp);
203 if (refuse) {
204 return NT_STATUS_ACCESS_DENIED;
207 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
209 again:
211 val = talloc_realloc(mem_ctx, val, char, attr_size);
212 if (!val) {
213 return NT_STATUS_NO_MEMORY;
216 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
217 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
218 attr_size = max_xattr_size;
219 goto again;
222 if (sizeret == -1) {
223 return map_nt_error_from_unix(errno);
226 DBG_DEBUG("EA %s is of length %zd\n", ea_name, sizeret);
227 dump_data(10, (uint8_t *)val, sizeret);
229 pea->flags = 0;
230 if (strnequal(ea_name, "user.", 5)) {
231 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
232 } else {
233 pea->name = talloc_strdup(mem_ctx, ea_name);
235 if (pea->name == NULL) {
236 TALLOC_FREE(val);
237 return NT_STATUS_NO_MEMORY;
239 pea->value.data = (unsigned char *)val;
240 pea->value.length = (size_t)sizeret;
241 return NT_STATUS_OK;
244 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
245 files_struct *fsp,
246 char ***pnames,
247 size_t *pnum_names)
249 char smallbuf[1024];
250 /* Get a list of all xattrs. Max namesize is 64k. */
251 size_t ea_namelist_size = 1024;
252 char *ea_namelist = smallbuf;
253 char *to_free = NULL;
255 char *p;
256 char **names;
257 size_t num_names;
258 ssize_t sizeret = -1;
259 NTSTATUS status;
261 if (pnames) {
262 *pnames = NULL;
264 *pnum_names = 0;
266 if ((fsp == NULL) || refuse_symlink_fsp(fsp)) {
268 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
269 * symlink. This is ok, handle it here, by just return no EA's
270 * on a symlink.
272 return NT_STATUS_OK;
275 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
276 ea_namelist_size);
278 if ((sizeret == -1) && (errno == ERANGE)) {
279 ea_namelist_size = 65536;
280 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
281 if (ea_namelist == NULL) {
282 return NT_STATUS_NO_MEMORY;
284 to_free = ea_namelist;
286 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
287 ea_namelist_size);
290 if (sizeret == -1) {
291 status = map_nt_error_from_unix(errno);
292 TALLOC_FREE(to_free);
293 return status;
296 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
298 if (sizeret == 0) {
299 TALLOC_FREE(to_free);
300 return NT_STATUS_OK;
304 * Ensure the result is 0-terminated
307 if (ea_namelist[sizeret-1] != '\0') {
308 TALLOC_FREE(to_free);
309 return NT_STATUS_INTERNAL_ERROR;
313 * count the names
315 num_names = 0;
317 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
318 num_names += 1;
321 *pnum_names = num_names;
323 if (pnames == NULL) {
324 TALLOC_FREE(to_free);
325 return NT_STATUS_OK;
328 names = talloc_array(mem_ctx, char *, num_names);
329 if (names == NULL) {
330 DEBUG(0, ("talloc failed\n"));
331 TALLOC_FREE(to_free);
332 return NT_STATUS_NO_MEMORY;
335 if (ea_namelist == smallbuf) {
336 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
337 if (ea_namelist == NULL) {
338 TALLOC_FREE(names);
339 return NT_STATUS_NO_MEMORY;
341 } else {
342 talloc_steal(names, ea_namelist);
344 ea_namelist = talloc_realloc(names, ea_namelist, char,
345 sizeret);
346 if (ea_namelist == NULL) {
347 TALLOC_FREE(names);
348 return NT_STATUS_NO_MEMORY;
352 num_names = 0;
354 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
355 names[num_names++] = p;
358 *pnames = names;
360 return NT_STATUS_OK;
363 /****************************************************************************
364 Return a linked list of the total EA's. Plus the total size
365 ****************************************************************************/
367 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
368 files_struct *fsp,
369 size_t *pea_total_len,
370 struct ea_list **ea_list)
372 /* Get a list of all xattrs. Max namesize is 64k. */
373 size_t i, num_names;
374 char **names;
375 struct ea_list *ea_list_head = NULL;
376 bool posix_pathnames = false;
377 NTSTATUS status;
379 *pea_total_len = 0;
380 *ea_list = NULL;
382 /* symlink */
383 if (fsp == NULL) {
384 return NT_STATUS_OK;
387 if (!lp_ea_support(SNUM(fsp->conn))) {
388 return NT_STATUS_OK;
391 if (fsp_is_alternate_stream(fsp)) {
392 return NT_STATUS_INVALID_PARAMETER;
395 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
397 status = get_ea_names_from_fsp(talloc_tos(),
398 fsp,
399 &names,
400 &num_names);
402 if (!NT_STATUS_IS_OK(status)) {
403 return status;
406 if (num_names == 0) {
407 return NT_STATUS_OK;
410 for (i=0; i<num_names; i++) {
411 struct ea_list *listp;
412 fstring dos_ea_name;
415 * POSIX EA names are divided into several namespaces by
416 * means of string prefixes. Usually, the system controls
417 * semantics for each namespace, but the 'user' namespace is
418 * available for arbitrary use, which comes closest to
419 * Windows EA semantics. Hence, we map POSIX EAs from the
420 * 'user' namespace to Windows EAs, and just ignore all the
421 * other namespaces. Also, a few specific names in the 'user'
422 * namespace are used by Samba internally. Filter them out as
423 * well, and only present the EAs that are available for
424 * arbitrary use.
426 if (!strnequal(names[i], "user.", 5)
427 || samba_private_attr_name(names[i]))
428 continue;
431 * Filter out any underlying POSIX EA names
432 * that a Windows client can't handle.
434 if (!posix_pathnames &&
435 is_invalid_windows_ea_name(names[i])) {
436 continue;
439 listp = talloc(mem_ctx, struct ea_list);
440 if (listp == NULL) {
441 return NT_STATUS_NO_MEMORY;
444 status = get_ea_value_fsp(listp,
445 fsp,
446 names[i],
447 &listp->ea);
449 if (!NT_STATUS_IS_OK(status)) {
450 TALLOC_FREE(listp);
451 return status;
454 if (listp->ea.value.length == 0) {
456 * We can never return a zero length EA.
457 * Windows reports the EA's as corrupted.
459 TALLOC_FREE(listp);
460 continue;
462 if (listp->ea.value.length > 65536) {
464 * SMB clients may report error with file
465 * if large EA is presented to them.
467 DBG_ERR("EA [%s] on file [%s] exceeds "
468 "maximum permitted EA size of 64KiB: %zu\n.",
469 listp->ea.name, fsp_str_dbg(fsp),
470 listp->ea.value.length);
471 TALLOC_FREE(listp);
472 continue;
475 push_ascii_fstring(dos_ea_name, listp->ea.name);
477 *pea_total_len +=
478 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
480 DBG_DEBUG("total_len = %zu, %s, val len = %zu\n",
481 *pea_total_len,
482 dos_ea_name,
483 listp->ea.value.length);
485 DLIST_ADD_END(ea_list_head, listp);
489 /* Add on 4 for total length. */
490 if (*pea_total_len) {
491 *pea_total_len += 4;
494 DBG_DEBUG("total_len = %zu\n", *pea_total_len);
496 *ea_list = ea_list_head;
497 return NT_STATUS_OK;
500 /****************************************************************************
501 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
502 that was filled.
503 ****************************************************************************/
505 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
506 connection_struct *conn, struct ea_list *ea_list)
508 unsigned int ret_data_size = 4;
509 char *p = pdata;
511 SMB_ASSERT(total_data_size >= 4);
513 if (!lp_ea_support(SNUM(conn))) {
514 SIVAL(pdata,4,0);
515 return 4;
518 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
519 size_t dos_namelen;
520 fstring dos_ea_name;
521 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
522 dos_namelen = strlen(dos_ea_name);
523 if (dos_namelen > 255 || dos_namelen == 0) {
524 break;
526 if (ea_list->ea.value.length > 65535) {
527 break;
529 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
530 break;
533 /* We know we have room. */
534 SCVAL(p,0,ea_list->ea.flags);
535 SCVAL(p,1,dos_namelen);
536 SSVAL(p,2,ea_list->ea.value.length);
537 strlcpy(p+4, dos_ea_name, dos_namelen+1);
538 if (ea_list->ea.value.length > 0) {
539 memcpy(p + 4 + dos_namelen + 1,
540 ea_list->ea.value.data,
541 ea_list->ea.value.length);
544 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
545 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
548 ret_data_size = PTR_DIFF(p, pdata);
549 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
550 SIVAL(pdata,0,ret_data_size);
551 return ret_data_size;
554 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
555 char *pdata,
556 unsigned int total_data_size,
557 unsigned int *ret_data_size,
558 connection_struct *conn,
559 struct ea_list *ea_list)
561 uint8_t *p = (uint8_t *)pdata;
562 uint8_t *last_start = NULL;
563 bool do_store_data = (pdata != NULL);
565 *ret_data_size = 0;
567 if (!lp_ea_support(SNUM(conn))) {
568 return NT_STATUS_NO_EAS_ON_FILE;
571 for (; ea_list; ea_list = ea_list->next) {
572 size_t dos_namelen;
573 fstring dos_ea_name;
574 size_t this_size;
575 size_t pad = 0;
577 if (last_start != NULL && do_store_data) {
578 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
580 last_start = p;
582 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
583 dos_namelen = strlen(dos_ea_name);
584 if (dos_namelen > 255 || dos_namelen == 0) {
585 return NT_STATUS_INTERNAL_ERROR;
587 if (ea_list->ea.value.length > 65535) {
588 return NT_STATUS_INTERNAL_ERROR;
591 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
593 if (ea_list->next) {
594 pad = (4 - (this_size % 4)) % 4;
595 this_size += pad;
598 if (do_store_data) {
599 if (this_size > total_data_size) {
600 return NT_STATUS_INFO_LENGTH_MISMATCH;
603 /* We know we have room. */
604 SIVAL(p, 0x00, 0); /* next offset */
605 SCVAL(p, 0x04, ea_list->ea.flags);
606 SCVAL(p, 0x05, dos_namelen);
607 SSVAL(p, 0x06, ea_list->ea.value.length);
608 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
609 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
610 if (pad) {
611 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
612 '\0',
613 pad);
615 total_data_size -= this_size;
618 p += this_size;
621 *ret_data_size = PTR_DIFF(p, pdata);
622 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
623 return NT_STATUS_OK;
626 unsigned int estimate_ea_size(files_struct *fsp)
628 size_t total_ea_len = 0;
629 TALLOC_CTX *mem_ctx;
630 struct ea_list *ea_list = NULL;
631 NTSTATUS status;
633 /* symlink */
634 if (fsp == NULL) {
635 return 0;
638 if (!lp_ea_support(SNUM(fsp->conn))) {
639 return 0;
642 mem_ctx = talloc_stackframe();
644 /* If this is a stream fsp, then we need to instead find the
645 * estimated ea len from the main file, not the stream
646 * (streams cannot have EAs), but the estimate isn't just 0 in
647 * this case! */
648 fsp = metadata_fsp(fsp);
649 (void)get_ea_list_from_fsp(mem_ctx,
650 fsp,
651 &total_ea_len,
652 &ea_list);
654 if(conn_using_smb2(fsp->conn->sconn)) {
655 unsigned int ret_data_size;
657 * We're going to be using fill_ea_chained_buffer() to
658 * marshall EA's - this size is significantly larger
659 * than the SMB1 buffer. Re-calculate the size without
660 * marshalling.
662 status = fill_ea_chained_buffer(mem_ctx,
663 NULL,
665 &ret_data_size,
666 fsp->conn,
667 ea_list);
668 if (!NT_STATUS_IS_OK(status)) {
669 ret_data_size = 0;
671 total_ea_len = ret_data_size;
673 TALLOC_FREE(mem_ctx);
674 return total_ea_len;
677 /****************************************************************************
678 Ensure the EA name is case insensitive by matching any existing EA name.
679 ****************************************************************************/
681 static void canonicalize_ea_name(files_struct *fsp,
682 fstring unix_ea_name)
684 size_t total_ea_len;
685 TALLOC_CTX *mem_ctx = talloc_tos();
686 struct ea_list *ea_list;
687 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
688 fsp,
689 &total_ea_len,
690 &ea_list);
691 if (!NT_STATUS_IS_OK(status)) {
692 return;
695 for (; ea_list; ea_list = ea_list->next) {
696 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
697 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
698 &unix_ea_name[5], ea_list->ea.name));
699 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
700 break;
705 /****************************************************************************
706 Set or delete an extended attribute.
707 ****************************************************************************/
709 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
710 struct ea_list *ea_list)
712 NTSTATUS status;
713 bool posix_pathnames = false;
714 bool refuse;
716 if (!lp_ea_support(SNUM(conn))) {
717 return NT_STATUS_EAS_NOT_SUPPORTED;
720 if (fsp == NULL) {
721 return NT_STATUS_INVALID_HANDLE;
724 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
726 refuse = refuse_symlink_fsp(fsp);
727 if (refuse) {
728 return NT_STATUS_ACCESS_DENIED;
731 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
732 if (!NT_STATUS_IS_OK(status)) {
733 return status;
736 /* Setting EAs on streams isn't supported. */
737 if (fsp_is_alternate_stream(fsp)) {
738 return NT_STATUS_INVALID_PARAMETER;
742 * Filter out invalid Windows EA names - before
743 * we set *any* of them.
746 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
747 return STATUS_INVALID_EA_NAME;
750 for (;ea_list; ea_list = ea_list->next) {
751 int ret;
752 fstring unix_ea_name;
755 * Complementing the forward mapping from POSIX EAs to
756 * Windows EAs in get_ea_list_from_fsp(), here we map in the
757 * opposite direction from Windows EAs to the 'user' namespace
758 * of POSIX EAs. Hence, all POSIX EA names the we set here must
759 * start with a 'user.' prefix.
761 fstrcpy(unix_ea_name, "user.");
762 fstrcat(unix_ea_name, ea_list->ea.name);
764 canonicalize_ea_name(fsp, unix_ea_name);
766 DBG_DEBUG("ea_name %s ealen = %zu\n",
767 unix_ea_name,
768 ea_list->ea.value.length);
770 if (samba_private_attr_name(unix_ea_name)) {
771 DBG_DEBUG("ea name %s is a private Samba name.\n",
772 unix_ea_name);
773 return NT_STATUS_ACCESS_DENIED;
776 if (ea_list->ea.value.length == 0) {
777 /* Remove the attribute. */
778 DBG_DEBUG("deleting ea name %s on "
779 "file %s by file descriptor.\n",
780 unix_ea_name, fsp_str_dbg(fsp));
781 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
782 #ifdef ENOATTR
783 /* Removing a non existent attribute always succeeds. */
784 if (ret == -1 && errno == ENOATTR) {
785 DBG_DEBUG("deleting ea name %s didn't exist - "
786 "succeeding by default.\n",
787 unix_ea_name);
788 ret = 0;
790 #endif
791 } else {
792 DBG_DEBUG("setting ea name %s on file "
793 "%s by file descriptor.\n",
794 unix_ea_name,
795 fsp_str_dbg(fsp));
796 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
797 ea_list->ea.value.data, ea_list->ea.value.length, 0);
800 if (ret == -1) {
801 #ifdef ENOTSUP
802 if (errno == ENOTSUP) {
803 return NT_STATUS_EAS_NOT_SUPPORTED;
805 #endif
806 return map_nt_error_from_unix(errno);
810 return NT_STATUS_OK;
813 /****************************************************************************
814 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
815 ****************************************************************************/
817 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
819 struct ea_list *ea_list_head = NULL;
820 size_t offset = 0;
821 size_t bytes_used = 0;
823 while (offset < data_size) {
824 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
826 if (!eal) {
827 return NULL;
830 DLIST_ADD_END(ea_list_head, eal);
831 offset += bytes_used;
834 return ea_list_head;
837 /****************************************************************************
838 Count the total EA size needed.
839 ****************************************************************************/
841 static size_t ea_list_size(struct ea_list *ealist)
843 fstring dos_ea_name;
844 struct ea_list *listp;
845 size_t ret = 0;
847 for (listp = ealist; listp; listp = listp->next) {
848 push_ascii_fstring(dos_ea_name, listp->ea.name);
849 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
851 /* Add on 4 for total length. */
852 if (ret) {
853 ret += 4;
856 return ret;
859 /****************************************************************************
860 Return a union of EA's from a file list and a list of names.
861 The TALLOC context for the two lists *MUST* be identical as we steal
862 memory from one list to add to another. JRA.
863 ****************************************************************************/
865 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
867 struct ea_list *nlistp, *flistp;
869 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
870 for (flistp = file_list; flistp; flistp = flistp->next) {
871 if (strequal(nlistp->ea.name, flistp->ea.name)) {
872 break;
876 if (flistp) {
877 /* Copy the data from this entry. */
878 nlistp->ea.flags = flistp->ea.flags;
879 nlistp->ea.value = flistp->ea.value;
880 } else {
881 /* Null entry. */
882 nlistp->ea.flags = 0;
883 ZERO_STRUCT(nlistp->ea.value);
887 *total_ea_len = ea_list_size(name_list);
888 return name_list;
891 /****************************************************************************
892 Map wire perms onto standard UNIX permissions. Obey share restrictions.
893 ****************************************************************************/
895 NTSTATUS unix_perms_from_wire(connection_struct *conn,
896 const SMB_STRUCT_STAT *psbuf,
897 uint32_t perms,
898 mode_t *ret_perms)
900 mode_t ret = 0;
902 if (perms == SMB_MODE_NO_CHANGE) {
903 if (!VALID_STAT(*psbuf)) {
904 return NT_STATUS_INVALID_PARAMETER;
906 *ret_perms = psbuf->st_ex_mode;
907 return NT_STATUS_OK;
910 ret = wire_perms_to_unix(perms);
912 *ret_perms = ret;
913 return NT_STATUS_OK;
916 /****************************************************************************
917 Get a level dependent lanman2 dir entry.
918 ****************************************************************************/
920 struct smbd_dirptr_lanman2_state {
921 connection_struct *conn;
922 uint32_t info_level;
923 bool check_mangled_names;
924 bool case_sensitive;
927 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
928 void *private_data,
929 const char *dname,
930 const char *mask,
931 char **_fname)
933 struct smbd_dirptr_lanman2_state *state =
934 (struct smbd_dirptr_lanman2_state *)private_data;
935 bool ok;
936 char mangled_name[13]; /* mangled 8.3 name. */
937 bool got_match;
938 const char *fname;
940 /* Mangle fname if it's an illegal name. */
941 if (mangle_must_mangle(dname, state->conn->params)) {
943 * Slow path - ensure we can push the original name as UCS2. If
944 * not, then just don't return this name.
946 NTSTATUS status;
947 size_t ret_len = 0;
948 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
949 uint8_t *tmp = talloc_array(talloc_tos(),
950 uint8_t,
951 len);
953 status = srvstr_push(NULL,
954 FLAGS2_UNICODE_STRINGS,
955 tmp,
956 dname,
957 len,
958 STR_TERMINATE,
959 &ret_len);
961 TALLOC_FREE(tmp);
963 if (!NT_STATUS_IS_OK(status)) {
964 return false;
967 ok = name_to_8_3(dname, mangled_name,
968 true, state->conn->params);
969 if (!ok) {
970 return false;
972 fname = mangled_name;
973 } else {
974 fname = dname;
977 got_match = mask_match(fname, mask,
978 state->case_sensitive);
980 if(!got_match && state->check_mangled_names &&
981 !mangle_is_8_3(fname, false, state->conn->params)) {
983 * It turns out that NT matches wildcards against
984 * both long *and* short names. This may explain some
985 * of the wildcard weirdness from old DOS clients
986 * that some people have been seeing.... JRA.
988 /* Force the mangling into 8.3. */
989 ok = name_to_8_3(fname, mangled_name,
990 false, state->conn->params);
991 if (!ok) {
992 return false;
995 got_match = mask_match(mangled_name, mask,
996 state->case_sensitive);
999 if (!got_match) {
1000 return false;
1003 *_fname = talloc_strdup(ctx, fname);
1004 if (*_fname == NULL) {
1005 return false;
1008 return true;
1011 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1013 uint32_t ea_size = IO_REPARSE_TAG_DFS;
1015 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1016 (void)fsctl_get_reparse_tag(fsp, &ea_size);
1017 } else {
1018 ea_size = estimate_ea_size(fsp);
1021 return ea_size;
1024 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1025 connection_struct *conn,
1026 uint16_t flags2,
1027 uint32_t info_level,
1028 struct ea_list *name_list,
1029 bool check_mangled_names,
1030 bool requires_resume_key,
1031 uint32_t mode,
1032 const char *fname,
1033 const struct smb_filename *smb_fname,
1034 int space_remaining,
1035 uint8_t align,
1036 bool do_pad,
1037 char *base_data,
1038 char **ppdata,
1039 char *end_data,
1040 uint64_t *last_entry_off)
1042 char *p, *q, *pdata = *ppdata;
1043 uint32_t reskey=0;
1044 uint64_t file_size = 0;
1045 uint64_t allocation_size = 0;
1046 uint64_t file_id = 0;
1047 size_t len = 0;
1048 struct timespec mdate_ts = {0};
1049 struct timespec adate_ts = {0};
1050 struct timespec cdate_ts = {0};
1051 struct timespec create_date_ts = {0};
1052 char *nameptr;
1053 char *last_entry_ptr;
1054 bool was_8_3;
1055 int off;
1056 int pad = 0;
1057 NTSTATUS status;
1058 struct readdir_attr_data *readdir_attr_data = NULL;
1059 uint32_t ea_size;
1061 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1062 file_size = get_file_size_stat(&smb_fname->st);
1064 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1067 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1068 * a DFS symlink.
1070 if (smb_fname->fsp != NULL &&
1071 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1072 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1073 ctx,
1074 &readdir_attr_data);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1077 status)) {
1078 return status;
1083 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1085 mdate_ts = smb_fname->st.st_ex_mtime;
1086 adate_ts = smb_fname->st.st_ex_atime;
1087 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1088 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1090 if (lp_dos_filetime_resolution(SNUM(conn))) {
1091 dos_filetime_timespec(&create_date_ts);
1092 dos_filetime_timespec(&mdate_ts);
1093 dos_filetime_timespec(&adate_ts);
1094 dos_filetime_timespec(&cdate_ts);
1097 /* align the record */
1098 SMB_ASSERT(align >= 1);
1100 off = (int)PTR_DIFF(pdata, base_data);
1101 pad = (off + (align-1)) & ~(align-1);
1102 pad -= off;
1104 if (pad && pad > space_remaining) {
1105 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1106 "for padding (wanted %u, had %d)\n",
1107 (unsigned int)pad,
1108 space_remaining ));
1109 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1112 off += pad;
1113 /* initialize padding to 0 */
1114 if (pad) {
1115 memset(pdata, 0, pad);
1117 space_remaining -= pad;
1119 DBG_DEBUG("space_remaining = %d\n", space_remaining);
1121 pdata += pad;
1122 p = pdata;
1123 last_entry_ptr = p;
1125 pad = 0;
1126 off = 0;
1128 switch (info_level) {
1129 case SMB_FIND_INFO_STANDARD:
1130 DBG_DEBUG("SMB_FIND_INFO_STANDARD\n");
1131 if(requires_resume_key) {
1132 SIVAL(p,0,reskey);
1133 p += 4;
1135 srv_put_dos_date2_ts(p, 0, create_date_ts);
1136 srv_put_dos_date2_ts(p, 4, adate_ts);
1137 srv_put_dos_date2_ts(p, 8, mdate_ts);
1138 SIVAL(p,12,(uint32_t)file_size);
1139 SIVAL(p,16,(uint32_t)allocation_size);
1140 SSVAL(p,20,mode);
1141 p += 23;
1142 nameptr = p;
1143 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1144 p += ucs2_align(base_data, p, 0);
1146 status = srvstr_push(base_data, flags2, p,
1147 fname, PTR_DIFF(end_data, p),
1148 STR_TERMINATE, &len);
1149 if (!NT_STATUS_IS_OK(status)) {
1150 return status;
1152 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1153 if (len > 2) {
1154 SCVAL(nameptr, -1, len - 2);
1155 } else {
1156 SCVAL(nameptr, -1, 0);
1158 } else {
1159 if (len > 1) {
1160 SCVAL(nameptr, -1, len - 1);
1161 } else {
1162 SCVAL(nameptr, -1, 0);
1165 p += len;
1166 break;
1168 case SMB_FIND_EA_SIZE:
1169 DBG_DEBUG("SMB_FIND_EA_SIZE\n");
1170 if (requires_resume_key) {
1171 SIVAL(p,0,reskey);
1172 p += 4;
1174 srv_put_dos_date2_ts(p, 0, create_date_ts);
1175 srv_put_dos_date2_ts(p, 4, adate_ts);
1176 srv_put_dos_date2_ts(p, 8, mdate_ts);
1177 SIVAL(p,12,(uint32_t)file_size);
1178 SIVAL(p,16,(uint32_t)allocation_size);
1179 SSVAL(p,20,mode);
1181 ea_size = estimate_ea_size(smb_fname->fsp);
1182 SIVAL(p,22,ea_size); /* Extended attributes */
1184 p += 27;
1185 nameptr = p - 1;
1186 status = srvstr_push(base_data, flags2,
1187 p, fname, PTR_DIFF(end_data, p),
1188 STR_TERMINATE | STR_NOALIGN, &len);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 return status;
1192 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1193 if (len > 2) {
1194 len -= 2;
1195 } else {
1196 len = 0;
1198 } else {
1199 if (len > 1) {
1200 len -= 1;
1201 } else {
1202 len = 0;
1205 SCVAL(nameptr,0,len);
1206 p += len;
1207 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1208 break;
1210 case SMB_FIND_EA_LIST:
1212 struct ea_list *file_list = NULL;
1213 size_t ea_len = 0;
1215 DBG_DEBUG("SMB_FIND_EA_LIST\n");
1216 if (!name_list) {
1217 return NT_STATUS_INVALID_PARAMETER;
1219 if (requires_resume_key) {
1220 SIVAL(p,0,reskey);
1221 p += 4;
1223 srv_put_dos_date2_ts(p, 0, create_date_ts);
1224 srv_put_dos_date2_ts(p, 4, adate_ts);
1225 srv_put_dos_date2_ts(p, 8, mdate_ts);
1226 SIVAL(p,12,(uint32_t)file_size);
1227 SIVAL(p,16,(uint32_t)allocation_size);
1228 SSVAL(p,20,mode);
1229 p += 22; /* p now points to the EA area. */
1231 status = get_ea_list_from_fsp(ctx,
1232 smb_fname->fsp,
1233 &ea_len, &file_list);
1234 if (!NT_STATUS_IS_OK(status)) {
1235 file_list = NULL;
1237 name_list = ea_list_union(name_list, file_list, &ea_len);
1239 /* We need to determine if this entry will fit in the space available. */
1240 /* Max string size is 255 bytes. */
1241 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1242 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1243 "(wanted %u, had %d)\n",
1244 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1245 space_remaining ));
1246 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1249 /* Push the ea_data followed by the name. */
1250 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1251 nameptr = p;
1252 status = srvstr_push(base_data, flags2,
1253 p + 1, fname, PTR_DIFF(end_data, p+1),
1254 STR_TERMINATE | STR_NOALIGN, &len);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 return status;
1258 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1259 if (len > 2) {
1260 len -= 2;
1261 } else {
1262 len = 0;
1264 } else {
1265 if (len > 1) {
1266 len -= 1;
1267 } else {
1268 len = 0;
1271 SCVAL(nameptr,0,len);
1272 p += len + 1;
1273 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1274 break;
1277 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1278 DBG_DEBUG("SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n");
1279 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1280 p += 4;
1281 SIVAL(p,0,reskey); p += 4;
1282 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1283 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1284 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1285 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1286 SOFF_T(p,0,file_size); p += 8;
1287 SOFF_T(p,0,allocation_size); p += 8;
1288 SIVAL(p,0,mode); p += 4;
1289 q = p; p += 4; /* q is placeholder for name length. */
1290 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1291 SIVAL(p, 0, ea_size);
1292 p += 4;
1293 /* Clear the short name buffer. This is
1294 * IMPORTANT as not doing so will trigger
1295 * a Win2k client bug. JRA.
1297 if (!was_8_3 && check_mangled_names) {
1298 char mangled_name[13]; /* mangled 8.3 name. */
1299 if (!name_to_8_3(fname,mangled_name,True,
1300 conn->params)) {
1301 /* Error - mangle failed ! */
1302 memset(mangled_name,'\0',12);
1304 mangled_name[12] = 0;
1305 status = srvstr_push(base_data, flags2,
1306 p+2, mangled_name, 24,
1307 STR_UPPER|STR_UNICODE, &len);
1308 if (!NT_STATUS_IS_OK(status)) {
1309 return status;
1311 if (len < 24) {
1312 memset(p + 2 + len,'\0',24 - len);
1314 SSVAL(p, 0, len);
1315 } else {
1316 memset(p,'\0',26);
1318 p += 2 + 24;
1319 status = srvstr_push(base_data, flags2, p,
1320 fname, PTR_DIFF(end_data, p),
1321 STR_TERMINATE_ASCII, &len);
1322 if (!NT_STATUS_IS_OK(status)) {
1323 return status;
1325 SIVAL(q,0,len);
1326 p += len;
1328 len = PTR_DIFF(p, pdata);
1329 pad = (len + (align-1)) & ~(align-1);
1331 * offset to the next entry, the caller
1332 * will overwrite it for the last entry
1333 * that's why we always include the padding
1335 SIVAL(pdata,0,pad);
1337 * set padding to zero
1339 if (do_pad) {
1340 memset(p, 0, pad - len);
1341 p = pdata + pad;
1342 } else {
1343 p = pdata + len;
1345 break;
1347 case SMB_FIND_FILE_DIRECTORY_INFO:
1348 DBG_DEBUG("SMB_FIND_FILE_DIRECTORY_INFO\n");
1349 p += 4;
1350 SIVAL(p,0,reskey); p += 4;
1351 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1352 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1353 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1354 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1355 SOFF_T(p,0,file_size); p += 8;
1356 SOFF_T(p,0,allocation_size); p += 8;
1357 SIVAL(p,0,mode); p += 4;
1358 status = srvstr_push(base_data, flags2,
1359 p + 4, fname, PTR_DIFF(end_data, p+4),
1360 STR_TERMINATE_ASCII, &len);
1361 if (!NT_STATUS_IS_OK(status)) {
1362 return status;
1364 SIVAL(p,0,len);
1365 p += 4 + len;
1367 len = PTR_DIFF(p, pdata);
1368 pad = (len + (align-1)) & ~(align-1);
1370 * offset to the next entry, the caller
1371 * will overwrite it for the last entry
1372 * that's why we always include the padding
1374 SIVAL(pdata,0,pad);
1376 * set padding to zero
1378 if (do_pad) {
1379 memset(p, 0, pad - len);
1380 p = pdata + pad;
1381 } else {
1382 p = pdata + len;
1384 break;
1386 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1387 DBG_DEBUG("SMB_FIND_FILE_FULL_DIRECTORY_INFO\n");
1388 p += 4;
1389 SIVAL(p,0,reskey); p += 4;
1390 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1391 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1392 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1393 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1394 SOFF_T(p,0,file_size); p += 8;
1395 SOFF_T(p,0,allocation_size); p += 8;
1396 SIVAL(p,0,mode); p += 4;
1397 q = p; p += 4; /* q is placeholder for name length. */
1398 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1399 SIVAL(p, 0, ea_size);
1400 p +=4;
1401 status = srvstr_push(base_data, flags2, p,
1402 fname, PTR_DIFF(end_data, p),
1403 STR_TERMINATE_ASCII, &len);
1404 if (!NT_STATUS_IS_OK(status)) {
1405 return status;
1407 SIVAL(q, 0, len);
1408 p += len;
1410 len = PTR_DIFF(p, pdata);
1411 pad = (len + (align-1)) & ~(align-1);
1413 * offset to the next entry, the caller
1414 * will overwrite it for the last entry
1415 * that's why we always include the padding
1417 SIVAL(pdata,0,pad);
1419 * set padding to zero
1421 if (do_pad) {
1422 memset(p, 0, pad - len);
1423 p = pdata + pad;
1424 } else {
1425 p = pdata + len;
1427 break;
1429 case SMB_FIND_FILE_NAMES_INFO:
1430 DBG_DEBUG("SMB_FIND_FILE_NAMES_INFO\n");
1431 p += 4;
1432 SIVAL(p,0,reskey); p += 4;
1433 p += 4;
1434 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1435 acl on a dir (tridge) */
1436 status = srvstr_push(base_data, flags2, p,
1437 fname, PTR_DIFF(end_data, p),
1438 STR_TERMINATE_ASCII, &len);
1439 if (!NT_STATUS_IS_OK(status)) {
1440 return status;
1442 SIVAL(p, -4, len);
1443 p += len;
1445 len = PTR_DIFF(p, pdata);
1446 pad = (len + (align-1)) & ~(align-1);
1448 * offset to the next entry, the caller
1449 * will overwrite it for the last entry
1450 * that's why we always include the padding
1452 SIVAL(pdata,0,pad);
1454 * set padding to zero
1456 if (do_pad) {
1457 memset(p, 0, pad - len);
1458 p = pdata + pad;
1459 } else {
1460 p = pdata + len;
1462 break;
1464 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1465 DBG_DEBUG("SMB_FIND_ID_FULL_DIRECTORY_INFO\n");
1466 p += 4;
1467 SIVAL(p,0,reskey); p += 4;
1468 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1469 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1470 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1471 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1472 SOFF_T(p,0,file_size); p += 8;
1473 SOFF_T(p,0,allocation_size); p += 8;
1474 SIVAL(p,0,mode); p += 4;
1475 q = p; p += 4; /* q is placeholder for name length. */
1476 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1477 SIVAL(p, 0, ea_size);
1478 p += 4;
1479 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1480 SBVAL(p,0,file_id); p += 8;
1481 status = srvstr_push(base_data, flags2, p,
1482 fname, PTR_DIFF(end_data, p),
1483 STR_TERMINATE_ASCII, &len);
1484 if (!NT_STATUS_IS_OK(status)) {
1485 return status;
1487 SIVAL(q, 0, len);
1488 p += len;
1490 len = PTR_DIFF(p, pdata);
1491 pad = (len + (align-1)) & ~(align-1);
1493 * offset to the next entry, the caller
1494 * will overwrite it for the last entry
1495 * that's why we always include the padding
1497 SIVAL(pdata,0,pad);
1499 * set padding to zero
1501 if (do_pad) {
1502 memset(p, 0, pad - len);
1503 p = pdata + pad;
1504 } else {
1505 p = pdata + len;
1507 break;
1509 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1510 DBG_DEBUG("SMB_FIND_ID_BOTH_DIRECTORY_INFO\n");
1511 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1512 p += 4;
1513 SIVAL(p,0,reskey); p += 4;
1514 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1515 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1516 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1517 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1518 SOFF_T(p,0,file_size); p += 8;
1519 SOFF_T(p,0,allocation_size); p += 8;
1520 SIVAL(p,0,mode); p += 4;
1521 q = p; p += 4; /* q is placeholder for name length */
1522 if (readdir_attr_data &&
1523 readdir_attr_data->type == RDATTR_AAPL) {
1525 * OS X specific SMB2 extension negotiated via
1526 * AAPL create context: return max_access in
1527 * ea_size field.
1529 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1530 } else {
1531 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1533 SIVAL(p,0,ea_size); /* Extended attributes */
1534 p += 4;
1536 if (readdir_attr_data &&
1537 readdir_attr_data->type == RDATTR_AAPL) {
1539 * OS X specific SMB2 extension negotiated via
1540 * AAPL create context: return resource fork
1541 * length and compressed FinderInfo in
1542 * shortname field.
1544 * According to documentation short_name_len
1545 * should be 0, but on the wire behaviour
1546 * shows its set to 24 by clients.
1548 SSVAL(p, 0, 24);
1550 /* Resourefork length */
1551 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1553 /* Compressed FinderInfo */
1554 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1555 } else if (!was_8_3 && check_mangled_names) {
1556 char mangled_name[13]; /* mangled 8.3 name. */
1557 if (!name_to_8_3(fname,mangled_name,True,
1558 conn->params)) {
1559 /* Error - mangle failed ! */
1560 memset(mangled_name,'\0',12);
1562 mangled_name[12] = 0;
1563 status = srvstr_push(base_data, flags2,
1564 p+2, mangled_name, 24,
1565 STR_UPPER|STR_UNICODE, &len);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 return status;
1569 SSVAL(p, 0, len);
1570 if (len < 24) {
1571 memset(p + 2 + len,'\0',24 - len);
1573 SSVAL(p, 0, len);
1574 } else {
1575 /* Clear the short name buffer. This is
1576 * IMPORTANT as not doing so will trigger
1577 * a Win2k client bug. JRA.
1579 memset(p,'\0',26);
1581 p += 26;
1583 /* Reserved ? */
1584 if (readdir_attr_data &&
1585 readdir_attr_data->type == RDATTR_AAPL) {
1587 * OS X specific SMB2 extension negotiated via
1588 * AAPL create context: return UNIX mode in
1589 * reserved field.
1591 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1592 SSVAL(p, 0, aapl_mode);
1593 } else {
1594 SSVAL(p, 0, 0);
1596 p += 2;
1598 SBVAL(p,0,file_id); p += 8;
1599 status = srvstr_push(base_data, flags2, p,
1600 fname, PTR_DIFF(end_data, p),
1601 STR_TERMINATE_ASCII, &len);
1602 if (!NT_STATUS_IS_OK(status)) {
1603 return status;
1605 SIVAL(q,0,len);
1606 p += len;
1608 len = PTR_DIFF(p, pdata);
1609 pad = (len + (align-1)) & ~(align-1);
1611 * offset to the next entry, the caller
1612 * will overwrite it for the last entry
1613 * that's why we always include the padding
1615 SIVAL(pdata,0,pad);
1617 * set padding to zero
1619 if (do_pad) {
1620 memset(p, 0, pad - len);
1621 p = pdata + pad;
1622 } else {
1623 p = pdata + len;
1625 break;
1627 /* CIFS UNIX Extension. */
1629 case SMB_FIND_FILE_UNIX:
1630 case SMB_FIND_FILE_UNIX_INFO2:
1631 p+= 4;
1632 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1634 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1636 if (info_level == SMB_FIND_FILE_UNIX) {
1637 DBG_DEBUG("SMB_FIND_FILE_UNIX\n");
1638 p = store_file_unix_basic(conn, p,
1639 NULL, &smb_fname->st);
1640 status = srvstr_push(base_data, flags2, p,
1641 fname, PTR_DIFF(end_data, p),
1642 STR_TERMINATE, &len);
1643 if (!NT_STATUS_IS_OK(status)) {
1644 return status;
1646 } else {
1647 DBG_DEBUG("SMB_FIND_FILE_UNIX_INFO2\n");
1648 p = store_file_unix_basic_info2(conn, p,
1649 NULL, &smb_fname->st);
1650 nameptr = p;
1651 p += 4;
1652 status = srvstr_push(base_data, flags2, p, fname,
1653 PTR_DIFF(end_data, p), 0, &len);
1654 if (!NT_STATUS_IS_OK(status)) {
1655 return status;
1657 SIVAL(nameptr, 0, len);
1660 p += len;
1662 len = PTR_DIFF(p, pdata);
1663 pad = (len + (align-1)) & ~(align-1);
1665 * offset to the next entry, the caller
1666 * will overwrite it for the last entry
1667 * that's why we always include the padding
1669 SIVAL(pdata,0,pad);
1671 * set padding to zero
1673 if (do_pad) {
1674 memset(p, 0, pad - len);
1675 p = pdata + pad;
1676 } else {
1677 p = pdata + len;
1679 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1681 break;
1683 /* SMB2 UNIX Extension. */
1685 case SMB2_FILE_POSIX_INFORMATION:
1687 struct smb3_file_posix_information info = {};
1688 uint8_t buf[sizeof(info)];
1689 struct ndr_push ndr = {
1690 .data = buf,
1691 .alloc_size = sizeof(buf),
1692 .fixed_buf_size = true,
1694 enum ndr_err_code ndr_err;
1695 uint32_t tag = 0;
1697 DBG_DEBUG("SMB2_FILE_POSIX_INFORMATION\n");
1699 p+= 4;
1700 SIVAL(p,0,reskey); p+= 4;
1702 if (!conn_using_smb2(conn->sconn)) {
1703 return NT_STATUS_INVALID_LEVEL;
1706 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1707 status = fsctl_get_reparse_tag(smb_fname->fsp,
1708 &tag);
1709 if (!NT_STATUS_IS_OK(status)) {
1710 DBG_DEBUG("Could not get reparse "
1711 "tag for %s: %s\n",
1712 smb_fname_str_dbg(smb_fname),
1713 nt_errstr(status));
1714 return status;
1718 smb3_file_posix_information_init(
1719 conn, &smb_fname->st, tag, mode, &info);
1721 ndr_err = ndr_push_smb3_file_posix_information(
1722 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
1723 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1724 return NT_STATUS_INSUFFICIENT_RESOURCES;
1727 memcpy(p, buf, ndr.offset);
1728 p += ndr.offset;
1730 nameptr = p;
1731 p += 4;
1732 status = srvstr_push(base_data, flags2, p, fname,
1733 PTR_DIFF(end_data, p), 0, &len);
1734 if (!NT_STATUS_IS_OK(status)) {
1735 return status;
1737 SIVAL(nameptr, 0, len);
1739 p += len;
1741 len = PTR_DIFF(p, pdata);
1742 pad = (len + (align-1)) & ~(align-1);
1744 * offset to the next entry, the caller
1745 * will overwrite it for the last entry
1746 * that's why we always include the padding
1748 SIVAL(pdata,0,pad);
1749 break;
1752 default:
1753 return NT_STATUS_INVALID_LEVEL;
1756 if (PTR_DIFF(p,pdata) > space_remaining) {
1757 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1758 "(wanted %u, had %d)\n",
1759 (unsigned int)PTR_DIFF(p,pdata),
1760 space_remaining ));
1761 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1764 /* Setup the last entry pointer, as an offset from base_data */
1765 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1766 /* Advance the data pointer to the next slot */
1767 *ppdata = p;
1769 return NT_STATUS_OK;
1772 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1773 connection_struct *conn,
1774 struct dptr_struct *dirptr,
1775 uint16_t flags2,
1776 const char *path_mask,
1777 uint32_t dirtype,
1778 int info_level,
1779 int requires_resume_key,
1780 bool dont_descend,
1781 bool ask_sharemode,
1782 bool get_dosmode,
1783 uint8_t align,
1784 bool do_pad,
1785 char **ppdata,
1786 char *base_data,
1787 char *end_data,
1788 int space_remaining,
1789 struct smb_filename **_smb_fname,
1790 int *_last_entry_off,
1791 struct ea_list *name_list,
1792 struct file_id *file_id)
1794 const char *p;
1795 const char *mask = NULL;
1796 uint32_t mode = 0;
1797 char *fname = NULL;
1798 struct smb_filename *smb_fname = NULL;
1799 struct smbd_dirptr_lanman2_state state;
1800 bool ok;
1801 uint64_t last_entry_off = 0;
1802 NTSTATUS status;
1803 enum mangled_names_options mangled_names;
1804 bool marshall_with_83_names;
1806 mangled_names = lp_mangled_names(conn->params);
1808 ZERO_STRUCT(state);
1809 state.conn = conn;
1810 state.info_level = info_level;
1811 if (mangled_names != MANGLED_NAMES_NO) {
1812 state.check_mangled_names = true;
1814 state.case_sensitive = dptr_case_sensitive(dirptr);
1816 p = strrchr_m(path_mask,'/');
1817 if(p != NULL) {
1818 if(p[1] == '\0') {
1819 mask = "*.*";
1820 } else {
1821 mask = p+1;
1823 } else {
1824 mask = path_mask;
1827 ok = smbd_dirptr_get_entry(ctx,
1828 dirptr,
1829 mask,
1830 dirtype,
1831 dont_descend,
1832 ask_sharemode,
1833 get_dosmode,
1834 smbd_dirptr_lanman2_match_fn,
1835 &state,
1836 &fname,
1837 &smb_fname,
1838 &mode);
1839 if (!ok) {
1840 return NT_STATUS_END_OF_FILE;
1843 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1845 status = smbd_marshall_dir_entry(ctx,
1846 conn,
1847 flags2,
1848 info_level,
1849 name_list,
1850 marshall_with_83_names,
1851 requires_resume_key,
1852 mode,
1853 fname,
1854 smb_fname,
1855 space_remaining,
1856 align,
1857 do_pad,
1858 base_data,
1859 ppdata,
1860 end_data,
1861 &last_entry_off);
1862 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1863 DEBUG(1,("Conversion error: illegal character: %s\n",
1864 smb_fname_str_dbg(smb_fname)));
1867 if (file_id != NULL) {
1868 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1871 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1872 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1875 if (!NT_STATUS_IS_OK(status)) {
1876 TALLOC_FREE(smb_fname);
1877 TALLOC_FREE(fname);
1878 return status;
1881 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1883 if (_smb_fname != NULL) {
1885 * smb_fname is already talloc'ed off ctx.
1886 * We just need to make sure we don't return
1887 * any stream_name, and replace base_name
1888 * with fname in case base_name got mangled.
1889 * This allows us to preserve any smb_fname->fsp
1890 * for asynchronous handle lookups.
1892 TALLOC_FREE(smb_fname->stream_name);
1895 * smbd_dirptr_set_last_name_sent() above consumed
1896 * base_name
1898 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1900 if (smb_fname->base_name == NULL) {
1901 TALLOC_FREE(smb_fname);
1902 TALLOC_FREE(fname);
1903 return NT_STATUS_NO_MEMORY;
1905 *_smb_fname = smb_fname;
1906 } else {
1907 TALLOC_FREE(smb_fname);
1909 TALLOC_FREE(fname);
1911 *_last_entry_off = last_entry_off;
1912 return NT_STATUS_OK;
1915 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1917 const struct loadparm_substitution *lp_sub =
1918 loadparm_s3_global_substitution();
1920 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1921 return objid;
1924 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1926 SMB_ASSERT(extended_info != NULL);
1928 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1929 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1930 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1931 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1932 #ifdef SAMBA_VERSION_REVISION
1933 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1934 #endif
1935 extended_info->samba_subversion = 0;
1936 #ifdef SAMBA_VERSION_RC_RELEASE
1937 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1938 #else
1939 #ifdef SAMBA_VERSION_PRE_RELEASE
1940 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
1941 #endif
1942 #endif
1943 #ifdef SAMBA_VERSION_VENDOR_PATCH
1944 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
1945 #endif
1946 extended_info->samba_gitcommitdate = 0;
1947 #ifdef SAMBA_VERSION_COMMIT_TIME
1948 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
1949 #endif
1951 memset(extended_info->samba_version_string, 0,
1952 sizeof(extended_info->samba_version_string));
1954 snprintf (extended_info->samba_version_string,
1955 sizeof(extended_info->samba_version_string),
1956 "%s", samba_version_string());
1959 static bool fsinfo_unix_valid_level(connection_struct *conn,
1960 struct files_struct *fsp,
1961 uint16_t info_level)
1963 if (conn_using_smb2(conn->sconn) &&
1964 fsp->fsp_flags.posix_open &&
1965 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL)
1967 return true;
1969 #if defined(SMB1SERVER)
1970 if (lp_smb1_unix_extensions() &&
1971 info_level == SMB_QUERY_POSIX_FS_INFO) {
1972 return true;
1974 #endif
1975 return false;
1979 * fsp is only valid for SMB2.
1981 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
1982 connection_struct *conn,
1983 TALLOC_CTX *mem_ctx,
1984 uint16_t info_level,
1985 uint16_t flags2,
1986 unsigned int max_data_bytes,
1987 size_t *fixed_portion,
1988 struct files_struct *fsp,
1989 struct smb_filename *fname,
1990 char **ppdata,
1991 int *ret_data_len)
1993 const struct loadparm_substitution *lp_sub =
1994 loadparm_s3_global_substitution();
1995 char *pdata, *end_data;
1996 int data_len = 0;
1997 size_t len = 0;
1998 const char *vname = volume_label(talloc_tos(), SNUM(conn));
1999 int snum = SNUM(conn);
2000 const char *fstype = lp_fstype(SNUM(conn));
2001 const char *filename = NULL;
2002 uint64_t bytes_per_sector = 512;
2003 struct smb_filename smb_fname;
2004 SMB_STRUCT_STAT st;
2005 NTSTATUS status = NT_STATUS_OK;
2006 uint64_t df_ret;
2007 uint32_t serial;
2009 if (fname == NULL || fname->base_name == NULL) {
2010 filename = ".";
2011 } else {
2012 filename = fname->base_name;
2015 if (IS_IPC(conn)) {
2016 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2017 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2018 "info level (0x%x) on IPC$.\n",
2019 (unsigned int)info_level));
2020 return NT_STATUS_ACCESS_DENIED;
2024 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2026 smb_fname = (struct smb_filename) {
2027 .base_name = discard_const_p(char, filename),
2028 .flags = fname ? fname->flags : 0,
2029 .twrp = fname ? fname->twrp : 0,
2032 if(info_level != SMB_FS_QUOTA_INFORMATION
2033 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2034 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2035 return map_nt_error_from_unix(errno);
2038 st = smb_fname.st;
2040 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2041 return NT_STATUS_INVALID_PARAMETER;
2044 *ppdata = (char *)SMB_REALLOC(
2045 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2046 if (*ppdata == NULL) {
2047 return NT_STATUS_NO_MEMORY;
2050 pdata = *ppdata;
2051 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2052 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2054 *fixed_portion = 0;
2056 switch (info_level) {
2057 case SMB_INFO_ALLOCATION:
2059 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2060 data_len = 18;
2061 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2062 &dfree, &dsize);
2063 if (df_ret == (uint64_t)-1) {
2064 return map_nt_error_from_unix(errno);
2067 block_size = lp_block_size(snum);
2068 if (bsize < block_size) {
2069 uint64_t factor = block_size/bsize;
2070 bsize = block_size;
2071 dsize /= factor;
2072 dfree /= factor;
2074 if (bsize > block_size) {
2075 uint64_t factor = bsize/block_size;
2076 bsize = block_size;
2077 dsize *= factor;
2078 dfree *= factor;
2080 sectors_per_unit = bsize/bytes_per_sector;
2082 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2083 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2084 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2087 * For large drives, return max values and not modulo.
2089 dsize = MIN(dsize, UINT32_MAX);
2090 dfree = MIN(dfree, UINT32_MAX);
2092 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2093 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2094 SIVAL(pdata,l1_cUnit,dsize);
2095 SIVAL(pdata,l1_cUnitAvail,dfree);
2096 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2097 break;
2100 case SMB_INFO_VOLUME:
2101 /* Return volume name */
2103 * Add volume serial number - hash of a combination of
2104 * the called hostname and the service name.
2106 serial = generate_volume_serial_number(lp_sub, snum);
2107 SIVAL(pdata,0,serial);
2109 * Win2k3 and previous mess this up by sending a name length
2110 * one byte short. I believe only older clients (OS/2 Win9x) use
2111 * this call so try fixing this by adding a terminating null to
2112 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2114 status = srvstr_push(
2115 pdata, flags2,
2116 pdata+l2_vol_szVolLabel, vname,
2117 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2118 STR_NOALIGN|STR_TERMINATE, &len);
2119 if (!NT_STATUS_IS_OK(status)) {
2120 return status;
2122 SCVAL(pdata,l2_vol_cch,len);
2123 data_len = l2_vol_szVolLabel + len;
2124 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2125 "name = %s serial = 0x%04"PRIx32"\n",
2126 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2127 (unsigned)len, vname, serial));
2128 break;
2130 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2131 case SMB_FS_ATTRIBUTE_INFORMATION:
2133 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2134 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2135 conn->fs_capabilities); /* FS ATTRIBUTES */
2137 SIVAL(pdata,4,255); /* Max filename component length */
2138 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2139 and will think we can't do long filenames */
2140 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2141 PTR_DIFF(end_data, pdata+12),
2142 STR_UNICODE, &len);
2143 if (!NT_STATUS_IS_OK(status)) {
2144 return status;
2146 SIVAL(pdata,8,len);
2147 data_len = 12 + len;
2148 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2149 /* the client only requested a portion of the
2150 file system name */
2151 data_len = max_data_bytes;
2152 status = STATUS_BUFFER_OVERFLOW;
2154 *fixed_portion = 16;
2155 break;
2157 case SMB_QUERY_FS_LABEL_INFO:
2158 case SMB_FS_LABEL_INFORMATION:
2159 status = srvstr_push(pdata, flags2, pdata+4, vname,
2160 PTR_DIFF(end_data, pdata+4), 0, &len);
2161 if (!NT_STATUS_IS_OK(status)) {
2162 return status;
2164 data_len = 4 + len;
2165 SIVAL(pdata,0,len);
2166 break;
2168 case SMB_QUERY_FS_VOLUME_INFO:
2169 case SMB_FS_VOLUME_INFORMATION:
2170 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2171 pdata, &st.st_ex_btime);
2173 * Add volume serial number - hash of a combination of
2174 * the called hostname and the service name.
2176 serial = generate_volume_serial_number(lp_sub, snum);
2177 SIVAL(pdata,8,serial);
2179 /* Max label len is 32 characters. */
2180 status = srvstr_push(pdata, flags2, pdata+18, vname,
2181 PTR_DIFF(end_data, pdata+18),
2182 STR_UNICODE, &len);
2183 if (!NT_STATUS_IS_OK(status)) {
2184 return status;
2186 SIVAL(pdata,12,len);
2187 data_len = 18+len;
2189 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2190 "namelen = %d, vol=%s serv=%s "
2191 "serial=0x%04"PRIx32"\n",
2192 (int)strlen(vname),vname,
2193 lp_servicename(talloc_tos(), lp_sub, snum),
2194 serial));
2195 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2196 /* the client only requested a portion of the
2197 volume label */
2198 data_len = max_data_bytes;
2199 status = STATUS_BUFFER_OVERFLOW;
2201 *fixed_portion = 24;
2202 break;
2204 case SMB_QUERY_FS_SIZE_INFO:
2205 case SMB_FS_SIZE_INFORMATION:
2207 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2208 data_len = 24;
2209 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2210 &dfree, &dsize);
2211 if (df_ret == (uint64_t)-1) {
2212 return map_nt_error_from_unix(errno);
2214 block_size = lp_block_size(snum);
2215 if (bsize < block_size) {
2216 uint64_t factor = block_size/bsize;
2217 bsize = block_size;
2218 dsize /= factor;
2219 dfree /= factor;
2221 if (bsize > block_size) {
2222 uint64_t factor = bsize/block_size;
2223 bsize = block_size;
2224 dsize *= factor;
2225 dfree *= factor;
2227 sectors_per_unit = bsize/bytes_per_sector;
2228 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2229 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2230 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2231 SBIG_UINT(pdata,0,dsize);
2232 SBIG_UINT(pdata,8,dfree);
2233 SIVAL(pdata,16,sectors_per_unit);
2234 SIVAL(pdata,20,bytes_per_sector);
2235 *fixed_portion = 24;
2236 break;
2239 case SMB_FS_FULL_SIZE_INFORMATION:
2241 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2242 data_len = 32;
2243 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2244 &dfree, &dsize);
2245 if (df_ret == (uint64_t)-1) {
2246 return map_nt_error_from_unix(errno);
2248 block_size = lp_block_size(snum);
2249 if (bsize < block_size) {
2250 uint64_t factor = block_size/bsize;
2251 bsize = block_size;
2252 dsize /= factor;
2253 dfree /= factor;
2255 if (bsize > block_size) {
2256 uint64_t factor = bsize/block_size;
2257 bsize = block_size;
2258 dsize *= factor;
2259 dfree *= factor;
2261 sectors_per_unit = bsize/bytes_per_sector;
2262 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2263 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2264 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2265 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2266 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2267 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2268 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2269 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2270 *fixed_portion = 32;
2271 break;
2274 case SMB_QUERY_FS_DEVICE_INFO:
2275 case SMB_FS_DEVICE_INFORMATION:
2277 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2279 if (!CAN_WRITE(conn)) {
2280 characteristics |= FILE_READ_ONLY_DEVICE;
2282 data_len = 8;
2283 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2284 SIVAL(pdata,4,characteristics);
2285 *fixed_portion = 8;
2286 break;
2289 #ifdef HAVE_SYS_QUOTAS
2290 case SMB_FS_QUOTA_INFORMATION:
2292 * what we have to send --metze:
2294 * Unknown1: 24 NULL bytes
2295 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2296 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2297 * Quota Flags: 2 byte :
2298 * Unknown3: 6 NULL bytes
2300 * 48 bytes total
2302 * details for Quota Flags:
2304 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2305 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2306 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2307 * 0x0001 Enable Quotas: enable quota for this fs
2311 /* we need to fake up a fsp here,
2312 * because its not send in this call
2314 files_struct tmpfsp = {
2315 .conn = conn,
2316 .fnum = FNUM_FIELD_INVALID,
2318 SMB_NTQUOTA_STRUCT quotas = {};
2320 /* access check */
2321 if (get_current_uid(conn) != 0) {
2322 DEBUG(0,("get_user_quota: access_denied "
2323 "service [%s] user [%s]\n",
2324 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2325 conn->session_info->unix_info->unix_name));
2326 return NT_STATUS_ACCESS_DENIED;
2329 status = vfs_get_ntquota(&tmpfsp, SMB_USER_FS_QUOTA_TYPE,
2330 NULL, &quotas);
2331 if (!NT_STATUS_IS_OK(status)) {
2332 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2333 return status;
2336 data_len = 48;
2338 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2339 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2341 /* Unknown1 24 NULL bytes*/
2342 SBIG_UINT(pdata,0,(uint64_t)0);
2343 SBIG_UINT(pdata,8,(uint64_t)0);
2344 SBIG_UINT(pdata,16,(uint64_t)0);
2346 /* Default Soft Quota 8 bytes */
2347 SBIG_UINT(pdata,24,quotas.softlim);
2349 /* Default Hard Quota 8 bytes */
2350 SBIG_UINT(pdata,32,quotas.hardlim);
2352 /* Quota flag 2 bytes */
2353 SSVAL(pdata,40,quotas.qflags);
2355 /* Unknown3 6 NULL bytes */
2356 SSVAL(pdata,42,0);
2357 SIVAL(pdata,44,0);
2359 break;
2361 #endif /* HAVE_SYS_QUOTAS */
2362 case SMB_FS_OBJECTID_INFORMATION:
2364 unsigned char objid[16];
2365 struct smb_extended_info extended_info;
2366 memcpy(pdata,create_volume_objectid(conn, objid),16);
2367 samba_extended_info_version (&extended_info);
2368 SIVAL(pdata,16,extended_info.samba_magic);
2369 SIVAL(pdata,20,extended_info.samba_version);
2370 SIVAL(pdata,24,extended_info.samba_subversion);
2371 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2372 memcpy(pdata+36,extended_info.samba_version_string,28);
2373 data_len = 64;
2374 break;
2377 case SMB_FS_SECTOR_SIZE_INFORMATION:
2379 uint32_t bps_logical = lp_parm_ulong(
2380 SNUM(conn),
2381 "fs", "logical bytes per sector",
2382 bytes_per_sector);
2383 uint32_t bps_aligned = lp_parm_ulong(
2384 SNUM(conn),
2385 "fs", "aligned bytes per sector",
2386 bytes_per_sector);
2387 uint32_t bps_performance = lp_parm_ulong(
2388 SNUM(conn),
2389 "fs", "performance bytes per sector",
2390 bytes_per_sector);
2391 uint32_t bps_effective = lp_parm_ulong(
2392 SNUM(conn),
2393 "fs", "effective aligned bytes per sector",
2394 bytes_per_sector);
2396 data_len = 28;
2398 * These values match a physical Windows Server 2012
2399 * share backed by NTFS atop spinning rust.
2401 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2402 /* logical_bytes_per_sector */
2403 SIVAL(pdata, 0, bps_logical);
2404 /* phys_bytes_per_sector_atomic */
2405 SIVAL(pdata, 4, bps_aligned);
2406 /* phys_bytes_per_sector_perf */
2407 SIVAL(pdata, 8, bps_performance);
2408 /* fs_effective_phys_bytes_per_sector_atomic */
2409 SIVAL(pdata, 12, bps_effective);
2410 /* flags */
2411 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2412 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2413 /* byte_off_sector_align */
2414 SIVAL(pdata, 20, 0);
2415 /* byte_off_partition_align */
2416 SIVAL(pdata, 24, 0);
2417 *fixed_portion = 28;
2418 break;
2422 #if defined(WITH_SMB1SERVER)
2424 * Query the version and capabilities of the CIFS UNIX extensions
2425 * in use.
2428 case SMB_QUERY_CIFS_UNIX_INFO:
2430 bool large_write = lp_min_receive_file_size() &&
2431 !smb1_srv_is_signing_active(xconn);
2432 bool large_read = !smb1_srv_is_signing_active(xconn);
2433 int encrypt_caps = 0;
2435 if (!lp_smb1_unix_extensions()) {
2436 return NT_STATUS_INVALID_LEVEL;
2439 switch (conn->encrypt_level) {
2440 case SMB_SIGNING_OFF:
2441 encrypt_caps = 0;
2442 break;
2443 case SMB_SIGNING_DESIRED:
2444 case SMB_SIGNING_IF_REQUIRED:
2445 case SMB_SIGNING_DEFAULT:
2446 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2447 break;
2448 case SMB_SIGNING_REQUIRED:
2449 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2450 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2451 large_write = false;
2452 large_read = false;
2453 break;
2456 data_len = 12;
2457 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2458 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2460 /* We have POSIX ACLs, pathname, encryption,
2461 * large read/write, and locking capability. */
2463 SBIG_UINT(pdata,4,((uint64_t)(
2464 CIFS_UNIX_POSIX_ACLS_CAP|
2465 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2466 CIFS_UNIX_FCNTL_LOCKS_CAP|
2467 CIFS_UNIX_EXTATTR_CAP|
2468 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2469 encrypt_caps|
2470 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2471 (large_write ?
2472 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2473 break;
2475 #endif
2477 case SMB_QUERY_POSIX_FS_INFO:
2478 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2480 int rc;
2481 struct vfs_statvfs_struct svfs;
2483 if (!fsinfo_unix_valid_level(conn, fsp, info_level)) {
2484 return NT_STATUS_INVALID_LEVEL;
2487 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2489 if (!rc) {
2490 data_len = 56;
2491 SIVAL(pdata,0,svfs.OptimalTransferSize);
2492 SIVAL(pdata,4,svfs.BlockSize);
2493 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2494 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2495 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2496 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2497 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2498 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2499 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO successful\n"));
2500 #ifdef EOPNOTSUPP
2501 } else if (rc == EOPNOTSUPP) {
2502 return NT_STATUS_INVALID_LEVEL;
2503 #endif /* EOPNOTSUPP */
2504 } else {
2505 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2506 return NT_STATUS_DOS(ERRSRV, ERRerror);
2508 break;
2511 case SMB_QUERY_POSIX_WHOAMI:
2513 uint32_t flags = 0;
2514 uint32_t sid_bytes;
2515 uint32_t i;
2517 if (!lp_smb1_unix_extensions()) {
2518 return NT_STATUS_INVALID_LEVEL;
2521 if (max_data_bytes < 40) {
2522 return NT_STATUS_BUFFER_TOO_SMALL;
2525 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2526 flags |= SMB_WHOAMI_GUEST;
2529 /* NOTE: 8 bytes for UID/GID, irrespective of native
2530 * platform size. This matches
2531 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2533 data_len = 4 /* flags */
2534 + 4 /* flag mask */
2535 + 8 /* uid */
2536 + 8 /* gid */
2537 + 4 /* ngroups */
2538 + 4 /* num_sids */
2539 + 4 /* SID bytes */
2540 + 4 /* pad/reserved */
2541 + (conn->session_info->unix_token->ngroups * 8)
2542 /* groups list */
2543 + (conn->session_info->security_token->num_sids *
2544 SID_MAX_SIZE)
2545 /* SID list */;
2547 SIVAL(pdata, 0, flags);
2548 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2549 SBIG_UINT(pdata, 8,
2550 (uint64_t)conn->session_info->unix_token->uid);
2551 SBIG_UINT(pdata, 16,
2552 (uint64_t)conn->session_info->unix_token->gid);
2555 if (data_len >= max_data_bytes) {
2556 /* Potential overflow, skip the GIDs and SIDs. */
2558 SIVAL(pdata, 24, 0); /* num_groups */
2559 SIVAL(pdata, 28, 0); /* num_sids */
2560 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2561 SIVAL(pdata, 36, 0); /* reserved */
2563 data_len = 40;
2564 break;
2567 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2568 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2570 /* We walk the SID list twice, but this call is fairly
2571 * infrequent, and I don't expect that it's performance
2572 * sensitive -- jpeach
2574 for (i = 0, sid_bytes = 0;
2575 i < conn->session_info->security_token->num_sids; ++i) {
2576 sid_bytes += ndr_size_dom_sid(
2577 &conn->session_info->security_token->sids[i],
2581 /* SID list byte count */
2582 SIVAL(pdata, 32, sid_bytes);
2584 /* 4 bytes pad/reserved - must be zero */
2585 SIVAL(pdata, 36, 0);
2586 data_len = 40;
2588 /* GID list */
2589 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2590 SBIG_UINT(pdata, data_len,
2591 (uint64_t)conn->session_info->unix_token->groups[i]);
2592 data_len += 8;
2595 /* SID list */
2596 for (i = 0;
2597 i < conn->session_info->security_token->num_sids; ++i) {
2598 int sid_len = ndr_size_dom_sid(
2599 &conn->session_info->security_token->sids[i],
2602 sid_linearize((uint8_t *)(pdata + data_len),
2603 sid_len,
2604 &conn->session_info->security_token->sids[i]);
2605 data_len += sid_len;
2608 break;
2611 case SMB_MAC_QUERY_FS_INFO:
2613 * Thursby MAC extension... ONLY on NTFS filesystems
2614 * once we do streams then we don't need this
2616 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2617 data_len = 88;
2618 SIVAL(pdata,84,0x100); /* Don't support mac... */
2619 break;
2622 FALL_THROUGH;
2623 default:
2624 return NT_STATUS_INVALID_LEVEL;
2627 *ret_data_len = data_len;
2628 return status;
2631 NTSTATUS smb_set_fsquota(connection_struct *conn,
2632 struct smb_request *req,
2633 files_struct *fsp,
2634 const DATA_BLOB *qdata)
2636 const struct loadparm_substitution *lp_sub =
2637 loadparm_s3_global_substitution();
2638 NTSTATUS status;
2639 SMB_NTQUOTA_STRUCT quotas;
2641 ZERO_STRUCT(quotas);
2643 /* access check */
2644 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2645 DBG_NOTICE("access_denied service [%s] user [%s]\n",
2646 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2647 conn->session_info->unix_info->unix_name);
2648 return NT_STATUS_ACCESS_DENIED;
2651 if (!check_fsp_ntquota_handle(conn, req,
2652 fsp)) {
2653 DBG_WARNING("no valid QUOTA HANDLE\n");
2654 return NT_STATUS_INVALID_HANDLE;
2657 /* note: normally there're 48 bytes,
2658 * but we didn't use the last 6 bytes for now
2659 * --metze
2661 if (qdata->length < 42) {
2662 DBG_ERR("requires total_data(%zu) >= 42 bytes!\n",
2663 qdata->length);
2664 return NT_STATUS_INVALID_PARAMETER;
2667 /* unknown_1 24 NULL bytes in pdata*/
2669 /* the soft quotas 8 bytes (uint64_t)*/
2670 quotas.softlim = BVAL(qdata->data,24);
2672 /* the hard quotas 8 bytes (uint64_t)*/
2673 quotas.hardlim = BVAL(qdata->data,32);
2675 /* quota_flags 2 bytes **/
2676 quotas.qflags = SVAL(qdata->data,40);
2678 /* unknown_2 6 NULL bytes follow*/
2680 /* now set the quotas */
2681 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2682 DBG_WARNING("vfs_set_ntquota() failed for service [%s]\n",
2683 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)));
2684 status = map_nt_error_from_unix(errno);
2685 } else {
2686 status = NT_STATUS_OK;
2688 return status;
2691 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2692 struct smb_request *req,
2693 TALLOC_CTX *mem_ctx,
2694 uint16_t info_level,
2695 files_struct *fsp,
2696 const DATA_BLOB *pdata)
2698 switch (info_level) {
2699 case SMB_FS_QUOTA_INFORMATION:
2701 return smb_set_fsquota(conn,
2702 req,
2703 fsp,
2704 pdata);
2707 default:
2708 break;
2710 return NT_STATUS_INVALID_LEVEL;
2713 /****************************************************************************
2714 Store the FILE_UNIX_BASIC info.
2715 ****************************************************************************/
2717 char *store_file_unix_basic(connection_struct *conn,
2718 char *pdata,
2719 files_struct *fsp,
2720 const SMB_STRUCT_STAT *psbuf)
2722 dev_t devno;
2724 DBG_DEBUG("SMB_QUERY_FILE_UNIX_BASIC\n");
2725 DBG_NOTICE("st_mode=%o\n", (int)psbuf->st_ex_mode);
2727 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2728 pdata += 8;
2730 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2731 pdata += 8;
2733 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2734 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2735 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2736 pdata += 24;
2738 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2739 SIVAL(pdata,4,0);
2740 pdata += 8;
2742 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2743 SIVAL(pdata,4,0);
2744 pdata += 8;
2746 SIVAL(pdata, 0, unix_filetype_to_wire(psbuf->st_ex_mode));
2747 pdata += 4;
2749 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2750 devno = psbuf->st_ex_rdev;
2751 } else {
2752 devno = psbuf->st_ex_dev;
2755 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2756 SIVAL(pdata,4,0);
2757 pdata += 8;
2759 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2760 SIVAL(pdata,4,0);
2761 pdata += 8;
2763 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2764 pdata += 8;
2766 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2767 SIVAL(pdata,4,0);
2768 pdata += 8;
2770 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2771 SIVAL(pdata,4,0);
2772 pdata += 8;
2774 return pdata;
2777 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2778 * the chflags(2) (or equivalent) flags.
2780 * XXX: this really should be behind the VFS interface. To do this, we would
2781 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2782 * Each VFS module could then implement its own mapping as appropriate for the
2783 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2785 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2786 info2_flags_map[] =
2788 #ifdef UF_NODUMP
2789 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2790 #endif
2792 #ifdef UF_IMMUTABLE
2793 { UF_IMMUTABLE, EXT_IMMUTABLE },
2794 #endif
2796 #ifdef UF_APPEND
2797 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2798 #endif
2800 #ifdef UF_HIDDEN
2801 { UF_HIDDEN, EXT_HIDDEN },
2802 #endif
2804 /* Do not remove. We need to guarantee that this array has at least one
2805 * entry to build on HP-UX.
2807 { 0, 0 }
2811 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2812 uint32_t *smb_fflags, uint32_t *smb_fmask)
2814 size_t i;
2816 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2817 *smb_fmask |= info2_flags_map[i].smb_fflag;
2818 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2819 *smb_fflags |= info2_flags_map[i].smb_fflag;
2824 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2825 const uint32_t smb_fflags,
2826 const uint32_t smb_fmask,
2827 int *stat_fflags)
2829 uint32_t max_fmask = 0;
2830 size_t i;
2832 *stat_fflags = psbuf->st_ex_flags;
2834 /* For each flags requested in smb_fmask, check the state of the
2835 * corresponding flag in smb_fflags and set or clear the matching
2836 * stat flag.
2839 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2840 max_fmask |= info2_flags_map[i].smb_fflag;
2841 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2842 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2843 *stat_fflags |= info2_flags_map[i].stat_fflag;
2844 } else {
2845 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2850 /* If smb_fmask is asking to set any bits that are not supported by
2851 * our flag mappings, we should fail.
2853 if ((smb_fmask & max_fmask) != smb_fmask) {
2854 return False;
2857 return True;
2861 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2862 * of file flags and birth (create) time.
2864 char *store_file_unix_basic_info2(connection_struct *conn,
2865 char *pdata,
2866 files_struct *fsp,
2867 const SMB_STRUCT_STAT *psbuf)
2869 uint32_t file_flags = 0;
2870 uint32_t flags_mask = 0;
2872 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2874 /* Create (birth) time 64 bit */
2875 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2876 pdata += 8;
2878 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2879 SIVAL(pdata, 0, file_flags); /* flags */
2880 SIVAL(pdata, 4, flags_mask); /* mask */
2881 pdata += 8;
2883 return pdata;
2886 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2887 const struct stream_struct *streams,
2888 char *data,
2889 unsigned int max_data_bytes,
2890 unsigned int *data_size)
2892 unsigned int i;
2893 unsigned int ofs = 0;
2895 if (max_data_bytes < 32) {
2896 return NT_STATUS_INFO_LENGTH_MISMATCH;
2899 for (i = 0; i < num_streams; i++) {
2900 unsigned int next_offset;
2901 size_t namelen;
2902 smb_ucs2_t *namebuf;
2904 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2905 streams[i].name, &namelen) ||
2906 namelen <= 2)
2908 return NT_STATUS_INVALID_PARAMETER;
2912 * name_buf is now null-terminated, we need to marshall as not
2913 * terminated
2916 namelen -= 2;
2919 * We cannot overflow ...
2921 if ((ofs + 24 + namelen) > max_data_bytes) {
2922 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2923 i));
2924 TALLOC_FREE(namebuf);
2925 return STATUS_BUFFER_OVERFLOW;
2928 SIVAL(data, ofs+4, namelen);
2929 SOFF_T(data, ofs+8, streams[i].size);
2930 SOFF_T(data, ofs+16, streams[i].alloc_size);
2931 memcpy(data+ofs+24, namebuf, namelen);
2932 TALLOC_FREE(namebuf);
2934 next_offset = ofs + 24 + namelen;
2936 if (i == num_streams-1) {
2937 SIVAL(data, ofs, 0);
2939 else {
2940 unsigned int align = ndr_align_size(next_offset, 8);
2942 if ((next_offset + align) > max_data_bytes) {
2943 DEBUG(10, ("refusing to overflow align "
2944 "reply at stream %u\n",
2945 i));
2946 TALLOC_FREE(namebuf);
2947 return STATUS_BUFFER_OVERFLOW;
2950 memset(data+next_offset, 0, align);
2951 next_offset += align;
2953 SIVAL(data, ofs, next_offset - ofs);
2954 ofs = next_offset;
2957 ofs = next_offset;
2960 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
2962 *data_size = ofs;
2964 return NT_STATUS_OK;
2967 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
2968 TALLOC_CTX *mem_ctx,
2969 struct smb_request *req,
2970 uint16_t info_level,
2971 files_struct *fsp,
2972 struct smb_filename *smb_fname,
2973 bool delete_pending,
2974 struct timespec write_time_ts,
2975 struct ea_list *ea_list,
2976 uint16_t flags2,
2977 unsigned int max_data_bytes,
2978 size_t *fixed_portion,
2979 char **ppdata,
2980 unsigned int *pdata_size)
2982 char *pdata = *ppdata;
2983 char *dstart, *dend;
2984 unsigned int data_size;
2985 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
2986 SMB_STRUCT_STAT *psbuf = NULL;
2987 SMB_STRUCT_STAT *base_sp = NULL;
2988 char *p;
2989 char *base_name;
2990 char *dos_fname;
2991 int mode;
2992 int nlink;
2993 NTSTATUS status;
2994 uint64_t file_size = 0;
2995 uint64_t pos = 0;
2996 uint64_t allocation_size = 0;
2997 uint64_t file_id = 0;
2998 uint32_t access_mask = 0;
2999 size_t len = 0;
3001 if (INFO_LEVEL_IS_UNIX(info_level)) {
3002 bool ok = false;
3004 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3005 DBG_DEBUG("SMB1 unix extensions activated\n");
3006 ok = true;
3009 if (conn_using_smb2(conn->sconn) &&
3010 fsp->fsp_flags.posix_open)
3012 DBG_DEBUG("SMB2 posix open\n");
3013 ok = true;
3016 if (!ok) {
3017 return NT_STATUS_INVALID_LEVEL;
3021 DBG_INFO("%s (%s) level=%d max_data=%u\n",
3022 smb_fname_str_dbg(smb_fname),
3023 fsp_fnum_dbg(fsp),
3024 info_level, max_data_bytes);
3027 * In case of querying a symlink in POSIX context,
3028 * fsp will be NULL. fdos_mode() deals with it.
3030 if (fsp != NULL) {
3031 smb_fname = fsp->fsp_name;
3033 mode = fdos_mode(fsp);
3034 psbuf = &smb_fname->st;
3036 if (fsp != NULL) {
3037 base_sp = fsp->base_fsp ?
3038 &fsp->base_fsp->fsp_name->st :
3039 &fsp->fsp_name->st;
3040 } else {
3041 base_sp = &smb_fname->st;
3044 nlink = psbuf->st_ex_nlink;
3046 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3047 nlink = 1;
3050 if ((nlink > 0) && delete_pending) {
3051 nlink -= 1;
3054 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3055 return NT_STATUS_INVALID_PARAMETER;
3058 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3059 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3060 if (*ppdata == NULL) {
3061 return NT_STATUS_NO_MEMORY;
3063 pdata = *ppdata;
3064 dstart = pdata;
3065 dend = dstart + data_size - 1;
3067 if (!is_omit_timespec(&write_time_ts) &&
3068 !INFO_LEVEL_IS_UNIX(info_level))
3070 update_stat_ex_mtime(psbuf, write_time_ts);
3073 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3074 mtime_ts = psbuf->st_ex_mtime;
3075 atime_ts = psbuf->st_ex_atime;
3076 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3078 if (lp_dos_filetime_resolution(SNUM(conn))) {
3079 dos_filetime_timespec(&create_time_ts);
3080 dos_filetime_timespec(&mtime_ts);
3081 dos_filetime_timespec(&atime_ts);
3082 dos_filetime_timespec(&ctime_ts);
3085 p = strrchr_m(smb_fname->base_name,'/');
3086 if (p == NULL) {
3087 base_name = smb_fname->base_name;
3088 } else {
3089 base_name = p+1;
3092 /* NT expects the name to be in an exact form of the *full*
3093 filename. See the trans2 torture test */
3094 if (ISDOT(base_name)) {
3095 dos_fname = talloc_strdup(mem_ctx, "\\");
3096 if (!dos_fname) {
3097 return NT_STATUS_NO_MEMORY;
3099 } else {
3100 dos_fname = talloc_asprintf(mem_ctx,
3101 "\\%s",
3102 smb_fname->base_name);
3103 if (!dos_fname) {
3104 return NT_STATUS_NO_MEMORY;
3106 if (is_named_stream(smb_fname)) {
3107 dos_fname = talloc_asprintf(dos_fname, "%s",
3108 smb_fname->stream_name);
3109 if (!dos_fname) {
3110 return NT_STATUS_NO_MEMORY;
3114 string_replace(dos_fname, '/', '\\');
3117 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3119 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3120 /* Do we have this path open ? */
3121 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3122 files_struct *fsp1 = file_find_di_first(
3123 conn->sconn, fileid, true);
3124 if (fsp1 && fsp1->initial_allocation_size) {
3125 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3129 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3130 file_size = get_file_size_stat(psbuf);
3133 if (fsp) {
3134 pos = fh_get_position_information(fsp->fh);
3137 if (fsp) {
3138 access_mask = fsp->access_mask;
3139 } else {
3140 /* GENERIC_EXECUTE mapping from Windows */
3141 access_mask = 0x12019F;
3144 /* This should be an index number - looks like
3145 dev/ino to me :-)
3147 I think this causes us to fail the IFSKIT
3148 BasicFileInformationTest. -tpot */
3149 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3151 *fixed_portion = 0;
3153 switch (info_level) {
3154 case SMB_INFO_STANDARD:
3155 DBG_DEBUG("SMB_INFO_STANDARD\n");
3156 data_size = 22;
3157 srv_put_dos_date2_ts(pdata,
3158 l1_fdateCreation,
3159 create_time_ts);
3160 srv_put_dos_date2_ts(pdata,
3161 l1_fdateLastAccess,
3162 atime_ts);
3163 srv_put_dos_date2_ts(pdata,
3164 l1_fdateLastWrite,
3165 mtime_ts); /* write time */
3166 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3167 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3168 SSVAL(pdata,l1_attrFile,mode);
3169 break;
3171 case SMB_INFO_QUERY_EA_SIZE:
3173 unsigned int ea_size =
3174 estimate_ea_size(smb_fname->fsp);
3175 DBG_DEBUG("SMB_INFO_QUERY_EA_SIZE\n");
3176 data_size = 26;
3177 srv_put_dos_date2_ts(pdata, 0, create_time_ts);
3178 srv_put_dos_date2_ts(pdata, 4, atime_ts);
3179 srv_put_dos_date2_ts(pdata,
3181 mtime_ts); /* write time */
3182 SIVAL(pdata,12,(uint32_t)file_size);
3183 SIVAL(pdata,16,(uint32_t)allocation_size);
3184 SSVAL(pdata,20,mode);
3185 SIVAL(pdata,22,ea_size);
3186 break;
3189 case SMB_INFO_IS_NAME_VALID:
3190 DBG_DEBUG("SMB_INFO_IS_NAME_VALID\n");
3191 if (fsp) {
3192 /* os/2 needs this ? really ?*/
3193 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3195 /* This is only reached for qpathinfo */
3196 data_size = 0;
3197 break;
3199 case SMB_INFO_QUERY_EAS_FROM_LIST:
3201 size_t total_ea_len = 0;
3202 struct ea_list *ea_file_list = NULL;
3203 DBG_DEBUG("SMB_INFO_QUERY_EAS_FROM_LIST\n");
3205 status =
3206 get_ea_list_from_fsp(mem_ctx,
3207 smb_fname->fsp,
3208 &total_ea_len, &ea_file_list);
3209 if (!NT_STATUS_IS_OK(status)) {
3210 return status;
3213 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3215 if (!ea_list || (total_ea_len > data_size)) {
3216 data_size = 4;
3217 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3218 break;
3221 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3222 break;
3225 case SMB_INFO_QUERY_ALL_EAS:
3227 /* We have data_size bytes to put EA's into. */
3228 size_t total_ea_len = 0;
3229 DBG_DEBUG(" SMB_INFO_QUERY_ALL_EAS\n");
3231 status = get_ea_list_from_fsp(mem_ctx,
3232 smb_fname->fsp,
3233 &total_ea_len, &ea_list);
3234 if (!NT_STATUS_IS_OK(status)) {
3235 return status;
3238 if (!ea_list || (total_ea_len > data_size)) {
3239 data_size = 4;
3240 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3241 break;
3244 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3245 break;
3248 case SMB2_FILE_FULL_EA_INFORMATION:
3250 /* We have data_size bytes to put EA's into. */
3251 size_t total_ea_len = 0;
3252 struct ea_list *ea_file_list = NULL;
3254 DBG_DEBUG("SMB2_INFO_QUERY_ALL_EAS\n");
3256 /*TODO: add filtering and index handling */
3258 status =
3259 get_ea_list_from_fsp(mem_ctx,
3260 smb_fname->fsp,
3261 &total_ea_len, &ea_file_list);
3262 if (!NT_STATUS_IS_OK(status)) {
3263 return status;
3265 if (!ea_file_list) {
3266 return NT_STATUS_NO_EAS_ON_FILE;
3269 status = fill_ea_chained_buffer(mem_ctx,
3270 pdata,
3271 data_size,
3272 &data_size,
3273 conn, ea_file_list);
3274 if (!NT_STATUS_IS_OK(status)) {
3275 return status;
3277 break;
3280 case SMB_FILE_BASIC_INFORMATION:
3281 case SMB_QUERY_FILE_BASIC_INFO:
3283 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3284 DBG_DEBUG("SMB_QUERY_FILE_BASIC_INFO\n");
3285 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3286 } else {
3287 DBG_DEBUG("SMB_FILE_BASIC_INFORMATION\n");
3288 data_size = 40;
3289 SIVAL(pdata,36,0);
3291 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3292 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3293 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3294 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3295 SIVAL(pdata,32,mode);
3297 DBG_INFO("SMB_QFBI - create: %s access: %s "
3298 "write: %s change: %s mode: %x\n",
3299 ctime(&create_time_ts.tv_sec),
3300 ctime(&atime_ts.tv_sec),
3301 ctime(&mtime_ts.tv_sec),
3302 ctime(&ctime_ts.tv_sec),
3303 mode);
3304 *fixed_portion = data_size;
3305 break;
3307 case SMB_FILE_STANDARD_INFORMATION:
3308 case SMB_QUERY_FILE_STANDARD_INFO:
3310 DBG_DEBUG("SMB_FILE_STANDARD_INFORMATION\n");
3311 data_size = 24;
3312 SOFF_T(pdata,0,allocation_size);
3313 SOFF_T(pdata,8,file_size);
3314 SIVAL(pdata,16,nlink);
3315 SCVAL(pdata,20,delete_pending?1:0);
3316 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3317 SSVAL(pdata,22,0); /* Padding. */
3318 *fixed_portion = 24;
3319 break;
3321 case SMB_FILE_EA_INFORMATION:
3322 case SMB_QUERY_FILE_EA_INFO:
3324 unsigned int ea_size =
3325 estimate_ea_size(smb_fname->fsp);
3326 DBG_DEBUG("SMB_FILE_EA_INFORMATION\n");
3327 data_size = 4;
3328 *fixed_portion = 4;
3329 SIVAL(pdata,0,ea_size);
3330 break;
3333 /* Get the 8.3 name - used if NT SMB was negotiated. */
3334 case SMB_QUERY_FILE_ALT_NAME_INFO:
3335 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3337 char mangled_name[13];
3338 DBG_DEBUG("SMB_FILE_ALTERNATE_NAME_INFORMATION\n");
3339 if (!name_to_8_3(base_name,mangled_name,
3340 True,conn->params)) {
3341 return NT_STATUS_NO_MEMORY;
3343 status = srvstr_push(dstart, flags2,
3344 pdata+4, mangled_name,
3345 PTR_DIFF(dend, pdata+4),
3346 STR_UNICODE, &len);
3347 if (!NT_STATUS_IS_OK(status)) {
3348 return status;
3350 data_size = 4 + len;
3351 SIVAL(pdata,0,len);
3352 *fixed_portion = 8;
3353 break;
3356 case SMB_QUERY_FILE_NAME_INFO:
3359 this must be *exactly* right for ACLs on mapped drives to work
3361 status = srvstr_push(dstart, flags2,
3362 pdata+4, dos_fname,
3363 PTR_DIFF(dend, pdata+4),
3364 STR_UNICODE, &len);
3365 if (!NT_STATUS_IS_OK(status)) {
3366 return status;
3368 DBG_DEBUG("SMB_QUERY_FILE_NAME_INFO\n");
3369 data_size = 4 + len;
3370 SIVAL(pdata,0,len);
3371 break;
3374 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3376 char *nfname = NULL;
3378 if (fsp == NULL ||
3379 !conn_using_smb2(fsp->conn->sconn)) {
3380 return NT_STATUS_INVALID_LEVEL;
3383 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3384 if (nfname == NULL) {
3385 return NT_STATUS_NO_MEMORY;
3388 if (ISDOT(nfname)) {
3389 nfname[0] = '\0';
3391 string_replace(nfname, '/', '\\');
3393 if (fsp_is_alternate_stream(fsp)) {
3394 const char *s = smb_fname->stream_name;
3395 const char *e = NULL;
3396 size_t n;
3398 SMB_ASSERT(s[0] != '\0');
3401 * smb_fname->stream_name is in form
3402 * of ':StrEam:$DATA', but we should only
3403 * append ':StrEam' here.
3406 e = strchr(&s[1], ':');
3407 if (e == NULL) {
3408 n = strlen(s);
3409 } else {
3410 n = PTR_DIFF(e, s);
3412 nfname = talloc_strndup_append(nfname, s, n);
3413 if (nfname == NULL) {
3414 return NT_STATUS_NO_MEMORY;
3418 status = srvstr_push(dstart, flags2,
3419 pdata+4, nfname,
3420 PTR_DIFF(dend, pdata+4),
3421 STR_UNICODE, &len);
3422 if (!NT_STATUS_IS_OK(status)) {
3423 return status;
3425 DBG_DEBUG("SMB_FILE_NORMALIZED_NAME_INFORMATION\n");
3426 data_size = 4 + len;
3427 SIVAL(pdata,0,len);
3428 *fixed_portion = 8;
3429 break;
3432 case SMB_FILE_ALLOCATION_INFORMATION:
3433 case SMB_QUERY_FILE_ALLOCATION_INFO:
3434 DBG_DEBUG("SMB_FILE_ALLOCATION_INFORMATION\n");
3435 data_size = 8;
3436 SOFF_T(pdata,0,allocation_size);
3437 break;
3439 case SMB_FILE_END_OF_FILE_INFORMATION:
3440 case SMB_QUERY_FILE_END_OF_FILEINFO:
3441 DBG_DEBUG("SMB_FILE_END_OF_FILE_INFORMATION\n");
3442 data_size = 8;
3443 SOFF_T(pdata,0,file_size);
3444 break;
3446 case SMB_QUERY_FILE_ALL_INFO:
3447 case SMB_FILE_ALL_INFORMATION:
3449 unsigned int ea_size =
3450 estimate_ea_size(smb_fname->fsp);
3451 DBG_DEBUG("SMB_FILE_ALL_INFORMATION\n");
3452 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3453 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3454 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3455 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3456 SIVAL(pdata,32,mode);
3457 SIVAL(pdata,36,0); /* padding. */
3458 pdata += 40;
3459 SOFF_T(pdata,0,allocation_size);
3460 SOFF_T(pdata,8,file_size);
3461 SIVAL(pdata,16,nlink);
3462 SCVAL(pdata,20,delete_pending);
3463 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3464 SSVAL(pdata,22,0);
3465 pdata += 24;
3466 SIVAL(pdata,0,ea_size);
3467 pdata += 4; /* EA info */
3468 status = srvstr_push(dstart, flags2,
3469 pdata+4, dos_fname,
3470 PTR_DIFF(dend, pdata+4),
3471 STR_UNICODE, &len);
3472 if (!NT_STATUS_IS_OK(status)) {
3473 return status;
3475 SIVAL(pdata,0,len);
3476 pdata += 4 + len;
3477 data_size = PTR_DIFF(pdata,(*ppdata));
3478 *fixed_portion = 10;
3479 break;
3482 case SMB2_FILE_ALL_INFORMATION:
3484 unsigned int ea_size =
3485 estimate_ea_size(smb_fname->fsp);
3486 DBG_DEBUG("SMB2_FILE_ALL_INFORMATION\n");
3487 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3488 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3489 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3490 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3491 SIVAL(pdata, 0x20, mode);
3492 SIVAL(pdata, 0x24, 0); /* padding. */
3493 SBVAL(pdata, 0x28, allocation_size);
3494 SBVAL(pdata, 0x30, file_size);
3495 SIVAL(pdata, 0x38, nlink);
3496 SCVAL(pdata, 0x3C, delete_pending);
3497 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3498 SSVAL(pdata, 0x3E, 0); /* padding */
3499 SBVAL(pdata, 0x40, file_id);
3500 SIVAL(pdata, 0x48, ea_size);
3501 SIVAL(pdata, 0x4C, access_mask);
3502 SBVAL(pdata, 0x50, pos);
3503 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3504 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3506 pdata += 0x60;
3508 status = srvstr_push(dstart, flags2,
3509 pdata+4, dos_fname,
3510 PTR_DIFF(dend, pdata+4),
3511 STR_UNICODE, &len);
3512 if (!NT_STATUS_IS_OK(status)) {
3513 return status;
3515 SIVAL(pdata,0,len);
3516 pdata += 4 + len;
3517 data_size = PTR_DIFF(pdata,(*ppdata));
3518 *fixed_portion = 104;
3519 break;
3521 case SMB_FILE_INTERNAL_INFORMATION:
3523 DBG_DEBUG("SMB_FILE_INTERNAL_INFORMATION\n");
3524 SBVAL(pdata, 0, file_id);
3525 data_size = 8;
3526 *fixed_portion = 8;
3527 break;
3529 case SMB_FILE_ACCESS_INFORMATION:
3530 DBG_DEBUG("SMB_FILE_ACCESS_INFORMATION\n");
3531 SIVAL(pdata, 0, access_mask);
3532 data_size = 4;
3533 *fixed_portion = 4;
3534 break;
3536 case SMB_FILE_NAME_INFORMATION:
3537 /* Pathname with leading '\'. */
3539 size_t byte_len;
3540 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3541 DBG_DEBUG("SMB_FILE_NAME_INFORMATION\n");
3542 SIVAL(pdata,0,byte_len);
3543 data_size = 4 + byte_len;
3544 break;
3547 case SMB_FILE_DISPOSITION_INFORMATION:
3548 DBG_DEBUG("SMB_FILE_DISPOSITION_INFORMATION\n");
3549 data_size = 1;
3550 SCVAL(pdata,0,delete_pending);
3551 *fixed_portion = 1;
3552 break;
3554 case SMB_FILE_POSITION_INFORMATION:
3555 DBG_DEBUG("SMB_FILE_POSITION_INFORMATION\n");
3556 data_size = 8;
3557 SOFF_T(pdata,0,pos);
3558 *fixed_portion = 8;
3559 break;
3561 case SMB_FILE_MODE_INFORMATION:
3562 DBG_DEBUG("SMB_FILE_MODE_INFORMATION\n");
3563 SIVAL(pdata,0,mode);
3564 data_size = 4;
3565 *fixed_portion = 4;
3566 break;
3568 case SMB_FILE_ALIGNMENT_INFORMATION:
3569 DBG_DEBUG("SMB_FILE_ALIGNMENT_INFORMATION\n");
3570 SIVAL(pdata,0,0); /* No alignment needed. */
3571 data_size = 4;
3572 *fixed_portion = 4;
3573 break;
3576 * NT4 server just returns "invalid query" to this - if we try
3577 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3578 * want this. JRA.
3580 /* The first statement above is false - verified using Thursby
3581 * client against NT4 -- gcolley.
3583 case SMB_QUERY_FILE_STREAM_INFO:
3584 case SMB_FILE_STREAM_INFORMATION: {
3585 unsigned int num_streams = 0;
3586 struct stream_struct *streams = NULL;
3588 DBG_DEBUG("SMB_FILE_STREAM_INFORMATION\n");
3590 if (is_ntfs_stream_smb_fname(smb_fname)) {
3591 return NT_STATUS_INVALID_PARAMETER;
3594 status = vfs_fstreaminfo(fsp,
3595 mem_ctx,
3596 &num_streams,
3597 &streams);
3599 if (!NT_STATUS_IS_OK(status)) {
3600 DBG_DEBUG("could not get stream info: %s\n",
3601 nt_errstr(status));
3602 return status;
3605 status = marshall_stream_info(num_streams, streams,
3606 pdata, max_data_bytes,
3607 &data_size);
3609 if (!NT_STATUS_IS_OK(status)) {
3610 DBG_DEBUG("marshall_stream_info failed: %s\n",
3611 nt_errstr(status));
3612 TALLOC_FREE(streams);
3613 return status;
3616 TALLOC_FREE(streams);
3618 *fixed_portion = 32;
3620 break;
3622 case SMB_QUERY_COMPRESSION_INFO:
3623 case SMB_FILE_COMPRESSION_INFORMATION:
3624 DBG_DEBUG("SMB_FILE_COMPRESSION_INFORMATION\n");
3625 SOFF_T(pdata,0,file_size);
3626 SIVAL(pdata,8,0); /* ??? */
3627 SIVAL(pdata,12,0); /* ??? */
3628 data_size = 16;
3629 *fixed_portion = 16;
3630 break;
3632 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3633 DBG_DEBUG("SMB_FILE_NETWORK_OPEN_INFORMATION\n");
3634 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3635 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3636 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3637 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3638 SOFF_T(pdata,32,allocation_size);
3639 SOFF_T(pdata,40,file_size);
3640 SIVAL(pdata,48,mode);
3641 SIVAL(pdata,52,0); /* ??? */
3642 data_size = 56;
3643 *fixed_portion = 56;
3644 break;
3646 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION: {
3647 uint32_t tag = 0;
3649 DBG_DEBUG("SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n");
3651 (void)fsctl_get_reparse_tag(fsp, &tag);
3653 DBG_DEBUG("tag=%"PRIu32"\n", tag);
3655 SIVAL(pdata, 0, mode);
3656 SIVAL(pdata, 4, tag);
3657 data_size = 8;
3658 *fixed_portion = 8;
3659 break;
3662 * SMB2 UNIX Extensions.
3664 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3666 struct smb3_file_posix_information info = {};
3667 uint8_t buf[sizeof(info)];
3668 struct ndr_push ndr = {
3669 .data = buf,
3670 .alloc_size = sizeof(buf),
3671 .fixed_buf_size = true,
3673 enum ndr_err_code ndr_err;
3675 if (!conn_using_smb2(conn->sconn)) {
3676 return NT_STATUS_INVALID_LEVEL;
3678 if (fsp == NULL) {
3679 return NT_STATUS_INVALID_HANDLE;
3681 if (!fsp->fsp_flags.posix_open) {
3682 return NT_STATUS_INVALID_LEVEL;
3685 smb3_file_posix_information_init(
3686 conn, &smb_fname->st, 0, mode, &info);
3688 ndr_err = ndr_push_smb3_file_posix_information(
3689 &ndr, NDR_SCALARS|NDR_BUFFERS, &info);
3690 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3691 return NT_STATUS_INSUFFICIENT_RESOURCES;
3694 memcpy(pdata, buf, ndr.offset);
3695 data_size = ndr.offset;
3696 break;
3699 default:
3700 return NT_STATUS_INVALID_LEVEL;
3703 *pdata_size = data_size;
3704 return NT_STATUS_OK;
3707 /****************************************************************************
3708 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3709 code.
3710 ****************************************************************************/
3712 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3713 connection_struct *conn,
3714 struct smb_request *req,
3715 bool overwrite_if_exists,
3716 const struct smb_filename *smb_fname_old,
3717 struct smb_filename *smb_fname_new)
3719 NTSTATUS status = NT_STATUS_OK;
3720 int ret;
3721 bool ok;
3722 struct smb_filename *parent_fname_old = NULL;
3723 struct smb_filename *base_name_old = NULL;
3724 struct smb_filename *parent_fname_new = NULL;
3725 struct smb_filename *base_name_new = NULL;
3727 /* source must already exist. */
3728 if (!VALID_STAT(smb_fname_old->st)) {
3729 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3730 goto out;
3733 /* No links from a directory. */
3734 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3735 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3736 goto out;
3739 /* Setting a hardlink to/from a stream isn't currently supported. */
3740 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3741 if (ok) {
3742 DBG_DEBUG("Old name has streams\n");
3743 status = NT_STATUS_INVALID_PARAMETER;
3744 goto out;
3746 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3747 if (ok) {
3748 DBG_DEBUG("New name has streams\n");
3749 status = NT_STATUS_INVALID_PARAMETER;
3750 goto out;
3753 if (smb_fname_old->twrp != 0) {
3754 status = NT_STATUS_NOT_SAME_DEVICE;
3755 goto out;
3758 status = parent_pathref(talloc_tos(),
3759 conn->cwd_fsp,
3760 smb_fname_old,
3761 &parent_fname_old,
3762 &base_name_old);
3763 if (!NT_STATUS_IS_OK(status)) {
3764 goto out;
3767 status = parent_pathref(talloc_tos(),
3768 conn->cwd_fsp,
3769 smb_fname_new,
3770 &parent_fname_new,
3771 &base_name_new);
3772 if (!NT_STATUS_IS_OK(status)) {
3773 goto out;
3776 if (VALID_STAT(smb_fname_new->st)) {
3777 if (overwrite_if_exists) {
3778 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3779 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3780 goto out;
3782 status = unlink_internals(conn,
3783 req,
3784 FILE_ATTRIBUTE_NORMAL,
3785 NULL, /* new_dirfsp */
3786 smb_fname_new);
3787 if (!NT_STATUS_IS_OK(status)) {
3788 goto out;
3790 } else {
3791 /* Disallow if newname already exists. */
3792 status = NT_STATUS_OBJECT_NAME_COLLISION;
3793 goto out;
3797 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3798 smb_fname_old->base_name, smb_fname_new->base_name));
3800 ret = SMB_VFS_LINKAT(conn,
3801 parent_fname_old->fsp,
3802 base_name_old,
3803 parent_fname_new->fsp,
3804 base_name_new,
3807 if (ret != 0) {
3808 status = map_nt_error_from_unix(errno);
3809 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3810 nt_errstr(status), smb_fname_old->base_name,
3811 smb_fname_new->base_name));
3812 goto out;
3815 notify_fname(conn,
3816 NOTIFY_ACTION_ADDED |
3817 NOTIFY_ACTION_DIRLEASE_BREAK,
3818 FILE_NOTIFY_CHANGE_FILE_NAME,
3819 smb_fname_new,
3820 fsp_get_smb2_lease(smb_fname_old->fsp));
3822 out:
3824 TALLOC_FREE(parent_fname_old);
3825 TALLOC_FREE(parent_fname_new);
3826 return status;
3829 /****************************************************************************
3830 Deal with setting the time from any of the setfilepathinfo functions.
3831 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3832 calling this function.
3833 ****************************************************************************/
3835 NTSTATUS smb_set_file_time(connection_struct *conn,
3836 files_struct *fsp,
3837 struct smb_filename *smb_fname,
3838 struct smb_file_time *ft,
3839 bool setting_write_time)
3841 const struct smb2_lease *lease = NULL;
3842 struct files_struct *set_fsp = NULL;
3843 struct timeval_buf tbuf[4];
3844 uint32_t action = NOTIFY_ACTION_MODIFIED;
3845 uint32_t filter =
3846 FILE_NOTIFY_CHANGE_LAST_ACCESS
3847 |FILE_NOTIFY_CHANGE_LAST_WRITE
3848 |FILE_NOTIFY_CHANGE_CREATION;
3849 int ret;
3851 if (!VALID_STAT(smb_fname->st)) {
3852 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3855 if (fsp == NULL) {
3856 /* A symlink */
3857 return NT_STATUS_OK;
3860 set_fsp = metadata_fsp(fsp);
3862 /* get some defaults (no modifications) if any info is zero or -1. */
3863 if (is_omit_timespec(&ft->create_time)) {
3864 filter &= ~FILE_NOTIFY_CHANGE_CREATION;
3867 if (is_omit_timespec(&ft->atime)) {
3868 filter &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3871 if (is_omit_timespec(&ft->mtime)) {
3872 filter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3875 if (!setting_write_time) {
3876 /* ft->mtime comes from change time, not write time. */
3877 filter &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3880 /* Ensure the resolution is the correct for
3881 * what we can store on this filesystem. */
3883 round_timespec(conn->ts_res, &ft->create_time);
3884 round_timespec(conn->ts_res, &ft->ctime);
3885 round_timespec(conn->ts_res, &ft->atime);
3886 round_timespec(conn->ts_res, &ft->mtime);
3888 DBG_DEBUG("actime: %s\n ",
3889 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3890 DBG_DEBUG("modtime: %s\n ",
3891 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3892 DBG_DEBUG("ctime: %s\n ",
3893 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3894 DBG_DEBUG("createtime: %s\n ",
3895 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3897 if (setting_write_time) {
3899 * This was a Windows setfileinfo on an open file.
3900 * NT does this a lot. We also need to
3901 * set the time here, as it can be read by
3902 * FindFirst/FindNext and with the patch for bug #2045
3903 * in smbd/fileio.c it ensures that this timestamp is
3904 * kept sticky even after a write. We save the request
3905 * away and will set it on file close and after a write. JRA.
3908 DBG_DEBUG("setting pending modtime to %s\n",
3909 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3911 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3912 action |= NOTIFY_ACTION_DIRLEASE_BREAK;
3913 lease = fsp_get_smb2_lease(fsp);
3916 DBG_DEBUG("setting utimes to modified values.\n");
3918 ret = file_ntimes(conn, set_fsp, ft);
3919 if (ret != 0) {
3920 return map_nt_error_from_unix(errno);
3923 notify_fname(conn,
3924 action,
3925 filter,
3926 smb_fname,
3927 lease);
3928 return NT_STATUS_OK;
3931 /****************************************************************************
3932 Deal with setting the dosmode from any of the setfilepathinfo functions.
3933 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3934 done before calling this function.
3935 ****************************************************************************/
3937 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3938 struct files_struct *fsp,
3939 uint32_t dosmode)
3941 struct files_struct *dos_fsp = NULL;
3942 uint32_t current_dosmode;
3943 int ret;
3945 if (!VALID_STAT(fsp->fsp_name->st)) {
3946 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3949 dos_fsp = metadata_fsp(fsp);
3951 if (dosmode != 0) {
3952 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3953 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
3954 } else {
3955 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
3959 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
3961 /* check the mode isn't different, before changing it */
3962 if (dosmode == 0) {
3963 return NT_STATUS_OK;
3965 current_dosmode = fdos_mode(dos_fsp);
3966 if (dosmode == current_dosmode) {
3967 return NT_STATUS_OK;
3970 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
3971 fsp_str_dbg(dos_fsp), dosmode);
3973 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
3974 if (ret != 0) {
3975 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
3976 fsp_str_dbg(dos_fsp), strerror(errno));
3977 return map_nt_error_from_unix(errno);
3980 return NT_STATUS_OK;
3983 /****************************************************************************
3984 Deal with setting the size from any of the setfilepathinfo functions.
3985 ****************************************************************************/
3987 NTSTATUS smb_set_file_size(connection_struct *conn,
3988 struct smb_request *req,
3989 files_struct *fsp,
3990 struct smb_filename *smb_fname,
3991 const SMB_STRUCT_STAT *psbuf,
3992 off_t size,
3993 bool fail_after_createfile)
3995 NTSTATUS status = NT_STATUS_OK;
3996 files_struct *new_fsp = NULL;
3998 if (!VALID_STAT(*psbuf)) {
3999 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4002 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4003 (uint64_t)size,
4004 get_file_size_stat(psbuf));
4006 if (size == get_file_size_stat(psbuf)) {
4007 if (fsp == NULL) {
4008 return NT_STATUS_OK;
4010 if (!fsp->fsp_flags.modified) {
4011 return NT_STATUS_OK;
4013 trigger_write_time_update_immediate(fsp);
4014 return NT_STATUS_OK;
4017 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4018 smb_fname_str_dbg(smb_fname), (double)size));
4020 if (fsp &&
4021 !fsp->fsp_flags.is_pathref &&
4022 fsp_get_io_fd(fsp) != -1)
4024 /* Handle based call. */
4025 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4026 if (!NT_STATUS_IS_OK(status)) {
4027 return status;
4030 if (vfs_set_filelen(fsp, size) == -1) {
4031 return map_nt_error_from_unix(errno);
4033 trigger_write_time_update_immediate(fsp);
4034 return NT_STATUS_OK;
4037 status = SMB_VFS_CREATE_FILE(
4038 conn, /* conn */
4039 req, /* req */
4040 NULL, /* dirfsp */
4041 smb_fname, /* fname */
4042 FILE_WRITE_DATA, /* access_mask */
4043 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4044 FILE_SHARE_DELETE),
4045 FILE_OPEN, /* create_disposition*/
4046 0, /* create_options */
4047 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4048 0, /* oplock_request */
4049 NULL, /* lease */
4050 0, /* allocation_size */
4051 0, /* private_flags */
4052 NULL, /* sd */
4053 NULL, /* ea_list */
4054 &new_fsp, /* result */
4055 NULL, /* pinfo */
4056 NULL, NULL); /* create context */
4058 if (!NT_STATUS_IS_OK(status)) {
4059 /* NB. We check for open_was_deferred in the caller. */
4060 return status;
4063 /* See RAW-SFILEINFO-END-OF-FILE */
4064 if (fail_after_createfile) {
4065 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4066 return NT_STATUS_INVALID_LEVEL;
4069 if (vfs_set_filelen(new_fsp, size) == -1) {
4070 status = map_nt_error_from_unix(errno);
4071 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4072 return status;
4075 trigger_write_time_update_immediate(new_fsp);
4076 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4077 return NT_STATUS_OK;
4080 /****************************************************************************
4081 Deal with SMB_INFO_SET_EA.
4082 ****************************************************************************/
4084 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4085 const char *pdata,
4086 int total_data,
4087 files_struct *fsp,
4088 struct smb_filename *smb_fname)
4090 struct ea_list *ea_list = NULL;
4091 TALLOC_CTX *ctx = NULL;
4092 NTSTATUS status = NT_STATUS_OK;
4094 if (total_data < 10) {
4096 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4097 length. They seem to have no effect. Bug #3212. JRA */
4099 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4100 /* We're done. We only get EA info in this call. */
4101 return NT_STATUS_OK;
4104 return NT_STATUS_INVALID_PARAMETER;
4107 if (IVAL(pdata,0) > total_data) {
4108 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4109 IVAL(pdata,0), (unsigned int)total_data));
4110 return NT_STATUS_INVALID_PARAMETER;
4113 ctx = talloc_tos();
4114 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4115 if (!ea_list) {
4116 return NT_STATUS_INVALID_PARAMETER;
4119 if (fsp == NULL) {
4121 * The only way fsp can be NULL here is if
4122 * smb_fname points at a symlink and
4123 * and we're in POSIX context.
4124 * Ensure this is the case.
4126 * In this case we cannot set the EA.
4128 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4129 return NT_STATUS_ACCESS_DENIED;
4132 status = set_ea(conn, fsp, ea_list);
4134 return status;
4137 /****************************************************************************
4138 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4139 ****************************************************************************/
4141 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4142 const char *pdata,
4143 int total_data,
4144 files_struct *fsp)
4146 struct ea_list *ea_list = NULL;
4147 NTSTATUS status;
4149 if (fsp == NULL) {
4150 return NT_STATUS_INVALID_HANDLE;
4153 if (!lp_ea_support(SNUM(conn))) {
4154 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4155 "EA's not supported.\n",
4156 (unsigned int)total_data));
4157 return NT_STATUS_EAS_NOT_SUPPORTED;
4160 if (total_data < 10) {
4161 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4162 "too small.\n",
4163 (unsigned int)total_data));
4164 return NT_STATUS_INVALID_PARAMETER;
4167 ea_list = read_nttrans_ea_list(talloc_tos(),
4168 pdata,
4169 total_data);
4171 if (!ea_list) {
4172 return NT_STATUS_INVALID_PARAMETER;
4175 status = set_ea(conn, fsp, ea_list);
4177 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4178 smb_fname_str_dbg(fsp->fsp_name),
4179 nt_errstr(status) ));
4181 return status;
4185 /****************************************************************************
4186 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4187 ****************************************************************************/
4189 NTSTATUS smb_check_file_disposition_info(struct files_struct *fsp,
4190 const char *data,
4191 int total_data,
4192 bool *_delete_on_close)
4194 bool delete_on_close;
4195 uint32_t dosmode = 0;
4196 NTSTATUS status;
4198 if (total_data < 1) {
4199 return NT_STATUS_INVALID_PARAMETER;
4202 if (fsp == NULL) {
4203 return NT_STATUS_INVALID_HANDLE;
4206 delete_on_close = (PULL_LE_U8(data, 0) ? true : false);
4207 *_delete_on_close = delete_on_close;
4209 dosmode = fdos_mode(fsp);
4211 DBG_DEBUG("file [%s] dosmode = %u, delete_on_close = %s\n",
4212 fsp_str_dbg(fsp),
4213 (unsigned int)dosmode,
4214 delete_on_close ? "yes" : "no");
4216 if (!delete_on_close) {
4217 return NT_STATUS_OK;
4220 status = can_set_delete_on_close(fsp, dosmode);
4221 if (!NT_STATUS_IS_OK(status)) {
4222 return status;
4225 return NT_STATUS_OK;
4228 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4229 const char *pdata,
4230 int total_data,
4231 files_struct *fsp,
4232 struct smb_filename *smb_fname)
4234 NTSTATUS status;
4235 bool delete_on_close;
4237 status = smb_check_file_disposition_info(fsp,
4238 pdata,
4239 total_data,
4240 &delete_on_close);
4241 if (!NT_STATUS_IS_OK(status)) {
4242 return status;
4245 /* The set is across all open files on this dev/inode pair. */
4246 if (!set_delete_on_close(fsp, delete_on_close,
4247 conn->session_info->security_token,
4248 conn->session_info->unix_token)) {
4249 return NT_STATUS_ACCESS_DENIED;
4251 return NT_STATUS_OK;
4254 /****************************************************************************
4255 Deal with SMB_FILE_POSITION_INFORMATION.
4256 ****************************************************************************/
4258 static NTSTATUS smb_file_position_information(connection_struct *conn,
4259 const char *pdata,
4260 int total_data,
4261 files_struct *fsp)
4263 uint64_t position_information;
4265 if (total_data < 8) {
4266 return NT_STATUS_INVALID_PARAMETER;
4269 if (fsp == NULL) {
4270 /* Ignore on pathname based set. */
4271 return NT_STATUS_OK;
4274 position_information = (uint64_t)IVAL(pdata,0);
4275 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4277 DEBUG(10,("smb_file_position_information: Set file position "
4278 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4279 (double)position_information));
4280 fh_set_position_information(fsp->fh, position_information);
4281 return NT_STATUS_OK;
4284 /****************************************************************************
4285 Deal with SMB_FILE_MODE_INFORMATION.
4286 ****************************************************************************/
4288 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4289 const char *pdata,
4290 int total_data)
4292 uint32_t mode;
4294 if (total_data < 4) {
4295 return NT_STATUS_INVALID_PARAMETER;
4297 mode = IVAL(pdata,0);
4298 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4299 return NT_STATUS_INVALID_PARAMETER;
4301 return NT_STATUS_OK;
4304 /****************************************************************************
4305 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4306 ****************************************************************************/
4308 NTSTATUS smb2_parse_file_rename_information(TALLOC_CTX *ctx,
4309 struct connection_struct *conn,
4310 struct smb_request *req,
4311 const char *pdata,
4312 int total_data,
4313 files_struct *fsp,
4314 struct smb_filename *smb_fname_src,
4315 bool *_overwrite,
4316 struct files_struct **_dst_dirfsp,
4317 struct smb_filename **_smb_fname_dst,
4318 char **_dst_original_lcomp)
4320 char *newname = NULL;
4321 struct files_struct *dst_dirfsp = NULL;
4322 struct smb_filename *smb_fname_dst = NULL;
4323 char *dst_original_lcomp = NULL;
4324 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4325 bool overwrite = false;
4326 uint32_t len;
4327 NTSTATUS status;
4329 if (!fsp) {
4330 return NT_STATUS_INVALID_HANDLE;
4333 if (total_data < 20) {
4334 return NT_STATUS_INVALID_PARAMETER;
4337 overwrite = (CVAL(pdata,0) ? True : False);
4338 len = IVAL(pdata,16);
4340 if (len > (total_data - 20) || (len == 0)) {
4341 return NT_STATUS_INVALID_PARAMETER;
4344 (void)srvstr_pull_talloc(ctx,
4345 pdata,
4346 req->flags2,
4347 &newname,
4348 &pdata[20],
4349 len,
4350 STR_TERMINATE);
4352 if (newname == NULL) {
4353 return NT_STATUS_INVALID_PARAMETER;
4356 /* SMB2 rename paths are never DFS. */
4357 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4358 ucf_flags &= ~UCF_DFS_PATHNAME;
4360 status = check_path_syntax(newname,
4361 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4362 if (!NT_STATUS_IS_OK(status)) {
4363 TALLOC_FREE(newname);
4364 return status;
4367 DBG_DEBUG("got name |%s|\n", newname);
4369 if (newname[0] == ':') {
4370 /* Create an smb_fname to call rename_internals_fsp() with. */
4371 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4372 fsp->base_fsp->fsp_name->base_name,
4373 newname,
4374 NULL,
4375 fsp->base_fsp->fsp_name->twrp,
4376 fsp->base_fsp->fsp_name->flags);
4377 if (smb_fname_dst == NULL) {
4378 TALLOC_FREE(newname);
4379 return NT_STATUS_NO_MEMORY;
4381 goto done;
4382 } else {
4383 status = filename_convert_dirfsp(ctx,
4384 conn,
4385 newname,
4386 ucf_flags,
4387 0, /* Never a TWRP. */
4388 &dst_dirfsp,
4389 &smb_fname_dst);
4390 if (!NT_STATUS_IS_OK(status)) {
4391 return status;
4396 * Set the original last component, since
4397 * rename_internals_fsp() requires it.
4399 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4400 conn,
4401 newname,
4402 ucf_flags);
4403 if (dst_original_lcomp == NULL) {
4404 TALLOC_FREE(newname);
4405 TALLOC_FREE(smb_fname_dst);
4406 return NT_STATUS_NO_MEMORY;
4409 done:
4410 *_overwrite = overwrite;
4411 *_dst_dirfsp = dst_dirfsp;
4412 *_smb_fname_dst = smb_fname_dst;
4413 *_dst_original_lcomp = dst_original_lcomp;
4414 return NT_STATUS_OK;
4417 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4418 struct smb_request *req,
4419 const char *pdata,
4420 int total_data,
4421 files_struct *fsp,
4422 struct share_mode_lock **lck,
4423 struct smb_filename *smb_fname_src)
4425 bool overwrite;
4426 struct files_struct *dst_dirfsp = NULL;
4427 struct smb_filename *smb_fname_dst = NULL;
4428 char *dst_original_lcomp = NULL;
4429 NTSTATUS status = NT_STATUS_OK;
4430 TALLOC_CTX *ctx = talloc_tos();
4432 status = smb2_parse_file_rename_information(ctx,
4433 conn,
4434 req,
4435 pdata,
4436 total_data,
4437 fsp,
4438 smb_fname_src,
4439 &overwrite,
4440 &dst_dirfsp,
4441 &smb_fname_dst,
4442 &dst_original_lcomp);
4443 if (!NT_STATUS_IS_OK(status)) {
4444 return status;
4447 DBG_DEBUG("SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4448 fsp_fnum_dbg(fsp),
4449 fsp_str_dbg(fsp),
4450 smb_fname_str_dbg(smb_fname_dst));
4452 status = rename_internals_fsp(conn,
4453 fsp,
4454 lck,
4455 smb_fname_dst,
4456 dst_original_lcomp,
4457 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4458 overwrite);
4460 TALLOC_FREE(smb_fname_dst);
4461 return status;
4464 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4465 struct smb_request *req,
4466 const char *pdata,
4467 int total_data,
4468 files_struct *fsp,
4469 struct smb_filename *smb_fname_src)
4471 bool overwrite;
4472 uint32_t len;
4473 char *newname = NULL;
4474 struct files_struct *dst_dirfsp = NULL;
4475 struct smb_filename *smb_fname_dst = NULL;
4476 NTSTATUS status = NT_STATUS_OK;
4477 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4478 size_t ret;
4479 TALLOC_CTX *ctx = talloc_tos();
4481 if (!fsp) {
4482 return NT_STATUS_INVALID_HANDLE;
4485 if (total_data < 20) {
4486 return NT_STATUS_INVALID_PARAMETER;
4489 overwrite = (CVAL(pdata,0) ? true : false);
4490 len = IVAL(pdata,16);
4492 if (len > (total_data - 20) || (len == 0)) {
4493 return NT_STATUS_INVALID_PARAMETER;
4496 ret = srvstr_pull_talloc(ctx,
4497 pdata,
4498 req->flags2,
4499 &newname,
4500 &pdata[20],
4501 len,
4502 STR_TERMINATE);
4504 if (ret == (size_t)-1 || newname == NULL) {
4505 return NT_STATUS_INVALID_PARAMETER;
4508 /* SMB2 hardlink paths are never DFS. */
4509 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4510 ucf_flags &= ~UCF_DFS_PATHNAME;
4512 status = check_path_syntax(newname,
4513 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4514 if (!NT_STATUS_IS_OK(status)) {
4515 return status;
4518 DBG_DEBUG("got name |%s|\n", newname);
4520 status = filename_convert_dirfsp(ctx,
4521 conn,
4522 newname,
4523 ucf_flags,
4524 0, /* No TWRP. */
4525 &dst_dirfsp,
4526 &smb_fname_dst);
4527 if (!NT_STATUS_IS_OK(status)) {
4528 return status;
4531 if (fsp->base_fsp) {
4532 /* No stream names. */
4533 return NT_STATUS_NOT_SUPPORTED;
4536 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4537 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4538 smb_fname_str_dbg(smb_fname_dst));
4539 status = hardlink_internals(ctx,
4540 conn,
4541 req,
4542 overwrite,
4543 fsp->fsp_name,
4544 smb_fname_dst);
4546 TALLOC_FREE(smb_fname_dst);
4547 return status;
4550 static NTSTATUS smb_file_link_information(connection_struct *conn,
4551 struct smb_request *req,
4552 const char *pdata,
4553 int total_data,
4554 files_struct *fsp,
4555 struct smb_filename *smb_fname_src)
4557 bool overwrite;
4558 uint32_t len;
4559 char *newname = NULL;
4560 struct files_struct *dst_dirfsp = NULL;
4561 struct smb_filename *smb_fname_dst = NULL;
4562 NTSTATUS status = NT_STATUS_OK;
4563 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4564 NTTIME dst_twrp = 0;
4565 TALLOC_CTX *ctx = talloc_tos();
4567 if (!fsp) {
4568 return NT_STATUS_INVALID_HANDLE;
4571 if (total_data < 20) {
4572 return NT_STATUS_INVALID_PARAMETER;
4575 overwrite = (CVAL(pdata,0) ? true : false);
4576 len = IVAL(pdata,16);
4578 if (len > (total_data - 20) || (len == 0)) {
4579 return NT_STATUS_INVALID_PARAMETER;
4582 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4583 srvstr_get_path_posix(ctx,
4584 pdata,
4585 req->flags2,
4586 &newname,
4587 &pdata[20],
4588 len,
4589 STR_TERMINATE,
4590 &status);
4591 ucf_flags |= UCF_POSIX_PATHNAMES;
4592 } else {
4593 srvstr_get_path(ctx,
4594 pdata,
4595 req->flags2,
4596 &newname,
4597 &pdata[20],
4598 len,
4599 STR_TERMINATE,
4600 &status);
4602 if (!NT_STATUS_IS_OK(status)) {
4603 return status;
4606 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4607 newname));
4609 if (ucf_flags & UCF_GMT_PATHNAME) {
4610 extract_snapshot_token(newname, &dst_twrp);
4612 /* hardlink paths are never DFS. */
4613 ucf_flags &= ~UCF_DFS_PATHNAME;
4615 status = filename_convert_dirfsp(ctx,
4616 conn,
4617 newname,
4618 ucf_flags,
4619 dst_twrp,
4620 &dst_dirfsp,
4621 &smb_fname_dst);
4622 if (!NT_STATUS_IS_OK(status)) {
4623 return status;
4626 if (fsp->base_fsp) {
4627 /* No stream names. */
4628 return NT_STATUS_NOT_SUPPORTED;
4631 DEBUG(10,("smb_file_link_information: "
4632 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4633 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4634 smb_fname_str_dbg(smb_fname_dst)));
4635 status = hardlink_internals(ctx,
4636 conn,
4637 req,
4638 overwrite,
4639 fsp->fsp_name,
4640 smb_fname_dst);
4642 TALLOC_FREE(smb_fname_dst);
4643 return status;
4647 /****************************************************************************
4648 Deal with SMB_FILE_RENAME_INFORMATION.
4649 ****************************************************************************/
4651 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4652 struct smb_request *req,
4653 const char *pdata,
4654 int total_data,
4655 files_struct *fsp,
4656 struct smb_filename *smb_fname_src)
4658 bool overwrite;
4659 uint32_t root_fid;
4660 uint32_t len;
4661 char *newname = NULL;
4662 struct files_struct *dst_dirfsp = NULL;
4663 struct smb_filename *smb_fname_dst = NULL;
4664 const char *dst_original_lcomp = NULL;
4665 NTSTATUS status = NT_STATUS_OK;
4666 char *p;
4667 TALLOC_CTX *ctx = talloc_tos();
4669 if (total_data < 13) {
4670 return NT_STATUS_INVALID_PARAMETER;
4673 overwrite = (CVAL(pdata,0) != 0);
4674 root_fid = IVAL(pdata,4);
4675 len = IVAL(pdata,8);
4677 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4678 return NT_STATUS_INVALID_PARAMETER;
4681 if (req->posix_pathnames) {
4682 srvstr_get_path_posix(ctx,
4683 pdata,
4684 req->flags2,
4685 &newname,
4686 &pdata[12],
4687 len,
4689 &status);
4690 } else {
4691 srvstr_get_path(ctx,
4692 pdata,
4693 req->flags2,
4694 &newname,
4695 &pdata[12],
4696 len,
4698 &status);
4700 if (!NT_STATUS_IS_OK(status)) {
4701 return status;
4704 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4705 newname));
4707 /* Check the new name has no '/' characters. */
4708 if (strchr_m(newname, '/')) {
4709 return NT_STATUS_NOT_SUPPORTED;
4712 if (fsp && fsp->base_fsp) {
4713 /* newname must be a stream name. */
4714 if (newname[0] != ':') {
4715 return NT_STATUS_NOT_SUPPORTED;
4718 /* Create an smb_fname to call rename_internals_fsp() with. */
4719 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4720 fsp->base_fsp->fsp_name->base_name,
4721 newname,
4722 NULL,
4723 fsp->base_fsp->fsp_name->twrp,
4724 fsp->base_fsp->fsp_name->flags);
4725 if (smb_fname_dst == NULL) {
4726 status = NT_STATUS_NO_MEMORY;
4727 goto out;
4731 * Get the original last component, since
4732 * rename_internals_fsp() requires it.
4734 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4735 conn,
4736 newname,
4738 if (dst_original_lcomp == NULL) {
4739 status = NT_STATUS_NO_MEMORY;
4740 goto out;
4743 } else {
4745 * Build up an smb_fname_dst based on the filename passed in.
4746 * We basically just strip off the last component, and put on
4747 * the newname instead.
4749 char *base_name = NULL;
4750 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4751 NTTIME dst_twrp = 0;
4753 /* newname must *not* be a stream name. */
4754 if (newname[0] == ':') {
4755 return NT_STATUS_NOT_SUPPORTED;
4759 * Strip off the last component (filename) of the path passed
4760 * in.
4762 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4763 if (!base_name) {
4764 return NT_STATUS_NO_MEMORY;
4766 p = strrchr_m(base_name, '/');
4767 if (p) {
4768 p[1] = '\0';
4769 } else {
4770 base_name = talloc_strdup(ctx, "");
4771 if (!base_name) {
4772 return NT_STATUS_NO_MEMORY;
4775 /* Append the new name. */
4776 base_name = talloc_asprintf_append(base_name,
4777 "%s",
4778 newname);
4779 if (!base_name) {
4780 return NT_STATUS_NO_MEMORY;
4783 if (ucf_flags & UCF_GMT_PATHNAME) {
4784 extract_snapshot_token(base_name, &dst_twrp);
4787 /* The newname is *not* a DFS path. */
4788 ucf_flags &= ~UCF_DFS_PATHNAME;
4790 status = filename_convert_dirfsp(ctx,
4791 conn,
4792 base_name,
4793 ucf_flags,
4794 dst_twrp,
4795 &dst_dirfsp,
4796 &smb_fname_dst);
4798 if (!NT_STATUS_IS_OK(status)) {
4799 goto out;
4801 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4802 conn,
4803 newname,
4804 ucf_flags);
4805 if (dst_original_lcomp == NULL) {
4806 status = NT_STATUS_NO_MEMORY;
4807 goto out;
4811 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4812 DEBUG(10,("smb_file_rename_information: "
4813 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4814 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4815 smb_fname_str_dbg(smb_fname_dst)));
4818 * If no pathnames are open below this directory,
4819 * allow the rename.
4821 if (have_file_open_below(fsp)) {
4822 status = NT_STATUS_ACCESS_DENIED;
4823 goto out;
4826 status = rename_internals_fsp(conn,
4827 fsp,
4828 NULL,
4829 smb_fname_dst,
4830 dst_original_lcomp,
4832 overwrite);
4833 } else {
4834 DEBUG(10,("smb_file_rename_information: "
4835 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4836 smb_fname_str_dbg(smb_fname_src),
4837 smb_fname_str_dbg(smb_fname_dst)));
4838 status = rename_internals(ctx,
4839 conn,
4840 req,
4841 NULL, /* src_dirfsp */
4842 smb_fname_src,
4843 smb_fname_dst,
4844 dst_original_lcomp,
4846 overwrite,
4847 FILE_WRITE_ATTRIBUTES);
4849 out:
4850 TALLOC_FREE(smb_fname_dst);
4851 return status;
4854 /****************************************************************************
4855 Deal with SMB_SET_FILE_BASIC_INFO.
4856 ****************************************************************************/
4858 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4859 const char *pdata,
4860 int total_data,
4861 files_struct *fsp,
4862 struct smb_filename *smb_fname)
4864 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4865 struct smb_file_time ft;
4866 uint32_t dosmode = 0;
4867 NTSTATUS status = NT_STATUS_OK;
4869 init_smb_file_time(&ft);
4871 if (total_data < 36) {
4872 return NT_STATUS_INVALID_PARAMETER;
4875 if (fsp == NULL) {
4876 return NT_STATUS_INVALID_HANDLE;
4879 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4880 if (!NT_STATUS_IS_OK(status)) {
4881 return status;
4884 /* Set the attributes */
4885 dosmode = IVAL(pdata,32);
4886 status = smb_set_file_dosmode(conn, fsp, dosmode);
4887 if (!NT_STATUS_IS_OK(status)) {
4888 return status;
4891 /* create time */
4892 ft.create_time = pull_long_date_full_timespec(pdata);
4894 /* access time */
4895 ft.atime = pull_long_date_full_timespec(pdata+8);
4897 /* write time. */
4898 ft.mtime = pull_long_date_full_timespec(pdata+16);
4900 /* change time. */
4901 ft.ctime = pull_long_date_full_timespec(pdata+24);
4903 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4904 smb_fname_str_dbg(smb_fname)));
4906 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4907 if (!NT_STATUS_IS_OK(status)) {
4908 return status;
4911 if (fsp->fsp_flags.modified) {
4912 trigger_write_time_update_immediate(fsp);
4914 return NT_STATUS_OK;
4917 /****************************************************************************
4918 Deal with SMB_INFO_STANDARD.
4919 ****************************************************************************/
4921 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4922 const char *pdata,
4923 int total_data,
4924 files_struct *fsp,
4925 struct smb_filename *smb_fname)
4927 NTSTATUS status;
4928 struct smb_file_time ft;
4930 init_smb_file_time(&ft);
4932 if (total_data < 12) {
4933 return NT_STATUS_INVALID_PARAMETER;
4936 if (fsp == NULL) {
4937 return NT_STATUS_INVALID_HANDLE;
4940 /* create time */
4941 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4942 /* access time */
4943 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4944 /* write time */
4945 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4947 DEBUG(10,("smb_set_info_standard: file %s\n",
4948 smb_fname_str_dbg(smb_fname)));
4950 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4951 if (!NT_STATUS_IS_OK(status)) {
4952 return status;
4955 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4956 if (!NT_STATUS_IS_OK(status)) {
4957 return status;
4960 if (fsp->fsp_flags.modified) {
4961 trigger_write_time_update_immediate(fsp);
4963 return NT_STATUS_OK;
4966 /****************************************************************************
4967 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4968 ****************************************************************************/
4970 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4971 struct smb_request *req,
4972 const char *pdata,
4973 int total_data,
4974 files_struct *fsp,
4975 struct smb_filename *smb_fname)
4977 uint64_t allocation_size = 0;
4978 NTSTATUS status = NT_STATUS_OK;
4979 files_struct *new_fsp = NULL;
4981 if (!VALID_STAT(smb_fname->st)) {
4982 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4985 if (total_data < 8) {
4986 return NT_STATUS_INVALID_PARAMETER;
4989 allocation_size = (uint64_t)IVAL(pdata,0);
4990 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4991 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4992 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4993 (double)allocation_size));
4995 if (allocation_size) {
4996 allocation_size = smb_roundup(conn, allocation_size);
4999 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5000 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5001 (double)allocation_size));
5003 if (fsp &&
5004 !fsp->fsp_flags.is_pathref &&
5005 fsp_get_io_fd(fsp) != -1)
5007 /* Open file handle. */
5008 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
5009 if (!NT_STATUS_IS_OK(status)) {
5010 return status;
5013 /* Only change if needed. */
5014 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5015 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5016 return map_nt_error_from_unix(errno);
5019 /* But always update the time. */
5021 * This is equivalent to a write. Ensure it's seen immediately
5022 * if there are no pending writes.
5024 trigger_write_time_update_immediate(fsp);
5025 return NT_STATUS_OK;
5028 /* Pathname or stat or directory file. */
5029 status = SMB_VFS_CREATE_FILE(
5030 conn, /* conn */
5031 req, /* req */
5032 NULL, /* dirfsp */
5033 smb_fname, /* fname */
5034 FILE_WRITE_DATA, /* access_mask */
5035 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5036 FILE_SHARE_DELETE),
5037 FILE_OPEN, /* create_disposition*/
5038 0, /* create_options */
5039 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5040 0, /* oplock_request */
5041 NULL, /* lease */
5042 0, /* allocation_size */
5043 0, /* private_flags */
5044 NULL, /* sd */
5045 NULL, /* ea_list */
5046 &new_fsp, /* result */
5047 NULL, /* pinfo */
5048 NULL, NULL); /* create context */
5050 if (!NT_STATUS_IS_OK(status)) {
5051 /* NB. We check for open_was_deferred in the caller. */
5052 return status;
5055 /* Only change if needed. */
5056 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5057 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5058 status = map_nt_error_from_unix(errno);
5059 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5060 return status;
5064 /* Changing the allocation size should set the last mod time. */
5066 * This is equivalent to a write. Ensure it's seen immediately
5067 * if there are no pending writes.
5069 trigger_write_time_update_immediate(new_fsp);
5070 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5071 return NT_STATUS_OK;
5074 /****************************************************************************
5075 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5076 ****************************************************************************/
5078 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5079 struct smb_request *req,
5080 const char *pdata,
5081 int total_data,
5082 files_struct *fsp,
5083 struct smb_filename *smb_fname,
5084 bool fail_after_createfile)
5086 off_t size;
5088 if (total_data < 8) {
5089 return NT_STATUS_INVALID_PARAMETER;
5092 size = IVAL(pdata,0);
5093 size |= (((off_t)IVAL(pdata,4)) << 32);
5094 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5095 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5096 (double)size));
5098 return smb_set_file_size(conn, req,
5099 fsp,
5100 smb_fname,
5101 &smb_fname->st,
5102 size,
5103 fail_after_createfile);
5107 * Set an info_level
5109 * Called from the SMB1 and SMB2 code. For the path-based SMB1 code, there may
5110 * not be a full fsp from the FSA layer.
5112 * lck may be NULL, currently only passed for SMB2 rename requests.
5114 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5115 struct smb_request *req,
5116 TALLOC_CTX *mem_ctx,
5117 uint16_t info_level,
5118 files_struct *fsp,
5119 struct share_mode_lock **lck,
5120 struct smb_filename *smb_fname,
5121 char *pdata,
5122 int total_data,
5123 int *ret_data_size)
5125 NTSTATUS status = NT_STATUS_OK;
5126 int data_return_size = 0;
5128 *ret_data_size = 0;
5130 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5131 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5132 fsp_fnum_dbg(fsp),
5133 info_level, total_data));
5135 SMB_ASSERT(fsp != NULL);
5137 switch (info_level) {
5139 case SMB_INFO_STANDARD:
5141 status = smb_set_info_standard(conn,
5142 pdata,
5143 total_data,
5144 fsp,
5145 smb_fname);
5146 break;
5149 case SMB_INFO_SET_EA:
5151 status = smb_info_set_ea(conn,
5152 pdata,
5153 total_data,
5154 fsp,
5155 smb_fname);
5156 break;
5159 case SMB_SET_FILE_BASIC_INFO:
5160 case SMB_FILE_BASIC_INFORMATION:
5162 status = smb_set_file_basic_info(conn,
5163 pdata,
5164 total_data,
5165 fsp,
5166 smb_fname);
5167 break;
5170 case SMB_FILE_ALLOCATION_INFORMATION:
5171 case SMB_SET_FILE_ALLOCATION_INFO:
5173 status = smb_set_file_allocation_info(conn, req,
5174 pdata,
5175 total_data,
5176 fsp,
5177 smb_fname);
5178 break;
5181 case SMB_FILE_END_OF_FILE_INFORMATION:
5182 case SMB_SET_FILE_END_OF_FILE_INFO:
5185 * XP/Win7 both fail after the createfile with
5186 * SMB_SET_FILE_END_OF_FILE_INFO but not
5187 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5188 * The level is known here, so pass it down
5189 * appropriately.
5191 bool should_fail =
5192 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5194 status = smb_set_file_end_of_file_info(conn, req,
5195 pdata,
5196 total_data,
5197 fsp,
5198 smb_fname,
5199 should_fail);
5200 break;
5203 case SMB_FILE_DISPOSITION_INFORMATION:
5204 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5206 status = smb_set_file_disposition_info(conn,
5207 pdata,
5208 total_data,
5209 fsp,
5210 smb_fname);
5211 break;
5214 case SMB_FILE_POSITION_INFORMATION:
5216 status = smb_file_position_information(conn,
5217 pdata,
5218 total_data,
5219 fsp);
5220 break;
5223 case SMB_FILE_FULL_EA_INFORMATION:
5225 status = smb_set_file_full_ea_info(conn,
5226 pdata,
5227 total_data,
5228 fsp);
5229 break;
5232 /* From tridge Samba4 :
5233 * MODE_INFORMATION in setfileinfo (I have no
5234 * idea what "mode information" on a file is - it takes a value of 0,
5235 * 2, 4 or 6. What could it be?).
5238 case SMB_FILE_MODE_INFORMATION:
5240 status = smb_file_mode_information(conn,
5241 pdata,
5242 total_data);
5243 break;
5246 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5247 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5248 case SMB_FILE_SHORT_NAME_INFORMATION:
5249 return NT_STATUS_NOT_SUPPORTED;
5251 case SMB_FILE_RENAME_INFORMATION:
5253 status = smb_file_rename_information(conn, req,
5254 pdata, total_data,
5255 fsp, smb_fname);
5256 break;
5259 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5261 /* SMB2 rename information. */
5262 status = smb2_file_rename_information(conn,
5263 req,
5264 pdata,
5265 total_data,
5266 fsp,
5267 lck,
5268 smb_fname);
5269 break;
5272 case SMB_FILE_LINK_INFORMATION:
5274 if (conn_using_smb2(conn->sconn)) {
5275 status = smb2_file_link_information(conn,
5276 req,
5277 pdata,
5278 total_data,
5279 fsp,
5280 smb_fname);
5281 } else {
5282 status = smb_file_link_information(conn,
5283 req,
5284 pdata,
5285 total_data,
5286 fsp,
5287 smb_fname);
5289 break;
5292 default:
5293 return NT_STATUS_INVALID_LEVEL;
5296 if (!NT_STATUS_IS_OK(status)) {
5297 return status;
5300 *ret_data_size = data_return_size;
5301 return NT_STATUS_OK;
5304 static uint32_t generate_volume_serial_number(
5305 const struct loadparm_substitution *lp_sub,
5306 int snum)
5308 int serial = lp_volume_serial_number(snum);
5309 return serial != -1 ? serial:
5310 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5311 (str_checksum(get_local_machine_name())<<16);