smbd: Move smb_set_file_unix_hlink() to smb1_trans2.c
[Samba.git] / source3 / smbd / smb2_trans2.c
blobd4a7125460520a1d4591489bb9c89f1b4ce9471e
1 /*
2 Unix SMB/CIFS implementation.
3 SMB transaction2 handling
4 Copyright (C) Jeremy Allison 1994-2007
5 Copyright (C) Stefan (metze) Metzmacher 2003
6 Copyright (C) Volker Lendecke 2005-2007
7 Copyright (C) Steve French 2005
8 Copyright (C) James Peach 2006-2007
10 Extensively modified by Andrew Tridgell, 1995
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 3 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "includes.h"
27 #include "ntioctl.h"
28 #include "system/filesys.h"
29 #include "lib/util/time_basic.h"
30 #include "version.h"
31 #include "smbd/smbd.h"
32 #include "smbd/globals.h"
33 #include "../libcli/auth/libcli_auth.h"
34 #include "../librpc/gen_ndr/xattr.h"
35 #include "../librpc/gen_ndr/ndr_security.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
44 #include "messages.h"
45 #include "libcli/smb/smb2_posix.h"
46 #include "lib/util/string_wrappers.h"
47 #include "source3/lib/substitute.h"
48 #include "source3/lib/adouble.h"
50 #define DIR_ENTRY_SAFETY_MARGIN 4096
52 static uint32_t generate_volume_serial_number(
53 const struct loadparm_substitution *lp_sub,
54 int snum);
56 /****************************************************************************
57 Check if an open file handle is a symlink.
58 ****************************************************************************/
60 NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
63 if (!VALID_STAT(fsp->fsp_name->st)) {
64 return NT_STATUS_ACCESS_DENIED;
66 if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
67 return NT_STATUS_ACCESS_DENIED;
69 if (fsp_get_pathref_fd(fsp) == -1) {
70 return NT_STATUS_ACCESS_DENIED;
72 return NT_STATUS_OK;
75 NTSTATUS check_access_fsp(struct files_struct *fsp,
76 uint32_t access_mask)
78 if (!fsp->fsp_flags.is_fsa) {
79 return smbd_check_access_rights_fsp(fsp->conn->cwd_fsp,
80 fsp,
81 false,
82 access_mask);
84 if (!(fsp->access_mask & access_mask)) {
85 return NT_STATUS_ACCESS_DENIED;
87 return NT_STATUS_OK;
90 #if defined(HAVE_POSIX_ACLS)
91 /****************************************************************************
92 Utility function to open a fsp for a POSIX handle operation.
93 ****************************************************************************/
95 static NTSTATUS get_posix_fsp(connection_struct *conn,
96 struct smb_request *req,
97 struct smb_filename *smb_fname,
98 uint32_t access_mask,
99 files_struct **ret_fsp)
101 NTSTATUS status;
102 uint32_t create_disposition = FILE_OPEN;
103 uint32_t share_access = FILE_SHARE_READ|
104 FILE_SHARE_WRITE|
105 FILE_SHARE_DELETE;
106 struct smb2_create_blobs *posx = NULL;
109 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
110 * but set reasonable defaults.
112 uint32_t file_attributes = 0664;
113 uint32_t oplock = NO_OPLOCK;
114 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
116 /* File or directory must exist. */
117 if (!VALID_STAT(smb_fname->st)) {
118 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
120 /* Cannot be a symlink. */
121 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
122 return NT_STATUS_ACCESS_DENIED;
124 /* Set options correctly for directory open. */
125 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
127 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
128 * directories, but set reasonable defaults.
130 file_attributes = 0775;
131 create_options = FILE_DIRECTORY_FILE;
134 status = make_smb2_posix_create_ctx(
135 talloc_tos(), &posx, file_attributes);
136 if (!NT_STATUS_IS_OK(status)) {
137 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
138 nt_errstr(status));
139 goto done;
142 status = SMB_VFS_CREATE_FILE(
143 conn, /* conn */
144 req, /* req */
145 NULL, /* dirfsp */
146 smb_fname, /* fname */
147 access_mask, /* access_mask */
148 share_access, /* share_access */
149 create_disposition,/* create_disposition*/
150 create_options, /* create_options */
151 file_attributes,/* file_attributes */
152 oplock, /* oplock_request */
153 NULL, /* lease */
154 0, /* allocation_size */
155 0, /* private_flags */
156 NULL, /* sd */
157 NULL, /* ea_list */
158 ret_fsp, /* result */
159 NULL, /* pinfo */
160 posx, /* in_context */
161 NULL); /* out_context */
163 done:
164 TALLOC_FREE(posx);
165 return status;
167 #endif
169 /********************************************************************
170 Roundup a value to the nearest allocation roundup size boundary.
171 Only do this for Windows clients.
172 ********************************************************************/
174 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
176 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
178 /* Only roundup for Windows clients. */
179 enum remote_arch_types ra_type = get_remote_arch();
180 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
181 val = SMB_ROUNDUP(val,rval);
183 return val;
186 /****************************************************************************
187 Utility functions for dealing with extended attributes.
188 ****************************************************************************/
190 /****************************************************************************
191 Refuse to allow clients to overwrite our private xattrs.
192 ****************************************************************************/
194 bool samba_private_attr_name(const char *unix_ea_name)
196 static const char * const prohibited_ea_names[] = {
197 SAMBA_POSIX_INHERITANCE_EA_NAME,
198 SAMBA_XATTR_DOS_ATTRIB,
199 SAMBA_XATTR_MARKER,
200 XATTR_NTACL_NAME,
201 AFPINFO_EA_NETATALK,
202 NULL
205 int i;
207 for (i = 0; prohibited_ea_names[i]; i++) {
208 if (strequal( prohibited_ea_names[i], unix_ea_name))
209 return true;
211 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
212 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
213 return true;
215 return false;
218 /****************************************************************************
219 Get one EA value. Fill in a struct ea_struct.
220 ****************************************************************************/
222 NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
223 files_struct *fsp,
224 const char *ea_name,
225 struct ea_struct *pea)
227 /* Get the value of this xattr. Max size is 64k. */
228 size_t attr_size = 256;
229 char *val = NULL;
230 ssize_t sizeret;
231 size_t max_xattr_size = 0;
233 if (fsp == NULL) {
234 return NT_STATUS_INVALID_HANDLE;
237 max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
239 again:
241 val = talloc_realloc(mem_ctx, val, char, attr_size);
242 if (!val) {
243 return NT_STATUS_NO_MEMORY;
246 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
247 if (sizeret == -1 && errno == ERANGE && attr_size < max_xattr_size) {
248 attr_size = max_xattr_size;
249 goto again;
252 if (sizeret == -1) {
253 return map_nt_error_from_unix(errno);
256 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
257 dump_data(10, (uint8_t *)val, sizeret);
259 pea->flags = 0;
260 if (strnequal(ea_name, "user.", 5)) {
261 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
262 } else {
263 pea->name = talloc_strdup(mem_ctx, ea_name);
265 if (pea->name == NULL) {
266 TALLOC_FREE(val);
267 return NT_STATUS_NO_MEMORY;
269 pea->value.data = (unsigned char *)val;
270 pea->value.length = (size_t)sizeret;
271 return NT_STATUS_OK;
274 NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
275 files_struct *fsp,
276 char ***pnames,
277 size_t *pnum_names)
279 char smallbuf[1024];
280 /* Get a list of all xattrs. Max namesize is 64k. */
281 size_t ea_namelist_size = 1024;
282 char *ea_namelist = smallbuf;
283 char *to_free = NULL;
285 char *p;
286 char **names;
287 size_t num_names;
288 ssize_t sizeret = -1;
289 NTSTATUS status;
291 if (pnames) {
292 *pnames = NULL;
294 *pnum_names = 0;
296 if (fsp == NULL) {
298 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
299 * symlink. This is ok, handle it here, by just return no EA's
300 * on a symlink.
302 return NT_STATUS_OK;
305 /* should be the case that fsp != NULL */
306 SMB_ASSERT(fsp != NULL);
308 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
309 ea_namelist_size);
311 if ((sizeret == -1) && (errno == ERANGE)) {
312 ea_namelist_size = 65536;
313 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
314 if (ea_namelist == NULL) {
315 return NT_STATUS_NO_MEMORY;
317 to_free = ea_namelist;
319 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
320 ea_namelist_size);
323 if (sizeret == -1) {
324 status = map_nt_error_from_unix(errno);
325 TALLOC_FREE(to_free);
326 return status;
329 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
331 if (sizeret == 0) {
332 TALLOC_FREE(to_free);
333 return NT_STATUS_OK;
337 * Ensure the result is 0-terminated
340 if (ea_namelist[sizeret-1] != '\0') {
341 TALLOC_FREE(to_free);
342 return NT_STATUS_INTERNAL_ERROR;
346 * count the names
348 num_names = 0;
350 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
351 num_names += 1;
354 *pnum_names = num_names;
356 if (pnames == NULL) {
357 TALLOC_FREE(to_free);
358 return NT_STATUS_OK;
361 names = talloc_array(mem_ctx, char *, num_names);
362 if (names == NULL) {
363 DEBUG(0, ("talloc failed\n"));
364 TALLOC_FREE(to_free);
365 return NT_STATUS_NO_MEMORY;
368 if (ea_namelist == smallbuf) {
369 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
370 if (ea_namelist == NULL) {
371 TALLOC_FREE(names);
372 return NT_STATUS_NO_MEMORY;
374 } else {
375 talloc_steal(names, ea_namelist);
377 ea_namelist = talloc_realloc(names, ea_namelist, char,
378 sizeret);
379 if (ea_namelist == NULL) {
380 TALLOC_FREE(names);
381 return NT_STATUS_NO_MEMORY;
385 num_names = 0;
387 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
388 names[num_names++] = p;
391 *pnames = names;
393 return NT_STATUS_OK;
396 /****************************************************************************
397 Return a linked list of the total EA's. Plus the total size
398 ****************************************************************************/
400 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
401 files_struct *fsp,
402 size_t *pea_total_len,
403 struct ea_list **ea_list)
405 /* Get a list of all xattrs. Max namesize is 64k. */
406 size_t i, num_names;
407 char **names;
408 struct ea_list *ea_list_head = NULL;
409 bool posix_pathnames = false;
410 NTSTATUS status;
412 *pea_total_len = 0;
413 *ea_list = NULL;
415 /* symlink */
416 if (fsp == NULL) {
417 return NT_STATUS_OK;
420 if (!lp_ea_support(SNUM(fsp->conn))) {
421 return NT_STATUS_OK;
424 if (fsp_is_alternate_stream(fsp)) {
425 return NT_STATUS_INVALID_PARAMETER;
428 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
430 status = get_ea_names_from_fsp(talloc_tos(),
431 fsp,
432 &names,
433 &num_names);
435 if (!NT_STATUS_IS_OK(status)) {
436 return status;
439 if (num_names == 0) {
440 return NT_STATUS_OK;
443 for (i=0; i<num_names; i++) {
444 struct ea_list *listp;
445 fstring dos_ea_name;
448 * POSIX EA names are divided into several namespaces by
449 * means of string prefixes. Usually, the system controls
450 * semantics for each namespace, but the 'user' namespace is
451 * available for arbitrary use, which comes closest to
452 * Windows EA semantics. Hence, we map POSIX EAs from the
453 * 'user' namespace to Windows EAs, and just ignore all the
454 * other namespaces. Also, a few specific names in the 'user'
455 * namespace are used by Samba internally. Filter them out as
456 * well, and only present the EAs that are available for
457 * arbitrary use.
459 if (!strnequal(names[i], "user.", 5)
460 || samba_private_attr_name(names[i]))
461 continue;
464 * Filter out any underlying POSIX EA names
465 * that a Windows client can't handle.
467 if (!posix_pathnames &&
468 is_invalid_windows_ea_name(names[i])) {
469 continue;
472 listp = talloc(mem_ctx, struct ea_list);
473 if (listp == NULL) {
474 return NT_STATUS_NO_MEMORY;
477 status = get_ea_value_fsp(listp,
478 fsp,
479 names[i],
480 &listp->ea);
482 if (!NT_STATUS_IS_OK(status)) {
483 TALLOC_FREE(listp);
484 return status;
487 if (listp->ea.value.length == 0) {
489 * We can never return a zero length EA.
490 * Windows reports the EA's as corrupted.
492 TALLOC_FREE(listp);
493 continue;
494 } else if (listp->ea.value.length > 65536) {
496 * SMB clients may report error with file
497 * if large EA is presented to them.
499 DBG_ERR("EA [%s] on file [%s] exceeds "
500 "maximum permitted EA size of 64KiB: %zu\n.",
501 listp->ea.name, fsp_str_dbg(fsp),
502 listp->ea.value.length);
503 TALLOC_FREE(listp);
504 continue;
507 push_ascii_fstring(dos_ea_name, listp->ea.name);
509 *pea_total_len +=
510 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
512 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
513 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
514 (unsigned int)listp->ea.value.length));
516 DLIST_ADD_END(ea_list_head, listp);
520 /* Add on 4 for total length. */
521 if (*pea_total_len) {
522 *pea_total_len += 4;
525 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
526 (unsigned int)*pea_total_len));
528 *ea_list = ea_list_head;
529 return NT_STATUS_OK;
532 /****************************************************************************
533 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
534 that was filled.
535 ****************************************************************************/
537 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
538 connection_struct *conn, struct ea_list *ea_list)
540 unsigned int ret_data_size = 4;
541 char *p = pdata;
543 SMB_ASSERT(total_data_size >= 4);
545 if (!lp_ea_support(SNUM(conn))) {
546 SIVAL(pdata,4,0);
547 return 4;
550 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
551 size_t dos_namelen;
552 fstring dos_ea_name;
553 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
554 dos_namelen = strlen(dos_ea_name);
555 if (dos_namelen > 255 || dos_namelen == 0) {
556 break;
558 if (ea_list->ea.value.length > 65535) {
559 break;
561 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
562 break;
565 /* We know we have room. */
566 SCVAL(p,0,ea_list->ea.flags);
567 SCVAL(p,1,dos_namelen);
568 SSVAL(p,2,ea_list->ea.value.length);
569 strlcpy(p+4, dos_ea_name, dos_namelen+1);
570 if (ea_list->ea.value.length > 0) {
571 memcpy(p + 4 + dos_namelen + 1,
572 ea_list->ea.value.data,
573 ea_list->ea.value.length);
576 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
577 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
580 ret_data_size = PTR_DIFF(p, pdata);
581 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
582 SIVAL(pdata,0,ret_data_size);
583 return ret_data_size;
586 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
587 char *pdata,
588 unsigned int total_data_size,
589 unsigned int *ret_data_size,
590 connection_struct *conn,
591 struct ea_list *ea_list)
593 uint8_t *p = (uint8_t *)pdata;
594 uint8_t *last_start = NULL;
595 bool do_store_data = (pdata != NULL);
597 *ret_data_size = 0;
599 if (!lp_ea_support(SNUM(conn))) {
600 return NT_STATUS_NO_EAS_ON_FILE;
603 for (; ea_list; ea_list = ea_list->next) {
604 size_t dos_namelen;
605 fstring dos_ea_name;
606 size_t this_size;
607 size_t pad = 0;
609 if (last_start != NULL && do_store_data) {
610 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
612 last_start = p;
614 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
615 dos_namelen = strlen(dos_ea_name);
616 if (dos_namelen > 255 || dos_namelen == 0) {
617 return NT_STATUS_INTERNAL_ERROR;
619 if (ea_list->ea.value.length > 65535) {
620 return NT_STATUS_INTERNAL_ERROR;
623 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
625 if (ea_list->next) {
626 pad = (4 - (this_size % 4)) % 4;
627 this_size += pad;
630 if (do_store_data) {
631 if (this_size > total_data_size) {
632 return NT_STATUS_INFO_LENGTH_MISMATCH;
635 /* We know we have room. */
636 SIVAL(p, 0x00, 0); /* next offset */
637 SCVAL(p, 0x04, ea_list->ea.flags);
638 SCVAL(p, 0x05, dos_namelen);
639 SSVAL(p, 0x06, ea_list->ea.value.length);
640 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
641 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
642 if (pad) {
643 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
644 '\0',
645 pad);
647 total_data_size -= this_size;
650 p += this_size;
653 *ret_data_size = PTR_DIFF(p, pdata);
654 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
655 return NT_STATUS_OK;
658 unsigned int estimate_ea_size(files_struct *fsp)
660 size_t total_ea_len = 0;
661 TALLOC_CTX *mem_ctx;
662 struct ea_list *ea_list = NULL;
663 NTSTATUS status;
665 /* symlink */
666 if (fsp == NULL) {
667 return 0;
670 if (!lp_ea_support(SNUM(fsp->conn))) {
671 return 0;
674 mem_ctx = talloc_stackframe();
676 /* If this is a stream fsp, then we need to instead find the
677 * estimated ea len from the main file, not the stream
678 * (streams cannot have EAs), but the estimate isn't just 0 in
679 * this case! */
680 fsp = metadata_fsp(fsp);
681 (void)get_ea_list_from_fsp(mem_ctx,
682 fsp,
683 &total_ea_len,
684 &ea_list);
686 if(fsp->conn->sconn->using_smb2) {
687 unsigned int ret_data_size;
689 * We're going to be using fill_ea_chained_buffer() to
690 * marshall EA's - this size is significantly larger
691 * than the SMB1 buffer. Re-calculate the size without
692 * marshalling.
694 status = fill_ea_chained_buffer(mem_ctx,
695 NULL,
697 &ret_data_size,
698 fsp->conn,
699 ea_list);
700 if (!NT_STATUS_IS_OK(status)) {
701 ret_data_size = 0;
703 total_ea_len = ret_data_size;
705 TALLOC_FREE(mem_ctx);
706 return total_ea_len;
709 /****************************************************************************
710 Ensure the EA name is case insensitive by matching any existing EA name.
711 ****************************************************************************/
713 static void canonicalize_ea_name(files_struct *fsp,
714 fstring unix_ea_name)
716 size_t total_ea_len;
717 TALLOC_CTX *mem_ctx = talloc_tos();
718 struct ea_list *ea_list;
719 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
720 fsp,
721 &total_ea_len,
722 &ea_list);
723 if (!NT_STATUS_IS_OK(status)) {
724 return;
727 for (; ea_list; ea_list = ea_list->next) {
728 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
729 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
730 &unix_ea_name[5], ea_list->ea.name));
731 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
732 break;
737 /****************************************************************************
738 Set or delete an extended attribute.
739 ****************************************************************************/
741 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
742 struct ea_list *ea_list)
744 NTSTATUS status;
745 bool posix_pathnames = false;
747 if (!lp_ea_support(SNUM(conn))) {
748 return NT_STATUS_EAS_NOT_SUPPORTED;
751 if (fsp == NULL) {
752 return NT_STATUS_INVALID_HANDLE;
755 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
757 status = refuse_symlink_fsp(fsp);
758 if (!NT_STATUS_IS_OK(status)) {
759 return status;
762 status = check_access_fsp(fsp, FILE_WRITE_EA);
763 if (!NT_STATUS_IS_OK(status)) {
764 return status;
767 /* Setting EAs on streams isn't supported. */
768 if (fsp_is_alternate_stream(fsp)) {
769 return NT_STATUS_INVALID_PARAMETER;
773 * Filter out invalid Windows EA names - before
774 * we set *any* of them.
777 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
778 return STATUS_INVALID_EA_NAME;
781 for (;ea_list; ea_list = ea_list->next) {
782 int ret;
783 fstring unix_ea_name;
786 * Complementing the forward mapping from POSIX EAs to
787 * Windows EAs in get_ea_list_from_fsp(), here we map in the
788 * opposite direction from Windows EAs to the 'user' namespace
789 * of POSIX EAs. Hence, all POSIX EA names the we set here must
790 * start with a 'user.' prefix.
792 fstrcpy(unix_ea_name, "user.");
793 fstrcat(unix_ea_name, ea_list->ea.name);
795 canonicalize_ea_name(fsp, unix_ea_name);
797 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
799 if (samba_private_attr_name(unix_ea_name)) {
800 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
801 return NT_STATUS_ACCESS_DENIED;
804 if (ea_list->ea.value.length == 0) {
805 /* Remove the attribute. */
806 DBG_DEBUG("deleting ea name %s on "
807 "file %s by file descriptor.\n",
808 unix_ea_name, fsp_str_dbg(fsp));
809 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
810 #ifdef ENOATTR
811 /* Removing a non existent attribute always succeeds. */
812 if (ret == -1 && errno == ENOATTR) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
814 unix_ea_name));
815 ret = 0;
817 #endif
818 } else {
819 DEBUG(10,("set_ea: setting ea name %s on file "
820 "%s by file descriptor.\n",
821 unix_ea_name, fsp_str_dbg(fsp)));
822 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
823 ea_list->ea.value.data, ea_list->ea.value.length, 0);
826 if (ret == -1) {
827 #ifdef ENOTSUP
828 if (errno == ENOTSUP) {
829 return NT_STATUS_EAS_NOT_SUPPORTED;
831 #endif
832 return map_nt_error_from_unix(errno);
836 return NT_STATUS_OK;
839 /****************************************************************************
840 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
841 ****************************************************************************/
843 struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
845 struct ea_list *ea_list_head = NULL;
846 size_t offset = 0;
847 size_t bytes_used = 0;
849 while (offset < data_size) {
850 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
852 if (!eal) {
853 return NULL;
856 DLIST_ADD_END(ea_list_head, eal);
857 offset += bytes_used;
860 return ea_list_head;
863 /****************************************************************************
864 Count the total EA size needed.
865 ****************************************************************************/
867 static size_t ea_list_size(struct ea_list *ealist)
869 fstring dos_ea_name;
870 struct ea_list *listp;
871 size_t ret = 0;
873 for (listp = ealist; listp; listp = listp->next) {
874 push_ascii_fstring(dos_ea_name, listp->ea.name);
875 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
877 /* Add on 4 for total length. */
878 if (ret) {
879 ret += 4;
882 return ret;
885 /****************************************************************************
886 Return a union of EA's from a file list and a list of names.
887 The TALLOC context for the two lists *MUST* be identical as we steal
888 memory from one list to add to another. JRA.
889 ****************************************************************************/
891 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
893 struct ea_list *nlistp, *flistp;
895 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
896 for (flistp = file_list; flistp; flistp = flistp->next) {
897 if (strequal(nlistp->ea.name, flistp->ea.name)) {
898 break;
902 if (flistp) {
903 /* Copy the data from this entry. */
904 nlistp->ea.flags = flistp->ea.flags;
905 nlistp->ea.value = flistp->ea.value;
906 } else {
907 /* Null entry. */
908 nlistp->ea.flags = 0;
909 ZERO_STRUCT(nlistp->ea.value);
913 *total_ea_len = ea_list_size(name_list);
914 return name_list;
917 /*********************************************************
918 Routine to check if a given string matches exactly.
919 as a special case a mask of "." does NOT match. That
920 is required for correct wildcard semantics
921 Case can be significant or not.
922 **********************************************************/
924 static bool exact_match(bool has_wild,
925 bool case_sensitive,
926 const char *str,
927 const char *mask)
929 if (mask[0] == '.' && mask[1] == 0) {
930 return false;
933 if (has_wild) {
934 return false;
937 if (case_sensitive) {
938 return strcmp(str,mask)==0;
939 } else {
940 return strcasecmp_m(str,mask) == 0;
944 /****************************************************************************
945 Return the filetype for UNIX extensions.
946 ****************************************************************************/
948 static uint32_t unix_filetype(mode_t mode)
950 if(S_ISREG(mode))
951 return UNIX_TYPE_FILE;
952 else if(S_ISDIR(mode))
953 return UNIX_TYPE_DIR;
954 #ifdef S_ISLNK
955 else if(S_ISLNK(mode))
956 return UNIX_TYPE_SYMLINK;
957 #endif
958 #ifdef S_ISCHR
959 else if(S_ISCHR(mode))
960 return UNIX_TYPE_CHARDEV;
961 #endif
962 #ifdef S_ISBLK
963 else if(S_ISBLK(mode))
964 return UNIX_TYPE_BLKDEV;
965 #endif
966 #ifdef S_ISFIFO
967 else if(S_ISFIFO(mode))
968 return UNIX_TYPE_FIFO;
969 #endif
970 #ifdef S_ISSOCK
971 else if(S_ISSOCK(mode))
972 return UNIX_TYPE_SOCKET;
973 #endif
975 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
976 return UNIX_TYPE_UNKNOWN;
979 /****************************************************************************
980 Map wire perms onto standard UNIX permissions. Obey share restrictions.
981 ****************************************************************************/
983 NTSTATUS unix_perms_from_wire(connection_struct *conn,
984 const SMB_STRUCT_STAT *psbuf,
985 uint32_t perms,
986 enum perm_type ptype,
987 mode_t *ret_perms)
989 mode_t ret = 0;
991 if (perms == SMB_MODE_NO_CHANGE) {
992 if (!VALID_STAT(*psbuf)) {
993 return NT_STATUS_INVALID_PARAMETER;
994 } else {
995 *ret_perms = psbuf->st_ex_mode;
996 return NT_STATUS_OK;
1000 ret = wire_perms_to_unix(perms);
1002 if (ptype == PERM_NEW_FILE) {
1004 * "create mask"/"force create mode" are
1005 * only applied to new files, not existing ones.
1007 ret &= lp_create_mask(SNUM(conn));
1008 /* Add in force bits */
1009 ret |= lp_force_create_mode(SNUM(conn));
1010 } else if (ptype == PERM_NEW_DIR) {
1012 * "directory mask"/"force directory mode" are
1013 * only applied to new directories, not existing ones.
1015 ret &= lp_directory_mask(SNUM(conn));
1016 /* Add in force bits */
1017 ret |= lp_force_directory_mode(SNUM(conn));
1020 *ret_perms = ret;
1021 return NT_STATUS_OK;
1024 /****************************************************************************
1025 Needed to show the msdfs symlinks as directories. Modifies psbuf
1026 to be a directory if it's a msdfs link.
1027 ****************************************************************************/
1029 static bool check_msdfs_link(struct files_struct *dirfsp,
1030 struct smb_filename *atname,
1031 struct smb_filename *smb_fname)
1033 int saved_errno = errno;
1034 if(lp_host_msdfs() &&
1035 lp_msdfs_root(SNUM(dirfsp->conn)) &&
1036 is_msdfs_link(dirfsp, atname)) {
1039 * Copy the returned stat struct from the relative
1040 * to the full pathname.
1042 smb_fname->st = atname->st;
1044 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1045 "as a directory\n",
1046 smb_fname->base_name));
1047 smb_fname->st.st_ex_mode =
1048 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1049 errno = saved_errno;
1050 return true;
1052 errno = saved_errno;
1053 return false;
1057 /****************************************************************************
1058 Get a level dependent lanman2 dir entry.
1059 ****************************************************************************/
1061 struct smbd_dirptr_lanman2_state {
1062 connection_struct *conn;
1063 uint32_t info_level;
1064 bool check_mangled_names;
1065 bool has_wild;
1066 bool got_exact_match;
1067 bool case_sensitive;
1070 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1071 void *private_data,
1072 const char *dname,
1073 const char *mask,
1074 char **_fname)
1076 struct smbd_dirptr_lanman2_state *state =
1077 (struct smbd_dirptr_lanman2_state *)private_data;
1078 bool ok;
1079 char mangled_name[13]; /* mangled 8.3 name. */
1080 bool got_match;
1081 const char *fname;
1083 /* Mangle fname if it's an illegal name. */
1084 if (mangle_must_mangle(dname, state->conn->params)) {
1086 * Slow path - ensure we can push the original name as UCS2. If
1087 * not, then just don't return this name.
1089 NTSTATUS status;
1090 size_t ret_len = 0;
1091 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1092 uint8_t *tmp = talloc_array(talloc_tos(),
1093 uint8_t,
1094 len);
1096 status = srvstr_push(NULL,
1097 FLAGS2_UNICODE_STRINGS,
1098 tmp,
1099 dname,
1100 len,
1101 STR_TERMINATE,
1102 &ret_len);
1104 TALLOC_FREE(tmp);
1106 if (!NT_STATUS_IS_OK(status)) {
1107 return false;
1110 ok = name_to_8_3(dname, mangled_name,
1111 true, state->conn->params);
1112 if (!ok) {
1113 return false;
1115 fname = mangled_name;
1116 } else {
1117 fname = dname;
1120 got_match = exact_match(state->has_wild,
1121 state->case_sensitive,
1122 fname, mask);
1123 state->got_exact_match = got_match;
1124 if (!got_match) {
1125 got_match = mask_match(fname, mask,
1126 state->case_sensitive);
1129 if(!got_match && state->check_mangled_names &&
1130 !mangle_is_8_3(fname, false, state->conn->params)) {
1132 * It turns out that NT matches wildcards against
1133 * both long *and* short names. This may explain some
1134 * of the wildcard wierdness from old DOS clients
1135 * that some people have been seeing.... JRA.
1137 /* Force the mangling into 8.3. */
1138 ok = name_to_8_3(fname, mangled_name,
1139 false, state->conn->params);
1140 if (!ok) {
1141 return false;
1144 got_match = exact_match(state->has_wild,
1145 state->case_sensitive,
1146 mangled_name, mask);
1147 state->got_exact_match = got_match;
1148 if (!got_match) {
1149 got_match = mask_match(mangled_name, mask,
1150 state->case_sensitive);
1154 if (!got_match) {
1155 return false;
1158 *_fname = talloc_strdup(ctx, fname);
1159 if (*_fname == NULL) {
1160 return false;
1163 return true;
1166 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1167 void *private_data,
1168 struct files_struct *dirfsp,
1169 struct smb_filename *atname,
1170 struct smb_filename *smb_fname,
1171 bool get_dosmode,
1172 uint32_t *_mode)
1174 struct smbd_dirptr_lanman2_state *state =
1175 (struct smbd_dirptr_lanman2_state *)private_data;
1176 bool ms_dfs_link = false;
1178 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1179 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1180 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1181 "Couldn't lstat [%s] (%s)\n",
1182 smb_fname_str_dbg(smb_fname),
1183 strerror(errno)));
1184 return false;
1186 return true;
1189 if (!VALID_STAT(smb_fname->st) &&
1190 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1191 /* Needed to show the msdfs symlinks as
1192 * directories */
1194 ms_dfs_link = check_msdfs_link(dirfsp,
1195 atname,
1196 smb_fname);
1197 if (!ms_dfs_link) {
1198 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1199 "Couldn't stat [%s] (%s)\n",
1200 smb_fname_str_dbg(smb_fname),
1201 strerror(errno)));
1202 return false;
1205 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1206 return true;
1209 if (!get_dosmode) {
1210 return true;
1213 *_mode = fdos_mode(smb_fname->fsp);
1214 smb_fname->st = smb_fname->fsp->fsp_name->st;
1216 return true;
1219 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1220 connection_struct *conn,
1221 uint16_t flags2,
1222 uint32_t info_level,
1223 struct ea_list *name_list,
1224 bool check_mangled_names,
1225 bool requires_resume_key,
1226 uint32_t mode,
1227 const char *fname,
1228 const struct smb_filename *smb_fname,
1229 int space_remaining,
1230 uint8_t align,
1231 bool do_pad,
1232 char *base_data,
1233 char **ppdata,
1234 char *end_data,
1235 uint64_t *last_entry_off)
1237 char *p, *q, *pdata = *ppdata;
1238 uint32_t reskey=0;
1239 uint64_t file_size = 0;
1240 uint64_t allocation_size = 0;
1241 uint64_t file_id = 0;
1242 size_t len = 0;
1243 struct timespec mdate_ts = {0};
1244 struct timespec adate_ts = {0};
1245 struct timespec cdate_ts = {0};
1246 struct timespec create_date_ts = {0};
1247 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1248 char *nameptr;
1249 char *last_entry_ptr;
1250 bool was_8_3;
1251 int off;
1252 int pad = 0;
1253 NTSTATUS status;
1254 struct readdir_attr_data *readdir_attr_data = NULL;
1256 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1257 file_size = get_file_size_stat(&smb_fname->st);
1259 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1262 * Skip SMB_VFS_FREADDIR_ATTR if the directory entry is a symlink or
1263 * a DFS symlink.
1265 if (smb_fname->fsp != NULL &&
1266 !(mode & FILE_ATTRIBUTE_REPARSE_POINT)) {
1267 status = SMB_VFS_FREADDIR_ATTR(smb_fname->fsp,
1268 ctx,
1269 &readdir_attr_data);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED,
1272 status)) {
1273 return status;
1278 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1280 mdate_ts = smb_fname->st.st_ex_mtime;
1281 adate_ts = smb_fname->st.st_ex_atime;
1282 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1283 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1285 if (lp_dos_filetime_resolution(SNUM(conn))) {
1286 dos_filetime_timespec(&create_date_ts);
1287 dos_filetime_timespec(&mdate_ts);
1288 dos_filetime_timespec(&adate_ts);
1289 dos_filetime_timespec(&cdate_ts);
1292 create_date = convert_timespec_to_time_t(create_date_ts);
1293 mdate = convert_timespec_to_time_t(mdate_ts);
1294 adate = convert_timespec_to_time_t(adate_ts);
1296 /* align the record */
1297 SMB_ASSERT(align >= 1);
1299 off = (int)PTR_DIFF(pdata, base_data);
1300 pad = (off + (align-1)) & ~(align-1);
1301 pad -= off;
1303 if (pad && pad > space_remaining) {
1304 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1305 "for padding (wanted %u, had %d)\n",
1306 (unsigned int)pad,
1307 space_remaining ));
1308 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1311 off += pad;
1312 /* initialize padding to 0 */
1313 if (pad) {
1314 memset(pdata, 0, pad);
1316 space_remaining -= pad;
1318 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1319 space_remaining ));
1321 pdata += pad;
1322 p = pdata;
1323 last_entry_ptr = p;
1325 pad = 0;
1326 off = 0;
1328 switch (info_level) {
1329 case SMB_FIND_INFO_STANDARD:
1330 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1331 if(requires_resume_key) {
1332 SIVAL(p,0,reskey);
1333 p += 4;
1335 srv_put_dos_date2(p,0,create_date);
1336 srv_put_dos_date2(p,4,adate);
1337 srv_put_dos_date2(p,8,mdate);
1338 SIVAL(p,12,(uint32_t)file_size);
1339 SIVAL(p,16,(uint32_t)allocation_size);
1340 SSVAL(p,20,mode);
1341 p += 23;
1342 nameptr = p;
1343 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1344 p += ucs2_align(base_data, p, 0);
1346 status = srvstr_push(base_data, flags2, p,
1347 fname, PTR_DIFF(end_data, p),
1348 STR_TERMINATE, &len);
1349 if (!NT_STATUS_IS_OK(status)) {
1350 return status;
1352 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1353 if (len > 2) {
1354 SCVAL(nameptr, -1, len - 2);
1355 } else {
1356 SCVAL(nameptr, -1, 0);
1358 } else {
1359 if (len > 1) {
1360 SCVAL(nameptr, -1, len - 1);
1361 } else {
1362 SCVAL(nameptr, -1, 0);
1365 p += len;
1366 break;
1368 case SMB_FIND_EA_SIZE:
1369 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1370 if (requires_resume_key) {
1371 SIVAL(p,0,reskey);
1372 p += 4;
1374 srv_put_dos_date2(p,0,create_date);
1375 srv_put_dos_date2(p,4,adate);
1376 srv_put_dos_date2(p,8,mdate);
1377 SIVAL(p,12,(uint32_t)file_size);
1378 SIVAL(p,16,(uint32_t)allocation_size);
1379 SSVAL(p,20,mode);
1381 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1382 SIVAL(p,22,ea_size); /* Extended attributes */
1384 p += 27;
1385 nameptr = p - 1;
1386 status = srvstr_push(base_data, flags2,
1387 p, fname, PTR_DIFF(end_data, p),
1388 STR_TERMINATE | STR_NOALIGN, &len);
1389 if (!NT_STATUS_IS_OK(status)) {
1390 return status;
1392 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1393 if (len > 2) {
1394 len -= 2;
1395 } else {
1396 len = 0;
1398 } else {
1399 if (len > 1) {
1400 len -= 1;
1401 } else {
1402 len = 0;
1405 SCVAL(nameptr,0,len);
1406 p += len;
1407 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1408 break;
1410 case SMB_FIND_EA_LIST:
1412 struct ea_list *file_list = NULL;
1413 size_t ea_len = 0;
1415 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1416 if (!name_list) {
1417 return NT_STATUS_INVALID_PARAMETER;
1419 if (requires_resume_key) {
1420 SIVAL(p,0,reskey);
1421 p += 4;
1423 srv_put_dos_date2(p,0,create_date);
1424 srv_put_dos_date2(p,4,adate);
1425 srv_put_dos_date2(p,8,mdate);
1426 SIVAL(p,12,(uint32_t)file_size);
1427 SIVAL(p,16,(uint32_t)allocation_size);
1428 SSVAL(p,20,mode);
1429 p += 22; /* p now points to the EA area. */
1431 status = get_ea_list_from_fsp(ctx,
1432 smb_fname->fsp,
1433 &ea_len, &file_list);
1434 if (!NT_STATUS_IS_OK(status)) {
1435 file_list = NULL;
1437 name_list = ea_list_union(name_list, file_list, &ea_len);
1439 /* We need to determine if this entry will fit in the space available. */
1440 /* Max string size is 255 bytes. */
1441 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1442 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1443 "(wanted %u, had %d)\n",
1444 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1445 space_remaining ));
1446 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1449 /* Push the ea_data followed by the name. */
1450 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1451 nameptr = p;
1452 status = srvstr_push(base_data, flags2,
1453 p + 1, fname, PTR_DIFF(end_data, p+1),
1454 STR_TERMINATE | STR_NOALIGN, &len);
1455 if (!NT_STATUS_IS_OK(status)) {
1456 return status;
1458 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1459 if (len > 2) {
1460 len -= 2;
1461 } else {
1462 len = 0;
1464 } else {
1465 if (len > 1) {
1466 len -= 1;
1467 } else {
1468 len = 0;
1471 SCVAL(nameptr,0,len);
1472 p += len + 1;
1473 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1474 break;
1477 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1478 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1479 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1480 p += 4;
1481 SIVAL(p,0,reskey); p += 4;
1482 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1483 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1484 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1485 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1486 SOFF_T(p,0,file_size); p += 8;
1487 SOFF_T(p,0,allocation_size); p += 8;
1488 SIVAL(p,0,mode); p += 4;
1489 q = p; p += 4; /* q is placeholder for name length. */
1490 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1491 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1492 } else {
1493 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1494 SIVAL(p,0,ea_size); /* Extended attributes */
1496 p += 4;
1497 /* Clear the short name buffer. This is
1498 * IMPORTANT as not doing so will trigger
1499 * a Win2k client bug. JRA.
1501 if (!was_8_3 && check_mangled_names) {
1502 char mangled_name[13]; /* mangled 8.3 name. */
1503 if (!name_to_8_3(fname,mangled_name,True,
1504 conn->params)) {
1505 /* Error - mangle failed ! */
1506 memset(mangled_name,'\0',12);
1508 mangled_name[12] = 0;
1509 status = srvstr_push(base_data, flags2,
1510 p+2, mangled_name, 24,
1511 STR_UPPER|STR_UNICODE, &len);
1512 if (!NT_STATUS_IS_OK(status)) {
1513 return status;
1515 if (len < 24) {
1516 memset(p + 2 + len,'\0',24 - len);
1518 SSVAL(p, 0, len);
1519 } else {
1520 memset(p,'\0',26);
1522 p += 2 + 24;
1523 status = srvstr_push(base_data, flags2, p,
1524 fname, PTR_DIFF(end_data, p),
1525 STR_TERMINATE_ASCII, &len);
1526 if (!NT_STATUS_IS_OK(status)) {
1527 return status;
1529 SIVAL(q,0,len);
1530 p += len;
1532 len = PTR_DIFF(p, pdata);
1533 pad = (len + (align-1)) & ~(align-1);
1535 * offset to the next entry, the caller
1536 * will overwrite it for the last entry
1537 * that's why we always include the padding
1539 SIVAL(pdata,0,pad);
1541 * set padding to zero
1543 if (do_pad) {
1544 memset(p, 0, pad - len);
1545 p = pdata + pad;
1546 } else {
1547 p = pdata + len;
1549 break;
1551 case SMB_FIND_FILE_DIRECTORY_INFO:
1552 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
1553 p += 4;
1554 SIVAL(p,0,reskey); p += 4;
1555 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1556 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1557 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1558 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1559 SOFF_T(p,0,file_size); p += 8;
1560 SOFF_T(p,0,allocation_size); p += 8;
1561 SIVAL(p,0,mode); p += 4;
1562 status = srvstr_push(base_data, flags2,
1563 p + 4, fname, PTR_DIFF(end_data, p+4),
1564 STR_TERMINATE_ASCII, &len);
1565 if (!NT_STATUS_IS_OK(status)) {
1566 return status;
1568 SIVAL(p,0,len);
1569 p += 4 + len;
1571 len = PTR_DIFF(p, pdata);
1572 pad = (len + (align-1)) & ~(align-1);
1574 * offset to the next entry, the caller
1575 * will overwrite it for the last entry
1576 * that's why we always include the padding
1578 SIVAL(pdata,0,pad);
1580 * set padding to zero
1582 if (do_pad) {
1583 memset(p, 0, pad - len);
1584 p = pdata + pad;
1585 } else {
1586 p = pdata + len;
1588 break;
1590 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
1591 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
1592 p += 4;
1593 SIVAL(p,0,reskey); p += 4;
1594 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1595 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1596 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1597 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1598 SOFF_T(p,0,file_size); p += 8;
1599 SOFF_T(p,0,allocation_size); p += 8;
1600 SIVAL(p,0,mode); p += 4;
1601 q = p; p += 4; /* q is placeholder for name length. */
1602 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1603 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1604 } else {
1605 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1606 SIVAL(p,0,ea_size); /* Extended attributes */
1608 p +=4;
1609 status = srvstr_push(base_data, flags2, p,
1610 fname, PTR_DIFF(end_data, p),
1611 STR_TERMINATE_ASCII, &len);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 return status;
1615 SIVAL(q, 0, len);
1616 p += len;
1618 len = PTR_DIFF(p, pdata);
1619 pad = (len + (align-1)) & ~(align-1);
1621 * offset to the next entry, the caller
1622 * will overwrite it for the last entry
1623 * that's why we always include the padding
1625 SIVAL(pdata,0,pad);
1627 * set padding to zero
1629 if (do_pad) {
1630 memset(p, 0, pad - len);
1631 p = pdata + pad;
1632 } else {
1633 p = pdata + len;
1635 break;
1637 case SMB_FIND_FILE_NAMES_INFO:
1638 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
1639 p += 4;
1640 SIVAL(p,0,reskey); p += 4;
1641 p += 4;
1642 /* this must *not* be null terminated or w2k gets in a loop trying to set an
1643 acl on a dir (tridge) */
1644 status = srvstr_push(base_data, flags2, p,
1645 fname, PTR_DIFF(end_data, p),
1646 STR_TERMINATE_ASCII, &len);
1647 if (!NT_STATUS_IS_OK(status)) {
1648 return status;
1650 SIVAL(p, -4, len);
1651 p += len;
1653 len = PTR_DIFF(p, pdata);
1654 pad = (len + (align-1)) & ~(align-1);
1656 * offset to the next entry, the caller
1657 * will overwrite it for the last entry
1658 * that's why we always include the padding
1660 SIVAL(pdata,0,pad);
1662 * set padding to zero
1664 if (do_pad) {
1665 memset(p, 0, pad - len);
1666 p = pdata + pad;
1667 } else {
1668 p = pdata + len;
1670 break;
1672 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
1673 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
1674 p += 4;
1675 SIVAL(p,0,reskey); p += 4;
1676 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1677 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1678 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1679 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1680 SOFF_T(p,0,file_size); p += 8;
1681 SOFF_T(p,0,allocation_size); p += 8;
1682 SIVAL(p,0,mode); p += 4;
1683 q = p; p += 4; /* q is placeholder for name length. */
1684 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1685 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1686 } else {
1687 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1688 SIVAL(p,0,ea_size); /* Extended attributes */
1690 p += 4;
1691 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
1692 SBVAL(p,0,file_id); p += 8;
1693 status = srvstr_push(base_data, flags2, p,
1694 fname, PTR_DIFF(end_data, p),
1695 STR_TERMINATE_ASCII, &len);
1696 if (!NT_STATUS_IS_OK(status)) {
1697 return status;
1699 SIVAL(q, 0, len);
1700 p += len;
1702 len = PTR_DIFF(p, pdata);
1703 pad = (len + (align-1)) & ~(align-1);
1705 * offset to the next entry, the caller
1706 * will overwrite it for the last entry
1707 * that's why we always include the padding
1709 SIVAL(pdata,0,pad);
1711 * set padding to zero
1713 if (do_pad) {
1714 memset(p, 0, pad - len);
1715 p = pdata + pad;
1716 } else {
1717 p = pdata + len;
1719 break;
1721 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
1722 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
1723 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1724 p += 4;
1725 SIVAL(p,0,reskey); p += 4;
1726 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
1727 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
1728 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
1729 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
1730 SOFF_T(p,0,file_size); p += 8;
1731 SOFF_T(p,0,allocation_size); p += 8;
1732 SIVAL(p,0,mode); p += 4;
1733 q = p; p += 4; /* q is placeholder for name length */
1734 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1735 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1736 } else if (readdir_attr_data &&
1737 readdir_attr_data->type == RDATTR_AAPL) {
1739 * OS X specific SMB2 extension negotiated via
1740 * AAPL create context: return max_access in
1741 * ea_size field.
1743 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
1744 } else {
1745 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1746 SIVAL(p,0,ea_size); /* Extended attributes */
1748 p += 4;
1750 if (readdir_attr_data &&
1751 readdir_attr_data->type == RDATTR_AAPL) {
1753 * OS X specific SMB2 extension negotiated via
1754 * AAPL create context: return resource fork
1755 * length and compressed FinderInfo in
1756 * shortname field.
1758 * According to documentation short_name_len
1759 * should be 0, but on the wire behaviour
1760 * shows its set to 24 by clients.
1762 SSVAL(p, 0, 24);
1764 /* Resourefork length */
1765 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
1767 /* Compressed FinderInfo */
1768 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
1769 } else if (!was_8_3 && check_mangled_names) {
1770 char mangled_name[13]; /* mangled 8.3 name. */
1771 if (!name_to_8_3(fname,mangled_name,True,
1772 conn->params)) {
1773 /* Error - mangle failed ! */
1774 memset(mangled_name,'\0',12);
1776 mangled_name[12] = 0;
1777 status = srvstr_push(base_data, flags2,
1778 p+2, mangled_name, 24,
1779 STR_UPPER|STR_UNICODE, &len);
1780 if (!NT_STATUS_IS_OK(status)) {
1781 return status;
1783 SSVAL(p, 0, len);
1784 if (len < 24) {
1785 memset(p + 2 + len,'\0',24 - len);
1787 SSVAL(p, 0, len);
1788 } else {
1789 /* Clear the short name buffer. This is
1790 * IMPORTANT as not doing so will trigger
1791 * a Win2k client bug. JRA.
1793 memset(p,'\0',26);
1795 p += 26;
1797 /* Reserved ? */
1798 if (readdir_attr_data &&
1799 readdir_attr_data->type == RDATTR_AAPL) {
1801 * OS X specific SMB2 extension negotiated via
1802 * AAPL create context: return UNIX mode in
1803 * reserved field.
1805 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
1806 SSVAL(p, 0, aapl_mode);
1807 } else {
1808 SSVAL(p, 0, 0);
1810 p += 2;
1812 SBVAL(p,0,file_id); p += 8;
1813 status = srvstr_push(base_data, flags2, p,
1814 fname, PTR_DIFF(end_data, p),
1815 STR_TERMINATE_ASCII, &len);
1816 if (!NT_STATUS_IS_OK(status)) {
1817 return status;
1819 SIVAL(q,0,len);
1820 p += len;
1822 len = PTR_DIFF(p, pdata);
1823 pad = (len + (align-1)) & ~(align-1);
1825 * offset to the next entry, the caller
1826 * will overwrite it for the last entry
1827 * that's why we always include the padding
1829 SIVAL(pdata,0,pad);
1831 * set padding to zero
1833 if (do_pad) {
1834 memset(p, 0, pad - len);
1835 p = pdata + pad;
1836 } else {
1837 p = pdata + len;
1839 break;
1841 /* CIFS UNIX Extension. */
1843 case SMB_FIND_FILE_UNIX:
1844 case SMB_FIND_FILE_UNIX_INFO2:
1845 p+= 4;
1846 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
1848 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
1850 if (info_level == SMB_FIND_FILE_UNIX) {
1851 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
1852 p = store_file_unix_basic(conn, p,
1853 NULL, &smb_fname->st);
1854 status = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE, &len);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 return status;
1860 } else {
1861 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
1862 p = store_file_unix_basic_info2(conn, p,
1863 NULL, &smb_fname->st);
1864 nameptr = p;
1865 p += 4;
1866 status = srvstr_push(base_data, flags2, p, fname,
1867 PTR_DIFF(end_data, p), 0, &len);
1868 if (!NT_STATUS_IS_OK(status)) {
1869 return status;
1871 SIVAL(nameptr, 0, len);
1874 p += len;
1876 len = PTR_DIFF(p, pdata);
1877 pad = (len + (align-1)) & ~(align-1);
1879 * offset to the next entry, the caller
1880 * will overwrite it for the last entry
1881 * that's why we always include the padding
1883 SIVAL(pdata,0,pad);
1885 * set padding to zero
1887 if (do_pad) {
1888 memset(p, 0, pad - len);
1889 p = pdata + pad;
1890 } else {
1891 p = pdata + len;
1893 /* End of SMB_QUERY_FILE_UNIX_BASIC */
1895 break;
1897 /* SMB2 UNIX Extension. */
1899 case SMB2_FILE_POSIX_INFORMATION:
1901 uint8_t *buf = NULL;
1902 ssize_t plen = 0;
1903 p+= 4;
1904 SIVAL(p,0,reskey); p+= 4;
1906 DEBUG(10,("smbd_marshall_dir_entry: "
1907 "SMB2_FILE_POSIX_INFORMATION\n"));
1908 if (!(conn->sconn->using_smb2)) {
1909 return NT_STATUS_INVALID_LEVEL;
1911 if (!lp_smb3_unix_extensions()) {
1912 return NT_STATUS_INVALID_LEVEL;
1915 /* Determine the size of the posix info context */
1916 plen = store_smb2_posix_info(conn,
1917 &smb_fname->st,
1919 mode,
1920 NULL,
1922 if (plen == -1) {
1923 return NT_STATUS_INVALID_PARAMETER;
1925 buf = talloc_zero_size(ctx, plen);
1926 if (buf == NULL) {
1927 return NT_STATUS_NO_MEMORY;
1930 /* Store the context in buf */
1931 store_smb2_posix_info(conn,
1932 &smb_fname->st,
1934 mode,
1935 buf,
1936 plen);
1937 memcpy(p, buf, plen);
1938 p += plen;
1939 TALLOC_FREE(buf);
1941 nameptr = p;
1942 p += 4;
1943 status = srvstr_push(base_data, flags2, p, fname,
1944 PTR_DIFF(end_data, p), 0, &len);
1945 if (!NT_STATUS_IS_OK(status)) {
1946 return status;
1948 SIVAL(nameptr, 0, len);
1950 p += len;
1952 len = PTR_DIFF(p, pdata);
1953 pad = (len + (align-1)) & ~(align-1);
1955 * offset to the next entry, the caller
1956 * will overwrite it for the last entry
1957 * that's why we always include the padding
1959 SIVAL(pdata,0,pad);
1960 break;
1963 default:
1964 return NT_STATUS_INVALID_LEVEL;
1967 if (PTR_DIFF(p,pdata) > space_remaining) {
1968 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1969 "(wanted %u, had %d)\n",
1970 (unsigned int)PTR_DIFF(p,pdata),
1971 space_remaining ));
1972 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1975 /* Setup the last entry pointer, as an offset from base_data */
1976 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
1977 /* Advance the data pointer to the next slot */
1978 *ppdata = p;
1980 return NT_STATUS_OK;
1983 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
1984 connection_struct *conn,
1985 struct dptr_struct *dirptr,
1986 uint16_t flags2,
1987 const char *path_mask,
1988 uint32_t dirtype,
1989 int info_level,
1990 int requires_resume_key,
1991 bool dont_descend,
1992 bool ask_sharemode,
1993 bool get_dosmode,
1994 uint8_t align,
1995 bool do_pad,
1996 char **ppdata,
1997 char *base_data,
1998 char *end_data,
1999 int space_remaining,
2000 struct smb_filename **_smb_fname,
2001 bool *got_exact_match,
2002 int *_last_entry_off,
2003 struct ea_list *name_list,
2004 struct file_id *file_id)
2006 const char *p;
2007 const char *mask = NULL;
2008 long prev_dirpos = 0;
2009 uint32_t mode = 0;
2010 char *fname = NULL;
2011 struct smb_filename *smb_fname = NULL;
2012 struct smbd_dirptr_lanman2_state state;
2013 bool ok;
2014 uint64_t last_entry_off = 0;
2015 NTSTATUS status;
2016 enum mangled_names_options mangled_names;
2017 bool marshall_with_83_names;
2019 mangled_names = lp_mangled_names(conn->params);
2021 ZERO_STRUCT(state);
2022 state.conn = conn;
2023 state.info_level = info_level;
2024 if (mangled_names != MANGLED_NAMES_NO) {
2025 state.check_mangled_names = true;
2027 state.has_wild = dptr_has_wild(dirptr);
2028 state.got_exact_match = false;
2029 state.case_sensitive = dptr_case_sensitive(dirptr);
2031 *got_exact_match = false;
2033 p = strrchr_m(path_mask,'/');
2034 if(p != NULL) {
2035 if(p[1] == '\0') {
2036 mask = "*.*";
2037 } else {
2038 mask = p+1;
2040 } else {
2041 mask = path_mask;
2044 ok = smbd_dirptr_get_entry(ctx,
2045 dirptr,
2046 mask,
2047 dirtype,
2048 dont_descend,
2049 ask_sharemode,
2050 get_dosmode,
2051 smbd_dirptr_lanman2_match_fn,
2052 smbd_dirptr_lanman2_mode_fn,
2053 &state,
2054 &fname,
2055 &smb_fname,
2056 &mode,
2057 &prev_dirpos);
2058 if (!ok) {
2059 return NT_STATUS_END_OF_FILE;
2062 *got_exact_match = state.got_exact_match;
2064 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2066 status = smbd_marshall_dir_entry(ctx,
2067 conn,
2068 flags2,
2069 info_level,
2070 name_list,
2071 marshall_with_83_names,
2072 requires_resume_key,
2073 mode,
2074 fname,
2075 smb_fname,
2076 space_remaining,
2077 align,
2078 do_pad,
2079 base_data,
2080 ppdata,
2081 end_data,
2082 &last_entry_off);
2083 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2084 DEBUG(1,("Conversion error: illegal character: %s\n",
2085 smb_fname_str_dbg(smb_fname)));
2088 if (file_id != NULL) {
2089 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2092 if (!NT_STATUS_IS_OK(status) &&
2093 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2095 TALLOC_FREE(smb_fname);
2096 TALLOC_FREE(fname);
2097 return status;
2100 if (_smb_fname != NULL) {
2102 * smb_fname is already talloc'ed off ctx.
2103 * We just need to make sure we don't return
2104 * any stream_name, and replace base_name
2105 * with fname in case base_name got mangled.
2106 * This allows us to preserve any smb_fname->fsp
2107 * for asynchronous handle lookups.
2109 TALLOC_FREE(smb_fname->stream_name);
2110 TALLOC_FREE(smb_fname->base_name);
2111 smb_fname->base_name = talloc_strdup(smb_fname, fname);
2113 if (smb_fname->base_name == NULL) {
2114 TALLOC_FREE(smb_fname);
2115 TALLOC_FREE(fname);
2116 return NT_STATUS_NO_MEMORY;
2118 *_smb_fname = smb_fname;
2119 } else {
2120 TALLOC_FREE(smb_fname);
2122 TALLOC_FREE(fname);
2124 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2125 dptr_SeekDir(dirptr, prev_dirpos);
2126 return status;
2129 *_last_entry_off = last_entry_off;
2130 return NT_STATUS_OK;
2133 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
2135 const struct loadparm_substitution *lp_sub =
2136 loadparm_s3_global_substitution();
2138 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
2139 return objid;
2142 static void samba_extended_info_version(struct smb_extended_info *extended_info)
2144 SMB_ASSERT(extended_info != NULL);
2146 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
2147 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
2148 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
2149 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
2150 #ifdef SAMBA_VERSION_REVISION
2151 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
2152 #endif
2153 extended_info->samba_subversion = 0;
2154 #ifdef SAMBA_VERSION_RC_RELEASE
2155 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
2156 #else
2157 #ifdef SAMBA_VERSION_PRE_RELEASE
2158 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
2159 #endif
2160 #endif
2161 #ifdef SAMBA_VERSION_VENDOR_PATCH
2162 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
2163 #endif
2164 extended_info->samba_gitcommitdate = 0;
2165 #ifdef SAMBA_VERSION_COMMIT_TIME
2166 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
2167 #endif
2169 memset(extended_info->samba_version_string, 0,
2170 sizeof(extended_info->samba_version_string));
2172 snprintf (extended_info->samba_version_string,
2173 sizeof(extended_info->samba_version_string),
2174 "%s", samba_version_string());
2177 static bool fsinfo_unix_valid_level(connection_struct *conn,
2178 uint16_t info_level)
2180 if (conn->sconn->using_smb2 &&
2181 lp_smb3_unix_extensions() &&
2182 info_level == SMB2_FS_POSIX_INFORMATION_INTERNAL) {
2183 return true;
2185 #if defined(SMB1SERVER)
2186 if (lp_smb1_unix_extensions() &&
2187 info_level == SMB_QUERY_POSIX_FS_INFO) {
2188 return true;
2190 #endif
2191 return false;
2194 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
2195 connection_struct *conn,
2196 TALLOC_CTX *mem_ctx,
2197 uint16_t info_level,
2198 uint16_t flags2,
2199 unsigned int max_data_bytes,
2200 size_t *fixed_portion,
2201 struct smb_filename *fname,
2202 char **ppdata,
2203 int *ret_data_len)
2205 const struct loadparm_substitution *lp_sub =
2206 loadparm_s3_global_substitution();
2207 char *pdata, *end_data;
2208 int data_len = 0;
2209 size_t len = 0;
2210 const char *vname = volume_label(talloc_tos(), SNUM(conn));
2211 int snum = SNUM(conn);
2212 const char *fstype = lp_fstype(SNUM(conn));
2213 const char *filename = NULL;
2214 const uint64_t bytes_per_sector = 512;
2215 uint32_t additional_flags = 0;
2216 struct smb_filename smb_fname;
2217 SMB_STRUCT_STAT st;
2218 NTSTATUS status = NT_STATUS_OK;
2219 uint64_t df_ret;
2220 uint32_t serial;
2222 if (fname == NULL || fname->base_name == NULL) {
2223 filename = ".";
2224 } else {
2225 filename = fname->base_name;
2228 if (IS_IPC(conn)) {
2229 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
2230 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
2231 "info level (0x%x) on IPC$.\n",
2232 (unsigned int)info_level));
2233 return NT_STATUS_ACCESS_DENIED;
2237 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
2239 smb_fname = (struct smb_filename) {
2240 .base_name = discard_const_p(char, filename),
2241 .flags = fname ? fname->flags : 0,
2242 .twrp = fname ? fname->twrp : 0,
2245 if(info_level != SMB_FS_QUOTA_INFORMATION
2246 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
2247 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
2248 return map_nt_error_from_unix(errno);
2251 st = smb_fname.st;
2253 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2254 return NT_STATUS_INVALID_PARAMETER;
2257 *ppdata = (char *)SMB_REALLOC(
2258 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2259 if (*ppdata == NULL) {
2260 return NT_STATUS_NO_MEMORY;
2263 pdata = *ppdata;
2264 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2265 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2267 *fixed_portion = 0;
2269 switch (info_level) {
2270 case SMB_INFO_ALLOCATION:
2272 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2273 data_len = 18;
2274 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2275 &dfree, &dsize);
2276 if (df_ret == (uint64_t)-1) {
2277 return map_nt_error_from_unix(errno);
2280 block_size = lp_block_size(snum);
2281 if (bsize < block_size) {
2282 uint64_t factor = block_size/bsize;
2283 bsize = block_size;
2284 dsize /= factor;
2285 dfree /= factor;
2287 if (bsize > block_size) {
2288 uint64_t factor = bsize/block_size;
2289 bsize = block_size;
2290 dsize *= factor;
2291 dfree *= factor;
2293 sectors_per_unit = bsize/bytes_per_sector;
2295 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
2296 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
2297 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2300 * For large drives, return max values and not modulo.
2302 dsize = MIN(dsize, UINT32_MAX);
2303 dfree = MIN(dfree, UINT32_MAX);
2305 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
2306 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
2307 SIVAL(pdata,l1_cUnit,dsize);
2308 SIVAL(pdata,l1_cUnitAvail,dfree);
2309 SSVAL(pdata,l1_cbSector,bytes_per_sector);
2310 break;
2313 case SMB_INFO_VOLUME:
2314 /* Return volume name */
2316 * Add volume serial number - hash of a combination of
2317 * the called hostname and the service name.
2319 serial = generate_volume_serial_number(lp_sub, snum);
2320 SIVAL(pdata,0,serial);
2322 * Win2k3 and previous mess this up by sending a name length
2323 * one byte short. I believe only older clients (OS/2 Win9x) use
2324 * this call so try fixing this by adding a terminating null to
2325 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
2327 status = srvstr_push(
2328 pdata, flags2,
2329 pdata+l2_vol_szVolLabel, vname,
2330 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
2331 STR_NOALIGN|STR_TERMINATE, &len);
2332 if (!NT_STATUS_IS_OK(status)) {
2333 return status;
2335 SCVAL(pdata,l2_vol_cch,len);
2336 data_len = l2_vol_szVolLabel + len;
2337 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, "
2338 "name = %s serial = 0x%04"PRIx32"\n",
2339 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
2340 (unsigned)len, vname, serial));
2341 break;
2343 case SMB_QUERY_FS_ATTRIBUTE_INFO:
2344 case SMB_FS_ATTRIBUTE_INFORMATION:
2346 additional_flags = 0;
2347 #if defined(HAVE_SYS_QUOTAS)
2348 additional_flags |= FILE_VOLUME_QUOTAS;
2349 #endif
2351 if(lp_nt_acl_support(SNUM(conn))) {
2352 additional_flags |= FILE_PERSISTENT_ACLS;
2355 /* Capabilities are filled in at connection time through STATVFS call */
2356 additional_flags |= conn->fs_capabilities;
2357 additional_flags |= lp_parm_int(conn->params->service,
2358 "share", "fake_fscaps",
2361 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
2362 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
2363 additional_flags); /* FS ATTRIBUTES */
2365 SIVAL(pdata,4,255); /* Max filename component length */
2366 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
2367 and will think we can't do long filenames */
2368 status = srvstr_push(pdata, flags2, pdata+12, fstype,
2369 PTR_DIFF(end_data, pdata+12),
2370 STR_UNICODE, &len);
2371 if (!NT_STATUS_IS_OK(status)) {
2372 return status;
2374 SIVAL(pdata,8,len);
2375 data_len = 12 + len;
2376 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
2377 /* the client only requested a portion of the
2378 file system name */
2379 data_len = max_data_bytes;
2380 status = STATUS_BUFFER_OVERFLOW;
2382 *fixed_portion = 16;
2383 break;
2385 case SMB_QUERY_FS_LABEL_INFO:
2386 case SMB_FS_LABEL_INFORMATION:
2387 status = srvstr_push(pdata, flags2, pdata+4, vname,
2388 PTR_DIFF(end_data, pdata+4), 0, &len);
2389 if (!NT_STATUS_IS_OK(status)) {
2390 return status;
2392 data_len = 4 + len;
2393 SIVAL(pdata,0,len);
2394 break;
2396 case SMB_QUERY_FS_VOLUME_INFO:
2397 case SMB_FS_VOLUME_INFORMATION:
2398 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,
2399 pdata, &st.st_ex_btime);
2401 * Add volume serial number - hash of a combination of
2402 * the called hostname and the service name.
2404 serial = generate_volume_serial_number(lp_sub, snum);
2405 SIVAL(pdata,8,serial);
2407 /* Max label len is 32 characters. */
2408 status = srvstr_push(pdata, flags2, pdata+18, vname,
2409 PTR_DIFF(end_data, pdata+18),
2410 STR_UNICODE, &len);
2411 if (!NT_STATUS_IS_OK(status)) {
2412 return status;
2414 SIVAL(pdata,12,len);
2415 data_len = 18+len;
2417 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO "
2418 "namelen = %d, vol=%s serv=%s "
2419 "serial=0x%04"PRIx32"\n",
2420 (int)strlen(vname),vname,
2421 lp_servicename(talloc_tos(), lp_sub, snum),
2422 serial));
2423 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
2424 /* the client only requested a portion of the
2425 volume label */
2426 data_len = max_data_bytes;
2427 status = STATUS_BUFFER_OVERFLOW;
2429 *fixed_portion = 24;
2430 break;
2432 case SMB_QUERY_FS_SIZE_INFO:
2433 case SMB_FS_SIZE_INFORMATION:
2435 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2436 data_len = 24;
2437 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2438 &dfree, &dsize);
2439 if (df_ret == (uint64_t)-1) {
2440 return map_nt_error_from_unix(errno);
2442 block_size = lp_block_size(snum);
2443 if (bsize < block_size) {
2444 uint64_t factor = block_size/bsize;
2445 bsize = block_size;
2446 dsize /= factor;
2447 dfree /= factor;
2449 if (bsize > block_size) {
2450 uint64_t factor = bsize/block_size;
2451 bsize = block_size;
2452 dsize *= factor;
2453 dfree *= factor;
2455 sectors_per_unit = bsize/bytes_per_sector;
2456 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2457 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2458 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2459 SBIG_UINT(pdata,0,dsize);
2460 SBIG_UINT(pdata,8,dfree);
2461 SIVAL(pdata,16,sectors_per_unit);
2462 SIVAL(pdata,20,bytes_per_sector);
2463 *fixed_portion = 24;
2464 break;
2467 case SMB_FS_FULL_SIZE_INFORMATION:
2469 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
2470 data_len = 32;
2471 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
2472 &dfree, &dsize);
2473 if (df_ret == (uint64_t)-1) {
2474 return map_nt_error_from_unix(errno);
2476 block_size = lp_block_size(snum);
2477 if (bsize < block_size) {
2478 uint64_t factor = block_size/bsize;
2479 bsize = block_size;
2480 dsize /= factor;
2481 dfree /= factor;
2483 if (bsize > block_size) {
2484 uint64_t factor = bsize/block_size;
2485 bsize = block_size;
2486 dsize *= factor;
2487 dfree *= factor;
2489 sectors_per_unit = bsize/bytes_per_sector;
2490 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
2491 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
2492 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
2493 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
2494 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
2495 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
2496 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
2497 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
2498 *fixed_portion = 32;
2499 break;
2502 case SMB_QUERY_FS_DEVICE_INFO:
2503 case SMB_FS_DEVICE_INFORMATION:
2505 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
2507 if (!CAN_WRITE(conn)) {
2508 characteristics |= FILE_READ_ONLY_DEVICE;
2510 data_len = 8;
2511 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
2512 SIVAL(pdata,4,characteristics);
2513 *fixed_portion = 8;
2514 break;
2517 #ifdef HAVE_SYS_QUOTAS
2518 case SMB_FS_QUOTA_INFORMATION:
2520 * what we have to send --metze:
2522 * Unknown1: 24 NULL bytes
2523 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
2524 * Hard Quota Limit: 8 bytes seems like uint64_t or so
2525 * Quota Flags: 2 byte :
2526 * Unknown3: 6 NULL bytes
2528 * 48 bytes total
2530 * details for Quota Flags:
2532 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
2533 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
2534 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
2535 * 0x0001 Enable Quotas: enable quota for this fs
2539 /* we need to fake up a fsp here,
2540 * because its not send in this call
2542 files_struct fsp;
2543 SMB_NTQUOTA_STRUCT quotas;
2545 ZERO_STRUCT(fsp);
2546 ZERO_STRUCT(quotas);
2548 fsp.conn = conn;
2549 fsp.fnum = FNUM_FIELD_INVALID;
2551 /* access check */
2552 if (get_current_uid(conn) != 0) {
2553 DEBUG(0,("get_user_quota: access_denied "
2554 "service [%s] user [%s]\n",
2555 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2556 conn->session_info->unix_info->unix_name));
2557 return NT_STATUS_ACCESS_DENIED;
2560 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
2561 NULL, &quotas);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2564 return status;
2567 data_len = 48;
2569 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
2570 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2572 /* Unknown1 24 NULL bytes*/
2573 SBIG_UINT(pdata,0,(uint64_t)0);
2574 SBIG_UINT(pdata,8,(uint64_t)0);
2575 SBIG_UINT(pdata,16,(uint64_t)0);
2577 /* Default Soft Quota 8 bytes */
2578 SBIG_UINT(pdata,24,quotas.softlim);
2580 /* Default Hard Quota 8 bytes */
2581 SBIG_UINT(pdata,32,quotas.hardlim);
2583 /* Quota flag 2 bytes */
2584 SSVAL(pdata,40,quotas.qflags);
2586 /* Unknown3 6 NULL bytes */
2587 SSVAL(pdata,42,0);
2588 SIVAL(pdata,44,0);
2590 break;
2592 #endif /* HAVE_SYS_QUOTAS */
2593 case SMB_FS_OBJECTID_INFORMATION:
2595 unsigned char objid[16];
2596 struct smb_extended_info extended_info;
2597 memcpy(pdata,create_volume_objectid(conn, objid),16);
2598 samba_extended_info_version (&extended_info);
2599 SIVAL(pdata,16,extended_info.samba_magic);
2600 SIVAL(pdata,20,extended_info.samba_version);
2601 SIVAL(pdata,24,extended_info.samba_subversion);
2602 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
2603 memcpy(pdata+36,extended_info.samba_version_string,28);
2604 data_len = 64;
2605 break;
2608 case SMB_FS_SECTOR_SIZE_INFORMATION:
2610 data_len = 28;
2612 * These values match a physical Windows Server 2012
2613 * share backed by NTFS atop spinning rust.
2615 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
2616 /* logical_bytes_per_sector */
2617 SIVAL(pdata, 0, bytes_per_sector);
2618 /* phys_bytes_per_sector_atomic */
2619 SIVAL(pdata, 4, bytes_per_sector);
2620 /* phys_bytes_per_sector_perf */
2621 SIVAL(pdata, 8, bytes_per_sector);
2622 /* fs_effective_phys_bytes_per_sector_atomic */
2623 SIVAL(pdata, 12, bytes_per_sector);
2624 /* flags */
2625 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
2626 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
2627 /* byte_off_sector_align */
2628 SIVAL(pdata, 20, 0);
2629 /* byte_off_partition_align */
2630 SIVAL(pdata, 24, 0);
2631 *fixed_portion = 28;
2632 break;
2636 #if defined(WITH_SMB1SERVER)
2638 * Query the version and capabilities of the CIFS UNIX extensions
2639 * in use.
2642 case SMB_QUERY_CIFS_UNIX_INFO:
2644 bool large_write = lp_min_receive_file_size() &&
2645 !smb1_srv_is_signing_active(xconn);
2646 bool large_read = !smb1_srv_is_signing_active(xconn);
2647 int encrypt_caps = 0;
2649 if (!lp_smb1_unix_extensions()) {
2650 return NT_STATUS_INVALID_LEVEL;
2653 switch (conn->encrypt_level) {
2654 case SMB_SIGNING_OFF:
2655 encrypt_caps = 0;
2656 break;
2657 case SMB_SIGNING_DESIRED:
2658 case SMB_SIGNING_IF_REQUIRED:
2659 case SMB_SIGNING_DEFAULT:
2660 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
2661 break;
2662 case SMB_SIGNING_REQUIRED:
2663 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
2664 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
2665 large_write = false;
2666 large_read = false;
2667 break;
2670 data_len = 12;
2671 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
2672 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
2674 /* We have POSIX ACLs, pathname, encryption,
2675 * large read/write, and locking capability. */
2677 SBIG_UINT(pdata,4,((uint64_t)(
2678 CIFS_UNIX_POSIX_ACLS_CAP|
2679 CIFS_UNIX_POSIX_PATHNAMES_CAP|
2680 CIFS_UNIX_FCNTL_LOCKS_CAP|
2681 CIFS_UNIX_EXTATTR_CAP|
2682 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
2683 encrypt_caps|
2684 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
2685 (large_write ?
2686 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
2687 break;
2689 #endif
2691 case SMB_QUERY_POSIX_FS_INFO:
2692 case SMB2_FS_POSIX_INFORMATION_INTERNAL:
2694 int rc;
2695 struct vfs_statvfs_struct svfs;
2697 if (!fsinfo_unix_valid_level(conn, info_level)) {
2698 return NT_STATUS_INVALID_LEVEL;
2701 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
2703 if (!rc) {
2704 data_len = 56;
2705 SIVAL(pdata,0,svfs.OptimalTransferSize);
2706 SIVAL(pdata,4,svfs.BlockSize);
2707 SBIG_UINT(pdata,8,svfs.TotalBlocks);
2708 SBIG_UINT(pdata,16,svfs.BlocksAvail);
2709 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
2710 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
2711 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
2712 SBIG_UINT(pdata,48,svfs.FsIdentifier);
2713 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
2714 #ifdef EOPNOTSUPP
2715 } else if (rc == EOPNOTSUPP) {
2716 return NT_STATUS_INVALID_LEVEL;
2717 #endif /* EOPNOTSUPP */
2718 } else {
2719 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2720 return NT_STATUS_DOS(ERRSRV, ERRerror);
2722 break;
2725 case SMB_QUERY_POSIX_WHOAMI:
2727 uint32_t flags = 0;
2728 uint32_t sid_bytes;
2729 uint32_t i;
2731 if (!lp_smb1_unix_extensions()) {
2732 return NT_STATUS_INVALID_LEVEL;
2735 if (max_data_bytes < 40) {
2736 return NT_STATUS_BUFFER_TOO_SMALL;
2739 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
2740 flags |= SMB_WHOAMI_GUEST;
2743 /* NOTE: 8 bytes for UID/GID, irrespective of native
2744 * platform size. This matches
2745 * SMB_QUERY_FILE_UNIX_BASIC and friends.
2747 data_len = 4 /* flags */
2748 + 4 /* flag mask */
2749 + 8 /* uid */
2750 + 8 /* gid */
2751 + 4 /* ngroups */
2752 + 4 /* num_sids */
2753 + 4 /* SID bytes */
2754 + 4 /* pad/reserved */
2755 + (conn->session_info->unix_token->ngroups * 8)
2756 /* groups list */
2757 + (conn->session_info->security_token->num_sids *
2758 SID_MAX_SIZE)
2759 /* SID list */;
2761 SIVAL(pdata, 0, flags);
2762 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
2763 SBIG_UINT(pdata, 8,
2764 (uint64_t)conn->session_info->unix_token->uid);
2765 SBIG_UINT(pdata, 16,
2766 (uint64_t)conn->session_info->unix_token->gid);
2769 if (data_len >= max_data_bytes) {
2770 /* Potential overflow, skip the GIDs and SIDs. */
2772 SIVAL(pdata, 24, 0); /* num_groups */
2773 SIVAL(pdata, 28, 0); /* num_sids */
2774 SIVAL(pdata, 32, 0); /* num_sid_bytes */
2775 SIVAL(pdata, 36, 0); /* reserved */
2777 data_len = 40;
2778 break;
2781 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
2782 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
2784 /* We walk the SID list twice, but this call is fairly
2785 * infrequent, and I don't expect that it's performance
2786 * sensitive -- jpeach
2788 for (i = 0, sid_bytes = 0;
2789 i < conn->session_info->security_token->num_sids; ++i) {
2790 sid_bytes += ndr_size_dom_sid(
2791 &conn->session_info->security_token->sids[i],
2795 /* SID list byte count */
2796 SIVAL(pdata, 32, sid_bytes);
2798 /* 4 bytes pad/reserved - must be zero */
2799 SIVAL(pdata, 36, 0);
2800 data_len = 40;
2802 /* GID list */
2803 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
2804 SBIG_UINT(pdata, data_len,
2805 (uint64_t)conn->session_info->unix_token->groups[i]);
2806 data_len += 8;
2809 /* SID list */
2810 for (i = 0;
2811 i < conn->session_info->security_token->num_sids; ++i) {
2812 int sid_len = ndr_size_dom_sid(
2813 &conn->session_info->security_token->sids[i],
2816 sid_linearize((uint8_t *)(pdata + data_len),
2817 sid_len,
2818 &conn->session_info->security_token->sids[i]);
2819 data_len += sid_len;
2822 break;
2825 case SMB_MAC_QUERY_FS_INFO:
2827 * Thursby MAC extension... ONLY on NTFS filesystems
2828 * once we do streams then we don't need this
2830 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
2831 data_len = 88;
2832 SIVAL(pdata,84,0x100); /* Don't support mac... */
2833 break;
2836 FALL_THROUGH;
2837 default:
2838 return NT_STATUS_INVALID_LEVEL;
2841 *ret_data_len = data_len;
2842 return status;
2845 NTSTATUS smb_set_fsquota(connection_struct *conn,
2846 struct smb_request *req,
2847 files_struct *fsp,
2848 const DATA_BLOB *qdata)
2850 const struct loadparm_substitution *lp_sub =
2851 loadparm_s3_global_substitution();
2852 NTSTATUS status;
2853 SMB_NTQUOTA_STRUCT quotas;
2855 ZERO_STRUCT(quotas);
2857 /* access check */
2858 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
2859 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
2860 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
2861 conn->session_info->unix_info->unix_name));
2862 return NT_STATUS_ACCESS_DENIED;
2865 if (!check_fsp_ntquota_handle(conn, req,
2866 fsp)) {
2867 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
2868 return NT_STATUS_INVALID_HANDLE;
2871 /* note: normally there're 48 bytes,
2872 * but we didn't use the last 6 bytes for now
2873 * --metze
2875 if (qdata->length < 42) {
2876 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
2877 (unsigned int)qdata->length));
2878 return NT_STATUS_INVALID_PARAMETER;
2881 /* unknown_1 24 NULL bytes in pdata*/
2883 /* the soft quotas 8 bytes (uint64_t)*/
2884 quotas.softlim = BVAL(qdata->data,24);
2886 /* the hard quotas 8 bytes (uint64_t)*/
2887 quotas.hardlim = BVAL(qdata->data,32);
2889 /* quota_flags 2 bytes **/
2890 quotas.qflags = SVAL(qdata->data,40);
2892 /* unknown_2 6 NULL bytes follow*/
2894 /* now set the quotas */
2895 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
2896 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
2897 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
2898 status = map_nt_error_from_unix(errno);
2899 } else {
2900 status = NT_STATUS_OK;
2902 return status;
2905 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
2906 struct smb_request *req,
2907 TALLOC_CTX *mem_ctx,
2908 uint16_t info_level,
2909 files_struct *fsp,
2910 const DATA_BLOB *pdata)
2912 switch (info_level) {
2913 case SMB_FS_QUOTA_INFORMATION:
2915 return smb_set_fsquota(conn,
2916 req,
2917 fsp,
2918 pdata);
2921 default:
2922 break;
2924 return NT_STATUS_INVALID_LEVEL;
2927 #if defined(HAVE_POSIX_ACLS)
2928 /****************************************************************************
2929 Utility function to count the number of entries in a POSIX acl.
2930 ****************************************************************************/
2932 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
2934 unsigned int ace_count = 0;
2935 int entry_id = SMB_ACL_FIRST_ENTRY;
2936 SMB_ACL_ENTRY_T entry;
2938 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2939 /* get_next... */
2940 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2941 entry_id = SMB_ACL_NEXT_ENTRY;
2943 ace_count++;
2945 return ace_count;
2948 /****************************************************************************
2949 Utility function to marshall a POSIX acl into wire format.
2950 ****************************************************************************/
2952 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
2954 int entry_id = SMB_ACL_FIRST_ENTRY;
2955 SMB_ACL_ENTRY_T entry;
2957 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
2958 SMB_ACL_TAG_T tagtype;
2959 SMB_ACL_PERMSET_T permset;
2960 unsigned char perms = 0;
2961 unsigned int own_grp;
2963 /* get_next... */
2964 if (entry_id == SMB_ACL_FIRST_ENTRY) {
2965 entry_id = SMB_ACL_NEXT_ENTRY;
2968 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
2969 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
2970 return False;
2973 if (sys_acl_get_permset(entry, &permset) == -1) {
2974 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
2975 return False;
2978 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
2979 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
2980 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
2982 SCVAL(pdata,1,perms);
2984 switch (tagtype) {
2985 case SMB_ACL_USER_OBJ:
2986 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
2987 own_grp = (unsigned int)pst->st_ex_uid;
2988 SIVAL(pdata,2,own_grp);
2989 SIVAL(pdata,6,0);
2990 break;
2991 case SMB_ACL_USER:
2993 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
2994 if (!puid) {
2995 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
2996 return False;
2998 own_grp = (unsigned int)*puid;
2999 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
3000 SIVAL(pdata,2,own_grp);
3001 SIVAL(pdata,6,0);
3002 break;
3004 case SMB_ACL_GROUP_OBJ:
3005 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
3006 own_grp = (unsigned int)pst->st_ex_gid;
3007 SIVAL(pdata,2,own_grp);
3008 SIVAL(pdata,6,0);
3009 break;
3010 case SMB_ACL_GROUP:
3012 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
3013 if (!pgid) {
3014 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
3015 return False;
3017 own_grp = (unsigned int)*pgid;
3018 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
3019 SIVAL(pdata,2,own_grp);
3020 SIVAL(pdata,6,0);
3021 break;
3023 case SMB_ACL_MASK:
3024 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
3025 SIVAL(pdata,2,0xFFFFFFFF);
3026 SIVAL(pdata,6,0xFFFFFFFF);
3027 break;
3028 case SMB_ACL_OTHER:
3029 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
3030 SIVAL(pdata,2,0xFFFFFFFF);
3031 SIVAL(pdata,6,0xFFFFFFFF);
3032 break;
3033 default:
3034 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
3035 return False;
3037 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
3040 return True;
3042 #endif
3044 /****************************************************************************
3045 Store the FILE_UNIX_BASIC info.
3046 ****************************************************************************/
3048 char *store_file_unix_basic(connection_struct *conn,
3049 char *pdata,
3050 files_struct *fsp,
3051 const SMB_STRUCT_STAT *psbuf)
3053 dev_t devno;
3055 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
3056 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
3058 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
3059 pdata += 8;
3061 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
3062 pdata += 8;
3064 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
3065 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
3066 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
3067 pdata += 24;
3069 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
3070 SIVAL(pdata,4,0);
3071 pdata += 8;
3073 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
3074 SIVAL(pdata,4,0);
3075 pdata += 8;
3077 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
3078 pdata += 4;
3080 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
3081 devno = psbuf->st_ex_rdev;
3082 } else {
3083 devno = psbuf->st_ex_dev;
3086 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
3087 SIVAL(pdata,4,0);
3088 pdata += 8;
3090 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
3091 SIVAL(pdata,4,0);
3092 pdata += 8;
3094 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
3095 pdata += 8;
3097 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
3098 SIVAL(pdata,4,0);
3099 pdata += 8;
3101 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
3102 SIVAL(pdata,4,0);
3103 pdata += 8;
3105 return pdata;
3108 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
3109 * the chflags(2) (or equivalent) flags.
3111 * XXX: this really should be behind the VFS interface. To do this, we would
3112 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
3113 * Each VFS module could then implement its own mapping as appropriate for the
3114 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
3116 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
3117 info2_flags_map[] =
3119 #ifdef UF_NODUMP
3120 { UF_NODUMP, EXT_DO_NOT_BACKUP },
3121 #endif
3123 #ifdef UF_IMMUTABLE
3124 { UF_IMMUTABLE, EXT_IMMUTABLE },
3125 #endif
3127 #ifdef UF_APPEND
3128 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
3129 #endif
3131 #ifdef UF_HIDDEN
3132 { UF_HIDDEN, EXT_HIDDEN },
3133 #endif
3135 /* Do not remove. We need to guarantee that this array has at least one
3136 * entry to build on HP-UX.
3138 { 0, 0 }
3142 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
3143 uint32_t *smb_fflags, uint32_t *smb_fmask)
3145 size_t i;
3147 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3148 *smb_fmask |= info2_flags_map[i].smb_fflag;
3149 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
3150 *smb_fflags |= info2_flags_map[i].smb_fflag;
3155 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
3156 const uint32_t smb_fflags,
3157 const uint32_t smb_fmask,
3158 int *stat_fflags)
3160 uint32_t max_fmask = 0;
3161 size_t i;
3163 *stat_fflags = psbuf->st_ex_flags;
3165 /* For each flags requested in smb_fmask, check the state of the
3166 * corresponding flag in smb_fflags and set or clear the matching
3167 * stat flag.
3170 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
3171 max_fmask |= info2_flags_map[i].smb_fflag;
3172 if (smb_fmask & info2_flags_map[i].smb_fflag) {
3173 if (smb_fflags & info2_flags_map[i].smb_fflag) {
3174 *stat_fflags |= info2_flags_map[i].stat_fflag;
3175 } else {
3176 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
3181 /* If smb_fmask is asking to set any bits that are not supported by
3182 * our flag mappings, we should fail.
3184 if ((smb_fmask & max_fmask) != smb_fmask) {
3185 return False;
3188 return True;
3192 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
3193 * of file flags and birth (create) time.
3195 char *store_file_unix_basic_info2(connection_struct *conn,
3196 char *pdata,
3197 files_struct *fsp,
3198 const SMB_STRUCT_STAT *psbuf)
3200 uint32_t file_flags = 0;
3201 uint32_t flags_mask = 0;
3203 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
3205 /* Create (birth) time 64 bit */
3206 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
3207 pdata += 8;
3209 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
3210 SIVAL(pdata, 0, file_flags); /* flags */
3211 SIVAL(pdata, 4, flags_mask); /* mask */
3212 pdata += 8;
3214 return pdata;
3217 static NTSTATUS marshall_stream_info(unsigned int num_streams,
3218 const struct stream_struct *streams,
3219 char *data,
3220 unsigned int max_data_bytes,
3221 unsigned int *data_size)
3223 unsigned int i;
3224 unsigned int ofs = 0;
3226 if (max_data_bytes < 32) {
3227 return NT_STATUS_INFO_LENGTH_MISMATCH;
3230 for (i = 0; i < num_streams; i++) {
3231 unsigned int next_offset;
3232 size_t namelen;
3233 smb_ucs2_t *namebuf;
3235 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
3236 streams[i].name, &namelen) ||
3237 namelen <= 2)
3239 return NT_STATUS_INVALID_PARAMETER;
3243 * name_buf is now null-terminated, we need to marshall as not
3244 * terminated
3247 namelen -= 2;
3250 * We cannot overflow ...
3252 if ((ofs + 24 + namelen) > max_data_bytes) {
3253 DEBUG(10, ("refusing to overflow reply at stream %u\n",
3254 i));
3255 TALLOC_FREE(namebuf);
3256 return STATUS_BUFFER_OVERFLOW;
3259 SIVAL(data, ofs+4, namelen);
3260 SOFF_T(data, ofs+8, streams[i].size);
3261 SOFF_T(data, ofs+16, streams[i].alloc_size);
3262 memcpy(data+ofs+24, namebuf, namelen);
3263 TALLOC_FREE(namebuf);
3265 next_offset = ofs + 24 + namelen;
3267 if (i == num_streams-1) {
3268 SIVAL(data, ofs, 0);
3270 else {
3271 unsigned int align = ndr_align_size(next_offset, 8);
3273 if ((next_offset + align) > max_data_bytes) {
3274 DEBUG(10, ("refusing to overflow align "
3275 "reply at stream %u\n",
3276 i));
3277 TALLOC_FREE(namebuf);
3278 return STATUS_BUFFER_OVERFLOW;
3281 memset(data+next_offset, 0, align);
3282 next_offset += align;
3284 SIVAL(data, ofs, next_offset - ofs);
3285 ofs = next_offset;
3288 ofs = next_offset;
3291 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
3293 *data_size = ofs;
3295 return NT_STATUS_OK;
3298 static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
3299 struct smb_request *req,
3300 struct smb_filename *smb_fname,
3301 char *pdata,
3302 unsigned int data_size_in,
3303 unsigned int *pdata_size_out)
3305 NTSTATUS status;
3306 size_t len = 0;
3307 int link_len = 0;
3308 struct smb_filename *parent_fname = NULL;
3309 struct smb_filename *base_name = NULL;
3311 char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
3313 if (!buffer) {
3314 return NT_STATUS_NO_MEMORY;
3317 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
3318 smb_fname_str_dbg(smb_fname));
3320 if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
3321 TALLOC_FREE(buffer);
3322 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
3325 status = parent_pathref(talloc_tos(),
3326 conn->cwd_fsp,
3327 smb_fname,
3328 &parent_fname,
3329 &base_name);
3330 if (!NT_STATUS_IS_OK(status)) {
3331 TALLOC_FREE(buffer);
3332 return status;
3335 link_len = SMB_VFS_READLINKAT(conn,
3336 parent_fname->fsp,
3337 base_name,
3338 buffer,
3339 PATH_MAX);
3341 TALLOC_FREE(parent_fname);
3343 if (link_len == -1) {
3344 TALLOC_FREE(buffer);
3345 return map_nt_error_from_unix(errno);
3348 buffer[link_len] = 0;
3349 status = srvstr_push(pdata,
3350 req->flags2,
3351 pdata,
3352 buffer,
3353 data_size_in,
3354 STR_TERMINATE,
3355 &len);
3356 TALLOC_FREE(buffer);
3357 if (!NT_STATUS_IS_OK(status)) {
3358 return status;
3360 *pdata_size_out = len;
3362 return NT_STATUS_OK;
3365 #if defined(HAVE_POSIX_ACLS)
3366 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
3367 struct smb_request *req,
3368 files_struct *fsp,
3369 struct smb_filename *smb_fname,
3370 char *pdata,
3371 unsigned int data_size_in,
3372 unsigned int *pdata_size_out)
3374 SMB_ACL_T file_acl = NULL;
3375 SMB_ACL_T def_acl = NULL;
3376 uint16_t num_file_acls = 0;
3377 uint16_t num_def_acls = 0;
3378 unsigned int size_needed = 0;
3379 NTSTATUS status;
3380 bool ok;
3381 bool close_fsp = false;
3384 * Ensure we always operate on a file descriptor, not just
3385 * the filename.
3387 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3388 uint32_t access_mask = SEC_STD_READ_CONTROL|
3389 FILE_READ_ATTRIBUTES|
3390 FILE_WRITE_ATTRIBUTES;
3392 status = get_posix_fsp(conn,
3393 req,
3394 smb_fname,
3395 access_mask,
3396 &fsp);
3398 if (!NT_STATUS_IS_OK(status)) {
3399 goto out;
3401 close_fsp = true;
3404 SMB_ASSERT(fsp != NULL);
3406 status = refuse_symlink_fsp(fsp);
3407 if (!NT_STATUS_IS_OK(status)) {
3408 goto out;
3411 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp, SMB_ACL_TYPE_ACCESS,
3412 talloc_tos());
3414 if (file_acl == NULL && no_acl_syscall_error(errno)) {
3415 DBG_INFO("ACLs not implemented on "
3416 "filesystem containing %s\n",
3417 fsp_str_dbg(fsp));
3418 status = NT_STATUS_NOT_IMPLEMENTED;
3419 goto out;
3422 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
3424 * We can only have default POSIX ACLs on
3425 * directories.
3427 if (!fsp->fsp_flags.is_directory) {
3428 DBG_INFO("Non-directory open %s\n",
3429 fsp_str_dbg(fsp));
3430 status = NT_STATUS_INVALID_HANDLE;
3431 goto out;
3433 def_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
3434 SMB_ACL_TYPE_DEFAULT,
3435 talloc_tos());
3436 def_acl = free_empty_sys_acl(conn, def_acl);
3439 num_file_acls = count_acl_entries(conn, file_acl);
3440 num_def_acls = count_acl_entries(conn, def_acl);
3442 /* Wrap checks. */
3443 if (num_file_acls + num_def_acls < num_file_acls) {
3444 status = NT_STATUS_INVALID_PARAMETER;
3445 goto out;
3448 size_needed = num_file_acls + num_def_acls;
3451 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
3452 * than UINT_MAX, so check by division.
3454 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
3455 status = NT_STATUS_INVALID_PARAMETER;
3456 goto out;
3459 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
3460 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
3461 status = NT_STATUS_INVALID_PARAMETER;
3462 goto out;
3464 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
3466 if ( data_size_in < size_needed) {
3467 DBG_INFO("data_size too small (%u) need %u\n",
3468 data_size_in,
3469 size_needed);
3470 status = NT_STATUS_BUFFER_TOO_SMALL;
3471 goto out;
3474 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
3475 SSVAL(pdata,2,num_file_acls);
3476 SSVAL(pdata,4,num_def_acls);
3477 pdata += SMB_POSIX_ACL_HEADER_SIZE;
3479 ok = marshall_posix_acl(conn,
3480 pdata,
3481 &fsp->fsp_name->st,
3482 file_acl);
3483 if (!ok) {
3484 status = NT_STATUS_INTERNAL_ERROR;
3485 goto out;
3487 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
3489 ok = marshall_posix_acl(conn,
3490 pdata,
3491 &fsp->fsp_name->st,
3492 def_acl);
3493 if (!ok) {
3494 status = NT_STATUS_INTERNAL_ERROR;
3495 goto out;
3498 *pdata_size_out = size_needed;
3499 status = NT_STATUS_OK;
3501 out:
3503 if (close_fsp) {
3505 * Ensure the stat struct in smb_fname is up to
3506 * date. Structure copy.
3508 smb_fname->st = fsp->fsp_name->st;
3509 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
3512 TALLOC_FREE(file_acl);
3513 TALLOC_FREE(def_acl);
3514 return status;
3516 #endif
3518 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
3519 TALLOC_CTX *mem_ctx,
3520 struct smb_request *req,
3521 uint16_t info_level,
3522 files_struct *fsp,
3523 struct smb_filename *smb_fname,
3524 bool delete_pending,
3525 struct timespec write_time_ts,
3526 struct ea_list *ea_list,
3527 int lock_data_count,
3528 char *lock_data,
3529 uint16_t flags2,
3530 unsigned int max_data_bytes,
3531 size_t *fixed_portion,
3532 char **ppdata,
3533 unsigned int *pdata_size)
3535 char *pdata = *ppdata;
3536 char *dstart, *dend;
3537 unsigned int data_size;
3538 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
3539 time_t create_time, mtime, atime, c_time;
3540 SMB_STRUCT_STAT *psbuf = NULL;
3541 SMB_STRUCT_STAT *base_sp = NULL;
3542 char *p;
3543 char *base_name;
3544 char *dos_fname;
3545 int mode;
3546 int nlink;
3547 NTSTATUS status;
3548 uint64_t file_size = 0;
3549 uint64_t pos = 0;
3550 uint64_t allocation_size = 0;
3551 uint64_t file_id = 0;
3552 uint32_t access_mask = 0;
3553 size_t len = 0;
3555 if (INFO_LEVEL_IS_UNIX(info_level)) {
3556 bool ok = false;
3558 if (lp_smb1_unix_extensions() && req->posix_pathnames) {
3559 DBG_DEBUG("SMB1 unix extensions activated\n");
3560 ok = true;
3563 if (lp_smb3_unix_extensions() &&
3564 (fsp != NULL) &&
3565 (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
3566 DBG_DEBUG("SMB2 posix open\n");
3567 ok = true;
3570 if (!ok) {
3571 return NT_STATUS_INVALID_LEVEL;
3575 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
3576 smb_fname_str_dbg(smb_fname),
3577 fsp_fnum_dbg(fsp),
3578 info_level, max_data_bytes));
3581 * In case of querying a symlink in POSIX context,
3582 * fsp will be NULL. fdos_mode() deals with it.
3584 if (fsp != NULL) {
3585 smb_fname = fsp->fsp_name;
3587 mode = fdos_mode(fsp);
3588 psbuf = &smb_fname->st;
3590 if (fsp != NULL) {
3591 base_sp = fsp->base_fsp ?
3592 &fsp->base_fsp->fsp_name->st :
3593 &fsp->fsp_name->st;
3594 } else {
3595 base_sp = &smb_fname->st;
3598 nlink = psbuf->st_ex_nlink;
3600 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
3601 nlink = 1;
3604 if ((nlink > 0) && delete_pending) {
3605 nlink -= 1;
3608 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3609 return NT_STATUS_INVALID_PARAMETER;
3612 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
3613 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
3614 if (*ppdata == NULL) {
3615 return NT_STATUS_NO_MEMORY;
3617 pdata = *ppdata;
3618 dstart = pdata;
3619 dend = dstart + data_size - 1;
3621 if (!is_omit_timespec(&write_time_ts) &&
3622 !INFO_LEVEL_IS_UNIX(info_level))
3624 update_stat_ex_mtime(psbuf, write_time_ts);
3627 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
3628 mtime_ts = psbuf->st_ex_mtime;
3629 atime_ts = psbuf->st_ex_atime;
3630 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
3632 if (lp_dos_filetime_resolution(SNUM(conn))) {
3633 dos_filetime_timespec(&create_time_ts);
3634 dos_filetime_timespec(&mtime_ts);
3635 dos_filetime_timespec(&atime_ts);
3636 dos_filetime_timespec(&ctime_ts);
3639 create_time = convert_timespec_to_time_t(create_time_ts);
3640 mtime = convert_timespec_to_time_t(mtime_ts);
3641 atime = convert_timespec_to_time_t(atime_ts);
3642 c_time = convert_timespec_to_time_t(ctime_ts);
3644 p = strrchr_m(smb_fname->base_name,'/');
3645 if (!p)
3646 base_name = smb_fname->base_name;
3647 else
3648 base_name = p+1;
3650 /* NT expects the name to be in an exact form of the *full*
3651 filename. See the trans2 torture test */
3652 if (ISDOT(base_name)) {
3653 dos_fname = talloc_strdup(mem_ctx, "\\");
3654 if (!dos_fname) {
3655 return NT_STATUS_NO_MEMORY;
3657 } else {
3658 dos_fname = talloc_asprintf(mem_ctx,
3659 "\\%s",
3660 smb_fname->base_name);
3661 if (!dos_fname) {
3662 return NT_STATUS_NO_MEMORY;
3664 if (is_named_stream(smb_fname)) {
3665 dos_fname = talloc_asprintf(dos_fname, "%s",
3666 smb_fname->stream_name);
3667 if (!dos_fname) {
3668 return NT_STATUS_NO_MEMORY;
3672 string_replace(dos_fname, '/', '\\');
3675 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
3677 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
3678 /* Do we have this path open ? */
3679 files_struct *fsp1;
3680 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
3681 fsp1 = file_find_di_first(conn->sconn, fileid, true);
3682 if (fsp1 && fsp1->initial_allocation_size) {
3683 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
3687 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
3688 file_size = get_file_size_stat(psbuf);
3691 if (fsp) {
3692 pos = fh_get_position_information(fsp->fh);
3695 if (fsp) {
3696 access_mask = fsp->access_mask;
3697 } else {
3698 /* GENERIC_EXECUTE mapping from Windows */
3699 access_mask = 0x12019F;
3702 /* This should be an index number - looks like
3703 dev/ino to me :-)
3705 I think this causes us to fail the IFSKIT
3706 BasicFileInformationTest. -tpot */
3707 file_id = SMB_VFS_FS_FILE_ID(conn, base_sp);
3709 *fixed_portion = 0;
3711 switch (info_level) {
3712 case SMB_INFO_STANDARD:
3713 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
3714 data_size = 22;
3715 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
3716 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
3717 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
3718 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
3719 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
3720 SSVAL(pdata,l1_attrFile,mode);
3721 break;
3723 case SMB_INFO_QUERY_EA_SIZE:
3725 unsigned int ea_size =
3726 estimate_ea_size(smb_fname->fsp);
3727 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
3728 data_size = 26;
3729 srv_put_dos_date2(pdata,0,create_time);
3730 srv_put_dos_date2(pdata,4,atime);
3731 srv_put_dos_date2(pdata,8,mtime); /* write time */
3732 SIVAL(pdata,12,(uint32_t)file_size);
3733 SIVAL(pdata,16,(uint32_t)allocation_size);
3734 SSVAL(pdata,20,mode);
3735 SIVAL(pdata,22,ea_size);
3736 break;
3739 case SMB_INFO_IS_NAME_VALID:
3740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
3741 if (fsp) {
3742 /* os/2 needs this ? really ?*/
3743 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
3745 /* This is only reached for qpathinfo */
3746 data_size = 0;
3747 break;
3749 case SMB_INFO_QUERY_EAS_FROM_LIST:
3751 size_t total_ea_len = 0;
3752 struct ea_list *ea_file_list = NULL;
3753 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
3755 status =
3756 get_ea_list_from_fsp(mem_ctx,
3757 smb_fname->fsp,
3758 &total_ea_len, &ea_file_list);
3759 if (!NT_STATUS_IS_OK(status)) {
3760 return status;
3763 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
3765 if (!ea_list || (total_ea_len > data_size)) {
3766 data_size = 4;
3767 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3768 break;
3771 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3772 break;
3775 case SMB_INFO_QUERY_ALL_EAS:
3777 /* We have data_size bytes to put EA's into. */
3778 size_t total_ea_len = 0;
3779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
3781 status = get_ea_list_from_fsp(mem_ctx,
3782 smb_fname->fsp,
3783 &total_ea_len, &ea_list);
3784 if (!NT_STATUS_IS_OK(status)) {
3785 return status;
3788 if (!ea_list || (total_ea_len > data_size)) {
3789 data_size = 4;
3790 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
3791 break;
3794 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
3795 break;
3798 case SMB2_FILE_FULL_EA_INFORMATION:
3800 /* We have data_size bytes to put EA's into. */
3801 size_t total_ea_len = 0;
3802 struct ea_list *ea_file_list = NULL;
3804 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
3806 /*TODO: add filtering and index handling */
3808 status =
3809 get_ea_list_from_fsp(mem_ctx,
3810 smb_fname->fsp,
3811 &total_ea_len, &ea_file_list);
3812 if (!NT_STATUS_IS_OK(status)) {
3813 return status;
3815 if (!ea_file_list) {
3816 return NT_STATUS_NO_EAS_ON_FILE;
3819 status = fill_ea_chained_buffer(mem_ctx,
3820 pdata,
3821 data_size,
3822 &data_size,
3823 conn, ea_file_list);
3824 if (!NT_STATUS_IS_OK(status)) {
3825 return status;
3827 break;
3830 case SMB_FILE_BASIC_INFORMATION:
3831 case SMB_QUERY_FILE_BASIC_INFO:
3833 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
3834 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
3835 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
3836 } else {
3837 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
3838 data_size = 40;
3839 SIVAL(pdata,36,0);
3841 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
3842 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
3843 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
3844 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
3845 SIVAL(pdata,32,mode);
3847 DEBUG(5,("SMB_QFBI - "));
3848 DEBUG(5,("create: %s ", ctime(&create_time)));
3849 DEBUG(5,("access: %s ", ctime(&atime)));
3850 DEBUG(5,("write: %s ", ctime(&mtime)));
3851 DEBUG(5,("change: %s ", ctime(&c_time)));
3852 DEBUG(5,("mode: %x\n", mode));
3853 *fixed_portion = data_size;
3854 break;
3856 case SMB_FILE_STANDARD_INFORMATION:
3857 case SMB_QUERY_FILE_STANDARD_INFO:
3859 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
3860 data_size = 24;
3861 SOFF_T(pdata,0,allocation_size);
3862 SOFF_T(pdata,8,file_size);
3863 SIVAL(pdata,16,nlink);
3864 SCVAL(pdata,20,delete_pending?1:0);
3865 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
3866 SSVAL(pdata,22,0); /* Padding. */
3867 *fixed_portion = 24;
3868 break;
3870 case SMB_FILE_EA_INFORMATION:
3871 case SMB_QUERY_FILE_EA_INFO:
3873 unsigned int ea_size =
3874 estimate_ea_size(smb_fname->fsp);
3875 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
3876 data_size = 4;
3877 *fixed_portion = 4;
3878 SIVAL(pdata,0,ea_size);
3879 break;
3882 /* Get the 8.3 name - used if NT SMB was negotiated. */
3883 case SMB_QUERY_FILE_ALT_NAME_INFO:
3884 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
3886 char mangled_name[13];
3887 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
3888 if (!name_to_8_3(base_name,mangled_name,
3889 True,conn->params)) {
3890 return NT_STATUS_NO_MEMORY;
3892 status = srvstr_push(dstart, flags2,
3893 pdata+4, mangled_name,
3894 PTR_DIFF(dend, pdata+4),
3895 STR_UNICODE, &len);
3896 if (!NT_STATUS_IS_OK(status)) {
3897 return status;
3899 data_size = 4 + len;
3900 SIVAL(pdata,0,len);
3901 *fixed_portion = 8;
3902 break;
3905 case SMB_QUERY_FILE_NAME_INFO:
3908 this must be *exactly* right for ACLs on mapped drives to work
3910 status = srvstr_push(dstart, flags2,
3911 pdata+4, dos_fname,
3912 PTR_DIFF(dend, pdata+4),
3913 STR_UNICODE, &len);
3914 if (!NT_STATUS_IS_OK(status)) {
3915 return status;
3917 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
3918 data_size = 4 + len;
3919 SIVAL(pdata,0,len);
3920 break;
3923 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
3925 char *nfname = NULL;
3927 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
3928 return NT_STATUS_INVALID_LEVEL;
3931 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
3932 if (nfname == NULL) {
3933 return NT_STATUS_NO_MEMORY;
3936 if (ISDOT(nfname)) {
3937 nfname[0] = '\0';
3939 string_replace(nfname, '/', '\\');
3941 if (fsp_is_alternate_stream(fsp)) {
3942 const char *s = smb_fname->stream_name;
3943 const char *e = NULL;
3944 size_t n;
3946 SMB_ASSERT(s[0] != '\0');
3949 * smb_fname->stream_name is in form
3950 * of ':StrEam:$DATA', but we should only
3951 * append ':StrEam' here.
3954 e = strchr(&s[1], ':');
3955 if (e == NULL) {
3956 n = strlen(s);
3957 } else {
3958 n = PTR_DIFF(e, s);
3960 nfname = talloc_strndup_append(nfname, s, n);
3961 if (nfname == NULL) {
3962 return NT_STATUS_NO_MEMORY;
3966 status = srvstr_push(dstart, flags2,
3967 pdata+4, nfname,
3968 PTR_DIFF(dend, pdata+4),
3969 STR_UNICODE, &len);
3970 if (!NT_STATUS_IS_OK(status)) {
3971 return status;
3973 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
3974 data_size = 4 + len;
3975 SIVAL(pdata,0,len);
3976 *fixed_portion = 8;
3977 break;
3980 case SMB_FILE_ALLOCATION_INFORMATION:
3981 case SMB_QUERY_FILE_ALLOCATION_INFO:
3982 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
3983 data_size = 8;
3984 SOFF_T(pdata,0,allocation_size);
3985 break;
3987 case SMB_FILE_END_OF_FILE_INFORMATION:
3988 case SMB_QUERY_FILE_END_OF_FILEINFO:
3989 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
3990 data_size = 8;
3991 SOFF_T(pdata,0,file_size);
3992 break;
3994 case SMB_QUERY_FILE_ALL_INFO:
3995 case SMB_FILE_ALL_INFORMATION:
3997 unsigned int ea_size =
3998 estimate_ea_size(smb_fname->fsp);
3999 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
4000 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
4001 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
4002 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
4003 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
4004 SIVAL(pdata,32,mode);
4005 SIVAL(pdata,36,0); /* padding. */
4006 pdata += 40;
4007 SOFF_T(pdata,0,allocation_size);
4008 SOFF_T(pdata,8,file_size);
4009 SIVAL(pdata,16,nlink);
4010 SCVAL(pdata,20,delete_pending);
4011 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4012 SSVAL(pdata,22,0);
4013 pdata += 24;
4014 SIVAL(pdata,0,ea_size);
4015 pdata += 4; /* EA info */
4016 status = srvstr_push(dstart, flags2,
4017 pdata+4, dos_fname,
4018 PTR_DIFF(dend, pdata+4),
4019 STR_UNICODE, &len);
4020 if (!NT_STATUS_IS_OK(status)) {
4021 return status;
4023 SIVAL(pdata,0,len);
4024 pdata += 4 + len;
4025 data_size = PTR_DIFF(pdata,(*ppdata));
4026 *fixed_portion = 10;
4027 break;
4030 case SMB2_FILE_ALL_INFORMATION:
4032 unsigned int ea_size =
4033 estimate_ea_size(smb_fname->fsp);
4034 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
4035 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
4036 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
4037 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
4038 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
4039 SIVAL(pdata, 0x20, mode);
4040 SIVAL(pdata, 0x24, 0); /* padding. */
4041 SBVAL(pdata, 0x28, allocation_size);
4042 SBVAL(pdata, 0x30, file_size);
4043 SIVAL(pdata, 0x38, nlink);
4044 SCVAL(pdata, 0x3C, delete_pending);
4045 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
4046 SSVAL(pdata, 0x3E, 0); /* padding */
4047 SBVAL(pdata, 0x40, file_id);
4048 SIVAL(pdata, 0x48, ea_size);
4049 SIVAL(pdata, 0x4C, access_mask);
4050 SBVAL(pdata, 0x50, pos);
4051 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
4052 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
4054 pdata += 0x60;
4056 status = srvstr_push(dstart, flags2,
4057 pdata+4, dos_fname,
4058 PTR_DIFF(dend, pdata+4),
4059 STR_UNICODE, &len);
4060 if (!NT_STATUS_IS_OK(status)) {
4061 return status;
4063 SIVAL(pdata,0,len);
4064 pdata += 4 + len;
4065 data_size = PTR_DIFF(pdata,(*ppdata));
4066 *fixed_portion = 104;
4067 break;
4069 case SMB_FILE_INTERNAL_INFORMATION:
4071 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
4072 SBVAL(pdata, 0, file_id);
4073 data_size = 8;
4074 *fixed_portion = 8;
4075 break;
4077 case SMB_FILE_ACCESS_INFORMATION:
4078 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
4079 SIVAL(pdata, 0, access_mask);
4080 data_size = 4;
4081 *fixed_portion = 4;
4082 break;
4084 case SMB_FILE_NAME_INFORMATION:
4085 /* Pathname with leading '\'. */
4087 size_t byte_len;
4088 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
4089 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
4090 SIVAL(pdata,0,byte_len);
4091 data_size = 4 + byte_len;
4092 break;
4095 case SMB_FILE_DISPOSITION_INFORMATION:
4096 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
4097 data_size = 1;
4098 SCVAL(pdata,0,delete_pending);
4099 *fixed_portion = 1;
4100 break;
4102 case SMB_FILE_POSITION_INFORMATION:
4103 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
4104 data_size = 8;
4105 SOFF_T(pdata,0,pos);
4106 *fixed_portion = 8;
4107 break;
4109 case SMB_FILE_MODE_INFORMATION:
4110 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
4111 SIVAL(pdata,0,mode);
4112 data_size = 4;
4113 *fixed_portion = 4;
4114 break;
4116 case SMB_FILE_ALIGNMENT_INFORMATION:
4117 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
4118 SIVAL(pdata,0,0); /* No alignment needed. */
4119 data_size = 4;
4120 *fixed_portion = 4;
4121 break;
4124 * NT4 server just returns "invalid query" to this - if we try
4125 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
4126 * want this. JRA.
4128 /* The first statement above is false - verified using Thursby
4129 * client against NT4 -- gcolley.
4131 case SMB_QUERY_FILE_STREAM_INFO:
4132 case SMB_FILE_STREAM_INFORMATION: {
4133 unsigned int num_streams = 0;
4134 struct stream_struct *streams = NULL;
4136 DEBUG(10,("smbd_do_qfilepathinfo: "
4137 "SMB_FILE_STREAM_INFORMATION\n"));
4139 if (is_ntfs_stream_smb_fname(smb_fname)) {
4140 return NT_STATUS_INVALID_PARAMETER;
4143 status = vfs_fstreaminfo(fsp,
4144 mem_ctx,
4145 &num_streams,
4146 &streams);
4148 if (!NT_STATUS_IS_OK(status)) {
4149 DEBUG(10, ("could not get stream info: %s\n",
4150 nt_errstr(status)));
4151 return status;
4154 status = marshall_stream_info(num_streams, streams,
4155 pdata, max_data_bytes,
4156 &data_size);
4158 if (!NT_STATUS_IS_OK(status)) {
4159 DEBUG(10, ("marshall_stream_info failed: %s\n",
4160 nt_errstr(status)));
4161 TALLOC_FREE(streams);
4162 return status;
4165 TALLOC_FREE(streams);
4167 *fixed_portion = 32;
4169 break;
4171 case SMB_QUERY_COMPRESSION_INFO:
4172 case SMB_FILE_COMPRESSION_INFORMATION:
4173 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
4174 SOFF_T(pdata,0,file_size);
4175 SIVAL(pdata,8,0); /* ??? */
4176 SIVAL(pdata,12,0); /* ??? */
4177 data_size = 16;
4178 *fixed_portion = 16;
4179 break;
4181 case SMB_FILE_NETWORK_OPEN_INFORMATION:
4182 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
4183 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
4184 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
4185 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
4186 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
4187 SOFF_T(pdata,32,allocation_size);
4188 SOFF_T(pdata,40,file_size);
4189 SIVAL(pdata,48,mode);
4190 SIVAL(pdata,52,0); /* ??? */
4191 data_size = 56;
4192 *fixed_portion = 56;
4193 break;
4195 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
4196 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
4197 SIVAL(pdata,0,mode);
4198 SIVAL(pdata,4,0);
4199 data_size = 8;
4200 *fixed_portion = 8;
4201 break;
4204 * CIFS UNIX Extensions.
4207 case SMB_QUERY_FILE_UNIX_BASIC:
4209 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4210 data_size = PTR_DIFF(pdata,(*ppdata));
4212 DEBUG(4,("smbd_do_qfilepathinfo: "
4213 "SMB_QUERY_FILE_UNIX_BASIC\n"));
4214 dump_data(4, (uint8_t *)(*ppdata), data_size);
4216 break;
4218 case SMB_QUERY_FILE_UNIX_INFO2:
4220 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
4221 data_size = PTR_DIFF(pdata,(*ppdata));
4224 int i;
4225 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
4227 for (i=0; i<100; i++)
4228 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
4229 DEBUG(4,("\n"));
4232 break;
4234 case SMB_QUERY_FILE_UNIX_LINK:
4236 status = smb_unix_read_symlink(conn,
4237 req,
4238 smb_fname,
4239 pdata,
4240 data_size,
4241 &data_size);
4242 if (!NT_STATUS_IS_OK(status)) {
4243 return status;
4245 break;
4248 #if defined(HAVE_POSIX_ACLS)
4249 case SMB_QUERY_POSIX_ACL:
4251 status = smb_query_posix_acl(conn,
4252 req,
4253 fsp,
4254 smb_fname,
4255 pdata,
4256 data_size,
4257 &data_size);
4258 if (!NT_STATUS_IS_OK(status)) {
4259 return status;
4261 break;
4263 #endif
4266 case SMB_QUERY_POSIX_LOCK:
4268 uint64_t count;
4269 uint64_t offset;
4270 uint64_t smblctx;
4271 enum brl_type lock_type;
4273 /* We need an open file with a real fd for this. */
4274 if (fsp == NULL ||
4275 fsp->fsp_flags.is_pathref ||
4276 fsp_get_io_fd(fsp) == -1)
4278 return NT_STATUS_INVALID_LEVEL;
4281 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
4282 return NT_STATUS_INVALID_PARAMETER;
4285 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
4286 case POSIX_LOCK_TYPE_READ:
4287 lock_type = READ_LOCK;
4288 break;
4289 case POSIX_LOCK_TYPE_WRITE:
4290 lock_type = WRITE_LOCK;
4291 break;
4292 case POSIX_LOCK_TYPE_UNLOCK:
4293 default:
4294 /* There's no point in asking for an unlock... */
4295 return NT_STATUS_INVALID_PARAMETER;
4298 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
4299 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
4300 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
4302 status = query_lock(fsp,
4303 &smblctx,
4304 &count,
4305 &offset,
4306 &lock_type,
4307 POSIX_LOCK);
4309 if (ERROR_WAS_LOCK_DENIED(status)) {
4310 /* Here we need to report who has it locked... */
4311 data_size = POSIX_LOCK_DATA_SIZE;
4313 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
4314 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
4315 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
4316 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
4317 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
4319 } else if (NT_STATUS_IS_OK(status)) {
4320 /* For success we just return a copy of what we sent
4321 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
4322 data_size = POSIX_LOCK_DATA_SIZE;
4323 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
4324 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
4325 } else {
4326 return status;
4328 break;
4332 * SMB2 UNIX Extensions.
4334 case SMB2_FILE_POSIX_INFORMATION_INTERNAL:
4336 uint8_t *buf = NULL;
4337 ssize_t plen = 0;
4339 if (!(conn->sconn->using_smb2)) {
4340 return NT_STATUS_INVALID_LEVEL;
4342 if (!lp_smb3_unix_extensions()) {
4343 return NT_STATUS_INVALID_LEVEL;
4345 if (fsp == NULL) {
4346 return NT_STATUS_INVALID_HANDLE;
4348 if (!(fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)) {
4349 return NT_STATUS_INVALID_LEVEL;
4352 /* Determine the size of the posix info context */
4353 plen = store_smb2_posix_info(conn,
4354 &smb_fname->st,
4356 mode,
4357 NULL,
4359 if (plen == -1 || data_size < plen) {
4360 return NT_STATUS_INVALID_PARAMETER;
4362 buf = talloc_zero_size(mem_ctx, plen);
4363 if (buf == NULL) {
4364 return NT_STATUS_NO_MEMORY;
4367 /* Store the context in buf */
4368 store_smb2_posix_info(conn,
4369 &smb_fname->st,
4371 mode,
4372 buf,
4373 plen);
4374 memcpy(pdata, buf, plen);
4375 data_size = plen;
4376 break;
4379 default:
4380 return NT_STATUS_INVALID_LEVEL;
4383 *pdata_size = data_size;
4384 return NT_STATUS_OK;
4387 /****************************************************************************
4388 Set a hard link (called by UNIX extensions and by NT rename with HARD link
4389 code.
4390 ****************************************************************************/
4392 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
4393 connection_struct *conn,
4394 struct smb_request *req,
4395 bool overwrite_if_exists,
4396 struct files_struct *old_dirfsp,
4397 const struct smb_filename *smb_fname_old,
4398 struct files_struct *new_dirfsp,
4399 struct smb_filename *smb_fname_new)
4401 NTSTATUS status = NT_STATUS_OK;
4402 int ret;
4403 bool ok;
4404 struct smb_filename *parent_fname_old = NULL;
4405 struct smb_filename *base_name_old = NULL;
4406 struct smb_filename *parent_fname_new = NULL;
4407 struct smb_filename *base_name_new = NULL;
4409 /* source must already exist. */
4410 if (!VALID_STAT(smb_fname_old->st)) {
4411 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
4412 goto out;
4415 /* No links from a directory. */
4416 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
4417 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4418 goto out;
4421 /* Setting a hardlink to/from a stream isn't currently supported. */
4422 ok = is_ntfs_stream_smb_fname(smb_fname_old);
4423 if (ok) {
4424 DBG_DEBUG("Old name has streams\n");
4425 status = NT_STATUS_INVALID_PARAMETER;
4426 goto out;
4428 ok = is_ntfs_stream_smb_fname(smb_fname_new);
4429 if (ok) {
4430 DBG_DEBUG("New name has streams\n");
4431 status = NT_STATUS_INVALID_PARAMETER;
4432 goto out;
4435 status = parent_pathref(talloc_tos(),
4436 conn->cwd_fsp,
4437 smb_fname_old,
4438 &parent_fname_old,
4439 &base_name_old);
4440 if (!NT_STATUS_IS_OK(status)) {
4441 goto out;
4444 status = parent_pathref(talloc_tos(),
4445 conn->cwd_fsp,
4446 smb_fname_new,
4447 &parent_fname_new,
4448 &base_name_new);
4449 if (!NT_STATUS_IS_OK(status)) {
4450 goto out;
4453 if (VALID_STAT(smb_fname_new->st)) {
4454 if (overwrite_if_exists) {
4455 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
4456 status = NT_STATUS_FILE_IS_A_DIRECTORY;
4457 goto out;
4459 status = unlink_internals(conn,
4460 req,
4461 FILE_ATTRIBUTE_NORMAL,
4462 NULL, /* new_dirfsp */
4463 smb_fname_new);
4464 if (!NT_STATUS_IS_OK(status)) {
4465 goto out;
4467 } else {
4468 /* Disallow if newname already exists. */
4469 status = NT_STATUS_OBJECT_NAME_COLLISION;
4470 goto out;
4474 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
4475 smb_fname_old->base_name, smb_fname_new->base_name));
4477 ret = SMB_VFS_LINKAT(conn,
4478 parent_fname_old->fsp,
4479 base_name_old,
4480 parent_fname_new->fsp,
4481 base_name_new,
4484 if (ret != 0) {
4485 status = map_nt_error_from_unix(errno);
4486 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
4487 nt_errstr(status), smb_fname_old->base_name,
4488 smb_fname_new->base_name));
4491 out:
4493 TALLOC_FREE(parent_fname_old);
4494 TALLOC_FREE(parent_fname_new);
4495 return status;
4498 /****************************************************************************
4499 Deal with setting the time from any of the setfilepathinfo functions.
4500 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
4501 calling this function.
4502 ****************************************************************************/
4504 NTSTATUS smb_set_file_time(connection_struct *conn,
4505 files_struct *fsp,
4506 struct smb_filename *smb_fname,
4507 struct smb_file_time *ft,
4508 bool setting_write_time)
4510 struct files_struct *set_fsp = NULL;
4511 struct timeval_buf tbuf[4];
4512 uint32_t action =
4513 FILE_NOTIFY_CHANGE_LAST_ACCESS
4514 |FILE_NOTIFY_CHANGE_LAST_WRITE
4515 |FILE_NOTIFY_CHANGE_CREATION;
4516 int ret;
4518 if (!VALID_STAT(smb_fname->st)) {
4519 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4522 if (fsp == NULL) {
4523 /* A symlink */
4524 return NT_STATUS_OK;
4527 set_fsp = metadata_fsp(fsp);
4529 /* get some defaults (no modifications) if any info is zero or -1. */
4530 if (is_omit_timespec(&ft->create_time)) {
4531 action &= ~FILE_NOTIFY_CHANGE_CREATION;
4534 if (is_omit_timespec(&ft->atime)) {
4535 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
4538 if (is_omit_timespec(&ft->mtime)) {
4539 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4542 if (!setting_write_time) {
4543 /* ft->mtime comes from change time, not write time. */
4544 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
4547 /* Ensure the resolution is the correct for
4548 * what we can store on this filesystem. */
4550 round_timespec(conn->ts_res, &ft->create_time);
4551 round_timespec(conn->ts_res, &ft->ctime);
4552 round_timespec(conn->ts_res, &ft->atime);
4553 round_timespec(conn->ts_res, &ft->mtime);
4555 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
4556 timespec_string_buf(&ft->atime, true, &tbuf[0]));
4557 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
4558 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
4559 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
4560 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
4561 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
4562 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
4564 if (setting_write_time) {
4566 * This was a Windows setfileinfo on an open file.
4567 * NT does this a lot. We also need to
4568 * set the time here, as it can be read by
4569 * FindFirst/FindNext and with the patch for bug #2045
4570 * in smbd/fileio.c it ensures that this timestamp is
4571 * kept sticky even after a write. We save the request
4572 * away and will set it on file close and after a write. JRA.
4575 DBG_DEBUG("setting pending modtime to %s\n",
4576 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
4578 if (set_fsp != NULL) {
4579 set_sticky_write_time_fsp(set_fsp, ft->mtime);
4580 } else {
4581 set_sticky_write_time_path(
4582 vfs_file_id_from_sbuf(conn, &smb_fname->st),
4583 ft->mtime);
4587 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
4589 ret = file_ntimes(conn, set_fsp, ft);
4590 if (ret != 0) {
4591 return map_nt_error_from_unix(errno);
4594 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
4595 smb_fname->base_name);
4596 return NT_STATUS_OK;
4599 /****************************************************************************
4600 Deal with setting the dosmode from any of the setfilepathinfo functions.
4601 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
4602 done before calling this function.
4603 ****************************************************************************/
4605 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
4606 struct files_struct *fsp,
4607 uint32_t dosmode)
4609 struct files_struct *dos_fsp = NULL;
4610 uint32_t current_dosmode;
4611 int ret;
4613 if (!VALID_STAT(fsp->fsp_name->st)) {
4614 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4617 dos_fsp = metadata_fsp(fsp);
4619 if (dosmode != 0) {
4620 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4621 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
4622 } else {
4623 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
4627 DBG_DEBUG("dosmode: 0x%" PRIx32 "\n", dosmode);
4629 /* check the mode isn't different, before changing it */
4630 if (dosmode == 0) {
4631 return NT_STATUS_OK;
4633 current_dosmode = fdos_mode(dos_fsp);
4634 if (dosmode == current_dosmode) {
4635 return NT_STATUS_OK;
4638 DBG_DEBUG("file %s : setting dos mode 0x%" PRIx32 "\n",
4639 fsp_str_dbg(dos_fsp), dosmode);
4641 ret = file_set_dosmode(conn, dos_fsp->fsp_name, dosmode, NULL, false);
4642 if (ret != 0) {
4643 DBG_WARNING("file_set_dosmode of %s failed: %s\n",
4644 fsp_str_dbg(dos_fsp), strerror(errno));
4645 return map_nt_error_from_unix(errno);
4648 return NT_STATUS_OK;
4651 /****************************************************************************
4652 Deal with setting the size from any of the setfilepathinfo functions.
4653 ****************************************************************************/
4655 static NTSTATUS smb_set_file_size(connection_struct *conn,
4656 struct smb_request *req,
4657 files_struct *fsp,
4658 struct smb_filename *smb_fname,
4659 const SMB_STRUCT_STAT *psbuf,
4660 off_t size,
4661 bool fail_after_createfile)
4663 NTSTATUS status = NT_STATUS_OK;
4664 files_struct *new_fsp = NULL;
4666 if (!VALID_STAT(*psbuf)) {
4667 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4670 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
4671 (uint64_t)size,
4672 get_file_size_stat(psbuf));
4674 if (size == get_file_size_stat(psbuf)) {
4675 if (fsp == NULL) {
4676 return NT_STATUS_OK;
4678 if (!fsp->fsp_flags.modified) {
4679 return NT_STATUS_OK;
4681 trigger_write_time_update_immediate(fsp);
4682 return NT_STATUS_OK;
4685 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
4686 smb_fname_str_dbg(smb_fname), (double)size));
4688 if (fsp &&
4689 !fsp->fsp_flags.is_pathref &&
4690 fsp_get_io_fd(fsp) != -1)
4692 /* Handle based call. */
4693 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
4694 return NT_STATUS_ACCESS_DENIED;
4697 if (vfs_set_filelen(fsp, size) == -1) {
4698 return map_nt_error_from_unix(errno);
4700 trigger_write_time_update_immediate(fsp);
4701 return NT_STATUS_OK;
4704 status = SMB_VFS_CREATE_FILE(
4705 conn, /* conn */
4706 req, /* req */
4707 NULL, /* dirfsp */
4708 smb_fname, /* fname */
4709 FILE_WRITE_DATA, /* access_mask */
4710 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
4711 FILE_SHARE_DELETE),
4712 FILE_OPEN, /* create_disposition*/
4713 0, /* create_options */
4714 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
4715 0, /* oplock_request */
4716 NULL, /* lease */
4717 0, /* allocation_size */
4718 0, /* private_flags */
4719 NULL, /* sd */
4720 NULL, /* ea_list */
4721 &new_fsp, /* result */
4722 NULL, /* pinfo */
4723 NULL, NULL); /* create context */
4725 if (!NT_STATUS_IS_OK(status)) {
4726 /* NB. We check for open_was_deferred in the caller. */
4727 return status;
4730 /* See RAW-SFILEINFO-END-OF-FILE */
4731 if (fail_after_createfile) {
4732 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4733 return NT_STATUS_INVALID_LEVEL;
4736 if (vfs_set_filelen(new_fsp, size) == -1) {
4737 status = map_nt_error_from_unix(errno);
4738 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4739 return status;
4742 trigger_write_time_update_immediate(new_fsp);
4743 close_file_free(req, &new_fsp, NORMAL_CLOSE);
4744 return NT_STATUS_OK;
4747 /****************************************************************************
4748 Deal with SMB_INFO_SET_EA.
4749 ****************************************************************************/
4751 static NTSTATUS smb_info_set_ea(connection_struct *conn,
4752 const char *pdata,
4753 int total_data,
4754 files_struct *fsp,
4755 struct smb_filename *smb_fname)
4757 struct ea_list *ea_list = NULL;
4758 TALLOC_CTX *ctx = NULL;
4759 NTSTATUS status = NT_STATUS_OK;
4761 if (total_data < 10) {
4763 /* OS/2 workplace shell seems to send SET_EA requests of "null"
4764 length. They seem to have no effect. Bug #3212. JRA */
4766 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
4767 /* We're done. We only get EA info in this call. */
4768 return NT_STATUS_OK;
4771 return NT_STATUS_INVALID_PARAMETER;
4774 if (IVAL(pdata,0) > total_data) {
4775 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
4776 IVAL(pdata,0), (unsigned int)total_data));
4777 return NT_STATUS_INVALID_PARAMETER;
4780 ctx = talloc_tos();
4781 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
4782 if (!ea_list) {
4783 return NT_STATUS_INVALID_PARAMETER;
4786 if (fsp == NULL) {
4788 * The only way fsp can be NULL here is if
4789 * smb_fname points at a symlink and
4790 * and we're in POSIX context.
4791 * Ensure this is the case.
4793 * In this case we cannot set the EA.
4795 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
4796 return NT_STATUS_ACCESS_DENIED;
4799 status = set_ea(conn, fsp, ea_list);
4801 return status;
4804 /****************************************************************************
4805 Deal with SMB_FILE_FULL_EA_INFORMATION set.
4806 ****************************************************************************/
4808 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
4809 const char *pdata,
4810 int total_data,
4811 files_struct *fsp)
4813 struct ea_list *ea_list = NULL;
4814 NTSTATUS status;
4816 if (fsp == NULL) {
4817 return NT_STATUS_INVALID_HANDLE;
4820 if (!lp_ea_support(SNUM(conn))) {
4821 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
4822 "EA's not supported.\n",
4823 (unsigned int)total_data));
4824 return NT_STATUS_EAS_NOT_SUPPORTED;
4827 if (total_data < 10) {
4828 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
4829 "too small.\n",
4830 (unsigned int)total_data));
4831 return NT_STATUS_INVALID_PARAMETER;
4834 ea_list = read_nttrans_ea_list(talloc_tos(),
4835 pdata,
4836 total_data);
4838 if (!ea_list) {
4839 return NT_STATUS_INVALID_PARAMETER;
4842 status = set_ea(conn, fsp, ea_list);
4844 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
4845 smb_fname_str_dbg(fsp->fsp_name),
4846 nt_errstr(status) ));
4848 return status;
4852 /****************************************************************************
4853 Deal with SMB_SET_FILE_DISPOSITION_INFO.
4854 ****************************************************************************/
4856 NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
4857 const char *pdata,
4858 int total_data,
4859 files_struct *fsp,
4860 struct smb_filename *smb_fname)
4862 NTSTATUS status = NT_STATUS_OK;
4863 bool delete_on_close;
4864 uint32_t dosmode = 0;
4866 if (total_data < 1) {
4867 return NT_STATUS_INVALID_PARAMETER;
4870 if (fsp == NULL) {
4871 return NT_STATUS_INVALID_HANDLE;
4874 delete_on_close = (CVAL(pdata,0) ? True : False);
4875 dosmode = fdos_mode(fsp);
4877 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
4878 "delete_on_close = %u\n",
4879 smb_fname_str_dbg(smb_fname),
4880 (unsigned int)dosmode,
4881 (unsigned int)delete_on_close ));
4883 if (delete_on_close) {
4884 status = can_set_delete_on_close(fsp, dosmode);
4885 if (!NT_STATUS_IS_OK(status)) {
4886 return status;
4890 /* The set is across all open files on this dev/inode pair. */
4891 if (!set_delete_on_close(fsp, delete_on_close,
4892 conn->session_info->security_token,
4893 conn->session_info->unix_token)) {
4894 return NT_STATUS_ACCESS_DENIED;
4896 return NT_STATUS_OK;
4899 /****************************************************************************
4900 Deal with SMB_FILE_POSITION_INFORMATION.
4901 ****************************************************************************/
4903 static NTSTATUS smb_file_position_information(connection_struct *conn,
4904 const char *pdata,
4905 int total_data,
4906 files_struct *fsp)
4908 uint64_t position_information;
4910 if (total_data < 8) {
4911 return NT_STATUS_INVALID_PARAMETER;
4914 if (fsp == NULL) {
4915 /* Ignore on pathname based set. */
4916 return NT_STATUS_OK;
4919 position_information = (uint64_t)IVAL(pdata,0);
4920 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
4922 DEBUG(10,("smb_file_position_information: Set file position "
4923 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
4924 (double)position_information));
4925 fh_set_position_information(fsp->fh, position_information);
4926 return NT_STATUS_OK;
4929 /****************************************************************************
4930 Deal with SMB_FILE_MODE_INFORMATION.
4931 ****************************************************************************/
4933 static NTSTATUS smb_file_mode_information(connection_struct *conn,
4934 const char *pdata,
4935 int total_data)
4937 uint32_t mode;
4939 if (total_data < 4) {
4940 return NT_STATUS_INVALID_PARAMETER;
4942 mode = IVAL(pdata,0);
4943 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
4944 return NT_STATUS_INVALID_PARAMETER;
4946 return NT_STATUS_OK;
4949 /****************************************************************************
4950 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
4951 ****************************************************************************/
4953 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
4954 struct smb_request *req,
4955 const char *pdata,
4956 int total_data,
4957 files_struct *fsp,
4958 struct smb_filename *smb_fname_src)
4960 bool overwrite;
4961 uint32_t len;
4962 char *newname = NULL;
4963 struct files_struct *dst_dirfsp = NULL;
4964 struct smb_filename *smb_fname_dst = NULL;
4965 const char *dst_original_lcomp = NULL;
4966 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
4967 NTTIME dst_twrp = 0;
4968 NTSTATUS status = NT_STATUS_OK;
4969 bool is_dfs = (req->flags2 & FLAGS2_DFS_PATHNAMES);
4970 TALLOC_CTX *ctx = talloc_tos();
4972 if (!fsp) {
4973 return NT_STATUS_INVALID_HANDLE;
4976 if (total_data < 20) {
4977 return NT_STATUS_INVALID_PARAMETER;
4980 overwrite = (CVAL(pdata,0) ? True : False);
4981 len = IVAL(pdata,16);
4983 if (len > (total_data - 20) || (len == 0)) {
4984 return NT_STATUS_INVALID_PARAMETER;
4987 (void)srvstr_pull_talloc(ctx,
4988 pdata,
4989 req->flags2,
4990 &newname,
4991 &pdata[20],
4992 len,
4993 STR_TERMINATE);
4995 if (newname == NULL) {
4996 return NT_STATUS_INVALID_PARAMETER;
4998 status = check_path_syntax_smb2(newname, is_dfs);
4999 if (!NT_STATUS_IS_OK(status)) {
5000 return status;
5003 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
5004 newname));
5006 if (newname[0] == ':') {
5007 /* Create an smb_fname to call rename_internals_fsp() with. */
5008 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5009 fsp->base_fsp->fsp_name->base_name,
5010 newname,
5011 NULL,
5012 fsp->base_fsp->fsp_name->twrp,
5013 fsp->base_fsp->fsp_name->flags);
5014 if (smb_fname_dst == NULL) {
5015 status = NT_STATUS_NO_MEMORY;
5016 goto out;
5018 } else {
5019 if (ucf_flags & UCF_GMT_PATHNAME) {
5020 extract_snapshot_token(newname, &dst_twrp);
5022 status = filename_convert_dirfsp(ctx,
5023 conn,
5024 newname,
5025 ucf_flags,
5026 dst_twrp,
5027 &dst_dirfsp,
5028 &smb_fname_dst);
5029 if (!NT_STATUS_IS_OK(status)) {
5030 goto out;
5035 * Set the original last component, since
5036 * rename_internals_fsp() requires it.
5038 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5039 conn,
5040 newname,
5041 ucf_flags);
5042 if (dst_original_lcomp == NULL) {
5043 status = NT_STATUS_NO_MEMORY;
5044 goto out;
5047 DEBUG(10,("smb2_file_rename_information: "
5048 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5049 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5050 smb_fname_str_dbg(smb_fname_dst)));
5051 status = rename_internals_fsp(conn,
5052 fsp,
5053 NULL, /* dst_dirfsp */
5054 smb_fname_dst,
5055 dst_original_lcomp,
5056 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
5057 overwrite);
5059 out:
5060 TALLOC_FREE(smb_fname_dst);
5061 return status;
5064 static NTSTATUS smb_file_link_information(connection_struct *conn,
5065 struct smb_request *req,
5066 const char *pdata,
5067 int total_data,
5068 files_struct *fsp,
5069 struct smb_filename *smb_fname_src)
5071 bool overwrite;
5072 uint32_t len;
5073 char *newname = NULL;
5074 struct files_struct *dst_dirfsp = NULL;
5075 struct smb_filename *smb_fname_dst = NULL;
5076 NTSTATUS status = NT_STATUS_OK;
5077 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5078 NTTIME dst_twrp = 0;
5079 TALLOC_CTX *ctx = talloc_tos();
5081 if (!fsp) {
5082 return NT_STATUS_INVALID_HANDLE;
5085 if (total_data < 20) {
5086 return NT_STATUS_INVALID_PARAMETER;
5089 overwrite = (CVAL(pdata,0) ? true : false);
5090 len = IVAL(pdata,16);
5092 if (len > (total_data - 20) || (len == 0)) {
5093 return NT_STATUS_INVALID_PARAMETER;
5096 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
5097 srvstr_get_path_posix(ctx,
5098 pdata,
5099 req->flags2,
5100 &newname,
5101 &pdata[20],
5102 len,
5103 STR_TERMINATE,
5104 &status);
5105 ucf_flags |= UCF_POSIX_PATHNAMES;
5106 } else {
5107 srvstr_get_path(ctx,
5108 pdata,
5109 req->flags2,
5110 &newname,
5111 &pdata[20],
5112 len,
5113 STR_TERMINATE,
5114 &status);
5116 if (!NT_STATUS_IS_OK(status)) {
5117 return status;
5120 DEBUG(10,("smb_file_link_information: got name |%s|\n",
5121 newname));
5123 if (ucf_flags & UCF_GMT_PATHNAME) {
5124 extract_snapshot_token(newname, &dst_twrp);
5126 status = filename_convert_dirfsp(ctx,
5127 conn,
5128 newname,
5129 ucf_flags,
5130 dst_twrp,
5131 &dst_dirfsp,
5132 &smb_fname_dst);
5133 if (!NT_STATUS_IS_OK(status)) {
5134 return status;
5137 if (fsp->base_fsp) {
5138 /* No stream names. */
5139 return NT_STATUS_NOT_SUPPORTED;
5142 DEBUG(10,("smb_file_link_information: "
5143 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
5144 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5145 smb_fname_str_dbg(smb_fname_dst)));
5146 status = hardlink_internals(ctx,
5147 conn,
5148 req,
5149 overwrite,
5150 NULL, /* src_dirfsp */
5151 fsp->fsp_name,
5152 dst_dirfsp, /* dst_dirfsp */
5153 smb_fname_dst);
5155 TALLOC_FREE(smb_fname_dst);
5156 return status;
5159 /****************************************************************************
5160 Deal with SMB_FILE_RENAME_INFORMATION.
5161 ****************************************************************************/
5163 static NTSTATUS smb_file_rename_information(connection_struct *conn,
5164 struct smb_request *req,
5165 const char *pdata,
5166 int total_data,
5167 files_struct *fsp,
5168 struct smb_filename *smb_fname_src)
5170 bool overwrite;
5171 uint32_t root_fid;
5172 uint32_t len;
5173 char *newname = NULL;
5174 struct files_struct *dst_dirfsp = NULL;
5175 struct smb_filename *smb_fname_dst = NULL;
5176 const char *dst_original_lcomp = NULL;
5177 NTSTATUS status = NT_STATUS_OK;
5178 char *p;
5179 TALLOC_CTX *ctx = talloc_tos();
5181 if (total_data < 13) {
5182 return NT_STATUS_INVALID_PARAMETER;
5185 overwrite = (CVAL(pdata,0) != 0);
5186 root_fid = IVAL(pdata,4);
5187 len = IVAL(pdata,8);
5189 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
5190 return NT_STATUS_INVALID_PARAMETER;
5193 if (req->posix_pathnames) {
5194 srvstr_get_path_posix(ctx,
5195 pdata,
5196 req->flags2,
5197 &newname,
5198 &pdata[12],
5199 len,
5201 &status);
5202 } else {
5203 srvstr_get_path(ctx,
5204 pdata,
5205 req->flags2,
5206 &newname,
5207 &pdata[12],
5208 len,
5210 &status);
5212 if (!NT_STATUS_IS_OK(status)) {
5213 return status;
5216 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
5217 newname));
5219 /* Check the new name has no '/' characters. */
5220 if (strchr_m(newname, '/')) {
5221 return NT_STATUS_NOT_SUPPORTED;
5224 if (fsp && fsp->base_fsp) {
5225 /* newname must be a stream name. */
5226 if (newname[0] != ':') {
5227 return NT_STATUS_NOT_SUPPORTED;
5230 /* Create an smb_fname to call rename_internals_fsp() with. */
5231 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
5232 fsp->base_fsp->fsp_name->base_name,
5233 newname,
5234 NULL,
5235 fsp->base_fsp->fsp_name->twrp,
5236 fsp->base_fsp->fsp_name->flags);
5237 if (smb_fname_dst == NULL) {
5238 status = NT_STATUS_NO_MEMORY;
5239 goto out;
5243 * Get the original last component, since
5244 * rename_internals_fsp() requires it.
5246 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5247 conn,
5248 newname,
5250 if (dst_original_lcomp == NULL) {
5251 status = NT_STATUS_NO_MEMORY;
5252 goto out;
5255 } else {
5257 * Build up an smb_fname_dst based on the filename passed in.
5258 * We basically just strip off the last component, and put on
5259 * the newname instead.
5261 char *base_name = NULL;
5262 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5263 NTTIME dst_twrp = 0;
5265 /* newname must *not* be a stream name. */
5266 if (newname[0] == ':') {
5267 return NT_STATUS_NOT_SUPPORTED;
5271 * Strip off the last component (filename) of the path passed
5272 * in.
5274 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
5275 if (!base_name) {
5276 return NT_STATUS_NO_MEMORY;
5278 p = strrchr_m(base_name, '/');
5279 if (p) {
5280 p[1] = '\0';
5281 } else {
5282 base_name = talloc_strdup(ctx, "");
5283 if (!base_name) {
5284 return NT_STATUS_NO_MEMORY;
5287 /* Append the new name. */
5288 base_name = talloc_asprintf_append(base_name,
5289 "%s",
5290 newname);
5291 if (!base_name) {
5292 return NT_STATUS_NO_MEMORY;
5295 if (ucf_flags & UCF_GMT_PATHNAME) {
5296 extract_snapshot_token(base_name, &dst_twrp);
5298 status = filename_convert_dirfsp(ctx,
5299 conn,
5300 base_name,
5301 ucf_flags,
5302 dst_twrp,
5303 &dst_dirfsp,
5304 &smb_fname_dst);
5306 if (!NT_STATUS_IS_OK(status)) {
5307 goto out;
5309 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
5310 conn,
5311 newname,
5312 ucf_flags);
5313 if (dst_original_lcomp == NULL) {
5314 status = NT_STATUS_NO_MEMORY;
5315 goto out;
5319 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
5320 DEBUG(10,("smb_file_rename_information: "
5321 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
5322 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
5323 smb_fname_str_dbg(smb_fname_dst)));
5324 status = rename_internals_fsp(conn,
5325 fsp,
5326 dst_dirfsp,
5327 smb_fname_dst,
5328 dst_original_lcomp,
5330 overwrite);
5331 } else {
5332 DEBUG(10,("smb_file_rename_information: "
5333 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
5334 smb_fname_str_dbg(smb_fname_src),
5335 smb_fname_str_dbg(smb_fname_dst)));
5336 status = rename_internals(ctx,
5337 conn,
5338 req,
5339 NULL, /* src_dirfsp */
5340 smb_fname_src,
5341 dst_dirfsp,
5342 smb_fname_dst,
5343 dst_original_lcomp,
5345 overwrite,
5346 FILE_WRITE_ATTRIBUTES);
5348 out:
5349 TALLOC_FREE(smb_fname_dst);
5350 return status;
5353 /****************************************************************************
5354 Deal with SMB_SET_POSIX_ACL.
5355 ****************************************************************************/
5357 #if defined(HAVE_POSIX_ACLS)
5358 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
5359 struct smb_request *req,
5360 const char *pdata,
5361 int total_data_in,
5362 files_struct *fsp,
5363 struct smb_filename *smb_fname)
5365 uint16_t posix_acl_version;
5366 uint16_t num_file_acls;
5367 uint16_t num_def_acls;
5368 bool valid_file_acls = true;
5369 bool valid_def_acls = true;
5370 NTSTATUS status;
5371 unsigned int size_needed;
5372 unsigned int total_data;
5373 bool close_fsp = false;
5375 if (total_data_in < 0) {
5376 status = NT_STATUS_INVALID_PARAMETER;
5377 goto out;
5380 total_data = total_data_in;
5382 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
5383 status = NT_STATUS_INVALID_PARAMETER;
5384 goto out;
5386 posix_acl_version = SVAL(pdata,0);
5387 num_file_acls = SVAL(pdata,2);
5388 num_def_acls = SVAL(pdata,4);
5390 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5391 valid_file_acls = false;
5392 num_file_acls = 0;
5395 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
5396 valid_def_acls = false;
5397 num_def_acls = 0;
5400 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
5401 status = NT_STATUS_INVALID_PARAMETER;
5402 goto out;
5405 /* Wrap checks. */
5406 if (num_file_acls + num_def_acls < num_file_acls) {
5407 status = NT_STATUS_INVALID_PARAMETER;
5408 goto out;
5411 size_needed = num_file_acls + num_def_acls;
5414 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5415 * than UINT_MAX, so check by division.
5417 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5418 status = NT_STATUS_INVALID_PARAMETER;
5419 goto out;
5422 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5423 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5424 status = NT_STATUS_INVALID_PARAMETER;
5425 goto out;
5427 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5429 if (total_data < size_needed) {
5430 status = NT_STATUS_INVALID_PARAMETER;
5431 goto out;
5435 * Ensure we always operate on a file descriptor, not just
5436 * the filename.
5438 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5439 uint32_t access_mask = SEC_STD_WRITE_OWNER|
5440 SEC_STD_WRITE_DAC|
5441 SEC_STD_READ_CONTROL|
5442 FILE_READ_ATTRIBUTES|
5443 FILE_WRITE_ATTRIBUTES;
5445 status = get_posix_fsp(conn,
5446 req,
5447 smb_fname,
5448 access_mask,
5449 &fsp);
5451 if (!NT_STATUS_IS_OK(status)) {
5452 goto out;
5454 close_fsp = true;
5457 /* Here we know fsp != NULL */
5458 SMB_ASSERT(fsp != NULL);
5460 status = refuse_symlink_fsp(fsp);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 goto out;
5465 /* If we have a default acl, this *must* be a directory. */
5466 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
5467 DBG_INFO("Can't set default acls on "
5468 "non-directory %s\n",
5469 fsp_str_dbg(fsp));
5470 return NT_STATUS_INVALID_HANDLE;
5473 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
5474 "num_def_acls = %"PRIu16"\n",
5475 fsp_str_dbg(fsp),
5476 num_file_acls,
5477 num_def_acls);
5479 /* Move pdata to the start of the file ACL entries. */
5480 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5482 if (valid_file_acls) {
5483 status = set_unix_posix_acl(conn,
5484 fsp,
5485 num_file_acls,
5486 pdata);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 goto out;
5492 /* Move pdata to the start of the default ACL entries. */
5493 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5495 if (valid_def_acls) {
5496 status = set_unix_posix_default_acl(conn,
5497 fsp,
5498 num_def_acls,
5499 pdata);
5500 if (!NT_STATUS_IS_OK(status)) {
5501 goto out;
5505 status = NT_STATUS_OK;
5507 out:
5509 if (close_fsp) {
5510 (void)close_file_free(req, &fsp, NORMAL_CLOSE);
5512 return status;
5514 #endif
5516 /****************************************************************************
5517 Deal with SMB_SET_FILE_BASIC_INFO.
5518 ****************************************************************************/
5520 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
5521 const char *pdata,
5522 int total_data,
5523 files_struct *fsp,
5524 struct smb_filename *smb_fname)
5526 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
5527 struct smb_file_time ft;
5528 uint32_t dosmode = 0;
5529 NTSTATUS status = NT_STATUS_OK;
5531 init_smb_file_time(&ft);
5533 if (total_data < 36) {
5534 return NT_STATUS_INVALID_PARAMETER;
5537 if (fsp == NULL) {
5538 return NT_STATUS_INVALID_HANDLE;
5541 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5542 if (!NT_STATUS_IS_OK(status)) {
5543 return status;
5546 /* Set the attributes */
5547 dosmode = IVAL(pdata,32);
5548 status = smb_set_file_dosmode(conn, fsp, dosmode);
5549 if (!NT_STATUS_IS_OK(status)) {
5550 return status;
5553 /* create time */
5554 ft.create_time = pull_long_date_full_timespec(pdata);
5556 /* access time */
5557 ft.atime = pull_long_date_full_timespec(pdata+8);
5559 /* write time. */
5560 ft.mtime = pull_long_date_full_timespec(pdata+16);
5562 /* change time. */
5563 ft.ctime = pull_long_date_full_timespec(pdata+24);
5565 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
5566 smb_fname_str_dbg(smb_fname)));
5568 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5569 if (!NT_STATUS_IS_OK(status)) {
5570 return status;
5573 if (fsp->fsp_flags.modified) {
5574 trigger_write_time_update_immediate(fsp);
5576 return NT_STATUS_OK;
5579 /****************************************************************************
5580 Deal with SMB_INFO_STANDARD.
5581 ****************************************************************************/
5583 static NTSTATUS smb_set_info_standard(connection_struct *conn,
5584 const char *pdata,
5585 int total_data,
5586 files_struct *fsp,
5587 struct smb_filename *smb_fname)
5589 NTSTATUS status;
5590 struct smb_file_time ft;
5592 init_smb_file_time(&ft);
5594 if (total_data < 12) {
5595 return NT_STATUS_INVALID_PARAMETER;
5598 if (fsp == NULL) {
5599 return NT_STATUS_INVALID_HANDLE;
5602 /* create time */
5603 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
5604 /* access time */
5605 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
5606 /* write time */
5607 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
5609 DEBUG(10,("smb_set_info_standard: file %s\n",
5610 smb_fname_str_dbg(smb_fname)));
5612 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
5613 if (!NT_STATUS_IS_OK(status)) {
5614 return status;
5617 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
5618 if (!NT_STATUS_IS_OK(status)) {
5619 return status;
5622 if (fsp->fsp_flags.modified) {
5623 trigger_write_time_update_immediate(fsp);
5625 return NT_STATUS_OK;
5628 /****************************************************************************
5629 Deal with SMB_SET_FILE_ALLOCATION_INFO.
5630 ****************************************************************************/
5632 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
5633 struct smb_request *req,
5634 const char *pdata,
5635 int total_data,
5636 files_struct *fsp,
5637 struct smb_filename *smb_fname)
5639 uint64_t allocation_size = 0;
5640 NTSTATUS status = NT_STATUS_OK;
5641 files_struct *new_fsp = NULL;
5643 if (!VALID_STAT(smb_fname->st)) {
5644 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5647 if (total_data < 8) {
5648 return NT_STATUS_INVALID_PARAMETER;
5651 allocation_size = (uint64_t)IVAL(pdata,0);
5652 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
5653 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
5654 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5655 (double)allocation_size));
5657 if (allocation_size) {
5658 allocation_size = smb_roundup(conn, allocation_size);
5661 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
5662 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
5663 (double)allocation_size));
5665 if (fsp &&
5666 !fsp->fsp_flags.is_pathref &&
5667 fsp_get_io_fd(fsp) != -1)
5669 /* Open file handle. */
5670 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
5671 return NT_STATUS_ACCESS_DENIED;
5674 /* Only change if needed. */
5675 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5676 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
5677 return map_nt_error_from_unix(errno);
5680 /* But always update the time. */
5682 * This is equivalent to a write. Ensure it's seen immediately
5683 * if there are no pending writes.
5685 trigger_write_time_update_immediate(fsp);
5686 return NT_STATUS_OK;
5689 /* Pathname or stat or directory file. */
5690 status = SMB_VFS_CREATE_FILE(
5691 conn, /* conn */
5692 req, /* req */
5693 NULL, /* dirfsp */
5694 smb_fname, /* fname */
5695 FILE_WRITE_DATA, /* access_mask */
5696 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
5697 FILE_SHARE_DELETE),
5698 FILE_OPEN, /* create_disposition*/
5699 0, /* create_options */
5700 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
5701 0, /* oplock_request */
5702 NULL, /* lease */
5703 0, /* allocation_size */
5704 0, /* private_flags */
5705 NULL, /* sd */
5706 NULL, /* ea_list */
5707 &new_fsp, /* result */
5708 NULL, /* pinfo */
5709 NULL, NULL); /* create context */
5711 if (!NT_STATUS_IS_OK(status)) {
5712 /* NB. We check for open_was_deferred in the caller. */
5713 return status;
5716 /* Only change if needed. */
5717 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
5718 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
5719 status = map_nt_error_from_unix(errno);
5720 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5721 return status;
5725 /* Changing the allocation size should set the last mod time. */
5727 * This is equivalent to a write. Ensure it's seen immediately
5728 * if there are no pending writes.
5730 trigger_write_time_update_immediate(new_fsp);
5731 close_file_free(req, &new_fsp, NORMAL_CLOSE);
5732 return NT_STATUS_OK;
5735 /****************************************************************************
5736 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
5737 ****************************************************************************/
5739 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
5740 struct smb_request *req,
5741 const char *pdata,
5742 int total_data,
5743 files_struct *fsp,
5744 struct smb_filename *smb_fname,
5745 bool fail_after_createfile)
5747 off_t size;
5749 if (total_data < 8) {
5750 return NT_STATUS_INVALID_PARAMETER;
5753 size = IVAL(pdata,0);
5754 size |= (((off_t)IVAL(pdata,4)) << 32);
5755 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
5756 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
5757 (double)size));
5759 return smb_set_file_size(conn, req,
5760 fsp,
5761 smb_fname,
5762 &smb_fname->st,
5763 size,
5764 fail_after_createfile);
5767 /****************************************************************************
5768 Allow a UNIX info mknod.
5769 ****************************************************************************/
5771 static NTSTATUS smb_unix_mknod(connection_struct *conn,
5772 const char *pdata,
5773 int total_data,
5774 const struct smb_filename *smb_fname)
5776 uint32_t file_type = IVAL(pdata,56);
5777 #if defined(HAVE_MAKEDEV)
5778 uint32_t dev_major = IVAL(pdata,60);
5779 uint32_t dev_minor = IVAL(pdata,68);
5780 #endif
5781 SMB_DEV_T dev = (SMB_DEV_T)0;
5782 uint32_t raw_unixmode = IVAL(pdata,84);
5783 NTSTATUS status;
5784 mode_t unixmode;
5785 int ret;
5786 struct smb_filename *parent_fname = NULL;
5787 struct smb_filename *base_name = NULL;
5789 if (total_data < 100) {
5790 return NT_STATUS_INVALID_PARAMETER;
5793 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5794 PERM_NEW_FILE, &unixmode);
5795 if (!NT_STATUS_IS_OK(status)) {
5796 return status;
5799 #if defined(HAVE_MAKEDEV)
5800 dev = makedev(dev_major, dev_minor);
5801 #endif
5803 switch (file_type) {
5804 /* We can't create other objects here. */
5805 case UNIX_TYPE_FILE:
5806 case UNIX_TYPE_DIR:
5807 case UNIX_TYPE_SYMLINK:
5808 return NT_STATUS_ACCESS_DENIED;
5809 #if defined(S_IFIFO)
5810 case UNIX_TYPE_FIFO:
5811 unixmode |= S_IFIFO;
5812 break;
5813 #endif
5814 #if defined(S_IFSOCK)
5815 case UNIX_TYPE_SOCKET:
5816 unixmode |= S_IFSOCK;
5817 break;
5818 #endif
5819 #if defined(S_IFCHR)
5820 case UNIX_TYPE_CHARDEV:
5821 /* This is only allowed for root. */
5822 if (get_current_uid(conn) != sec_initial_uid()) {
5823 return NT_STATUS_ACCESS_DENIED;
5825 unixmode |= S_IFCHR;
5826 break;
5827 #endif
5828 #if defined(S_IFBLK)
5829 case UNIX_TYPE_BLKDEV:
5830 if (get_current_uid(conn) != sec_initial_uid()) {
5831 return NT_STATUS_ACCESS_DENIED;
5833 unixmode |= S_IFBLK;
5834 break;
5835 #endif
5836 default:
5837 return NT_STATUS_INVALID_PARAMETER;
5840 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
5841 "%.0f mode 0%o for file %s\n", (double)dev,
5842 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
5844 status = parent_pathref(talloc_tos(),
5845 conn->cwd_fsp,
5846 smb_fname,
5847 &parent_fname,
5848 &base_name);
5849 if (!NT_STATUS_IS_OK(status)) {
5850 return status;
5853 /* Ok - do the mknod. */
5854 ret = SMB_VFS_MKNODAT(conn,
5855 parent_fname->fsp,
5856 base_name,
5857 unixmode,
5858 dev);
5860 if (ret != 0) {
5861 TALLOC_FREE(parent_fname);
5862 return map_nt_error_from_unix(errno);
5865 /* If any of the other "set" calls fail we
5866 * don't want to end up with a half-constructed mknod.
5869 if (lp_inherit_permissions(SNUM(conn))) {
5870 inherit_access_posix_acl(conn,
5871 parent_fname->fsp,
5872 smb_fname,
5873 unixmode);
5875 TALLOC_FREE(parent_fname);
5877 return NT_STATUS_OK;
5880 /****************************************************************************
5881 Deal with SMB_SET_FILE_UNIX_BASIC.
5882 ****************************************************************************/
5884 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
5885 struct smb_request *req,
5886 const char *pdata,
5887 int total_data,
5888 files_struct *fsp,
5889 struct smb_filename *smb_fname)
5891 struct smb_file_time ft;
5892 uint32_t raw_unixmode;
5893 mode_t unixmode;
5894 off_t size = 0;
5895 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
5896 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
5897 NTSTATUS status = NT_STATUS_OK;
5898 enum perm_type ptype;
5899 files_struct *all_fsps = NULL;
5900 bool modify_mtime = true;
5901 struct file_id id;
5902 SMB_STRUCT_STAT sbuf;
5904 init_smb_file_time(&ft);
5906 if (total_data < 100) {
5907 return NT_STATUS_INVALID_PARAMETER;
5910 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
5911 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
5912 size=IVAL(pdata,0); /* first 8 Bytes are size */
5913 size |= (((off_t)IVAL(pdata,4)) << 32);
5916 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
5917 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
5918 set_owner = (uid_t)IVAL(pdata,40);
5919 set_grp = (gid_t)IVAL(pdata,48);
5920 raw_unixmode = IVAL(pdata,84);
5922 if (VALID_STAT(smb_fname->st)) {
5923 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
5924 ptype = PERM_EXISTING_DIR;
5925 } else {
5926 ptype = PERM_EXISTING_FILE;
5928 } else {
5929 ptype = PERM_NEW_FILE;
5932 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
5933 ptype, &unixmode);
5934 if (!NT_STATUS_IS_OK(status)) {
5935 return status;
5938 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
5939 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
5940 smb_fname_str_dbg(smb_fname), (double)size,
5941 (unsigned int)set_owner, (unsigned int)set_grp,
5942 (int)raw_unixmode));
5944 sbuf = smb_fname->st;
5946 if (!VALID_STAT(sbuf)) {
5948 * The only valid use of this is to create character and block
5949 * devices, and named pipes. This is deprecated (IMHO) and
5950 * a new info level should be used for mknod. JRA.
5953 return smb_unix_mknod(conn,
5954 pdata,
5955 total_data,
5956 smb_fname);
5959 #if 1
5960 /* Horrible backwards compatibility hack as an old server bug
5961 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
5962 * */
5964 if (!size) {
5965 size = get_file_size_stat(&sbuf);
5967 #endif
5970 * Deal with the UNIX specific mode set.
5973 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
5974 int ret;
5976 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
5977 DBG_WARNING("Can't set mode on symlink %s\n",
5978 smb_fname_str_dbg(smb_fname));
5979 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
5982 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
5983 "setting mode 0%o for file %s\n",
5984 (unsigned int)unixmode,
5985 smb_fname_str_dbg(smb_fname)));
5986 ret = SMB_VFS_FCHMOD(fsp, unixmode);
5987 if (ret != 0) {
5988 return map_nt_error_from_unix(errno);
5993 * Deal with the UNIX specific uid set.
5996 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
5997 (sbuf.st_ex_uid != set_owner)) {
5998 int ret;
6000 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6001 "changing owner %u for path %s\n",
6002 (unsigned int)set_owner,
6003 smb_fname_str_dbg(smb_fname)));
6005 if (fsp &&
6006 !fsp->fsp_flags.is_pathref &&
6007 fsp_get_io_fd(fsp) != -1)
6009 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
6010 } else {
6012 * UNIX extensions calls must always operate
6013 * on symlinks.
6015 ret = SMB_VFS_LCHOWN(conn, smb_fname,
6016 set_owner, (gid_t)-1);
6019 if (ret != 0) {
6020 status = map_nt_error_from_unix(errno);
6021 return status;
6026 * Deal with the UNIX specific gid set.
6029 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
6030 (sbuf.st_ex_gid != set_grp)) {
6031 int ret;
6033 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
6034 "changing group %u for file %s\n",
6035 (unsigned int)set_grp,
6036 smb_fname_str_dbg(smb_fname)));
6037 if (fsp &&
6038 !fsp->fsp_flags.is_pathref &&
6039 fsp_get_io_fd(fsp) != -1)
6041 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
6042 } else {
6044 * UNIX extensions calls must always operate
6045 * on symlinks.
6047 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
6048 set_grp);
6050 if (ret != 0) {
6051 status = map_nt_error_from_unix(errno);
6052 return status;
6056 /* Deal with any size changes. */
6058 if (S_ISREG(sbuf.st_ex_mode)) {
6059 status = smb_set_file_size(conn, req,
6060 fsp,
6061 smb_fname,
6062 &sbuf,
6063 size,
6064 false);
6065 if (!NT_STATUS_IS_OK(status)) {
6066 return status;
6070 /* Deal with any time changes. */
6071 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
6072 /* No change, don't cancel anything. */
6073 return status;
6076 id = vfs_file_id_from_sbuf(conn, &sbuf);
6077 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
6078 all_fsps = file_find_di_next(all_fsps, true)) {
6080 * We're setting the time explicitly for UNIX.
6081 * Cancel any pending changes over all handles.
6083 all_fsps->fsp_flags.update_write_time_on_close = false;
6084 TALLOC_FREE(all_fsps->update_write_time_event);
6088 * Override the "setting_write_time"
6089 * parameter here as it almost does what
6090 * we need. Just remember if we modified
6091 * mtime and send the notify ourselves.
6093 if (is_omit_timespec(&ft.mtime)) {
6094 modify_mtime = false;
6097 status = smb_set_file_time(conn,
6098 fsp,
6099 smb_fname,
6100 &ft,
6101 false);
6102 if (modify_mtime) {
6103 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
6104 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
6106 return status;
6109 /****************************************************************************
6110 Deal with SMB_SET_FILE_UNIX_INFO2.
6111 ****************************************************************************/
6113 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
6114 struct smb_request *req,
6115 const char *pdata,
6116 int total_data,
6117 files_struct *fsp,
6118 struct smb_filename *smb_fname)
6120 NTSTATUS status;
6121 uint32_t smb_fflags;
6122 uint32_t smb_fmask;
6124 if (total_data < 116) {
6125 return NT_STATUS_INVALID_PARAMETER;
6128 /* Start by setting all the fields that are common between UNIX_BASIC
6129 * and UNIX_INFO2.
6131 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
6132 fsp, smb_fname);
6133 if (!NT_STATUS_IS_OK(status)) {
6134 return status;
6137 smb_fflags = IVAL(pdata, 108);
6138 smb_fmask = IVAL(pdata, 112);
6140 /* NB: We should only attempt to alter the file flags if the client
6141 * sends a non-zero mask.
6143 if (smb_fmask != 0) {
6144 int stat_fflags = 0;
6146 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
6147 smb_fmask, &stat_fflags)) {
6148 /* Client asked to alter a flag we don't understand. */
6149 return NT_STATUS_INVALID_PARAMETER;
6152 if (fsp == NULL || S_ISLNK(smb_fname->st.st_ex_mode)) {
6153 DBG_WARNING("Can't change flags on symlink %s\n",
6154 smb_fname_str_dbg(smb_fname));
6155 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6157 if (SMB_VFS_FCHFLAGS(fsp, stat_fflags) != 0) {
6158 return map_nt_error_from_unix(errno);
6162 /* XXX: need to add support for changing the create_time here. You
6163 * can do this for paths on Darwin with setattrlist(2). The right way
6164 * to hook this up is probably by extending the VFS utimes interface.
6167 return NT_STATUS_OK;
6170 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
6171 struct smb_request *req,
6172 TALLOC_CTX *mem_ctx,
6173 uint16_t info_level,
6174 struct smb_filename *smb_fname,
6175 files_struct *fsp,
6176 char **ppdata,
6177 int total_data,
6178 int *ret_data_size)
6180 char *pdata = *ppdata;
6181 NTSTATUS status = NT_STATUS_OK;
6182 int data_return_size = 0;
6184 *ret_data_size = 0;
6186 if (!CAN_WRITE(conn)) {
6187 /* Allow POSIX opens. The open path will deny
6188 * any non-readonly opens. */
6189 if (info_level != SMB_POSIX_PATH_OPEN) {
6190 return NT_STATUS_DOS(ERRSRV, ERRaccess);
6194 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
6195 smb_fname_str_dbg(smb_fname),
6196 fsp_fnum_dbg(fsp),
6197 info_level,
6198 total_data);
6200 switch (info_level) {
6201 case SMB_SET_FILE_UNIX_BASIC:
6203 status = smb_set_file_unix_basic(conn, req,
6204 pdata,
6205 total_data,
6206 fsp,
6207 smb_fname);
6208 break;
6211 case SMB_SET_FILE_UNIX_INFO2:
6213 status = smb_set_file_unix_info2(conn, req,
6214 pdata,
6215 total_data,
6216 fsp,
6217 smb_fname);
6218 break;
6221 #if defined(HAVE_POSIX_ACLS)
6222 case SMB_SET_POSIX_ACL:
6224 status = smb_set_posix_acl(conn,
6225 req,
6226 pdata,
6227 total_data,
6228 fsp,
6229 smb_fname);
6230 break;
6232 #endif
6234 #if defined(WITH_SMB1SERVER)
6235 case SMB_SET_POSIX_LOCK:
6237 if (fsp == NULL) {
6238 return NT_STATUS_INVALID_LEVEL;
6240 status = smb_set_posix_lock(conn, req,
6241 pdata, total_data, fsp);
6242 break;
6244 #endif
6246 default:
6247 return NT_STATUS_INVALID_LEVEL;
6250 if (!NT_STATUS_IS_OK(status)) {
6251 return status;
6254 *ret_data_size = data_return_size;
6255 return NT_STATUS_OK;
6258 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
6259 struct smb_request *req,
6260 TALLOC_CTX *mem_ctx,
6261 uint16_t info_level,
6262 files_struct *fsp,
6263 struct smb_filename *smb_fname,
6264 char **ppdata, int total_data,
6265 int *ret_data_size)
6267 char *pdata = *ppdata;
6268 NTSTATUS status = NT_STATUS_OK;
6269 int data_return_size = 0;
6271 if (INFO_LEVEL_IS_UNIX(info_level)) {
6272 if (!lp_smb1_unix_extensions()) {
6273 return NT_STATUS_INVALID_LEVEL;
6275 if (!req->posix_pathnames) {
6276 return NT_STATUS_INVALID_LEVEL;
6278 status = smbd_do_posix_setfilepathinfo(conn,
6279 req,
6280 req,
6281 info_level,
6282 smb_fname,
6283 fsp,
6284 ppdata,
6285 total_data,
6286 &data_return_size);
6287 if (!NT_STATUS_IS_OK(status)) {
6288 return status;
6290 *ret_data_size = data_return_size;
6291 return NT_STATUS_OK;
6294 *ret_data_size = 0;
6296 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
6297 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
6298 fsp_fnum_dbg(fsp),
6299 info_level, total_data));
6301 switch (info_level) {
6303 case SMB_INFO_STANDARD:
6305 status = smb_set_info_standard(conn,
6306 pdata,
6307 total_data,
6308 fsp,
6309 smb_fname);
6310 break;
6313 case SMB_INFO_SET_EA:
6315 status = smb_info_set_ea(conn,
6316 pdata,
6317 total_data,
6318 fsp,
6319 smb_fname);
6320 break;
6323 case SMB_SET_FILE_BASIC_INFO:
6324 case SMB_FILE_BASIC_INFORMATION:
6326 status = smb_set_file_basic_info(conn,
6327 pdata,
6328 total_data,
6329 fsp,
6330 smb_fname);
6331 break;
6334 case SMB_FILE_ALLOCATION_INFORMATION:
6335 case SMB_SET_FILE_ALLOCATION_INFO:
6337 status = smb_set_file_allocation_info(conn, req,
6338 pdata,
6339 total_data,
6340 fsp,
6341 smb_fname);
6342 break;
6345 case SMB_FILE_END_OF_FILE_INFORMATION:
6346 case SMB_SET_FILE_END_OF_FILE_INFO:
6349 * XP/Win7 both fail after the createfile with
6350 * SMB_SET_FILE_END_OF_FILE_INFO but not
6351 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
6352 * The level is known here, so pass it down
6353 * appropriately.
6355 bool should_fail =
6356 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
6358 status = smb_set_file_end_of_file_info(conn, req,
6359 pdata,
6360 total_data,
6361 fsp,
6362 smb_fname,
6363 should_fail);
6364 break;
6367 case SMB_FILE_DISPOSITION_INFORMATION:
6368 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
6370 #if 0
6371 /* JRA - We used to just ignore this on a path ?
6372 * Shouldn't this be invalid level on a pathname
6373 * based call ?
6375 if (tran_call != TRANSACT2_SETFILEINFO) {
6376 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
6378 #endif
6379 status = smb_set_file_disposition_info(conn,
6380 pdata,
6381 total_data,
6382 fsp,
6383 smb_fname);
6384 break;
6387 case SMB_FILE_POSITION_INFORMATION:
6389 status = smb_file_position_information(conn,
6390 pdata,
6391 total_data,
6392 fsp);
6393 break;
6396 case SMB_FILE_FULL_EA_INFORMATION:
6398 status = smb_set_file_full_ea_info(conn,
6399 pdata,
6400 total_data,
6401 fsp);
6402 break;
6405 /* From tridge Samba4 :
6406 * MODE_INFORMATION in setfileinfo (I have no
6407 * idea what "mode information" on a file is - it takes a value of 0,
6408 * 2, 4 or 6. What could it be?).
6411 case SMB_FILE_MODE_INFORMATION:
6413 status = smb_file_mode_information(conn,
6414 pdata,
6415 total_data);
6416 break;
6419 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
6420 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
6421 case SMB_FILE_SHORT_NAME_INFORMATION:
6422 return NT_STATUS_NOT_SUPPORTED;
6424 case SMB_FILE_RENAME_INFORMATION:
6426 status = smb_file_rename_information(conn, req,
6427 pdata, total_data,
6428 fsp, smb_fname);
6429 break;
6432 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
6434 /* SMB2 rename information. */
6435 status = smb2_file_rename_information(conn, req,
6436 pdata, total_data,
6437 fsp, smb_fname);
6438 break;
6441 case SMB_FILE_LINK_INFORMATION:
6443 status = smb_file_link_information(conn, req,
6444 pdata, total_data,
6445 fsp, smb_fname);
6446 break;
6449 default:
6450 return NT_STATUS_INVALID_LEVEL;
6453 if (!NT_STATUS_IS_OK(status)) {
6454 return status;
6457 *ret_data_size = data_return_size;
6458 return NT_STATUS_OK;
6461 static uint32_t generate_volume_serial_number(
6462 const struct loadparm_substitution *lp_sub,
6463 int snum)
6465 int serial = lp_volume_serial_number(snum);
6466 return serial != -1 ? serial:
6467 str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
6468 (str_checksum(get_local_machine_name())<<16);