smbd: check for previous versions in check_any_access_fsp()
[Samba.git] / source3 / smbd / smb2_trans2.c
blob7fb7f45505cad05fefa8b6fbd25e1c6fd180c8b0
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 /**
76 * Check that one or more of the rights in access mask are
77 * allowed. Iow, access_requested can contain more then one right and
78 * it is sufficient having only one of those granted to pass.
79 **/
80 NTSTATUS check_any_access_fsp(struct files_struct *fsp,
81 uint32_t access_requested)
83 const uint32_t ro_access = SEC_RIGHTS_FILE_READ | SEC_FILE_EXECUTE;
84 uint32_t ro_access_granted = 0;
85 uint32_t access_granted = 0;
86 NTSTATUS status;
88 if (fsp->fsp_flags.is_fsa) {
89 access_granted = fsp->access_mask;
90 } else {
91 uint32_t mask = 1;
93 while (mask != 0) {
94 if (!(mask & access_requested)) {
95 mask <<= 1;
96 continue;
99 status = smbd_check_access_rights_fsp(
100 fsp->conn->cwd_fsp,
101 fsp,
102 false,
103 mask);
104 if (NT_STATUS_IS_OK(status)) {
105 access_granted |= mask;
106 if (fsp->fsp_name->twrp == 0) {
108 * We can only optimize
109 * the non-snapshot case
111 break;
114 mask <<= 1;
117 if ((access_granted & access_requested) == 0) {
118 return NT_STATUS_ACCESS_DENIED;
121 if (fsp->fsp_name->twrp == 0) {
122 return NT_STATUS_OK;
125 ro_access_granted = access_granted & ro_access;
126 if ((ro_access_granted & access_requested) == 0) {
127 return NT_STATUS_MEDIA_WRITE_PROTECTED;
130 return NT_STATUS_OK;
133 /********************************************************************
134 Roundup a value to the nearest allocation roundup size boundary.
135 Only do this for Windows clients.
136 ********************************************************************/
138 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
140 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
142 /* Only roundup for Windows clients. */
143 enum remote_arch_types ra_type = get_remote_arch();
144 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
145 val = SMB_ROUNDUP(val,rval);
147 return val;
150 /****************************************************************************
151 Utility functions for dealing with extended attributes.
152 ****************************************************************************/
154 /****************************************************************************
155 Refuse to allow clients to overwrite our private xattrs.
156 ****************************************************************************/
158 bool samba_private_attr_name(const char *unix_ea_name)
160 bool prohibited = false;
162 prohibited |= strequal(unix_ea_name, SAMBA_POSIX_INHERITANCE_EA_NAME);
163 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_DOS_ATTRIB);
164 prohibited |= strequal(unix_ea_name, SAMBA_XATTR_MARKER);
165 prohibited |= strequal(unix_ea_name, XATTR_NTACL_NAME);
166 prohibited |= strequal(unix_ea_name, AFPINFO_EA_NETATALK);
168 if (prohibited) {
169 return true;
172 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
173 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
174 return true;
176 return false;
179 /****************************************************************************
180 Get one EA value. Fill in a struct ea_struct.
181 ****************************************************************************/
183 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
184 files_struct *fsp,
185 const char *ea_name,
186 struct ea_struct *pea)
188 /* Get the value of this xattr. Max size is 64k. */
189 size_t attr_size = 256;
190 char *val = NULL;
191 ssize_t sizeret;
192 size_t max_xattr_size = 0;
194 if (fsp == NULL) {
195 return NT_STATUS_INVALID_HANDLE;
198 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
200 again:
202 val = talloc_realloc(mem_ctx, val, char, attr_size);
203 if (!val) {
204 return NT_STATUS_NO_MEMORY;
207 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
208 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
209 attr_size = max_xattr_size;
210 goto again;
213 if (sizeret == -1) {
214 return map_nt_error_from_unix(errno);
217 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
218 dump_data(10, (uint8_t *)val, sizeret);
220 pea->flags = 0;
221 if (strnequal(ea_name, "user.", 5)) {
222 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
223 } else {
224 pea->name = talloc_strdup(mem_ctx, ea_name);
226 if (pea->name == NULL) {
227 TALLOC_FREE(val);
228 return NT_STATUS_NO_MEMORY;
230 pea->value.data = (unsigned char *)val;
231 pea->value.length = (size_t)sizeret;
232 return NT_STATUS_OK;
235 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
236 files_struct *fsp,
237 char ***pnames,
238 size_t *pnum_names)
240 char smallbuf[1024];
241 /* Get a list of all xattrs. Max namesize is 64k. */
242 size_t ea_namelist_size = 1024;
243 char *ea_namelist = smallbuf;
244 char *to_free = NULL;
246 char *p;
247 char **names;
248 size_t num_names;
249 ssize_t sizeret = -1;
250 NTSTATUS status;
252 if (pnames) {
253 *pnames = NULL;
255 *pnum_names = 0;
257 if (fsp == NULL) {
259 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
260 * symlink. This is ok, handle it here, by just return no EA's
261 * on a symlink.
263 return NT_STATUS_OK;
266 /* should be the case that fsp != NULL */
267 SMB_ASSERT(fsp != NULL);
269 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
270 ea_namelist_size);
272 if ((sizeret == -1) && (errno == ERANGE)) {
273 ea_namelist_size = 65536;
274 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
275 if (ea_namelist == NULL) {
276 return NT_STATUS_NO_MEMORY;
278 to_free = ea_namelist;
280 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
281 ea_namelist_size);
284 if (sizeret == -1) {
285 status = map_nt_error_from_unix(errno);
286 TALLOC_FREE(to_free);
287 return status;
290 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
292 if (sizeret == 0) {
293 TALLOC_FREE(to_free);
294 return NT_STATUS_OK;
298 * Ensure the result is 0-terminated
301 if (ea_namelist[sizeret-1] != '\0') {
302 TALLOC_FREE(to_free);
303 return NT_STATUS_INTERNAL_ERROR;
307 * count the names
309 num_names = 0;
311 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
312 num_names += 1;
315 *pnum_names = num_names;
317 if (pnames == NULL) {
318 TALLOC_FREE(to_free);
319 return NT_STATUS_OK;
322 names = talloc_array(mem_ctx, char *, num_names);
323 if (names == NULL) {
324 DEBUG(0, ("talloc failed\n"));
325 TALLOC_FREE(to_free);
326 return NT_STATUS_NO_MEMORY;
329 if (ea_namelist == smallbuf) {
330 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
331 if (ea_namelist == NULL) {
332 TALLOC_FREE(names);
333 return NT_STATUS_NO_MEMORY;
335 } else {
336 talloc_steal(names, ea_namelist);
338 ea_namelist = talloc_realloc(names, ea_namelist, char,
339 sizeret);
340 if (ea_namelist == NULL) {
341 TALLOC_FREE(names);
342 return NT_STATUS_NO_MEMORY;
346 num_names = 0;
348 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
349 names[num_names++] = p;
352 *pnames = names;
354 return NT_STATUS_OK;
357 /****************************************************************************
358 Return a linked list of the total EA's. Plus the total size
359 ****************************************************************************/
361 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
362 files_struct *fsp,
363 size_t *pea_total_len,
364 struct ea_list **ea_list)
366 /* Get a list of all xattrs. Max namesize is 64k. */
367 size_t i, num_names;
368 char **names;
369 struct ea_list *ea_list_head = NULL;
370 bool posix_pathnames = false;
371 NTSTATUS status;
373 *pea_total_len = 0;
374 *ea_list = NULL;
376 /* symlink */
377 if (fsp == NULL) {
378 return NT_STATUS_OK;
381 if (!lp_ea_support(SNUM(fsp->conn))) {
382 return NT_STATUS_OK;
385 if (fsp_is_alternate_stream(fsp)) {
386 return NT_STATUS_INVALID_PARAMETER;
389 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
391 status = get_ea_names_from_fsp(talloc_tos(),
392 fsp,
393 &names,
394 &num_names);
396 if (!NT_STATUS_IS_OK(status)) {
397 return status;
400 if (num_names == 0) {
401 return NT_STATUS_OK;
404 for (i=0; i<num_names; i++) {
405 struct ea_list *listp;
406 fstring dos_ea_name;
409 * POSIX EA names are divided into several namespaces by
410 * means of string prefixes. Usually, the system controls
411 * semantics for each namespace, but the 'user' namespace is
412 * available for arbitrary use, which comes closest to
413 * Windows EA semantics. Hence, we map POSIX EAs from the
414 * 'user' namespace to Windows EAs, and just ignore all the
415 * other namespaces. Also, a few specific names in the 'user'
416 * namespace are used by Samba internally. Filter them out as
417 * well, and only present the EAs that are available for
418 * arbitrary use.
420 if (!strnequal(names[i], "user.", 5)
421 || samba_private_attr_name(names[i]))
422 continue;
425 * Filter out any underlying POSIX EA names
426 * that a Windows client can't handle.
428 if (!posix_pathnames &&
429 is_invalid_windows_ea_name(names[i])) {
430 continue;
433 listp = talloc(mem_ctx, struct ea_list);
434 if (listp == NULL) {
435 return NT_STATUS_NO_MEMORY;
438 status = get_ea_value_fsp(listp,
439 fsp,
440 names[i],
441 &listp->ea);
443 if (!NT_STATUS_IS_OK(status)) {
444 TALLOC_FREE(listp);
445 return status;
448 if (listp->ea.value.length == 0) {
450 * We can never return a zero length EA.
451 * Windows reports the EA's as corrupted.
453 TALLOC_FREE(listp);
454 continue;
455 } else if (listp->ea.value.length > 65536) {
457 * SMB clients may report error with file
458 * if large EA is presented to them.
460 DBG_ERR("EA [%s] on file [%s] exceeds "
461 "maximum permitted EA size of 64KiB: %zu\n.",
462 listp->ea.name, fsp_str_dbg(fsp),
463 listp->ea.value.length);
464 TALLOC_FREE(listp);
465 continue;
468 push_ascii_fstring(dos_ea_name, listp->ea.name);
470 *pea_total_len +=
471 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
473 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
474 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
475 (unsigned int)listp->ea.value.length));
477 DLIST_ADD_END(ea_list_head, listp);
481 /* Add on 4 for total length. */
482 if (*pea_total_len) {
483 *pea_total_len += 4;
486 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
487 (unsigned int)*pea_total_len));
489 *ea_list = ea_list_head;
490 return NT_STATUS_OK;
493 /****************************************************************************
494 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
495 that was filled.
496 ****************************************************************************/
498 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
499 connection_struct *conn, struct ea_list *ea_list)
501 unsigned int ret_data_size = 4;
502 char *p = pdata;
504 SMB_ASSERT(total_data_size >= 4);
506 if (!lp_ea_support(SNUM(conn))) {
507 SIVAL(pdata,4,0);
508 return 4;
511 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
512 size_t dos_namelen;
513 fstring dos_ea_name;
514 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
515 dos_namelen = strlen(dos_ea_name);
516 if (dos_namelen > 255 || dos_namelen == 0) {
517 break;
519 if (ea_list->ea.value.length > 65535) {
520 break;
522 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
523 break;
526 /* We know we have room. */
527 SCVAL(p,0,ea_list->ea.flags);
528 SCVAL(p,1,dos_namelen);
529 SSVAL(p,2,ea_list->ea.value.length);
530 strlcpy(p+4, dos_ea_name, dos_namelen+1);
531 if (ea_list->ea.value.length > 0) {
532 memcpy(p + 4 + dos_namelen + 1,
533 ea_list->ea.value.data,
534 ea_list->ea.value.length);
537 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
538 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
541 ret_data_size = PTR_DIFF(p, pdata);
542 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
543 SIVAL(pdata,0,ret_data_size);
544 return ret_data_size;
547 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
548 char *pdata,
549 unsigned int total_data_size,
550 unsigned int *ret_data_size,
551 connection_struct *conn,
552 struct ea_list *ea_list)
554 uint8_t *p = (uint8_t *)pdata;
555 uint8_t *last_start = NULL;
556 bool do_store_data = (pdata != NULL);
558 *ret_data_size = 0;
560 if (!lp_ea_support(SNUM(conn))) {
561 return NT_STATUS_NO_EAS_ON_FILE;
564 for (; ea_list; ea_list = ea_list->next) {
565 size_t dos_namelen;
566 fstring dos_ea_name;
567 size_t this_size;
568 size_t pad = 0;
570 if (last_start != NULL && do_store_data) {
571 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
573 last_start = p;
575 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
576 dos_namelen = strlen(dos_ea_name);
577 if (dos_namelen > 255 || dos_namelen == 0) {
578 return NT_STATUS_INTERNAL_ERROR;
580 if (ea_list->ea.value.length > 65535) {
581 return NT_STATUS_INTERNAL_ERROR;
584 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
586 if (ea_list->next) {
587 pad = (4 - (this_size % 4)) % 4;
588 this_size += pad;
591 if (do_store_data) {
592 if (this_size > total_data_size) {
593 return NT_STATUS_INFO_LENGTH_MISMATCH;
596 /* We know we have room. */
597 SIVAL(p, 0x00, 0); /* next offset */
598 SCVAL(p, 0x04, ea_list->ea.flags);
599 SCVAL(p, 0x05, dos_namelen);
600 SSVAL(p, 0x06, ea_list->ea.value.length);
601 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
602 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
603 if (pad) {
604 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
605 '\0',
606 pad);
608 total_data_size -= this_size;
611 p += this_size;
614 *ret_data_size = PTR_DIFF(p, pdata);
615 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
616 return NT_STATUS_OK;
619 unsigned int estimate_ea_size(files_struct *fsp)
621 size_t total_ea_len = 0;
622 TALLOC_CTX *mem_ctx;
623 struct ea_list *ea_list = NULL;
624 NTSTATUS status;
626 /* symlink */
627 if (fsp == NULL) {
628 return 0;
631 if (!lp_ea_support(SNUM(fsp->conn))) {
632 return 0;
635 mem_ctx = talloc_stackframe();
637 /* If this is a stream fsp, then we need to instead find the
638 * estimated ea len from the main file, not the stream
639 * (streams cannot have EAs), but the estimate isn't just 0 in
640 * this case! */
641 fsp = metadata_fsp(fsp);
642 (void)get_ea_list_from_fsp(mem_ctx,
643 fsp,
644 &total_ea_len,
645 &ea_list);
647 if(fsp->conn->sconn->using_smb2) {
648 unsigned int ret_data_size;
650 * We're going to be using fill_ea_chained_buffer() to
651 * marshall EA's - this size is significantly larger
652 * than the SMB1 buffer. Re-calculate the size without
653 * marshalling.
655 status = fill_ea_chained_buffer(mem_ctx,
656 NULL,
658 &ret_data_size,
659 fsp->conn,
660 ea_list);
661 if (!NT_STATUS_IS_OK(status)) {
662 ret_data_size = 0;
664 total_ea_len = ret_data_size;
666 TALLOC_FREE(mem_ctx);
667 return total_ea_len;
670 /****************************************************************************
671 Ensure the EA name is case insensitive by matching any existing EA name.
672 ****************************************************************************/
674 static void canonicalize_ea_name(files_struct *fsp,
675 fstring unix_ea_name)
677 size_t total_ea_len;
678 TALLOC_CTX *mem_ctx = talloc_tos();
679 struct ea_list *ea_list;
680 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
681 fsp,
682 &total_ea_len,
683 &ea_list);
684 if (!NT_STATUS_IS_OK(status)) {
685 return;
688 for (; ea_list; ea_list = ea_list->next) {
689 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
690 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
691 &unix_ea_name[5], ea_list->ea.name));
692 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
693 break;
698 /****************************************************************************
699 Set or delete an extended attribute.
700 ****************************************************************************/
702 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
703 struct ea_list *ea_list)
705 NTSTATUS status;
706 bool posix_pathnames = false;
708 if (!lp_ea_support(SNUM(conn))) {
709 return NT_STATUS_EAS_NOT_SUPPORTED;
712 if (fsp == NULL) {
713 return NT_STATUS_INVALID_HANDLE;
716 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
718 status = refuse_symlink_fsp(fsp);
719 if (!NT_STATUS_IS_OK(status)) {
720 return status;
723 status = check_any_access_fsp(fsp, FILE_WRITE_EA);
724 if (!NT_STATUS_IS_OK(status)) {
725 return status;
728 /* Setting EAs on streams isn't supported. */
729 if (fsp_is_alternate_stream(fsp)) {
730 return NT_STATUS_INVALID_PARAMETER;
734 * Filter out invalid Windows EA names - before
735 * we set *any* of them.
738 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
739 return STATUS_INVALID_EA_NAME;
742 for (;ea_list; ea_list = ea_list->next) {
743 int ret;
744 fstring unix_ea_name;
747 * Complementing the forward mapping from POSIX EAs to
748 * Windows EAs in get_ea_list_from_fsp(), here we map in the
749 * opposite direction from Windows EAs to the 'user' namespace
750 * of POSIX EAs. Hence, all POSIX EA names the we set here must
751 * start with a 'user.' prefix.
753 fstrcpy(unix_ea_name, "user.");
754 fstrcat(unix_ea_name, ea_list->ea.name);
756 canonicalize_ea_name(fsp, unix_ea_name);
758 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
760 if (samba_private_attr_name(unix_ea_name)) {
761 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
762 return NT_STATUS_ACCESS_DENIED;
765 if (ea_list->ea.value.length == 0) {
766 /* Remove the attribute. */
767 DBG_DEBUG("deleting ea name %s on "
768 "file %s by file descriptor.\n",
769 unix_ea_name, fsp_str_dbg(fsp));
770 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
771 #ifdef ENOATTR
772 /* Removing a non existent attribute always succeeds. */
773 if (ret == -1 && errno == ENOATTR) {
774 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
775 unix_ea_name));
776 ret = 0;
778 #endif
779 } else {
780 DEBUG(10,("set_ea: setting ea name %s on file "
781 "%s by file descriptor.\n",
782 unix_ea_name, fsp_str_dbg(fsp)));
783 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
784 ea_list->ea.value.data, ea_list->ea.value.length, 0);
787 if (ret == -1) {
788 #ifdef ENOTSUP
789 if (errno == ENOTSUP) {
790 return NT_STATUS_EAS_NOT_SUPPORTED;
792 #endif
793 return map_nt_error_from_unix(errno);
797 return NT_STATUS_OK;
800 /****************************************************************************
801 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
802 ****************************************************************************/
804 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
806 struct ea_list *ea_list_head = NULL;
807 size_t offset = 0;
808 size_t bytes_used = 0;
810 while (offset < data_size) {
811 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
813 if (!eal) {
814 return NULL;
817 DLIST_ADD_END(ea_list_head, eal);
818 offset += bytes_used;
821 return ea_list_head;
824 /****************************************************************************
825 Count the total EA size needed.
826 ****************************************************************************/
828 static size_t ea_list_size(struct ea_list *ealist)
830 fstring dos_ea_name;
831 struct ea_list *listp;
832 size_t ret = 0;
834 for (listp = ealist; listp; listp = listp->next) {
835 push_ascii_fstring(dos_ea_name, listp->ea.name);
836 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
838 /* Add on 4 for total length. */
839 if (ret) {
840 ret += 4;
843 return ret;
846 /****************************************************************************
847 Return a union of EA's from a file list and a list of names.
848 The TALLOC context for the two lists *MUST* be identical as we steal
849 memory from one list to add to another. JRA.
850 ****************************************************************************/
852 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
854 struct ea_list *nlistp, *flistp;
856 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
857 for (flistp = file_list; flistp; flistp = flistp->next) {
858 if (strequal(nlistp->ea.name, flistp->ea.name)) {
859 break;
863 if (flistp) {
864 /* Copy the data from this entry. */
865 nlistp->ea.flags = flistp->ea.flags;
866 nlistp->ea.value = flistp->ea.value;
867 } else {
868 /* Null entry. */
869 nlistp->ea.flags = 0;
870 ZERO_STRUCT(nlistp->ea.value);
874 *total_ea_len = ea_list_size(name_list);
875 return name_list;
878 /****************************************************************************
879 Return the filetype for UNIX extensions.
880 ****************************************************************************/
882 static uint32_t unix_filetype(mode_t mode)
884 if(S_ISREG(mode))
885 return UNIX_TYPE_FILE;
886 else if(S_ISDIR(mode))
887 return UNIX_TYPE_DIR;
888 #ifdef S_ISLNK
889 else if(S_ISLNK(mode))
890 return UNIX_TYPE_SYMLINK;
891 #endif
892 #ifdef S_ISCHR
893 else if(S_ISCHR(mode))
894 return UNIX_TYPE_CHARDEV;
895 #endif
896 #ifdef S_ISBLK
897 else if(S_ISBLK(mode))
898 return UNIX_TYPE_BLKDEV;
899 #endif
900 #ifdef S_ISFIFO
901 else if(S_ISFIFO(mode))
902 return UNIX_TYPE_FIFO;
903 #endif
904 #ifdef S_ISSOCK
905 else if(S_ISSOCK(mode))
906 return UNIX_TYPE_SOCKET;
907 #endif
909 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
910 return UNIX_TYPE_UNKNOWN;
913 /****************************************************************************
914 Map wire perms onto standard UNIX permissions. Obey share restrictions.
915 ****************************************************************************/
917 NTSTATUS unix_perms_from_wire(connection_struct *conn,
918 const SMB_STRUCT_STAT *psbuf,
919 uint32_t perms,
920 enum perm_type ptype,
921 mode_t *ret_perms)
923 mode_t ret = 0;
925 if (perms == SMB_MODE_NO_CHANGE) {
926 if (!VALID_STAT(*psbuf)) {
927 return NT_STATUS_INVALID_PARAMETER;
928 } else {
929 *ret_perms = psbuf->st_ex_mode;
930 return NT_STATUS_OK;
934 ret = wire_perms_to_unix(perms);
936 if (ptype == PERM_NEW_FILE) {
938 * "create mask"/"force create mode" are
939 * only applied to new files, not existing ones.
941 ret &= lp_create_mask(SNUM(conn));
942 /* Add in force bits */
943 ret |= lp_force_create_mode(SNUM(conn));
944 } else if (ptype == PERM_NEW_DIR) {
946 * "directory mask"/"force directory mode" are
947 * only applied to new directories, not existing ones.
949 ret &= lp_directory_mask(SNUM(conn));
950 /* Add in force bits */
951 ret |= lp_force_directory_mode(SNUM(conn));
954 *ret_perms = ret;
955 return NT_STATUS_OK;
958 /****************************************************************************
959 Get a level dependent lanman2 dir entry.
960 ****************************************************************************/
962 struct smbd_dirptr_lanman2_state {
963 connection_struct *conn;
964 uint32_t info_level;
965 bool check_mangled_names;
966 bool case_sensitive;
969 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
970 void *private_data,
971 const char *dname,
972 const char *mask,
973 char **_fname)
975 struct smbd_dirptr_lanman2_state *state =
976 (struct smbd_dirptr_lanman2_state *)private_data;
977 bool ok;
978 char mangled_name[13]; /* mangled 8.3 name. */
979 bool got_match;
980 const char *fname;
982 /* Mangle fname if it's an illegal name. */
983 if (mangle_must_mangle(dname, state->conn->params)) {
985 * Slow path - ensure we can push the original name as UCS2. If
986 * not, then just don't return this name.
988 NTSTATUS status;
989 size_t ret_len = 0;
990 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
991 uint8_t *tmp = talloc_array(talloc_tos(),
992 uint8_t,
993 len);
995 status = srvstr_push(NULL,
996 FLAGS2_UNICODE_STRINGS,
997 tmp,
998 dname,
999 len,
1000 STR_TERMINATE,
1001 &ret_len);
1003 TALLOC_FREE(tmp);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 return false;
1009 ok = name_to_8_3(dname, mangled_name,
1010 true, state->conn->params);
1011 if (!ok) {
1012 return false;
1014 fname = mangled_name;
1015 } else {
1016 fname = dname;
1019 got_match = mask_match(fname, mask,
1020 state->case_sensitive);
1022 if(!got_match && state->check_mangled_names &&
1023 !mangle_is_8_3(fname, false, state->conn->params)) {
1025 * It turns out that NT matches wildcards against
1026 * both long *and* short names. This may explain some
1027 * of the wildcard weirdness from old DOS clients
1028 * that some people have been seeing.... JRA.
1030 /* Force the mangling into 8.3. */
1031 ok = name_to_8_3(fname, mangled_name,
1032 false, state->conn->params);
1033 if (!ok) {
1034 return false;
1037 got_match = mask_match(mangled_name, mask,
1038 state->case_sensitive);
1041 if (!got_match) {
1042 return false;
1045 *_fname = talloc_strdup(ctx, fname);
1046 if (*_fname == NULL) {
1047 return false;
1050 return true;
1053 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1054 void *private_data,
1055 struct files_struct *dirfsp,
1056 struct smb_filename *smb_fname,
1057 bool get_dosmode,
1058 uint32_t *_mode)
1060 if (get_dosmode) {
1061 SMB_ASSERT(smb_fname != NULL);
1062 *_mode = fdos_mode(smb_fname->fsp);
1063 if (smb_fname->fsp != NULL) {
1064 smb_fname->st = smb_fname->fsp->fsp_name->st;
1067 return true;
1070 static uint32_t get_dirent_ea_size(uint32_t mode, files_struct *fsp)
1072 if (!(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1073 unsigned ea_size = estimate_ea_size(fsp);
1074 return ea_size;
1076 return IO_REPARSE_TAG_DFS;
1079 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1080 connection_struct *conn,
1081 uint16_t flags2,
1082 uint32_t info_level,
1083 struct ea_list *name_list,
1084 bool check_mangled_names,
1085 bool requires_resume_key,
1086 uint32_t mode,
1087 const char *fname,
1088 const struct smb_filename *smb_fname,
1089 int space_remaining,
1090 uint8_t align,
1091 bool do_pad,
1092 char *base_data,
1093 char **ppdata,
1094 char *end_data,
1095 uint64_t *last_entry_off)
1097 char *p, *q, *pdata = *ppdata;
1098 uint32_t reskey=0;
1099 uint64_t file_size = 0;
1100 uint64_t allocation_size = 0;
1101 uint64_t file_id = 0;
1102 size_t len = 0;
1103 struct timespec mdate_ts = {0};
1104 struct timespec adate_ts = {0};
1105 struct timespec cdate_ts = {0};
1106 struct timespec create_date_ts = {0};
1107 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1108 char *nameptr;
1109 char *last_entry_ptr;
1110 bool was_8_3;
1111 int off;
1112 int pad = 0;
1113 NTSTATUS status;
1114 struct readdir_attr_data *readdir_attr_data = NULL;
1115 uint32_t ea_size;
1117 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1118 file_size = get_file_size_stat(&smb_fname->st);
1120 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1123 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1124 * a DFS symlink.
1126 if (smb_fname->fsp != NULL &&
1127 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1128 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1129 ctx,
1130 &readdir_attr_data);
1131 if (!NT_STATUS_IS_OK(status)) {
1132 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1133 status)) {
1134 return status;
1139 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1141 mdate_ts = smb_fname->st.st_ex_mtime;
1142 adate_ts = smb_fname->st.st_ex_atime;
1143 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1144 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1146 if (lp_dos_filetime_resolution(SNUM(conn))) {
1147 dos_filetime_timespec(&create_date_ts);
1148 dos_filetime_timespec(&mdate_ts);
1149 dos_filetime_timespec(&adate_ts);
1150 dos_filetime_timespec(&cdate_ts);
1153 create_date = convert_timespec_to_time_t(create_date_ts);
1154 mdate = convert_timespec_to_time_t(mdate_ts);
1155 adate = convert_timespec_to_time_t(adate_ts);
1157 /* align the record */
1158 SMB_ASSERT(align >= 1);
1160 off = (int)PTR_DIFF(pdata, base_data);
1161 pad = (off + (align-1)) & ~(align-1);
1162 pad -= off;
1164 if (pad && pad > space_remaining) {
1165 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1166 "for padding (wanted %u, had %d)\n",
1167 (unsigned int)pad,
1168 space_remaining ));
1169 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1172 off += pad;
1173 /* initialize padding to 0 */
1174 if (pad) {
1175 memset(pdata, 0, pad);
1177 space_remaining -= pad;
1179 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1180 space_remaining ));
1182 pdata += pad;
1183 p = pdata;
1184 last_entry_ptr = p;
1186 pad = 0;
1187 off = 0;
1189 switch (info_level) {
1190 case SMB_FIND_INFO_STANDARD:
1191 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1192 if(requires_resume_key) {
1193 SIVAL(p,0,reskey);
1194 p += 4;
1196 srv_put_dos_date2(p,0,create_date);
1197 srv_put_dos_date2(p,4,adate);
1198 srv_put_dos_date2(p,8,mdate);
1199 SIVAL(p,12,(uint32_t)file_size);
1200 SIVAL(p,16,(uint32_t)allocation_size);
1201 SSVAL(p,20,mode);
1202 p += 23;
1203 nameptr = p;
1204 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1205 p += ucs2_align(base_data, p, 0);
1207 status = srvstr_push(base_data, flags2, p,
1208 fname, PTR_DIFF(end_data, p),
1209 STR_TERMINATE, &len);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 return status;
1213 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1214 if (len > 2) {
1215 SCVAL(nameptr, -1, len - 2);
1216 } else {
1217 SCVAL(nameptr, -1, 0);
1219 } else {
1220 if (len > 1) {
1221 SCVAL(nameptr, -1, len - 1);
1222 } else {
1223 SCVAL(nameptr, -1, 0);
1226 p += len;
1227 break;
1229 case SMB_FIND_EA_SIZE:
1230 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1231 if (requires_resume_key) {
1232 SIVAL(p,0,reskey);
1233 p += 4;
1235 srv_put_dos_date2(p,0,create_date);
1236 srv_put_dos_date2(p,4,adate);
1237 srv_put_dos_date2(p,8,mdate);
1238 SIVAL(p,12,(uint32_t)file_size);
1239 SIVAL(p,16,(uint32_t)allocation_size);
1240 SSVAL(p,20,mode);
1242 ea_size = estimate_ea_size(smb_fname->fsp);
1243 SIVAL(p,22,ea_size); /* Extended attributes */
1245 p += 27;
1246 nameptr = p - 1;
1247 status = srvstr_push(base_data, flags2,
1248 p, fname, PTR_DIFF(end_data, p),
1249 STR_TERMINATE | STR_NOALIGN, &len);
1250 if (!NT_STATUS_IS_OK(status)) {
1251 return status;
1253 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1254 if (len > 2) {
1255 len -= 2;
1256 } else {
1257 len = 0;
1259 } else {
1260 if (len > 1) {
1261 len -= 1;
1262 } else {
1263 len = 0;
1266 SCVAL(nameptr,0,len);
1267 p += len;
1268 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1269 break;
1271 case SMB_FIND_EA_LIST:
1273 struct ea_list *file_list = NULL;
1274 size_t ea_len = 0;
1276 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1277 if (!name_list) {
1278 return NT_STATUS_INVALID_PARAMETER;
1280 if (requires_resume_key) {
1281 SIVAL(p,0,reskey);
1282 p += 4;
1284 srv_put_dos_date2(p,0,create_date);
1285 srv_put_dos_date2(p,4,adate);
1286 srv_put_dos_date2(p,8,mdate);
1287 SIVAL(p,12,(uint32_t)file_size);
1288 SIVAL(p,16,(uint32_t)allocation_size);
1289 SSVAL(p,20,mode);
1290 p += 22; /* p now points to the EA area. */
1292 status = get_ea_list_from_fsp(ctx,
1293 smb_fname->fsp,
1294 &ea_len, &file_list);
1295 if (!NT_STATUS_IS_OK(status)) {
1296 file_list = NULL;
1298 name_list = ea_list_union(name_list, file_list, &ea_len);
1300 /* We need to determine if this entry will fit in the space available. */
1301 /* Max string size is 255 bytes. */
1302 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1303 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1304 "(wanted %u, had %d)\n",
1305 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1306 space_remaining ));
1307 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1310 /* Push the ea_data followed by the name. */
1311 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1312 nameptr = p;
1313 status = srvstr_push(base_data, flags2,
1314 p + 1, fname, PTR_DIFF(end_data, p+1),
1315 STR_TERMINATE | STR_NOALIGN, &len);
1316 if (!NT_STATUS_IS_OK(status)) {
1317 return status;
1319 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1320 if (len > 2) {
1321 len -= 2;
1322 } else {
1323 len = 0;
1325 } else {
1326 if (len > 1) {
1327 len -= 1;
1328 } else {
1329 len = 0;
1332 SCVAL(nameptr,0,len);
1333 p += len + 1;
1334 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1335 break;
1338 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1339 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1340 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1341 p += 4;
1342 SIVAL(p,0,reskey); p += 4;
1343 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1344 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1345 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1346 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1347 SOFF_T(p,0,file_size); p += 8;
1348 SOFF_T(p,0,allocation_size); p += 8;
1349 SIVAL(p,0,mode); p += 4;
1350 q = p; p += 4; /* q is placeholder for name length. */
1351 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1352 SIVAL(p, 0, ea_size);
1353 p += 4;
1354 /* Clear the short name buffer. This is
1355 * IMPORTANT as not doing so will trigger
1356 * a Win2k client bug. JRA.
1358 if (!was_8_3 && check_mangled_names) {
1359 char mangled_name[13]; /* mangled 8.3 name. */
1360 if (!name_to_8_3(fname,mangled_name,True,
1361 conn->params)) {
1362 /* Error - mangle failed ! */
1363 memset(mangled_name,'\0',12);
1365 mangled_name[12] = 0;
1366 status = srvstr_push(base_data, flags2,
1367 p+2, mangled_name, 24,
1368 STR_UPPER|STR_UNICODE, &len);
1369 if (!NT_STATUS_IS_OK(status)) {
1370 return status;
1372 if (len < 24) {
1373 memset(p + 2 + len,'\0',24 - len);
1375 SSVAL(p, 0, len);
1376 } else {
1377 memset(p,'\0',26);
1379 p += 2 + 24;
1380 status = srvstr_push(base_data, flags2, p,
1381 fname, PTR_DIFF(end_data, p),
1382 STR_TERMINATE_ASCII, &len);
1383 if (!NT_STATUS_IS_OK(status)) {
1384 return status;
1386 SIVAL(q,0,len);
1387 p += len;
1389 len = PTR_DIFF(p, pdata);
1390 pad = (len + (align-1)) & ~(align-1);
1392 * offset to the next entry, the caller
1393 * will overwrite it for the last entry
1394 * that's why we always include the padding
1396 SIVAL(pdata,0,pad);
1398 * set padding to zero
1400 if (do_pad) {
1401 memset(p, 0, pad - len);
1402 p = pdata + pad;
1403 } else {
1404 p = pdata + len;
1406 break;
1408 case SMB_FIND_FILE_DIRECTORY_INFO:
1409 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1410 p += 4;
1411 SIVAL(p,0,reskey); p += 4;
1412 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1413 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1414 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1415 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1416 SOFF_T(p,0,file_size); p += 8;
1417 SOFF_T(p,0,allocation_size); p += 8;
1418 SIVAL(p,0,mode); p += 4;
1419 status = srvstr_push(base_data, flags2,
1420 p + 4, fname, PTR_DIFF(end_data, p+4),
1421 STR_TERMINATE_ASCII, &len);
1422 if (!NT_STATUS_IS_OK(status)) {
1423 return status;
1425 SIVAL(p,0,len);
1426 p += 4 + len;
1428 len = PTR_DIFF(p, pdata);
1429 pad = (len + (align-1)) & ~(align-1);
1431 * offset to the next entry, the caller
1432 * will overwrite it for the last entry
1433 * that's why we always include the padding
1435 SIVAL(pdata,0,pad);
1437 * set padding to zero
1439 if (do_pad) {
1440 memset(p, 0, pad - len);
1441 p = pdata + pad;
1442 } else {
1443 p = pdata + len;
1445 break;
1447 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1448 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1449 p += 4;
1450 SIVAL(p,0,reskey); p += 4;
1451 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1452 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1453 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1454 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1455 SOFF_T(p,0,file_size); p += 8;
1456 SOFF_T(p,0,allocation_size); p += 8;
1457 SIVAL(p,0,mode); p += 4;
1458 q = p; p += 4; /* q is placeholder for name length. */
1459 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1460 SIVAL(p, 0, ea_size);
1461 p +=4;
1462 status = srvstr_push(base_data, flags2, p,
1463 fname, PTR_DIFF(end_data, p),
1464 STR_TERMINATE_ASCII, &len);
1465 if (!NT_STATUS_IS_OK(status)) {
1466 return status;
1468 SIVAL(q, 0, len);
1469 p += len;
1471 len = PTR_DIFF(p, pdata);
1472 pad = (len + (align-1)) & ~(align-1);
1474 * offset to the next entry, the caller
1475 * will overwrite it for the last entry
1476 * that's why we always include the padding
1478 SIVAL(pdata,0,pad);
1480 * set padding to zero
1482 if (do_pad) {
1483 memset(p, 0, pad - len);
1484 p = pdata + pad;
1485 } else {
1486 p = pdata + len;
1488 break;
1490 case SMB_FIND_FILE_NAMES_INFO:
1491 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1492 p += 4;
1493 SIVAL(p,0,reskey); p += 4;
1494 p += 4;
1495 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1496 acl on a dir (tridge) */
1497 status = srvstr_push(base_data, flags2, p,
1498 fname, PTR_DIFF(end_data, p),
1499 STR_TERMINATE_ASCII, &len);
1500 if (!NT_STATUS_IS_OK(status)) {
1501 return status;
1503 SIVAL(p, -4, len);
1504 p += len;
1506 len = PTR_DIFF(p, pdata);
1507 pad = (len + (align-1)) & ~(align-1);
1509 * offset to the next entry, the caller
1510 * will overwrite it for the last entry
1511 * that's why we always include the padding
1513 SIVAL(pdata,0,pad);
1515 * set padding to zero
1517 if (do_pad) {
1518 memset(p, 0, pad - len);
1519 p = pdata + pad;
1520 } else {
1521 p = pdata + len;
1523 break;
1525 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1526 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1527 p += 4;
1528 SIVAL(p,0,reskey); p += 4;
1529 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1530 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1531 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1532 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1533 SOFF_T(p,0,file_size); p += 8;
1534 SOFF_T(p,0,allocation_size); p += 8;
1535 SIVAL(p,0,mode); p += 4;
1536 q = p; p += 4; /* q is placeholder for name length. */
1537 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1538 SIVAL(p, 0, ea_size);
1539 p += 4;
1540 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1541 SBVAL(p,0,file_id); p += 8;
1542 status = srvstr_push(base_data, flags2, p,
1543 fname, PTR_DIFF(end_data, p),
1544 STR_TERMINATE_ASCII, &len);
1545 if (!NT_STATUS_IS_OK(status)) {
1546 return status;
1548 SIVAL(q, 0, len);
1549 p += len;
1551 len = PTR_DIFF(p, pdata);
1552 pad = (len + (align-1)) & ~(align-1);
1554 * offset to the next entry, the caller
1555 * will overwrite it for the last entry
1556 * that's why we always include the padding
1558 SIVAL(pdata,0,pad);
1560 * set padding to zero
1562 if (do_pad) {
1563 memset(p, 0, pad - len);
1564 p = pdata + pad;
1565 } else {
1566 p = pdata + len;
1568 break;
1570 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1571 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1572 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1573 p += 4;
1574 SIVAL(p,0,reskey); p += 4;
1575 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1576 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1577 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1578 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1579 SOFF_T(p,0,file_size); p += 8;
1580 SOFF_T(p,0,allocation_size); p += 8;
1581 SIVAL(p,0,mode); p += 4;
1582 q = p; p += 4; /* q is placeholder for name length */
1583 if (readdir_attr_data &&
1584 readdir_attr_data->type == RDATTR_AAPL) {
1586 * OS X specific SMB2 extension negotiated via
1587 * AAPL create context: return max_access in
1588 * ea_size field.
1590 ea_size = readdir_attr_data->attr_data.aapl.max_access;
1591 } else {
1592 ea_size = get_dirent_ea_size(mode, smb_fname->fsp);
1594 SIVAL(p,0,ea_size); /* Extended attributes */
1595 p += 4;
1597 if (readdir_attr_data &&
1598 readdir_attr_data->type == RDATTR_AAPL) {
1600 * OS X specific SMB2 extension negotiated via
1601 * AAPL create context: return resource fork
1602 * length and compressed FinderInfo in
1603 * shortname field.
1605 * According to documentation short_name_len
1606 * should be 0, but on the wire behaviour
1607 * shows its set to 24 by clients.
1609 SSVAL(p, 0, 24);
1611 /* Resourefork length */
1612 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1614 /* Compressed FinderInfo */
1615 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1616 } else if (!was_8_3 && check_mangled_names) {
1617 char mangled_name[13]; /* mangled 8.3 name. */
1618 if (!name_to_8_3(fname,mangled_name,True,
1619 conn->params)) {
1620 /* Error - mangle failed ! */
1621 memset(mangled_name,'\0',12);
1623 mangled_name[12] = 0;
1624 status = srvstr_push(base_data, flags2,
1625 p+2, mangled_name, 24,
1626 STR_UPPER|STR_UNICODE, &len);
1627 if (!NT_STATUS_IS_OK(status)) {
1628 return status;
1630 SSVAL(p, 0, len);
1631 if (len < 24) {
1632 memset(p + 2 + len,'\0',24 - len);
1634 SSVAL(p, 0, len);
1635 } else {
1636 /* Clear the short name buffer. This is
1637 * IMPORTANT as not doing so will trigger
1638 * a Win2k client bug. JRA.
1640 memset(p,'\0',26);
1642 p += 26;
1644 /* Reserved ? */
1645 if (readdir_attr_data &&
1646 readdir_attr_data->type == RDATTR_AAPL) {
1648 * OS X specific SMB2 extension negotiated via
1649 * AAPL create context: return UNIX mode in
1650 * reserved field.
1652 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1653 SSVAL(p, 0, aapl_mode);
1654 } else {
1655 SSVAL(p, 0, 0);
1657 p += 2;
1659 SBVAL(p,0,file_id); p += 8;
1660 status = srvstr_push(base_data, flags2, p,
1661 fname, PTR_DIFF(end_data, p),
1662 STR_TERMINATE_ASCII, &len);
1663 if (!NT_STATUS_IS_OK(status)) {
1664 return status;
1666 SIVAL(q,0,len);
1667 p += len;
1669 len = PTR_DIFF(p, pdata);
1670 pad = (len + (align-1)) & ~(align-1);
1672 * offset to the next entry, the caller
1673 * will overwrite it for the last entry
1674 * that's why we always include the padding
1676 SIVAL(pdata,0,pad);
1678 * set padding to zero
1680 if (do_pad) {
1681 memset(p, 0, pad - len);
1682 p = pdata + pad;
1683 } else {
1684 p = pdata + len;
1686 break;
1688 /* CIFS UNIX Extension. */
1690 case SMB_FIND_FILE_UNIX:
1691 case SMB_FIND_FILE_UNIX_INFO2:
1692 p+= 4;
1693 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1695 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1697 if (info_level == SMB_FIND_FILE_UNIX) {
1698 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1699 p = store_file_unix_basic(conn, p,
1700 NULL, &smb_fname->st);
1701 status = srvstr_push(base_data, flags2, p,
1702 fname, PTR_DIFF(end_data, p),
1703 STR_TERMINATE, &len);
1704 if (!NT_STATUS_IS_OK(status)) {
1705 return status;
1707 } else {
1708 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1709 p = store_file_unix_basic_info2(conn, p,
1710 NULL, &smb_fname->st);
1711 nameptr = p;
1712 p += 4;
1713 status = srvstr_push(base_data, flags2, p, fname,
1714 PTR_DIFF(end_data, p), 0, &len);
1715 if (!NT_STATUS_IS_OK(status)) {
1716 return status;
1718 SIVAL(nameptr, 0, len);
1721 p += len;
1723 len = PTR_DIFF(p, pdata);
1724 pad = (len + (align-1)) & ~(align-1);
1726 * offset to the next entry, the caller
1727 * will overwrite it for the last entry
1728 * that's why we always include the padding
1730 SIVAL(pdata,0,pad);
1732 * set padding to zero
1734 if (do_pad) {
1735 memset(p, 0, pad - len);
1736 p = pdata + pad;
1737 } else {
1738 p = pdata + len;
1740 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1742 break;
1744 /* SMB2 UNIX Extension. */
1746 case SMB2_FILE_POSIX_INFORMATION:
1748 uint8_t *buf = NULL;
1749 ssize_t plen = 0;
1750 p+= 4;
1751 SIVAL(p,0,reskey); p+= 4;
1753 DEBUG(10,("smbd_marshall_dir_entry: "
1754 "SMB2_FILE_POSIX_INFORMATION\n"));
1755 if (!(conn->sconn->using_smb2)) {
1756 return NT_STATUS_INVALID_LEVEL;
1758 if (!lp_smb3_unix_extensions()) {
1759 return NT_STATUS_INVALID_LEVEL;
1762 /* Determine the size of the posix info context */
1763 plen = store_smb2_posix_info(conn,
1764 &smb_fname->st,
1766 mode,
1767 NULL,
1769 if (plen == -1) {
1770 return NT_STATUS_INVALID_PARAMETER;
1772 buf = talloc_zero_size(ctx, plen);
1773 if (buf == NULL) {
1774 return NT_STATUS_NO_MEMORY;
1777 /* Store the context in buf */
1778 store_smb2_posix_info(conn,
1779 &smb_fname->st,
1781 mode,
1782 buf,
1783 plen);
1784 memcpy(p, buf, plen);
1785 p += plen;
1786 TALLOC_FREE(buf);
1788 nameptr = p;
1789 p += 4;
1790 status = srvstr_push(base_data, flags2, p, fname,
1791 PTR_DIFF(end_data, p), 0, &len);
1792 if (!NT_STATUS_IS_OK(status)) {
1793 return status;
1795 SIVAL(nameptr, 0, len);
1797 p += len;
1799 len = PTR_DIFF(p, pdata);
1800 pad = (len + (align-1)) & ~(align-1);
1802 * offset to the next entry, the caller
1803 * will overwrite it for the last entry
1804 * that's why we always include the padding
1806 SIVAL(pdata,0,pad);
1807 break;
1810 default:
1811 return NT_STATUS_INVALID_LEVEL;
1814 if (PTR_DIFF(p,pdata) > space_remaining) {
1815 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1816 "(wanted %u, had %d)\n",
1817 (unsigned int)PTR_DIFF(p,pdata),
1818 space_remaining ));
1819 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1822 /* Setup the last entry pointer, as an offset from base_data */
1823 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1824 /* Advance the data pointer to the next slot */
1825 *ppdata = p;
1827 return NT_STATUS_OK;
1830 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1831 connection_struct *conn,
1832 struct dptr_struct *dirptr,
1833 uint16_t flags2,
1834 const char *path_mask,
1835 uint32_t dirtype,
1836 int info_level,
1837 int requires_resume_key,
1838 bool dont_descend,
1839 bool ask_sharemode,
1840 bool get_dosmode,
1841 uint8_t align,
1842 bool do_pad,
1843 char **ppdata,
1844 char *base_data,
1845 char *end_data,
1846 int space_remaining,
1847 struct smb_filename **_smb_fname,
1848 int *_last_entry_off,
1849 struct ea_list *name_list,
1850 struct file_id *file_id)
1852 const char *p;
1853 const char *mask = NULL;
1854 uint32_t mode = 0;
1855 char *fname = NULL;
1856 struct smb_filename *smb_fname = NULL;
1857 struct smbd_dirptr_lanman2_state state;
1858 bool ok;
1859 uint64_t last_entry_off = 0;
1860 NTSTATUS status;
1861 enum mangled_names_options mangled_names;
1862 bool marshall_with_83_names;
1864 mangled_names = lp_mangled_names(conn->params);
1866 ZERO_STRUCT(state);
1867 state.conn = conn;
1868 state.info_level = info_level;
1869 if (mangled_names != MANGLED_NAMES_NO) {
1870 state.check_mangled_names = true;
1872 state.case_sensitive = dptr_case_sensitive(dirptr);
1874 p = strrchr_m(path_mask,'/');
1875 if(p != NULL) {
1876 if(p[1] == '\0') {
1877 mask = "*.*";
1878 } else {
1879 mask = p+1;
1881 } else {
1882 mask = path_mask;
1885 ok = smbd_dirptr_get_entry(ctx,
1886 dirptr,
1887 mask,
1888 dirtype,
1889 dont_descend,
1890 ask_sharemode,
1891 get_dosmode,
1892 smbd_dirptr_lanman2_match_fn,
1893 smbd_dirptr_lanman2_mode_fn,
1894 &state,
1895 &fname,
1896 &smb_fname,
1897 &mode);
1898 if (!ok) {
1899 return NT_STATUS_END_OF_FILE;
1902 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
1904 status = smbd_marshall_dir_entry(ctx,
1905 conn,
1906 flags2,
1907 info_level,
1908 name_list,
1909 marshall_with_83_names,
1910 requires_resume_key,
1911 mode,
1912 fname,
1913 smb_fname,
1914 space_remaining,
1915 align,
1916 do_pad,
1917 base_data,
1918 ppdata,
1919 end_data,
1920 &last_entry_off);
1921 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
1922 DEBUG(1,("Conversion error: illegal character: %s\n",
1923 smb_fname_str_dbg(smb_fname)));
1926 if (file_id != NULL) {
1927 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
1930 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
1931 smbd_dirptr_push_overflow(dirptr, &fname, &smb_fname, mode);
1934 if (!NT_STATUS_IS_OK(status)) {
1935 TALLOC_FREE(smb_fname);
1936 TALLOC_FREE(fname);
1937 return status;
1940 smbd_dirptr_set_last_name_sent(dirptr, &smb_fname->base_name);
1942 if (_smb_fname != NULL) {
1944 * smb_fname is already talloc'ed off ctx.
1945 * We just need to make sure we don't return
1946 * any stream_name, and replace base_name
1947 * with fname in case base_name got mangled.
1948 * This allows us to preserve any smb_fname->fsp
1949 * for asynchronous handle lookups.
1951 TALLOC_FREE(smb_fname->stream_name);
1954 * smbd_dirptr_set_last_name_sent() above consumed
1955 * base_name
1957 smb_fname->base_name = talloc_strdup(smb_fname, fname);
1959 if (smb_fname->base_name == NULL) {
1960 TALLOC_FREE(smb_fname);
1961 TALLOC_FREE(fname);
1962 return NT_STATUS_NO_MEMORY;
1964 *_smb_fname = smb_fname;
1965 } else {
1966 TALLOC_FREE(smb_fname);
1968 TALLOC_FREE(fname);
1970 *_last_entry_off = last_entry_off;
1971 return NT_STATUS_OK;
1974 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
1976 const struct loadparm_substitution *lp_sub =
1977 loadparm_s3_global_substitution();
1979 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
1980 return objid;
1983 static void samba_extended_info_version(struct smb_extended_info *extended_info)
1985 SMB_ASSERT(extended_info != NULL);
1987 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
1988 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
1989 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
1990 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
1991 #ifdef SAMBA_VERSION_REVISION
1992 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
1993 #endif
1994 extended_info->samba_subversion = 0;
1995 #ifdef SAMBA_VERSION_RC_RELEASE
1996 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
1997 #else
1998 #ifdef SAMBA_VERSION_PRE_RELEASE
1999 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2000 #endif
2001 #endif
2002 #ifdef SAMBA_VERSION_VENDOR_PATCH
2003 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2004 #endif
2005 extended_info->samba_gitcommitdate = 0;
2006 #ifdef SAMBA_VERSION_COMMIT_TIME
2007 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2008 #endif
2010 memset(extended_info->samba_version_string, 0,
2011 sizeof(extended_info->samba_version_string));
2013 snprintf (extended_info->samba_version_string,
2014 sizeof(extended_info->samba_version_string),
2015 "%s", samba_version_string());
2018 static bool fsinfo_unix_valid_level(connection_struct *conn,
2019 uint16_t info_level)
2021 if (conn->sconn->using_smb2 &&
2022 lp_smb3_unix_extensions() &&
2023 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
2024 return true;
2026 #if defined(SMB1SERVER)
2027 if (lp_smb1_unix_extensions() &&
2028 info_level == SMB_QUERY_POSIX_FS_INFO) {
2029 return true;
2031 #endif
2032 return false;
2035 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2036 connection_struct *conn,
2037 TALLOC_CTX *mem_ctx,
2038 uint16_t info_level,
2039 uint16_t flags2,
2040 unsigned int max_data_bytes,
2041 size_t *fixed_portion,
2042 struct smb_filename *fname,
2043 char **ppdata,
2044 int *ret_data_len)
2046 const struct loadparm_substitution *lp_sub =
2047 loadparm_s3_global_substitution();
2048 char *pdata, *end_data;
2049 int data_len = 0;
2050 size_t len = 0;
2051 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2052 int snum = SNUM(conn);
2053 const char *fstype = lp_fstype(SNUM(conn));
2054 const char *filename = NULL;
2055 const uint64_t bytes_per_sector = 512;
2056 uint32_t additional_flags = 0;
2057 struct smb_filename smb_fname;
2058 SMB_STRUCT_STAT st;
2059 NTSTATUS status = NT_STATUS_OK;
2060 uint64_t df_ret;
2061 uint32_t serial;
2063 if (fname == NULL || fname->base_name == NULL) {
2064 filename = ".";
2065 } else {
2066 filename = fname->base_name;
2069 if (IS_IPC(conn)) {
2070 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2071 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2072 "info level (0x%x) on IPC$.\n",
2073 (unsigned int)info_level));
2074 return NT_STATUS_ACCESS_DENIED;
2078 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2080 smb_fname = (struct smb_filename) {
2081 .base_name = discard_const_p(char, filename),
2082 .flags = fname ? fname->flags : 0,
2083 .twrp = fname ? fname->twrp : 0,
2086 if(info_level != SMB_FS_QUOTA_INFORMATION
2087 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2088 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2089 return map_nt_error_from_unix(errno);
2092 st = smb_fname.st;
2094 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2095 return NT_STATUS_INVALID_PARAMETER;
2098 *ppdata = (char *)SMB_REALLOC(
2099 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2100 if (*ppdata == NULL) {
2101 return NT_STATUS_NO_MEMORY;
2104 pdata = *ppdata;
2105 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2106 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2108 *fixed_portion = 0;
2110 switch (info_level) {
2111 case SMB_INFO_ALLOCATION:
2113 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2114 data_len = 18;
2115 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2116 &dfree, &dsize);
2117 if (df_ret == (uint64_t)-1) {
2118 return map_nt_error_from_unix(errno);
2121 block_size = lp_block_size(snum);
2122 if (bsize < block_size) {
2123 uint64_t factor = block_size/bsize;
2124 bsize = block_size;
2125 dsize /= factor;
2126 dfree /= factor;
2128 if (bsize > block_size) {
2129 uint64_t factor = bsize/block_size;
2130 bsize = block_size;
2131 dsize *= factor;
2132 dfree *= factor;
2134 sectors_per_unit = bsize/bytes_per_sector;
2136 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2137 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2138 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2141 * For large drives, return max values and not modulo.
2143 dsize = MIN(dsize, UINT32_MAX);
2144 dfree = MIN(dfree, UINT32_MAX);
2146 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2147 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2148 SIVAL(pdata,l1_cUnit,dsize);
2149 SIVAL(pdata,l1_cUnitAvail,dfree);
2150 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2151 break;
2154 case SMB_INFO_VOLUME:
2155 /* Return volume name */
2157 * Add volume serial number - hash of a combination of
2158 * the called hostname and the service name.
2160 serial = generate_volume_serial_number(lp_sub, snum);
2161 SIVAL(pdata,0,serial);
2163 * Win2k3 and previous mess this up by sending a name length
2164 * one byte short. I believe only older clients (OS/2 Win9x) use
2165 * this call so try fixing this by adding a terminating null to
2166 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2168 status = srvstr_push(
2169 pdata, flags2,
2170 pdata+l2_vol_szVolLabel, vname,
2171 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2172 STR_NOALIGN|STR_TERMINATE, &len);
2173 if (!NT_STATUS_IS_OK(status)) {
2174 return status;
2176 SCVAL(pdata,l2_vol_cch,len);
2177 data_len = l2_vol_szVolLabel + len;
2178 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2179 "name = %s serial = 0x%04"PRIx32"\n",
2180 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2181 (unsigned)len, vname, serial));
2182 break;
2184 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2185 case SMB_FS_ATTRIBUTE_INFORMATION:
2187 additional_flags = 0;
2188 #if defined(HAVE_SYS_QUOTAS)
2189 additional_flags |= FILE_VOLUME_QUOTAS;
2190 #endif
2192 if(lp_nt_acl_support(SNUM(conn))) {
2193 additional_flags |= FILE_PERSISTENT_ACLS;
2196 /* Capabilities are filled in at connection time through STATVFS call */
2197 additional_flags |= conn->fs_capabilities;
2198 additional_flags |= lp_parm_int(conn->params->service,
2199 "share", "fake_fscaps",
2202 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2203 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2204 additional_flags); /* FS ATTRIBUTES */
2206 SIVAL(pdata,4,255); /* Max filename component length */
2207 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2208 and will think we can't do long filenames */
2209 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2210 PTR_DIFF(end_data, pdata+12),
2211 STR_UNICODE, &len);
2212 if (!NT_STATUS_IS_OK(status)) {
2213 return status;
2215 SIVAL(pdata,8,len);
2216 data_len = 12 + len;
2217 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2218 /* the client only requested a portion of the
2219 file system name */
2220 data_len = max_data_bytes;
2221 status = STATUS_BUFFER_OVERFLOW;
2223 *fixed_portion = 16;
2224 break;
2226 case SMB_QUERY_FS_LABEL_INFO:
2227 case SMB_FS_LABEL_INFORMATION:
2228 status = srvstr_push(pdata, flags2, pdata+4, vname,
2229 PTR_DIFF(end_data, pdata+4), 0, &len);
2230 if (!NT_STATUS_IS_OK(status)) {
2231 return status;
2233 data_len = 4 + len;
2234 SIVAL(pdata,0,len);
2235 break;
2237 case SMB_QUERY_FS_VOLUME_INFO:
2238 case SMB_FS_VOLUME_INFORMATION:
2239 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2240 pdata, &st.st_ex_btime);
2242 * Add volume serial number - hash of a combination of
2243 * the called hostname and the service name.
2245 serial = generate_volume_serial_number(lp_sub, snum);
2246 SIVAL(pdata,8,serial);
2248 /* Max label len is 32 characters. */
2249 status = srvstr_push(pdata, flags2, pdata+18, vname,
2250 PTR_DIFF(end_data, pdata+18),
2251 STR_UNICODE, &len);
2252 if (!NT_STATUS_IS_OK(status)) {
2253 return status;
2255 SIVAL(pdata,12,len);
2256 data_len = 18+len;
2258 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2259 "namelen = %d, vol=%s serv=%s "
2260 "serial=0x%04"PRIx32"\n",
2261 (int)strlen(vname),vname,
2262 lp_servicename(talloc_tos(), lp_sub, snum),
2263 serial));
2264 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2265 /* the client only requested a portion of the
2266 volume label */
2267 data_len = max_data_bytes;
2268 status = STATUS_BUFFER_OVERFLOW;
2270 *fixed_portion = 24;
2271 break;
2273 case SMB_QUERY_FS_SIZE_INFO:
2274 case SMB_FS_SIZE_INFORMATION:
2276 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2277 data_len = 24;
2278 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2279 &dfree, &dsize);
2280 if (df_ret == (uint64_t)-1) {
2281 return map_nt_error_from_unix(errno);
2283 block_size = lp_block_size(snum);
2284 if (bsize < block_size) {
2285 uint64_t factor = block_size/bsize;
2286 bsize = block_size;
2287 dsize /= factor;
2288 dfree /= factor;
2290 if (bsize > block_size) {
2291 uint64_t factor = bsize/block_size;
2292 bsize = block_size;
2293 dsize *= factor;
2294 dfree *= factor;
2296 sectors_per_unit = bsize/bytes_per_sector;
2297 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2298 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2299 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2300 SBIG_UINT(pdata,0,dsize);
2301 SBIG_UINT(pdata,8,dfree);
2302 SIVAL(pdata,16,sectors_per_unit);
2303 SIVAL(pdata,20,bytes_per_sector);
2304 *fixed_portion = 24;
2305 break;
2308 case SMB_FS_FULL_SIZE_INFORMATION:
2310 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2311 data_len = 32;
2312 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2313 &dfree, &dsize);
2314 if (df_ret == (uint64_t)-1) {
2315 return map_nt_error_from_unix(errno);
2317 block_size = lp_block_size(snum);
2318 if (bsize < block_size) {
2319 uint64_t factor = block_size/bsize;
2320 bsize = block_size;
2321 dsize /= factor;
2322 dfree /= factor;
2324 if (bsize > block_size) {
2325 uint64_t factor = bsize/block_size;
2326 bsize = block_size;
2327 dsize *= factor;
2328 dfree *= factor;
2330 sectors_per_unit = bsize/bytes_per_sector;
2331 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2332 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2333 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2334 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2335 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2336 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2337 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2338 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2339 *fixed_portion = 32;
2340 break;
2343 case SMB_QUERY_FS_DEVICE_INFO:
2344 case SMB_FS_DEVICE_INFORMATION:
2346 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2348 if (!CAN_WRITE(conn)) {
2349 characteristics |= FILE_READ_ONLY_DEVICE;
2351 data_len = 8;
2352 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2353 SIVAL(pdata,4,characteristics);
2354 *fixed_portion = 8;
2355 break;
2358 #ifdef HAVE_SYS_QUOTAS
2359 case SMB_FS_QUOTA_INFORMATION:
2361 * what we have to send --metze:
2363 * Unknown1: 24 NULL bytes
2364 * Soft Quota Threshold: 8 bytes seems like uint64_t or so
2365 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2366 * Quota Flags: 2 byte :
2367 * Unknown3: 6 NULL bytes
2369 * 48 bytes total
2371 * details for Quota Flags:
2373 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2374 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2375 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2376 * 0x0001 Enable Quotas: enable quota for this fs
2380 /* we need to fake up a fsp here,
2381 * because its not send in this call
2383 files_struct fsp;
2384 SMB_NTQUOTA_STRUCT quotas;
2386 ZERO_STRUCT(fsp);
2387 ZERO_STRUCT(quotas);
2389 fsp.conn = conn;
2390 fsp.fnum = FNUM_FIELD_INVALID;
2392 /* access check */
2393 if (get_current_uid(conn) != 0) {
2394 DEBUG(0,("get_user_quota: access_denied "
2395 "service [%s] user [%s]\n",
2396 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2397 conn->session_info->unix_info->unix_name));
2398 return NT_STATUS_ACCESS_DENIED;
2401 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2402 NULL, &quotas);
2403 if (!NT_STATUS_IS_OK(status)) {
2404 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2405 return status;
2408 data_len = 48;
2410 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2411 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2413 /* Unknown1 24 NULL bytes*/
2414 SBIG_UINT(pdata,0,(uint64_t)0);
2415 SBIG_UINT(pdata,8,(uint64_t)0);
2416 SBIG_UINT(pdata,16,(uint64_t)0);
2418 /* Default Soft Quota 8 bytes */
2419 SBIG_UINT(pdata,24,quotas.softlim);
2421 /* Default Hard Quota 8 bytes */
2422 SBIG_UINT(pdata,32,quotas.hardlim);
2424 /* Quota flag 2 bytes */
2425 SSVAL(pdata,40,quotas.qflags);
2427 /* Unknown3 6 NULL bytes */
2428 SSVAL(pdata,42,0);
2429 SIVAL(pdata,44,0);
2431 break;
2433 #endif /* HAVE_SYS_QUOTAS */
2434 case SMB_FS_OBJECTID_INFORMATION:
2436 unsigned char objid[16];
2437 struct smb_extended_info extended_info;
2438 memcpy(pdata,create_volume_objectid(conn, objid),16);
2439 samba_extended_info_version (&extended_info);
2440 SIVAL(pdata,16,extended_info.samba_magic);
2441 SIVAL(pdata,20,extended_info.samba_version);
2442 SIVAL(pdata,24,extended_info.samba_subversion);
2443 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2444 memcpy(pdata+36,extended_info.samba_version_string,28);
2445 data_len = 64;
2446 break;
2449 case SMB_FS_SECTOR_SIZE_INFORMATION:
2451 data_len = 28;
2453 * These values match a physical Windows Server 2012
2454 * share backed by NTFS atop spinning rust.
2456 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2457 /* logical_bytes_per_sector */
2458 SIVAL(pdata, 0, bytes_per_sector);
2459 /* phys_bytes_per_sector_atomic */
2460 SIVAL(pdata, 4, bytes_per_sector);
2461 /* phys_bytes_per_sector_perf */
2462 SIVAL(pdata, 8, bytes_per_sector);
2463 /* fs_effective_phys_bytes_per_sector_atomic */
2464 SIVAL(pdata, 12, bytes_per_sector);
2465 /* flags */
2466 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2467 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2468 /* byte_off_sector_align */
2469 SIVAL(pdata, 20, 0);
2470 /* byte_off_partition_align */
2471 SIVAL(pdata, 24, 0);
2472 *fixed_portion = 28;
2473 break;
2477 #if defined(WITH_SMB1SERVER)
2479 * Query the version and capabilities of the CIFS UNIX extensions
2480 * in use.
2483 case SMB_QUERY_CIFS_UNIX_INFO:
2485 bool large_write = lp_min_receive_file_size() &&
2486 !smb1_srv_is_signing_active(xconn);
2487 bool large_read = !smb1_srv_is_signing_active(xconn);
2488 int encrypt_caps = 0;
2490 if (!lp_smb1_unix_extensions()) {
2491 return NT_STATUS_INVALID_LEVEL;
2494 switch (conn->encrypt_level) {
2495 case SMB_SIGNING_OFF:
2496 encrypt_caps = 0;
2497 break;
2498 case SMB_SIGNING_DESIRED:
2499 case SMB_SIGNING_IF_REQUIRED:
2500 case SMB_SIGNING_DEFAULT:
2501 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2502 break;
2503 case SMB_SIGNING_REQUIRED:
2504 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2505 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2506 large_write = false;
2507 large_read = false;
2508 break;
2511 data_len = 12;
2512 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2513 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2515 /* We have POSIX ACLs, pathname, encryption,
2516 * large read/write, and locking capability. */
2518 SBIG_UINT(pdata,4,((uint64_t)(
2519 CIFS_UNIX_POSIX_ACLS_CAP|
2520 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2521 CIFS_UNIX_FCNTL_LOCKS_CAP|
2522 CIFS_UNIX_EXTATTR_CAP|
2523 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2524 encrypt_caps|
2525 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2526 (large_write ?
2527 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2528 break;
2530 #endif
2532 case SMB_QUERY_POSIX_FS_INFO:
2533 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2535 int rc;
2536 struct vfs_statvfs_struct svfs;
2538 if (!fsinfo_unix_valid_level(conn, info_level)) {
2539 return NT_STATUS_INVALID_LEVEL;
2542 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2544 if (!rc) {
2545 data_len = 56;
2546 SIVAL(pdata,0,svfs.OptimalTransferSize);
2547 SIVAL(pdata,4,svfs.BlockSize);
2548 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2549 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2550 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2551 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2552 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2553 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2554 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2555 #ifdef EOPNOTSUPP
2556 } else if (rc == EOPNOTSUPP) {
2557 return NT_STATUS_INVALID_LEVEL;
2558 #endif /* EOPNOTSUPP */
2559 } else {
2560 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2561 return NT_STATUS_DOS(ERRSRV, ERRerror);
2563 break;
2566 case SMB_QUERY_POSIX_WHOAMI:
2568 uint32_t flags = 0;
2569 uint32_t sid_bytes;
2570 uint32_t i;
2572 if (!lp_smb1_unix_extensions()) {
2573 return NT_STATUS_INVALID_LEVEL;
2576 if (max_data_bytes < 40) {
2577 return NT_STATUS_BUFFER_TOO_SMALL;
2580 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2581 flags |= SMB_WHOAMI_GUEST;
2584 /* NOTE: 8 bytes for UID/GID, irrespective of native
2585 * platform size. This matches
2586 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2588 data_len = 4 /* flags */
2589 + 4 /* flag mask */
2590 + 8 /* uid */
2591 + 8 /* gid */
2592 + 4 /* ngroups */
2593 + 4 /* num_sids */
2594 + 4 /* SID bytes */
2595 + 4 /* pad/reserved */
2596 + (conn->session_info->unix_token->ngroups * 8)
2597 /* groups list */
2598 + (conn->session_info->security_token->num_sids *
2599 SID_MAX_SIZE)
2600 /* SID list */;
2602 SIVAL(pdata, 0, flags);
2603 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2604 SBIG_UINT(pdata, 8,
2605 (uint64_t)conn->session_info->unix_token->uid);
2606 SBIG_UINT(pdata, 16,
2607 (uint64_t)conn->session_info->unix_token->gid);
2610 if (data_len >= max_data_bytes) {
2611 /* Potential overflow, skip the GIDs and SIDs. */
2613 SIVAL(pdata, 24, 0); /* num_groups */
2614 SIVAL(pdata, 28, 0); /* num_sids */
2615 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2616 SIVAL(pdata, 36, 0); /* reserved */
2618 data_len = 40;
2619 break;
2622 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2623 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2625 /* We walk the SID list twice, but this call is fairly
2626 * infrequent, and I don't expect that it's performance
2627 * sensitive -- jpeach
2629 for (i = 0, sid_bytes = 0;
2630 i < conn->session_info->security_token->num_sids; ++i) {
2631 sid_bytes += ndr_size_dom_sid(
2632 &conn->session_info->security_token->sids[i],
2636 /* SID list byte count */
2637 SIVAL(pdata, 32, sid_bytes);
2639 /* 4 bytes pad/reserved - must be zero */
2640 SIVAL(pdata, 36, 0);
2641 data_len = 40;
2643 /* GID list */
2644 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2645 SBIG_UINT(pdata, data_len,
2646 (uint64_t)conn->session_info->unix_token->groups[i]);
2647 data_len += 8;
2650 /* SID list */
2651 for (i = 0;
2652 i < conn->session_info->security_token->num_sids; ++i) {
2653 int sid_len = ndr_size_dom_sid(
2654 &conn->session_info->security_token->sids[i],
2657 sid_linearize((uint8_t *)(pdata + data_len),
2658 sid_len,
2659 &conn->session_info->security_token->sids[i]);
2660 data_len += sid_len;
2663 break;
2666 case SMB_MAC_QUERY_FS_INFO:
2668 * Thursby MAC extension... ONLY on NTFS filesystems
2669 * once we do streams then we don't need this
2671 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2672 data_len = 88;
2673 SIVAL(pdata,84,0x100); /* Don't support mac... */
2674 break;
2677 FALL_THROUGH;
2678 default:
2679 return NT_STATUS_INVALID_LEVEL;
2682 *ret_data_len = data_len;
2683 return status;
2686 NTSTATUS smb_set_fsquota(connection_struct *conn,
2687 struct smb_request *req,
2688 files_struct *fsp,
2689 const DATA_BLOB *qdata)
2691 const struct loadparm_substitution *lp_sub =
2692 loadparm_s3_global_substitution();
2693 NTSTATUS status;
2694 SMB_NTQUOTA_STRUCT quotas;
2696 ZERO_STRUCT(quotas);
2698 /* access check */
2699 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2700 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2701 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2702 conn->session_info->unix_info->unix_name));
2703 return NT_STATUS_ACCESS_DENIED;
2706 if (!check_fsp_ntquota_handle(conn, req,
2707 fsp)) {
2708 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2709 return NT_STATUS_INVALID_HANDLE;
2712 /* note: normally there're 48 bytes,
2713 * but we didn't use the last 6 bytes for now
2714 * --metze
2716 if (qdata->length < 42) {
2717 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2718 (unsigned int)qdata->length));
2719 return NT_STATUS_INVALID_PARAMETER;
2722 /* unknown_1 24 NULL bytes in pdata*/
2724 /* the soft quotas 8 bytes (uint64_t)*/
2725 quotas.softlim = BVAL(qdata->data,24);
2727 /* the hard quotas 8 bytes (uint64_t)*/
2728 quotas.hardlim = BVAL(qdata->data,32);
2730 /* quota_flags 2 bytes **/
2731 quotas.qflags = SVAL(qdata->data,40);
2733 /* unknown_2 6 NULL bytes follow*/
2735 /* now set the quotas */
2736 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2737 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2738 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2739 status = map_nt_error_from_unix(errno);
2740 } else {
2741 status = NT_STATUS_OK;
2743 return status;
2746 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2747 struct smb_request *req,
2748 TALLOC_CTX *mem_ctx,
2749 uint16_t info_level,
2750 files_struct *fsp,
2751 const DATA_BLOB *pdata)
2753 switch (info_level) {
2754 case SMB_FS_QUOTA_INFORMATION:
2756 return smb_set_fsquota(conn,
2757 req,
2758 fsp,
2759 pdata);
2762 default:
2763 break;
2765 return NT_STATUS_INVALID_LEVEL;
2768 /****************************************************************************
2769 Store the FILE_UNIX_BASIC info.
2770 ****************************************************************************/
2772 char *store_file_unix_basic(connection_struct *conn,
2773 char *pdata,
2774 files_struct *fsp,
2775 const SMB_STRUCT_STAT *psbuf)
2777 dev_t devno;
2779 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
2780 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
2782 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
2783 pdata += 8;
2785 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
2786 pdata += 8;
2788 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
2789 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
2790 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
2791 pdata += 24;
2793 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
2794 SIVAL(pdata,4,0);
2795 pdata += 8;
2797 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
2798 SIVAL(pdata,4,0);
2799 pdata += 8;
2801 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
2802 pdata += 4;
2804 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
2805 devno = psbuf->st_ex_rdev;
2806 } else {
2807 devno = psbuf->st_ex_dev;
2810 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
2811 SIVAL(pdata,4,0);
2812 pdata += 8;
2814 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
2815 SIVAL(pdata,4,0);
2816 pdata += 8;
2818 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
2819 pdata += 8;
2821 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
2822 SIVAL(pdata,4,0);
2823 pdata += 8;
2825 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
2826 SIVAL(pdata,4,0);
2827 pdata += 8;
2829 return pdata;
2832 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
2833 * the chflags(2) (or equivalent) flags.
2835 * XXX: this really should be behind the VFS interface. To do this, we would
2836 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
2837 * Each VFS module could then implement its own mapping as appropriate for the
2838 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
2840 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
2841 info2_flags_map[] =
2843 #ifdef UF_NODUMP
2844 { UF_NODUMP, EXT_DO_NOT_BACKUP },
2845 #endif
2847 #ifdef UF_IMMUTABLE
2848 { UF_IMMUTABLE, EXT_IMMUTABLE },
2849 #endif
2851 #ifdef UF_APPEND
2852 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
2853 #endif
2855 #ifdef UF_HIDDEN
2856 { UF_HIDDEN, EXT_HIDDEN },
2857 #endif
2859 /* Do not remove. We need to guarantee that this array has at least one
2860 * entry to build on HP-UX.
2862 { 0, 0 }
2866 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
2867 uint32_t *smb_fflags, uint32_t *smb_fmask)
2869 size_t i;
2871 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2872 *smb_fmask |= info2_flags_map[i].smb_fflag;
2873 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
2874 *smb_fflags |= info2_flags_map[i].smb_fflag;
2879 bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
2880 const uint32_t smb_fflags,
2881 const uint32_t smb_fmask,
2882 int *stat_fflags)
2884 uint32_t max_fmask = 0;
2885 size_t i;
2887 *stat_fflags = psbuf->st_ex_flags;
2889 /* For each flags requested in smb_fmask, check the state of the
2890 * corresponding flag in smb_fflags and set or clear the matching
2891 * stat flag.
2894 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
2895 max_fmask |= info2_flags_map[i].smb_fflag;
2896 if (smb_fmask & info2_flags_map[i].smb_fflag) {
2897 if (smb_fflags & info2_flags_map[i].smb_fflag) {
2898 *stat_fflags |= info2_flags_map[i].stat_fflag;
2899 } else {
2900 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
2905 /* If smb_fmask is asking to set any bits that are not supported by
2906 * our flag mappings, we should fail.
2908 if ((smb_fmask & max_fmask) != smb_fmask) {
2909 return False;
2912 return True;
2916 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
2917 * of file flags and birth (create) time.
2919 char *store_file_unix_basic_info2(connection_struct *conn,
2920 char *pdata,
2921 files_struct *fsp,
2922 const SMB_STRUCT_STAT *psbuf)
2924 uint32_t file_flags = 0;
2925 uint32_t flags_mask = 0;
2927 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
2929 /* Create (birth) time 64 bit */
2930 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
2931 pdata += 8;
2933 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
2934 SIVAL(pdata, 0, file_flags); /* flags */
2935 SIVAL(pdata, 4, flags_mask); /* mask */
2936 pdata += 8;
2938 return pdata;
2941 static NTSTATUS marshall_stream_info(unsigned int num_streams,
2942 const struct stream_struct *streams,
2943 char *data,
2944 unsigned int max_data_bytes,
2945 unsigned int *data_size)
2947 unsigned int i;
2948 unsigned int ofs = 0;
2950 if (max_data_bytes < 32) {
2951 return NT_STATUS_INFO_LENGTH_MISMATCH;
2954 for (i = 0; i < num_streams; i++) {
2955 unsigned int next_offset;
2956 size_t namelen;
2957 smb_ucs2_t *namebuf;
2959 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
2960 streams[i].name, &namelen) ||
2961 namelen <= 2)
2963 return NT_STATUS_INVALID_PARAMETER;
2967 * name_buf is now null-terminated, we need to marshall as not
2968 * terminated
2971 namelen -= 2;
2974 * We cannot overflow ...
2976 if ((ofs + 24 + namelen) > max_data_bytes) {
2977 DEBUG(10, ("refusing to overflow reply at stream %u\n",
2978 i));
2979 TALLOC_FREE(namebuf);
2980 return STATUS_BUFFER_OVERFLOW;
2983 SIVAL(data, ofs+4, namelen);
2984 SOFF_T(data, ofs+8, streams[i].size);
2985 SOFF_T(data, ofs+16, streams[i].alloc_size);
2986 memcpy(data+ofs+24, namebuf, namelen);
2987 TALLOC_FREE(namebuf);
2989 next_offset = ofs + 24 + namelen;
2991 if (i == num_streams-1) {
2992 SIVAL(data, ofs, 0);
2994 else {
2995 unsigned int align = ndr_align_size(next_offset, 8);
2997 if ((next_offset + align) > max_data_bytes) {
2998 DEBUG(10, ("refusing to overflow align "
2999 "reply at stream %u\n",
3000 i));
3001 TALLOC_FREE(namebuf);
3002 return STATUS_BUFFER_OVERFLOW;
3005 memset(data+next_offset, 0, align);
3006 next_offset += align;
3008 SIVAL(data, ofs, next_offset - ofs);
3009 ofs = next_offset;
3012 ofs = next_offset;
3015 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
3017 *data_size = ofs;
3019 return NT_STATUS_OK;
3022 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3023 TALLOC_CTX *mem_ctx,
3024 struct smb_request *req,
3025 uint16_t info_level,
3026 files_struct *fsp,
3027 struct smb_filename *smb_fname,
3028 bool delete_pending,
3029 struct timespec write_time_ts,
3030 struct ea_list *ea_list,
3031 uint16_t flags2,
3032 unsigned int max_data_bytes,
3033 size_t *fixed_portion,
3034 char **ppdata,
3035 unsigned int *pdata_size)
3037 char *pdata = *ppdata;
3038 char *dstart, *dend;
3039 unsigned int data_size;
3040 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3041 time_t create_time, mtime, atime, c_time;
3042 SMB_STRUCT_STAT *psbuf = NULL;
3043 SMB_STRUCT_STAT *base_sp = NULL;
3044 char *p;
3045 char *base_name;
3046 char *dos_fname;
3047 int mode;
3048 int nlink;
3049 NTSTATUS status;
3050 uint64_t file_size = 0;
3051 uint64_t pos = 0;
3052 uint64_t allocation_size = 0;
3053 uint64_t file_id = 0;
3054 uint32_t access_mask = 0;
3055 size_t len = 0;
3057 if (INFO_LEVEL_IS_UNIX(info_level)) {
3058 bool ok = false;
3060 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3061 DBG_DEBUG("SMB1 unix extensions activated\n");
3062 ok = true;
3065 if (lp_smb3_unix_extensions() &&
3066 (fsp != NULL) &&
3067 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3068 DBG_DEBUG("SMB2 posix open\n");
3069 ok = true;
3072 if (!ok) {
3073 return NT_STATUS_INVALID_LEVEL;
3077 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3078 smb_fname_str_dbg(smb_fname),
3079 fsp_fnum_dbg(fsp),
3080 info_level, max_data_bytes));
3083 * In case of querying a symlink in POSIX context,
3084 * fsp will be NULL. fdos_mode() deals with it.
3086 if (fsp != NULL) {
3087 smb_fname = fsp->fsp_name;
3089 mode = fdos_mode(fsp);
3090 psbuf = &smb_fname->st;
3092 if (fsp != NULL) {
3093 base_sp = fsp->base_fsp ?
3094 &fsp->base_fsp->fsp_name->st :
3095 &fsp->fsp_name->st;
3096 } else {
3097 base_sp = &smb_fname->st;
3100 nlink = psbuf->st_ex_nlink;
3102 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3103 nlink = 1;
3106 if ((nlink > 0) && delete_pending) {
3107 nlink -= 1;
3110 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3111 return NT_STATUS_INVALID_PARAMETER;
3114 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3115 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3116 if (*ppdata == NULL) {
3117 return NT_STATUS_NO_MEMORY;
3119 pdata = *ppdata;
3120 dstart = pdata;
3121 dend = dstart + data_size - 1;
3123 if (!is_omit_timespec(&write_time_ts) &&
3124 !INFO_LEVEL_IS_UNIX(info_level))
3126 update_stat_ex_mtime(psbuf, write_time_ts);
3129 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3130 mtime_ts = psbuf->st_ex_mtime;
3131 atime_ts = psbuf->st_ex_atime;
3132 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3134 if (lp_dos_filetime_resolution(SNUM(conn))) {
3135 dos_filetime_timespec(&create_time_ts);
3136 dos_filetime_timespec(&mtime_ts);
3137 dos_filetime_timespec(&atime_ts);
3138 dos_filetime_timespec(&ctime_ts);
3141 create_time = convert_timespec_to_time_t(create_time_ts);
3142 mtime = convert_timespec_to_time_t(mtime_ts);
3143 atime = convert_timespec_to_time_t(atime_ts);
3144 c_time = convert_timespec_to_time_t(ctime_ts);
3146 p = strrchr_m(smb_fname->base_name,'/');
3147 if (!p)
3148 base_name = smb_fname->base_name;
3149 else
3150 base_name = p+1;
3152 /* NT expects the name to be in an exact form of the *full*
3153 filename. See the trans2 torture test */
3154 if (ISDOT(base_name)) {
3155 dos_fname = talloc_strdup(mem_ctx, "\\");
3156 if (!dos_fname) {
3157 return NT_STATUS_NO_MEMORY;
3159 } else {
3160 dos_fname = talloc_asprintf(mem_ctx,
3161 "\\%s",
3162 smb_fname->base_name);
3163 if (!dos_fname) {
3164 return NT_STATUS_NO_MEMORY;
3166 if (is_named_stream(smb_fname)) {
3167 dos_fname = talloc_asprintf(dos_fname, "%s",
3168 smb_fname->stream_name);
3169 if (!dos_fname) {
3170 return NT_STATUS_NO_MEMORY;
3174 string_replace(dos_fname, '/', '\\');
3177 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3179 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3180 /* Do we have this path open ? */
3181 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3182 files_struct *fsp1 = file_find_di_first(
3183 conn->sconn, fileid, true);
3184 if (fsp1 && fsp1->initial_allocation_size) {
3185 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3189 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3190 file_size = get_file_size_stat(psbuf);
3193 if (fsp) {
3194 pos = fh_get_position_information(fsp->fh);
3197 if (fsp) {
3198 access_mask = fsp->access_mask;
3199 } else {
3200 /* GENERIC_EXECUTE mapping from Windows */
3201 access_mask = 0x12019F;
3204 /* This should be an index number - looks like
3205 dev/ino to me :-)
3207 I think this causes us to fail the IFSKIT
3208 BasicFileInformationTest. -tpot */
3209 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3211 *fixed_portion = 0;
3213 switch (info_level) {
3214 case SMB_INFO_STANDARD:
3215 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3216 data_size = 22;
3217 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3218 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3219 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3220 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3221 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3222 SSVAL(pdata,l1_attrFile,mode);
3223 break;
3225 case SMB_INFO_QUERY_EA_SIZE:
3227 unsigned int ea_size =
3228 estimate_ea_size(smb_fname->fsp);
3229 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3230 data_size = 26;
3231 srv_put_dos_date2(pdata,0,create_time);
3232 srv_put_dos_date2(pdata,4,atime);
3233 srv_put_dos_date2(pdata,8,mtime); /* write time */
3234 SIVAL(pdata,12,(uint32_t)file_size);
3235 SIVAL(pdata,16,(uint32_t)allocation_size);
3236 SSVAL(pdata,20,mode);
3237 SIVAL(pdata,22,ea_size);
3238 break;
3241 case SMB_INFO_IS_NAME_VALID:
3242 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3243 if (fsp) {
3244 /* os/2 needs this ? really ?*/
3245 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3247 /* This is only reached for qpathinfo */
3248 data_size = 0;
3249 break;
3251 case SMB_INFO_QUERY_EAS_FROM_LIST:
3253 size_t total_ea_len = 0;
3254 struct ea_list *ea_file_list = NULL;
3255 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3257 status =
3258 get_ea_list_from_fsp(mem_ctx,
3259 smb_fname->fsp,
3260 &total_ea_len, &ea_file_list);
3261 if (!NT_STATUS_IS_OK(status)) {
3262 return status;
3265 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3267 if (!ea_list || (total_ea_len > data_size)) {
3268 data_size = 4;
3269 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3270 break;
3273 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3274 break;
3277 case SMB_INFO_QUERY_ALL_EAS:
3279 /* We have data_size bytes to put EA's into. */
3280 size_t total_ea_len = 0;
3281 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3283 status = get_ea_list_from_fsp(mem_ctx,
3284 smb_fname->fsp,
3285 &total_ea_len, &ea_list);
3286 if (!NT_STATUS_IS_OK(status)) {
3287 return status;
3290 if (!ea_list || (total_ea_len > data_size)) {
3291 data_size = 4;
3292 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3293 break;
3296 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3297 break;
3300 case SMB2_FILE_FULL_EA_INFORMATION:
3302 /* We have data_size bytes to put EA's into. */
3303 size_t total_ea_len = 0;
3304 struct ea_list *ea_file_list = NULL;
3306 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3308 /*TODO: add filtering and index handling */
3310 status =
3311 get_ea_list_from_fsp(mem_ctx,
3312 smb_fname->fsp,
3313 &total_ea_len, &ea_file_list);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 return status;
3317 if (!ea_file_list) {
3318 return NT_STATUS_NO_EAS_ON_FILE;
3321 status = fill_ea_chained_buffer(mem_ctx,
3322 pdata,
3323 data_size,
3324 &data_size,
3325 conn, ea_file_list);
3326 if (!NT_STATUS_IS_OK(status)) {
3327 return status;
3329 break;
3332 case SMB_FILE_BASIC_INFORMATION:
3333 case SMB_QUERY_FILE_BASIC_INFO:
3335 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3336 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3337 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3338 } else {
3339 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3340 data_size = 40;
3341 SIVAL(pdata,36,0);
3343 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3344 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3345 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3346 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3347 SIVAL(pdata,32,mode);
3349 DEBUG(5,("SMB_QFBI - "));
3350 DEBUG(5,("create: %s ", ctime(&create_time)));
3351 DEBUG(5,("access: %s ", ctime(&atime)));
3352 DEBUG(5,("write: %s ", ctime(&mtime)));
3353 DEBUG(5,("change: %s ", ctime(&c_time)));
3354 DEBUG(5,("mode: %x\n", mode));
3355 *fixed_portion = data_size;
3356 break;
3358 case SMB_FILE_STANDARD_INFORMATION:
3359 case SMB_QUERY_FILE_STANDARD_INFO:
3361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3362 data_size = 24;
3363 SOFF_T(pdata,0,allocation_size);
3364 SOFF_T(pdata,8,file_size);
3365 SIVAL(pdata,16,nlink);
3366 SCVAL(pdata,20,delete_pending?1:0);
3367 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3368 SSVAL(pdata,22,0); /* Padding. */
3369 *fixed_portion = 24;
3370 break;
3372 case SMB_FILE_EA_INFORMATION:
3373 case SMB_QUERY_FILE_EA_INFO:
3375 unsigned int ea_size =
3376 estimate_ea_size(smb_fname->fsp);
3377 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3378 data_size = 4;
3379 *fixed_portion = 4;
3380 SIVAL(pdata,0,ea_size);
3381 break;
3384 /* Get the 8.3 name - used if NT SMB was negotiated. */
3385 case SMB_QUERY_FILE_ALT_NAME_INFO:
3386 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3388 char mangled_name[13];
3389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3390 if (!name_to_8_3(base_name,mangled_name,
3391 True,conn->params)) {
3392 return NT_STATUS_NO_MEMORY;
3394 status = srvstr_push(dstart, flags2,
3395 pdata+4, mangled_name,
3396 PTR_DIFF(dend, pdata+4),
3397 STR_UNICODE, &len);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 return status;
3401 data_size = 4 + len;
3402 SIVAL(pdata,0,len);
3403 *fixed_portion = 8;
3404 break;
3407 case SMB_QUERY_FILE_NAME_INFO:
3410 this must be *exactly* right for ACLs on mapped drives to work
3412 status = srvstr_push(dstart, flags2,
3413 pdata+4, dos_fname,
3414 PTR_DIFF(dend, pdata+4),
3415 STR_UNICODE, &len);
3416 if (!NT_STATUS_IS_OK(status)) {
3417 return status;
3419 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3420 data_size = 4 + len;
3421 SIVAL(pdata,0,len);
3422 break;
3425 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3427 char *nfname = NULL;
3429 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3430 return NT_STATUS_INVALID_LEVEL;
3433 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3434 if (nfname == NULL) {
3435 return NT_STATUS_NO_MEMORY;
3438 if (ISDOT(nfname)) {
3439 nfname[0] = '\0';
3441 string_replace(nfname, '/', '\\');
3443 if (fsp_is_alternate_stream(fsp)) {
3444 const char *s = smb_fname->stream_name;
3445 const char *e = NULL;
3446 size_t n;
3448 SMB_ASSERT(s[0] != '\0');
3451 * smb_fname->stream_name is in form
3452 * of ':StrEam:$DATA', but we should only
3453 * append ':StrEam' here.
3456 e = strchr(&s[1], ':');
3457 if (e == NULL) {
3458 n = strlen(s);
3459 } else {
3460 n = PTR_DIFF(e, s);
3462 nfname = talloc_strndup_append(nfname, s, n);
3463 if (nfname == NULL) {
3464 return NT_STATUS_NO_MEMORY;
3468 status = srvstr_push(dstart, flags2,
3469 pdata+4, nfname,
3470 PTR_DIFF(dend, pdata+4),
3471 STR_UNICODE, &len);
3472 if (!NT_STATUS_IS_OK(status)) {
3473 return status;
3475 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3476 data_size = 4 + len;
3477 SIVAL(pdata,0,len);
3478 *fixed_portion = 8;
3479 break;
3482 case SMB_FILE_ALLOCATION_INFORMATION:
3483 case SMB_QUERY_FILE_ALLOCATION_INFO:
3484 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3485 data_size = 8;
3486 SOFF_T(pdata,0,allocation_size);
3487 break;
3489 case SMB_FILE_END_OF_FILE_INFORMATION:
3490 case SMB_QUERY_FILE_END_OF_FILEINFO:
3491 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3492 data_size = 8;
3493 SOFF_T(pdata,0,file_size);
3494 break;
3496 case SMB_QUERY_FILE_ALL_INFO:
3497 case SMB_FILE_ALL_INFORMATION:
3499 unsigned int ea_size =
3500 estimate_ea_size(smb_fname->fsp);
3501 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
3502 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3503 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3504 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3505 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3506 SIVAL(pdata,32,mode);
3507 SIVAL(pdata,36,0); /* padding. */
3508 pdata += 40;
3509 SOFF_T(pdata,0,allocation_size);
3510 SOFF_T(pdata,8,file_size);
3511 SIVAL(pdata,16,nlink);
3512 SCVAL(pdata,20,delete_pending);
3513 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3514 SSVAL(pdata,22,0);
3515 pdata += 24;
3516 SIVAL(pdata,0,ea_size);
3517 pdata += 4; /* EA info */
3518 status = srvstr_push(dstart, flags2,
3519 pdata+4, dos_fname,
3520 PTR_DIFF(dend, pdata+4),
3521 STR_UNICODE, &len);
3522 if (!NT_STATUS_IS_OK(status)) {
3523 return status;
3525 SIVAL(pdata,0,len);
3526 pdata += 4 + len;
3527 data_size = PTR_DIFF(pdata,(*ppdata));
3528 *fixed_portion = 10;
3529 break;
3532 case SMB2_FILE_ALL_INFORMATION:
3534 unsigned int ea_size =
3535 estimate_ea_size(smb_fname->fsp);
3536 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
3537 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
3538 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
3539 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
3540 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
3541 SIVAL(pdata, 0x20, mode);
3542 SIVAL(pdata, 0x24, 0); /* padding. */
3543 SBVAL(pdata, 0x28, allocation_size);
3544 SBVAL(pdata, 0x30, file_size);
3545 SIVAL(pdata, 0x38, nlink);
3546 SCVAL(pdata, 0x3C, delete_pending);
3547 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3548 SSVAL(pdata, 0x3E, 0); /* padding */
3549 SBVAL(pdata, 0x40, file_id);
3550 SIVAL(pdata, 0x48, ea_size);
3551 SIVAL(pdata, 0x4C, access_mask);
3552 SBVAL(pdata, 0x50, pos);
3553 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
3554 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
3556 pdata += 0x60;
3558 status = srvstr_push(dstart, flags2,
3559 pdata+4, dos_fname,
3560 PTR_DIFF(dend, pdata+4),
3561 STR_UNICODE, &len);
3562 if (!NT_STATUS_IS_OK(status)) {
3563 return status;
3565 SIVAL(pdata,0,len);
3566 pdata += 4 + len;
3567 data_size = PTR_DIFF(pdata,(*ppdata));
3568 *fixed_portion = 104;
3569 break;
3571 case SMB_FILE_INTERNAL_INFORMATION:
3573 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
3574 SBVAL(pdata, 0, file_id);
3575 data_size = 8;
3576 *fixed_portion = 8;
3577 break;
3579 case SMB_FILE_ACCESS_INFORMATION:
3580 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
3581 SIVAL(pdata, 0, access_mask);
3582 data_size = 4;
3583 *fixed_portion = 4;
3584 break;
3586 case SMB_FILE_NAME_INFORMATION:
3587 /* Pathname with leading '\'. */
3589 size_t byte_len;
3590 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
3591 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
3592 SIVAL(pdata,0,byte_len);
3593 data_size = 4 + byte_len;
3594 break;
3597 case SMB_FILE_DISPOSITION_INFORMATION:
3598 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
3599 data_size = 1;
3600 SCVAL(pdata,0,delete_pending);
3601 *fixed_portion = 1;
3602 break;
3604 case SMB_FILE_POSITION_INFORMATION:
3605 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
3606 data_size = 8;
3607 SOFF_T(pdata,0,pos);
3608 *fixed_portion = 8;
3609 break;
3611 case SMB_FILE_MODE_INFORMATION:
3612 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
3613 SIVAL(pdata,0,mode);
3614 data_size = 4;
3615 *fixed_portion = 4;
3616 break;
3618 case SMB_FILE_ALIGNMENT_INFORMATION:
3619 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
3620 SIVAL(pdata,0,0); /* No alignment needed. */
3621 data_size = 4;
3622 *fixed_portion = 4;
3623 break;
3626 * NT4 server just returns "invalid query" to this - if we try
3627 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
3628 * want this. JRA.
3630 /* The first statement above is false - verified using Thursby
3631 * client against NT4 -- gcolley.
3633 case SMB_QUERY_FILE_STREAM_INFO:
3634 case SMB_FILE_STREAM_INFORMATION: {
3635 unsigned int num_streams = 0;
3636 struct stream_struct *streams = NULL;
3638 DEBUG(10,("smbd_do_qfilepathinfo: "
3639 "SMB_FILE_STREAM_INFORMATION\n"));
3641 if (is_ntfs_stream_smb_fname(smb_fname)) {
3642 return NT_STATUS_INVALID_PARAMETER;
3645 status = vfs_fstreaminfo(fsp,
3646 mem_ctx,
3647 &num_streams,
3648 &streams);
3650 if (!NT_STATUS_IS_OK(status)) {
3651 DEBUG(10, ("could not get stream info: %s\n",
3652 nt_errstr(status)));
3653 return status;
3656 status = marshall_stream_info(num_streams, streams,
3657 pdata, max_data_bytes,
3658 &data_size);
3660 if (!NT_STATUS_IS_OK(status)) {
3661 DEBUG(10, ("marshall_stream_info failed: %s\n",
3662 nt_errstr(status)));
3663 TALLOC_FREE(streams);
3664 return status;
3667 TALLOC_FREE(streams);
3669 *fixed_portion = 32;
3671 break;
3673 case SMB_QUERY_COMPRESSION_INFO:
3674 case SMB_FILE_COMPRESSION_INFORMATION:
3675 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
3676 SOFF_T(pdata,0,file_size);
3677 SIVAL(pdata,8,0); /* ??? */
3678 SIVAL(pdata,12,0); /* ??? */
3679 data_size = 16;
3680 *fixed_portion = 16;
3681 break;
3683 case SMB_FILE_NETWORK_OPEN_INFORMATION:
3684 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
3685 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3686 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3687 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3688 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3689 SOFF_T(pdata,32,allocation_size);
3690 SOFF_T(pdata,40,file_size);
3691 SIVAL(pdata,48,mode);
3692 SIVAL(pdata,52,0); /* ??? */
3693 data_size = 56;
3694 *fixed_portion = 56;
3695 break;
3697 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
3698 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
3699 SIVAL(pdata,0,mode);
3700 SIVAL(pdata,4,0);
3701 data_size = 8;
3702 *fixed_portion = 8;
3703 break;
3706 * SMB2 UNIX Extensions.
3708 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
3710 uint8_t *buf = NULL;
3711 ssize_t plen = 0;
3713 if (!(conn->sconn->using_smb2)) {
3714 return NT_STATUS_INVALID_LEVEL;
3716 if (!lp_smb3_unix_extensions()) {
3717 return NT_STATUS_INVALID_LEVEL;
3719 if (fsp == NULL) {
3720 return NT_STATUS_INVALID_HANDLE;
3722 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3723 return NT_STATUS_INVALID_LEVEL;
3726 /* Determine the size of the posix info context */
3727 plen = store_smb2_posix_info(conn,
3728 &smb_fname->st,
3730 mode,
3731 NULL,
3733 if (plen == -1 || data_size < plen) {
3734 return NT_STATUS_INVALID_PARAMETER;
3736 buf = talloc_zero_size(mem_ctx, plen);
3737 if (buf == NULL) {
3738 return NT_STATUS_NO_MEMORY;
3741 /* Store the context in buf */
3742 store_smb2_posix_info(conn,
3743 &smb_fname->st,
3745 mode,
3746 buf,
3747 plen);
3748 memcpy(pdata, buf, plen);
3749 data_size = plen;
3750 break;
3753 default:
3754 return NT_STATUS_INVALID_LEVEL;
3757 *pdata_size = data_size;
3758 return NT_STATUS_OK;
3761 /****************************************************************************
3762 Set a hard link (called by UNIX extensions and by NT rename with HARD link
3763 code.
3764 ****************************************************************************/
3766 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
3767 connection_struct *conn,
3768 struct smb_request *req,
3769 bool overwrite_if_exists,
3770 struct files_struct *old_dirfsp,
3771 const struct smb_filename *smb_fname_old,
3772 struct files_struct *new_dirfsp,
3773 struct smb_filename *smb_fname_new)
3775 NTSTATUS status = NT_STATUS_OK;
3776 int ret;
3777 bool ok;
3778 struct smb_filename *parent_fname_old = NULL;
3779 struct smb_filename *base_name_old = NULL;
3780 struct smb_filename *parent_fname_new = NULL;
3781 struct smb_filename *base_name_new = NULL;
3783 /* source must already exist. */
3784 if (!VALID_STAT(smb_fname_old->st)) {
3785 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
3786 goto out;
3789 /* No links from a directory. */
3790 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
3791 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3792 goto out;
3795 /* Setting a hardlink to/from a stream isn't currently supported. */
3796 ok = is_ntfs_stream_smb_fname(smb_fname_old);
3797 if (ok) {
3798 DBG_DEBUG("Old name has streams\n");
3799 status = NT_STATUS_INVALID_PARAMETER;
3800 goto out;
3802 ok = is_ntfs_stream_smb_fname(smb_fname_new);
3803 if (ok) {
3804 DBG_DEBUG("New name has streams\n");
3805 status = NT_STATUS_INVALID_PARAMETER;
3806 goto out;
3809 if (smb_fname_old->twrp != 0) {
3810 status = NT_STATUS_NOT_SAME_DEVICE;
3811 goto out;
3814 status = parent_pathref(talloc_tos(),
3815 conn->cwd_fsp,
3816 smb_fname_old,
3817 &parent_fname_old,
3818 &base_name_old);
3819 if (!NT_STATUS_IS_OK(status)) {
3820 goto out;
3823 status = parent_pathref(talloc_tos(),
3824 conn->cwd_fsp,
3825 smb_fname_new,
3826 &parent_fname_new,
3827 &base_name_new);
3828 if (!NT_STATUS_IS_OK(status)) {
3829 goto out;
3832 if (VALID_STAT(smb_fname_new->st)) {
3833 if (overwrite_if_exists) {
3834 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
3835 status = NT_STATUS_FILE_IS_A_DIRECTORY;
3836 goto out;
3838 status = unlink_internals(conn,
3839 req,
3840 FILE_ATTRIBUTE_NORMAL,
3841 NULL, /* new_dirfsp */
3842 smb_fname_new);
3843 if (!NT_STATUS_IS_OK(status)) {
3844 goto out;
3846 } else {
3847 /* Disallow if newname already exists. */
3848 status = NT_STATUS_OBJECT_NAME_COLLISION;
3849 goto out;
3853 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
3854 smb_fname_old->base_name, smb_fname_new->base_name));
3856 ret = SMB_VFS_LINKAT(conn,
3857 parent_fname_old->fsp,
3858 base_name_old,
3859 parent_fname_new->fsp,
3860 base_name_new,
3863 if (ret != 0) {
3864 status = map_nt_error_from_unix(errno);
3865 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
3866 nt_errstr(status), smb_fname_old->base_name,
3867 smb_fname_new->base_name));
3870 out:
3872 TALLOC_FREE(parent_fname_old);
3873 TALLOC_FREE(parent_fname_new);
3874 return status;
3877 /****************************************************************************
3878 Deal with setting the time from any of the setfilepathinfo functions.
3879 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
3880 calling this function.
3881 ****************************************************************************/
3883 NTSTATUS smb_set_file_time(connection_struct *conn,
3884 files_struct *fsp,
3885 struct smb_filename *smb_fname,
3886 struct smb_file_time *ft,
3887 bool setting_write_time)
3889 struct files_struct *set_fsp = NULL;
3890 struct timeval_buf tbuf[4];
3891 uint32_t action =
3892 FILE_NOTIFY_CHANGE_LAST_ACCESS
3893 |FILE_NOTIFY_CHANGE_LAST_WRITE
3894 |FILE_NOTIFY_CHANGE_CREATION;
3895 int ret;
3897 if (!VALID_STAT(smb_fname->st)) {
3898 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3901 if (fsp == NULL) {
3902 /* A symlink */
3903 return NT_STATUS_OK;
3906 set_fsp = metadata_fsp(fsp);
3908 /* get some defaults (no modifications) if any info is zero or -1. */
3909 if (is_omit_timespec(&ft->create_time)) {
3910 action &= ~FILE_NOTIFY_CHANGE_CREATION;
3913 if (is_omit_timespec(&ft->atime)) {
3914 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
3917 if (is_omit_timespec(&ft->mtime)) {
3918 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3921 if (!setting_write_time) {
3922 /* ft->mtime comes from change time, not write time. */
3923 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
3926 /* Ensure the resolution is the correct for
3927 * what we can store on this filesystem. */
3929 round_timespec(conn->ts_res, &ft->create_time);
3930 round_timespec(conn->ts_res, &ft->ctime);
3931 round_timespec(conn->ts_res, &ft->atime);
3932 round_timespec(conn->ts_res, &ft->mtime);
3934 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
3935 timespec_string_buf(&ft->atime, true, &tbuf[0]));
3936 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
3937 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
3938 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
3939 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
3940 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
3941 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
3943 if (setting_write_time) {
3945 * This was a Windows setfileinfo on an open file.
3946 * NT does this a lot. We also need to
3947 * set the time here, as it can be read by
3948 * FindFirst/FindNext and with the patch for bug #2045
3949 * in smbd/fileio.c it ensures that this timestamp is
3950 * kept sticky even after a write. We save the request
3951 * away and will set it on file close and after a write. JRA.
3954 DBG_DEBUG("setting pending modtime to %s\n",
3955 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
3957 if (set_fsp != NULL) {
3958 set_sticky_write_time_fsp(set_fsp, ft->mtime);
3959 } else {
3960 set_sticky_write_time_path(
3961 vfs_file_id_from_sbuf(conn, &smb_fname->st),
3962 ft->mtime);
3966 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
3968 ret = file_ntimes(conn, set_fsp, ft);
3969 if (ret != 0) {
3970 return map_nt_error_from_unix(errno);
3973 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
3974 smb_fname->base_name);
3975 return NT_STATUS_OK;
3978 /****************************************************************************
3979 Deal with setting the dosmode from any of the setfilepathinfo functions.
3980 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
3981 done before calling this function.
3982 ****************************************************************************/
3984 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
3985 struct files_struct *fsp,
3986 uint32_t dosmode)
3988 struct files_struct *dos_fsp = NULL;
3989 uint32_t current_dosmode;
3990 int ret;
3992 if (!VALID_STAT(fsp->fsp_name->st)) {
3993 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3996 dos_fsp = metadata_fsp(fsp);
3998 if (dosmode != 0) {
3999 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4000 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4001 } else {
4002 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4006 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4008 /* check the mode isn't different, before changing it */
4009 if (dosmode == 0) {
4010 return NT_STATUS_OK;
4012 current_dosmode = fdos_mode(dos_fsp);
4013 if (dosmode == current_dosmode) {
4014 return NT_STATUS_OK;
4017 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4018 fsp_str_dbg(dos_fsp), dosmode);
4020 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4021 if (ret != 0) {
4022 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4023 fsp_str_dbg(dos_fsp), strerror(errno));
4024 return map_nt_error_from_unix(errno);
4027 return NT_STATUS_OK;
4030 /****************************************************************************
4031 Deal with setting the size from any of the setfilepathinfo functions.
4032 ****************************************************************************/
4034 NTSTATUS smb_set_file_size(connection_struct *conn,
4035 struct smb_request *req,
4036 files_struct *fsp,
4037 struct smb_filename *smb_fname,
4038 const SMB_STRUCT_STAT *psbuf,
4039 off_t size,
4040 bool fail_after_createfile)
4042 NTSTATUS status = NT_STATUS_OK;
4043 files_struct *new_fsp = NULL;
4045 if (!VALID_STAT(*psbuf)) {
4046 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4049 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4050 (uint64_t)size,
4051 get_file_size_stat(psbuf));
4053 if (size == get_file_size_stat(psbuf)) {
4054 if (fsp == NULL) {
4055 return NT_STATUS_OK;
4057 if (!fsp->fsp_flags.modified) {
4058 return NT_STATUS_OK;
4060 trigger_write_time_update_immediate(fsp);
4061 return NT_STATUS_OK;
4064 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4065 smb_fname_str_dbg(smb_fname), (double)size));
4067 if (fsp &&
4068 !fsp->fsp_flags.is_pathref &&
4069 fsp_get_io_fd(fsp) != -1)
4071 /* Handle based call. */
4072 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4073 if (!NT_STATUS_IS_OK(status)) {
4074 return status;
4077 if (vfs_set_filelen(fsp, size) == -1) {
4078 return map_nt_error_from_unix(errno);
4080 trigger_write_time_update_immediate(fsp);
4081 return NT_STATUS_OK;
4084 status = SMB_VFS_CREATE_FILE(
4085 conn, /* conn */
4086 req, /* req */
4087 NULL, /* dirfsp */
4088 smb_fname, /* fname */
4089 FILE_WRITE_DATA, /* access_mask */
4090 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4091 FILE_SHARE_DELETE),
4092 FILE_OPEN, /* create_disposition*/
4093 0, /* create_options */
4094 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4095 0, /* oplock_request */
4096 NULL, /* lease */
4097 0, /* allocation_size */
4098 0, /* private_flags */
4099 NULL, /* sd */
4100 NULL, /* ea_list */
4101 &new_fsp, /* result */
4102 NULL, /* pinfo */
4103 NULL, NULL); /* create context */
4105 if (!NT_STATUS_IS_OK(status)) {
4106 /* NB. We check for open_was_deferred in the caller. */
4107 return status;
4110 /* See RAW-SFILEINFO-END-OF-FILE */
4111 if (fail_after_createfile) {
4112 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4113 return NT_STATUS_INVALID_LEVEL;
4116 if (vfs_set_filelen(new_fsp, size) == -1) {
4117 status = map_nt_error_from_unix(errno);
4118 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4119 return status;
4122 trigger_write_time_update_immediate(new_fsp);
4123 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4124 return NT_STATUS_OK;
4127 /****************************************************************************
4128 Deal with SMB_INFO_SET_EA.
4129 ****************************************************************************/
4131 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4132 const char *pdata,
4133 int total_data,
4134 files_struct *fsp,
4135 struct smb_filename *smb_fname)
4137 struct ea_list *ea_list = NULL;
4138 TALLOC_CTX *ctx = NULL;
4139 NTSTATUS status = NT_STATUS_OK;
4141 if (total_data < 10) {
4143 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4144 length. They seem to have no effect. Bug #3212. JRA */
4146 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4147 /* We're done. We only get EA info in this call. */
4148 return NT_STATUS_OK;
4151 return NT_STATUS_INVALID_PARAMETER;
4154 if (IVAL(pdata,0) > total_data) {
4155 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4156 IVAL(pdata,0), (unsigned int)total_data));
4157 return NT_STATUS_INVALID_PARAMETER;
4160 ctx = talloc_tos();
4161 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4162 if (!ea_list) {
4163 return NT_STATUS_INVALID_PARAMETER;
4166 if (fsp == NULL) {
4168 * The only way fsp can be NULL here is if
4169 * smb_fname points at a symlink and
4170 * and we're in POSIX context.
4171 * Ensure this is the case.
4173 * In this case we cannot set the EA.
4175 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4176 return NT_STATUS_ACCESS_DENIED;
4179 status = set_ea(conn, fsp, ea_list);
4181 return status;
4184 /****************************************************************************
4185 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4186 ****************************************************************************/
4188 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4189 const char *pdata,
4190 int total_data,
4191 files_struct *fsp)
4193 struct ea_list *ea_list = NULL;
4194 NTSTATUS status;
4196 if (fsp == NULL) {
4197 return NT_STATUS_INVALID_HANDLE;
4200 if (!lp_ea_support(SNUM(conn))) {
4201 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4202 "EA's not supported.\n",
4203 (unsigned int)total_data));
4204 return NT_STATUS_EAS_NOT_SUPPORTED;
4207 if (total_data < 10) {
4208 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4209 "too small.\n",
4210 (unsigned int)total_data));
4211 return NT_STATUS_INVALID_PARAMETER;
4214 ea_list = read_nttrans_ea_list(talloc_tos(),
4215 pdata,
4216 total_data);
4218 if (!ea_list) {
4219 return NT_STATUS_INVALID_PARAMETER;
4222 status = set_ea(conn, fsp, ea_list);
4224 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4225 smb_fname_str_dbg(fsp->fsp_name),
4226 nt_errstr(status) ));
4228 return status;
4232 /****************************************************************************
4233 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4234 ****************************************************************************/
4236 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4237 const char *pdata,
4238 int total_data,
4239 files_struct *fsp,
4240 struct smb_filename *smb_fname)
4242 NTSTATUS status = NT_STATUS_OK;
4243 bool delete_on_close;
4244 uint32_t dosmode = 0;
4246 if (total_data < 1) {
4247 return NT_STATUS_INVALID_PARAMETER;
4250 if (fsp == NULL) {
4251 return NT_STATUS_INVALID_HANDLE;
4254 delete_on_close = (CVAL(pdata,0) ? True : False);
4255 dosmode = fdos_mode(fsp);
4257 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4258 "delete_on_close = %u\n",
4259 smb_fname_str_dbg(smb_fname),
4260 (unsigned int)dosmode,
4261 (unsigned int)delete_on_close ));
4263 if (delete_on_close) {
4264 status = can_set_delete_on_close(fsp, dosmode);
4265 if (!NT_STATUS_IS_OK(status)) {
4266 return status;
4270 /* The set is across all open files on this dev/inode pair. */
4271 if (!set_delete_on_close(fsp, delete_on_close,
4272 conn->session_info->security_token,
4273 conn->session_info->unix_token)) {
4274 return NT_STATUS_ACCESS_DENIED;
4276 return NT_STATUS_OK;
4279 /****************************************************************************
4280 Deal with SMB_FILE_POSITION_INFORMATION.
4281 ****************************************************************************/
4283 static NTSTATUS smb_file_position_information(connection_struct *conn,
4284 const char *pdata,
4285 int total_data,
4286 files_struct *fsp)
4288 uint64_t position_information;
4290 if (total_data < 8) {
4291 return NT_STATUS_INVALID_PARAMETER;
4294 if (fsp == NULL) {
4295 /* Ignore on pathname based set. */
4296 return NT_STATUS_OK;
4299 position_information = (uint64_t)IVAL(pdata,0);
4300 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4302 DEBUG(10,("smb_file_position_information: Set file position "
4303 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4304 (double)position_information));
4305 fh_set_position_information(fsp->fh, position_information);
4306 return NT_STATUS_OK;
4309 /****************************************************************************
4310 Deal with SMB_FILE_MODE_INFORMATION.
4311 ****************************************************************************/
4313 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4314 const char *pdata,
4315 int total_data)
4317 uint32_t mode;
4319 if (total_data < 4) {
4320 return NT_STATUS_INVALID_PARAMETER;
4322 mode = IVAL(pdata,0);
4323 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4324 return NT_STATUS_INVALID_PARAMETER;
4326 return NT_STATUS_OK;
4329 /****************************************************************************
4330 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4331 ****************************************************************************/
4333 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4334 struct smb_request *req,
4335 const char *pdata,
4336 int total_data,
4337 files_struct *fsp,
4338 struct smb_filename *smb_fname_src)
4340 bool overwrite;
4341 uint32_t len;
4342 char *newname = NULL;
4343 struct files_struct *dst_dirfsp = NULL;
4344 struct smb_filename *smb_fname_dst = NULL;
4345 const char *dst_original_lcomp = NULL;
4346 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4347 NTSTATUS status = NT_STATUS_OK;
4348 TALLOC_CTX *ctx = talloc_tos();
4350 if (!fsp) {
4351 return NT_STATUS_INVALID_HANDLE;
4354 if (total_data < 20) {
4355 return NT_STATUS_INVALID_PARAMETER;
4358 overwrite = (CVAL(pdata,0) ? True : False);
4359 len = IVAL(pdata,16);
4361 if (len > (total_data - 20) || (len == 0)) {
4362 return NT_STATUS_INVALID_PARAMETER;
4365 (void)srvstr_pull_talloc(ctx,
4366 pdata,
4367 req->flags2,
4368 &newname,
4369 &pdata[20],
4370 len,
4371 STR_TERMINATE);
4373 if (newname == NULL) {
4374 return NT_STATUS_INVALID_PARAMETER;
4377 /* SMB2 rename paths are never DFS. */
4378 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4379 ucf_flags &= ~UCF_DFS_PATHNAME;
4381 status = check_path_syntax(newname,
4382 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4383 if (!NT_STATUS_IS_OK(status)) {
4384 return status;
4387 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
4388 newname));
4390 if (newname[0] == ':') {
4391 /* Create an smb_fname to call rename_internals_fsp() with. */
4392 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4393 fsp->base_fsp->fsp_name->base_name,
4394 newname,
4395 NULL,
4396 fsp->base_fsp->fsp_name->twrp,
4397 fsp->base_fsp->fsp_name->flags);
4398 if (smb_fname_dst == NULL) {
4399 status = NT_STATUS_NO_MEMORY;
4400 goto out;
4402 } else {
4403 status = filename_convert_dirfsp(ctx,
4404 conn,
4405 newname,
4406 ucf_flags,
4407 0, /* Never a TWRP. */
4408 &dst_dirfsp,
4409 &smb_fname_dst);
4410 if (!NT_STATUS_IS_OK(status)) {
4411 goto out;
4416 * Set the original last component, since
4417 * rename_internals_fsp() requires it.
4419 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4420 conn,
4421 newname,
4422 ucf_flags);
4423 if (dst_original_lcomp == NULL) {
4424 status = NT_STATUS_NO_MEMORY;
4425 goto out;
4428 DEBUG(10,("smb2_file_rename_information: "
4429 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4430 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4431 smb_fname_str_dbg(smb_fname_dst)));
4432 status = rename_internals_fsp(conn,
4433 fsp,
4434 NULL, /* dst_dirfsp */
4435 smb_fname_dst,
4436 dst_original_lcomp,
4437 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
4438 overwrite);
4440 out:
4441 TALLOC_FREE(smb_fname_dst);
4442 return status;
4445 static NTSTATUS smb2_file_link_information(connection_struct *conn,
4446 struct smb_request *req,
4447 const char *pdata,
4448 int total_data,
4449 files_struct *fsp,
4450 struct smb_filename *smb_fname_src)
4452 bool overwrite;
4453 uint32_t len;
4454 char *newname = NULL;
4455 struct files_struct *dst_dirfsp = NULL;
4456 struct smb_filename *smb_fname_dst = NULL;
4457 NTSTATUS status = NT_STATUS_OK;
4458 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4459 size_t ret;
4460 TALLOC_CTX *ctx = talloc_tos();
4462 if (!fsp) {
4463 return NT_STATUS_INVALID_HANDLE;
4466 if (total_data < 20) {
4467 return NT_STATUS_INVALID_PARAMETER;
4470 overwrite = (CVAL(pdata,0) ? true : false);
4471 len = IVAL(pdata,16);
4473 if (len > (total_data - 20) || (len == 0)) {
4474 return NT_STATUS_INVALID_PARAMETER;
4477 ret = srvstr_pull_talloc(ctx,
4478 pdata,
4479 req->flags2,
4480 &newname,
4481 &pdata[20],
4482 len,
4483 STR_TERMINATE);
4485 if (ret == (size_t)-1 || newname == NULL) {
4486 return NT_STATUS_INVALID_PARAMETER;
4489 /* SMB2 hardlink paths are never DFS. */
4490 req->flags2 &= ~FLAGS2_DFS_PATHNAMES;
4491 ucf_flags &= ~UCF_DFS_PATHNAME;
4493 status = check_path_syntax(newname,
4494 fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
4495 if (!NT_STATUS_IS_OK(status)) {
4496 return status;
4499 DBG_DEBUG("got name |%s|\n", newname);
4501 status = filename_convert_dirfsp(ctx,
4502 conn,
4503 newname,
4504 ucf_flags,
4505 0, /* No TWRP. */
4506 &dst_dirfsp,
4507 &smb_fname_dst);
4508 if (!NT_STATUS_IS_OK(status)) {
4509 return status;
4512 if (fsp->base_fsp) {
4513 /* No stream names. */
4514 return NT_STATUS_NOT_SUPPORTED;
4517 DBG_DEBUG("SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4518 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4519 smb_fname_str_dbg(smb_fname_dst));
4520 status = hardlink_internals(ctx,
4521 conn,
4522 req,
4523 overwrite,
4524 NULL, /* src_dirfsp */
4525 fsp->fsp_name,
4526 dst_dirfsp, /* dst_dirfsp */
4527 smb_fname_dst);
4529 TALLOC_FREE(smb_fname_dst);
4530 return status;
4533 static NTSTATUS smb_file_link_information(connection_struct *conn,
4534 struct smb_request *req,
4535 const char *pdata,
4536 int total_data,
4537 files_struct *fsp,
4538 struct smb_filename *smb_fname_src)
4540 bool overwrite;
4541 uint32_t len;
4542 char *newname = NULL;
4543 struct files_struct *dst_dirfsp = NULL;
4544 struct smb_filename *smb_fname_dst = NULL;
4545 NTSTATUS status = NT_STATUS_OK;
4546 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4547 NTTIME dst_twrp = 0;
4548 TALLOC_CTX *ctx = talloc_tos();
4550 if (!fsp) {
4551 return NT_STATUS_INVALID_HANDLE;
4554 if (total_data < 20) {
4555 return NT_STATUS_INVALID_PARAMETER;
4558 overwrite = (CVAL(pdata,0) ? true : false);
4559 len = IVAL(pdata,16);
4561 if (len > (total_data - 20) || (len == 0)) {
4562 return NT_STATUS_INVALID_PARAMETER;
4565 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
4566 srvstr_get_path_posix(ctx,
4567 pdata,
4568 req->flags2,
4569 &newname,
4570 &pdata[20],
4571 len,
4572 STR_TERMINATE,
4573 &status);
4574 ucf_flags |= UCF_POSIX_PATHNAMES;
4575 } else {
4576 srvstr_get_path(ctx,
4577 pdata,
4578 req->flags2,
4579 &newname,
4580 &pdata[20],
4581 len,
4582 STR_TERMINATE,
4583 &status);
4585 if (!NT_STATUS_IS_OK(status)) {
4586 return status;
4589 DEBUG(10,("smb_file_link_information: got name |%s|\n",
4590 newname));
4592 if (ucf_flags & UCF_GMT_PATHNAME) {
4593 extract_snapshot_token(newname, &dst_twrp);
4595 /* hardlink paths are never DFS. */
4596 ucf_flags &= ~UCF_DFS_PATHNAME;
4598 status = filename_convert_dirfsp(ctx,
4599 conn,
4600 newname,
4601 ucf_flags,
4602 dst_twrp,
4603 &dst_dirfsp,
4604 &smb_fname_dst);
4605 if (!NT_STATUS_IS_OK(status)) {
4606 return status;
4609 if (fsp->base_fsp) {
4610 /* No stream names. */
4611 return NT_STATUS_NOT_SUPPORTED;
4614 DEBUG(10,("smb_file_link_information: "
4615 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
4616 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4617 smb_fname_str_dbg(smb_fname_dst)));
4618 status = hardlink_internals(ctx,
4619 conn,
4620 req,
4621 overwrite,
4622 NULL, /* src_dirfsp */
4623 fsp->fsp_name,
4624 dst_dirfsp, /* dst_dirfsp */
4625 smb_fname_dst);
4627 TALLOC_FREE(smb_fname_dst);
4628 return status;
4632 /****************************************************************************
4633 Deal with SMB_FILE_RENAME_INFORMATION.
4634 ****************************************************************************/
4636 static NTSTATUS smb_file_rename_information(connection_struct *conn,
4637 struct smb_request *req,
4638 const char *pdata,
4639 int total_data,
4640 files_struct *fsp,
4641 struct smb_filename *smb_fname_src)
4643 bool overwrite;
4644 uint32_t root_fid;
4645 uint32_t len;
4646 char *newname = NULL;
4647 struct files_struct *dst_dirfsp = NULL;
4648 struct smb_filename *smb_fname_dst = NULL;
4649 const char *dst_original_lcomp = NULL;
4650 NTSTATUS status = NT_STATUS_OK;
4651 char *p;
4652 TALLOC_CTX *ctx = talloc_tos();
4654 if (total_data < 13) {
4655 return NT_STATUS_INVALID_PARAMETER;
4658 overwrite = (CVAL(pdata,0) != 0);
4659 root_fid = IVAL(pdata,4);
4660 len = IVAL(pdata,8);
4662 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
4663 return NT_STATUS_INVALID_PARAMETER;
4666 if (req->posix_pathnames) {
4667 srvstr_get_path_posix(ctx,
4668 pdata,
4669 req->flags2,
4670 &newname,
4671 &pdata[12],
4672 len,
4674 &status);
4675 } else {
4676 srvstr_get_path(ctx,
4677 pdata,
4678 req->flags2,
4679 &newname,
4680 &pdata[12],
4681 len,
4683 &status);
4685 if (!NT_STATUS_IS_OK(status)) {
4686 return status;
4689 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
4690 newname));
4692 /* Check the new name has no '/' characters. */
4693 if (strchr_m(newname, '/')) {
4694 return NT_STATUS_NOT_SUPPORTED;
4697 if (fsp && fsp->base_fsp) {
4698 /* newname must be a stream name. */
4699 if (newname[0] != ':') {
4700 return NT_STATUS_NOT_SUPPORTED;
4703 /* Create an smb_fname to call rename_internals_fsp() with. */
4704 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
4705 fsp->base_fsp->fsp_name->base_name,
4706 newname,
4707 NULL,
4708 fsp->base_fsp->fsp_name->twrp,
4709 fsp->base_fsp->fsp_name->flags);
4710 if (smb_fname_dst == NULL) {
4711 status = NT_STATUS_NO_MEMORY;
4712 goto out;
4716 * Get the original last component, since
4717 * rename_internals_fsp() requires it.
4719 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4720 conn,
4721 newname,
4723 if (dst_original_lcomp == NULL) {
4724 status = NT_STATUS_NO_MEMORY;
4725 goto out;
4728 } else {
4730 * Build up an smb_fname_dst based on the filename passed in.
4731 * We basically just strip off the last component, and put on
4732 * the newname instead.
4734 char *base_name = NULL;
4735 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4736 NTTIME dst_twrp = 0;
4738 /* newname must *not* be a stream name. */
4739 if (newname[0] == ':') {
4740 return NT_STATUS_NOT_SUPPORTED;
4744 * Strip off the last component (filename) of the path passed
4745 * in.
4747 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
4748 if (!base_name) {
4749 return NT_STATUS_NO_MEMORY;
4751 p = strrchr_m(base_name, '/');
4752 if (p) {
4753 p[1] = '\0';
4754 } else {
4755 base_name = talloc_strdup(ctx, "");
4756 if (!base_name) {
4757 return NT_STATUS_NO_MEMORY;
4760 /* Append the new name. */
4761 base_name = talloc_asprintf_append(base_name,
4762 "%s",
4763 newname);
4764 if (!base_name) {
4765 return NT_STATUS_NO_MEMORY;
4768 if (ucf_flags & UCF_GMT_PATHNAME) {
4769 extract_snapshot_token(base_name, &dst_twrp);
4772 /* The newname is *not* a DFS path. */
4773 ucf_flags &= ~UCF_DFS_PATHNAME;
4775 status = filename_convert_dirfsp(ctx,
4776 conn,
4777 base_name,
4778 ucf_flags,
4779 dst_twrp,
4780 &dst_dirfsp,
4781 &smb_fname_dst);
4783 if (!NT_STATUS_IS_OK(status)) {
4784 goto out;
4786 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
4787 conn,
4788 newname,
4789 ucf_flags);
4790 if (dst_original_lcomp == NULL) {
4791 status = NT_STATUS_NO_MEMORY;
4792 goto out;
4796 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
4797 DEBUG(10,("smb_file_rename_information: "
4798 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
4799 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
4800 smb_fname_str_dbg(smb_fname_dst)));
4801 status = rename_internals_fsp(conn,
4802 fsp,
4803 dst_dirfsp,
4804 smb_fname_dst,
4805 dst_original_lcomp,
4807 overwrite);
4808 } else {
4809 DEBUG(10,("smb_file_rename_information: "
4810 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
4811 smb_fname_str_dbg(smb_fname_src),
4812 smb_fname_str_dbg(smb_fname_dst)));
4813 status = rename_internals(ctx,
4814 conn,
4815 req,
4816 NULL, /* src_dirfsp */
4817 smb_fname_src,
4818 dst_dirfsp,
4819 smb_fname_dst,
4820 dst_original_lcomp,
4822 overwrite,
4823 FILE_WRITE_ATTRIBUTES);
4825 out:
4826 TALLOC_FREE(smb_fname_dst);
4827 return status;
4830 /****************************************************************************
4831 Deal with SMB_SET_FILE_BASIC_INFO.
4832 ****************************************************************************/
4834 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
4835 const char *pdata,
4836 int total_data,
4837 files_struct *fsp,
4838 struct smb_filename *smb_fname)
4840 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
4841 struct smb_file_time ft;
4842 uint32_t dosmode = 0;
4843 NTSTATUS status = NT_STATUS_OK;
4845 init_smb_file_time(&ft);
4847 if (total_data < 36) {
4848 return NT_STATUS_INVALID_PARAMETER;
4851 if (fsp == NULL) {
4852 return NT_STATUS_INVALID_HANDLE;
4855 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4856 if (!NT_STATUS_IS_OK(status)) {
4857 return status;
4860 /* Set the attributes */
4861 dosmode = IVAL(pdata,32);
4862 status = smb_set_file_dosmode(conn, fsp, dosmode);
4863 if (!NT_STATUS_IS_OK(status)) {
4864 return status;
4867 /* create time */
4868 ft.create_time = pull_long_date_full_timespec(pdata);
4870 /* access time */
4871 ft.atime = pull_long_date_full_timespec(pdata+8);
4873 /* write time. */
4874 ft.mtime = pull_long_date_full_timespec(pdata+16);
4876 /* change time. */
4877 ft.ctime = pull_long_date_full_timespec(pdata+24);
4879 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
4880 smb_fname_str_dbg(smb_fname)));
4882 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4883 if (!NT_STATUS_IS_OK(status)) {
4884 return status;
4887 if (fsp->fsp_flags.modified) {
4888 trigger_write_time_update_immediate(fsp);
4890 return NT_STATUS_OK;
4893 /****************************************************************************
4894 Deal with SMB_INFO_STANDARD.
4895 ****************************************************************************/
4897 static NTSTATUS smb_set_info_standard(connection_struct *conn,
4898 const char *pdata,
4899 int total_data,
4900 files_struct *fsp,
4901 struct smb_filename *smb_fname)
4903 NTSTATUS status;
4904 struct smb_file_time ft;
4906 init_smb_file_time(&ft);
4908 if (total_data < 12) {
4909 return NT_STATUS_INVALID_PARAMETER;
4912 if (fsp == NULL) {
4913 return NT_STATUS_INVALID_HANDLE;
4916 /* create time */
4917 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
4918 /* access time */
4919 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
4920 /* write time */
4921 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
4923 DEBUG(10,("smb_set_info_standard: file %s\n",
4924 smb_fname_str_dbg(smb_fname)));
4926 status = check_any_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
4927 if (!NT_STATUS_IS_OK(status)) {
4928 return status;
4931 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
4932 if (!NT_STATUS_IS_OK(status)) {
4933 return status;
4936 if (fsp->fsp_flags.modified) {
4937 trigger_write_time_update_immediate(fsp);
4939 return NT_STATUS_OK;
4942 /****************************************************************************
4943 Deal with SMB_SET_FILE_ALLOCATION_INFO.
4944 ****************************************************************************/
4946 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
4947 struct smb_request *req,
4948 const char *pdata,
4949 int total_data,
4950 files_struct *fsp,
4951 struct smb_filename *smb_fname)
4953 uint64_t allocation_size = 0;
4954 NTSTATUS status = NT_STATUS_OK;
4955 files_struct *new_fsp = NULL;
4957 if (!VALID_STAT(smb_fname->st)) {
4958 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4961 if (total_data < 8) {
4962 return NT_STATUS_INVALID_PARAMETER;
4965 allocation_size = (uint64_t)IVAL(pdata,0);
4966 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
4967 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
4968 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
4969 (double)allocation_size));
4971 if (allocation_size) {
4972 allocation_size = smb_roundup(conn, allocation_size);
4975 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
4976 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
4977 (double)allocation_size));
4979 if (fsp &&
4980 !fsp->fsp_flags.is_pathref &&
4981 fsp_get_io_fd(fsp) != -1)
4983 /* Open file handle. */
4984 status = check_any_access_fsp(fsp, FILE_WRITE_DATA);
4985 if (!NT_STATUS_IS_OK(status)) {
4986 return status;
4989 /* Only change if needed. */
4990 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
4991 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
4992 return map_nt_error_from_unix(errno);
4995 /* But always update the time. */
4997 * This is equivalent to a write. Ensure it's seen immediately
4998 * if there are no pending writes.
5000 trigger_write_time_update_immediate(fsp);
5001 return NT_STATUS_OK;
5004 /* Pathname or stat or directory file. */
5005 status = SMB_VFS_CREATE_FILE(
5006 conn, /* conn */
5007 req, /* req */
5008 NULL, /* dirfsp */
5009 smb_fname, /* fname */
5010 FILE_WRITE_DATA, /* access_mask */
5011 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5012 FILE_SHARE_DELETE),
5013 FILE_OPEN, /* create_disposition*/
5014 0, /* create_options */
5015 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5016 0, /* oplock_request */
5017 NULL, /* lease */
5018 0, /* allocation_size */
5019 0, /* private_flags */
5020 NULL, /* sd */
5021 NULL, /* ea_list */
5022 &new_fsp, /* result */
5023 NULL, /* pinfo */
5024 NULL, NULL); /* create context */
5026 if (!NT_STATUS_IS_OK(status)) {
5027 /* NB. We check for open_was_deferred in the caller. */
5028 return status;
5031 /* Only change if needed. */
5032 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5033 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5034 status = map_nt_error_from_unix(errno);
5035 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5036 return status;
5040 /* Changing the allocation size should set the last mod time. */
5042 * This is equivalent to a write. Ensure it's seen immediately
5043 * if there are no pending writes.
5045 trigger_write_time_update_immediate(new_fsp);
5046 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5047 return NT_STATUS_OK;
5050 /****************************************************************************
5051 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5052 ****************************************************************************/
5054 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5055 struct smb_request *req,
5056 const char *pdata,
5057 int total_data,
5058 files_struct *fsp,
5059 struct smb_filename *smb_fname,
5060 bool fail_after_createfile)
5062 off_t size;
5064 if (total_data < 8) {
5065 return NT_STATUS_INVALID_PARAMETER;
5068 size = IVAL(pdata,0);
5069 size |= (((off_t)IVAL(pdata,4)) << 32);
5070 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5071 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5072 (double)size));
5074 return smb_set_file_size(conn, req,
5075 fsp,
5076 smb_fname,
5077 &smb_fname->st,
5078 size,
5079 fail_after_createfile);
5082 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
5083 struct smb_request *req,
5084 TALLOC_CTX *mem_ctx,
5085 uint16_t info_level,
5086 files_struct *fsp,
5087 struct smb_filename *smb_fname,
5088 char **ppdata, int total_data,
5089 int *ret_data_size)
5091 char *pdata = *ppdata;
5092 NTSTATUS status = NT_STATUS_OK;
5093 int data_return_size = 0;
5095 *ret_data_size = 0;
5097 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
5098 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
5099 fsp_fnum_dbg(fsp),
5100 info_level, total_data));
5102 switch (info_level) {
5104 case SMB_INFO_STANDARD:
5106 status = smb_set_info_standard(conn,
5107 pdata,
5108 total_data,
5109 fsp,
5110 smb_fname);
5111 break;
5114 case SMB_INFO_SET_EA:
5116 status = smb_info_set_ea(conn,
5117 pdata,
5118 total_data,
5119 fsp,
5120 smb_fname);
5121 break;
5124 case SMB_SET_FILE_BASIC_INFO:
5125 case SMB_FILE_BASIC_INFORMATION:
5127 status = smb_set_file_basic_info(conn,
5128 pdata,
5129 total_data,
5130 fsp,
5131 smb_fname);
5132 break;
5135 case SMB_FILE_ALLOCATION_INFORMATION:
5136 case SMB_SET_FILE_ALLOCATION_INFO:
5138 status = smb_set_file_allocation_info(conn, req,
5139 pdata,
5140 total_data,
5141 fsp,
5142 smb_fname);
5143 break;
5146 case SMB_FILE_END_OF_FILE_INFORMATION:
5147 case SMB_SET_FILE_END_OF_FILE_INFO:
5150 * XP/Win7 both fail after the createfile with
5151 * SMB_SET_FILE_END_OF_FILE_INFO but not
5152 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
5153 * The level is known here, so pass it down
5154 * appropriately.
5156 bool should_fail =
5157 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
5159 status = smb_set_file_end_of_file_info(conn, req,
5160 pdata,
5161 total_data,
5162 fsp,
5163 smb_fname,
5164 should_fail);
5165 break;
5168 case SMB_FILE_DISPOSITION_INFORMATION:
5169 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
5171 #if 0
5172 /* JRA - We used to just ignore this on a path ?
5173 * Shouldn't this be invalid level on a pathname
5174 * based call ?
5176 if (tran_call != TRANSACT2_SETFILEINFO) {
5177 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
5179 #endif
5180 status = smb_set_file_disposition_info(conn,
5181 pdata,
5182 total_data,
5183 fsp,
5184 smb_fname);
5185 break;
5188 case SMB_FILE_POSITION_INFORMATION:
5190 status = smb_file_position_information(conn,
5191 pdata,
5192 total_data,
5193 fsp);
5194 break;
5197 case SMB_FILE_FULL_EA_INFORMATION:
5199 status = smb_set_file_full_ea_info(conn,
5200 pdata,
5201 total_data,
5202 fsp);
5203 break;
5206 /* From tridge Samba4 :
5207 * MODE_INFORMATION in setfileinfo (I have no
5208 * idea what "mode information" on a file is - it takes a value of 0,
5209 * 2, 4 or 6. What could it be?).
5212 case SMB_FILE_MODE_INFORMATION:
5214 status = smb_file_mode_information(conn,
5215 pdata,
5216 total_data);
5217 break;
5220 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
5221 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
5222 case SMB_FILE_SHORT_NAME_INFORMATION:
5223 return NT_STATUS_NOT_SUPPORTED;
5225 case SMB_FILE_RENAME_INFORMATION:
5227 status = smb_file_rename_information(conn, req,
5228 pdata, total_data,
5229 fsp, smb_fname);
5230 break;
5233 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
5235 /* SMB2 rename information. */
5236 status = smb2_file_rename_information(conn, req,
5237 pdata, total_data,
5238 fsp, smb_fname);
5239 break;
5242 case SMB_FILE_LINK_INFORMATION:
5244 if (conn->sconn->using_smb2) {
5245 status = smb2_file_link_information(conn,
5246 req,
5247 pdata,
5248 total_data,
5249 fsp,
5250 smb_fname);
5251 } else {
5252 status = smb_file_link_information(conn,
5253 req,
5254 pdata,
5255 total_data,
5256 fsp,
5257 smb_fname);
5259 break;
5262 default:
5263 return NT_STATUS_INVALID_LEVEL;
5266 if (!NT_STATUS_IS_OK(status)) {
5267 return status;
5270 *ret_data_size = data_return_size;
5271 return NT_STATUS_OK;
5274 static uint32_t generate_volume_serial_number(
5275 const struct loadparm_substitution *lp_sub,
5276 int snum)
5278 int serial = lp_volume_serial_number(snum);
5279 return serial != -1 ? serial:
5280 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
5281 (str_checksum(get_local_machine_name())<<16);