s4:auth: Set ‘authoritative’ even if there is an error
[Samba.git] / source3 / smbd / smb2_trans2.c
blob3221f9089c61e64643ffb4e6e64d3abcda6a201a
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 "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
44 #include "messages.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static uint32_t generate_volume_serial_number(
53 const struct loadparm_substitution *lp_sub,
54 int snum);
56 /****************************************************************************
57 Check if an open file handle is a symlink.
58 ****************************************************************************/
60 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
63 if (!VALID_STAT(fsp->fsp_name->st)) {
64 return NT_STATUS_ACCESS_DENIED;
66 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
67 return NT_STATUS_ACCESS_DENIED;
69 if (fsp_get_pathref_fd(fsp) == -1) {
70 return NT_STATUS_ACCESS_DENIED;
72 return NT_STATUS_OK;
75 NTSTATUS check_access_fsp(struct files_struct *fsp,
76 uint32_t access_mask)
78 if (!fsp->fsp_flags.is_fsa) {
79 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
80 fsp,
81 false,
82 access_mask);
84 if (!(fsp->access_mask & access_mask)) {
85 return NT_STATUS_ACCESS_DENIED;
87 return NT_STATUS_OK;
90 /********************************************************************
91 Roundup a value to the nearest allocation roundup size boundary.
92 Only do this for Windows clients.
93 ********************************************************************/
95 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
97 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
99 /* Only roundup for Windows clients. */
100 enum remote_arch_types ra_type = get_remote_arch();
101 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
102 val = SMB_ROUNDUP(val,rval);
104 return val;
107 /****************************************************************************
108 Utility functions for dealing with extended attributes.
109 ****************************************************************************/
111 /****************************************************************************
112 Refuse to allow clients to overwrite our private xattrs.
113 ****************************************************************************/
115 bool samba_private_attr_name(const char *unix_ea_name)
117 bool prohibited = false;
119 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
120 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
121 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
122 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
123 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
125 if (prohibited) {
126 return true;
129 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
130 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
131 return true;
133 return false;
136 /****************************************************************************
137 Get one EA value. Fill in a struct ea_struct.
138 ****************************************************************************/
140 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
141 files_struct *fsp,
142 const char *ea_name,
143 struct ea_struct *pea)
145 /* Get the value of this xattr. Max size is 64k. */
146 size_t attr_size = 256;
147 char *val = NULL;
148 ssize_t sizeret;
149 size_t max_xattr_size = 0;
151 if (fsp == NULL) {
152 return NT_STATUS_INVALID_HANDLE;
155 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
157 again:
159 val = talloc_realloc(mem_ctx, val, char, attr_size);
160 if (!val) {
161 return NT_STATUS_NO_MEMORY;
164 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
165 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
166 attr_size = max_xattr_size;
167 goto again;
170 if (sizeret == -1) {
171 return map_nt_error_from_unix(errno);
174 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
175 dump_data(10, (uint8_t *)val, sizeret);
177 pea->flags = 0;
178 if (strnequal(ea_name, "user.", 5)) {
179 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
180 } else {
181 pea->name = talloc_strdup(mem_ctx, ea_name);
183 if (pea->name == NULL) {
184 TALLOC_FREE(val);
185 return NT_STATUS_NO_MEMORY;
187 pea->value.data = (unsigned char *)val;
188 pea->value.length = (size_t)sizeret;
189 return NT_STATUS_OK;
192 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
193 files_struct *fsp,
194 char ***pnames,
195 size_t *pnum_names)
197 char smallbuf[1024];
198 /* Get a list of all xattrs. Max namesize is 64k. */
199 size_t ea_namelist_size = 1024;
200 char *ea_namelist = smallbuf;
201 char *to_free = NULL;
203 char *p;
204 char **names;
205 size_t num_names;
206 ssize_t sizeret = -1;
207 NTSTATUS status;
209 if (pnames) {
210 *pnames = NULL;
212 *pnum_names = 0;
214 if (fsp == NULL) {
216 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
217 * symlink. This is ok, handle it here, by just return no EA's
218 * on a symlink.
220 return NT_STATUS_OK;
223 /* should be the case that fsp != NULL */
224 SMB_ASSERT(fsp != NULL);
226 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
227 ea_namelist_size);
229 if ((sizeret == -1) && (errno == ERANGE)) {
230 ea_namelist_size = 65536;
231 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
232 if (ea_namelist == NULL) {
233 return NT_STATUS_NO_MEMORY;
235 to_free = ea_namelist;
237 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
238 ea_namelist_size);
241 if (sizeret == -1) {
242 status = map_nt_error_from_unix(errno);
243 TALLOC_FREE(to_free);
244 return status;
247 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
249 if (sizeret == 0) {
250 TALLOC_FREE(to_free);
251 return NT_STATUS_OK;
255 * Ensure the result is 0-terminated
258 if (ea_namelist[sizeret-1] != '\0') {
259 TALLOC_FREE(to_free);
260 return NT_STATUS_INTERNAL_ERROR;
264 * count the names
266 num_names = 0;
268 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
269 num_names += 1;
272 *pnum_names = num_names;
274 if (pnames == NULL) {
275 TALLOC_FREE(to_free);
276 return NT_STATUS_OK;
279 names = talloc_array(mem_ctx, char *, num_names);
280 if (names == NULL) {
281 DEBUG(0, ("talloc failed\n"));
282 TALLOC_FREE(to_free);
283 return NT_STATUS_NO_MEMORY;
286 if (ea_namelist == smallbuf) {
287 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
288 if (ea_namelist == NULL) {
289 TALLOC_FREE(names);
290 return NT_STATUS_NO_MEMORY;
292 } else {
293 talloc_steal(names, ea_namelist);
295 ea_namelist = talloc_realloc(names, ea_namelist, char,
296 sizeret);
297 if (ea_namelist == NULL) {
298 TALLOC_FREE(names);
299 return NT_STATUS_NO_MEMORY;
303 num_names = 0;
305 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
306 names[num_names++] = p;
309 *pnames = names;
311 return NT_STATUS_OK;
314 /****************************************************************************
315 Return a linked list of the total EA's. Plus the total size
316 ****************************************************************************/
318 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
319 files_struct *fsp,
320 size_t *pea_total_len,
321 struct ea_list **ea_list)
323 /* Get a list of all xattrs. Max namesize is 64k. */
324 size_t i, num_names;
325 char **names;
326 struct ea_list *ea_list_head = NULL;
327 bool posix_pathnames = false;
328 NTSTATUS status;
330 *pea_total_len = 0;
331 *ea_list = NULL;
333 /* symlink */
334 if (fsp == NULL) {
335 return NT_STATUS_OK;
338 if (!lp_ea_support(SNUM(fsp->conn))) {
339 return NT_STATUS_OK;
342 if (fsp_is_alternate_stream(fsp)) {
343 return NT_STATUS_INVALID_PARAMETER;
346 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
348 status = get_ea_names_from_fsp(talloc_tos(),
349 fsp,
350 &names,
351 &num_names);
353 if (!NT_STATUS_IS_OK(status)) {
354 return status;
357 if (num_names == 0) {
358 return NT_STATUS_OK;
361 for (i=0; i<num_names; i++) {
362 struct ea_list *listp;
363 fstring dos_ea_name;
366 * POSIX EA names are divided into several namespaces by
367 * means of string prefixes. Usually, the system controls
368 * semantics for each namespace, but the 'user' namespace is
369 * available for arbitrary use, which comes closest to
370 * Windows EA semantics. Hence, we map POSIX EAs from the
371 * 'user' namespace to Windows EAs, and just ignore all the
372 * other namespaces. Also, a few specific names in the 'user'
373 * namespace are used by Samba internally. Filter them out as
374 * well, and only present the EAs that are available for
375 * arbitrary use.
377 if (!strnequal(names[i], "user.", 5)
378 || samba_private_attr_name(names[i]))
379 continue;
382 * Filter out any underlying POSIX EA names
383 * that a Windows client can't handle.
385 if (!posix_pathnames &&
386 is_invalid_windows_ea_name(names[i])) {
387 continue;
390 listp = talloc(mem_ctx, struct ea_list);
391 if (listp == NULL) {
392 return NT_STATUS_NO_MEMORY;
395 status = get_ea_value_fsp(listp,
396 fsp,
397 names[i],
398 &listp->ea);
400 if (!NT_STATUS_IS_OK(status)) {
401 TALLOC_FREE(listp);
402 return status;
405 if (listp->ea.value.length == 0) {
407 * We can never return a zero length EA.
408 * Windows reports the EA's as corrupted.
410 TALLOC_FREE(listp);
411 continue;
412 } else if (listp->ea.value.length > 65536) {
414 * SMB clients may report error with file
415 * if large EA is presented to them.
417 DBG_ERR("EA [%s] on file [%s] exceeds "
418 "maximum permitted EA size of 64KiB: %zu\n.",
419 listp->ea.name, fsp_str_dbg(fsp),
420 listp->ea.value.length);
421 TALLOC_FREE(listp);
422 continue;
425 push_ascii_fstring(dos_ea_name, listp->ea.name);
427 *pea_total_len +=
428 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
430 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
431 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
432 (unsigned int)listp->ea.value.length));
434 DLIST_ADD_END(ea_list_head, listp);
438 /* Add on 4 for total length. */
439 if (*pea_total_len) {
440 *pea_total_len += 4;
443 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
444 (unsigned int)*pea_total_len));
446 *ea_list = ea_list_head;
447 return NT_STATUS_OK;
450 /****************************************************************************
451 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
452 that was filled.
453 ****************************************************************************/
455 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
456 connection_struct *conn, struct ea_list *ea_list)
458 unsigned int ret_data_size = 4;
459 char *p = pdata;
461 SMB_ASSERT(total_data_size >= 4);
463 if (!lp_ea_support(SNUM(conn))) {
464 SIVAL(pdata,4,0);
465 return 4;
468 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
469 size_t dos_namelen;
470 fstring dos_ea_name;
471 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
472 dos_namelen = strlen(dos_ea_name);
473 if (dos_namelen > 255 || dos_namelen == 0) {
474 break;
476 if (ea_list->ea.value.length > 65535) {
477 break;
479 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
480 break;
483 /* We know we have room. */
484 SCVAL(p,0,ea_list->ea.flags);
485 SCVAL(p,1,dos_namelen);
486 SSVAL(p,2,ea_list->ea.value.length);
487 strlcpy(p+4, dos_ea_name, dos_namelen+1);
488 if (ea_list->ea.value.length > 0) {
489 memcpy(p + 4 + dos_namelen + 1,
490 ea_list->ea.value.data,
491 ea_list->ea.value.length);
494 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
495 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
498 ret_data_size = PTR_DIFF(p, pdata);
499 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
500 SIVAL(pdata,0,ret_data_size);
501 return ret_data_size;
504 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
505 char *pdata,
506 unsigned int total_data_size,
507 unsigned int *ret_data_size,
508 connection_struct *conn,
509 struct ea_list *ea_list)
511 uint8_t *p = (uint8_t *)pdata;
512 uint8_t *last_start = NULL;
513 bool do_store_data = (pdata != NULL);
515 *ret_data_size = 0;
517 if (!lp_ea_support(SNUM(conn))) {
518 return NT_STATUS_NO_EAS_ON_FILE;
521 for (; ea_list; ea_list = ea_list->next) {
522 size_t dos_namelen;
523 fstring dos_ea_name;
524 size_t this_size;
525 size_t pad = 0;
527 if (last_start != NULL && do_store_data) {
528 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
530 last_start = p;
532 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
533 dos_namelen = strlen(dos_ea_name);
534 if (dos_namelen > 255 || dos_namelen == 0) {
535 return NT_STATUS_INTERNAL_ERROR;
537 if (ea_list->ea.value.length > 65535) {
538 return NT_STATUS_INTERNAL_ERROR;
541 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
543 if (ea_list->next) {
544 pad = (4 - (this_size % 4)) % 4;
545 this_size += pad;
548 if (do_store_data) {
549 if (this_size > total_data_size) {
550 return NT_STATUS_INFO_LENGTH_MISMATCH;
553 /* We know we have room. */
554 SIVAL(p, 0x00, 0); /* next offset */
555 SCVAL(p, 0x04, ea_list->ea.flags);
556 SCVAL(p, 0x05, dos_namelen);
557 SSVAL(p, 0x06, ea_list->ea.value.length);
558 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
559 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
560 if (pad) {
561 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
562 '\0',
563 pad);
565 total_data_size -= this_size;
568 p += this_size;
571 *ret_data_size = PTR_DIFF(p, pdata);
572 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
573 return NT_STATUS_OK;
576 unsigned int estimate_ea_size(files_struct *fsp)
578 size_t total_ea_len = 0;
579 TALLOC_CTX *mem_ctx;
580 struct ea_list *ea_list = NULL;
581 NTSTATUS status;
583 /* symlink */
584 if (fsp == NULL) {
585 return 0;
588 if (!lp_ea_support(SNUM(fsp->conn))) {
589 return 0;
592 mem_ctx = talloc_stackframe();
594 /* If this is a stream fsp, then we need to instead find the
595 * estimated ea len from the main file, not the stream
596 * (streams cannot have EAs), but the estimate isn't just 0 in
597 * this case! */
598 fsp = metadata_fsp(fsp);
599 (void)get_ea_list_from_fsp(mem_ctx,
600 fsp,
601 &total_ea_len,
602 &ea_list);
604 if(fsp->conn->sconn->using_smb2) {
605 unsigned int ret_data_size;
607 * We're going to be using fill_ea_chained_buffer() to
608 * marshall EA's - this size is significantly larger
609 * than the SMB1 buffer. Re-calculate the size without
610 * marshalling.
612 status = fill_ea_chained_buffer(mem_ctx,
613 NULL,
615 &ret_data_size,
616 fsp->conn,
617 ea_list);
618 if (!NT_STATUS_IS_OK(status)) {
619 ret_data_size = 0;
621 total_ea_len = ret_data_size;
623 TALLOC_FREE(mem_ctx);
624 return total_ea_len;
627 /****************************************************************************
628 Ensure the EA name is case insensitive by matching any existing EA name.
629 ****************************************************************************/
631 static void canonicalize_ea_name(files_struct *fsp,
632 fstring unix_ea_name)
634 size_t total_ea_len;
635 TALLOC_CTX *mem_ctx = talloc_tos();
636 struct ea_list *ea_list;
637 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
638 fsp,
639 &total_ea_len,
640 &ea_list);
641 if (!NT_STATUS_IS_OK(status)) {
642 return;
645 for (; ea_list; ea_list = ea_list->next) {
646 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
647 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
648 &unix_ea_name[5], ea_list->ea.name));
649 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
650 break;
655 /****************************************************************************
656 Set or delete an extended attribute.
657 ****************************************************************************/
659 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
660 struct ea_list *ea_list)
662 NTSTATUS status;
663 bool posix_pathnames = false;
665 if (!lp_ea_support(SNUM(conn))) {
666 return NT_STATUS_EAS_NOT_SUPPORTED;
669 if (fsp == NULL) {
670 return NT_STATUS_INVALID_HANDLE;
673 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
675 status = refuse_symlink_fsp(fsp);
676 if (!NT_STATUS_IS_OK(status)) {
677 return status;
680 status = check_access_fsp(fsp, FILE_WRITE_EA);
681 if (!NT_STATUS_IS_OK(status)) {
682 return status;
685 /* Setting EAs on streams isn't supported. */
686 if (fsp_is_alternate_stream(fsp)) {
687 return NT_STATUS_INVALID_PARAMETER;
691 * Filter out invalid Windows EA names - before
692 * we set *any* of them.
695 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
696 return STATUS_INVALID_EA_NAME;
699 for (;ea_list; ea_list = ea_list->next) {
700 int ret;
701 fstring unix_ea_name;
704 * Complementing the forward mapping from POSIX EAs to
705 * Windows EAs in get_ea_list_from_fsp(), here we map in the
706 * opposite direction from Windows EAs to the 'user' namespace
707 * of POSIX EAs. Hence, all POSIX EA names the we set here must
708 * start with a 'user.' prefix.
710 fstrcpy(unix_ea_name, "user.");
711 fstrcat(unix_ea_name, ea_list->ea.name);
713 canonicalize_ea_name(fsp, unix_ea_name);
715 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
717 if (samba_private_attr_name(unix_ea_name)) {
718 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
719 return NT_STATUS_ACCESS_DENIED;
722 if (ea_list->ea.value.length == 0) {
723 /* Remove the attribute. */
724 DBG_DEBUG("deleting ea name %s on "
725 "file %s by file descriptor.\n",
726 unix_ea_name, fsp_str_dbg(fsp));
727 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
728 #ifdef ENOATTR
729 /* Removing a non existent attribute always succeeds. */
730 if (ret == -1 && errno == ENOATTR) {
731 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
732 unix_ea_name));
733 ret = 0;
735 #endif
736 } else {
737 DEBUG(10,("set_ea: setting ea name %s on file "
738 "%s by file descriptor.\n",
739 unix_ea_name, fsp_str_dbg(fsp)));
740 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
741 ea_list->ea.value.data, ea_list->ea.value.length, 0);
744 if (ret == -1) {
745 #ifdef ENOTSUP
746 if (errno == ENOTSUP) {
747 return NT_STATUS_EAS_NOT_SUPPORTED;
749 #endif
750 return map_nt_error_from_unix(errno);
754 return NT_STATUS_OK;
757 /****************************************************************************
758 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
759 ****************************************************************************/
761 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
763 struct ea_list *ea_list_head = NULL;
764 size_t offset = 0;
765 size_t bytes_used = 0;
767 while (offset < data_size) {
768 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
770 if (!eal) {
771 return NULL;
774 DLIST_ADD_END(ea_list_head, eal);
775 offset += bytes_used;
778 return ea_list_head;
781 /****************************************************************************
782 Count the total EA size needed.
783 ****************************************************************************/
785 static size_t ea_list_size(struct ea_list *ealist)
787 fstring dos_ea_name;
788 struct ea_list *listp;
789 size_t ret = 0;
791 for (listp = ealist; listp; listp = listp->next) {
792 push_ascii_fstring(dos_ea_name, listp->ea.name);
793 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
795 /* Add on 4 for total length. */
796 if (ret) {
797 ret += 4;
800 return ret;
803 /****************************************************************************
804 Return a union of EA's from a file list and a list of names.
805 The TALLOC context for the two lists *MUST* be identical as we steal
806 memory from one list to add to another. JRA.
807 ****************************************************************************/
809 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
811 struct ea_list *nlistp, *flistp;
813 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
814 for (flistp = file_list; flistp; flistp = flistp->next) {
815 if (strequal(nlistp->ea.name, flistp->ea.name)) {
816 break;
820 if (flistp) {
821 /* Copy the data from this entry. */
822 nlistp->ea.flags = flistp->ea.flags;
823 nlistp->ea.value = flistp->ea.value;
824 } else {
825 /* Null entry. */
826 nlistp->ea.flags = 0;
827 ZERO_STRUCT(nlistp->ea.value);
831 *total_ea_len = ea_list_size(name_list);
832 return name_list;
835 /****************************************************************************
836 Return the filetype for UNIX extensions.
837 ****************************************************************************/
839 static uint32_t unix_filetype(mode_t mode)
841 if(S_ISREG(mode))
842 return UNIX_TYPE_FILE;
843 else if(S_ISDIR(mode))
844 return UNIX_TYPE_DIR;
845 #ifdef S_ISLNK
846 else if(S_ISLNK(mode))
847 return UNIX_TYPE_SYMLINK;
848 #endif
849 #ifdef S_ISCHR
850 else if(S_ISCHR(mode))
851 return UNIX_TYPE_CHARDEV;
852 #endif
853 #ifdef S_ISBLK
854 else if(S_ISBLK(mode))
855 return UNIX_TYPE_BLKDEV;
856 #endif
857 #ifdef S_ISFIFO
858 else if(S_ISFIFO(mode))
859 return UNIX_TYPE_FIFO;
860 #endif
861 #ifdef S_ISSOCK
862 else if(S_ISSOCK(mode))
863 return UNIX_TYPE_SOCKET;
864 #endif
866 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
867 return UNIX_TYPE_UNKNOWN;
870 /****************************************************************************
871 Map wire perms onto standard UNIX permissions. Obey share restrictions.
872 ****************************************************************************/
874 NTSTATUS unix_perms_from_wire(connection_struct *conn,
875 const SMB_STRUCT_STAT *psbuf,
876 uint32_t perms,
877 enum perm_type ptype,
878 mode_t *ret_perms)
880 mode_t ret = 0;
882 if (perms == SMB_MODE_NO_CHANGE) {
883 if (!VALID_STAT(*psbuf)) {
884 return NT_STATUS_INVALID_PARAMETER;
885 } else {
886 *ret_perms = psbuf->st_ex_mode;
887 return NT_STATUS_OK;
891 ret = wire_perms_to_unix(perms);
893 if (ptype == PERM_NEW_FILE) {
895 * "create mask"/"force create mode" are
896 * only applied to new files, not existing ones.
898 ret &= lp_create_mask(SNUM(conn));
899 /* Add in force bits */
900 ret |= lp_force_create_mode(SNUM(conn));
901 } else if (ptype == PERM_NEW_DIR) {
903 * "directory mask"/"force directory mode" are
904 * only applied to new directories, not existing ones.
906 ret &= lp_directory_mask(SNUM(conn));
907 /* Add in force bits */
908 ret |= lp_force_directory_mode(SNUM(conn));
911 *ret_perms = ret;
912 return NT_STATUS_OK;
915 /****************************************************************************
916 Needed to show the msdfs symlinks as directories. Modifies psbuf
917 to be a directory if it's a msdfs link.
918 ****************************************************************************/
920 static bool check_msdfs_link(struct files_struct *dirfsp,
921 struct smb_filename *atname,
922 struct smb_filename *smb_fname)
924 int saved_errno = errno;
925 if(lp_host_msdfs() &&
926 lp_msdfs_root(SNUM(dirfsp->conn)) &&
927 is_msdfs_link(dirfsp, atname)) {
930 * Copy the returned stat struct from the relative
931 * to the full pathname.
933 smb_fname->st = atname->st;
935 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
936 "as a directory\n",
937 smb_fname->base_name));
938 smb_fname->st.st_ex_mode =
939 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
940 errno = saved_errno;
941 return true;
943 errno = saved_errno;
944 return false;
948 /****************************************************************************
949 Get a level dependent lanman2 dir entry.
950 ****************************************************************************/
952 struct smbd_dirptr_lanman2_state {
953 connection_struct *conn;
954 uint32_t info_level;
955 bool check_mangled_names;
956 bool case_sensitive;
959 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
960 void *private_data,
961 const char *dname,
962 const char *mask,
963 char **_fname)
965 struct smbd_dirptr_lanman2_state *state =
966 (struct smbd_dirptr_lanman2_state *)private_data;
967 bool ok;
968 char mangled_name[13]; /* mangled 8.3 name. */
969 bool got_match;
970 const char *fname;
972 /* Mangle fname if it's an illegal name. */
973 if (mangle_must_mangle(dname, state->conn->params)) {
975 * Slow path - ensure we can push the original name as UCS2. If
976 * not, then just don't return this name.
978 NTSTATUS status;
979 size_t ret_len = 0;
980 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
981 uint8_t *tmp = talloc_array(talloc_tos(),
982 uint8_t,
983 len);
985 status = srvstr_push(NULL,
986 FLAGS2_UNICODE_STRINGS,
987 tmp,
988 dname,
989 len,
990 STR_TERMINATE,
991 &ret_len);
993 TALLOC_FREE(tmp);
995 if (!NT_STATUS_IS_OK(status)) {
996 return false;
999 ok = name_to_8_3(dname, mangled_name,
1000 true, state->conn->params);
1001 if (!ok) {
1002 return false;
1004 fname = mangled_name;
1005 } else {
1006 fname = dname;
1009 got_match = mask_match(fname, mask,
1010 state->case_sensitive);
1012 if(!got_match && state->check_mangled_names &&
1013 !mangle_is_8_3(fname, false, state->conn->params)) {
1015 * It turns out that NT matches wildcards against
1016 * both long *and* short names. This may explain some
1017 * of the wildcard wierdness from old DOS clients
1018 * that some people have been seeing.... JRA.
1020 /* Force the mangling into 8.3. */
1021 ok = name_to_8_3(fname, mangled_name,
1022 false, state->conn->params);
1023 if (!ok) {
1024 return false;
1027 got_match = mask_match(mangled_name, mask,
1028 state->case_sensitive);
1031 if (!got_match) {
1032 return false;
1035 *_fname = talloc_strdup(ctx, fname);
1036 if (*_fname == NULL) {
1037 return false;
1040 return true;
1043 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1044 void *private_data,
1045 struct files_struct *dirfsp,
1046 struct smb_filename *atname,
1047 struct smb_filename *smb_fname,
1048 bool get_dosmode,
1049 uint32_t *_mode)
1051 struct smbd_dirptr_lanman2_state *state =
1052 (struct smbd_dirptr_lanman2_state *)private_data;
1054 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1055 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1056 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1057 "Couldn't lstat [%s] (%s)\n",
1058 smb_fname_str_dbg(smb_fname),
1059 strerror(errno)));
1060 return false;
1062 return true;
1065 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
1066 /* Needed to show the msdfs symlinks as
1067 * directories */
1069 bool ms_dfs_link = check_msdfs_link(dirfsp, atname, smb_fname);
1070 if (!ms_dfs_link) {
1071 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1072 "Couldn't stat [%s] (%s)\n",
1073 smb_fname_str_dbg(smb_fname),
1074 strerror(errno)));
1075 return false;
1078 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1079 return true;
1082 if (!get_dosmode) {
1083 return true;
1086 *_mode = fdos_mode(smb_fname->fsp);
1087 smb_fname->st = smb_fname->fsp->fsp_name->st;
1089 return true;
1092 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1094 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1095 unsigned ea_size = estimate_ea_size(fsp);
1096 return ea_size;
1098 return IO_REPARSE_TAG_DFS;
1101 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1102 connection_struct *conn,
1103 uint16_t flags2,
1104 uint32_t info_level,
1105 struct ea_list *name_list,
1106 bool check_mangled_names,
1107 bool requires_resume_key,
1108 uint32_t mode,
1109 const char *fname,
1110 const struct smb_filename *smb_fname,
1111 int space_remaining,
1112 uint8_t align,
1113 bool do_pad,
1114 char *base_data,
1115 char **ppdata,
1116 char *end_data,
1117 uint64_t *last_entry_off)
1119 char *p, *q, *pdata = *ppdata;
1120 uint32_t reskey=0;
1121 uint64_t file_size = 0;
1122 uint64_t allocation_size = 0;
1123 uint64_t file_id = 0;
1124 size_t len = 0;
1125 struct timespec mdate_ts = {0};
1126 struct timespec adate_ts = {0};
1127 struct timespec cdate_ts = {0};
1128 struct timespec create_date_ts = {0};
1129 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1130 char *nameptr;
1131 char *last_entry_ptr;
1132 bool was_8_3;
1133 int off;
1134 int pad = 0;
1135 NTSTATUS status;
1136 struct readdir_attr_data *readdir_attr_data = NULL;
1137 uint32_t ea_size;
1139 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1140 file_size = get_file_size_stat(&smb_fname->st);
1142 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1145 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1146 * a DFS symlink.
1148 if (smb_fname->fsp != NULL &&
1149 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1150 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1151 ctx,
1152 &readdir_attr_data);
1153 if (!NT_STATUS_IS_OK(status)) {
1154 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1155 status)) {
1156 return status;
1161 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1163 mdate_ts = smb_fname->st.st_ex_mtime;
1164 adate_ts = smb_fname->st.st_ex_atime;
1165 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1166 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1168 if (lp_dos_filetime_resolution(SNUM(conn))) {
1169 dos_filetime_timespec(&create_date_ts);
1170 dos_filetime_timespec(&mdate_ts);
1171 dos_filetime_timespec(&adate_ts);
1172 dos_filetime_timespec(&cdate_ts);
1175 create_date = convert_timespec_to_time_t(create_date_ts);
1176 mdate = convert_timespec_to_time_t(mdate_ts);
1177 adate = convert_timespec_to_time_t(adate_ts);
1179 /* align the record */
1180 SMB_ASSERT(align >= 1);
1182 off = (int)PTR_DIFF(pdata, base_data);
1183 pad = (off + (align-1)) & ~(align-1);
1184 pad -= off;
1186 if (pad && pad > space_remaining) {
1187 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1188 "for padding (wanted %u, had %d)\n",
1189 (unsigned int)pad,
1190 space_remaining ));
1191 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1194 off += pad;
1195 /* initialize padding to 0 */
1196 if (pad) {
1197 memset(pdata, 0, pad);
1199 space_remaining -= pad;
1201 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1202 space_remaining ));
1204 pdata += pad;
1205 p = pdata;
1206 last_entry_ptr = p;
1208 pad = 0;
1209 off = 0;
1211 switch (info_level) {
1212 case SMB_FIND_INFO_STANDARD:
1213 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1214 if(requires_resume_key) {
1215 SIVAL(p,0,reskey);
1216 p += 4;
1218 srv_put_dos_date2(p,0,create_date);
1219 srv_put_dos_date2(p,4,adate);
1220 srv_put_dos_date2(p,8,mdate);
1221 SIVAL(p,12,(uint32_t)file_size);
1222 SIVAL(p,16,(uint32_t)allocation_size);
1223 SSVAL(p,20,mode);
1224 p += 23;
1225 nameptr = p;
1226 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1227 p += ucs2_align(base_data, p, 0);
1229 status = srvstr_push(base_data, flags2, p,
1230 fname, PTR_DIFF(end_data, p),
1231 STR_TERMINATE, &len);
1232 if (!NT_STATUS_IS_OK(status)) {
1233 return status;
1235 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1236 if (len > 2) {
1237 SCVAL(nameptr, -1, len - 2);
1238 } else {
1239 SCVAL(nameptr, -1, 0);
1241 } else {
1242 if (len > 1) {
1243 SCVAL(nameptr, -1, len - 1);
1244 } else {
1245 SCVAL(nameptr, -1, 0);
1248 p += len;
1249 break;
1251 case SMB_FIND_EA_SIZE:
1252 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1253 if (requires_resume_key) {
1254 SIVAL(p,0,reskey);
1255 p += 4;
1257 srv_put_dos_date2(p,0,create_date);
1258 srv_put_dos_date2(p,4,adate);
1259 srv_put_dos_date2(p,8,mdate);
1260 SIVAL(p,12,(uint32_t)file_size);
1261 SIVAL(p,16,(uint32_t)allocation_size);
1262 SSVAL(p,20,mode);
1264 ea_size = estimate_ea_size(smb_fname->fsp);
1265 SIVAL(p,22,ea_size); /* Extended attributes */
1267 p += 27;
1268 nameptr = p - 1;
1269 status = srvstr_push(base_data, flags2,
1270 p, fname, PTR_DIFF(end_data, p),
1271 STR_TERMINATE | STR_NOALIGN, &len);
1272 if (!NT_STATUS_IS_OK(status)) {
1273 return status;
1275 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1276 if (len > 2) {
1277 len -= 2;
1278 } else {
1279 len = 0;
1281 } else {
1282 if (len > 1) {
1283 len -= 1;
1284 } else {
1285 len = 0;
1288 SCVAL(nameptr,0,len);
1289 p += len;
1290 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1291 break;
1293 case SMB_FIND_EA_LIST:
1295 struct ea_list *file_list = NULL;
1296 size_t ea_len = 0;
1298 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1299 if (!name_list) {
1300 return NT_STATUS_INVALID_PARAMETER;
1302 if (requires_resume_key) {
1303 SIVAL(p,0,reskey);
1304 p += 4;
1306 srv_put_dos_date2(p,0,create_date);
1307 srv_put_dos_date2(p,4,adate);
1308 srv_put_dos_date2(p,8,mdate);
1309 SIVAL(p,12,(uint32_t)file_size);
1310 SIVAL(p,16,(uint32_t)allocation_size);
1311 SSVAL(p,20,mode);
1312 p += 22; /* p now points to the EA area. */
1314 status = get_ea_list_from_fsp(ctx,
1315 smb_fname->fsp,
1316 &ea_len, &file_list);
1317 if (!NT_STATUS_IS_OK(status)) {
1318 file_list = NULL;
1320 name_list = ea_list_union(name_list, file_list, &ea_len);
1322 /* We need to determine if this entry will fit in the space available. */
1323 /* Max string size is 255 bytes. */
1324 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1325 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1326 "(wanted %u, had %d)\n",
1327 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1328 space_remaining ));
1329 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1332 /* Push the ea_data followed by the name. */
1333 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1334 nameptr = p;
1335 status = srvstr_push(base_data, flags2,
1336 p + 1, fname, PTR_DIFF(end_data, p+1),
1337 STR_TERMINATE | STR_NOALIGN, &len);
1338 if (!NT_STATUS_IS_OK(status)) {
1339 return status;
1341 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1342 if (len > 2) {
1343 len -= 2;
1344 } else {
1345 len = 0;
1347 } else {
1348 if (len > 1) {
1349 len -= 1;
1350 } else {
1351 len = 0;
1354 SCVAL(nameptr,0,len);
1355 p += len + 1;
1356 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1357 break;
1360 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1361 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1362 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1363 p += 4;
1364 SIVAL(p,0,reskey); p += 4;
1365 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1366 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1367 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1368 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1369 SOFF_T(p,0,file_size); p += 8;
1370 SOFF_T(p,0,allocation_size); p += 8;
1371 SIVAL(p,0,mode); p += 4;
1372 q = p; p += 4; /* q is placeholder for name length. */
1373 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1374 SIVAL(p, 0, ea_size);
1375 p += 4;
1376 /* Clear the short name buffer. This is
1377 * IMPORTANT as not doing so will trigger
1378 * a Win2k client bug. JRA.
1380 if (!was_8_3 && check_mangled_names) {
1381 char mangled_name[13]; /* mangled 8.3 name. */
1382 if (!name_to_8_3(fname,mangled_name,True,
1383 conn->params)) {
1384 /* Error - mangle failed ! */
1385 memset(mangled_name,'\0',12);
1387 mangled_name[12] = 0;
1388 status = srvstr_push(base_data, flags2,
1389 p+2, mangled_name, 24,
1390 STR_UPPER|STR_UNICODE, &len);
1391 if (!NT_STATUS_IS_OK(status)) {
1392 return status;
1394 if (len < 24) {
1395 memset(p + 2 + len,'\0',24 - len);
1397 SSVAL(p, 0, len);
1398 } else {
1399 memset(p,'\0',26);
1401 p += 2 + 24;
1402 status = srvstr_push(base_data, flags2, p,
1403 fname, PTR_DIFF(end_data, p),
1404 STR_TERMINATE_ASCII, &len);
1405 if (!NT_STATUS_IS_OK(status)) {
1406 return status;
1408 SIVAL(q,0,len);
1409 p += len;
1411 len = PTR_DIFF(p, pdata);
1412 pad = (len + (align-1)) & ~(align-1);
1414 * offset to the next entry, the caller
1415 * will overwrite it for the last entry
1416 * that's why we always include the padding
1418 SIVAL(pdata,0,pad);
1420 * set padding to zero
1422 if (do_pad) {
1423 memset(p, 0, pad - len);
1424 p = pdata + pad;
1425 } else {
1426 p = pdata + len;
1428 break;
1430 case SMB_FIND_FILE_DIRECTORY_INFO:
1431 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1432 p += 4;
1433 SIVAL(p,0,reskey); p += 4;
1434 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1435 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1436 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1437 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1438 SOFF_T(p,0,file_size); p += 8;
1439 SOFF_T(p,0,allocation_size); p += 8;
1440 SIVAL(p,0,mode); p += 4;
1441 status = srvstr_push(base_data, flags2,
1442 p + 4, fname, PTR_DIFF(end_data, p+4),
1443 STR_TERMINATE_ASCII, &len);
1444 if (!NT_STATUS_IS_OK(status)) {
1445 return status;
1447 SIVAL(p,0,len);
1448 p += 4 + len;
1450 len = PTR_DIFF(p, pdata);
1451 pad = (len + (align-1)) & ~(align-1);
1453 * offset to the next entry, the caller
1454 * will overwrite it for the last entry
1455 * that's why we always include the padding
1457 SIVAL(pdata,0,pad);
1459 * set padding to zero
1461 if (do_pad) {
1462 memset(p, 0, pad - len);
1463 p = pdata + pad;
1464 } else {
1465 p = pdata + len;
1467 break;
1469 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1470 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1471 p += 4;
1472 SIVAL(p,0,reskey); p += 4;
1473 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1474 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1475 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1476 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1477 SOFF_T(p,0,file_size); p += 8;
1478 SOFF_T(p,0,allocation_size); p += 8;
1479 SIVAL(p,0,mode); p += 4;
1480 q = p; p += 4; /* q is placeholder for name length. */
1481 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1482 SIVAL(p, 0, ea_size);
1483 p +=4;
1484 status = srvstr_push(base_data, flags2, p,
1485 fname, PTR_DIFF(end_data, p),
1486 STR_TERMINATE_ASCII, &len);
1487 if (!NT_STATUS_IS_OK(status)) {
1488 return status;
1490 SIVAL(q, 0, len);
1491 p += len;
1493 len = PTR_DIFF(p, pdata);
1494 pad = (len + (align-1)) & ~(align-1);
1496 * offset to the next entry, the caller
1497 * will overwrite it for the last entry
1498 * that's why we always include the padding
1500 SIVAL(pdata,0,pad);
1502 * set padding to zero
1504 if (do_pad) {
1505 memset(p, 0, pad - len);
1506 p = pdata + pad;
1507 } else {
1508 p = pdata + len;
1510 break;
1512 case SMB_FIND_FILE_NAMES_INFO:
1513 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1514 p += 4;
1515 SIVAL(p,0,reskey); p += 4;
1516 p += 4;
1517 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1518 acl on a dir (tridge) */
1519 status = srvstr_push(base_data, flags2, p,
1520 fname, PTR_DIFF(end_data, p),
1521 STR_TERMINATE_ASCII, &len);
1522 if (!NT_STATUS_IS_OK(status)) {
1523 return status;
1525 SIVAL(p, -4, len);
1526 p += len;
1528 len = PTR_DIFF(p, pdata);
1529 pad = (len + (align-1)) & ~(align-1);
1531 * offset to the next entry, the caller
1532 * will overwrite it for the last entry
1533 * that's why we always include the padding
1535 SIVAL(pdata,0,pad);
1537 * set padding to zero
1539 if (do_pad) {
1540 memset(p, 0, pad - len);
1541 p = pdata + pad;
1542 } else {
1543 p = pdata + len;
1545 break;
1547 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1548 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1549 p += 4;
1550 SIVAL(p,0,reskey); p += 4;
1551 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1552 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1553 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1554 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1555 SOFF_T(p,0,file_size); p += 8;
1556 SOFF_T(p,0,allocation_size); p += 8;
1557 SIVAL(p,0,mode); p += 4;
1558 q = p; p += 4; /* q is placeholder for name length. */
1559 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1560 SIVAL(p, 0, ea_size);
1561 p += 4;
1562 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1563 SBVAL(p,0,file_id); p += 8;
1564 status = srvstr_push(base_data, flags2, p,
1565 fname, PTR_DIFF(end_data, p),
1566 STR_TERMINATE_ASCII, &len);
1567 if (!NT_STATUS_IS_OK(status)) {
1568 return status;
1570 SIVAL(q, 0, len);
1571 p += len;
1573 len = PTR_DIFF(p, pdata);
1574 pad = (len + (align-1)) & ~(align-1);
1576 * offset to the next entry, the caller
1577 * will overwrite it for the last entry
1578 * that's why we always include the padding
1580 SIVAL(pdata,0,pad);
1582 * set padding to zero
1584 if (do_pad) {
1585 memset(p, 0, pad - len);
1586 p = pdata + pad;
1587 } else {
1588 p = pdata + len;
1590 break;
1592 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1593 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1594 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1595 p += 4;
1596 SIVAL(p,0,reskey); p += 4;
1597 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1598 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1599 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1600 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1601 SOFF_T(p,0,file_size); p += 8;
1602 SOFF_T(p,0,allocation_size); p += 8;
1603 SIVAL(p,0,mode); p += 4;
1604 q = p; p += 4; /* q is placeholder for name length */
1605 if (readdir_attr_data &&
1606 readdir_attr_data->type == RDATTR_AAPL) {
1608 * OS X specific SMB2 extension negotiated via
1609 * AAPL create context: return max_access in
1610 * ea_size field.
1612 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1613 } else {
1614 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1616 SIVAL(p,0,ea_size); /* Extended attributes */
1617 p += 4;
1619 if (readdir_attr_data &&
1620 readdir_attr_data->type == RDATTR_AAPL) {
1622 * OS X specific SMB2 extension negotiated via
1623 * AAPL create context: return resource fork
1624 * length and compressed FinderInfo in
1625 * shortname field.
1627 * According to documentation short_name_len
1628 * should be 0, but on the wire behaviour
1629 * shows its set to 24 by clients.
1631 SSVAL(p, 0, 24);
1633 /* Resourefork length */
1634 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1636 /* Compressed FinderInfo */
1637 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1638 } else if (!was_8_3 && check_mangled_names) {
1639 char mangled_name[13]; /* mangled 8.3 name. */
1640 if (!name_to_8_3(fname,mangled_name,True,
1641 conn->params)) {
1642 /* Error - mangle failed ! */
1643 memset(mangled_name,'\0',12);
1645 mangled_name[12] = 0;
1646 status = srvstr_push(base_data, flags2,
1647 p+2, mangled_name, 24,
1648 STR_UPPER|STR_UNICODE, &len);
1649 if (!NT_STATUS_IS_OK(status)) {
1650 return status;
1652 SSVAL(p, 0, len);
1653 if (len < 24) {
1654 memset(p + 2 + len,'\0',24 - len);
1656 SSVAL(p, 0, len);
1657 } else {
1658 /* Clear the short name buffer. This is
1659 * IMPORTANT as not doing so will trigger
1660 * a Win2k client bug. JRA.
1662 memset(p,'\0',26);
1664 p += 26;
1666 /* Reserved ? */
1667 if (readdir_attr_data &&
1668 readdir_attr_data->type == RDATTR_AAPL) {
1670 * OS X specific SMB2 extension negotiated via
1671 * AAPL create context: return UNIX mode in
1672 * reserved field.
1674 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1675 SSVAL(p, 0, aapl_mode);
1676 } else {
1677 SSVAL(p, 0, 0);
1679 p += 2;
1681 SBVAL(p,0,file_id); p += 8;
1682 status = srvstr_push(base_data, flags2, p,
1683 fname, PTR_DIFF(end_data, p),
1684 STR_TERMINATE_ASCII, &len);
1685 if (!NT_STATUS_IS_OK(status)) {
1686 return status;
1688 SIVAL(q,0,len);
1689 p += len;
1691 len = PTR_DIFF(p, pdata);
1692 pad = (len + (align-1)) & ~(align-1);
1694 * offset to the next entry, the caller
1695 * will overwrite it for the last entry
1696 * that's why we always include the padding
1698 SIVAL(pdata,0,pad);
1700 * set padding to zero
1702 if (do_pad) {
1703 memset(p, 0, pad - len);
1704 p = pdata + pad;
1705 } else {
1706 p = pdata + len;
1708 break;
1710 /* CIFS UNIX Extension. */
1712 case SMB_FIND_FILE_UNIX:
1713 case SMB_FIND_FILE_UNIX_INFO2:
1714 p+= 4;
1715 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1717 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1719 if (info_level == SMB_FIND_FILE_UNIX) {
1720 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1721 p = store_file_unix_basic(conn, p,
1722 NULL, &smb_fname->st);
1723 status = srvstr_push(base_data, flags2, p,
1724 fname, PTR_DIFF(end_data, p),
1725 STR_TERMINATE, &len);
1726 if (!NT_STATUS_IS_OK(status)) {
1727 return status;
1729 } else {
1730 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1731 p = store_file_unix_basic_info2(conn, p,
1732 NULL, &smb_fname->st);
1733 nameptr = p;
1734 p += 4;
1735 status = srvstr_push(base_data, flags2, p, fname,
1736 PTR_DIFF(end_data, p), 0, &len);
1737 if (!NT_STATUS_IS_OK(status)) {
1738 return status;
1740 SIVAL(nameptr, 0, len);
1743 p += len;
1745 len = PTR_DIFF(p, pdata);
1746 pad = (len + (align-1)) & ~(align-1);
1748 * offset to the next entry, the caller
1749 * will overwrite it for the last entry
1750 * that's why we always include the padding
1752 SIVAL(pdata,0,pad);
1754 * set padding to zero
1756 if (do_pad) {
1757 memset(p, 0, pad - len);
1758 p = pdata + pad;
1759 } else {
1760 p = pdata + len;
1762 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1764 break;
1766 /* SMB2 UNIX Extension. */
1768 case SMB2_FILE_POSIX_INFORMATION:
1770 uint8_t *buf = NULL;
1771 ssize_t plen = 0;
1772 p+= 4;
1773 SIVAL(p,0,reskey); p+= 4;
1775 DEBUG(10,("smbd_marshall_dir_entry: "
1776 "SMB2_FILE_POSIX_INFORMATION\n"));
1777 if (!(conn->sconn->using_smb2)) {
1778 return NT_STATUS_INVALID_LEVEL;
1780 if (!lp_smb3_unix_extensions()) {
1781 return NT_STATUS_INVALID_LEVEL;
1784 /* Determine the size of the posix info context */
1785 plen = store_smb2_posix_info(conn,
1786 &smb_fname->st,
1788 mode,
1789 NULL,
1791 if (plen == -1) {
1792 return NT_STATUS_INVALID_PARAMETER;
1794 buf = talloc_zero_size(ctx, plen);
1795 if (buf == NULL) {
1796 return NT_STATUS_NO_MEMORY;
1799 /* Store the context in buf */
1800 store_smb2_posix_info(conn,
1801 &smb_fname->st,
1803 mode,
1804 buf,
1805 plen);
1806 memcpy(p, buf, plen);
1807 p += plen;
1808 TALLOC_FREE(buf);
1810 nameptr = p;
1811 p += 4;
1812 status = srvstr_push(base_data, flags2, p, fname,
1813 PTR_DIFF(end_data, p), 0, &len);
1814 if (!NT_STATUS_IS_OK(status)) {
1815 return status;
1817 SIVAL(nameptr, 0, len);
1819 p += len;
1821 len = PTR_DIFF(p, pdata);
1822 pad = (len + (align-1)) & ~(align-1);
1824 * offset to the next entry, the caller
1825 * will overwrite it for the last entry
1826 * that's why we always include the padding
1828 SIVAL(pdata,0,pad);
1829 break;
1832 default:
1833 return NT_STATUS_INVALID_LEVEL;
1836 if (PTR_DIFF(p,pdata) > space_remaining) {
1837 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1838 "(wanted %u, had %d)\n",
1839 (unsigned int)PTR_DIFF(p,pdata),
1840 space_remaining ));
1841 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1844 /* Setup the last entry pointer, as an offset from base_data */
1845 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1846 /* Advance the data pointer to the next slot */
1847 *ppdata = p;
1849 return NT_STATUS_OK;
1852 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1853 connection_struct *conn,
1854 struct dptr_struct *dirptr,
1855 uint16_t flags2,
1856 const char *path_mask,
1857 uint32_t dirtype,
1858 int info_level,
1859 int requires_resume_key,
1860 bool dont_descend,
1861 bool ask_sharemode,
1862 bool get_dosmode,
1863 uint8_t align,
1864 bool do_pad,
1865 char **ppdata,
1866 char *base_data,
1867 char *end_data,
1868 int space_remaining,
1869 struct smb_filename **_smb_fname,
1870 int *_last_entry_off,
1871 struct ea_list *name_list,
1872 struct file_id *file_id)
1874 const char *p;
1875 const char *mask = NULL;
1876 uint32_t mode = 0;
1877 char *fname = NULL;
1878 struct smb_filename *smb_fname = NULL;
1879 struct smbd_dirptr_lanman2_state state;
1880 bool ok;
1881 uint64_t last_entry_off = 0;
1882 NTSTATUS status;
1883 enum mangled_names_options mangled_names;
1884 bool marshall_with_83_names;
1886 mangled_names = lp_mangled_names(conn->params);
1888 ZERO_STRUCT(state);
1889 state.conn = conn;
1890 state.info_level = info_level;
1891 if (mangled_names != MANGLED_NAMES_NO) {
1892 state.check_mangled_names = true;
1894 state.case_sensitive = dptr_case_sensitive(dirptr);
1896 p = strrchr_m(path_mask,'/');
1897 if(p != NULL) {
1898 if(p[1] == '\0') {
1899 mask = "*.*";
1900 } else {
1901 mask = p+1;
1903 } else {
1904 mask = path_mask;
1907 ok = smbd_dirptr_get_entry(ctx,
1908 dirptr,
1909 mask,
1910 dirtype,
1911 dont_descend,
1912 ask_sharemode,
1913 get_dosmode,
1914 smbd_dirptr_lanman2_match_fn,
1915 smbd_dirptr_lanman2_mode_fn,
1916 &state,
1917 &fname,
1918 &smb_fname,
1919 &mode);
1920 if (!ok) {
1921 return NT_STATUS_END_OF_FILE;
1924 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1926 status = smbd_marshall_dir_entry(ctx,
1927 conn,
1928 flags2,
1929 info_level,
1930 name_list,
1931 marshall_with_83_names,
1932 requires_resume_key,
1933 mode,
1934 fname,
1935 smb_fname,
1936 space_remaining,
1937 align,
1938 do_pad,
1939 base_data,
1940 ppdata,
1941 end_data,
1942 &last_entry_off);
1943 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1944 DEBUG(1,("Conversion error: illegal character: %s\n",
1945 smb_fname_str_dbg(smb_fname)));
1948 if (file_id != NULL) {
1949 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1952 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1953 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1956 if (!NT_STATUS_IS_OK(status)) {
1957 TALLOC_FREE(smb_fname);
1958 TALLOC_FREE(fname);
1959 return status;
1962 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1964 if (_smb_fname != NULL) {
1966 * smb_fname is already talloc'ed off ctx.
1967 * We just need to make sure we don't return
1968 * any stream_name, and replace base_name
1969 * with fname in case base_name got mangled.
1970 * This allows us to preserve any smb_fname->fsp
1971 * for asynchronous handle lookups.
1973 TALLOC_FREE(smb_fname->stream_name);
1976 * smbd_dirptr_set_last_name_sent() above consumed
1977 * base_name
1979 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1981 if (smb_fname->base_name == NULL) {
1982 TALLOC_FREE(smb_fname);
1983 TALLOC_FREE(fname);
1984 return NT_STATUS_NO_MEMORY;
1986 *_smb_fname = smb_fname;
1987 } else {
1988 TALLOC_FREE(smb_fname);
1990 TALLOC_FREE(fname);
1992 *_last_entry_off = last_entry_off;
1993 return NT_STATUS_OK;
1996 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1998 const struct loadparm_substitution *lp_sub =
1999 loadparm_s3_global_substitution();
2001 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
2002 return objid;
2005 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2007 SMB_ASSERT(extended_info != NULL);
2009 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2010 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2011 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2012 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2013 #ifdef SAMBA_VERSION_REVISION
2014 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2015 #endif
2016 extended_info->samba_subversion = 0;
2017 #ifdef SAMBA_VERSION_RC_RELEASE
2018 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2019 #else
2020 #ifdef SAMBA_VERSION_PRE_RELEASE
2021 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2022 #endif
2023 #endif
2024 #ifdef SAMBA_VERSION_VENDOR_PATCH
2025 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2026 #endif
2027 extended_info->samba_gitcommitdate = 0;
2028 #ifdef SAMBA_VERSION_COMMIT_TIME
2029 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2030 #endif
2032 memset(extended_info->samba_version_string, 0,
2033 sizeof(extended_info->samba_version_string));
2035 snprintf (extended_info->samba_version_string,
2036 sizeof(extended_info->samba_version_string),
2037 "%s", samba_version_string());
2040 static bool fsinfo_unix_valid_level(connection_struct *conn,
2041 uint16_t info_level)
2043 if (conn->sconn->using_smb2 &&
2044 lp_smb3_unix_extensions() &&
2045 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
2046 return true;
2048 #if defined(SMB1SERVER)
2049 if (lp_smb1_unix_extensions() &&
2050 info_level == SMB_QUERY_POSIX_FS_INFO) {
2051 return true;
2053 #endif
2054 return false;
2057 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2058 connection_struct *conn,
2059 TALLOC_CTX *mem_ctx,
2060 uint16_t info_level,
2061 uint16_t flags2,
2062 unsigned int max_data_bytes,
2063 size_t *fixed_portion,
2064 struct smb_filename *fname,
2065 char **ppdata,
2066 int *ret_data_len)
2068 const struct loadparm_substitution *lp_sub =
2069 loadparm_s3_global_substitution();
2070 char *pdata, *end_data;
2071 int data_len = 0;
2072 size_t len = 0;
2073 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2074 int snum = SNUM(conn);
2075 const char *fstype = lp_fstype(SNUM(conn));
2076 const char *filename = NULL;
2077 const uint64_t bytes_per_sector = 512;
2078 uint32_t additional_flags = 0;
2079 struct smb_filename smb_fname;
2080 SMB_STRUCT_STAT st;
2081 NTSTATUS status = NT_STATUS_OK;
2082 uint64_t df_ret;
2083 uint32_t serial;
2085 if (fname == NULL || fname->base_name == NULL) {
2086 filename = ".";
2087 } else {
2088 filename = fname->base_name;
2091 if (IS_IPC(conn)) {
2092 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2093 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2094 "info level (0x%x) on IPC$.\n",
2095 (unsigned int)info_level));
2096 return NT_STATUS_ACCESS_DENIED;
2100 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2102 smb_fname = (struct smb_filename) {
2103 .base_name = discard_const_p(char, filename),
2104 .flags = fname ? fname->flags : 0,
2105 .twrp = fname ? fname->twrp : 0,
2108 if(info_level != SMB_FS_QUOTA_INFORMATION
2109 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2110 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2111 return map_nt_error_from_unix(errno);
2114 st = smb_fname.st;
2116 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2117 return NT_STATUS_INVALID_PARAMETER;
2120 *ppdata = (char *)SMB_REALLOC(
2121 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2122 if (*ppdata == NULL) {
2123 return NT_STATUS_NO_MEMORY;
2126 pdata = *ppdata;
2127 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2128 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2130 *fixed_portion = 0;
2132 switch (info_level) {
2133 case SMB_INFO_ALLOCATION:
2135 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2136 data_len = 18;
2137 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2138 &dfree, &dsize);
2139 if (df_ret == (uint64_t)-1) {
2140 return map_nt_error_from_unix(errno);
2143 block_size = lp_block_size(snum);
2144 if (bsize < block_size) {
2145 uint64_t factor = block_size/bsize;
2146 bsize = block_size;
2147 dsize /= factor;
2148 dfree /= factor;
2150 if (bsize > block_size) {
2151 uint64_t factor = bsize/block_size;
2152 bsize = block_size;
2153 dsize *= factor;
2154 dfree *= factor;
2156 sectors_per_unit = bsize/bytes_per_sector;
2158 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2159 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2160 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2163 * For large drives, return max values and not modulo.
2165 dsize = MIN(dsize, UINT32_MAX);
2166 dfree = MIN(dfree, UINT32_MAX);
2168 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2169 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2170 SIVAL(pdata,l1_cUnit,dsize);
2171 SIVAL(pdata,l1_cUnitAvail,dfree);
2172 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2173 break;
2176 case SMB_INFO_VOLUME:
2177 /* Return volume name */
2179 * Add volume serial number - hash of a combination of
2180 * the called hostname and the service name.
2182 serial = generate_volume_serial_number(lp_sub, snum);
2183 SIVAL(pdata,0,serial);
2185 * Win2k3 and previous mess this up by sending a name length
2186 * one byte short. I believe only older clients (OS/2 Win9x) use
2187 * this call so try fixing this by adding a terminating null to
2188 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2190 status = srvstr_push(
2191 pdata, flags2,
2192 pdata+l2_vol_szVolLabel, vname,
2193 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2194 STR_NOALIGN|STR_TERMINATE, &len);
2195 if (!NT_STATUS_IS_OK(status)) {
2196 return status;
2198 SCVAL(pdata,l2_vol_cch,len);
2199 data_len = l2_vol_szVolLabel + len;
2200 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2201 "name = %s serial = 0x%04"PRIx32"\n",
2202 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2203 (unsigned)len, vname, serial));
2204 break;
2206 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2207 case SMB_FS_ATTRIBUTE_INFORMATION:
2209 additional_flags = 0;
2210 #if defined(HAVE_SYS_QUOTAS)
2211 additional_flags |= FILE_VOLUME_QUOTAS;
2212 #endif
2214 if(lp_nt_acl_support(SNUM(conn))) {
2215 additional_flags |= FILE_PERSISTENT_ACLS;
2218 /* Capabilities are filled in at connection time through STATVFS call */
2219 additional_flags |= conn->fs_capabilities;
2220 additional_flags |= lp_parm_int(conn->params->service,
2221 "share", "fake_fscaps",
2224 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2225 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2226 additional_flags); /* FS ATTRIBUTES */
2228 SIVAL(pdata,4,255); /* Max filename component length */
2229 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2230 and will think we can't do long filenames */
2231 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2232 PTR_DIFF(end_data, pdata+12),
2233 STR_UNICODE, &len);
2234 if (!NT_STATUS_IS_OK(status)) {
2235 return status;
2237 SIVAL(pdata,8,len);
2238 data_len = 12 + len;
2239 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2240 /* the client only requested a portion of the
2241 file system name */
2242 data_len = max_data_bytes;
2243 status = STATUS_BUFFER_OVERFLOW;
2245 *fixed_portion = 16;
2246 break;
2248 case SMB_QUERY_FS_LABEL_INFO:
2249 case SMB_FS_LABEL_INFORMATION:
2250 status = srvstr_push(pdata, flags2, pdata+4, vname,
2251 PTR_DIFF(end_data, pdata+4), 0, &len);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 return status;
2255 data_len = 4 + len;
2256 SIVAL(pdata,0,len);
2257 break;
2259 case SMB_QUERY_FS_VOLUME_INFO:
2260 case SMB_FS_VOLUME_INFORMATION:
2261 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2262 pdata, &st.st_ex_btime);
2264 * Add volume serial number - hash of a combination of
2265 * the called hostname and the service name.
2267 serial = generate_volume_serial_number(lp_sub, snum);
2268 SIVAL(pdata,8,serial);
2270 /* Max label len is 32 characters. */
2271 status = srvstr_push(pdata, flags2, pdata+18, vname,
2272 PTR_DIFF(end_data, pdata+18),
2273 STR_UNICODE, &len);
2274 if (!NT_STATUS_IS_OK(status)) {
2275 return status;
2277 SIVAL(pdata,12,len);
2278 data_len = 18+len;
2280 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2281 "namelen = %d, vol=%s serv=%s "
2282 "serial=0x%04"PRIx32"\n",
2283 (int)strlen(vname),vname,
2284 lp_servicename(talloc_tos(), lp_sub, snum),
2285 serial));
2286 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2287 /* the client only requested a portion of the
2288 volume label */
2289 data_len = max_data_bytes;
2290 status = STATUS_BUFFER_OVERFLOW;
2292 *fixed_portion = 24;
2293 break;
2295 case SMB_QUERY_FS_SIZE_INFO:
2296 case SMB_FS_SIZE_INFORMATION:
2298 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2299 data_len = 24;
2300 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2301 &dfree, &dsize);
2302 if (df_ret == (uint64_t)-1) {
2303 return map_nt_error_from_unix(errno);
2305 block_size = lp_block_size(snum);
2306 if (bsize < block_size) {
2307 uint64_t factor = block_size/bsize;
2308 bsize = block_size;
2309 dsize /= factor;
2310 dfree /= factor;
2312 if (bsize > block_size) {
2313 uint64_t factor = bsize/block_size;
2314 bsize = block_size;
2315 dsize *= factor;
2316 dfree *= factor;
2318 sectors_per_unit = bsize/bytes_per_sector;
2319 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2320 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2321 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2322 SBIG_UINT(pdata,0,dsize);
2323 SBIG_UINT(pdata,8,dfree);
2324 SIVAL(pdata,16,sectors_per_unit);
2325 SIVAL(pdata,20,bytes_per_sector);
2326 *fixed_portion = 24;
2327 break;
2330 case SMB_FS_FULL_SIZE_INFORMATION:
2332 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2333 data_len = 32;
2334 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2335 &dfree, &dsize);
2336 if (df_ret == (uint64_t)-1) {
2337 return map_nt_error_from_unix(errno);
2339 block_size = lp_block_size(snum);
2340 if (bsize < block_size) {
2341 uint64_t factor = block_size/bsize;
2342 bsize = block_size;
2343 dsize /= factor;
2344 dfree /= factor;
2346 if (bsize > block_size) {
2347 uint64_t factor = bsize/block_size;
2348 bsize = block_size;
2349 dsize *= factor;
2350 dfree *= factor;
2352 sectors_per_unit = bsize/bytes_per_sector;
2353 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2354 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2355 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2356 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2357 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2358 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2359 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2360 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2361 *fixed_portion = 32;
2362 break;
2365 case SMB_QUERY_FS_DEVICE_INFO:
2366 case SMB_FS_DEVICE_INFORMATION:
2368 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2370 if (!CAN_WRITE(conn)) {
2371 characteristics |= FILE_READ_ONLY_DEVICE;
2373 data_len = 8;
2374 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2375 SIVAL(pdata,4,characteristics);
2376 *fixed_portion = 8;
2377 break;
2380 #ifdef HAVE_SYS_QUOTAS
2381 case SMB_FS_QUOTA_INFORMATION:
2383 * what we have to send --metze:
2385 * Unknown1: 24 NULL bytes
2386 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2387 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2388 * Quota Flags: 2 byte :
2389 * Unknown3: 6 NULL bytes
2391 * 48 bytes total
2393 * details for Quota Flags:
2395 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2396 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2397 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2398 * 0x0001 Enable Quotas: enable quota for this fs
2402 /* we need to fake up a fsp here,
2403 * because its not send in this call
2405 files_struct fsp;
2406 SMB_NTQUOTA_STRUCT quotas;
2408 ZERO_STRUCT(fsp);
2409 ZERO_STRUCT(quotas);
2411 fsp.conn = conn;
2412 fsp.fnum = FNUM_FIELD_INVALID;
2414 /* access check */
2415 if (get_current_uid(conn) != 0) {
2416 DEBUG(0,("get_user_quota: access_denied "
2417 "service [%s] user [%s]\n",
2418 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2419 conn->session_info->unix_info->unix_name));
2420 return NT_STATUS_ACCESS_DENIED;
2423 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2424 NULL, &quotas);
2425 if (!NT_STATUS_IS_OK(status)) {
2426 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2427 return status;
2430 data_len = 48;
2432 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2433 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2435 /* Unknown1 24 NULL bytes*/
2436 SBIG_UINT(pdata,0,(uint64_t)0);
2437 SBIG_UINT(pdata,8,(uint64_t)0);
2438 SBIG_UINT(pdata,16,(uint64_t)0);
2440 /* Default Soft Quota 8 bytes */
2441 SBIG_UINT(pdata,24,quotas.softlim);
2443 /* Default Hard Quota 8 bytes */
2444 SBIG_UINT(pdata,32,quotas.hardlim);
2446 /* Quota flag 2 bytes */
2447 SSVAL(pdata,40,quotas.qflags);
2449 /* Unknown3 6 NULL bytes */
2450 SSVAL(pdata,42,0);
2451 SIVAL(pdata,44,0);
2453 break;
2455 #endif /* HAVE_SYS_QUOTAS */
2456 case SMB_FS_OBJECTID_INFORMATION:
2458 unsigned char objid[16];
2459 struct smb_extended_info extended_info;
2460 memcpy(pdata,create_volume_objectid(conn, objid),16);
2461 samba_extended_info_version (&extended_info);
2462 SIVAL(pdata,16,extended_info.samba_magic);
2463 SIVAL(pdata,20,extended_info.samba_version);
2464 SIVAL(pdata,24,extended_info.samba_subversion);
2465 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2466 memcpy(pdata+36,extended_info.samba_version_string,28);
2467 data_len = 64;
2468 break;
2471 case SMB_FS_SECTOR_SIZE_INFORMATION:
2473 data_len = 28;
2475 * These values match a physical Windows Server 2012
2476 * share backed by NTFS atop spinning rust.
2478 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2479 /* logical_bytes_per_sector */
2480 SIVAL(pdata, 0, bytes_per_sector);
2481 /* phys_bytes_per_sector_atomic */
2482 SIVAL(pdata, 4, bytes_per_sector);
2483 /* phys_bytes_per_sector_perf */
2484 SIVAL(pdata, 8, bytes_per_sector);
2485 /* fs_effective_phys_bytes_per_sector_atomic */
2486 SIVAL(pdata, 12, bytes_per_sector);
2487 /* flags */
2488 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2489 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2490 /* byte_off_sector_align */
2491 SIVAL(pdata, 20, 0);
2492 /* byte_off_partition_align */
2493 SIVAL(pdata, 24, 0);
2494 *fixed_portion = 28;
2495 break;
2499 #if defined(WITH_SMB1SERVER)
2501 * Query the version and capabilities of the CIFS UNIX extensions
2502 * in use.
2505 case SMB_QUERY_CIFS_UNIX_INFO:
2507 bool large_write = lp_min_receive_file_size() &&
2508 !smb1_srv_is_signing_active(xconn);
2509 bool large_read = !smb1_srv_is_signing_active(xconn);
2510 int encrypt_caps = 0;
2512 if (!lp_smb1_unix_extensions()) {
2513 return NT_STATUS_INVALID_LEVEL;
2516 switch (conn->encrypt_level) {
2517 case SMB_SIGNING_OFF:
2518 encrypt_caps = 0;
2519 break;
2520 case SMB_SIGNING_DESIRED:
2521 case SMB_SIGNING_IF_REQUIRED:
2522 case SMB_SIGNING_DEFAULT:
2523 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2524 break;
2525 case SMB_SIGNING_REQUIRED:
2526 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2527 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2528 large_write = false;
2529 large_read = false;
2530 break;
2533 data_len = 12;
2534 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2535 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2537 /* We have POSIX ACLs, pathname, encryption,
2538 * large read/write, and locking capability. */
2540 SBIG_UINT(pdata,4,((uint64_t)(
2541 CIFS_UNIX_POSIX_ACLS_CAP|
2542 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2543 CIFS_UNIX_FCNTL_LOCKS_CAP|
2544 CIFS_UNIX_EXTATTR_CAP|
2545 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2546 encrypt_caps|
2547 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2548 (large_write ?
2549 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2550 break;
2552 #endif
2554 case SMB_QUERY_POSIX_FS_INFO:
2555 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2557 int rc;
2558 struct vfs_statvfs_struct svfs;
2560 if (!fsinfo_unix_valid_level(conn, info_level)) {
2561 return NT_STATUS_INVALID_LEVEL;
2564 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2566 if (!rc) {
2567 data_len = 56;
2568 SIVAL(pdata,0,svfs.OptimalTransferSize);
2569 SIVAL(pdata,4,svfs.BlockSize);
2570 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2571 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2572 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2573 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2574 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2575 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2576 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2577 #ifdef EOPNOTSUPP
2578 } else if (rc == EOPNOTSUPP) {
2579 return NT_STATUS_INVALID_LEVEL;
2580 #endif /* EOPNOTSUPP */
2581 } else {
2582 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2583 return NT_STATUS_DOS(ERRSRV, ERRerror);
2585 break;
2588 case SMB_QUERY_POSIX_WHOAMI:
2590 uint32_t flags = 0;
2591 uint32_t sid_bytes;
2592 uint32_t i;
2594 if (!lp_smb1_unix_extensions()) {
2595 return NT_STATUS_INVALID_LEVEL;
2598 if (max_data_bytes < 40) {
2599 return NT_STATUS_BUFFER_TOO_SMALL;
2602 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2603 flags |= SMB_WHOAMI_GUEST;
2606 /* NOTE: 8 bytes for UID/GID, irrespective of native
2607 * platform size. This matches
2608 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2610 data_len = 4 /* flags */
2611 + 4 /* flag mask */
2612 + 8 /* uid */
2613 + 8 /* gid */
2614 + 4 /* ngroups */
2615 + 4 /* num_sids */
2616 + 4 /* SID bytes */
2617 + 4 /* pad/reserved */
2618 + (conn->session_info->unix_token->ngroups * 8)
2619 /* groups list */
2620 + (conn->session_info->security_token->num_sids *
2621 SID_MAX_SIZE)
2622 /* SID list */;
2624 SIVAL(pdata, 0, flags);
2625 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2626 SBIG_UINT(pdata, 8,
2627 (uint64_t)conn->session_info->unix_token->uid);
2628 SBIG_UINT(pdata, 16,
2629 (uint64_t)conn->session_info->unix_token->gid);
2632 if (data_len >= max_data_bytes) {
2633 /* Potential overflow, skip the GIDs and SIDs. */
2635 SIVAL(pdata, 24, 0); /* num_groups */
2636 SIVAL(pdata, 28, 0); /* num_sids */
2637 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2638 SIVAL(pdata, 36, 0); /* reserved */
2640 data_len = 40;
2641 break;
2644 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2645 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2647 /* We walk the SID list twice, but this call is fairly
2648 * infrequent, and I don't expect that it's performance
2649 * sensitive -- jpeach
2651 for (i = 0, sid_bytes = 0;
2652 i < conn->session_info->security_token->num_sids; ++i) {
2653 sid_bytes += ndr_size_dom_sid(
2654 &conn->session_info->security_token->sids[i],
2658 /* SID list byte count */
2659 SIVAL(pdata, 32, sid_bytes);
2661 /* 4 bytes pad/reserved - must be zero */
2662 SIVAL(pdata, 36, 0);
2663 data_len = 40;
2665 /* GID list */
2666 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2667 SBIG_UINT(pdata, data_len,
2668 (uint64_t)conn->session_info->unix_token->groups[i]);
2669 data_len += 8;
2672 /* SID list */
2673 for (i = 0;
2674 i < conn->session_info->security_token->num_sids; ++i) {
2675 int sid_len = ndr_size_dom_sid(
2676 &conn->session_info->security_token->sids[i],
2679 sid_linearize((uint8_t *)(pdata + data_len),
2680 sid_len,
2681 &conn->session_info->security_token->sids[i]);
2682 data_len += sid_len;
2685 break;
2688 case SMB_MAC_QUERY_FS_INFO:
2690 * Thursby MAC extension... ONLY on NTFS filesystems
2691 * once we do streams then we don't need this
2693 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2694 data_len = 88;
2695 SIVAL(pdata,84,0x100); /* Don't support mac... */
2696 break;
2699 FALL_THROUGH;
2700 default:
2701 return NT_STATUS_INVALID_LEVEL;
2704 *ret_data_len = data_len;
2705 return status;
2708 NTSTATUS smb_set_fsquota(connection_struct *conn,
2709 struct smb_request *req,
2710 files_struct *fsp,
2711 const DATA_BLOB *qdata)
2713 const struct loadparm_substitution *lp_sub =
2714 loadparm_s3_global_substitution();
2715 NTSTATUS status;
2716 SMB_NTQUOTA_STRUCT quotas;
2718 ZERO_STRUCT(quotas);
2720 /* access check */
2721 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2722 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2723 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2724 conn->session_info->unix_info->unix_name));
2725 return NT_STATUS_ACCESS_DENIED;
2728 if (!check_fsp_ntquota_handle(conn, req,
2729 fsp)) {
2730 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2731 return NT_STATUS_INVALID_HANDLE;
2734 /* note: normally there're 48 bytes,
2735 * but we didn't use the last 6 bytes for now
2736 * --metze
2738 if (qdata->length < 42) {
2739 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2740 (unsigned int)qdata->length));
2741 return NT_STATUS_INVALID_PARAMETER;
2744 /* unknown_1 24 NULL bytes in pdata*/
2746 /* the soft quotas 8 bytes (uint64_t)*/
2747 quotas.softlim = BVAL(qdata->data,24);
2749 /* the hard quotas 8 bytes (uint64_t)*/
2750 quotas.hardlim = BVAL(qdata->data,32);
2752 /* quota_flags 2 bytes **/
2753 quotas.qflags = SVAL(qdata->data,40);
2755 /* unknown_2 6 NULL bytes follow*/
2757 /* now set the quotas */
2758 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2759 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2760 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2761 status = map_nt_error_from_unix(errno);
2762 } else {
2763 status = NT_STATUS_OK;
2765 return status;
2768 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2769 struct smb_request *req,
2770 TALLOC_CTX *mem_ctx,
2771 uint16_t info_level,
2772 files_struct *fsp,
2773 const DATA_BLOB *pdata)
2775 switch (info_level) {
2776 case SMB_FS_QUOTA_INFORMATION:
2778 return smb_set_fsquota(conn,
2779 req,
2780 fsp,
2781 pdata);
2784 default:
2785 break;
2787 return NT_STATUS_INVALID_LEVEL;
2790 /****************************************************************************
2791 Store the FILE_UNIX_BASIC info.
2792 ****************************************************************************/
2794 char *store_file_unix_basic(connection_struct *conn,
2795 char *pdata,
2796 files_struct *fsp,
2797 const SMB_STRUCT_STAT *psbuf)
2799 dev_t devno;
2801 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2802 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
2804 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2805 pdata += 8;
2807 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2808 pdata += 8;
2810 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2811 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2812 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2813 pdata += 24;
2815 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2816 SIVAL(pdata,4,0);
2817 pdata += 8;
2819 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2820 SIVAL(pdata,4,0);
2821 pdata += 8;
2823 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2824 pdata += 4;
2826 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2827 devno = psbuf->st_ex_rdev;
2828 } else {
2829 devno = psbuf->st_ex_dev;
2832 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2833 SIVAL(pdata,4,0);
2834 pdata += 8;
2836 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2837 SIVAL(pdata,4,0);
2838 pdata += 8;
2840 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2841 pdata += 8;
2843 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2844 SIVAL(pdata,4,0);
2845 pdata += 8;
2847 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2848 SIVAL(pdata,4,0);
2849 pdata += 8;
2851 return pdata;
2854 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2855 * the chflags(2) (or equivalent) flags.
2857 * XXX: this really should be behind the VFS interface. To do this, we would
2858 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2859 * Each VFS module could then implement its own mapping as appropriate for the
2860 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2862 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2863 info2_flags_map[] =
2865 #ifdef UF_NODUMP
2866 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2867 #endif
2869 #ifdef UF_IMMUTABLE
2870 { UF_IMMUTABLE, EXT_IMMUTABLE },
2871 #endif
2873 #ifdef UF_APPEND
2874 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2875 #endif
2877 #ifdef UF_HIDDEN
2878 { UF_HIDDEN, EXT_HIDDEN },
2879 #endif
2881 /* Do not remove. We need to guarantee that this array has at least one
2882 * entry to build on HP-UX.
2884 { 0, 0 }
2888 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2889 uint32_t *smb_fflags, uint32_t *smb_fmask)
2891 size_t i;
2893 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2894 *smb_fmask |= info2_flags_map[i].smb_fflag;
2895 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2896 *smb_fflags |= info2_flags_map[i].smb_fflag;
2901 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2902 const uint32_t smb_fflags,
2903 const uint32_t smb_fmask,
2904 int *stat_fflags)
2906 uint32_t max_fmask = 0;
2907 size_t i;
2909 *stat_fflags = psbuf->st_ex_flags;
2911 /* For each flags requested in smb_fmask, check the state of the
2912 * corresponding flag in smb_fflags and set or clear the matching
2913 * stat flag.
2916 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2917 max_fmask |= info2_flags_map[i].smb_fflag;
2918 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2919 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2920 *stat_fflags |= info2_flags_map[i].stat_fflag;
2921 } else {
2922 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2927 /* If smb_fmask is asking to set any bits that are not supported by
2928 * our flag mappings, we should fail.
2930 if ((smb_fmask & max_fmask) != smb_fmask) {
2931 return False;
2934 return True;
2938 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2939 * of file flags and birth (create) time.
2941 char *store_file_unix_basic_info2(connection_struct *conn,
2942 char *pdata,
2943 files_struct *fsp,
2944 const SMB_STRUCT_STAT *psbuf)
2946 uint32_t file_flags = 0;
2947 uint32_t flags_mask = 0;
2949 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2951 /* Create (birth) time 64 bit */
2952 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2953 pdata += 8;
2955 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2956 SIVAL(pdata, 0, file_flags); /* flags */
2957 SIVAL(pdata, 4, flags_mask); /* mask */
2958 pdata += 8;
2960 return pdata;
2963 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2964 const struct stream_struct *streams,
2965 char *data,
2966 unsigned int max_data_bytes,
2967 unsigned int *data_size)
2969 unsigned int i;
2970 unsigned int ofs = 0;
2972 if (max_data_bytes < 32) {
2973 return NT_STATUS_INFO_LENGTH_MISMATCH;
2976 for (i = 0; i < num_streams; i++) {
2977 unsigned int next_offset;
2978 size_t namelen;
2979 smb_ucs2_t *namebuf;
2981 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2982 streams[i].name, &namelen) ||
2983 namelen <= 2)
2985 return NT_STATUS_INVALID_PARAMETER;
2989 * name_buf is now null-terminated, we need to marshall as not
2990 * terminated
2993 namelen -= 2;
2996 * We cannot overflow ...
2998 if ((ofs + 24 + namelen) > max_data_bytes) {
2999 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3000 i));
3001 TALLOC_FREE(namebuf);
3002 return STATUS_BUFFER_OVERFLOW;
3005 SIVAL(data, ofs+4, namelen);
3006 SOFF_T(data, ofs+8, streams[i].size);
3007 SOFF_T(data, ofs+16, streams[i].alloc_size);
3008 memcpy(data+ofs+24, namebuf, namelen);
3009 TALLOC_FREE(namebuf);
3011 next_offset = ofs + 24 + namelen;
3013 if (i == num_streams-1) {
3014 SIVAL(data, ofs, 0);
3016 else {
3017 unsigned int align = ndr_align_size(next_offset, 8);
3019 if ((next_offset + align) > max_data_bytes) {
3020 DEBUG(10, ("refusing to overflow align "
3021 "reply at stream %u\n",
3022 i));
3023 TALLOC_FREE(namebuf);
3024 return STATUS_BUFFER_OVERFLOW;
3027 memset(data+next_offset, 0, align);
3028 next_offset += align;
3030 SIVAL(data, ofs, next_offset - ofs);
3031 ofs = next_offset;
3034 ofs = next_offset;
3037 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
3039 *data_size = ofs;
3041 return NT_STATUS_OK;
3044 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3045 TALLOC_CTX *mem_ctx,
3046 struct smb_request *req,
3047 uint16_t info_level,
3048 files_struct *fsp,
3049 struct smb_filename *smb_fname,
3050 bool delete_pending,
3051 struct timespec write_time_ts,
3052 struct ea_list *ea_list,
3053 uint16_t flags2,
3054 unsigned int max_data_bytes,
3055 size_t *fixed_portion,
3056 char **ppdata,
3057 unsigned int *pdata_size)
3059 char *pdata = *ppdata;
3060 char *dstart, *dend;
3061 unsigned int data_size;
3062 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3063 time_t create_time, mtime, atime, c_time;
3064 SMB_STRUCT_STAT *psbuf = NULL;
3065 SMB_STRUCT_STAT *base_sp = NULL;
3066 char *p;
3067 char *base_name;
3068 char *dos_fname;
3069 int mode;
3070 int nlink;
3071 NTSTATUS status;
3072 uint64_t file_size = 0;
3073 uint64_t pos = 0;
3074 uint64_t allocation_size = 0;
3075 uint64_t file_id = 0;
3076 uint32_t access_mask = 0;
3077 size_t len = 0;
3079 if (INFO_LEVEL_IS_UNIX(info_level)) {
3080 bool ok = false;
3082 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3083 DBG_DEBUG("SMB1 unix extensions activated\n");
3084 ok = true;
3087 if (lp_smb3_unix_extensions() &&
3088 (fsp != NULL) &&
3089 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3090 DBG_DEBUG("SMB2 posix open\n");
3091 ok = true;
3094 if (!ok) {
3095 return NT_STATUS_INVALID_LEVEL;
3099 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3100 smb_fname_str_dbg(smb_fname),
3101 fsp_fnum_dbg(fsp),
3102 info_level, max_data_bytes));
3105 * In case of querying a symlink in POSIX context,
3106 * fsp will be NULL. fdos_mode() deals with it.
3108 if (fsp != NULL) {
3109 smb_fname = fsp->fsp_name;
3111 mode = fdos_mode(fsp);
3112 psbuf = &smb_fname->st;
3114 if (fsp != NULL) {
3115 base_sp = fsp->base_fsp ?
3116 &fsp->base_fsp->fsp_name->st :
3117 &fsp->fsp_name->st;
3118 } else {
3119 base_sp = &smb_fname->st;
3122 nlink = psbuf->st_ex_nlink;
3124 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3125 nlink = 1;
3128 if ((nlink > 0) && delete_pending) {
3129 nlink -= 1;
3132 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3133 return NT_STATUS_INVALID_PARAMETER;
3136 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3137 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3138 if (*ppdata == NULL) {
3139 return NT_STATUS_NO_MEMORY;
3141 pdata = *ppdata;
3142 dstart = pdata;
3143 dend = dstart + data_size - 1;
3145 if (!is_omit_timespec(&write_time_ts) &&
3146 !INFO_LEVEL_IS_UNIX(info_level))
3148 update_stat_ex_mtime(psbuf, write_time_ts);
3151 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3152 mtime_ts = psbuf->st_ex_mtime;
3153 atime_ts = psbuf->st_ex_atime;
3154 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3156 if (lp_dos_filetime_resolution(SNUM(conn))) {
3157 dos_filetime_timespec(&create_time_ts);
3158 dos_filetime_timespec(&mtime_ts);
3159 dos_filetime_timespec(&atime_ts);
3160 dos_filetime_timespec(&ctime_ts);
3163 create_time = convert_timespec_to_time_t(create_time_ts);
3164 mtime = convert_timespec_to_time_t(mtime_ts);
3165 atime = convert_timespec_to_time_t(atime_ts);
3166 c_time = convert_timespec_to_time_t(ctime_ts);
3168 p = strrchr_m(smb_fname->base_name,'/');
3169 if (!p)
3170 base_name = smb_fname->base_name;
3171 else
3172 base_name = p+1;
3174 /* NT expects the name to be in an exact form of the *full*
3175 filename. See the trans2 torture test */
3176 if (ISDOT(base_name)) {
3177 dos_fname = talloc_strdup(mem_ctx, "\\");
3178 if (!dos_fname) {
3179 return NT_STATUS_NO_MEMORY;
3181 } else {
3182 dos_fname = talloc_asprintf(mem_ctx,
3183 "\\%s",
3184 smb_fname->base_name);
3185 if (!dos_fname) {
3186 return NT_STATUS_NO_MEMORY;
3188 if (is_named_stream(smb_fname)) {
3189 dos_fname = talloc_asprintf(dos_fname, "%s",
3190 smb_fname->stream_name);
3191 if (!dos_fname) {
3192 return NT_STATUS_NO_MEMORY;
3196 string_replace(dos_fname, '/', '\\');
3199 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3201 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3202 /* Do we have this path open ? */
3203 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3204 files_struct *fsp1 = file_find_di_first(
3205 conn->sconn, fileid, true);
3206 if (fsp1 && fsp1->initial_allocation_size) {
3207 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3211 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3212 file_size = get_file_size_stat(psbuf);
3215 if (fsp) {
3216 pos = fh_get_position_information(fsp->fh);
3219 if (fsp) {
3220 access_mask = fsp->access_mask;
3221 } else {
3222 /* GENERIC_EXECUTE mapping from Windows */
3223 access_mask = 0x12019F;
3226 /* This should be an index number - looks like
3227 dev/ino to me :-)
3229 I think this causes us to fail the IFSKIT
3230 BasicFileInformationTest. -tpot */
3231 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3233 *fixed_portion = 0;
3235 switch (info_level) {
3236 case SMB_INFO_STANDARD:
3237 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3238 data_size = 22;
3239 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3240 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3241 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3242 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3243 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3244 SSVAL(pdata,l1_attrFile,mode);
3245 break;
3247 case SMB_INFO_QUERY_EA_SIZE:
3249 unsigned int ea_size =
3250 estimate_ea_size(smb_fname->fsp);
3251 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3252 data_size = 26;
3253 srv_put_dos_date2(pdata,0,create_time);
3254 srv_put_dos_date2(pdata,4,atime);
3255 srv_put_dos_date2(pdata,8,mtime); /* write time */
3256 SIVAL(pdata,12,(uint32_t)file_size);
3257 SIVAL(pdata,16,(uint32_t)allocation_size);
3258 SSVAL(pdata,20,mode);
3259 SIVAL(pdata,22,ea_size);
3260 break;
3263 case SMB_INFO_IS_NAME_VALID:
3264 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3265 if (fsp) {
3266 /* os/2 needs this ? really ?*/
3267 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3269 /* This is only reached for qpathinfo */
3270 data_size = 0;
3271 break;
3273 case SMB_INFO_QUERY_EAS_FROM_LIST:
3275 size_t total_ea_len = 0;
3276 struct ea_list *ea_file_list = NULL;
3277 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3279 status =
3280 get_ea_list_from_fsp(mem_ctx,
3281 smb_fname->fsp,
3282 &total_ea_len, &ea_file_list);
3283 if (!NT_STATUS_IS_OK(status)) {
3284 return status;
3287 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3289 if (!ea_list || (total_ea_len > data_size)) {
3290 data_size = 4;
3291 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3292 break;
3295 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3296 break;
3299 case SMB_INFO_QUERY_ALL_EAS:
3301 /* We have data_size bytes to put EA's into. */
3302 size_t total_ea_len = 0;
3303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3305 status = get_ea_list_from_fsp(mem_ctx,
3306 smb_fname->fsp,
3307 &total_ea_len, &ea_list);
3308 if (!NT_STATUS_IS_OK(status)) {
3309 return status;
3312 if (!ea_list || (total_ea_len > data_size)) {
3313 data_size = 4;
3314 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3315 break;
3318 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3319 break;
3322 case SMB2_FILE_FULL_EA_INFORMATION:
3324 /* We have data_size bytes to put EA's into. */
3325 size_t total_ea_len = 0;
3326 struct ea_list *ea_file_list = NULL;
3328 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3330 /*TODO: add filtering and index handling */
3332 status =
3333 get_ea_list_from_fsp(mem_ctx,
3334 smb_fname->fsp,
3335 &total_ea_len, &ea_file_list);
3336 if (!NT_STATUS_IS_OK(status)) {
3337 return status;
3339 if (!ea_file_list) {
3340 return NT_STATUS_NO_EAS_ON_FILE;
3343 status = fill_ea_chained_buffer(mem_ctx,
3344 pdata,
3345 data_size,
3346 &data_size,
3347 conn, ea_file_list);
3348 if (!NT_STATUS_IS_OK(status)) {
3349 return status;
3351 break;
3354 case SMB_FILE_BASIC_INFORMATION:
3355 case SMB_QUERY_FILE_BASIC_INFO:
3357 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3358 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3359 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3360 } else {
3361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3362 data_size = 40;
3363 SIVAL(pdata,36,0);
3365 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3366 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3367 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3368 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3369 SIVAL(pdata,32,mode);
3371 DEBUG(5,("SMB_QFBI - "));
3372 DEBUG(5,("create: %s ", ctime(&create_time)));
3373 DEBUG(5,("access: %s ", ctime(&atime)));
3374 DEBUG(5,("write: %s ", ctime(&mtime)));
3375 DEBUG(5,("change: %s ", ctime(&c_time)));
3376 DEBUG(5,("mode: %x\n", mode));
3377 *fixed_portion = data_size;
3378 break;
3380 case SMB_FILE_STANDARD_INFORMATION:
3381 case SMB_QUERY_FILE_STANDARD_INFO:
3383 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3384 data_size = 24;
3385 SOFF_T(pdata,0,allocation_size);
3386 SOFF_T(pdata,8,file_size);
3387 SIVAL(pdata,16,nlink);
3388 SCVAL(pdata,20,delete_pending?1:0);
3389 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3390 SSVAL(pdata,22,0); /* Padding. */
3391 *fixed_portion = 24;
3392 break;
3394 case SMB_FILE_EA_INFORMATION:
3395 case SMB_QUERY_FILE_EA_INFO:
3397 unsigned int ea_size =
3398 estimate_ea_size(smb_fname->fsp);
3399 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3400 data_size = 4;
3401 *fixed_portion = 4;
3402 SIVAL(pdata,0,ea_size);
3403 break;
3406 /* Get the 8.3 name - used if NT SMB was negotiated. */
3407 case SMB_QUERY_FILE_ALT_NAME_INFO:
3408 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3410 char mangled_name[13];
3411 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3412 if (!name_to_8_3(base_name,mangled_name,
3413 True,conn->params)) {
3414 return NT_STATUS_NO_MEMORY;
3416 status = srvstr_push(dstart, flags2,
3417 pdata+4, mangled_name,
3418 PTR_DIFF(dend, pdata+4),
3419 STR_UNICODE, &len);
3420 if (!NT_STATUS_IS_OK(status)) {
3421 return status;
3423 data_size = 4 + len;
3424 SIVAL(pdata,0,len);
3425 *fixed_portion = 8;
3426 break;
3429 case SMB_QUERY_FILE_NAME_INFO:
3432 this must be *exactly* right for ACLs on mapped drives to work
3434 status = srvstr_push(dstart, flags2,
3435 pdata+4, dos_fname,
3436 PTR_DIFF(dend, pdata+4),
3437 STR_UNICODE, &len);
3438 if (!NT_STATUS_IS_OK(status)) {
3439 return status;
3441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3442 data_size = 4 + len;
3443 SIVAL(pdata,0,len);
3444 break;
3447 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3449 char *nfname = NULL;
3451 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3452 return NT_STATUS_INVALID_LEVEL;
3455 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3456 if (nfname == NULL) {
3457 return NT_STATUS_NO_MEMORY;
3460 if (ISDOT(nfname)) {
3461 nfname[0] = '\0';
3463 string_replace(nfname, '/', '\\');
3465 if (fsp_is_alternate_stream(fsp)) {
3466 const char *s = smb_fname->stream_name;
3467 const char *e = NULL;
3468 size_t n;
3470 SMB_ASSERT(s[0] != '\0');
3473 * smb_fname->stream_name is in form
3474 * of ':StrEam:$DATA', but we should only
3475 * append ':StrEam' here.
3478 e = strchr(&s[1], ':');
3479 if (e == NULL) {
3480 n = strlen(s);
3481 } else {
3482 n = PTR_DIFF(e, s);
3484 nfname = talloc_strndup_append(nfname, s, n);
3485 if (nfname == NULL) {
3486 return NT_STATUS_NO_MEMORY;
3490 status = srvstr_push(dstart, flags2,
3491 pdata+4, nfname,
3492 PTR_DIFF(dend, pdata+4),
3493 STR_UNICODE, &len);
3494 if (!NT_STATUS_IS_OK(status)) {
3495 return status;
3497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3498 data_size = 4 + len;
3499 SIVAL(pdata,0,len);
3500 *fixed_portion = 8;
3501 break;
3504 case SMB_FILE_ALLOCATION_INFORMATION:
3505 case SMB_QUERY_FILE_ALLOCATION_INFO:
3506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3507 data_size = 8;
3508 SOFF_T(pdata,0,allocation_size);
3509 break;
3511 case SMB_FILE_END_OF_FILE_INFORMATION:
3512 case SMB_QUERY_FILE_END_OF_FILEINFO:
3513 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3514 data_size = 8;
3515 SOFF_T(pdata,0,file_size);
3516 break;
3518 case SMB_QUERY_FILE_ALL_INFO:
3519 case SMB_FILE_ALL_INFORMATION:
3521 unsigned int ea_size =
3522 estimate_ea_size(smb_fname->fsp);
3523 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3524 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3525 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3526 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3527 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3528 SIVAL(pdata,32,mode);
3529 SIVAL(pdata,36,0); /* padding. */
3530 pdata += 40;
3531 SOFF_T(pdata,0,allocation_size);
3532 SOFF_T(pdata,8,file_size);
3533 SIVAL(pdata,16,nlink);
3534 SCVAL(pdata,20,delete_pending);
3535 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3536 SSVAL(pdata,22,0);
3537 pdata += 24;
3538 SIVAL(pdata,0,ea_size);
3539 pdata += 4; /* EA info */
3540 status = srvstr_push(dstart, flags2,
3541 pdata+4, dos_fname,
3542 PTR_DIFF(dend, pdata+4),
3543 STR_UNICODE, &len);
3544 if (!NT_STATUS_IS_OK(status)) {
3545 return status;
3547 SIVAL(pdata,0,len);
3548 pdata += 4 + len;
3549 data_size = PTR_DIFF(pdata,(*ppdata));
3550 *fixed_portion = 10;
3551 break;
3554 case SMB2_FILE_ALL_INFORMATION:
3556 unsigned int ea_size =
3557 estimate_ea_size(smb_fname->fsp);
3558 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3559 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3560 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3561 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3562 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3563 SIVAL(pdata, 0x20, mode);
3564 SIVAL(pdata, 0x24, 0); /* padding. */
3565 SBVAL(pdata, 0x28, allocation_size);
3566 SBVAL(pdata, 0x30, file_size);
3567 SIVAL(pdata, 0x38, nlink);
3568 SCVAL(pdata, 0x3C, delete_pending);
3569 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3570 SSVAL(pdata, 0x3E, 0); /* padding */
3571 SBVAL(pdata, 0x40, file_id);
3572 SIVAL(pdata, 0x48, ea_size);
3573 SIVAL(pdata, 0x4C, access_mask);
3574 SBVAL(pdata, 0x50, pos);
3575 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3576 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3578 pdata += 0x60;
3580 status = srvstr_push(dstart, flags2,
3581 pdata+4, dos_fname,
3582 PTR_DIFF(dend, pdata+4),
3583 STR_UNICODE, &len);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 return status;
3587 SIVAL(pdata,0,len);
3588 pdata += 4 + len;
3589 data_size = PTR_DIFF(pdata,(*ppdata));
3590 *fixed_portion = 104;
3591 break;
3593 case SMB_FILE_INTERNAL_INFORMATION:
3595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3596 SBVAL(pdata, 0, file_id);
3597 data_size = 8;
3598 *fixed_portion = 8;
3599 break;
3601 case SMB_FILE_ACCESS_INFORMATION:
3602 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3603 SIVAL(pdata, 0, access_mask);
3604 data_size = 4;
3605 *fixed_portion = 4;
3606 break;
3608 case SMB_FILE_NAME_INFORMATION:
3609 /* Pathname with leading '\'. */
3611 size_t byte_len;
3612 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3614 SIVAL(pdata,0,byte_len);
3615 data_size = 4 + byte_len;
3616 break;
3619 case SMB_FILE_DISPOSITION_INFORMATION:
3620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3621 data_size = 1;
3622 SCVAL(pdata,0,delete_pending);
3623 *fixed_portion = 1;
3624 break;
3626 case SMB_FILE_POSITION_INFORMATION:
3627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3628 data_size = 8;
3629 SOFF_T(pdata,0,pos);
3630 *fixed_portion = 8;
3631 break;
3633 case SMB_FILE_MODE_INFORMATION:
3634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3635 SIVAL(pdata,0,mode);
3636 data_size = 4;
3637 *fixed_portion = 4;
3638 break;
3640 case SMB_FILE_ALIGNMENT_INFORMATION:
3641 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3642 SIVAL(pdata,0,0); /* No alignment needed. */
3643 data_size = 4;
3644 *fixed_portion = 4;
3645 break;
3648 * NT4 server just returns "invalid query" to this - if we try
3649 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3650 * want this. JRA.
3652 /* The first statement above is false - verified using Thursby
3653 * client against NT4 -- gcolley.
3655 case SMB_QUERY_FILE_STREAM_INFO:
3656 case SMB_FILE_STREAM_INFORMATION: {
3657 unsigned int num_streams = 0;
3658 struct stream_struct *streams = NULL;
3660 DEBUG(10,("smbd_do_qfilepathinfo: "
3661 "SMB_FILE_STREAM_INFORMATION\n"));
3663 if (is_ntfs_stream_smb_fname(smb_fname)) {
3664 return NT_STATUS_INVALID_PARAMETER;
3667 status = vfs_fstreaminfo(fsp,
3668 mem_ctx,
3669 &num_streams,
3670 &streams);
3672 if (!NT_STATUS_IS_OK(status)) {
3673 DEBUG(10, ("could not get stream info: %s\n",
3674 nt_errstr(status)));
3675 return status;
3678 status = marshall_stream_info(num_streams, streams,
3679 pdata, max_data_bytes,
3680 &data_size);
3682 if (!NT_STATUS_IS_OK(status)) {
3683 DEBUG(10, ("marshall_stream_info failed: %s\n",
3684 nt_errstr(status)));
3685 TALLOC_FREE(streams);
3686 return status;
3689 TALLOC_FREE(streams);
3691 *fixed_portion = 32;
3693 break;
3695 case SMB_QUERY_COMPRESSION_INFO:
3696 case SMB_FILE_COMPRESSION_INFORMATION:
3697 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3698 SOFF_T(pdata,0,file_size);
3699 SIVAL(pdata,8,0); /* ??? */
3700 SIVAL(pdata,12,0); /* ??? */
3701 data_size = 16;
3702 *fixed_portion = 16;
3703 break;
3705 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3706 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3707 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3708 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3709 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3710 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3711 SOFF_T(pdata,32,allocation_size);
3712 SOFF_T(pdata,40,file_size);
3713 SIVAL(pdata,48,mode);
3714 SIVAL(pdata,52,0); /* ??? */
3715 data_size = 56;
3716 *fixed_portion = 56;
3717 break;
3719 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3720 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3721 SIVAL(pdata,0,mode);
3722 SIVAL(pdata,4,0);
3723 data_size = 8;
3724 *fixed_portion = 8;
3725 break;
3728 * SMB2 UNIX Extensions.
3730 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3732 uint8_t *buf = NULL;
3733 ssize_t plen = 0;
3735 if (!(conn->sconn->using_smb2)) {
3736 return NT_STATUS_INVALID_LEVEL;
3738 if (!lp_smb3_unix_extensions()) {
3739 return NT_STATUS_INVALID_LEVEL;
3741 if (fsp == NULL) {
3742 return NT_STATUS_INVALID_HANDLE;
3744 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3745 return NT_STATUS_INVALID_LEVEL;
3748 /* Determine the size of the posix info context */
3749 plen = store_smb2_posix_info(conn,
3750 &smb_fname->st,
3752 mode,
3753 NULL,
3755 if (plen == -1 || data_size < plen) {
3756 return NT_STATUS_INVALID_PARAMETER;
3758 buf = talloc_zero_size(mem_ctx, plen);
3759 if (buf == NULL) {
3760 return NT_STATUS_NO_MEMORY;
3763 /* Store the context in buf */
3764 store_smb2_posix_info(conn,
3765 &smb_fname->st,
3767 mode,
3768 buf,
3769 plen);
3770 memcpy(pdata, buf, plen);
3771 data_size = plen;
3772 break;
3775 default:
3776 return NT_STATUS_INVALID_LEVEL;
3779 *pdata_size = data_size;
3780 return NT_STATUS_OK;
3783 /****************************************************************************
3784 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3785 code.
3786 ****************************************************************************/
3788 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3789 connection_struct *conn,
3790 struct smb_request *req,
3791 bool overwrite_if_exists,
3792 struct files_struct *old_dirfsp,
3793 const struct smb_filename *smb_fname_old,
3794 struct files_struct *new_dirfsp,
3795 struct smb_filename *smb_fname_new)
3797 NTSTATUS status = NT_STATUS_OK;
3798 int ret;
3799 bool ok;
3800 struct smb_filename *parent_fname_old = NULL;
3801 struct smb_filename *base_name_old = NULL;
3802 struct smb_filename *parent_fname_new = NULL;
3803 struct smb_filename *base_name_new = NULL;
3805 /* source must already exist. */
3806 if (!VALID_STAT(smb_fname_old->st)) {
3807 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3808 goto out;
3811 /* No links from a directory. */
3812 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3813 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3814 goto out;
3817 /* Setting a hardlink to/from a stream isn't currently supported. */
3818 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3819 if (ok) {
3820 DBG_DEBUG("Old name has streams\n");
3821 status = NT_STATUS_INVALID_PARAMETER;
3822 goto out;
3824 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3825 if (ok) {
3826 DBG_DEBUG("New name has streams\n");
3827 status = NT_STATUS_INVALID_PARAMETER;
3828 goto out;
3831 status = parent_pathref(talloc_tos(),
3832 conn->cwd_fsp,
3833 smb_fname_old,
3834 &parent_fname_old,
3835 &base_name_old);
3836 if (!NT_STATUS_IS_OK(status)) {
3837 goto out;
3840 status = parent_pathref(talloc_tos(),
3841 conn->cwd_fsp,
3842 smb_fname_new,
3843 &parent_fname_new,
3844 &base_name_new);
3845 if (!NT_STATUS_IS_OK(status)) {
3846 goto out;
3849 if (VALID_STAT(smb_fname_new->st)) {
3850 if (overwrite_if_exists) {
3851 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3852 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3853 goto out;
3855 status = unlink_internals(conn,
3856 req,
3857 FILE_ATTRIBUTE_NORMAL,
3858 NULL, /* new_dirfsp */
3859 smb_fname_new);
3860 if (!NT_STATUS_IS_OK(status)) {
3861 goto out;
3863 } else {
3864 /* Disallow if newname already exists. */
3865 status = NT_STATUS_OBJECT_NAME_COLLISION;
3866 goto out;
3870 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3871 smb_fname_old->base_name, smb_fname_new->base_name));
3873 ret = SMB_VFS_LINKAT(conn,
3874 parent_fname_old->fsp,
3875 base_name_old,
3876 parent_fname_new->fsp,
3877 base_name_new,
3880 if (ret != 0) {
3881 status = map_nt_error_from_unix(errno);
3882 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3883 nt_errstr(status), smb_fname_old->base_name,
3884 smb_fname_new->base_name));
3887 out:
3889 TALLOC_FREE(parent_fname_old);
3890 TALLOC_FREE(parent_fname_new);
3891 return status;
3894 /****************************************************************************
3895 Deal with setting the time from any of the setfilepathinfo functions.
3896 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3897 calling this function.
3898 ****************************************************************************/
3900 NTSTATUS smb_set_file_time(connection_struct *conn,
3901 files_struct *fsp,
3902 struct smb_filename *smb_fname,
3903 struct smb_file_time *ft,
3904 bool setting_write_time)
3906 struct files_struct *set_fsp = NULL;
3907 struct timeval_buf tbuf[4];
3908 uint32_t action =
3909 FILE_NOTIFY_CHANGE_LAST_ACCESS
3910 |FILE_NOTIFY_CHANGE_LAST_WRITE
3911 |FILE_NOTIFY_CHANGE_CREATION;
3912 int ret;
3914 if (!VALID_STAT(smb_fname->st)) {
3915 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3918 if (fsp == NULL) {
3919 /* A symlink */
3920 return NT_STATUS_OK;
3923 set_fsp = metadata_fsp(fsp);
3925 /* get some defaults (no modifications) if any info is zero or -1. */
3926 if (is_omit_timespec(&ft->create_time)) {
3927 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3930 if (is_omit_timespec(&ft->atime)) {
3931 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3934 if (is_omit_timespec(&ft->mtime)) {
3935 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3938 if (!setting_write_time) {
3939 /* ft->mtime comes from change time, not write time. */
3940 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3943 /* Ensure the resolution is the correct for
3944 * what we can store on this filesystem. */
3946 round_timespec(conn->ts_res, &ft->create_time);
3947 round_timespec(conn->ts_res, &ft->ctime);
3948 round_timespec(conn->ts_res, &ft->atime);
3949 round_timespec(conn->ts_res, &ft->mtime);
3951 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3952 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3953 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3954 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3955 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3956 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3957 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3958 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3960 if (setting_write_time) {
3962 * This was a Windows setfileinfo on an open file.
3963 * NT does this a lot. We also need to
3964 * set the time here, as it can be read by
3965 * FindFirst/FindNext and with the patch for bug #2045
3966 * in smbd/fileio.c it ensures that this timestamp is
3967 * kept sticky even after a write. We save the request
3968 * away and will set it on file close and after a write. JRA.
3971 DBG_DEBUG("setting pending modtime to %s\n",
3972 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3974 if (set_fsp != NULL) {
3975 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3976 } else {
3977 set_sticky_write_time_path(
3978 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3979 ft->mtime);
3983 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3985 ret = file_ntimes(conn, set_fsp, ft);
3986 if (ret != 0) {
3987 return map_nt_error_from_unix(errno);
3990 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3991 smb_fname->base_name);
3992 return NT_STATUS_OK;
3995 /****************************************************************************
3996 Deal with setting the dosmode from any of the setfilepathinfo functions.
3997 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3998 done before calling this function.
3999 ****************************************************************************/
4001 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4002 struct files_struct *fsp,
4003 uint32_t dosmode)
4005 struct files_struct *dos_fsp = NULL;
4006 uint32_t current_dosmode;
4007 int ret;
4009 if (!VALID_STAT(fsp->fsp_name->st)) {
4010 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4013 dos_fsp = metadata_fsp(fsp);
4015 if (dosmode != 0) {
4016 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4017 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4018 } else {
4019 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4023 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4025 /* check the mode isn't different, before changing it */
4026 if (dosmode == 0) {
4027 return NT_STATUS_OK;
4029 current_dosmode = fdos_mode(dos_fsp);
4030 if (dosmode == current_dosmode) {
4031 return NT_STATUS_OK;
4034 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4035 fsp_str_dbg(dos_fsp), dosmode);
4037 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4038 if (ret != 0) {
4039 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4040 fsp_str_dbg(dos_fsp), strerror(errno));
4041 return map_nt_error_from_unix(errno);
4044 return NT_STATUS_OK;
4047 /****************************************************************************
4048 Deal with setting the size from any of the setfilepathinfo functions.
4049 ****************************************************************************/
4051 NTSTATUS smb_set_file_size(connection_struct *conn,
4052 struct smb_request *req,
4053 files_struct *fsp,
4054 struct smb_filename *smb_fname,
4055 const SMB_STRUCT_STAT *psbuf,
4056 off_t size,
4057 bool fail_after_createfile)
4059 NTSTATUS status = NT_STATUS_OK;
4060 files_struct *new_fsp = NULL;
4062 if (!VALID_STAT(*psbuf)) {
4063 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4066 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4067 (uint64_t)size,
4068 get_file_size_stat(psbuf));
4070 if (size == get_file_size_stat(psbuf)) {
4071 if (fsp == NULL) {
4072 return NT_STATUS_OK;
4074 if (!fsp->fsp_flags.modified) {
4075 return NT_STATUS_OK;
4077 trigger_write_time_update_immediate(fsp);
4078 return NT_STATUS_OK;
4081 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4082 smb_fname_str_dbg(smb_fname), (double)size));
4084 if (fsp &&
4085 !fsp->fsp_flags.is_pathref &&
4086 fsp_get_io_fd(fsp) != -1)
4088 /* Handle based call. */
4089 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4090 return NT_STATUS_ACCESS_DENIED;
4093 if (vfs_set_filelen(fsp, size) == -1) {
4094 return map_nt_error_from_unix(errno);
4096 trigger_write_time_update_immediate(fsp);
4097 return NT_STATUS_OK;
4100 status = SMB_VFS_CREATE_FILE(
4101 conn, /* conn */
4102 req, /* req */
4103 NULL, /* dirfsp */
4104 smb_fname, /* fname */
4105 FILE_WRITE_DATA, /* access_mask */
4106 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4107 FILE_SHARE_DELETE),
4108 FILE_OPEN, /* create_disposition*/
4109 0, /* create_options */
4110 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4111 0, /* oplock_request */
4112 NULL, /* lease */
4113 0, /* allocation_size */
4114 0, /* private_flags */
4115 NULL, /* sd */
4116 NULL, /* ea_list */
4117 &new_fsp, /* result */
4118 NULL, /* pinfo */
4119 NULL, NULL); /* create context */
4121 if (!NT_STATUS_IS_OK(status)) {
4122 /* NB. We check for open_was_deferred in the caller. */
4123 return status;
4126 /* See RAW-SFILEINFO-END-OF-FILE */
4127 if (fail_after_createfile) {
4128 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4129 return NT_STATUS_INVALID_LEVEL;
4132 if (vfs_set_filelen(new_fsp, size) == -1) {
4133 status = map_nt_error_from_unix(errno);
4134 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4135 return status;
4138 trigger_write_time_update_immediate(new_fsp);
4139 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4140 return NT_STATUS_OK;
4143 /****************************************************************************
4144 Deal with SMB_INFO_SET_EA.
4145 ****************************************************************************/
4147 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4148 const char *pdata,
4149 int total_data,
4150 files_struct *fsp,
4151 struct smb_filename *smb_fname)
4153 struct ea_list *ea_list = NULL;
4154 TALLOC_CTX *ctx = NULL;
4155 NTSTATUS status = NT_STATUS_OK;
4157 if (total_data < 10) {
4159 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4160 length. They seem to have no effect. Bug #3212. JRA */
4162 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4163 /* We're done. We only get EA info in this call. */
4164 return NT_STATUS_OK;
4167 return NT_STATUS_INVALID_PARAMETER;
4170 if (IVAL(pdata,0) > total_data) {
4171 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4172 IVAL(pdata,0), (unsigned int)total_data));
4173 return NT_STATUS_INVALID_PARAMETER;
4176 ctx = talloc_tos();
4177 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4178 if (!ea_list) {
4179 return NT_STATUS_INVALID_PARAMETER;
4182 if (fsp == NULL) {
4184 * The only way fsp can be NULL here is if
4185 * smb_fname points at a symlink and
4186 * and we're in POSIX context.
4187 * Ensure this is the case.
4189 * In this case we cannot set the EA.
4191 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4192 return NT_STATUS_ACCESS_DENIED;
4195 status = set_ea(conn, fsp, ea_list);
4197 return status;
4200 /****************************************************************************
4201 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4202 ****************************************************************************/
4204 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4205 const char *pdata,
4206 int total_data,
4207 files_struct *fsp)
4209 struct ea_list *ea_list = NULL;
4210 NTSTATUS status;
4212 if (fsp == NULL) {
4213 return NT_STATUS_INVALID_HANDLE;
4216 if (!lp_ea_support(SNUM(conn))) {
4217 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4218 "EA's not supported.\n",
4219 (unsigned int)total_data));
4220 return NT_STATUS_EAS_NOT_SUPPORTED;
4223 if (total_data < 10) {
4224 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4225 "too small.\n",
4226 (unsigned int)total_data));
4227 return NT_STATUS_INVALID_PARAMETER;
4230 ea_list = read_nttrans_ea_list(talloc_tos(),
4231 pdata,
4232 total_data);
4234 if (!ea_list) {
4235 return NT_STATUS_INVALID_PARAMETER;
4238 status = set_ea(conn, fsp, ea_list);
4240 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4241 smb_fname_str_dbg(fsp->fsp_name),
4242 nt_errstr(status) ));
4244 return status;
4248 /****************************************************************************
4249 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4250 ****************************************************************************/
4252 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4253 const char *pdata,
4254 int total_data,
4255 files_struct *fsp,
4256 struct smb_filename *smb_fname)
4258 NTSTATUS status = NT_STATUS_OK;
4259 bool delete_on_close;
4260 uint32_t dosmode = 0;
4262 if (total_data < 1) {
4263 return NT_STATUS_INVALID_PARAMETER;
4266 if (fsp == NULL) {
4267 return NT_STATUS_INVALID_HANDLE;
4270 delete_on_close = (CVAL(pdata,0) ? True : False);
4271 dosmode = fdos_mode(fsp);
4273 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4274 "delete_on_close = %u\n",
4275 smb_fname_str_dbg(smb_fname),
4276 (unsigned int)dosmode,
4277 (unsigned int)delete_on_close ));
4279 if (delete_on_close) {
4280 status = can_set_delete_on_close(fsp, dosmode);
4281 if (!NT_STATUS_IS_OK(status)) {
4282 return status;
4286 /* The set is across all open files on this dev/inode pair. */
4287 if (!set_delete_on_close(fsp, delete_on_close,
4288 conn->session_info->security_token,
4289 conn->session_info->unix_token)) {
4290 return NT_STATUS_ACCESS_DENIED;
4292 return NT_STATUS_OK;
4295 /****************************************************************************
4296 Deal with SMB_FILE_POSITION_INFORMATION.
4297 ****************************************************************************/
4299 static NTSTATUS smb_file_position_information(connection_struct *conn,
4300 const char *pdata,
4301 int total_data,
4302 files_struct *fsp)
4304 uint64_t position_information;
4306 if (total_data < 8) {
4307 return NT_STATUS_INVALID_PARAMETER;
4310 if (fsp == NULL) {
4311 /* Ignore on pathname based set. */
4312 return NT_STATUS_OK;
4315 position_information = (uint64_t)IVAL(pdata,0);
4316 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4318 DEBUG(10,("smb_file_position_information: Set file position "
4319 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4320 (double)position_information));
4321 fh_set_position_information(fsp->fh, position_information);
4322 return NT_STATUS_OK;
4325 /****************************************************************************
4326 Deal with SMB_FILE_MODE_INFORMATION.
4327 ****************************************************************************/
4329 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4330 const char *pdata,
4331 int total_data)
4333 uint32_t mode;
4335 if (total_data < 4) {
4336 return NT_STATUS_INVALID_PARAMETER;
4338 mode = IVAL(pdata,0);
4339 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4340 return NT_STATUS_INVALID_PARAMETER;
4342 return NT_STATUS_OK;
4345 /****************************************************************************
4346 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4347 ****************************************************************************/
4349 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4350 struct smb_request *req,
4351 const char *pdata,
4352 int total_data,
4353 files_struct *fsp,
4354 struct smb_filename *smb_fname_src)
4356 bool overwrite;
4357 uint32_t len;
4358 char *newname = NULL;
4359 struct files_struct *dst_dirfsp = NULL;
4360 struct smb_filename *smb_fname_dst = NULL;
4361 const char *dst_original_lcomp = NULL;
4362 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4363 NTSTATUS status = NT_STATUS_OK;
4364 TALLOC_CTX *ctx = talloc_tos();
4366 if (!fsp) {
4367 return NT_STATUS_INVALID_HANDLE;
4370 if (total_data < 20) {
4371 return NT_STATUS_INVALID_PARAMETER;
4374 overwrite = (CVAL(pdata,0) ? True : False);
4375 len = IVAL(pdata,16);
4377 if (len > (total_data - 20) || (len == 0)) {
4378 return NT_STATUS_INVALID_PARAMETER;
4381 (void)srvstr_pull_talloc(ctx,
4382 pdata,
4383 req->flags2,
4384 &newname,
4385 &pdata[20],
4386 len,
4387 STR_TERMINATE);
4389 if (newname == NULL) {
4390 return NT_STATUS_INVALID_PARAMETER;
4393 /* SMB2 rename paths are never DFS. */
4394 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4395 ucf_flags &= ~UCF_DFS_PATHNAME;
4397 status = check_path_syntax(newname,
4398 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4399 if (!NT_STATUS_IS_OK(status)) {
4400 return status;
4403 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4404 newname));
4406 if (newname[0] == ':') {
4407 /* Create an smb_fname to call rename_internals_fsp() with. */
4408 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4409 fsp->base_fsp->fsp_name->base_name,
4410 newname,
4411 NULL,
4412 fsp->base_fsp->fsp_name->twrp,
4413 fsp->base_fsp->fsp_name->flags);
4414 if (smb_fname_dst == NULL) {
4415 status = NT_STATUS_NO_MEMORY;
4416 goto out;
4418 } else {
4419 status = filename_convert_dirfsp(ctx,
4420 conn,
4421 newname,
4422 ucf_flags,
4423 0, /* Never a TWRP. */
4424 &dst_dirfsp,
4425 &smb_fname_dst);
4426 if (!NT_STATUS_IS_OK(status)) {
4427 goto out;
4432 * Set the original last component, since
4433 * rename_internals_fsp() requires it.
4435 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4436 conn,
4437 newname,
4438 ucf_flags);
4439 if (dst_original_lcomp == NULL) {
4440 status = NT_STATUS_NO_MEMORY;
4441 goto out;
4444 DEBUG(10,("smb2_file_rename_information: "
4445 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4446 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4447 smb_fname_str_dbg(smb_fname_dst)));
4448 status = rename_internals_fsp(conn,
4449 fsp,
4450 NULL, /* dst_dirfsp */
4451 smb_fname_dst,
4452 dst_original_lcomp,
4453 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4454 overwrite);
4456 out:
4457 TALLOC_FREE(smb_fname_dst);
4458 return status;
4461 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4462 struct smb_request *req,
4463 const char *pdata,
4464 int total_data,
4465 files_struct *fsp,
4466 struct smb_filename *smb_fname_src)
4468 bool overwrite;
4469 uint32_t len;
4470 char *newname = NULL;
4471 struct files_struct *dst_dirfsp = NULL;
4472 struct smb_filename *smb_fname_dst = NULL;
4473 NTSTATUS status = NT_STATUS_OK;
4474 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4475 size_t ret;
4476 TALLOC_CTX *ctx = talloc_tos();
4478 if (!fsp) {
4479 return NT_STATUS_INVALID_HANDLE;
4482 if (total_data < 20) {
4483 return NT_STATUS_INVALID_PARAMETER;
4486 overwrite = (CVAL(pdata,0) ? true : false);
4487 len = IVAL(pdata,16);
4489 if (len > (total_data - 20) || (len == 0)) {
4490 return NT_STATUS_INVALID_PARAMETER;
4493 ret = srvstr_pull_talloc(ctx,
4494 pdata,
4495 req->flags2,
4496 &newname,
4497 &pdata[20],
4498 len,
4499 STR_TERMINATE);
4501 if (ret == (size_t)-1 || newname == NULL) {
4502 return NT_STATUS_INVALID_PARAMETER;
4505 /* SMB2 hardlink paths are never DFS. */
4506 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4507 ucf_flags &= ~UCF_DFS_PATHNAME;
4509 status = check_path_syntax(newname,
4510 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4511 if (!NT_STATUS_IS_OK(status)) {
4512 return status;
4515 DBG_DEBUG("got name |%s|\n", newname);
4517 status = filename_convert_dirfsp(ctx,
4518 conn,
4519 newname,
4520 ucf_flags,
4521 0, /* No TWRP. */
4522 &dst_dirfsp,
4523 &smb_fname_dst);
4524 if (!NT_STATUS_IS_OK(status)) {
4525 return status;
4528 if (fsp->base_fsp) {
4529 /* No stream names. */
4530 return NT_STATUS_NOT_SUPPORTED;
4533 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4534 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4535 smb_fname_str_dbg(smb_fname_dst));
4536 status = hardlink_internals(ctx,
4537 conn,
4538 req,
4539 overwrite,
4540 NULL, /* src_dirfsp */
4541 fsp->fsp_name,
4542 dst_dirfsp, /* dst_dirfsp */
4543 smb_fname_dst);
4545 TALLOC_FREE(smb_fname_dst);
4546 return status;
4549 static NTSTATUS smb_file_link_information(connection_struct *conn,
4550 struct smb_request *req,
4551 const char *pdata,
4552 int total_data,
4553 files_struct *fsp,
4554 struct smb_filename *smb_fname_src)
4556 bool overwrite;
4557 uint32_t len;
4558 char *newname = NULL;
4559 struct files_struct *dst_dirfsp = NULL;
4560 struct smb_filename *smb_fname_dst = NULL;
4561 NTSTATUS status = NT_STATUS_OK;
4562 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4563 NTTIME dst_twrp = 0;
4564 TALLOC_CTX *ctx = talloc_tos();
4566 if (!fsp) {
4567 return NT_STATUS_INVALID_HANDLE;
4570 if (total_data < 20) {
4571 return NT_STATUS_INVALID_PARAMETER;
4574 overwrite = (CVAL(pdata,0) ? true : false);
4575 len = IVAL(pdata,16);
4577 if (len > (total_data - 20) || (len == 0)) {
4578 return NT_STATUS_INVALID_PARAMETER;
4581 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4582 srvstr_get_path_posix(ctx,
4583 pdata,
4584 req->flags2,
4585 &newname,
4586 &pdata[20],
4587 len,
4588 STR_TERMINATE,
4589 &status);
4590 ucf_flags |= UCF_POSIX_PATHNAMES;
4591 } else {
4592 srvstr_get_path(ctx,
4593 pdata,
4594 req->flags2,
4595 &newname,
4596 &pdata[20],
4597 len,
4598 STR_TERMINATE,
4599 &status);
4601 if (!NT_STATUS_IS_OK(status)) {
4602 return status;
4605 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4606 newname));
4608 if (ucf_flags & UCF_GMT_PATHNAME) {
4609 extract_snapshot_token(newname, &dst_twrp);
4611 /* hardlink paths are never DFS. */
4612 ucf_flags &= ~UCF_DFS_PATHNAME;
4614 status = filename_convert_dirfsp(ctx,
4615 conn,
4616 newname,
4617 ucf_flags,
4618 dst_twrp,
4619 &dst_dirfsp,
4620 &smb_fname_dst);
4621 if (!NT_STATUS_IS_OK(status)) {
4622 return status;
4625 if (fsp->base_fsp) {
4626 /* No stream names. */
4627 return NT_STATUS_NOT_SUPPORTED;
4630 DEBUG(10,("smb_file_link_information: "
4631 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4632 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4633 smb_fname_str_dbg(smb_fname_dst)));
4634 status = hardlink_internals(ctx,
4635 conn,
4636 req,
4637 overwrite,
4638 NULL, /* src_dirfsp */
4639 fsp->fsp_name,
4640 dst_dirfsp, /* dst_dirfsp */
4641 smb_fname_dst);
4643 TALLOC_FREE(smb_fname_dst);
4644 return status;
4648 /****************************************************************************
4649 Deal with SMB_FILE_RENAME_INFORMATION.
4650 ****************************************************************************/
4652 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4653 struct smb_request *req,
4654 const char *pdata,
4655 int total_data,
4656 files_struct *fsp,
4657 struct smb_filename *smb_fname_src)
4659 bool overwrite;
4660 uint32_t root_fid;
4661 uint32_t len;
4662 char *newname = NULL;
4663 struct files_struct *dst_dirfsp = NULL;
4664 struct smb_filename *smb_fname_dst = NULL;
4665 const char *dst_original_lcomp = NULL;
4666 NTSTATUS status = NT_STATUS_OK;
4667 char *p;
4668 TALLOC_CTX *ctx = talloc_tos();
4670 if (total_data < 13) {
4671 return NT_STATUS_INVALID_PARAMETER;
4674 overwrite = (CVAL(pdata,0) != 0);
4675 root_fid = IVAL(pdata,4);
4676 len = IVAL(pdata,8);
4678 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4679 return NT_STATUS_INVALID_PARAMETER;
4682 if (req->posix_pathnames) {
4683 srvstr_get_path_posix(ctx,
4684 pdata,
4685 req->flags2,
4686 &newname,
4687 &pdata[12],
4688 len,
4690 &status);
4691 } else {
4692 srvstr_get_path(ctx,
4693 pdata,
4694 req->flags2,
4695 &newname,
4696 &pdata[12],
4697 len,
4699 &status);
4701 if (!NT_STATUS_IS_OK(status)) {
4702 return status;
4705 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4706 newname));
4708 /* Check the new name has no '/' characters. */
4709 if (strchr_m(newname, '/')) {
4710 return NT_STATUS_NOT_SUPPORTED;
4713 if (fsp && fsp->base_fsp) {
4714 /* newname must be a stream name. */
4715 if (newname[0] != ':') {
4716 return NT_STATUS_NOT_SUPPORTED;
4719 /* Create an smb_fname to call rename_internals_fsp() with. */
4720 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4721 fsp->base_fsp->fsp_name->base_name,
4722 newname,
4723 NULL,
4724 fsp->base_fsp->fsp_name->twrp,
4725 fsp->base_fsp->fsp_name->flags);
4726 if (smb_fname_dst == NULL) {
4727 status = NT_STATUS_NO_MEMORY;
4728 goto out;
4732 * Get the original last component, since
4733 * rename_internals_fsp() requires it.
4735 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4736 conn,
4737 newname,
4739 if (dst_original_lcomp == NULL) {
4740 status = NT_STATUS_NO_MEMORY;
4741 goto out;
4744 } else {
4746 * Build up an smb_fname_dst based on the filename passed in.
4747 * We basically just strip off the last component, and put on
4748 * the newname instead.
4750 char *base_name = NULL;
4751 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4752 NTTIME dst_twrp = 0;
4754 /* newname must *not* be a stream name. */
4755 if (newname[0] == ':') {
4756 return NT_STATUS_NOT_SUPPORTED;
4760 * Strip off the last component (filename) of the path passed
4761 * in.
4763 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4764 if (!base_name) {
4765 return NT_STATUS_NO_MEMORY;
4767 p = strrchr_m(base_name, '/');
4768 if (p) {
4769 p[1] = '\0';
4770 } else {
4771 base_name = talloc_strdup(ctx, "");
4772 if (!base_name) {
4773 return NT_STATUS_NO_MEMORY;
4776 /* Append the new name. */
4777 base_name = talloc_asprintf_append(base_name,
4778 "%s",
4779 newname);
4780 if (!base_name) {
4781 return NT_STATUS_NO_MEMORY;
4784 if (ucf_flags & UCF_GMT_PATHNAME) {
4785 extract_snapshot_token(base_name, &dst_twrp);
4788 /* The newname is *not* a DFS path. */
4789 ucf_flags &= ~UCF_DFS_PATHNAME;
4791 status = filename_convert_dirfsp(ctx,
4792 conn,
4793 base_name,
4794 ucf_flags,
4795 dst_twrp,
4796 &dst_dirfsp,
4797 &smb_fname_dst);
4799 if (!NT_STATUS_IS_OK(status)) {
4800 goto out;
4802 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4803 conn,
4804 newname,
4805 ucf_flags);
4806 if (dst_original_lcomp == NULL) {
4807 status = NT_STATUS_NO_MEMORY;
4808 goto out;
4812 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4813 DEBUG(10,("smb_file_rename_information: "
4814 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4815 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4816 smb_fname_str_dbg(smb_fname_dst)));
4817 status = rename_internals_fsp(conn,
4818 fsp,
4819 dst_dirfsp,
4820 smb_fname_dst,
4821 dst_original_lcomp,
4823 overwrite);
4824 } else {
4825 DEBUG(10,("smb_file_rename_information: "
4826 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4827 smb_fname_str_dbg(smb_fname_src),
4828 smb_fname_str_dbg(smb_fname_dst)));
4829 status = rename_internals(ctx,
4830 conn,
4831 req,
4832 NULL, /* src_dirfsp */
4833 smb_fname_src,
4834 dst_dirfsp,
4835 smb_fname_dst,
4836 dst_original_lcomp,
4838 overwrite,
4839 FILE_WRITE_ATTRIBUTES);
4841 out:
4842 TALLOC_FREE(smb_fname_dst);
4843 return status;
4846 /****************************************************************************
4847 Deal with SMB_SET_FILE_BASIC_INFO.
4848 ****************************************************************************/
4850 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4851 const char *pdata,
4852 int total_data,
4853 files_struct *fsp,
4854 struct smb_filename *smb_fname)
4856 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4857 struct smb_file_time ft;
4858 uint32_t dosmode = 0;
4859 NTSTATUS status = NT_STATUS_OK;
4861 init_smb_file_time(&ft);
4863 if (total_data < 36) {
4864 return NT_STATUS_INVALID_PARAMETER;
4867 if (fsp == NULL) {
4868 return NT_STATUS_INVALID_HANDLE;
4871 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4872 if (!NT_STATUS_IS_OK(status)) {
4873 return status;
4876 /* Set the attributes */
4877 dosmode = IVAL(pdata,32);
4878 status = smb_set_file_dosmode(conn, fsp, dosmode);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 return status;
4883 /* create time */
4884 ft.create_time = pull_long_date_full_timespec(pdata);
4886 /* access time */
4887 ft.atime = pull_long_date_full_timespec(pdata+8);
4889 /* write time. */
4890 ft.mtime = pull_long_date_full_timespec(pdata+16);
4892 /* change time. */
4893 ft.ctime = pull_long_date_full_timespec(pdata+24);
4895 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4896 smb_fname_str_dbg(smb_fname)));
4898 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4899 if (!NT_STATUS_IS_OK(status)) {
4900 return status;
4903 if (fsp->fsp_flags.modified) {
4904 trigger_write_time_update_immediate(fsp);
4906 return NT_STATUS_OK;
4909 /****************************************************************************
4910 Deal with SMB_INFO_STANDARD.
4911 ****************************************************************************/
4913 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4914 const char *pdata,
4915 int total_data,
4916 files_struct *fsp,
4917 struct smb_filename *smb_fname)
4919 NTSTATUS status;
4920 struct smb_file_time ft;
4922 init_smb_file_time(&ft);
4924 if (total_data < 12) {
4925 return NT_STATUS_INVALID_PARAMETER;
4928 if (fsp == NULL) {
4929 return NT_STATUS_INVALID_HANDLE;
4932 /* create time */
4933 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4934 /* access time */
4935 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4936 /* write time */
4937 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4939 DEBUG(10,("smb_set_info_standard: file %s\n",
4940 smb_fname_str_dbg(smb_fname)));
4942 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4943 if (!NT_STATUS_IS_OK(status)) {
4944 return status;
4947 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4948 if (!NT_STATUS_IS_OK(status)) {
4949 return status;
4952 if (fsp->fsp_flags.modified) {
4953 trigger_write_time_update_immediate(fsp);
4955 return NT_STATUS_OK;
4958 /****************************************************************************
4959 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4960 ****************************************************************************/
4962 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4963 struct smb_request *req,
4964 const char *pdata,
4965 int total_data,
4966 files_struct *fsp,
4967 struct smb_filename *smb_fname)
4969 uint64_t allocation_size = 0;
4970 NTSTATUS status = NT_STATUS_OK;
4971 files_struct *new_fsp = NULL;
4973 if (!VALID_STAT(smb_fname->st)) {
4974 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4977 if (total_data < 8) {
4978 return NT_STATUS_INVALID_PARAMETER;
4981 allocation_size = (uint64_t)IVAL(pdata,0);
4982 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4983 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4984 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4985 (double)allocation_size));
4987 if (allocation_size) {
4988 allocation_size = smb_roundup(conn, allocation_size);
4991 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4992 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4993 (double)allocation_size));
4995 if (fsp &&
4996 !fsp->fsp_flags.is_pathref &&
4997 fsp_get_io_fd(fsp) != -1)
4999 /* Open file handle. */
5000 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5001 return NT_STATUS_ACCESS_DENIED;
5004 /* Only change if needed. */
5005 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5006 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5007 return map_nt_error_from_unix(errno);
5010 /* But always update the time. */
5012 * This is equivalent to a write. Ensure it's seen immediately
5013 * if there are no pending writes.
5015 trigger_write_time_update_immediate(fsp);
5016 return NT_STATUS_OK;
5019 /* Pathname or stat or directory file. */
5020 status = SMB_VFS_CREATE_FILE(
5021 conn, /* conn */
5022 req, /* req */
5023 NULL, /* dirfsp */
5024 smb_fname, /* fname */
5025 FILE_WRITE_DATA, /* access_mask */
5026 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5027 FILE_SHARE_DELETE),
5028 FILE_OPEN, /* create_disposition*/
5029 0, /* create_options */
5030 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5031 0, /* oplock_request */
5032 NULL, /* lease */
5033 0, /* allocation_size */
5034 0, /* private_flags */
5035 NULL, /* sd */
5036 NULL, /* ea_list */
5037 &new_fsp, /* result */
5038 NULL, /* pinfo */
5039 NULL, NULL); /* create context */
5041 if (!NT_STATUS_IS_OK(status)) {
5042 /* NB. We check for open_was_deferred in the caller. */
5043 return status;
5046 /* Only change if needed. */
5047 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5048 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5049 status = map_nt_error_from_unix(errno);
5050 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5051 return status;
5055 /* Changing the allocation size should set the last mod time. */
5057 * This is equivalent to a write. Ensure it's seen immediately
5058 * if there are no pending writes.
5060 trigger_write_time_update_immediate(new_fsp);
5061 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5062 return NT_STATUS_OK;
5065 /****************************************************************************
5066 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5067 ****************************************************************************/
5069 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5070 struct smb_request *req,
5071 const char *pdata,
5072 int total_data,
5073 files_struct *fsp,
5074 struct smb_filename *smb_fname,
5075 bool fail_after_createfile)
5077 off_t size;
5079 if (total_data < 8) {
5080 return NT_STATUS_INVALID_PARAMETER;
5083 size = IVAL(pdata,0);
5084 size |= (((off_t)IVAL(pdata,4)) << 32);
5085 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5086 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5087 (double)size));
5089 return smb_set_file_size(conn, req,
5090 fsp,
5091 smb_fname,
5092 &smb_fname->st,
5093 size,
5094 fail_after_createfile);
5097 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5098 struct smb_request *req,
5099 TALLOC_CTX *mem_ctx,
5100 uint16_t info_level,
5101 files_struct *fsp,
5102 struct smb_filename *smb_fname,
5103 char **ppdata, int total_data,
5104 int *ret_data_size)
5106 char *pdata = *ppdata;
5107 NTSTATUS status = NT_STATUS_OK;
5108 int data_return_size = 0;
5110 *ret_data_size = 0;
5112 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5113 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5114 fsp_fnum_dbg(fsp),
5115 info_level, total_data));
5117 switch (info_level) {
5119 case SMB_INFO_STANDARD:
5121 status = smb_set_info_standard(conn,
5122 pdata,
5123 total_data,
5124 fsp,
5125 smb_fname);
5126 break;
5129 case SMB_INFO_SET_EA:
5131 status = smb_info_set_ea(conn,
5132 pdata,
5133 total_data,
5134 fsp,
5135 smb_fname);
5136 break;
5139 case SMB_SET_FILE_BASIC_INFO:
5140 case SMB_FILE_BASIC_INFORMATION:
5142 status = smb_set_file_basic_info(conn,
5143 pdata,
5144 total_data,
5145 fsp,
5146 smb_fname);
5147 break;
5150 case SMB_FILE_ALLOCATION_INFORMATION:
5151 case SMB_SET_FILE_ALLOCATION_INFO:
5153 status = smb_set_file_allocation_info(conn, req,
5154 pdata,
5155 total_data,
5156 fsp,
5157 smb_fname);
5158 break;
5161 case SMB_FILE_END_OF_FILE_INFORMATION:
5162 case SMB_SET_FILE_END_OF_FILE_INFO:
5165 * XP/Win7 both fail after the createfile with
5166 * SMB_SET_FILE_END_OF_FILE_INFO but not
5167 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5168 * The level is known here, so pass it down
5169 * appropriately.
5171 bool should_fail =
5172 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5174 status = smb_set_file_end_of_file_info(conn, req,
5175 pdata,
5176 total_data,
5177 fsp,
5178 smb_fname,
5179 should_fail);
5180 break;
5183 case SMB_FILE_DISPOSITION_INFORMATION:
5184 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5186 #if 0
5187 /* JRA - We used to just ignore this on a path ?
5188 * Shouldn't this be invalid level on a pathname
5189 * based call ?
5191 if (tran_call != TRANSACT2_SETFILEINFO) {
5192 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5194 #endif
5195 status = smb_set_file_disposition_info(conn,
5196 pdata,
5197 total_data,
5198 fsp,
5199 smb_fname);
5200 break;
5203 case SMB_FILE_POSITION_INFORMATION:
5205 status = smb_file_position_information(conn,
5206 pdata,
5207 total_data,
5208 fsp);
5209 break;
5212 case SMB_FILE_FULL_EA_INFORMATION:
5214 status = smb_set_file_full_ea_info(conn,
5215 pdata,
5216 total_data,
5217 fsp);
5218 break;
5221 /* From tridge Samba4 :
5222 * MODE_INFORMATION in setfileinfo (I have no
5223 * idea what "mode information" on a file is - it takes a value of 0,
5224 * 2, 4 or 6. What could it be?).
5227 case SMB_FILE_MODE_INFORMATION:
5229 status = smb_file_mode_information(conn,
5230 pdata,
5231 total_data);
5232 break;
5235 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5236 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5237 case SMB_FILE_SHORT_NAME_INFORMATION:
5238 return NT_STATUS_NOT_SUPPORTED;
5240 case SMB_FILE_RENAME_INFORMATION:
5242 status = smb_file_rename_information(conn, req,
5243 pdata, total_data,
5244 fsp, smb_fname);
5245 break;
5248 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5250 /* SMB2 rename information. */
5251 status = smb2_file_rename_information(conn, req,
5252 pdata, total_data,
5253 fsp, smb_fname);
5254 break;
5257 case SMB_FILE_LINK_INFORMATION:
5259 if (conn->sconn->using_smb2) {
5260 status = smb2_file_link_information(conn,
5261 req,
5262 pdata,
5263 total_data,
5264 fsp,
5265 smb_fname);
5266 } else {
5267 status = smb_file_link_information(conn,
5268 req,
5269 pdata,
5270 total_data,
5271 fsp,
5272 smb_fname);
5274 break;
5277 default:
5278 return NT_STATUS_INVALID_LEVEL;
5281 if (!NT_STATUS_IS_OK(status)) {
5282 return status;
5285 *ret_data_size = data_return_size;
5286 return NT_STATUS_OK;
5289 static uint32_t generate_volume_serial_number(
5290 const struct loadparm_substitution *lp_sub,
5291 int snum)
5293 int serial = lp_volume_serial_number(snum);
5294 return serial != -1 ? serial:
5295 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5296 (str_checksum(get_local_machine_name())<<16);