s3/smbd: Remove connection_struct from get_ea_names_from_file
[Samba.git] / source3 / smbd / trans2.c
blobfb528eceeb60b98b80f0ae8a86ff564f3954a209
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 "smb1_utils.h"
46 #include "libcli/smb/smb2_posix.h"
47 #include "lib/util/string_wrappers.h"
49 #define DIR_ENTRY_SAFETY_MARGIN 4096
51 static char *store_file_unix_basic(connection_struct *conn,
52 char *pdata,
53 files_struct *fsp,
54 const SMB_STRUCT_STAT *psbuf);
56 static char *store_file_unix_basic_info2(connection_struct *conn,
57 char *pdata,
58 files_struct *fsp,
59 const SMB_STRUCT_STAT *psbuf);
61 /****************************************************************************
62 Check if an open file handle or smb_fname is a symlink.
63 ****************************************************************************/
65 static NTSTATUS refuse_symlink(connection_struct *conn,
66 const files_struct *fsp,
67 const struct smb_filename *smb_fname)
69 SMB_STRUCT_STAT sbuf;
70 const SMB_STRUCT_STAT *pst = NULL;
72 if (fsp) {
73 pst = &fsp->fsp_name->st;
74 } else {
75 pst = &smb_fname->st;
78 if (!VALID_STAT(*pst)) {
79 int ret = vfs_stat_smb_basename(conn,
80 smb_fname,
81 &sbuf);
82 if (ret == -1 && errno != ENOENT) {
83 return map_nt_error_from_unix(errno);
84 } else if (ret == -1) {
85 /* it's not a symlink.. */
86 return NT_STATUS_OK;
88 pst = &sbuf;
91 if (S_ISLNK(pst->st_ex_mode)) {
92 return NT_STATUS_ACCESS_DENIED;
94 return NT_STATUS_OK;
97 NTSTATUS check_access_fsp(struct files_struct *fsp,
98 uint32_t access_mask)
100 if (!fsp->fsp_flags.is_fsa) {
101 return smbd_check_access_rights_fsp(fsp,
102 false,
103 access_mask);
105 if (!(fsp->access_mask & access_mask)) {
106 return NT_STATUS_ACCESS_DENIED;
108 return NT_STATUS_OK;
111 #if defined(HAVE_POSIX_ACLS)
112 /****************************************************************************
113 Utility function to open a fsp for a POSIX handle operation.
114 ****************************************************************************/
116 static NTSTATUS get_posix_fsp(connection_struct *conn,
117 struct smb_request *req,
118 struct smb_filename *smb_fname,
119 uint32_t access_mask,
120 files_struct **ret_fsp)
122 NTSTATUS status;
123 uint32_t create_disposition = FILE_OPEN;
124 uint32_t share_access = FILE_SHARE_READ|
125 FILE_SHARE_WRITE|
126 FILE_SHARE_DELETE;
127 struct smb2_create_blobs *posx = NULL;
130 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
131 * but set reasonable defaults.
133 uint32_t file_attributes = 0664;
134 uint32_t oplock = NO_OPLOCK;
135 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
137 /* File or directory must exist. */
138 if (!VALID_STAT(smb_fname->st)) {
139 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
141 /* Cannot be a symlink. */
142 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
143 return NT_STATUS_ACCESS_DENIED;
145 /* Set options correctly for directory open. */
146 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
148 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
149 * directories, but set reasonable defaults.
151 file_attributes = 0775;
152 create_options = FILE_DIRECTORY_FILE;
155 status = make_smb2_posix_create_ctx(
156 talloc_tos(), &posx, file_attributes);
157 if (!NT_STATUS_IS_OK(status)) {
158 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
159 nt_errstr(status));
160 goto done;
163 status = SMB_VFS_CREATE_FILE(
164 conn, /* conn */
165 req, /* req */
166 smb_fname, /* fname */
167 access_mask, /* access_mask */
168 share_access, /* share_access */
169 create_disposition,/* create_disposition*/
170 create_options, /* create_options */
171 file_attributes,/* file_attributes */
172 oplock, /* oplock_request */
173 NULL, /* lease */
174 0, /* allocation_size */
175 0, /* private_flags */
176 NULL, /* sd */
177 NULL, /* ea_list */
178 ret_fsp, /* result */
179 NULL, /* pinfo */
180 posx, /* in_context */
181 NULL); /* out_context */
183 done:
184 TALLOC_FREE(posx);
185 return status;
187 #endif
189 /********************************************************************
190 Roundup a value to the nearest allocation roundup size boundary.
191 Only do this for Windows clients.
192 ********************************************************************/
194 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
196 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
198 /* Only roundup for Windows clients. */
199 enum remote_arch_types ra_type = get_remote_arch();
200 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
201 val = SMB_ROUNDUP(val,rval);
203 return val;
206 /****************************************************************************
207 Utility functions for dealing with extended attributes.
208 ****************************************************************************/
210 /****************************************************************************
211 Refuse to allow clients to overwrite our private xattrs.
212 ****************************************************************************/
214 bool samba_private_attr_name(const char *unix_ea_name)
216 static const char * const prohibited_ea_names[] = {
217 SAMBA_POSIX_INHERITANCE_EA_NAME,
218 SAMBA_XATTR_DOS_ATTRIB,
219 SAMBA_XATTR_MARKER,
220 XATTR_NTACL_NAME,
221 NULL
224 int i;
226 for (i = 0; prohibited_ea_names[i]; i++) {
227 if (strequal( prohibited_ea_names[i], unix_ea_name))
228 return true;
230 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
231 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
232 return true;
234 return false;
237 /****************************************************************************
238 Get one EA value. Fill in a struct ea_struct.
239 ****************************************************************************/
241 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
242 connection_struct *conn,
243 files_struct *fsp,
244 const struct smb_filename *smb_fname,
245 const char *ea_name,
246 struct ea_struct *pea)
248 /* Get the value of this xattr. Max size is 64k. */
249 size_t attr_size = 256;
250 char *val = NULL;
251 ssize_t sizeret;
253 again:
255 val = talloc_realloc(mem_ctx, val, char, attr_size);
256 if (!val) {
257 return NT_STATUS_NO_MEMORY;
260 if (fsp && !fsp->fsp_flags.is_pathref && fsp_get_io_fd(fsp) != -1) {
261 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
262 } else {
263 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
264 ea_name, val, attr_size);
267 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
268 attr_size = 65536;
269 goto again;
272 if (sizeret == -1) {
273 return map_nt_error_from_unix(errno);
276 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
277 dump_data(10, (uint8_t *)val, sizeret);
279 pea->flags = 0;
280 if (strnequal(ea_name, "user.", 5)) {
281 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
282 } else {
283 pea->name = talloc_strdup(mem_ctx, ea_name);
285 if (pea->name == NULL) {
286 TALLOC_FREE(val);
287 return NT_STATUS_NO_MEMORY;
289 pea->value.data = (unsigned char *)val;
290 pea->value.length = (size_t)sizeret;
291 return NT_STATUS_OK;
294 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
295 files_struct *fsp,
296 char ***pnames,
297 size_t *pnum_names)
299 char smallbuf[1024];
300 /* Get a list of all xattrs. Max namesize is 64k. */
301 size_t ea_namelist_size = 1024;
302 char *ea_namelist = smallbuf;
303 char *to_free = NULL;
305 char *p;
306 char **names;
307 size_t num_names;
308 ssize_t sizeret = -1;
309 NTSTATUS status;
311 if (pnames) {
312 *pnames = NULL;
314 *pnum_names = 0;
316 if (fsp == NULL) {
318 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
319 * symlink. This is ok, handle it here, by just return no EA's
320 * on a symlink.
322 return NT_STATUS_OK;
325 /* should be the case that fsp != NULL */
326 SMB_ASSERT(fsp != NULL);
328 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
329 ea_namelist_size);
331 if ((sizeret == -1) && (errno == ERANGE)) {
332 ea_namelist_size = 65536;
333 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
334 if (ea_namelist == NULL) {
335 return NT_STATUS_NO_MEMORY;
337 to_free = ea_namelist;
339 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
340 ea_namelist_size);
343 if (sizeret == -1) {
344 status = map_nt_error_from_unix(errno);
345 TALLOC_FREE(to_free);
346 return status;
349 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
351 if (sizeret == 0) {
352 TALLOC_FREE(to_free);
353 return NT_STATUS_OK;
357 * Ensure the result is 0-terminated
360 if (ea_namelist[sizeret-1] != '\0') {
361 TALLOC_FREE(to_free);
362 return NT_STATUS_INTERNAL_ERROR;
366 * count the names
368 num_names = 0;
370 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
371 num_names += 1;
374 *pnum_names = num_names;
376 if (pnames == NULL) {
377 TALLOC_FREE(to_free);
378 return NT_STATUS_OK;
381 names = talloc_array(mem_ctx, char *, num_names);
382 if (names == NULL) {
383 DEBUG(0, ("talloc failed\n"));
384 TALLOC_FREE(to_free);
385 return NT_STATUS_NO_MEMORY;
388 if (ea_namelist == smallbuf) {
389 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
390 if (ea_namelist == NULL) {
391 TALLOC_FREE(names);
392 return NT_STATUS_NO_MEMORY;
394 } else {
395 talloc_steal(names, ea_namelist);
397 ea_namelist = talloc_realloc(names, ea_namelist, char,
398 sizeret);
399 if (ea_namelist == NULL) {
400 TALLOC_FREE(names);
401 return NT_STATUS_NO_MEMORY;
405 num_names = 0;
407 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
408 names[num_names++] = p;
411 *pnames = names;
413 return NT_STATUS_OK;
416 /****************************************************************************
417 Return a linked list of the total EA's. Plus the total size
418 ****************************************************************************/
420 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
421 files_struct *fsp,
422 size_t *pea_total_len,
423 struct ea_list **ea_list)
425 /* Get a list of all xattrs. Max namesize is 64k. */
426 size_t i, num_names;
427 char **names;
428 struct ea_list *ea_list_head = NULL;
429 bool posix_pathnames = false;
430 NTSTATUS status;
432 *pea_total_len = 0;
433 *ea_list = NULL;
435 /* symlink */
436 if (fsp == NULL) {
437 return NT_STATUS_OK;
440 if (!lp_ea_support(SNUM(fsp->conn))) {
441 return NT_STATUS_OK;
444 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
445 return NT_STATUS_INVALID_PARAMETER;
448 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
450 status = get_ea_names_from_file(talloc_tos(),
451 fsp,
452 &names,
453 &num_names);
455 if (!NT_STATUS_IS_OK(status)) {
456 return status;
459 if (num_names == 0) {
460 return NT_STATUS_OK;
463 for (i=0; i<num_names; i++) {
464 struct ea_list *listp;
465 fstring dos_ea_name;
467 if (strnequal(names[i], "system.", 7)
468 || samba_private_attr_name(names[i]))
469 continue;
472 * Filter out any underlying POSIX EA names
473 * that a Windows client can't handle.
475 if (!posix_pathnames &&
476 is_invalid_windows_ea_name(names[i])) {
477 continue;
480 listp = talloc(mem_ctx, struct ea_list);
481 if (listp == NULL) {
482 return NT_STATUS_NO_MEMORY;
485 status = get_ea_value(listp,
486 fsp->conn,
487 fsp,
488 fsp->fsp_name,
489 names[i],
490 &listp->ea);
492 if (!NT_STATUS_IS_OK(status)) {
493 TALLOC_FREE(listp);
494 return status;
497 if (listp->ea.value.length == 0) {
499 * We can never return a zero length EA.
500 * Windows reports the EA's as corrupted.
502 TALLOC_FREE(listp);
503 continue;
506 push_ascii_fstring(dos_ea_name, listp->ea.name);
508 *pea_total_len +=
509 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
511 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
512 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
513 (unsigned int)listp->ea.value.length));
515 DLIST_ADD_END(ea_list_head, listp);
519 /* Add on 4 for total length. */
520 if (*pea_total_len) {
521 *pea_total_len += 4;
524 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
525 (unsigned int)*pea_total_len));
527 *ea_list = ea_list_head;
528 return NT_STATUS_OK;
531 /****************************************************************************
532 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
533 that was filled.
534 ****************************************************************************/
536 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
537 connection_struct *conn, struct ea_list *ea_list)
539 unsigned int ret_data_size = 4;
540 char *p = pdata;
542 SMB_ASSERT(total_data_size >= 4);
544 if (!lp_ea_support(SNUM(conn))) {
545 SIVAL(pdata,4,0);
546 return 4;
549 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
550 size_t dos_namelen;
551 fstring dos_ea_name;
552 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
553 dos_namelen = strlen(dos_ea_name);
554 if (dos_namelen > 255 || dos_namelen == 0) {
555 break;
557 if (ea_list->ea.value.length > 65535) {
558 break;
560 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
561 break;
564 /* We know we have room. */
565 SCVAL(p,0,ea_list->ea.flags);
566 SCVAL(p,1,dos_namelen);
567 SSVAL(p,2,ea_list->ea.value.length);
568 strlcpy(p+4, dos_ea_name, dos_namelen+1);
569 if (ea_list->ea.value.length > 0) {
570 memcpy(p + 4 + dos_namelen + 1,
571 ea_list->ea.value.data,
572 ea_list->ea.value.length);
575 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
576 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
579 ret_data_size = PTR_DIFF(p, pdata);
580 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
581 SIVAL(pdata,0,ret_data_size);
582 return ret_data_size;
585 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
586 char *pdata,
587 unsigned int total_data_size,
588 unsigned int *ret_data_size,
589 connection_struct *conn,
590 struct ea_list *ea_list)
592 uint8_t *p = (uint8_t *)pdata;
593 uint8_t *last_start = NULL;
594 bool do_store_data = (pdata != NULL);
596 *ret_data_size = 0;
598 if (!lp_ea_support(SNUM(conn))) {
599 return NT_STATUS_NO_EAS_ON_FILE;
602 for (; ea_list; ea_list = ea_list->next) {
603 size_t dos_namelen;
604 fstring dos_ea_name;
605 size_t this_size;
606 size_t pad = 0;
608 if (last_start != NULL && do_store_data) {
609 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
611 last_start = p;
613 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
614 dos_namelen = strlen(dos_ea_name);
615 if (dos_namelen > 255 || dos_namelen == 0) {
616 return NT_STATUS_INTERNAL_ERROR;
618 if (ea_list->ea.value.length > 65535) {
619 return NT_STATUS_INTERNAL_ERROR;
622 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
624 if (ea_list->next) {
625 pad = (4 - (this_size % 4)) % 4;
626 this_size += pad;
629 if (do_store_data) {
630 if (this_size > total_data_size) {
631 return NT_STATUS_INFO_LENGTH_MISMATCH;
634 /* We know we have room. */
635 SIVAL(p, 0x00, 0); /* next offset */
636 SCVAL(p, 0x04, ea_list->ea.flags);
637 SCVAL(p, 0x05, dos_namelen);
638 SSVAL(p, 0x06, ea_list->ea.value.length);
639 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
640 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
641 if (pad) {
642 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
643 '\0',
644 pad);
646 total_data_size -= this_size;
649 p += this_size;
652 *ret_data_size = PTR_DIFF(p, pdata);
653 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
654 return NT_STATUS_OK;
657 static unsigned int estimate_ea_size(files_struct *fsp)
659 size_t total_ea_len = 0;
660 TALLOC_CTX *mem_ctx;
661 struct ea_list *ea_list = NULL;
662 NTSTATUS status;
664 /* symlink */
665 if (fsp == NULL) {
666 return 0;
669 mem_ctx = talloc_stackframe();
670 if (!lp_ea_support(SNUM(fsp->conn))) {
671 return 0;
674 /* If this is a stream fsp, then we need to instead find the
675 * estimated ea len from the main file, not the stream
676 * (streams cannot have EAs), but the estimate isn't just 0 in
677 * this case! */
678 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
679 fsp = fsp->base_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 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
753 status = refuse_symlink(conn, fsp, fsp->fsp_name);
754 if (!NT_STATUS_IS_OK(status)) {
755 return status;
758 status = check_access_fsp(fsp, FILE_WRITE_EA);
759 if (!NT_STATUS_IS_OK(status)) {
760 return status;
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
765 return NT_STATUS_INVALID_PARAMETER;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
774 return STATUS_INVALID_EA_NAME;
777 for (;ea_list; ea_list = ea_list->next) {
778 int ret;
779 fstring unix_ea_name;
781 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name, ea_list->ea.name);
784 canonicalize_ea_name(fsp, unix_ea_name);
786 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
788 if (samba_private_attr_name(unix_ea_name)) {
789 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
790 return NT_STATUS_ACCESS_DENIED;
793 if (ea_list->ea.value.length == 0) {
794 /* Remove the attribute. */
795 if (!fsp->fsp_flags.is_pathref &&
796 fsp_get_io_fd(fsp) != -1)
798 DEBUG(10,("set_ea: deleting ea name %s on "
799 "file %s by file descriptor.\n",
800 unix_ea_name, fsp_str_dbg(fsp)));
801 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
802 } else {
803 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
804 unix_ea_name, fsp->fsp_name->base_name));
805 ret = SMB_VFS_REMOVEXATTR(conn,
806 fsp->fsp_name,
807 unix_ea_name);
809 #ifdef ENOATTR
810 /* Removing a non existent attribute always succeeds. */
811 if (ret == -1 && errno == ENOATTR) {
812 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
813 unix_ea_name));
814 ret = 0;
816 #endif
817 } else {
818 if (!fsp->fsp_flags.is_pathref &&
819 fsp_get_io_fd(fsp) != -1)
821 DEBUG(10,("set_ea: setting ea name %s on file "
822 "%s by file descriptor.\n",
823 unix_ea_name, fsp_str_dbg(fsp)));
824 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
825 ea_list->ea.value.data, ea_list->ea.value.length, 0);
826 } else {
827 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
828 unix_ea_name, fsp->fsp_name->base_name));
829 ret = SMB_VFS_SETXATTR(conn,
830 fsp->fsp_name,
831 unix_ea_name,
832 ea_list->ea.value.data,
833 ea_list->ea.value.length,
838 if (ret == -1) {
839 #ifdef ENOTSUP
840 if (errno == ENOTSUP) {
841 return NT_STATUS_EAS_NOT_SUPPORTED;
843 #endif
844 return map_nt_error_from_unix(errno);
848 return NT_STATUS_OK;
850 /****************************************************************************
851 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
852 ****************************************************************************/
854 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
856 struct ea_list *ea_list_head = NULL;
857 size_t converted_size, offset = 0;
859 while (offset + 2 < data_size) {
860 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
861 unsigned int namelen = CVAL(pdata,offset);
863 offset++; /* Go past the namelen byte. */
865 /* integer wrap paranioa. */
866 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
867 (offset > data_size) || (namelen > data_size) ||
868 (offset + namelen >= data_size)) {
869 break;
871 /* Ensure the name is null terminated. */
872 if (pdata[offset + namelen] != '\0') {
873 return NULL;
875 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
876 &converted_size)) {
877 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
878 "failed: %s", strerror(errno)));
880 if (!eal->ea.name) {
881 return NULL;
884 offset += (namelen + 1); /* Go past the name + terminating zero. */
885 DLIST_ADD_END(ea_list_head, eal);
886 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
889 return ea_list_head;
892 /****************************************************************************
893 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
894 ****************************************************************************/
896 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
898 struct ea_list *ea_list_head = NULL;
899 size_t offset = 0;
900 size_t bytes_used = 0;
902 while (offset < data_size) {
903 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
905 if (!eal) {
906 return NULL;
909 DLIST_ADD_END(ea_list_head, eal);
910 offset += bytes_used;
913 return ea_list_head;
916 /****************************************************************************
917 Count the total EA size needed.
918 ****************************************************************************/
920 static size_t ea_list_size(struct ea_list *ealist)
922 fstring dos_ea_name;
923 struct ea_list *listp;
924 size_t ret = 0;
926 for (listp = ealist; listp; listp = listp->next) {
927 push_ascii_fstring(dos_ea_name, listp->ea.name);
928 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
930 /* Add on 4 for total length. */
931 if (ret) {
932 ret += 4;
935 return ret;
938 /****************************************************************************
939 Return a union of EA's from a file list and a list of names.
940 The TALLOC context for the two lists *MUST* be identical as we steal
941 memory from one list to add to another. JRA.
942 ****************************************************************************/
944 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
946 struct ea_list *nlistp, *flistp;
948 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
949 for (flistp = file_list; flistp; flistp = flistp->next) {
950 if (strequal(nlistp->ea.name, flistp->ea.name)) {
951 break;
955 if (flistp) {
956 /* Copy the data from this entry. */
957 nlistp->ea.flags = flistp->ea.flags;
958 nlistp->ea.value = flistp->ea.value;
959 } else {
960 /* Null entry. */
961 nlistp->ea.flags = 0;
962 ZERO_STRUCT(nlistp->ea.value);
966 *total_ea_len = ea_list_size(name_list);
967 return name_list;
970 /****************************************************************************
971 Send the required number of replies back.
972 We assume all fields other than the data fields are
973 set correctly for the type of call.
974 HACK ! Always assumes smb_setup field is zero.
975 ****************************************************************************/
977 void send_trans2_replies(connection_struct *conn,
978 struct smb_request *req,
979 NTSTATUS status,
980 const char *params,
981 int paramsize,
982 const char *pdata,
983 int datasize,
984 int max_data_bytes)
986 /* As we are using a protocol > LANMAN1 then the max_send
987 variable must have been set in the sessetupX call.
988 This takes precedence over the max_xmit field in the
989 global struct. These different max_xmit variables should
990 be merged as this is now too confusing */
992 int data_to_send = datasize;
993 int params_to_send = paramsize;
994 int useable_space;
995 const char *pp = params;
996 const char *pd = pdata;
997 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
998 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
999 int data_alignment_offset = 0;
1000 bool overflow = False;
1001 struct smbXsrv_connection *xconn = req->xconn;
1002 int max_send = xconn->smb1.sessions.max_send;
1004 /* Modify the data_to_send and datasize and set the error if
1005 we're trying to send more than max_data_bytes. We still send
1006 the part of the packet(s) that fit. Strange, but needed
1007 for OS/2. */
1009 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1010 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1011 max_data_bytes, datasize ));
1012 datasize = data_to_send = max_data_bytes;
1013 overflow = True;
1016 /* If there genuinely are no parameters or data to send just send the empty packet */
1018 if(params_to_send == 0 && data_to_send == 0) {
1019 reply_outbuf(req, 10, 0);
1020 if (NT_STATUS_V(status)) {
1021 uint8_t eclass;
1022 uint32_t ecode;
1023 ntstatus_to_dos(status, &eclass, &ecode);
1024 error_packet_set((char *)req->outbuf,
1025 eclass, ecode, status,
1026 __LINE__,__FILE__);
1028 show_msg((char *)req->outbuf);
1029 if (!srv_send_smb(xconn,
1030 (char *)req->outbuf,
1031 true, req->seqnum+1,
1032 IS_CONN_ENCRYPTED(conn),
1033 &req->pcd)) {
1034 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1036 TALLOC_FREE(req->outbuf);
1037 return;
1040 /* When sending params and data ensure that both are nicely aligned */
1041 /* Only do this alignment when there is also data to send - else
1042 can cause NT redirector problems. */
1044 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1045 data_alignment_offset = 4 - (params_to_send % 4);
1047 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1048 /* The alignment_offset is to align the param bytes on an even byte
1049 boundary. NT 4.0 Beta needs this to work correctly. */
1051 useable_space = max_send - (smb_size
1052 + 2 * 10 /* wct */
1053 + alignment_offset
1054 + data_alignment_offset);
1056 if (useable_space < 0) {
1057 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1058 "= %d!!!", useable_space));
1059 exit_server_cleanly("send_trans2_replies: Not enough space");
1062 while (params_to_send || data_to_send) {
1063 /* Calculate whether we will totally or partially fill this packet */
1065 total_sent_thistime = params_to_send + data_to_send;
1067 /* We can never send more than useable_space */
1069 * Note that 'useable_space' does not include the alignment offsets,
1070 * but we must include the alignment offsets in the calculation of
1071 * the length of the data we send over the wire, as the alignment offsets
1072 * are sent here. Fix from Marc_Jacobsen@hp.com.
1075 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1077 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1078 + data_alignment_offset);
1080 /* Set total params and data to be sent */
1081 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1082 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1084 /* Calculate how many parameters and data we can fit into
1085 * this packet. Parameters get precedence
1088 params_sent_thistime = MIN(params_to_send,useable_space);
1089 data_sent_thistime = useable_space - params_sent_thistime;
1090 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1092 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1094 /* smb_proff is the offset from the start of the SMB header to the
1095 parameter bytes, however the first 4 bytes of outbuf are
1096 the Netbios over TCP header. Thus use smb_base() to subtract
1097 them from the calculation */
1099 SSVAL(req->outbuf,smb_proff,
1100 ((smb_buf(req->outbuf)+alignment_offset)
1101 - smb_base(req->outbuf)));
1103 if(params_sent_thistime == 0)
1104 SSVAL(req->outbuf,smb_prdisp,0);
1105 else
1106 /* Absolute displacement of param bytes sent in this packet */
1107 SSVAL(req->outbuf,smb_prdisp,pp - params);
1109 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1110 if(data_sent_thistime == 0) {
1111 SSVAL(req->outbuf,smb_droff,0);
1112 SSVAL(req->outbuf,smb_drdisp, 0);
1113 } else {
1114 /* The offset of the data bytes is the offset of the
1115 parameter bytes plus the number of parameters being sent this time */
1116 SSVAL(req->outbuf, smb_droff,
1117 ((smb_buf(req->outbuf)+alignment_offset)
1118 - smb_base(req->outbuf))
1119 + params_sent_thistime + data_alignment_offset);
1120 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1123 /* Initialize the padding for alignment */
1125 if (alignment_offset != 0) {
1126 memset(smb_buf(req->outbuf), 0, alignment_offset);
1129 /* Copy the param bytes into the packet */
1131 if(params_sent_thistime) {
1132 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1133 params_sent_thistime);
1136 /* Copy in the data bytes */
1137 if(data_sent_thistime) {
1138 if (data_alignment_offset != 0) {
1139 memset((smb_buf(req->outbuf)+alignment_offset+
1140 params_sent_thistime), 0,
1141 data_alignment_offset);
1143 memcpy(smb_buf(req->outbuf)+alignment_offset
1144 +params_sent_thistime+data_alignment_offset,
1145 pd,data_sent_thistime);
1148 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1149 params_sent_thistime, data_sent_thistime, useable_space));
1150 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1151 params_to_send, data_to_send, paramsize, datasize));
1153 if (overflow) {
1154 error_packet_set((char *)req->outbuf,
1155 ERRDOS,ERRbufferoverflow,
1156 STATUS_BUFFER_OVERFLOW,
1157 __LINE__,__FILE__);
1158 } else if (NT_STATUS_V(status)) {
1159 uint8_t eclass;
1160 uint32_t ecode;
1161 ntstatus_to_dos(status, &eclass, &ecode);
1162 error_packet_set((char *)req->outbuf,
1163 eclass, ecode, status,
1164 __LINE__,__FILE__);
1167 /* Send the packet */
1168 show_msg((char *)req->outbuf);
1169 if (!srv_send_smb(xconn,
1170 (char *)req->outbuf,
1171 true, req->seqnum+1,
1172 IS_CONN_ENCRYPTED(conn),
1173 &req->pcd))
1174 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1176 TALLOC_FREE(req->outbuf);
1178 pp += params_sent_thistime;
1179 pd += data_sent_thistime;
1181 params_to_send -= params_sent_thistime;
1182 data_to_send -= data_sent_thistime;
1184 /* Sanity check */
1185 if(params_to_send < 0 || data_to_send < 0) {
1186 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1187 params_to_send, data_to_send));
1188 return;
1192 return;
1195 /****************************************************************************
1196 Reply to a TRANSACT2_OPEN.
1197 ****************************************************************************/
1199 static void call_trans2open(connection_struct *conn,
1200 struct smb_request *req,
1201 char **pparams, int total_params,
1202 char **ppdata, int total_data,
1203 unsigned int max_data_bytes)
1205 struct smb_filename *smb_fname = NULL;
1206 char *params = *pparams;
1207 char *pdata = *ppdata;
1208 int deny_mode;
1209 int32_t open_attr;
1210 bool oplock_request;
1211 #if 0
1212 bool return_additional_info;
1213 int16 open_sattr;
1214 time_t open_time;
1215 #endif
1216 int open_ofun;
1217 uint32_t open_size;
1218 char *pname;
1219 char *fname = NULL;
1220 off_t size=0;
1221 int fattr=0,mtime=0;
1222 SMB_INO_T inode = 0;
1223 int smb_action = 0;
1224 files_struct *fsp;
1225 struct ea_list *ea_list = NULL;
1226 uint16_t flags = 0;
1227 NTSTATUS status;
1228 uint32_t access_mask;
1229 uint32_t share_mode;
1230 uint32_t create_disposition;
1231 uint32_t create_options = 0;
1232 uint32_t private_flags = 0;
1233 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1234 TALLOC_CTX *ctx = talloc_tos();
1237 * Ensure we have enough parameters to perform the operation.
1240 if (total_params < 29) {
1241 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1242 goto out;
1245 flags = SVAL(params, 0);
1246 deny_mode = SVAL(params, 2);
1247 open_attr = SVAL(params,6);
1248 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1249 if (oplock_request) {
1250 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1253 #if 0
1254 return_additional_info = BITSETW(params,0);
1255 open_sattr = SVAL(params, 4);
1256 open_time = make_unix_date3(params+8);
1257 #endif
1258 open_ofun = SVAL(params,12);
1259 open_size = IVAL(params,14);
1260 pname = &params[28];
1262 if (IS_IPC(conn)) {
1263 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1264 goto out;
1267 if (req->posix_pathnames) {
1268 srvstr_get_path_posix(ctx,
1269 params,
1270 req->flags2,
1271 &fname,
1272 pname,
1273 total_params - 28,
1274 STR_TERMINATE,
1275 &status);
1276 } else {
1277 srvstr_get_path(ctx,
1278 params,
1279 req->flags2,
1280 &fname,
1281 pname,
1282 total_params - 28,
1283 STR_TERMINATE,
1284 &status);
1286 if (!NT_STATUS_IS_OK(status)) {
1287 reply_nterror(req, status);
1288 goto out;
1291 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1292 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1293 (unsigned int)open_ofun, open_size));
1295 status = filename_convert(ctx,
1296 conn,
1297 fname,
1298 ucf_flags,
1300 &smb_fname);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1303 reply_botherror(req,
1304 NT_STATUS_PATH_NOT_COVERED,
1305 ERRSRV, ERRbadpath);
1306 goto out;
1308 reply_nterror(req, status);
1309 goto out;
1312 if (open_ofun == 0) {
1313 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1314 goto out;
1317 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1318 open_ofun,
1319 &access_mask, &share_mode,
1320 &create_disposition,
1321 &create_options,
1322 &private_flags)) {
1323 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1324 goto out;
1327 /* Any data in this call is an EA list. */
1328 if (total_data && (total_data != 4)) {
1329 if (total_data < 10) {
1330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1331 goto out;
1334 if (IVAL(pdata,0) > total_data) {
1335 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1336 IVAL(pdata,0), (unsigned int)total_data));
1337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1338 goto out;
1341 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1342 total_data - 4);
1343 if (!ea_list) {
1344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1345 goto out;
1348 if (!lp_ea_support(SNUM(conn))) {
1349 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1350 goto out;
1353 if (!req->posix_pathnames &&
1354 ea_list_has_invalid_name(ea_list)) {
1355 int param_len = 30;
1356 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1357 if(*pparams == NULL ) {
1358 reply_nterror(req, NT_STATUS_NO_MEMORY);
1359 goto out;
1361 params = *pparams;
1362 memset(params, '\0', param_len);
1363 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1364 params, param_len, NULL, 0, max_data_bytes);
1365 goto out;
1369 status = SMB_VFS_CREATE_FILE(
1370 conn, /* conn */
1371 req, /* req */
1372 smb_fname, /* fname */
1373 access_mask, /* access_mask */
1374 share_mode, /* share_access */
1375 create_disposition, /* create_disposition*/
1376 create_options, /* create_options */
1377 open_attr, /* file_attributes */
1378 oplock_request, /* oplock_request */
1379 NULL, /* lease */
1380 open_size, /* allocation_size */
1381 private_flags,
1382 NULL, /* sd */
1383 ea_list, /* ea_list */
1384 &fsp, /* result */
1385 &smb_action, /* psbuf */
1386 NULL, NULL); /* create context */
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (open_was_deferred(req->xconn, req->mid)) {
1390 /* We have re-scheduled this call. */
1391 goto out;
1394 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1395 reply_openerror(req, status);
1396 goto out;
1399 fsp = fcb_or_dos_open(
1400 req,
1401 smb_fname,
1402 access_mask,
1403 create_options,
1404 private_flags);
1405 if (fsp == NULL) {
1406 bool ok = defer_smb1_sharing_violation(req);
1407 if (ok) {
1408 goto out;
1410 reply_openerror(req, status);
1411 goto out;
1414 smb_action = FILE_WAS_OPENED;
1417 size = get_file_size_stat(&smb_fname->st);
1418 fattr = fdos_mode(fsp);
1419 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1420 inode = smb_fname->st.st_ex_ino;
1421 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1422 close_file(req, fsp, ERROR_CLOSE);
1423 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1424 goto out;
1427 /* Realloc the size of parameters and data we will return */
1428 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1429 if(*pparams == NULL ) {
1430 reply_nterror(req, NT_STATUS_NO_MEMORY);
1431 goto out;
1433 params = *pparams;
1435 SSVAL(params,0,fsp->fnum);
1436 SSVAL(params,2,fattr);
1437 srv_put_dos_date2(params,4, mtime);
1438 SIVAL(params,8, (uint32_t)size);
1439 SSVAL(params,12,deny_mode);
1440 SSVAL(params,14,0); /* open_type - file or directory. */
1441 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1443 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1444 smb_action |= EXTENDED_OPLOCK_GRANTED;
1447 SSVAL(params,18,smb_action);
1450 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1452 SIVAL(params,20,inode);
1453 SSVAL(params,24,0); /* Padding. */
1454 if (flags & 8) {
1455 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
1456 SIVAL(params, 26, ea_size);
1457 } else {
1458 SIVAL(params, 26, 0);
1461 /* Send the required number of replies */
1462 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1463 out:
1464 TALLOC_FREE(smb_fname);
1467 /*********************************************************
1468 Routine to check if a given string matches exactly.
1469 as a special case a mask of "." does NOT match. That
1470 is required for correct wildcard semantics
1471 Case can be significant or not.
1472 **********************************************************/
1474 static bool exact_match(bool has_wild,
1475 bool case_sensitive,
1476 const char *str,
1477 const char *mask)
1479 if (mask[0] == '.' && mask[1] == 0) {
1480 return false;
1483 if (has_wild) {
1484 return false;
1487 if (case_sensitive) {
1488 return strcmp(str,mask)==0;
1489 } else {
1490 return strcasecmp_m(str,mask) == 0;
1494 /****************************************************************************
1495 Return the filetype for UNIX extensions.
1496 ****************************************************************************/
1498 static uint32_t unix_filetype(mode_t mode)
1500 if(S_ISREG(mode))
1501 return UNIX_TYPE_FILE;
1502 else if(S_ISDIR(mode))
1503 return UNIX_TYPE_DIR;
1504 #ifdef S_ISLNK
1505 else if(S_ISLNK(mode))
1506 return UNIX_TYPE_SYMLINK;
1507 #endif
1508 #ifdef S_ISCHR
1509 else if(S_ISCHR(mode))
1510 return UNIX_TYPE_CHARDEV;
1511 #endif
1512 #ifdef S_ISBLK
1513 else if(S_ISBLK(mode))
1514 return UNIX_TYPE_BLKDEV;
1515 #endif
1516 #ifdef S_ISFIFO
1517 else if(S_ISFIFO(mode))
1518 return UNIX_TYPE_FIFO;
1519 #endif
1520 #ifdef S_ISSOCK
1521 else if(S_ISSOCK(mode))
1522 return UNIX_TYPE_SOCKET;
1523 #endif
1525 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1526 return UNIX_TYPE_UNKNOWN;
1529 /****************************************************************************
1530 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1531 ****************************************************************************/
1533 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1534 const SMB_STRUCT_STAT *psbuf,
1535 uint32_t perms,
1536 enum perm_type ptype,
1537 mode_t *ret_perms)
1539 mode_t ret = 0;
1541 if (perms == SMB_MODE_NO_CHANGE) {
1542 if (!VALID_STAT(*psbuf)) {
1543 return NT_STATUS_INVALID_PARAMETER;
1544 } else {
1545 *ret_perms = psbuf->st_ex_mode;
1546 return NT_STATUS_OK;
1550 ret = wire_perms_to_unix(perms);
1552 if (ptype == PERM_NEW_FILE) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret &= lp_create_mask(SNUM(conn));
1558 /* Add in force bits */
1559 ret |= lp_force_create_mode(SNUM(conn));
1560 } else if (ptype == PERM_NEW_DIR) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret &= lp_directory_mask(SNUM(conn));
1566 /* Add in force bits */
1567 ret |= lp_force_directory_mode(SNUM(conn));
1570 *ret_perms = ret;
1571 return NT_STATUS_OK;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct *conn,
1580 struct smb_filename *smb_fname)
1582 int saved_errno = errno;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn)) &&
1585 is_msdfs_link(conn, smb_fname)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1588 "as a directory\n",
1589 smb_fname->base_name));
1590 smb_fname->st.st_ex_mode =
1591 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1592 errno = saved_errno;
1593 return true;
1595 errno = saved_errno;
1596 return false;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state {
1605 connection_struct *conn;
1606 uint32_t info_level;
1607 bool check_mangled_names;
1608 bool has_wild;
1609 bool got_exact_match;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1613 void *private_data,
1614 const char *dname,
1615 const char *mask,
1616 char **_fname)
1618 struct smbd_dirptr_lanman2_state *state =
1619 (struct smbd_dirptr_lanman2_state *)private_data;
1620 bool ok;
1621 char mangled_name[13]; /* mangled 8.3 name. */
1622 bool got_match;
1623 const char *fname;
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname, state->conn->params)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1631 NTSTATUS status;
1632 size_t ret_len = 0;
1633 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp = talloc_array(talloc_tos(),
1635 uint8_t,
1636 len);
1638 status = srvstr_push(NULL,
1639 FLAGS2_UNICODE_STRINGS,
1640 tmp,
1641 dname,
1642 len,
1643 STR_TERMINATE,
1644 &ret_len);
1646 TALLOC_FREE(tmp);
1648 if (!NT_STATUS_IS_OK(status)) {
1649 return false;
1652 ok = name_to_8_3(dname, mangled_name,
1653 true, state->conn->params);
1654 if (!ok) {
1655 return false;
1657 fname = mangled_name;
1658 } else {
1659 fname = dname;
1662 got_match = exact_match(state->has_wild,
1663 state->conn->case_sensitive,
1664 fname, mask);
1665 state->got_exact_match = got_match;
1666 if (!got_match) {
1667 got_match = mask_match(fname, mask,
1668 state->conn->case_sensitive);
1671 if(!got_match && state->check_mangled_names &&
1672 !mangle_is_8_3(fname, false, state->conn->params)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok = name_to_8_3(fname, mangled_name,
1681 false, state->conn->params);
1682 if (!ok) {
1683 return false;
1686 got_match = exact_match(state->has_wild,
1687 state->conn->case_sensitive,
1688 mangled_name, mask);
1689 state->got_exact_match = got_match;
1690 if (!got_match) {
1691 got_match = mask_match(mangled_name, mask,
1692 state->conn->case_sensitive);
1696 if (!got_match) {
1697 return false;
1700 *_fname = talloc_strdup(ctx, fname);
1701 if (*_fname == NULL) {
1702 return false;
1705 return true;
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1709 void *private_data,
1710 struct smb_filename *smb_fname,
1711 bool get_dosmode,
1712 uint32_t *_mode)
1714 struct smbd_dirptr_lanman2_state *state =
1715 (struct smbd_dirptr_lanman2_state *)private_data;
1716 bool ms_dfs_link = false;
1718 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1719 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1720 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1721 "Couldn't lstat [%s] (%s)\n",
1722 smb_fname_str_dbg(smb_fname),
1723 strerror(errno)));
1724 return false;
1726 return true;
1727 } else if (!VALID_STAT(smb_fname->st) &&
1728 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1729 /* Needed to show the msdfs symlinks as
1730 * directories */
1732 ms_dfs_link = check_msdfs_link(state->conn,
1733 smb_fname);
1734 if (!ms_dfs_link) {
1735 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1736 "Couldn't stat [%s] (%s)\n",
1737 smb_fname_str_dbg(smb_fname),
1738 strerror(errno)));
1739 return false;
1742 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1743 return true;
1746 if (!get_dosmode) {
1747 return true;
1750 *_mode = fdos_mode(smb_fname->fsp);
1751 smb_fname->st = smb_fname->fsp->fsp_name->st;
1753 return true;
1756 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1757 connection_struct *conn,
1758 uint16_t flags2,
1759 uint32_t info_level,
1760 struct ea_list *name_list,
1761 bool check_mangled_names,
1762 bool requires_resume_key,
1763 uint32_t mode,
1764 const char *fname,
1765 const struct smb_filename *smb_fname,
1766 int space_remaining,
1767 uint8_t align,
1768 bool do_pad,
1769 char *base_data,
1770 char **ppdata,
1771 char *end_data,
1772 uint64_t *last_entry_off)
1774 char *p, *q, *pdata = *ppdata;
1775 uint32_t reskey=0;
1776 uint64_t file_size = 0;
1777 uint64_t allocation_size = 0;
1778 uint64_t file_id = 0;
1779 size_t len = 0;
1780 struct timespec mdate_ts = {0};
1781 struct timespec adate_ts = {0};
1782 struct timespec cdate_ts = {0};
1783 struct timespec create_date_ts = {0};
1784 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1785 char *nameptr;
1786 char *last_entry_ptr;
1787 bool was_8_3;
1788 int off;
1789 int pad = 0;
1790 NTSTATUS status;
1791 struct readdir_attr_data *readdir_attr_data = NULL;
1793 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1794 file_size = get_file_size_stat(&smb_fname->st);
1796 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1798 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1799 if (!NT_STATUS_IS_OK(status)) {
1800 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1801 return status;
1805 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1807 mdate_ts = smb_fname->st.st_ex_mtime;
1808 adate_ts = smb_fname->st.st_ex_atime;
1809 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1810 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1812 if (lp_dos_filetime_resolution(SNUM(conn))) {
1813 dos_filetime_timespec(&create_date_ts);
1814 dos_filetime_timespec(&mdate_ts);
1815 dos_filetime_timespec(&adate_ts);
1816 dos_filetime_timespec(&cdate_ts);
1819 create_date = convert_timespec_to_time_t(create_date_ts);
1820 mdate = convert_timespec_to_time_t(mdate_ts);
1821 adate = convert_timespec_to_time_t(adate_ts);
1823 /* align the record */
1824 SMB_ASSERT(align >= 1);
1826 off = (int)PTR_DIFF(pdata, base_data);
1827 pad = (off + (align-1)) & ~(align-1);
1828 pad -= off;
1830 if (pad && pad > space_remaining) {
1831 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1832 "for padding (wanted %u, had %d)\n",
1833 (unsigned int)pad,
1834 space_remaining ));
1835 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1838 off += pad;
1839 /* initialize padding to 0 */
1840 if (pad) {
1841 memset(pdata, 0, pad);
1843 space_remaining -= pad;
1845 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1846 space_remaining ));
1848 pdata += pad;
1849 p = pdata;
1850 last_entry_ptr = p;
1852 pad = 0;
1853 off = 0;
1855 switch (info_level) {
1856 case SMB_FIND_INFO_STANDARD:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1858 if(requires_resume_key) {
1859 SIVAL(p,0,reskey);
1860 p += 4;
1862 srv_put_dos_date2(p,0,create_date);
1863 srv_put_dos_date2(p,4,adate);
1864 srv_put_dos_date2(p,8,mdate);
1865 SIVAL(p,12,(uint32_t)file_size);
1866 SIVAL(p,16,(uint32_t)allocation_size);
1867 SSVAL(p,20,mode);
1868 p += 23;
1869 nameptr = p;
1870 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1871 p += ucs2_align(base_data, p, 0);
1873 status = srvstr_push(base_data, flags2, p,
1874 fname, PTR_DIFF(end_data, p),
1875 STR_TERMINATE, &len);
1876 if (!NT_STATUS_IS_OK(status)) {
1877 return status;
1879 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1880 if (len > 2) {
1881 SCVAL(nameptr, -1, len - 2);
1882 } else {
1883 SCVAL(nameptr, -1, 0);
1885 } else {
1886 if (len > 1) {
1887 SCVAL(nameptr, -1, len - 1);
1888 } else {
1889 SCVAL(nameptr, -1, 0);
1892 p += len;
1893 break;
1895 case SMB_FIND_EA_SIZE:
1896 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1897 if (requires_resume_key) {
1898 SIVAL(p,0,reskey);
1899 p += 4;
1901 srv_put_dos_date2(p,0,create_date);
1902 srv_put_dos_date2(p,4,adate);
1903 srv_put_dos_date2(p,8,mdate);
1904 SIVAL(p,12,(uint32_t)file_size);
1905 SIVAL(p,16,(uint32_t)allocation_size);
1906 SSVAL(p,20,mode);
1908 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1909 SIVAL(p,22,ea_size); /* Extended attributes */
1911 p += 27;
1912 nameptr = p - 1;
1913 status = srvstr_push(base_data, flags2,
1914 p, fname, PTR_DIFF(end_data, p),
1915 STR_TERMINATE | STR_NOALIGN, &len);
1916 if (!NT_STATUS_IS_OK(status)) {
1917 return status;
1919 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1920 if (len > 2) {
1921 len -= 2;
1922 } else {
1923 len = 0;
1925 } else {
1926 if (len > 1) {
1927 len -= 1;
1928 } else {
1929 len = 0;
1932 SCVAL(nameptr,0,len);
1933 p += len;
1934 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1935 break;
1937 case SMB_FIND_EA_LIST:
1939 struct ea_list *file_list = NULL;
1940 size_t ea_len = 0;
1942 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1943 if (!name_list) {
1944 return NT_STATUS_INVALID_PARAMETER;
1946 if (requires_resume_key) {
1947 SIVAL(p,0,reskey);
1948 p += 4;
1950 srv_put_dos_date2(p,0,create_date);
1951 srv_put_dos_date2(p,4,adate);
1952 srv_put_dos_date2(p,8,mdate);
1953 SIVAL(p,12,(uint32_t)file_size);
1954 SIVAL(p,16,(uint32_t)allocation_size);
1955 SSVAL(p,20,mode);
1956 p += 22; /* p now points to the EA area. */
1958 status = get_ea_list_from_fsp(ctx,
1959 smb_fname->fsp,
1960 &ea_len, &file_list);
1961 if (!NT_STATUS_IS_OK(status)) {
1962 file_list = NULL;
1964 name_list = ea_list_union(name_list, file_list, &ea_len);
1966 /* We need to determine if this entry will fit in the space available. */
1967 /* Max string size is 255 bytes. */
1968 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1969 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1970 "(wanted %u, had %d)\n",
1971 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1972 space_remaining ));
1973 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1976 /* Push the ea_data followed by the name. */
1977 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1978 nameptr = p;
1979 status = srvstr_push(base_data, flags2,
1980 p + 1, fname, PTR_DIFF(end_data, p+1),
1981 STR_TERMINATE | STR_NOALIGN, &len);
1982 if (!NT_STATUS_IS_OK(status)) {
1983 return status;
1985 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1986 if (len > 2) {
1987 len -= 2;
1988 } else {
1989 len = 0;
1991 } else {
1992 if (len > 1) {
1993 len -= 1;
1994 } else {
1995 len = 0;
1998 SCVAL(nameptr,0,len);
1999 p += len + 1;
2000 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2001 break;
2004 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2005 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2006 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2007 p += 4;
2008 SIVAL(p,0,reskey); p += 4;
2009 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2010 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2011 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2012 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2013 SOFF_T(p,0,file_size); p += 8;
2014 SOFF_T(p,0,allocation_size); p += 8;
2015 SIVAL(p,0,mode); p += 4;
2016 q = p; p += 4; /* q is placeholder for name length. */
2017 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2018 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2019 } else {
2020 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2021 SIVAL(p,0,ea_size); /* Extended attributes */
2023 p += 4;
2024 /* Clear the short name buffer. This is
2025 * IMPORTANT as not doing so will trigger
2026 * a Win2k client bug. JRA.
2028 if (!was_8_3 && check_mangled_names) {
2029 char mangled_name[13]; /* mangled 8.3 name. */
2030 if (!name_to_8_3(fname,mangled_name,True,
2031 conn->params)) {
2032 /* Error - mangle failed ! */
2033 memset(mangled_name,'\0',12);
2035 mangled_name[12] = 0;
2036 status = srvstr_push(base_data, flags2,
2037 p+2, mangled_name, 24,
2038 STR_UPPER|STR_UNICODE, &len);
2039 if (!NT_STATUS_IS_OK(status)) {
2040 return status;
2042 if (len < 24) {
2043 memset(p + 2 + len,'\0',24 - len);
2045 SSVAL(p, 0, len);
2046 } else {
2047 memset(p,'\0',26);
2049 p += 2 + 24;
2050 status = srvstr_push(base_data, flags2, p,
2051 fname, PTR_DIFF(end_data, p),
2052 STR_TERMINATE_ASCII, &len);
2053 if (!NT_STATUS_IS_OK(status)) {
2054 return status;
2056 SIVAL(q,0,len);
2057 p += len;
2059 len = PTR_DIFF(p, pdata);
2060 pad = (len + (align-1)) & ~(align-1);
2062 * offset to the next entry, the caller
2063 * will overwrite it for the last entry
2064 * that's why we always include the padding
2066 SIVAL(pdata,0,pad);
2068 * set padding to zero
2070 if (do_pad) {
2071 memset(p, 0, pad - len);
2072 p = pdata + pad;
2073 } else {
2074 p = pdata + len;
2076 break;
2078 case SMB_FIND_FILE_DIRECTORY_INFO:
2079 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2080 p += 4;
2081 SIVAL(p,0,reskey); p += 4;
2082 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2083 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2084 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2085 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2086 SOFF_T(p,0,file_size); p += 8;
2087 SOFF_T(p,0,allocation_size); p += 8;
2088 SIVAL(p,0,mode); p += 4;
2089 status = srvstr_push(base_data, flags2,
2090 p + 4, fname, PTR_DIFF(end_data, p+4),
2091 STR_TERMINATE_ASCII, &len);
2092 if (!NT_STATUS_IS_OK(status)) {
2093 return status;
2095 SIVAL(p,0,len);
2096 p += 4 + len;
2098 len = PTR_DIFF(p, pdata);
2099 pad = (len + (align-1)) & ~(align-1);
2101 * offset to the next entry, the caller
2102 * will overwrite it for the last entry
2103 * that's why we always include the padding
2105 SIVAL(pdata,0,pad);
2107 * set padding to zero
2109 if (do_pad) {
2110 memset(p, 0, pad - len);
2111 p = pdata + pad;
2112 } else {
2113 p = pdata + len;
2115 break;
2117 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2118 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2119 p += 4;
2120 SIVAL(p,0,reskey); p += 4;
2121 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2122 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2123 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2124 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2125 SOFF_T(p,0,file_size); p += 8;
2126 SOFF_T(p,0,allocation_size); p += 8;
2127 SIVAL(p,0,mode); p += 4;
2128 q = p; p += 4; /* q is placeholder for name length. */
2129 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2130 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2131 } else {
2132 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2133 SIVAL(p,0,ea_size); /* Extended attributes */
2135 p +=4;
2136 status = srvstr_push(base_data, flags2, p,
2137 fname, PTR_DIFF(end_data, p),
2138 STR_TERMINATE_ASCII, &len);
2139 if (!NT_STATUS_IS_OK(status)) {
2140 return status;
2142 SIVAL(q, 0, len);
2143 p += len;
2145 len = PTR_DIFF(p, pdata);
2146 pad = (len + (align-1)) & ~(align-1);
2148 * offset to the next entry, the caller
2149 * will overwrite it for the last entry
2150 * that's why we always include the padding
2152 SIVAL(pdata,0,pad);
2154 * set padding to zero
2156 if (do_pad) {
2157 memset(p, 0, pad - len);
2158 p = pdata + pad;
2159 } else {
2160 p = pdata + len;
2162 break;
2164 case SMB_FIND_FILE_NAMES_INFO:
2165 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2166 p += 4;
2167 SIVAL(p,0,reskey); p += 4;
2168 p += 4;
2169 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2170 acl on a dir (tridge) */
2171 status = srvstr_push(base_data, flags2, p,
2172 fname, PTR_DIFF(end_data, p),
2173 STR_TERMINATE_ASCII, &len);
2174 if (!NT_STATUS_IS_OK(status)) {
2175 return status;
2177 SIVAL(p, -4, len);
2178 p += len;
2180 len = PTR_DIFF(p, pdata);
2181 pad = (len + (align-1)) & ~(align-1);
2183 * offset to the next entry, the caller
2184 * will overwrite it for the last entry
2185 * that's why we always include the padding
2187 SIVAL(pdata,0,pad);
2189 * set padding to zero
2191 if (do_pad) {
2192 memset(p, 0, pad - len);
2193 p = pdata + pad;
2194 } else {
2195 p = pdata + len;
2197 break;
2199 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2200 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2201 p += 4;
2202 SIVAL(p,0,reskey); p += 4;
2203 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2204 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2205 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2206 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2207 SOFF_T(p,0,file_size); p += 8;
2208 SOFF_T(p,0,allocation_size); p += 8;
2209 SIVAL(p,0,mode); p += 4;
2210 q = p; p += 4; /* q is placeholder for name length. */
2211 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2212 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2213 } else {
2214 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2215 SIVAL(p,0,ea_size); /* Extended attributes */
2217 p += 4;
2218 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2219 SBVAL(p,0,file_id); p += 8;
2220 status = srvstr_push(base_data, flags2, p,
2221 fname, PTR_DIFF(end_data, p),
2222 STR_TERMINATE_ASCII, &len);
2223 if (!NT_STATUS_IS_OK(status)) {
2224 return status;
2226 SIVAL(q, 0, len);
2227 p += len;
2229 len = PTR_DIFF(p, pdata);
2230 pad = (len + (align-1)) & ~(align-1);
2232 * offset to the next entry, the caller
2233 * will overwrite it for the last entry
2234 * that's why we always include the padding
2236 SIVAL(pdata,0,pad);
2238 * set padding to zero
2240 if (do_pad) {
2241 memset(p, 0, pad - len);
2242 p = pdata + pad;
2243 } else {
2244 p = pdata + len;
2246 break;
2248 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2249 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2250 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2251 p += 4;
2252 SIVAL(p,0,reskey); p += 4;
2253 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2254 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2255 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2256 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2257 SOFF_T(p,0,file_size); p += 8;
2258 SOFF_T(p,0,allocation_size); p += 8;
2259 SIVAL(p,0,mode); p += 4;
2260 q = p; p += 4; /* q is placeholder for name length */
2261 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2262 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2263 } else if (readdir_attr_data &&
2264 readdir_attr_data->type == RDATTR_AAPL) {
2266 * OS X specific SMB2 extension negotiated via
2267 * AAPL create context: return max_access in
2268 * ea_size field.
2270 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2271 } else {
2272 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2273 SIVAL(p,0,ea_size); /* Extended attributes */
2275 p += 4;
2277 if (readdir_attr_data &&
2278 readdir_attr_data->type == RDATTR_AAPL) {
2280 * OS X specific SMB2 extension negotiated via
2281 * AAPL create context: return resource fork
2282 * length and compressed FinderInfo in
2283 * shortname field.
2285 * According to documentation short_name_len
2286 * should be 0, but on the wire behaviour
2287 * shows its set to 24 by clients.
2289 SSVAL(p, 0, 24);
2291 /* Resourefork length */
2292 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2294 /* Compressed FinderInfo */
2295 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2296 } else if (!was_8_3 && check_mangled_names) {
2297 char mangled_name[13]; /* mangled 8.3 name. */
2298 if (!name_to_8_3(fname,mangled_name,True,
2299 conn->params)) {
2300 /* Error - mangle failed ! */
2301 memset(mangled_name,'\0',12);
2303 mangled_name[12] = 0;
2304 status = srvstr_push(base_data, flags2,
2305 p+2, mangled_name, 24,
2306 STR_UPPER|STR_UNICODE, &len);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 return status;
2310 SSVAL(p, 0, len);
2311 if (len < 24) {
2312 memset(p + 2 + len,'\0',24 - len);
2314 SSVAL(p, 0, len);
2315 } else {
2316 /* Clear the short name buffer. This is
2317 * IMPORTANT as not doing so will trigger
2318 * a Win2k client bug. JRA.
2320 memset(p,'\0',26);
2322 p += 26;
2324 /* Reserved ? */
2325 if (readdir_attr_data &&
2326 readdir_attr_data->type == RDATTR_AAPL) {
2328 * OS X specific SMB2 extension negotiated via
2329 * AAPL create context: return UNIX mode in
2330 * reserved field.
2332 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2333 SSVAL(p, 0, aapl_mode);
2334 } else {
2335 SSVAL(p, 0, 0);
2337 p += 2;
2339 SBVAL(p,0,file_id); p += 8;
2340 status = srvstr_push(base_data, flags2, p,
2341 fname, PTR_DIFF(end_data, p),
2342 STR_TERMINATE_ASCII, &len);
2343 if (!NT_STATUS_IS_OK(status)) {
2344 return status;
2346 SIVAL(q,0,len);
2347 p += len;
2349 len = PTR_DIFF(p, pdata);
2350 pad = (len + (align-1)) & ~(align-1);
2352 * offset to the next entry, the caller
2353 * will overwrite it for the last entry
2354 * that's why we always include the padding
2356 SIVAL(pdata,0,pad);
2358 * set padding to zero
2360 if (do_pad) {
2361 memset(p, 0, pad - len);
2362 p = pdata + pad;
2363 } else {
2364 p = pdata + len;
2366 break;
2368 /* CIFS UNIX Extension. */
2370 case SMB_FIND_FILE_UNIX:
2371 case SMB_FIND_FILE_UNIX_INFO2:
2372 p+= 4;
2373 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2375 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2377 if (info_level == SMB_FIND_FILE_UNIX) {
2378 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2379 p = store_file_unix_basic(conn, p,
2380 NULL, &smb_fname->st);
2381 status = srvstr_push(base_data, flags2, p,
2382 fname, PTR_DIFF(end_data, p),
2383 STR_TERMINATE, &len);
2384 if (!NT_STATUS_IS_OK(status)) {
2385 return status;
2387 } else {
2388 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2389 p = store_file_unix_basic_info2(conn, p,
2390 NULL, &smb_fname->st);
2391 nameptr = p;
2392 p += 4;
2393 status = srvstr_push(base_data, flags2, p, fname,
2394 PTR_DIFF(end_data, p), 0, &len);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 return status;
2398 SIVAL(nameptr, 0, len);
2401 p += len;
2403 len = PTR_DIFF(p, pdata);
2404 pad = (len + (align-1)) & ~(align-1);
2406 * offset to the next entry, the caller
2407 * will overwrite it for the last entry
2408 * that's why we always include the padding
2410 SIVAL(pdata,0,pad);
2412 * set padding to zero
2414 if (do_pad) {
2415 memset(p, 0, pad - len);
2416 p = pdata + pad;
2417 } else {
2418 p = pdata + len;
2420 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2422 break;
2424 default:
2425 return NT_STATUS_INVALID_LEVEL;
2428 if (PTR_DIFF(p,pdata) > space_remaining) {
2429 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2430 "(wanted %u, had %d)\n",
2431 (unsigned int)PTR_DIFF(p,pdata),
2432 space_remaining ));
2433 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2436 /* Setup the last entry pointer, as an offset from base_data */
2437 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2438 /* Advance the data pointer to the next slot */
2439 *ppdata = p;
2441 return NT_STATUS_OK;
2444 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2445 connection_struct *conn,
2446 struct dptr_struct *dirptr,
2447 uint16_t flags2,
2448 const char *path_mask,
2449 uint32_t dirtype,
2450 int info_level,
2451 int requires_resume_key,
2452 bool dont_descend,
2453 bool ask_sharemode,
2454 bool get_dosmode,
2455 uint8_t align,
2456 bool do_pad,
2457 char **ppdata,
2458 char *base_data,
2459 char *end_data,
2460 int space_remaining,
2461 struct smb_filename **_smb_fname,
2462 bool *got_exact_match,
2463 int *_last_entry_off,
2464 struct ea_list *name_list,
2465 struct file_id *file_id)
2467 const char *p;
2468 const char *mask = NULL;
2469 long prev_dirpos = 0;
2470 uint32_t mode = 0;
2471 char *fname = NULL;
2472 struct smb_filename *smb_fname = NULL;
2473 struct smbd_dirptr_lanman2_state state;
2474 bool ok;
2475 uint64_t last_entry_off = 0;
2476 NTSTATUS status;
2477 enum mangled_names_options mangled_names;
2478 bool marshall_with_83_names;
2480 mangled_names = lp_mangled_names(conn->params);
2482 ZERO_STRUCT(state);
2483 state.conn = conn;
2484 state.info_level = info_level;
2485 if (mangled_names != MANGLED_NAMES_NO) {
2486 state.check_mangled_names = true;
2488 state.has_wild = dptr_has_wild(dirptr);
2489 state.got_exact_match = false;
2491 *got_exact_match = false;
2493 p = strrchr_m(path_mask,'/');
2494 if(p != NULL) {
2495 if(p[1] == '\0') {
2496 mask = "*.*";
2497 } else {
2498 mask = p+1;
2500 } else {
2501 mask = path_mask;
2504 ok = smbd_dirptr_get_entry(ctx,
2505 dirptr,
2506 mask,
2507 dirtype,
2508 dont_descend,
2509 ask_sharemode,
2510 get_dosmode,
2511 smbd_dirptr_lanman2_match_fn,
2512 smbd_dirptr_lanman2_mode_fn,
2513 &state,
2514 &fname,
2515 &smb_fname,
2516 &mode,
2517 &prev_dirpos);
2518 if (!ok) {
2519 return NT_STATUS_END_OF_FILE;
2522 *got_exact_match = state.got_exact_match;
2524 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2526 status = smbd_marshall_dir_entry(ctx,
2527 conn,
2528 flags2,
2529 info_level,
2530 name_list,
2531 marshall_with_83_names,
2532 requires_resume_key,
2533 mode,
2534 fname,
2535 smb_fname,
2536 space_remaining,
2537 align,
2538 do_pad,
2539 base_data,
2540 ppdata,
2541 end_data,
2542 &last_entry_off);
2543 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2544 DEBUG(1,("Conversion error: illegal character: %s\n",
2545 smb_fname_str_dbg(smb_fname)));
2548 if (file_id != NULL) {
2549 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2552 if (!NT_STATUS_IS_OK(status) &&
2553 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2555 TALLOC_FREE(smb_fname);
2556 TALLOC_FREE(fname);
2557 return status;
2560 if (_smb_fname != NULL) {
2561 struct smb_filename *name = NULL;
2563 name = synthetic_smb_fname(ctx,
2564 fname,
2565 NULL,
2566 &smb_fname->st,
2567 smb_fname->twrp,
2569 if (name == NULL) {
2570 TALLOC_FREE(smb_fname);
2571 TALLOC_FREE(fname);
2572 return NT_STATUS_NO_MEMORY;
2574 *_smb_fname = name;
2577 TALLOC_FREE(smb_fname);
2578 TALLOC_FREE(fname);
2580 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2581 dptr_SeekDir(dirptr, prev_dirpos);
2582 return status;
2585 *_last_entry_off = last_entry_off;
2586 return NT_STATUS_OK;
2589 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2590 connection_struct *conn,
2591 struct dptr_struct *dirptr,
2592 uint16_t flags2,
2593 const char *path_mask,
2594 uint32_t dirtype,
2595 int info_level,
2596 bool requires_resume_key,
2597 bool dont_descend,
2598 bool ask_sharemode,
2599 char **ppdata,
2600 char *base_data,
2601 char *end_data,
2602 int space_remaining,
2603 bool *got_exact_match,
2604 int *last_entry_off,
2605 struct ea_list *name_list)
2607 uint8_t align = 4;
2608 const bool do_pad = true;
2610 if (info_level >= 1 && info_level <= 3) {
2611 /* No alignment on earlier info levels. */
2612 align = 1;
2615 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2616 path_mask, dirtype, info_level,
2617 requires_resume_key, dont_descend, ask_sharemode,
2618 true, align, do_pad,
2619 ppdata, base_data, end_data,
2620 space_remaining,
2621 NULL,
2622 got_exact_match,
2623 last_entry_off, name_list, NULL);
2626 /****************************************************************************
2627 Reply to a TRANS2_FINDFIRST.
2628 ****************************************************************************/
2630 static void call_trans2findfirst(connection_struct *conn,
2631 struct smb_request *req,
2632 char **pparams, int total_params,
2633 char **ppdata, int total_data,
2634 unsigned int max_data_bytes)
2636 /* We must be careful here that we don't return more than the
2637 allowed number of data bytes. If this means returning fewer than
2638 maxentries then so be it. We assume that the redirector has
2639 enough room for the fixed number of parameter bytes it has
2640 requested. */
2641 struct smb_filename *smb_dname = NULL;
2642 char *params = *pparams;
2643 char *pdata = *ppdata;
2644 char *data_end;
2645 uint32_t dirtype;
2646 int maxentries;
2647 uint16_t findfirst_flags;
2648 bool close_after_first;
2649 bool close_if_end;
2650 bool requires_resume_key;
2651 int info_level;
2652 char *directory = NULL;
2653 char *mask = NULL;
2654 char *p;
2655 int last_entry_off=0;
2656 int dptr_num = -1;
2657 int numentries = 0;
2658 int i;
2659 bool finished = False;
2660 bool dont_descend = False;
2661 bool out_of_space = False;
2662 int space_remaining;
2663 struct ea_list *ea_list = NULL;
2664 NTSTATUS ntstatus = NT_STATUS_OK;
2665 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2666 struct smbd_server_connection *sconn = req->sconn;
2667 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2668 ucf_flags_from_smb_request(req);
2669 bool backup_priv = false;
2670 bool as_root = false;
2671 files_struct *fsp = NULL;
2672 const struct loadparm_substitution *lp_sub =
2673 loadparm_s3_global_substitution();
2674 int ret;
2676 if (total_params < 13) {
2677 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2678 goto out;
2681 dirtype = SVAL(params,0);
2682 maxentries = SVAL(params,2);
2683 findfirst_flags = SVAL(params,4);
2684 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2685 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2686 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2687 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2688 security_token_has_privilege(get_current_nttok(conn),
2689 SEC_PRIV_BACKUP));
2691 info_level = SVAL(params,6);
2693 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2694 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2695 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2696 (int)backup_priv,
2697 info_level, max_data_bytes));
2699 if (!maxentries) {
2700 /* W2K3 seems to treat zero as 1. */
2701 maxentries = 1;
2704 switch (info_level) {
2705 case SMB_FIND_INFO_STANDARD:
2706 case SMB_FIND_EA_SIZE:
2707 case SMB_FIND_EA_LIST:
2708 case SMB_FIND_FILE_DIRECTORY_INFO:
2709 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2710 case SMB_FIND_FILE_NAMES_INFO:
2711 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2712 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2713 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2714 break;
2715 case SMB_FIND_FILE_UNIX:
2716 case SMB_FIND_FILE_UNIX_INFO2:
2717 if (!lp_unix_extensions()) {
2718 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2719 goto out;
2721 break;
2722 default:
2723 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2724 goto out;
2727 if (req->posix_pathnames) {
2728 /* Always use filesystem for UNIX mtime query. */
2729 ask_sharemode = false;
2732 if (req->posix_pathnames) {
2733 srvstr_get_path_posix(talloc_tos(),
2734 params,
2735 req->flags2,
2736 &directory,
2737 params+12,
2738 total_params - 12,
2739 STR_TERMINATE,
2740 &ntstatus);
2741 } else {
2742 srvstr_get_path(talloc_tos(),
2743 params,
2744 req->flags2,
2745 &directory,
2746 params+12,
2747 total_params - 12,
2748 STR_TERMINATE,
2749 &ntstatus);
2751 if (!NT_STATUS_IS_OK(ntstatus)) {
2752 reply_nterror(req, ntstatus);
2753 goto out;
2756 if (backup_priv) {
2757 become_root();
2758 as_root = true;
2759 ntstatus = filename_convert_with_privilege(talloc_tos(),
2760 conn,
2761 req,
2762 directory,
2763 ucf_flags,
2764 &smb_dname);
2765 } else {
2766 ntstatus = filename_convert(talloc_tos(), conn,
2767 directory,
2768 ucf_flags,
2770 &smb_dname);
2773 if (!NT_STATUS_IS_OK(ntstatus)) {
2774 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2775 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2776 ERRSRV, ERRbadpath);
2777 goto out;
2779 reply_nterror(req, ntstatus);
2780 goto out;
2784 * The above call to filename_convert() is on the path from the client
2785 * including the search mask. Until the code that chops of the search
2786 * mask from the path below is moved before the call to
2787 * filename_convert(), we close a possible pathref fsp to ensure
2788 * SMB_VFS_CREATE_FILE() below will internally open a pathref fsp on the
2789 * correct path.
2791 if (smb_dname->fsp != NULL) {
2792 ntstatus = fd_close(smb_dname->fsp);
2793 if (!NT_STATUS_IS_OK(ntstatus)) {
2794 reply_nterror(req, ntstatus);
2795 goto out;
2798 * The pathref fsp link destructor will set smb_dname->fsp to
2799 * NULL. Turning this into an assert to give a hint at readers
2800 * of the code trying to understand the mechanics.
2802 file_free(req, smb_dname->fsp);
2803 SMB_ASSERT(smb_dname->fsp == NULL);
2806 mask = get_original_lcomp(talloc_tos(),
2807 conn,
2808 directory,
2809 ucf_flags);
2810 if (mask == NULL) {
2811 reply_nterror(req, NT_STATUS_NO_MEMORY);
2812 goto out;
2815 directory = smb_dname->base_name;
2817 p = strrchr_m(directory,'/');
2818 if(p == NULL) {
2819 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2820 if((directory[0] == '.') && (directory[1] == '\0')) {
2821 mask = talloc_strdup(talloc_tos(),"*");
2822 if (!mask) {
2823 reply_nterror(req, NT_STATUS_NO_MEMORY);
2824 goto out;
2827 } else {
2828 *p = 0;
2831 if (p == NULL || p == directory) {
2832 struct smb_filename *old_name = smb_dname;
2834 /* Ensure we don't have a directory name of "". */
2835 smb_dname = synthetic_smb_fname(talloc_tos(),
2836 ".",
2837 NULL,
2838 &old_name->st,
2839 old_name->twrp,
2840 old_name->flags);
2841 TALLOC_FREE(old_name);
2842 if (smb_dname == NULL) {
2843 reply_nterror(req, NT_STATUS_NO_MEMORY);
2844 goto out;
2846 directory = smb_dname->base_name;
2849 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2851 if (info_level == SMB_FIND_EA_LIST) {
2852 uint32_t ea_size;
2854 if (total_data < 4) {
2855 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2856 goto out;
2859 ea_size = IVAL(pdata,0);
2860 if (ea_size != total_data) {
2861 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2862 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2863 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2864 goto out;
2867 if (!lp_ea_support(SNUM(conn))) {
2868 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2869 goto out;
2872 /* Pull out the list of names. */
2873 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2874 if (!ea_list) {
2875 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2876 goto out;
2880 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2881 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2882 goto out;
2885 *ppdata = (char *)SMB_REALLOC(
2886 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2887 if(*ppdata == NULL ) {
2888 reply_nterror(req, NT_STATUS_NO_MEMORY);
2889 goto out;
2891 pdata = *ppdata;
2892 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2894 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2895 * error.
2897 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2898 /* Realloc the params space */
2899 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2900 if (*pparams == NULL) {
2901 reply_nterror(req, NT_STATUS_NO_MEMORY);
2902 goto out;
2904 params = *pparams;
2907 * As we've cut off the last component from
2908 * smb_fname we need to re-stat smb_dname
2909 * so FILE_OPEN disposition knows the directory
2910 * exists.
2912 ret = vfs_stat(conn, smb_dname);
2913 if (ret == -1) {
2914 ntstatus = map_nt_error_from_unix(errno);
2915 reply_nterror(req, ntstatus);
2916 goto out;
2919 ntstatus = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
2920 if (!NT_STATUS_IS_OK(ntstatus)) {
2921 reply_nterror(req, ntstatus);
2922 goto out;
2926 * Open an fsp on this directory for the dptr.
2928 ntstatus = SMB_VFS_CREATE_FILE(
2929 conn, /* conn */
2930 req, /* req */
2931 smb_dname, /* dname */
2932 FILE_LIST_DIRECTORY, /* access_mask */
2933 FILE_SHARE_READ|
2934 FILE_SHARE_WRITE, /* share_access */
2935 FILE_OPEN, /* create_disposition*/
2936 FILE_DIRECTORY_FILE, /* create_options */
2937 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2938 NO_OPLOCK, /* oplock_request */
2939 NULL, /* lease */
2940 0, /* allocation_size */
2941 0, /* private_flags */
2942 NULL, /* sd */
2943 NULL, /* ea_list */
2944 &fsp, /* result */
2945 NULL, /* pinfo */
2946 NULL, /* in_context */
2947 NULL);/* out_context */
2949 if (!NT_STATUS_IS_OK(ntstatus)) {
2950 DBG_ERR("failed to open directory %s\n",
2951 smb_fname_str_dbg(smb_dname));
2952 reply_nterror(req, ntstatus);
2953 goto out;
2956 /* Save the wildcard match and attribs we are using on this directory -
2957 needed as lanman2 assumes these are being saved between calls */
2959 ntstatus = dptr_create(conn,
2960 req,
2961 fsp, /* fsp */
2962 False,
2963 True,
2964 req->smbpid,
2965 mask,
2966 dirtype,
2967 &fsp->dptr);
2969 if (!NT_STATUS_IS_OK(ntstatus)) {
2971 * Use NULL here for the first parameter (req)
2972 * as this is not a client visible handle so
2973 * can'tbe part of an SMB1 chain.
2975 close_file(NULL, fsp, NORMAL_CLOSE);
2976 fsp = NULL;
2977 reply_nterror(req, ntstatus);
2978 goto out;
2981 if (backup_priv) {
2982 /* Remember this in case we have
2983 to do a findnext. */
2984 dptr_set_priv(fsp->dptr);
2987 dptr_num = dptr_dnum(fsp->dptr);
2988 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2990 /* We don't need to check for VOL here as this is returned by
2991 a different TRANS2 call. */
2993 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2994 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
2995 if (in_list(directory,
2996 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
2997 conn->case_sensitive)) {
2998 dont_descend = True;
3001 p = pdata;
3002 space_remaining = max_data_bytes;
3003 out_of_space = False;
3005 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3006 bool got_exact_match = False;
3008 /* this is a heuristic to avoid seeking the dirptr except when
3009 absolutely necessary. It allows for a filename of about 40 chars */
3010 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3011 out_of_space = True;
3012 finished = False;
3013 } else {
3014 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3015 conn,
3016 fsp->dptr,
3017 req->flags2,
3018 mask,dirtype,info_level,
3019 requires_resume_key,dont_descend,
3020 ask_sharemode,
3021 &p,pdata,data_end,
3022 space_remaining,
3023 &got_exact_match,
3024 &last_entry_off, ea_list);
3025 if (NT_STATUS_EQUAL(ntstatus,
3026 NT_STATUS_ILLEGAL_CHARACTER)) {
3028 * Bad character conversion on name. Ignore this
3029 * entry.
3031 continue;
3033 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3034 out_of_space = true;
3035 } else {
3036 finished = !NT_STATUS_IS_OK(ntstatus);
3040 if (!finished && !out_of_space)
3041 numentries++;
3044 * As an optimisation if we know we aren't looking
3045 * for a wildcard name (ie. the name matches the wildcard exactly)
3046 * then we can finish on any (first) match.
3047 * This speeds up large directory searches. JRA.
3050 if(got_exact_match)
3051 finished = True;
3053 /* Ensure space_remaining never goes -ve. */
3054 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3055 space_remaining = 0;
3056 out_of_space = true;
3057 } else {
3058 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3062 /* Check if we can close the dirptr */
3063 if(close_after_first || (finished && close_if_end)) {
3064 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3065 dptr_num = -1;
3066 close_file(NULL, fsp, NORMAL_CLOSE);
3067 fsp = NULL;
3071 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3072 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3073 * the protocol level is less than NT1. Tested with smbclient. JRA.
3074 * This should fix the OS/2 client bug #2335.
3077 if(numentries == 0) {
3078 dptr_num = -1;
3080 * We may have already closed the file in the
3081 * close_after_first or finished case above.
3083 if (fsp != NULL) {
3084 close_file(NULL, fsp, NORMAL_CLOSE);
3085 fsp = NULL;
3087 if (get_Protocol() < PROTOCOL_NT1) {
3088 reply_force_doserror(req, ERRDOS, ERRnofiles);
3089 goto out;
3090 } else {
3091 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3092 ERRDOS, ERRbadfile);
3093 goto out;
3097 /* At this point pdata points to numentries directory entries. */
3099 /* Set up the return parameter block */
3100 SSVAL(params,0,dptr_num);
3101 SSVAL(params,2,numentries);
3102 SSVAL(params,4,finished);
3103 SSVAL(params,6,0); /* Never an EA error */
3104 SSVAL(params,8,last_entry_off);
3106 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3107 max_data_bytes);
3109 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3110 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3111 if (!directory) {
3112 reply_nterror(req, NT_STATUS_NO_MEMORY);
3116 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3117 smb_fn_name(req->cmd),
3118 mask, directory, dirtype, numentries ) );
3121 * Force a name mangle here to ensure that the
3122 * mask as an 8.3 name is top of the mangled cache.
3123 * The reasons for this are subtle. Don't remove
3124 * this code unless you know what you are doing
3125 * (see PR#13758). JRA.
3128 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3129 char mangled_name[13];
3130 name_to_8_3(mask, mangled_name, True, conn->params);
3132 out:
3134 if (as_root) {
3135 unbecome_root();
3138 TALLOC_FREE(smb_dname);
3139 return;
3142 /****************************************************************************
3143 Reply to a TRANS2_FINDNEXT.
3144 ****************************************************************************/
3146 static void call_trans2findnext(connection_struct *conn,
3147 struct smb_request *req,
3148 char **pparams, int total_params,
3149 char **ppdata, int total_data,
3150 unsigned int max_data_bytes)
3152 /* We must be careful here that we don't return more than the
3153 allowed number of data bytes. If this means returning fewer than
3154 maxentries then so be it. We assume that the redirector has
3155 enough room for the fixed number of parameter bytes it has
3156 requested. */
3157 char *params = *pparams;
3158 char *pdata = *ppdata;
3159 char *data_end;
3160 int dptr_num;
3161 int maxentries;
3162 uint16_t info_level;
3163 uint32_t resume_key;
3164 uint16_t findnext_flags;
3165 bool close_after_request;
3166 bool close_if_end;
3167 bool requires_resume_key;
3168 bool continue_bit;
3169 char *resume_name = NULL;
3170 const char *mask = NULL;
3171 const char *directory = NULL;
3172 char *p = NULL;
3173 uint16_t dirtype;
3174 int numentries = 0;
3175 int i, last_entry_off=0;
3176 bool finished = False;
3177 bool dont_descend = False;
3178 bool out_of_space = False;
3179 int space_remaining;
3180 struct ea_list *ea_list = NULL;
3181 NTSTATUS ntstatus = NT_STATUS_OK;
3182 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3183 TALLOC_CTX *ctx = talloc_tos();
3184 struct smbd_server_connection *sconn = req->sconn;
3185 bool backup_priv = false;
3186 bool as_root = false;
3187 files_struct *fsp = NULL;
3188 const struct loadparm_substitution *lp_sub =
3189 loadparm_s3_global_substitution();
3191 if (total_params < 13) {
3192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3193 return;
3196 dptr_num = SVAL(params,0);
3197 maxentries = SVAL(params,2);
3198 info_level = SVAL(params,4);
3199 resume_key = IVAL(params,6);
3200 findnext_flags = SVAL(params,10);
3201 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3202 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3203 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3204 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3206 if (!continue_bit) {
3207 /* We only need resume_name if continue_bit is zero. */
3208 if (req->posix_pathnames) {
3209 srvstr_get_path_posix(ctx,
3210 params,
3211 req->flags2,
3212 &resume_name,
3213 params+12,
3214 total_params - 12,
3215 STR_TERMINATE,
3216 &ntstatus);
3217 } else {
3218 srvstr_get_path(ctx,
3219 params,
3220 req->flags2,
3221 &resume_name,
3222 params+12,
3223 total_params - 12,
3224 STR_TERMINATE,
3225 &ntstatus);
3227 if (!NT_STATUS_IS_OK(ntstatus)) {
3228 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3229 complain (it thinks we're asking for the directory above the shared
3230 path or an invalid name). Catch this as the resume name is only compared, never used in
3231 a file access. JRA. */
3232 srvstr_pull_talloc(ctx, params, req->flags2,
3233 &resume_name, params+12,
3234 total_params - 12,
3235 STR_TERMINATE);
3237 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3238 reply_nterror(req, ntstatus);
3239 return;
3244 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3245 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3246 resume_key = %d resume name = %s continue=%d level = %d\n",
3247 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3248 requires_resume_key, resume_key,
3249 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3251 if (!maxentries) {
3252 /* W2K3 seems to treat zero as 1. */
3253 maxentries = 1;
3256 switch (info_level) {
3257 case SMB_FIND_INFO_STANDARD:
3258 case SMB_FIND_EA_SIZE:
3259 case SMB_FIND_EA_LIST:
3260 case SMB_FIND_FILE_DIRECTORY_INFO:
3261 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3262 case SMB_FIND_FILE_NAMES_INFO:
3263 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3264 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3265 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3266 break;
3267 case SMB_FIND_FILE_UNIX:
3268 case SMB_FIND_FILE_UNIX_INFO2:
3269 /* Always use filesystem for UNIX mtime query. */
3270 ask_sharemode = false;
3271 if (!lp_unix_extensions()) {
3272 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3273 return;
3275 break;
3276 default:
3277 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3278 return;
3281 if (info_level == SMB_FIND_EA_LIST) {
3282 uint32_t ea_size;
3284 if (total_data < 4) {
3285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3286 return;
3289 ea_size = IVAL(pdata,0);
3290 if (ea_size != total_data) {
3291 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3292 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3294 return;
3297 if (!lp_ea_support(SNUM(conn))) {
3298 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3299 return;
3302 /* Pull out the list of names. */
3303 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3304 if (!ea_list) {
3305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3306 return;
3310 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3311 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3312 return;
3315 *ppdata = (char *)SMB_REALLOC(
3316 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3317 if(*ppdata == NULL) {
3318 reply_nterror(req, NT_STATUS_NO_MEMORY);
3319 return;
3322 pdata = *ppdata;
3323 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3326 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3327 * error.
3329 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3330 /* Realloc the params space */
3331 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3332 if(*pparams == NULL ) {
3333 reply_nterror(req, NT_STATUS_NO_MEMORY);
3334 return;
3337 params = *pparams;
3339 /* Check that the dptr is valid */
3340 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3341 if (fsp == NULL) {
3342 reply_nterror(req, STATUS_NO_MORE_FILES);
3343 return;
3346 directory = dptr_path(sconn, dptr_num);
3348 /* Get the wildcard mask from the dptr */
3349 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3350 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3351 reply_nterror(req, STATUS_NO_MORE_FILES);
3352 return;
3355 /* Get the attr mask from the dptr */
3356 dirtype = dptr_attr(sconn, dptr_num);
3358 backup_priv = dptr_get_priv(fsp->dptr);
3360 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3361 "backup_priv = %d\n",
3362 dptr_num, mask, dirtype,
3363 (long)fsp->dptr,
3364 dptr_TellDir(fsp->dptr),
3365 (int)backup_priv));
3367 /* We don't need to check for VOL here as this is returned by
3368 a different TRANS2 call. */
3370 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3371 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3372 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3373 dont_descend = True;
3375 p = pdata;
3376 space_remaining = max_data_bytes;
3377 out_of_space = False;
3379 if (backup_priv) {
3380 become_root();
3381 as_root = true;
3385 * Seek to the correct position. We no longer use the resume key but
3386 * depend on the last file name instead.
3389 if(!continue_bit && resume_name && *resume_name) {
3390 SMB_STRUCT_STAT st;
3392 long current_pos = 0;
3394 * Remember, name_to_8_3 is called by
3395 * get_lanman2_dir_entry(), so the resume name
3396 * could be mangled. Ensure we check the unmangled name.
3399 if (mangle_is_mangled(resume_name, conn->params)) {
3400 char *new_resume_name = NULL;
3401 mangle_lookup_name_from_8_3(ctx,
3402 resume_name,
3403 &new_resume_name,
3404 conn->params);
3405 if (new_resume_name) {
3406 resume_name = new_resume_name;
3411 * Fix for NT redirector problem triggered by resume key indexes
3412 * changing between directory scans. We now return a resume key of 0
3413 * and instead look for the filename to continue from (also given
3414 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3415 * findfirst/findnext (as is usual) then the directory pointer
3416 * should already be at the correct place.
3419 finished = !dptr_SearchDir(fsp->dptr, resume_name, &current_pos, &st);
3420 } /* end if resume_name && !continue_bit */
3422 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3423 bool got_exact_match = False;
3425 /* this is a heuristic to avoid seeking the fsp->dptr except when
3426 absolutely necessary. It allows for a filename of about 40 chars */
3427 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3428 out_of_space = True;
3429 finished = False;
3430 } else {
3431 ntstatus = get_lanman2_dir_entry(ctx,
3432 conn,
3433 fsp->dptr,
3434 req->flags2,
3435 mask,dirtype,info_level,
3436 requires_resume_key,dont_descend,
3437 ask_sharemode,
3438 &p,pdata,data_end,
3439 space_remaining,
3440 &got_exact_match,
3441 &last_entry_off, ea_list);
3442 if (NT_STATUS_EQUAL(ntstatus,
3443 NT_STATUS_ILLEGAL_CHARACTER)) {
3445 * Bad character conversion on name. Ignore this
3446 * entry.
3448 continue;
3450 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3451 out_of_space = true;
3452 } else {
3453 finished = !NT_STATUS_IS_OK(ntstatus);
3457 if (!finished && !out_of_space)
3458 numentries++;
3461 * As an optimisation if we know we aren't looking
3462 * for a wildcard name (ie. the name matches the wildcard exactly)
3463 * then we can finish on any (first) match.
3464 * This speeds up large directory searches. JRA.
3467 if(got_exact_match)
3468 finished = True;
3470 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3473 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3474 smb_fn_name(req->cmd),
3475 mask, directory, dirtype, numentries ) );
3477 /* Check if we can close the fsp->dptr */
3478 if(close_after_request || (finished && close_if_end)) {
3479 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3480 dptr_num = -1;
3481 close_file(NULL, fsp, NORMAL_CLOSE);
3482 fsp = NULL;
3485 if (as_root) {
3486 unbecome_root();
3489 /* Set up the return parameter block */
3490 SSVAL(params,0,numentries);
3491 SSVAL(params,2,finished);
3492 SSVAL(params,4,0); /* Never an EA error */
3493 SSVAL(params,6,last_entry_off);
3495 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3496 max_data_bytes);
3498 return;
3501 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3503 const struct loadparm_substitution *lp_sub =
3504 loadparm_s3_global_substitution();
3506 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3507 return objid;
3510 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3512 SMB_ASSERT(extended_info != NULL);
3514 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3515 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3516 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3517 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3518 #ifdef SAMBA_VERSION_REVISION
3519 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3520 #endif
3521 extended_info->samba_subversion = 0;
3522 #ifdef SAMBA_VERSION_RC_RELEASE
3523 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3524 #else
3525 #ifdef SAMBA_VERSION_PRE_RELEASE
3526 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3527 #endif
3528 #endif
3529 #ifdef SAMBA_VERSION_VENDOR_PATCH
3530 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3531 #endif
3532 extended_info->samba_gitcommitdate = 0;
3533 #ifdef SAMBA_VERSION_COMMIT_TIME
3534 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3535 #endif
3537 memset(extended_info->samba_version_string, 0,
3538 sizeof(extended_info->samba_version_string));
3540 snprintf (extended_info->samba_version_string,
3541 sizeof(extended_info->samba_version_string),
3542 "%s", samba_version_string());
3545 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3546 connection_struct *conn,
3547 TALLOC_CTX *mem_ctx,
3548 uint16_t info_level,
3549 uint16_t flags2,
3550 unsigned int max_data_bytes,
3551 size_t *fixed_portion,
3552 struct smb_filename *fname,
3553 char **ppdata,
3554 int *ret_data_len)
3556 const struct loadparm_substitution *lp_sub =
3557 loadparm_s3_global_substitution();
3558 char *pdata, *end_data;
3559 int data_len = 0;
3560 size_t len = 0;
3561 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3562 int snum = SNUM(conn);
3563 const char *fstype = lp_fstype(SNUM(conn));
3564 const char *filename = NULL;
3565 const uint64_t bytes_per_sector = 512;
3566 uint32_t additional_flags = 0;
3567 struct smb_filename smb_fname;
3568 SMB_STRUCT_STAT st;
3569 NTSTATUS status = NT_STATUS_OK;
3570 uint64_t df_ret;
3572 if (fname == NULL || fname->base_name == NULL) {
3573 filename = ".";
3574 } else {
3575 filename = fname->base_name;
3578 if (IS_IPC(conn)) {
3579 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3580 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3581 "info level (0x%x) on IPC$.\n",
3582 (unsigned int)info_level));
3583 return NT_STATUS_ACCESS_DENIED;
3587 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3589 smb_fname = (struct smb_filename) {
3590 .base_name = discard_const_p(char, filename),
3591 .flags = fname ? fname->flags : 0,
3592 .twrp = fname ? fname->twrp : 0,
3595 if(info_level != SMB_FS_QUOTA_INFORMATION
3596 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3597 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3598 return map_nt_error_from_unix(errno);
3601 st = smb_fname.st;
3603 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3604 return NT_STATUS_INVALID_PARAMETER;
3607 *ppdata = (char *)SMB_REALLOC(
3608 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3609 if (*ppdata == NULL) {
3610 return NT_STATUS_NO_MEMORY;
3613 pdata = *ppdata;
3614 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3615 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3617 *fixed_portion = 0;
3619 switch (info_level) {
3620 case SMB_INFO_ALLOCATION:
3622 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3623 data_len = 18;
3624 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3625 &dfree, &dsize);
3626 if (df_ret == (uint64_t)-1) {
3627 return map_nt_error_from_unix(errno);
3630 block_size = lp_block_size(snum);
3631 if (bsize < block_size) {
3632 uint64_t factor = block_size/bsize;
3633 bsize = block_size;
3634 dsize /= factor;
3635 dfree /= factor;
3637 if (bsize > block_size) {
3638 uint64_t factor = bsize/block_size;
3639 bsize = block_size;
3640 dsize *= factor;
3641 dfree *= factor;
3643 sectors_per_unit = bsize/bytes_per_sector;
3645 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3647 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3650 * For large drives, return max values and not modulo.
3652 dsize = MIN(dsize, UINT32_MAX);
3653 dfree = MIN(dfree, UINT32_MAX);
3655 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3656 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3657 SIVAL(pdata,l1_cUnit,dsize);
3658 SIVAL(pdata,l1_cUnitAvail,dfree);
3659 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3660 break;
3663 case SMB_INFO_VOLUME:
3664 /* Return volume name */
3666 * Add volume serial number - hash of a combination of
3667 * the called hostname and the service name.
3669 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3671 * Win2k3 and previous mess this up by sending a name length
3672 * one byte short. I believe only older clients (OS/2 Win9x) use
3673 * this call so try fixing this by adding a terminating null to
3674 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3676 status = srvstr_push(
3677 pdata, flags2,
3678 pdata+l2_vol_szVolLabel, vname,
3679 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3680 STR_NOALIGN|STR_TERMINATE, &len);
3681 if (!NT_STATUS_IS_OK(status)) {
3682 return status;
3684 SCVAL(pdata,l2_vol_cch,len);
3685 data_len = l2_vol_szVolLabel + len;
3686 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3687 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3688 (unsigned)len, vname));
3689 break;
3691 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3692 case SMB_FS_ATTRIBUTE_INFORMATION:
3694 additional_flags = 0;
3695 #if defined(HAVE_SYS_QUOTAS)
3696 additional_flags |= FILE_VOLUME_QUOTAS;
3697 #endif
3699 if(lp_nt_acl_support(SNUM(conn))) {
3700 additional_flags |= FILE_PERSISTENT_ACLS;
3703 /* Capabilities are filled in at connection time through STATVFS call */
3704 additional_flags |= conn->fs_capabilities;
3705 additional_flags |= lp_parm_int(conn->params->service,
3706 "share", "fake_fscaps",
3709 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3710 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3711 additional_flags); /* FS ATTRIBUTES */
3713 SIVAL(pdata,4,255); /* Max filename component length */
3714 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3715 and will think we can't do long filenames */
3716 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3717 PTR_DIFF(end_data, pdata+12),
3718 STR_UNICODE, &len);
3719 if (!NT_STATUS_IS_OK(status)) {
3720 return status;
3722 SIVAL(pdata,8,len);
3723 data_len = 12 + len;
3724 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3725 /* the client only requested a portion of the
3726 file system name */
3727 data_len = max_data_bytes;
3728 status = STATUS_BUFFER_OVERFLOW;
3730 *fixed_portion = 16;
3731 break;
3733 case SMB_QUERY_FS_LABEL_INFO:
3734 case SMB_FS_LABEL_INFORMATION:
3735 status = srvstr_push(pdata, flags2, pdata+4, vname,
3736 PTR_DIFF(end_data, pdata+4), 0, &len);
3737 if (!NT_STATUS_IS_OK(status)) {
3738 return status;
3740 data_len = 4 + len;
3741 SIVAL(pdata,0,len);
3742 break;
3744 case SMB_QUERY_FS_VOLUME_INFO:
3745 case SMB_FS_VOLUME_INFORMATION:
3748 * Add volume serial number - hash of a combination of
3749 * the called hostname and the service name.
3751 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3752 (str_checksum(get_local_machine_name())<<16));
3754 /* Max label len is 32 characters. */
3755 status = srvstr_push(pdata, flags2, pdata+18, vname,
3756 PTR_DIFF(end_data, pdata+18),
3757 STR_UNICODE, &len);
3758 if (!NT_STATUS_IS_OK(status)) {
3759 return status;
3761 SIVAL(pdata,12,len);
3762 data_len = 18+len;
3764 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3765 (int)strlen(vname),vname,
3766 lp_servicename(talloc_tos(), lp_sub, snum)));
3767 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3768 /* the client only requested a portion of the
3769 volume label */
3770 data_len = max_data_bytes;
3771 status = STATUS_BUFFER_OVERFLOW;
3773 *fixed_portion = 24;
3774 break;
3776 case SMB_QUERY_FS_SIZE_INFO:
3777 case SMB_FS_SIZE_INFORMATION:
3779 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3780 data_len = 24;
3781 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3782 &dfree, &dsize);
3783 if (df_ret == (uint64_t)-1) {
3784 return map_nt_error_from_unix(errno);
3786 block_size = lp_block_size(snum);
3787 if (bsize < block_size) {
3788 uint64_t factor = block_size/bsize;
3789 bsize = block_size;
3790 dsize /= factor;
3791 dfree /= factor;
3793 if (bsize > block_size) {
3794 uint64_t factor = bsize/block_size;
3795 bsize = block_size;
3796 dsize *= factor;
3797 dfree *= factor;
3799 sectors_per_unit = bsize/bytes_per_sector;
3800 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3801 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3802 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3803 SBIG_UINT(pdata,0,dsize);
3804 SBIG_UINT(pdata,8,dfree);
3805 SIVAL(pdata,16,sectors_per_unit);
3806 SIVAL(pdata,20,bytes_per_sector);
3807 *fixed_portion = 24;
3808 break;
3811 case SMB_FS_FULL_SIZE_INFORMATION:
3813 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3814 data_len = 32;
3815 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3816 &dfree, &dsize);
3817 if (df_ret == (uint64_t)-1) {
3818 return map_nt_error_from_unix(errno);
3820 block_size = lp_block_size(snum);
3821 if (bsize < block_size) {
3822 uint64_t factor = block_size/bsize;
3823 bsize = block_size;
3824 dsize /= factor;
3825 dfree /= factor;
3827 if (bsize > block_size) {
3828 uint64_t factor = bsize/block_size;
3829 bsize = block_size;
3830 dsize *= factor;
3831 dfree *= factor;
3833 sectors_per_unit = bsize/bytes_per_sector;
3834 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3835 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3836 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3837 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3838 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3839 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3840 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3841 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3842 *fixed_portion = 32;
3843 break;
3846 case SMB_QUERY_FS_DEVICE_INFO:
3847 case SMB_FS_DEVICE_INFORMATION:
3849 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3851 if (!CAN_WRITE(conn)) {
3852 characteristics |= FILE_READ_ONLY_DEVICE;
3854 data_len = 8;
3855 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3856 SIVAL(pdata,4,characteristics);
3857 *fixed_portion = 8;
3858 break;
3861 #ifdef HAVE_SYS_QUOTAS
3862 case SMB_FS_QUOTA_INFORMATION:
3864 * what we have to send --metze:
3866 * Unknown1: 24 NULL bytes
3867 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3868 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3869 * Quota Flags: 2 byte :
3870 * Unknown3: 6 NULL bytes
3872 * 48 bytes total
3874 * details for Quota Flags:
3876 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3877 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3878 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3879 * 0x0001 Enable Quotas: enable quota for this fs
3883 /* we need to fake up a fsp here,
3884 * because its not send in this call
3886 files_struct fsp;
3887 SMB_NTQUOTA_STRUCT quotas;
3889 ZERO_STRUCT(fsp);
3890 ZERO_STRUCT(quotas);
3892 fsp.conn = conn;
3893 fsp.fnum = FNUM_FIELD_INVALID;
3895 /* access check */
3896 if (get_current_uid(conn) != 0) {
3897 DEBUG(0,("get_user_quota: access_denied "
3898 "service [%s] user [%s]\n",
3899 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3900 conn->session_info->unix_info->unix_name));
3901 return NT_STATUS_ACCESS_DENIED;
3904 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3905 NULL, &quotas);
3906 if (!NT_STATUS_IS_OK(status)) {
3907 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3908 return status;
3911 data_len = 48;
3913 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3914 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3916 /* Unknown1 24 NULL bytes*/
3917 SBIG_UINT(pdata,0,(uint64_t)0);
3918 SBIG_UINT(pdata,8,(uint64_t)0);
3919 SBIG_UINT(pdata,16,(uint64_t)0);
3921 /* Default Soft Quota 8 bytes */
3922 SBIG_UINT(pdata,24,quotas.softlim);
3924 /* Default Hard Quota 8 bytes */
3925 SBIG_UINT(pdata,32,quotas.hardlim);
3927 /* Quota flag 2 bytes */
3928 SSVAL(pdata,40,quotas.qflags);
3930 /* Unknown3 6 NULL bytes */
3931 SSVAL(pdata,42,0);
3932 SIVAL(pdata,44,0);
3934 break;
3936 #endif /* HAVE_SYS_QUOTAS */
3937 case SMB_FS_OBJECTID_INFORMATION:
3939 unsigned char objid[16];
3940 struct smb_extended_info extended_info;
3941 memcpy(pdata,create_volume_objectid(conn, objid),16);
3942 samba_extended_info_version (&extended_info);
3943 SIVAL(pdata,16,extended_info.samba_magic);
3944 SIVAL(pdata,20,extended_info.samba_version);
3945 SIVAL(pdata,24,extended_info.samba_subversion);
3946 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3947 memcpy(pdata+36,extended_info.samba_version_string,28);
3948 data_len = 64;
3949 break;
3952 case SMB_FS_SECTOR_SIZE_INFORMATION:
3954 data_len = 28;
3956 * These values match a physical Windows Server 2012
3957 * share backed by NTFS atop spinning rust.
3959 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3960 /* logical_bytes_per_sector */
3961 SIVAL(pdata, 0, bytes_per_sector);
3962 /* phys_bytes_per_sector_atomic */
3963 SIVAL(pdata, 4, bytes_per_sector);
3964 /* phys_bytes_per_sector_perf */
3965 SIVAL(pdata, 8, bytes_per_sector);
3966 /* fs_effective_phys_bytes_per_sector_atomic */
3967 SIVAL(pdata, 12, bytes_per_sector);
3968 /* flags */
3969 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3970 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3971 /* byte_off_sector_align */
3972 SIVAL(pdata, 20, 0);
3973 /* byte_off_partition_align */
3974 SIVAL(pdata, 24, 0);
3975 *fixed_portion = 28;
3976 break;
3981 * Query the version and capabilities of the CIFS UNIX extensions
3982 * in use.
3985 case SMB_QUERY_CIFS_UNIX_INFO:
3987 bool large_write = lp_min_receive_file_size() &&
3988 !srv_is_signing_active(xconn);
3989 bool large_read = !srv_is_signing_active(xconn);
3990 int encrypt_caps = 0;
3992 if (!lp_unix_extensions()) {
3993 return NT_STATUS_INVALID_LEVEL;
3996 switch (conn->encrypt_level) {
3997 case SMB_SIGNING_OFF:
3998 encrypt_caps = 0;
3999 break;
4000 case SMB_SIGNING_DESIRED:
4001 case SMB_SIGNING_IF_REQUIRED:
4002 case SMB_SIGNING_DEFAULT:
4003 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4004 break;
4005 case SMB_SIGNING_REQUIRED:
4006 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4007 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4008 large_write = false;
4009 large_read = false;
4010 break;
4013 data_len = 12;
4014 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4015 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4017 /* We have POSIX ACLs, pathname, encryption,
4018 * large read/write, and locking capability. */
4020 SBIG_UINT(pdata,4,((uint64_t)(
4021 CIFS_UNIX_POSIX_ACLS_CAP|
4022 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4023 CIFS_UNIX_FCNTL_LOCKS_CAP|
4024 CIFS_UNIX_EXTATTR_CAP|
4025 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4026 encrypt_caps|
4027 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4028 (large_write ?
4029 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4030 break;
4033 case SMB_QUERY_POSIX_FS_INFO:
4035 int rc;
4036 vfs_statvfs_struct svfs;
4038 if (!lp_unix_extensions()) {
4039 return NT_STATUS_INVALID_LEVEL;
4042 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4044 if (!rc) {
4045 data_len = 56;
4046 SIVAL(pdata,0,svfs.OptimalTransferSize);
4047 SIVAL(pdata,4,svfs.BlockSize);
4048 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4049 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4050 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4051 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4052 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4053 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4054 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4055 #ifdef EOPNOTSUPP
4056 } else if (rc == EOPNOTSUPP) {
4057 return NT_STATUS_INVALID_LEVEL;
4058 #endif /* EOPNOTSUPP */
4059 } else {
4060 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4061 return NT_STATUS_DOS(ERRSRV, ERRerror);
4063 break;
4066 case SMB_QUERY_POSIX_WHOAMI:
4068 uint32_t flags = 0;
4069 uint32_t sid_bytes;
4070 int i;
4072 if (!lp_unix_extensions()) {
4073 return NT_STATUS_INVALID_LEVEL;
4076 if (max_data_bytes < 40) {
4077 return NT_STATUS_BUFFER_TOO_SMALL;
4080 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4081 flags |= SMB_WHOAMI_GUEST;
4084 /* NOTE: 8 bytes for UID/GID, irrespective of native
4085 * platform size. This matches
4086 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4088 data_len = 4 /* flags */
4089 + 4 /* flag mask */
4090 + 8 /* uid */
4091 + 8 /* gid */
4092 + 4 /* ngroups */
4093 + 4 /* num_sids */
4094 + 4 /* SID bytes */
4095 + 4 /* pad/reserved */
4096 + (conn->session_info->unix_token->ngroups * 8)
4097 /* groups list */
4098 + (conn->session_info->security_token->num_sids *
4099 SID_MAX_SIZE)
4100 /* SID list */;
4102 SIVAL(pdata, 0, flags);
4103 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4104 SBIG_UINT(pdata, 8,
4105 (uint64_t)conn->session_info->unix_token->uid);
4106 SBIG_UINT(pdata, 16,
4107 (uint64_t)conn->session_info->unix_token->gid);
4110 if (data_len >= max_data_bytes) {
4111 /* Potential overflow, skip the GIDs and SIDs. */
4113 SIVAL(pdata, 24, 0); /* num_groups */
4114 SIVAL(pdata, 28, 0); /* num_sids */
4115 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4116 SIVAL(pdata, 36, 0); /* reserved */
4118 data_len = 40;
4119 break;
4122 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4123 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4125 /* We walk the SID list twice, but this call is fairly
4126 * infrequent, and I don't expect that it's performance
4127 * sensitive -- jpeach
4129 for (i = 0, sid_bytes = 0;
4130 i < conn->session_info->security_token->num_sids; ++i) {
4131 sid_bytes += ndr_size_dom_sid(
4132 &conn->session_info->security_token->sids[i],
4136 /* SID list byte count */
4137 SIVAL(pdata, 32, sid_bytes);
4139 /* 4 bytes pad/reserved - must be zero */
4140 SIVAL(pdata, 36, 0);
4141 data_len = 40;
4143 /* GID list */
4144 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4145 SBIG_UINT(pdata, data_len,
4146 (uint64_t)conn->session_info->unix_token->groups[i]);
4147 data_len += 8;
4150 /* SID list */
4151 for (i = 0;
4152 i < conn->session_info->security_token->num_sids; ++i) {
4153 int sid_len = ndr_size_dom_sid(
4154 &conn->session_info->security_token->sids[i],
4157 sid_linearize((uint8_t *)(pdata + data_len),
4158 sid_len,
4159 &conn->session_info->security_token->sids[i]);
4160 data_len += sid_len;
4163 break;
4166 case SMB_MAC_QUERY_FS_INFO:
4168 * Thursby MAC extension... ONLY on NTFS filesystems
4169 * once we do streams then we don't need this
4171 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4172 data_len = 88;
4173 SIVAL(pdata,84,0x100); /* Don't support mac... */
4174 break;
4177 FALL_THROUGH;
4178 default:
4179 return NT_STATUS_INVALID_LEVEL;
4182 *ret_data_len = data_len;
4183 return status;
4186 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4187 struct smb_request *req,
4188 files_struct *fsp,
4189 const DATA_BLOB *qdata)
4191 const struct loadparm_substitution *lp_sub =
4192 loadparm_s3_global_substitution();
4193 NTSTATUS status;
4194 SMB_NTQUOTA_STRUCT quotas;
4196 ZERO_STRUCT(quotas);
4198 /* access check */
4199 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4200 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4201 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4202 conn->session_info->unix_info->unix_name));
4203 return NT_STATUS_ACCESS_DENIED;
4206 if (!check_fsp_ntquota_handle(conn, req,
4207 fsp)) {
4208 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4209 return NT_STATUS_INVALID_HANDLE;
4212 /* note: normally there're 48 bytes,
4213 * but we didn't use the last 6 bytes for now
4214 * --metze
4216 if (qdata->length < 42) {
4217 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4218 (unsigned int)qdata->length));
4219 return NT_STATUS_INVALID_PARAMETER;
4222 /* unknown_1 24 NULL bytes in pdata*/
4224 /* the soft quotas 8 bytes (uint64_t)*/
4225 quotas.softlim = BVAL(qdata->data,24);
4227 /* the hard quotas 8 bytes (uint64_t)*/
4228 quotas.hardlim = BVAL(qdata->data,32);
4230 /* quota_flags 2 bytes **/
4231 quotas.qflags = SVAL(qdata->data,40);
4233 /* unknown_2 6 NULL bytes follow*/
4235 /* now set the quotas */
4236 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4237 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4238 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4239 status = map_nt_error_from_unix(errno);
4240 } else {
4241 status = NT_STATUS_OK;
4243 return status;
4246 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4247 struct smb_request *req,
4248 TALLOC_CTX *mem_ctx,
4249 uint16_t info_level,
4250 files_struct *fsp,
4251 const DATA_BLOB *pdata)
4253 switch (info_level) {
4254 case SMB_FS_QUOTA_INFORMATION:
4256 return smb_set_fsquota(conn,
4257 req,
4258 fsp,
4259 pdata);
4262 default:
4263 break;
4265 return NT_STATUS_INVALID_LEVEL;
4268 /****************************************************************************
4269 Reply to a TRANS2_QFSINFO (query filesystem info).
4270 ****************************************************************************/
4272 static void call_trans2qfsinfo(connection_struct *conn,
4273 struct smb_request *req,
4274 char **pparams, int total_params,
4275 char **ppdata, int total_data,
4276 unsigned int max_data_bytes)
4278 char *params = *pparams;
4279 uint16_t info_level;
4280 int data_len = 0;
4281 size_t fixed_portion;
4282 NTSTATUS status;
4284 if (total_params < 2) {
4285 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4286 return;
4289 info_level = SVAL(params,0);
4291 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4292 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4293 DEBUG(0,("call_trans2qfsinfo: encryption required "
4294 "and info level 0x%x sent.\n",
4295 (unsigned int)info_level));
4296 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4297 return;
4301 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4303 status = smbd_do_qfsinfo(req->xconn, conn, req,
4304 info_level,
4305 req->flags2,
4306 max_data_bytes,
4307 &fixed_portion,
4308 NULL,
4309 ppdata, &data_len);
4310 if (!NT_STATUS_IS_OK(status)) {
4311 reply_nterror(req, status);
4312 return;
4315 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4316 max_data_bytes);
4318 DEBUG( 4, ( "%s info_level = %d\n",
4319 smb_fn_name(req->cmd), info_level) );
4321 return;
4324 /****************************************************************************
4325 Reply to a TRANS2_SETFSINFO (set filesystem info).
4326 ****************************************************************************/
4328 static void call_trans2setfsinfo(connection_struct *conn,
4329 struct smb_request *req,
4330 char **pparams, int total_params,
4331 char **ppdata, int total_data,
4332 unsigned int max_data_bytes)
4334 const struct loadparm_substitution *lp_sub =
4335 loadparm_s3_global_substitution();
4336 struct smbXsrv_connection *xconn = req->xconn;
4337 char *pdata = *ppdata;
4338 char *params = *pparams;
4339 uint16_t info_level;
4341 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4342 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4344 /* */
4345 if (total_params < 4) {
4346 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4347 total_params));
4348 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4349 return;
4352 info_level = SVAL(params,2);
4354 if (IS_IPC(conn)) {
4355 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4356 info_level != SMB_SET_CIFS_UNIX_INFO) {
4357 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4358 "info level (0x%x) on IPC$.\n",
4359 (unsigned int)info_level));
4360 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4361 return;
4365 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4366 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4367 DEBUG(0,("call_trans2setfsinfo: encryption required "
4368 "and info level 0x%x sent.\n",
4369 (unsigned int)info_level));
4370 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4371 return;
4375 switch(info_level) {
4376 case SMB_SET_CIFS_UNIX_INFO:
4377 if (!lp_unix_extensions()) {
4378 DEBUG(2,("call_trans2setfsinfo: "
4379 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4380 "unix extensions off\n"));
4381 reply_nterror(req,
4382 NT_STATUS_INVALID_LEVEL);
4383 return;
4386 /* There should be 12 bytes of capabilities set. */
4387 if (total_data < 12) {
4388 reply_nterror(
4389 req,
4390 NT_STATUS_INVALID_PARAMETER);
4391 return;
4393 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4394 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4395 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4396 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4397 /* Just print these values for now. */
4398 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4399 "major = %u, minor = %u cap_low = 0x%x, "
4400 "cap_high = 0x%xn",
4401 (unsigned int)xconn->
4402 smb1.unix_info.client_major,
4403 (unsigned int)xconn->
4404 smb1.unix_info.client_minor,
4405 (unsigned int)xconn->
4406 smb1.unix_info.client_cap_low,
4407 (unsigned int)xconn->
4408 smb1.unix_info.client_cap_high));
4410 /* Here is where we must switch to posix pathname processing... */
4411 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4412 lp_set_posix_pathnames();
4413 mangle_change_to_posix();
4416 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4417 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4418 /* Client that knows how to do posix locks,
4419 * but not posix open/mkdir operations. Set a
4420 * default type for read/write checks. */
4422 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4425 break;
4427 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4429 NTSTATUS status;
4430 size_t param_len = 0;
4431 size_t data_len = total_data;
4433 if (!lp_unix_extensions()) {
4434 reply_nterror(
4435 req,
4436 NT_STATUS_INVALID_LEVEL);
4437 return;
4440 if (lp_server_smb_encrypt(SNUM(conn)) ==
4441 SMB_ENCRYPTION_OFF) {
4442 reply_nterror(
4443 req,
4444 NT_STATUS_NOT_SUPPORTED);
4445 return;
4448 if (xconn->smb1.echo_handler.trusted_fde) {
4449 DEBUG( 2,("call_trans2setfsinfo: "
4450 "request transport encryption disabled"
4451 "with 'fork echo handler = yes'\n"));
4452 reply_nterror(
4453 req,
4454 NT_STATUS_NOT_SUPPORTED);
4455 return;
4458 DEBUG( 4,("call_trans2setfsinfo: "
4459 "request transport encryption.\n"));
4461 status = srv_request_encryption_setup(conn,
4462 (unsigned char **)ppdata,
4463 &data_len,
4464 (unsigned char **)pparams,
4465 &param_len);
4467 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4468 !NT_STATUS_IS_OK(status)) {
4469 reply_nterror(req, status);
4470 return;
4473 send_trans2_replies(conn, req,
4474 NT_STATUS_OK,
4475 *pparams,
4476 param_len,
4477 *ppdata,
4478 data_len,
4479 max_data_bytes);
4481 if (NT_STATUS_IS_OK(status)) {
4482 /* Server-side transport
4483 * encryption is now *on*. */
4484 status = srv_encryption_start(conn);
4485 if (!NT_STATUS_IS_OK(status)) {
4486 char *reason = talloc_asprintf(talloc_tos(),
4487 "Failure in setting "
4488 "up encrypted transport: %s",
4489 nt_errstr(status));
4490 exit_server_cleanly(reason);
4493 return;
4496 case SMB_FS_QUOTA_INFORMATION:
4498 NTSTATUS status;
4499 DATA_BLOB qdata = {
4500 .data = (uint8_t *)pdata,
4501 .length = total_data
4503 files_struct *fsp = NULL;
4504 fsp = file_fsp(req, SVAL(params,0));
4506 status = smb_set_fsquota(conn,
4507 req,
4508 fsp,
4509 &qdata);
4510 if (!NT_STATUS_IS_OK(status)) {
4511 reply_nterror(req, status);
4512 return;
4514 break;
4516 default:
4517 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4518 info_level));
4519 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4520 return;
4521 break;
4525 * sending this reply works fine,
4526 * but I'm not sure it's the same
4527 * like windows do...
4528 * --metze
4530 reply_outbuf(req, 10, 0);
4533 #if defined(HAVE_POSIX_ACLS)
4534 /****************************************************************************
4535 Utility function to count the number of entries in a POSIX acl.
4536 ****************************************************************************/
4538 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4540 unsigned int ace_count = 0;
4541 int entry_id = SMB_ACL_FIRST_ENTRY;
4542 SMB_ACL_ENTRY_T entry;
4544 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4545 /* get_next... */
4546 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4547 entry_id = SMB_ACL_NEXT_ENTRY;
4549 ace_count++;
4551 return ace_count;
4554 /****************************************************************************
4555 Utility function to marshall a POSIX acl into wire format.
4556 ****************************************************************************/
4558 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4560 int entry_id = SMB_ACL_FIRST_ENTRY;
4561 SMB_ACL_ENTRY_T entry;
4563 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4564 SMB_ACL_TAG_T tagtype;
4565 SMB_ACL_PERMSET_T permset;
4566 unsigned char perms = 0;
4567 unsigned int own_grp;
4569 /* get_next... */
4570 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4571 entry_id = SMB_ACL_NEXT_ENTRY;
4574 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4575 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4576 return False;
4579 if (sys_acl_get_permset(entry, &permset) == -1) {
4580 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4581 return False;
4584 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4585 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4586 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4588 SCVAL(pdata,1,perms);
4590 switch (tagtype) {
4591 case SMB_ACL_USER_OBJ:
4592 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4593 own_grp = (unsigned int)pst->st_ex_uid;
4594 SIVAL(pdata,2,own_grp);
4595 SIVAL(pdata,6,0);
4596 break;
4597 case SMB_ACL_USER:
4599 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4600 if (!puid) {
4601 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4602 return False;
4604 own_grp = (unsigned int)*puid;
4605 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4606 SIVAL(pdata,2,own_grp);
4607 SIVAL(pdata,6,0);
4608 break;
4610 case SMB_ACL_GROUP_OBJ:
4611 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4612 own_grp = (unsigned int)pst->st_ex_gid;
4613 SIVAL(pdata,2,own_grp);
4614 SIVAL(pdata,6,0);
4615 break;
4616 case SMB_ACL_GROUP:
4618 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4619 if (!pgid) {
4620 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4621 return False;
4623 own_grp = (unsigned int)*pgid;
4624 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4625 SIVAL(pdata,2,own_grp);
4626 SIVAL(pdata,6,0);
4627 break;
4629 case SMB_ACL_MASK:
4630 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4631 SIVAL(pdata,2,0xFFFFFFFF);
4632 SIVAL(pdata,6,0xFFFFFFFF);
4633 break;
4634 case SMB_ACL_OTHER:
4635 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4636 SIVAL(pdata,2,0xFFFFFFFF);
4637 SIVAL(pdata,6,0xFFFFFFFF);
4638 break;
4639 default:
4640 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4641 return False;
4643 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4646 return True;
4648 #endif
4650 /****************************************************************************
4651 Store the FILE_UNIX_BASIC info.
4652 ****************************************************************************/
4654 static char *store_file_unix_basic(connection_struct *conn,
4655 char *pdata,
4656 files_struct *fsp,
4657 const SMB_STRUCT_STAT *psbuf)
4659 dev_t devno;
4661 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4662 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4664 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4665 pdata += 8;
4667 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4668 pdata += 8;
4670 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4671 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4672 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4673 pdata += 24;
4675 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4676 SIVAL(pdata,4,0);
4677 pdata += 8;
4679 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4680 SIVAL(pdata,4,0);
4681 pdata += 8;
4683 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4684 pdata += 4;
4686 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4687 devno = psbuf->st_ex_rdev;
4688 } else {
4689 devno = psbuf->st_ex_dev;
4692 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4693 SIVAL(pdata,4,0);
4694 pdata += 8;
4696 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4697 SIVAL(pdata,4,0);
4698 pdata += 8;
4700 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4701 pdata += 8;
4703 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4704 SIVAL(pdata,4,0);
4705 pdata += 8;
4707 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4708 SIVAL(pdata,4,0);
4709 pdata += 8;
4711 return pdata;
4714 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4715 * the chflags(2) (or equivalent) flags.
4717 * XXX: this really should be behind the VFS interface. To do this, we would
4718 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4719 * Each VFS module could then implement its own mapping as appropriate for the
4720 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4722 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4723 info2_flags_map[] =
4725 #ifdef UF_NODUMP
4726 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4727 #endif
4729 #ifdef UF_IMMUTABLE
4730 { UF_IMMUTABLE, EXT_IMMUTABLE },
4731 #endif
4733 #ifdef UF_APPEND
4734 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4735 #endif
4737 #ifdef UF_HIDDEN
4738 { UF_HIDDEN, EXT_HIDDEN },
4739 #endif
4741 /* Do not remove. We need to guarantee that this array has at least one
4742 * entry to build on HP-UX.
4744 { 0, 0 }
4748 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4749 uint32_t *smb_fflags, uint32_t *smb_fmask)
4751 int i;
4753 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4754 *smb_fmask |= info2_flags_map[i].smb_fflag;
4755 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4756 *smb_fflags |= info2_flags_map[i].smb_fflag;
4761 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4762 const uint32_t smb_fflags,
4763 const uint32_t smb_fmask,
4764 int *stat_fflags)
4766 uint32_t max_fmask = 0;
4767 int i;
4769 *stat_fflags = psbuf->st_ex_flags;
4771 /* For each flags requested in smb_fmask, check the state of the
4772 * corresponding flag in smb_fflags and set or clear the matching
4773 * stat flag.
4776 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4777 max_fmask |= info2_flags_map[i].smb_fflag;
4778 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4779 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4780 *stat_fflags |= info2_flags_map[i].stat_fflag;
4781 } else {
4782 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4787 /* If smb_fmask is asking to set any bits that are not supported by
4788 * our flag mappings, we should fail.
4790 if ((smb_fmask & max_fmask) != smb_fmask) {
4791 return False;
4794 return True;
4798 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4799 * of file flags and birth (create) time.
4801 static char *store_file_unix_basic_info2(connection_struct *conn,
4802 char *pdata,
4803 files_struct *fsp,
4804 const SMB_STRUCT_STAT *psbuf)
4806 uint32_t file_flags = 0;
4807 uint32_t flags_mask = 0;
4809 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4811 /* Create (birth) time 64 bit */
4812 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4813 pdata += 8;
4815 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4816 SIVAL(pdata, 0, file_flags); /* flags */
4817 SIVAL(pdata, 4, flags_mask); /* mask */
4818 pdata += 8;
4820 return pdata;
4823 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4824 const struct stream_struct *streams,
4825 char *data,
4826 unsigned int max_data_bytes,
4827 unsigned int *data_size)
4829 unsigned int i;
4830 unsigned int ofs = 0;
4832 if (max_data_bytes < 32) {
4833 return NT_STATUS_INFO_LENGTH_MISMATCH;
4836 for (i = 0; i < num_streams; i++) {
4837 unsigned int next_offset;
4838 size_t namelen;
4839 smb_ucs2_t *namebuf;
4841 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4842 streams[i].name, &namelen) ||
4843 namelen <= 2)
4845 return NT_STATUS_INVALID_PARAMETER;
4849 * name_buf is now null-terminated, we need to marshall as not
4850 * terminated
4853 namelen -= 2;
4856 * We cannot overflow ...
4858 if ((ofs + 24 + namelen) > max_data_bytes) {
4859 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4860 i));
4861 TALLOC_FREE(namebuf);
4862 return STATUS_BUFFER_OVERFLOW;
4865 SIVAL(data, ofs+4, namelen);
4866 SOFF_T(data, ofs+8, streams[i].size);
4867 SOFF_T(data, ofs+16, streams[i].alloc_size);
4868 memcpy(data+ofs+24, namebuf, namelen);
4869 TALLOC_FREE(namebuf);
4871 next_offset = ofs + 24 + namelen;
4873 if (i == num_streams-1) {
4874 SIVAL(data, ofs, 0);
4876 else {
4877 unsigned int align = ndr_align_size(next_offset, 8);
4879 if ((next_offset + align) > max_data_bytes) {
4880 DEBUG(10, ("refusing to overflow align "
4881 "reply at stream %u\n",
4882 i));
4883 TALLOC_FREE(namebuf);
4884 return STATUS_BUFFER_OVERFLOW;
4887 memset(data+next_offset, 0, align);
4888 next_offset += align;
4890 SIVAL(data, ofs, next_offset - ofs);
4891 ofs = next_offset;
4894 ofs = next_offset;
4897 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4899 *data_size = ofs;
4901 return NT_STATUS_OK;
4904 static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
4905 struct smb_request *req,
4906 struct smb_filename *smb_fname,
4907 char *pdata,
4908 unsigned int data_size_in,
4909 unsigned int *pdata_size_out)
4911 NTSTATUS status;
4912 size_t len = 0;
4913 int link_len = 0;
4914 struct smb_filename *parent_fname = NULL;
4915 struct smb_filename *base_name = NULL;
4917 char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
4919 if (!buffer) {
4920 return NT_STATUS_NO_MEMORY;
4923 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
4924 smb_fname_str_dbg(smb_fname));
4926 if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
4927 TALLOC_FREE(buffer);
4928 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4931 status = parent_pathref(talloc_tos(),
4932 conn->cwd_fsp,
4933 smb_fname,
4934 &parent_fname,
4935 &base_name);
4936 if (!NT_STATUS_IS_OK(status)) {
4937 TALLOC_FREE(buffer);
4938 return status;
4941 link_len = SMB_VFS_READLINKAT(conn,
4942 parent_fname->fsp,
4943 base_name,
4944 buffer,
4945 PATH_MAX);
4947 TALLOC_FREE(parent_fname);
4949 if (link_len == -1) {
4950 TALLOC_FREE(buffer);
4951 return map_nt_error_from_unix(errno);
4954 buffer[link_len] = 0;
4955 status = srvstr_push(pdata,
4956 req->flags2,
4957 pdata,
4958 buffer,
4959 data_size_in,
4960 STR_TERMINATE,
4961 &len);
4962 TALLOC_FREE(buffer);
4963 if (!NT_STATUS_IS_OK(status)) {
4964 return status;
4966 *pdata_size_out = len;
4968 return NT_STATUS_OK;
4971 #if defined(HAVE_POSIX_ACLS)
4972 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4973 struct smb_request *req,
4974 files_struct *fsp,
4975 struct smb_filename *smb_fname,
4976 char *pdata,
4977 unsigned int data_size_in,
4978 unsigned int *pdata_size_out)
4980 SMB_ACL_T file_acl = NULL;
4981 SMB_ACL_T def_acl = NULL;
4982 uint16_t num_file_acls = 0;
4983 uint16_t num_def_acls = 0;
4984 unsigned int size_needed = 0;
4985 NTSTATUS status;
4986 bool ok;
4987 bool close_fsp = false;
4990 * Ensure we always operate on a file descriptor, not just
4991 * the filename.
4993 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4994 uint32_t access_mask = SEC_STD_READ_CONTROL|
4995 FILE_READ_ATTRIBUTES|
4996 FILE_WRITE_ATTRIBUTES;
4998 status = get_posix_fsp(conn,
4999 req,
5000 smb_fname,
5001 access_mask,
5002 &fsp);
5004 if (!NT_STATUS_IS_OK(status)) {
5005 goto out;
5007 close_fsp = true;
5010 SMB_ASSERT(fsp != NULL);
5012 status = refuse_symlink(conn,
5013 fsp,
5014 fsp->fsp_name);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 goto out;
5019 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5020 talloc_tos());
5022 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5023 DBG_INFO("ACLs not implemented on "
5024 "filesystem containing %s\n",
5025 fsp_str_dbg(fsp));
5026 status = NT_STATUS_NOT_IMPLEMENTED;
5027 goto out;
5030 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5032 * We can only have default POSIX ACLs on
5033 * directories.
5035 if (!fsp->fsp_flags.is_directory) {
5036 DBG_INFO("Non-directory open %s\n",
5037 fsp_str_dbg(fsp));
5038 status = NT_STATUS_INVALID_HANDLE;
5039 goto out;
5041 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5042 fsp->fsp_name,
5043 SMB_ACL_TYPE_DEFAULT,
5044 talloc_tos());
5045 def_acl = free_empty_sys_acl(conn, def_acl);
5048 num_file_acls = count_acl_entries(conn, file_acl);
5049 num_def_acls = count_acl_entries(conn, def_acl);
5051 /* Wrap checks. */
5052 if (num_file_acls + num_def_acls < num_file_acls) {
5053 status = NT_STATUS_INVALID_PARAMETER;
5054 goto out;
5057 size_needed = num_file_acls + num_def_acls;
5060 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5061 * than UINT_MAX, so check by division.
5063 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5064 status = NT_STATUS_INVALID_PARAMETER;
5065 goto out;
5068 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5069 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5070 status = NT_STATUS_INVALID_PARAMETER;
5071 goto out;
5073 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5075 if ( data_size_in < size_needed) {
5076 DBG_INFO("data_size too small (%u) need %u\n",
5077 data_size_in,
5078 size_needed);
5079 status = NT_STATUS_BUFFER_TOO_SMALL;
5080 goto out;
5083 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5084 SSVAL(pdata,2,num_file_acls);
5085 SSVAL(pdata,4,num_def_acls);
5086 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5088 ok = marshall_posix_acl(conn,
5089 pdata,
5090 &fsp->fsp_name->st,
5091 file_acl);
5092 if (!ok) {
5093 status = NT_STATUS_INTERNAL_ERROR;
5094 goto out;
5096 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5098 ok = marshall_posix_acl(conn,
5099 pdata,
5100 &fsp->fsp_name->st,
5101 def_acl);
5102 if (!ok) {
5103 status = NT_STATUS_INTERNAL_ERROR;
5104 goto out;
5107 *pdata_size_out = size_needed;
5108 status = NT_STATUS_OK;
5110 out:
5112 if (close_fsp) {
5114 * Ensure the stat struct in smb_fname is up to
5115 * date. Structure copy.
5117 smb_fname->st = fsp->fsp_name->st;
5118 (void)close_file(req, fsp, NORMAL_CLOSE);
5119 fsp = NULL;
5122 TALLOC_FREE(file_acl);
5123 TALLOC_FREE(def_acl);
5124 return status;
5126 #endif
5128 /****************************************************************************
5129 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5130 ****************************************************************************/
5132 static void call_trans2qpipeinfo(connection_struct *conn,
5133 struct smb_request *req,
5134 unsigned int tran_call,
5135 char **pparams, int total_params,
5136 char **ppdata, int total_data,
5137 unsigned int max_data_bytes)
5139 char *params = *pparams;
5140 char *pdata = *ppdata;
5141 unsigned int data_size = 0;
5142 unsigned int param_size = 2;
5143 uint16_t info_level;
5144 files_struct *fsp;
5146 if (!params) {
5147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5148 return;
5151 if (total_params < 4) {
5152 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5153 return;
5156 fsp = file_fsp(req, SVAL(params,0));
5157 if (!fsp_is_np(fsp)) {
5158 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5159 return;
5162 info_level = SVAL(params,2);
5164 *pparams = (char *)SMB_REALLOC(*pparams,2);
5165 if (*pparams == NULL) {
5166 reply_nterror(req, NT_STATUS_NO_MEMORY);
5167 return;
5169 params = *pparams;
5170 SSVAL(params,0,0);
5171 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5172 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5173 return;
5175 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5176 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5177 if (*ppdata == NULL ) {
5178 reply_nterror(req, NT_STATUS_NO_MEMORY);
5179 return;
5181 pdata = *ppdata;
5183 switch (info_level) {
5184 case SMB_FILE_STANDARD_INFORMATION:
5185 memset(pdata,0,24);
5186 SOFF_T(pdata,0,4096LL);
5187 SIVAL(pdata,16,1);
5188 SIVAL(pdata,20,1);
5189 data_size = 24;
5190 break;
5192 default:
5193 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5194 return;
5197 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5198 max_data_bytes);
5200 return;
5203 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5204 TALLOC_CTX *mem_ctx,
5205 struct smb_request *req,
5206 uint16_t info_level,
5207 files_struct *fsp,
5208 struct smb_filename *smb_fname,
5209 bool delete_pending,
5210 struct timespec write_time_ts,
5211 struct ea_list *ea_list,
5212 int lock_data_count,
5213 char *lock_data,
5214 uint16_t flags2,
5215 unsigned int max_data_bytes,
5216 size_t *fixed_portion,
5217 char **ppdata,
5218 unsigned int *pdata_size)
5220 char *pdata = *ppdata;
5221 char *dstart, *dend;
5222 unsigned int data_size;
5223 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5224 time_t create_time, mtime, atime, c_time;
5225 SMB_STRUCT_STAT *psbuf = NULL;
5226 char *p;
5227 char *base_name;
5228 char *dos_fname;
5229 int mode;
5230 int nlink;
5231 NTSTATUS status;
5232 uint64_t file_size = 0;
5233 uint64_t pos = 0;
5234 uint64_t allocation_size = 0;
5235 uint64_t file_id = 0;
5236 uint32_t access_mask = 0;
5237 size_t len = 0;
5239 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5240 return NT_STATUS_INVALID_LEVEL;
5243 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5244 smb_fname_str_dbg(smb_fname),
5245 fsp_fnum_dbg(fsp),
5246 info_level, max_data_bytes));
5249 * In case of querying a symlink in POSIX context,
5250 * fsp will be NULL. fdos_mode() deals with it.
5252 if (fsp != NULL) {
5253 smb_fname = fsp->fsp_name;
5255 mode = fdos_mode(fsp);
5256 psbuf = &smb_fname->st;
5258 nlink = psbuf->st_ex_nlink;
5260 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5261 nlink = 1;
5264 if ((nlink > 0) && delete_pending) {
5265 nlink -= 1;
5268 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5269 return NT_STATUS_INVALID_PARAMETER;
5272 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5273 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5274 if (*ppdata == NULL) {
5275 return NT_STATUS_NO_MEMORY;
5277 pdata = *ppdata;
5278 dstart = pdata;
5279 dend = dstart + data_size - 1;
5281 if (!is_omit_timespec(&write_time_ts) &&
5282 !INFO_LEVEL_IS_UNIX(info_level))
5284 update_stat_ex_mtime(psbuf, write_time_ts);
5287 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5288 mtime_ts = psbuf->st_ex_mtime;
5289 atime_ts = psbuf->st_ex_atime;
5290 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5292 if (lp_dos_filetime_resolution(SNUM(conn))) {
5293 dos_filetime_timespec(&create_time_ts);
5294 dos_filetime_timespec(&mtime_ts);
5295 dos_filetime_timespec(&atime_ts);
5296 dos_filetime_timespec(&ctime_ts);
5299 create_time = convert_timespec_to_time_t(create_time_ts);
5300 mtime = convert_timespec_to_time_t(mtime_ts);
5301 atime = convert_timespec_to_time_t(atime_ts);
5302 c_time = convert_timespec_to_time_t(ctime_ts);
5304 p = strrchr_m(smb_fname->base_name,'/');
5305 if (!p)
5306 base_name = smb_fname->base_name;
5307 else
5308 base_name = p+1;
5310 /* NT expects the name to be in an exact form of the *full*
5311 filename. See the trans2 torture test */
5312 if (ISDOT(base_name)) {
5313 dos_fname = talloc_strdup(mem_ctx, "\\");
5314 if (!dos_fname) {
5315 return NT_STATUS_NO_MEMORY;
5317 } else {
5318 dos_fname = talloc_asprintf(mem_ctx,
5319 "\\%s",
5320 smb_fname->base_name);
5321 if (!dos_fname) {
5322 return NT_STATUS_NO_MEMORY;
5324 if (is_ntfs_stream_smb_fname(smb_fname)) {
5325 dos_fname = talloc_asprintf(dos_fname, "%s",
5326 smb_fname->stream_name);
5327 if (!dos_fname) {
5328 return NT_STATUS_NO_MEMORY;
5332 string_replace(dos_fname, '/', '\\');
5335 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5337 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5338 /* Do we have this path open ? */
5339 files_struct *fsp1;
5340 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5341 fsp1 = file_find_di_first(conn->sconn, fileid, true);
5342 if (fsp1 && fsp1->initial_allocation_size) {
5343 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5347 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5348 file_size = get_file_size_stat(psbuf);
5351 if (fsp) {
5352 pos = fh_get_position_information(fsp->fh);
5355 if (fsp) {
5356 access_mask = fsp->access_mask;
5357 } else {
5358 /* GENERIC_EXECUTE mapping from Windows */
5359 access_mask = 0x12019F;
5362 /* This should be an index number - looks like
5363 dev/ino to me :-)
5365 I think this causes us to fail the IFSKIT
5366 BasicFileInformationTest. -tpot */
5367 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5369 *fixed_portion = 0;
5371 switch (info_level) {
5372 case SMB_INFO_STANDARD:
5373 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5374 data_size = 22;
5375 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5376 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5377 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5378 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5379 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5380 SSVAL(pdata,l1_attrFile,mode);
5381 break;
5383 case SMB_INFO_QUERY_EA_SIZE:
5385 unsigned int ea_size =
5386 estimate_ea_size(smb_fname->fsp);
5387 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5388 data_size = 26;
5389 srv_put_dos_date2(pdata,0,create_time);
5390 srv_put_dos_date2(pdata,4,atime);
5391 srv_put_dos_date2(pdata,8,mtime); /* write time */
5392 SIVAL(pdata,12,(uint32_t)file_size);
5393 SIVAL(pdata,16,(uint32_t)allocation_size);
5394 SSVAL(pdata,20,mode);
5395 SIVAL(pdata,22,ea_size);
5396 break;
5399 case SMB_INFO_IS_NAME_VALID:
5400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5401 if (fsp) {
5402 /* os/2 needs this ? really ?*/
5403 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5405 /* This is only reached for qpathinfo */
5406 data_size = 0;
5407 break;
5409 case SMB_INFO_QUERY_EAS_FROM_LIST:
5411 size_t total_ea_len = 0;
5412 struct ea_list *ea_file_list = NULL;
5413 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5415 status =
5416 get_ea_list_from_fsp(mem_ctx,
5417 smb_fname->fsp,
5418 &total_ea_len, &ea_file_list);
5419 if (!NT_STATUS_IS_OK(status)) {
5420 return status;
5423 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5425 if (!ea_list || (total_ea_len > data_size)) {
5426 data_size = 4;
5427 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5428 break;
5431 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5432 break;
5435 case SMB_INFO_QUERY_ALL_EAS:
5437 /* We have data_size bytes to put EA's into. */
5438 size_t total_ea_len = 0;
5439 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5441 status = get_ea_list_from_fsp(mem_ctx,
5442 smb_fname->fsp,
5443 &total_ea_len, &ea_list);
5444 if (!NT_STATUS_IS_OK(status)) {
5445 return status;
5448 if (!ea_list || (total_ea_len > data_size)) {
5449 data_size = 4;
5450 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5451 break;
5454 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5455 break;
5458 case SMB2_FILE_FULL_EA_INFORMATION:
5460 /* We have data_size bytes to put EA's into. */
5461 size_t total_ea_len = 0;
5462 struct ea_list *ea_file_list = NULL;
5464 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5466 /*TODO: add filtering and index handling */
5468 status =
5469 get_ea_list_from_fsp(mem_ctx,
5470 smb_fname->fsp,
5471 &total_ea_len, &ea_file_list);
5472 if (!NT_STATUS_IS_OK(status)) {
5473 return status;
5475 if (!ea_file_list) {
5476 return NT_STATUS_NO_EAS_ON_FILE;
5479 status = fill_ea_chained_buffer(mem_ctx,
5480 pdata,
5481 data_size,
5482 &data_size,
5483 conn, ea_file_list);
5484 if (!NT_STATUS_IS_OK(status)) {
5485 return status;
5487 break;
5490 case SMB_FILE_BASIC_INFORMATION:
5491 case SMB_QUERY_FILE_BASIC_INFO:
5493 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5494 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5495 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5496 } else {
5497 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5498 data_size = 40;
5499 SIVAL(pdata,36,0);
5501 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5502 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5503 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5504 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5505 SIVAL(pdata,32,mode);
5507 DEBUG(5,("SMB_QFBI - "));
5508 DEBUG(5,("create: %s ", ctime(&create_time)));
5509 DEBUG(5,("access: %s ", ctime(&atime)));
5510 DEBUG(5,("write: %s ", ctime(&mtime)));
5511 DEBUG(5,("change: %s ", ctime(&c_time)));
5512 DEBUG(5,("mode: %x\n", mode));
5513 *fixed_portion = data_size;
5514 break;
5516 case SMB_FILE_STANDARD_INFORMATION:
5517 case SMB_QUERY_FILE_STANDARD_INFO:
5519 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5520 data_size = 24;
5521 SOFF_T(pdata,0,allocation_size);
5522 SOFF_T(pdata,8,file_size);
5523 SIVAL(pdata,16,nlink);
5524 SCVAL(pdata,20,delete_pending?1:0);
5525 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5526 SSVAL(pdata,22,0); /* Padding. */
5527 *fixed_portion = 24;
5528 break;
5530 case SMB_FILE_EA_INFORMATION:
5531 case SMB_QUERY_FILE_EA_INFO:
5533 unsigned int ea_size =
5534 estimate_ea_size(smb_fname->fsp);
5535 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5536 data_size = 4;
5537 *fixed_portion = 4;
5538 SIVAL(pdata,0,ea_size);
5539 break;
5542 /* Get the 8.3 name - used if NT SMB was negotiated. */
5543 case SMB_QUERY_FILE_ALT_NAME_INFO:
5544 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5546 char mangled_name[13];
5547 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5548 if (!name_to_8_3(base_name,mangled_name,
5549 True,conn->params)) {
5550 return NT_STATUS_NO_MEMORY;
5552 status = srvstr_push(dstart, flags2,
5553 pdata+4, mangled_name,
5554 PTR_DIFF(dend, pdata+4),
5555 STR_UNICODE, &len);
5556 if (!NT_STATUS_IS_OK(status)) {
5557 return status;
5559 data_size = 4 + len;
5560 SIVAL(pdata,0,len);
5561 *fixed_portion = 8;
5562 break;
5565 case SMB_QUERY_FILE_NAME_INFO:
5568 this must be *exactly* right for ACLs on mapped drives to work
5570 status = srvstr_push(dstart, flags2,
5571 pdata+4, dos_fname,
5572 PTR_DIFF(dend, pdata+4),
5573 STR_UNICODE, &len);
5574 if (!NT_STATUS_IS_OK(status)) {
5575 return status;
5577 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5578 data_size = 4 + len;
5579 SIVAL(pdata,0,len);
5580 break;
5583 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5585 char *nfname = NULL;
5587 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5588 return NT_STATUS_INVALID_LEVEL;
5591 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5592 if (nfname == NULL) {
5593 return NT_STATUS_NO_MEMORY;
5596 if (ISDOT(nfname)) {
5597 nfname[0] = '\0';
5599 string_replace(nfname, '/', '\\');
5601 if (smb_fname->stream_name != NULL) {
5602 const char *s = smb_fname->stream_name;
5603 const char *e = NULL;
5604 size_t n;
5606 SMB_ASSERT(s[0] != '\0');
5609 * smb_fname->stream_name is in form
5610 * of ':StrEam:$DATA', but we should only
5611 * append ':StrEam' here.
5614 e = strchr(&s[1], ':');
5615 if (e == NULL) {
5616 n = strlen(s);
5617 } else {
5618 n = PTR_DIFF(e, s);
5620 nfname = talloc_strndup_append(nfname, s, n);
5621 if (nfname == NULL) {
5622 return NT_STATUS_NO_MEMORY;
5626 status = srvstr_push(dstart, flags2,
5627 pdata+4, nfname,
5628 PTR_DIFF(dend, pdata+4),
5629 STR_UNICODE, &len);
5630 if (!NT_STATUS_IS_OK(status)) {
5631 return status;
5633 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5634 data_size = 4 + len;
5635 SIVAL(pdata,0,len);
5636 *fixed_portion = 8;
5637 break;
5640 case SMB_FILE_ALLOCATION_INFORMATION:
5641 case SMB_QUERY_FILE_ALLOCATION_INFO:
5642 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5643 data_size = 8;
5644 SOFF_T(pdata,0,allocation_size);
5645 break;
5647 case SMB_FILE_END_OF_FILE_INFORMATION:
5648 case SMB_QUERY_FILE_END_OF_FILEINFO:
5649 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5650 data_size = 8;
5651 SOFF_T(pdata,0,file_size);
5652 break;
5654 case SMB_QUERY_FILE_ALL_INFO:
5655 case SMB_FILE_ALL_INFORMATION:
5657 unsigned int ea_size =
5658 estimate_ea_size(smb_fname->fsp);
5659 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5660 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5661 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5662 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5663 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5664 SIVAL(pdata,32,mode);
5665 SIVAL(pdata,36,0); /* padding. */
5666 pdata += 40;
5667 SOFF_T(pdata,0,allocation_size);
5668 SOFF_T(pdata,8,file_size);
5669 SIVAL(pdata,16,nlink);
5670 SCVAL(pdata,20,delete_pending);
5671 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5672 SSVAL(pdata,22,0);
5673 pdata += 24;
5674 SIVAL(pdata,0,ea_size);
5675 pdata += 4; /* EA info */
5676 status = srvstr_push(dstart, flags2,
5677 pdata+4, dos_fname,
5678 PTR_DIFF(dend, pdata+4),
5679 STR_UNICODE, &len);
5680 if (!NT_STATUS_IS_OK(status)) {
5681 return status;
5683 SIVAL(pdata,0,len);
5684 pdata += 4 + len;
5685 data_size = PTR_DIFF(pdata,(*ppdata));
5686 *fixed_portion = 10;
5687 break;
5690 case SMB2_FILE_ALL_INFORMATION:
5692 unsigned int ea_size =
5693 estimate_ea_size(smb_fname->fsp);
5694 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5695 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5696 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5697 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5698 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5699 SIVAL(pdata, 0x20, mode);
5700 SIVAL(pdata, 0x24, 0); /* padding. */
5701 SBVAL(pdata, 0x28, allocation_size);
5702 SBVAL(pdata, 0x30, file_size);
5703 SIVAL(pdata, 0x38, nlink);
5704 SCVAL(pdata, 0x3C, delete_pending);
5705 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5706 SSVAL(pdata, 0x3E, 0); /* padding */
5707 SBVAL(pdata, 0x40, file_id);
5708 SIVAL(pdata, 0x48, ea_size);
5709 SIVAL(pdata, 0x4C, access_mask);
5710 SBVAL(pdata, 0x50, pos);
5711 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5712 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5714 pdata += 0x60;
5716 status = srvstr_push(dstart, flags2,
5717 pdata+4, dos_fname,
5718 PTR_DIFF(dend, pdata+4),
5719 STR_UNICODE, &len);
5720 if (!NT_STATUS_IS_OK(status)) {
5721 return status;
5723 SIVAL(pdata,0,len);
5724 pdata += 4 + len;
5725 data_size = PTR_DIFF(pdata,(*ppdata));
5726 *fixed_portion = 104;
5727 break;
5729 case SMB_FILE_INTERNAL_INFORMATION:
5731 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5732 SBVAL(pdata, 0, file_id);
5733 data_size = 8;
5734 *fixed_portion = 8;
5735 break;
5737 case SMB_FILE_ACCESS_INFORMATION:
5738 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5739 SIVAL(pdata, 0, access_mask);
5740 data_size = 4;
5741 *fixed_portion = 4;
5742 break;
5744 case SMB_FILE_NAME_INFORMATION:
5745 /* Pathname with leading '\'. */
5747 size_t byte_len;
5748 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5749 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5750 SIVAL(pdata,0,byte_len);
5751 data_size = 4 + byte_len;
5752 break;
5755 case SMB_FILE_DISPOSITION_INFORMATION:
5756 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5757 data_size = 1;
5758 SCVAL(pdata,0,delete_pending);
5759 *fixed_portion = 1;
5760 break;
5762 case SMB_FILE_POSITION_INFORMATION:
5763 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5764 data_size = 8;
5765 SOFF_T(pdata,0,pos);
5766 *fixed_portion = 8;
5767 break;
5769 case SMB_FILE_MODE_INFORMATION:
5770 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5771 SIVAL(pdata,0,mode);
5772 data_size = 4;
5773 *fixed_portion = 4;
5774 break;
5776 case SMB_FILE_ALIGNMENT_INFORMATION:
5777 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5778 SIVAL(pdata,0,0); /* No alignment needed. */
5779 data_size = 4;
5780 *fixed_portion = 4;
5781 break;
5784 * NT4 server just returns "invalid query" to this - if we try
5785 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5786 * want this. JRA.
5788 /* The first statement above is false - verified using Thursby
5789 * client against NT4 -- gcolley.
5791 case SMB_QUERY_FILE_STREAM_INFO:
5792 case SMB_FILE_STREAM_INFORMATION: {
5793 unsigned int num_streams = 0;
5794 struct stream_struct *streams = NULL;
5796 DEBUG(10,("smbd_do_qfilepathinfo: "
5797 "SMB_FILE_STREAM_INFORMATION\n"));
5799 if (is_ntfs_stream_smb_fname(smb_fname)) {
5800 return NT_STATUS_INVALID_PARAMETER;
5803 status = vfs_streaminfo(conn,
5804 fsp,
5805 smb_fname,
5806 talloc_tos(),
5807 &num_streams,
5808 &streams);
5810 if (!NT_STATUS_IS_OK(status)) {
5811 DEBUG(10, ("could not get stream info: %s\n",
5812 nt_errstr(status)));
5813 return status;
5816 status = marshall_stream_info(num_streams, streams,
5817 pdata, max_data_bytes,
5818 &data_size);
5820 if (!NT_STATUS_IS_OK(status)) {
5821 DEBUG(10, ("marshall_stream_info failed: %s\n",
5822 nt_errstr(status)));
5823 TALLOC_FREE(streams);
5824 return status;
5827 TALLOC_FREE(streams);
5829 *fixed_portion = 32;
5831 break;
5833 case SMB_QUERY_COMPRESSION_INFO:
5834 case SMB_FILE_COMPRESSION_INFORMATION:
5835 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5836 SOFF_T(pdata,0,file_size);
5837 SIVAL(pdata,8,0); /* ??? */
5838 SIVAL(pdata,12,0); /* ??? */
5839 data_size = 16;
5840 *fixed_portion = 16;
5841 break;
5843 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5844 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5845 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5846 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5847 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5848 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5849 SOFF_T(pdata,32,allocation_size);
5850 SOFF_T(pdata,40,file_size);
5851 SIVAL(pdata,48,mode);
5852 SIVAL(pdata,52,0); /* ??? */
5853 data_size = 56;
5854 *fixed_portion = 56;
5855 break;
5857 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5858 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5859 SIVAL(pdata,0,mode);
5860 SIVAL(pdata,4,0);
5861 data_size = 8;
5862 *fixed_portion = 8;
5863 break;
5866 * CIFS UNIX Extensions.
5869 case SMB_QUERY_FILE_UNIX_BASIC:
5871 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5872 data_size = PTR_DIFF(pdata,(*ppdata));
5874 DEBUG(4,("smbd_do_qfilepathinfo: "
5875 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5876 dump_data(4, (uint8_t *)(*ppdata), data_size);
5878 break;
5880 case SMB_QUERY_FILE_UNIX_INFO2:
5882 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5883 data_size = PTR_DIFF(pdata,(*ppdata));
5886 int i;
5887 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5889 for (i=0; i<100; i++)
5890 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5891 DEBUG(4,("\n"));
5894 break;
5896 case SMB_QUERY_FILE_UNIX_LINK:
5898 status = smb_unix_read_symlink(conn,
5899 req,
5900 smb_fname,
5901 pdata,
5902 data_size,
5903 &data_size);
5904 if (!NT_STATUS_IS_OK(status)) {
5905 return status;
5907 break;
5910 #if defined(HAVE_POSIX_ACLS)
5911 case SMB_QUERY_POSIX_ACL:
5913 status = smb_query_posix_acl(conn,
5914 req,
5915 fsp,
5916 smb_fname,
5917 pdata,
5918 data_size,
5919 &data_size);
5920 if (!NT_STATUS_IS_OK(status)) {
5921 return status;
5923 break;
5925 #endif
5928 case SMB_QUERY_POSIX_LOCK:
5930 uint64_t count;
5931 uint64_t offset;
5932 uint64_t smblctx;
5933 enum brl_type lock_type;
5935 /* We need an open file with a real fd for this. */
5936 if (fsp == NULL ||
5937 fsp->fsp_flags.is_pathref ||
5938 fsp_get_io_fd(fsp) == -1)
5940 return NT_STATUS_INVALID_LEVEL;
5943 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5944 return NT_STATUS_INVALID_PARAMETER;
5947 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5948 case POSIX_LOCK_TYPE_READ:
5949 lock_type = READ_LOCK;
5950 break;
5951 case POSIX_LOCK_TYPE_WRITE:
5952 lock_type = WRITE_LOCK;
5953 break;
5954 case POSIX_LOCK_TYPE_UNLOCK:
5955 default:
5956 /* There's no point in asking for an unlock... */
5957 return NT_STATUS_INVALID_PARAMETER;
5960 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5961 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5962 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5964 status = query_lock(fsp,
5965 &smblctx,
5966 &count,
5967 &offset,
5968 &lock_type,
5969 POSIX_LOCK);
5971 if (ERROR_WAS_LOCK_DENIED(status)) {
5972 /* Here we need to report who has it locked... */
5973 data_size = POSIX_LOCK_DATA_SIZE;
5975 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5976 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5977 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5978 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5979 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5981 } else if (NT_STATUS_IS_OK(status)) {
5982 /* For success we just return a copy of what we sent
5983 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5984 data_size = POSIX_LOCK_DATA_SIZE;
5985 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5986 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5987 } else {
5988 return status;
5990 break;
5993 default:
5994 return NT_STATUS_INVALID_LEVEL;
5997 *pdata_size = data_size;
5998 return NT_STATUS_OK;
6001 /****************************************************************************
6002 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6003 file name or file id).
6004 ****************************************************************************/
6006 static void call_trans2qfilepathinfo(connection_struct *conn,
6007 struct smb_request *req,
6008 unsigned int tran_call,
6009 char **pparams, int total_params,
6010 char **ppdata, int total_data,
6011 unsigned int max_data_bytes)
6013 char *params = *pparams;
6014 char *pdata = *ppdata;
6015 uint16_t info_level;
6016 unsigned int data_size = 0;
6017 unsigned int param_size = 2;
6018 struct smb_filename *smb_fname = NULL;
6019 bool delete_pending = False;
6020 struct timespec write_time_ts;
6021 files_struct *fsp = NULL;
6022 struct file_id fileid;
6023 struct ea_list *ea_list = NULL;
6024 int lock_data_count = 0;
6025 char *lock_data = NULL;
6026 size_t fixed_portion;
6027 NTSTATUS status = NT_STATUS_OK;
6029 if (!params) {
6030 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6031 return;
6034 ZERO_STRUCT(write_time_ts);
6036 if (tran_call == TRANSACT2_QFILEINFO) {
6037 if (total_params < 4) {
6038 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6039 return;
6042 if (IS_IPC(conn)) {
6043 call_trans2qpipeinfo(conn, req, tran_call,
6044 pparams, total_params,
6045 ppdata, total_data,
6046 max_data_bytes);
6047 return;
6050 fsp = file_fsp(req, SVAL(params,0));
6051 info_level = SVAL(params,2);
6053 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6055 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6056 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6057 return;
6060 /* Initial check for valid fsp ptr. */
6061 if (!check_fsp_open(conn, req, fsp)) {
6062 return;
6065 smb_fname = fsp->fsp_name;
6067 if(fsp->fake_file_handle) {
6069 * This is actually for the QUOTA_FAKE_FILE --metze
6072 /* We know this name is ok, it's already passed the checks. */
6074 } else if(fsp_get_pathref_fd(fsp) == -1) {
6076 * This is actually a QFILEINFO on a directory
6077 * handle (returned from an NT SMB). NT5.0 seems
6078 * to do this call. JRA.
6081 if (INFO_LEVEL_IS_UNIX(info_level)) {
6082 /* Always do lstat for UNIX calls. */
6083 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6084 DEBUG(3,("call_trans2qfilepathinfo: "
6085 "SMB_VFS_LSTAT of %s failed "
6086 "(%s)\n",
6087 smb_fname_str_dbg(smb_fname),
6088 strerror(errno)));
6089 reply_nterror(req,
6090 map_nt_error_from_unix(errno));
6091 return;
6093 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6094 DEBUG(3,("call_trans2qfilepathinfo: "
6095 "SMB_VFS_STAT of %s failed (%s)\n",
6096 smb_fname_str_dbg(smb_fname),
6097 strerror(errno)));
6098 reply_nterror(req,
6099 map_nt_error_from_unix(errno));
6100 return;
6103 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6104 fileid = vfs_file_id_from_sbuf(
6105 conn, &smb_fname->st);
6106 get_file_infos(fileid, fsp->name_hash,
6107 &delete_pending,
6108 &write_time_ts);
6110 } else {
6112 * Original code - this is an open file.
6114 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6115 DEBUG(3, ("fstat of %s failed (%s)\n",
6116 fsp_fnum_dbg(fsp), strerror(errno)));
6117 reply_nterror(req,
6118 map_nt_error_from_unix(errno));
6119 return;
6121 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6122 fileid = vfs_file_id_from_sbuf(
6123 conn, &smb_fname->st);
6124 get_file_infos(fileid, fsp->name_hash,
6125 &delete_pending,
6126 &write_time_ts);
6130 } else {
6131 uint32_t name_hash;
6132 char *fname = NULL;
6133 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6135 /* qpathinfo */
6136 if (total_params < 7) {
6137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6138 return;
6141 info_level = SVAL(params,0);
6143 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6145 if (INFO_LEVEL_IS_UNIX(info_level)) {
6146 if (!lp_unix_extensions()) {
6147 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6148 return;
6152 if (req->posix_pathnames) {
6153 srvstr_get_path_posix(req,
6154 params,
6155 req->flags2,
6156 &fname,
6157 &params[6],
6158 total_params - 6,
6159 STR_TERMINATE,
6160 &status);
6161 } else {
6162 srvstr_get_path(req,
6163 params,
6164 req->flags2,
6165 &fname,
6166 &params[6],
6167 total_params - 6,
6168 STR_TERMINATE,
6169 &status);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 reply_nterror(req, status);
6173 return;
6176 status = filename_convert(req,
6177 conn,
6178 fname,
6179 ucf_flags,
6181 &smb_fname);
6182 if (!NT_STATUS_IS_OK(status)) {
6183 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6184 reply_botherror(req,
6185 NT_STATUS_PATH_NOT_COVERED,
6186 ERRSRV, ERRbadpath);
6187 return;
6189 reply_nterror(req, status);
6190 return;
6194 * smb_fname->fsp may be NULL if smb_fname points at a symlink
6195 * and we're in POSIX context, so be careful when using fsp
6196 * below, it can still be NULL.
6198 fsp = smb_fname->fsp;
6200 /* If this is a stream, check if there is a delete_pending. */
6201 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6202 && is_ntfs_stream_smb_fname(smb_fname)) {
6203 struct smb_filename *smb_fname_base;
6205 /* Create an smb_filename with stream_name == NULL. */
6206 smb_fname_base = synthetic_smb_fname(
6207 talloc_tos(),
6208 smb_fname->base_name,
6209 NULL,
6210 NULL,
6211 smb_fname->twrp,
6212 smb_fname->flags);
6213 if (smb_fname_base == NULL) {
6214 reply_nterror(req, NT_STATUS_NO_MEMORY);
6215 return;
6218 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6219 /* Always do lstat for UNIX calls. */
6220 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6221 DEBUG(3,("call_trans2qfilepathinfo: "
6222 "SMB_VFS_LSTAT of %s failed "
6223 "(%s)\n",
6224 smb_fname_str_dbg(smb_fname_base),
6225 strerror(errno)));
6226 TALLOC_FREE(smb_fname_base);
6227 reply_nterror(req,
6228 map_nt_error_from_unix(errno));
6229 return;
6231 } else {
6232 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6233 DEBUG(3,("call_trans2qfilepathinfo: "
6234 "fileinfo of %s failed "
6235 "(%s)\n",
6236 smb_fname_str_dbg(smb_fname_base),
6237 strerror(errno)));
6238 TALLOC_FREE(smb_fname_base);
6239 reply_nterror(req,
6240 map_nt_error_from_unix(errno));
6241 return;
6245 status = file_name_hash(conn,
6246 smb_fname_str_dbg(smb_fname_base),
6247 &name_hash);
6248 if (!NT_STATUS_IS_OK(status)) {
6249 TALLOC_FREE(smb_fname_base);
6250 reply_nterror(req, status);
6251 return;
6254 fileid = vfs_file_id_from_sbuf(conn,
6255 &smb_fname_base->st);
6256 TALLOC_FREE(smb_fname_base);
6257 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6258 if (delete_pending) {
6259 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6260 return;
6264 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6265 /* Always do lstat for UNIX calls. */
6266 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6267 DEBUG(3,("call_trans2qfilepathinfo: "
6268 "SMB_VFS_LSTAT of %s failed (%s)\n",
6269 smb_fname_str_dbg(smb_fname),
6270 strerror(errno)));
6271 reply_nterror(req,
6272 map_nt_error_from_unix(errno));
6273 return;
6276 } else {
6277 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6278 DEBUG(3,("call_trans2qfilepathinfo: "
6279 "SMB_VFS_STAT of %s failed (%s)\n",
6280 smb_fname_str_dbg(smb_fname),
6281 strerror(errno)));
6282 reply_nterror(req,
6283 map_nt_error_from_unix(errno));
6284 return;
6288 status = file_name_hash(conn,
6289 smb_fname_str_dbg(smb_fname),
6290 &name_hash);
6291 if (!NT_STATUS_IS_OK(status)) {
6292 reply_nterror(req, status);
6293 return;
6296 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6297 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6298 get_file_infos(fileid, name_hash, &delete_pending,
6299 &write_time_ts);
6302 if (delete_pending) {
6303 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6304 return;
6308 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6309 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6310 fsp_fnum_dbg(fsp),
6311 info_level,tran_call,total_data));
6313 /* Pull out any data sent here before we realloc. */
6314 switch (info_level) {
6315 case SMB_INFO_QUERY_EAS_FROM_LIST:
6317 /* Pull any EA list from the data portion. */
6318 uint32_t ea_size;
6320 if (total_data < 4) {
6321 reply_nterror(
6322 req, NT_STATUS_INVALID_PARAMETER);
6323 return;
6325 ea_size = IVAL(pdata,0);
6327 if (total_data > 0 && ea_size != total_data) {
6328 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6329 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6330 reply_nterror(
6331 req, NT_STATUS_INVALID_PARAMETER);
6332 return;
6335 if (!lp_ea_support(SNUM(conn))) {
6336 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6337 return;
6340 /* Pull out the list of names. */
6341 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6342 if (!ea_list) {
6343 reply_nterror(
6344 req, NT_STATUS_INVALID_PARAMETER);
6345 return;
6347 break;
6350 case SMB_QUERY_POSIX_LOCK:
6352 if (fsp == NULL ||
6353 fsp->fsp_flags.is_pathref ||
6354 fsp_get_io_fd(fsp) == -1)
6356 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6357 return;
6360 if (total_data != POSIX_LOCK_DATA_SIZE) {
6361 reply_nterror(
6362 req, NT_STATUS_INVALID_PARAMETER);
6363 return;
6366 /* Copy the lock range data. */
6367 lock_data = (char *)talloc_memdup(
6368 req, pdata, total_data);
6369 if (!lock_data) {
6370 reply_nterror(req, NT_STATUS_NO_MEMORY);
6371 return;
6373 lock_data_count = total_data;
6374 break;
6376 default:
6377 break;
6380 *pparams = (char *)SMB_REALLOC(*pparams,2);
6381 if (*pparams == NULL) {
6382 reply_nterror(req, NT_STATUS_NO_MEMORY);
6383 return;
6385 params = *pparams;
6386 SSVAL(params,0,0);
6389 * draft-leach-cifs-v1-spec-02.txt
6390 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6391 * says:
6393 * The requested information is placed in the Data portion of the
6394 * transaction response. For the information levels greater than 0x100,
6395 * the transaction response has 1 parameter word which should be
6396 * ignored by the client.
6398 * However Windows only follows this rule for the IS_NAME_VALID call.
6400 switch (info_level) {
6401 case SMB_INFO_IS_NAME_VALID:
6402 param_size = 0;
6403 break;
6406 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
6408 * We use levels that start with 0xFF00
6409 * internally to represent SMB2 specific levels
6411 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6412 return;
6415 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6416 fsp, smb_fname,
6417 delete_pending, write_time_ts,
6418 ea_list,
6419 lock_data_count, lock_data,
6420 req->flags2, max_data_bytes,
6421 &fixed_portion,
6422 ppdata, &data_size);
6423 if (!NT_STATUS_IS_OK(status)) {
6424 if (open_was_deferred(req->xconn, req->mid)) {
6425 /* We have re-scheduled this call. */
6426 return;
6428 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6429 bool ok = defer_smb1_sharing_violation(req);
6430 if (ok) {
6431 return;
6434 reply_nterror(req, status);
6435 return;
6437 if (fixed_portion > max_data_bytes) {
6438 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6439 return;
6442 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6443 max_data_bytes);
6445 return;
6448 /****************************************************************************
6449 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6450 code.
6451 ****************************************************************************/
6453 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6454 connection_struct *conn,
6455 struct smb_request *req,
6456 bool overwrite_if_exists,
6457 const struct smb_filename *smb_fname_old,
6458 struct smb_filename *smb_fname_new)
6460 NTSTATUS status = NT_STATUS_OK;
6461 int ret;
6462 bool ok;
6463 struct smb_filename *parent_fname_old = NULL;
6464 struct smb_filename *base_name_old = NULL;
6465 struct smb_filename *parent_fname_new = NULL;
6466 struct smb_filename *base_name_new = NULL;
6468 /* source must already exist. */
6469 if (!VALID_STAT(smb_fname_old->st)) {
6470 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6471 goto out;
6474 /* No links from a directory. */
6475 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6476 status = NT_STATUS_FILE_IS_A_DIRECTORY;
6477 goto out;
6480 /* Setting a hardlink to/from a stream isn't currently supported. */
6481 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6482 if (ok) {
6483 DBG_DEBUG("Old name has streams\n");
6484 status = NT_STATUS_INVALID_PARAMETER;
6485 goto out;
6487 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6488 if (ok) {
6489 DBG_DEBUG("New name has streams\n");
6490 status = NT_STATUS_INVALID_PARAMETER;
6491 goto out;
6494 status = parent_pathref(talloc_tos(),
6495 conn->cwd_fsp,
6496 smb_fname_old,
6497 &parent_fname_old,
6498 &base_name_old);
6499 if (!NT_STATUS_IS_OK(status)) {
6500 goto out;
6503 status = parent_pathref(talloc_tos(),
6504 conn->cwd_fsp,
6505 smb_fname_new,
6506 &parent_fname_new,
6507 &base_name_new);
6508 if (!NT_STATUS_IS_OK(status)) {
6509 goto out;
6512 if (VALID_STAT(smb_fname_new->st)) {
6513 if (overwrite_if_exists) {
6514 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6515 status = NT_STATUS_FILE_IS_A_DIRECTORY;
6516 goto out;
6518 status = unlink_internals(conn,
6519 req,
6520 FILE_ATTRIBUTE_NORMAL,
6521 smb_fname_new,
6522 false);
6523 if (!NT_STATUS_IS_OK(status)) {
6524 goto out;
6526 } else {
6527 /* Disallow if newname already exists. */
6528 status = NT_STATUS_OBJECT_NAME_COLLISION;
6529 goto out;
6533 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6534 smb_fname_old->base_name, smb_fname_new->base_name));
6536 ret = SMB_VFS_LINKAT(conn,
6537 parent_fname_old->fsp,
6538 base_name_old,
6539 parent_fname_new->fsp,
6540 base_name_new,
6543 if (ret != 0) {
6544 status = map_nt_error_from_unix(errno);
6545 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6546 nt_errstr(status), smb_fname_old->base_name,
6547 smb_fname_new->base_name));
6550 out:
6552 TALLOC_FREE(parent_fname_old);
6553 TALLOC_FREE(parent_fname_new);
6554 return status;
6557 /****************************************************************************
6558 Deal with setting the time from any of the setfilepathinfo functions.
6559 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6560 calling this function.
6561 ****************************************************************************/
6563 NTSTATUS smb_set_file_time(connection_struct *conn,
6564 files_struct *fsp,
6565 struct smb_filename *smb_fname,
6566 struct smb_file_time *ft,
6567 bool setting_write_time)
6569 struct files_struct *set_fsp = NULL;
6570 struct timeval_buf tbuf[4];
6571 uint32_t action =
6572 FILE_NOTIFY_CHANGE_LAST_ACCESS
6573 |FILE_NOTIFY_CHANGE_LAST_WRITE
6574 |FILE_NOTIFY_CHANGE_CREATION;
6575 int ret;
6577 if (!VALID_STAT(smb_fname->st)) {
6578 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6581 if (fsp == NULL) {
6582 /* A symlink */
6583 return NT_STATUS_OK;
6586 set_fsp = fsp->base_fsp == NULL ? fsp : fsp->base_fsp;
6588 /* get some defaults (no modifications) if any info is zero or -1. */
6589 if (is_omit_timespec(&ft->create_time)) {
6590 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6593 if (is_omit_timespec(&ft->atime)) {
6594 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6597 if (is_omit_timespec(&ft->mtime)) {
6598 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6601 if (!setting_write_time) {
6602 /* ft->mtime comes from change time, not write time. */
6603 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6606 /* Ensure the resolution is the correct for
6607 * what we can store on this filesystem. */
6609 round_timespec(conn->ts_res, &ft->create_time);
6610 round_timespec(conn->ts_res, &ft->ctime);
6611 round_timespec(conn->ts_res, &ft->atime);
6612 round_timespec(conn->ts_res, &ft->mtime);
6614 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6615 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6616 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6617 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6618 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6619 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6620 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6621 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6623 if (setting_write_time) {
6625 * This was a Windows setfileinfo on an open file.
6626 * NT does this a lot. We also need to
6627 * set the time here, as it can be read by
6628 * FindFirst/FindNext and with the patch for bug #2045
6629 * in smbd/fileio.c it ensures that this timestamp is
6630 * kept sticky even after a write. We save the request
6631 * away and will set it on file close and after a write. JRA.
6634 DBG_DEBUG("setting pending modtime to %s\n",
6635 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6637 if (set_fsp != NULL) {
6638 set_sticky_write_time_fsp(set_fsp, ft->mtime);
6639 } else {
6640 set_sticky_write_time_path(
6641 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6642 ft->mtime);
6646 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6648 ret = file_ntimes(conn, set_fsp->fsp_name, ft);
6649 if (ret != 0) {
6650 return map_nt_error_from_unix(errno);
6653 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6654 smb_fname->base_name);
6655 return NT_STATUS_OK;
6658 /****************************************************************************
6659 Deal with setting the dosmode from any of the setfilepathinfo functions.
6660 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6661 done before calling this function.
6662 ****************************************************************************/
6664 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6665 struct files_struct *fsp,
6666 struct smb_filename *smb_fname,
6667 uint32_t dosmode)
6669 struct smb_filename *smb_fname_base;
6670 NTSTATUS status;
6672 if (!VALID_STAT(smb_fname->st)) {
6673 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6676 /* Always operate on the base_name, even if a stream was passed in. */
6677 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6678 smb_fname->base_name,
6679 NULL,
6680 &smb_fname->st,
6681 smb_fname->twrp,
6682 smb_fname->flags);
6683 if (smb_fname_base == NULL) {
6684 return NT_STATUS_NO_MEMORY;
6687 if (dosmode) {
6688 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6689 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6690 } else {
6691 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6695 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6697 /* check the mode isn't different, before changing it */
6698 if ((dosmode != 0) && (dosmode != fdos_mode(fsp))) {
6699 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6700 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6701 (unsigned int)dosmode));
6703 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6704 false)) {
6705 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6706 "%s failed (%s)\n",
6707 smb_fname_str_dbg(smb_fname_base),
6708 strerror(errno)));
6709 status = map_nt_error_from_unix(errno);
6710 goto out;
6713 status = NT_STATUS_OK;
6714 out:
6715 TALLOC_FREE(smb_fname_base);
6716 return status;
6719 /****************************************************************************
6720 Deal with setting the size from any of the setfilepathinfo functions.
6721 ****************************************************************************/
6723 static NTSTATUS smb_set_file_size(connection_struct *conn,
6724 struct smb_request *req,
6725 files_struct *fsp,
6726 struct smb_filename *smb_fname,
6727 const SMB_STRUCT_STAT *psbuf,
6728 off_t size,
6729 bool fail_after_createfile)
6731 NTSTATUS status = NT_STATUS_OK;
6732 files_struct *new_fsp = NULL;
6734 if (!VALID_STAT(*psbuf)) {
6735 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6738 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6739 (uint64_t)size,
6740 get_file_size_stat(psbuf));
6742 if (size == get_file_size_stat(psbuf)) {
6743 if (fsp == NULL) {
6744 return NT_STATUS_OK;
6746 if (!fsp->fsp_flags.modified) {
6747 return NT_STATUS_OK;
6749 trigger_write_time_update_immediate(fsp);
6750 return NT_STATUS_OK;
6753 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6754 smb_fname_str_dbg(smb_fname), (double)size));
6756 if (fsp &&
6757 !fsp->fsp_flags.is_pathref &&
6758 fsp_get_io_fd(fsp) != -1)
6760 /* Handle based call. */
6761 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6762 return NT_STATUS_ACCESS_DENIED;
6765 if (vfs_set_filelen(fsp, size) == -1) {
6766 return map_nt_error_from_unix(errno);
6768 trigger_write_time_update_immediate(fsp);
6769 return NT_STATUS_OK;
6772 status = SMB_VFS_CREATE_FILE(
6773 conn, /* conn */
6774 req, /* req */
6775 smb_fname, /* fname */
6776 FILE_WRITE_DATA, /* access_mask */
6777 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6778 FILE_SHARE_DELETE),
6779 FILE_OPEN, /* create_disposition*/
6780 0, /* create_options */
6781 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6782 0, /* oplock_request */
6783 NULL, /* lease */
6784 0, /* allocation_size */
6785 0, /* private_flags */
6786 NULL, /* sd */
6787 NULL, /* ea_list */
6788 &new_fsp, /* result */
6789 NULL, /* pinfo */
6790 NULL, NULL); /* create context */
6792 if (!NT_STATUS_IS_OK(status)) {
6793 /* NB. We check for open_was_deferred in the caller. */
6794 return status;
6797 /* See RAW-SFILEINFO-END-OF-FILE */
6798 if (fail_after_createfile) {
6799 close_file(req, new_fsp,NORMAL_CLOSE);
6800 return NT_STATUS_INVALID_LEVEL;
6803 if (vfs_set_filelen(new_fsp, size) == -1) {
6804 status = map_nt_error_from_unix(errno);
6805 close_file(req, new_fsp,NORMAL_CLOSE);
6806 return status;
6809 trigger_write_time_update_immediate(new_fsp);
6810 close_file(req, new_fsp,NORMAL_CLOSE);
6811 return NT_STATUS_OK;
6814 /****************************************************************************
6815 Deal with SMB_INFO_SET_EA.
6816 ****************************************************************************/
6818 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6819 const char *pdata,
6820 int total_data,
6821 files_struct *fsp,
6822 struct smb_filename *smb_fname)
6824 struct ea_list *ea_list = NULL;
6825 TALLOC_CTX *ctx = NULL;
6826 NTSTATUS status = NT_STATUS_OK;
6828 if (total_data < 10) {
6830 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6831 length. They seem to have no effect. Bug #3212. JRA */
6833 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6834 /* We're done. We only get EA info in this call. */
6835 return NT_STATUS_OK;
6838 return NT_STATUS_INVALID_PARAMETER;
6841 if (IVAL(pdata,0) > total_data) {
6842 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6843 IVAL(pdata,0), (unsigned int)total_data));
6844 return NT_STATUS_INVALID_PARAMETER;
6847 ctx = talloc_tos();
6848 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6849 if (!ea_list) {
6850 return NT_STATUS_INVALID_PARAMETER;
6853 if (fsp == NULL) {
6855 * The only way fsp can be NULL here is if
6856 * smb_fname points at a symlink and
6857 * and we're in POSIX context.
6858 * Ensure this is the case.
6860 * There is still a race condition in that
6861 * the symlink could be changed after we
6862 * checked it, so ensure we only operate
6863 * EA setting on a file handle.
6865 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
6866 if (!(smb_fname->flags & SMB_FILENAME_POSIX_PATH)) {
6867 return NT_STATUS_ACCESS_DENIED;
6869 status = refuse_symlink(conn, NULL, smb_fname);
6870 SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED));
6871 return NT_STATUS_ACCESS_DENIED;
6874 status = set_ea(conn, fsp, ea_list);
6876 return status;
6879 /****************************************************************************
6880 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6881 ****************************************************************************/
6883 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6884 const char *pdata,
6885 int total_data,
6886 files_struct *fsp)
6888 struct ea_list *ea_list = NULL;
6889 NTSTATUS status;
6891 if (!fsp) {
6892 return NT_STATUS_INVALID_HANDLE;
6895 if (!lp_ea_support(SNUM(conn))) {
6896 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6897 "EA's not supported.\n",
6898 (unsigned int)total_data));
6899 return NT_STATUS_EAS_NOT_SUPPORTED;
6902 if (total_data < 10) {
6903 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6904 "too small.\n",
6905 (unsigned int)total_data));
6906 return NT_STATUS_INVALID_PARAMETER;
6909 ea_list = read_nttrans_ea_list(talloc_tos(),
6910 pdata,
6911 total_data);
6913 if (!ea_list) {
6914 return NT_STATUS_INVALID_PARAMETER;
6917 status = set_ea(conn, fsp, ea_list);
6919 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6920 smb_fname_str_dbg(fsp->fsp_name),
6921 nt_errstr(status) ));
6923 return status;
6927 /****************************************************************************
6928 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6929 ****************************************************************************/
6931 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6932 const char *pdata,
6933 int total_data,
6934 files_struct *fsp,
6935 struct smb_filename *smb_fname)
6937 NTSTATUS status = NT_STATUS_OK;
6938 bool delete_on_close;
6939 uint32_t dosmode = 0;
6941 if (total_data < 1) {
6942 return NT_STATUS_INVALID_PARAMETER;
6945 if (fsp == NULL) {
6946 return NT_STATUS_INVALID_HANDLE;
6949 delete_on_close = (CVAL(pdata,0) ? True : False);
6950 dosmode = fdos_mode(fsp);
6952 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6953 "delete_on_close = %u\n",
6954 smb_fname_str_dbg(smb_fname),
6955 (unsigned int)dosmode,
6956 (unsigned int)delete_on_close ));
6958 if (delete_on_close) {
6959 status = can_set_delete_on_close(fsp, dosmode);
6960 if (!NT_STATUS_IS_OK(status)) {
6961 return status;
6965 /* The set is across all open files on this dev/inode pair. */
6966 if (!set_delete_on_close(fsp, delete_on_close,
6967 conn->session_info->security_token,
6968 conn->session_info->unix_token)) {
6969 return NT_STATUS_ACCESS_DENIED;
6971 return NT_STATUS_OK;
6974 /****************************************************************************
6975 Deal with SMB_FILE_POSITION_INFORMATION.
6976 ****************************************************************************/
6978 static NTSTATUS smb_file_position_information(connection_struct *conn,
6979 const char *pdata,
6980 int total_data,
6981 files_struct *fsp)
6983 uint64_t position_information;
6985 if (total_data < 8) {
6986 return NT_STATUS_INVALID_PARAMETER;
6989 if (fsp == NULL) {
6990 /* Ignore on pathname based set. */
6991 return NT_STATUS_OK;
6994 position_information = (uint64_t)IVAL(pdata,0);
6995 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6997 DEBUG(10,("smb_file_position_information: Set file position "
6998 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6999 (double)position_information));
7000 fh_set_position_information(fsp->fh, position_information);
7001 return NT_STATUS_OK;
7004 /****************************************************************************
7005 Deal with SMB_FILE_MODE_INFORMATION.
7006 ****************************************************************************/
7008 static NTSTATUS smb_file_mode_information(connection_struct *conn,
7009 const char *pdata,
7010 int total_data)
7012 uint32_t mode;
7014 if (total_data < 4) {
7015 return NT_STATUS_INVALID_PARAMETER;
7017 mode = IVAL(pdata,0);
7018 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
7019 return NT_STATUS_INVALID_PARAMETER;
7021 return NT_STATUS_OK;
7024 /****************************************************************************
7025 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
7026 ****************************************************************************/
7028 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
7029 struct smb_request *req,
7030 const char *pdata,
7031 int total_data,
7032 struct smb_filename *new_smb_fname)
7034 char *link_target = NULL;
7035 struct smb_filename target_fname;
7036 TALLOC_CTX *ctx = talloc_tos();
7037 NTSTATUS status;
7038 int ret;
7039 struct smb_filename *parent_fname = NULL;
7040 struct smb_filename *base_name = NULL;
7042 /* Set a symbolic link. */
7043 /* Don't allow this if follow links is false. */
7045 if (total_data == 0) {
7046 return NT_STATUS_INVALID_PARAMETER;
7049 if (!lp_follow_symlinks(SNUM(conn))) {
7050 return NT_STATUS_ACCESS_DENIED;
7053 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
7054 total_data, STR_TERMINATE);
7056 if (!link_target) {
7057 return NT_STATUS_INVALID_PARAMETER;
7060 target_fname = (struct smb_filename) {
7061 .base_name = link_target,
7064 /* Removes @GMT tokens if any */
7065 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
7066 if (!NT_STATUS_IS_OK(status)) {
7067 return status;
7070 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7071 new_smb_fname->base_name, link_target ));
7073 status = parent_pathref(talloc_tos(),
7074 conn->cwd_fsp,
7075 new_smb_fname,
7076 &parent_fname,
7077 &base_name);
7078 if (!NT_STATUS_IS_OK(status)) {
7079 return status;
7082 ret = SMB_VFS_SYMLINKAT(conn,
7083 &target_fname,
7084 parent_fname->fsp,
7085 base_name);
7086 if (ret != 0) {
7087 TALLOC_FREE(parent_fname);
7088 return map_nt_error_from_unix(errno);
7091 TALLOC_FREE(parent_fname);
7092 return NT_STATUS_OK;
7095 /****************************************************************************
7096 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7097 ****************************************************************************/
7099 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7100 struct smb_request *req,
7101 const char *pdata, int total_data,
7102 struct smb_filename *smb_fname_new)
7104 char *oldname = NULL;
7105 struct smb_filename *smb_fname_old = NULL;
7106 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7107 TALLOC_CTX *ctx = talloc_tos();
7108 NTSTATUS status = NT_STATUS_OK;
7110 /* Set a hard link. */
7111 if (total_data == 0) {
7112 return NT_STATUS_INVALID_PARAMETER;
7115 if (req->posix_pathnames) {
7116 srvstr_get_path_posix(ctx,
7117 pdata,
7118 req->flags2,
7119 &oldname,
7120 pdata,
7121 total_data,
7122 STR_TERMINATE,
7123 &status);
7124 } else {
7125 srvstr_get_path(ctx,
7126 pdata,
7127 req->flags2,
7128 &oldname,
7129 pdata,
7130 total_data,
7131 STR_TERMINATE,
7132 &status);
7134 if (!NT_STATUS_IS_OK(status)) {
7135 return status;
7138 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7139 smb_fname_str_dbg(smb_fname_new), oldname));
7141 status = filename_convert(ctx,
7142 conn,
7143 oldname,
7144 ucf_flags,
7146 &smb_fname_old);
7147 if (!NT_STATUS_IS_OK(status)) {
7148 return status;
7151 return hardlink_internals(ctx, conn, req, false,
7152 smb_fname_old, smb_fname_new);
7155 /****************************************************************************
7156 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7157 ****************************************************************************/
7159 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7160 struct smb_request *req,
7161 const char *pdata,
7162 int total_data,
7163 files_struct *fsp,
7164 struct smb_filename *smb_fname_src)
7166 bool overwrite;
7167 uint32_t len;
7168 char *newname = NULL;
7169 struct smb_filename *smb_fname_dst = NULL;
7170 const char *dst_original_lcomp = NULL;
7171 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7172 NTSTATUS status = NT_STATUS_OK;
7173 TALLOC_CTX *ctx = talloc_tos();
7175 if (!fsp) {
7176 return NT_STATUS_INVALID_HANDLE;
7179 if (total_data < 20) {
7180 return NT_STATUS_INVALID_PARAMETER;
7183 overwrite = (CVAL(pdata,0) ? True : False);
7184 len = IVAL(pdata,16);
7186 if (len > (total_data - 20) || (len == 0)) {
7187 return NT_STATUS_INVALID_PARAMETER;
7190 if (req->posix_pathnames) {
7191 srvstr_get_path_posix(ctx,
7192 pdata,
7193 req->flags2,
7194 &newname,
7195 &pdata[20],
7196 len,
7197 STR_TERMINATE,
7198 &status);
7199 } else {
7200 srvstr_get_path(ctx,
7201 pdata,
7202 req->flags2,
7203 &newname,
7204 &pdata[20],
7205 len,
7206 STR_TERMINATE,
7207 &status);
7209 if (!NT_STATUS_IS_OK(status)) {
7210 return status;
7213 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7214 newname));
7216 status = filename_convert(ctx,
7217 conn,
7218 newname,
7219 ucf_flags,
7221 &smb_fname_dst);
7222 if (!NT_STATUS_IS_OK(status)) {
7223 return status;
7226 if (fsp->base_fsp) {
7227 /* newname must be a stream name. */
7228 if (newname[0] != ':') {
7229 return NT_STATUS_NOT_SUPPORTED;
7232 /* Create an smb_fname to call rename_internals_fsp() with. */
7233 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7234 fsp->base_fsp->fsp_name->base_name,
7235 newname,
7236 NULL,
7237 fsp->base_fsp->fsp_name->twrp,
7238 fsp->base_fsp->fsp_name->flags);
7239 if (smb_fname_dst == NULL) {
7240 status = NT_STATUS_NO_MEMORY;
7241 goto out;
7246 * Set the original last component, since
7247 * rename_internals_fsp() requires it.
7249 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7250 conn,
7251 newname,
7252 ucf_flags);
7253 if (dst_original_lcomp == NULL) {
7254 status = NT_STATUS_NO_MEMORY;
7255 goto out;
7258 DEBUG(10,("smb2_file_rename_information: "
7259 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7260 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7261 smb_fname_str_dbg(smb_fname_dst)));
7262 status = rename_internals_fsp(conn,
7263 fsp,
7264 smb_fname_dst,
7265 dst_original_lcomp,
7266 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7267 overwrite);
7269 out:
7270 TALLOC_FREE(smb_fname_dst);
7271 return status;
7274 static NTSTATUS smb_file_link_information(connection_struct *conn,
7275 struct smb_request *req,
7276 const char *pdata,
7277 int total_data,
7278 files_struct *fsp,
7279 struct smb_filename *smb_fname_src)
7281 bool overwrite;
7282 uint32_t len;
7283 char *newname = NULL;
7284 struct smb_filename *smb_fname_dst = NULL;
7285 NTSTATUS status = NT_STATUS_OK;
7286 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7287 TALLOC_CTX *ctx = talloc_tos();
7289 if (!fsp) {
7290 return NT_STATUS_INVALID_HANDLE;
7293 if (total_data < 20) {
7294 return NT_STATUS_INVALID_PARAMETER;
7297 overwrite = (CVAL(pdata,0) ? true : false);
7298 len = IVAL(pdata,16);
7300 if (len > (total_data - 20) || (len == 0)) {
7301 return NT_STATUS_INVALID_PARAMETER;
7304 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7305 srvstr_get_path_posix(ctx,
7306 pdata,
7307 req->flags2,
7308 &newname,
7309 &pdata[20],
7310 len,
7311 STR_TERMINATE,
7312 &status);
7313 ucf_flags |= UCF_POSIX_PATHNAMES;
7314 } else {
7315 srvstr_get_path(ctx,
7316 pdata,
7317 req->flags2,
7318 &newname,
7319 &pdata[20],
7320 len,
7321 STR_TERMINATE,
7322 &status);
7324 if (!NT_STATUS_IS_OK(status)) {
7325 return status;
7328 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7329 newname));
7331 status = filename_convert(ctx,
7332 conn,
7333 newname,
7334 ucf_flags,
7336 &smb_fname_dst);
7337 if (!NT_STATUS_IS_OK(status)) {
7338 return status;
7341 if (fsp->base_fsp) {
7342 /* No stream names. */
7343 return NT_STATUS_NOT_SUPPORTED;
7346 DEBUG(10,("smb_file_link_information: "
7347 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7348 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7349 smb_fname_str_dbg(smb_fname_dst)));
7350 status = hardlink_internals(ctx,
7351 conn,
7352 req,
7353 overwrite,
7354 fsp->fsp_name,
7355 smb_fname_dst);
7357 TALLOC_FREE(smb_fname_dst);
7358 return status;
7361 /****************************************************************************
7362 Deal with SMB_FILE_RENAME_INFORMATION.
7363 ****************************************************************************/
7365 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7366 struct smb_request *req,
7367 const char *pdata,
7368 int total_data,
7369 files_struct *fsp,
7370 struct smb_filename *smb_fname_src)
7372 bool overwrite;
7373 uint32_t root_fid;
7374 uint32_t len;
7375 char *newname = NULL;
7376 struct smb_filename *smb_fname_dst = NULL;
7377 const char *dst_original_lcomp = NULL;
7378 NTSTATUS status = NT_STATUS_OK;
7379 char *p;
7380 TALLOC_CTX *ctx = talloc_tos();
7382 if (total_data < 13) {
7383 return NT_STATUS_INVALID_PARAMETER;
7386 overwrite = (CVAL(pdata,0) ? True : False);
7387 root_fid = IVAL(pdata,4);
7388 len = IVAL(pdata,8);
7390 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7391 return NT_STATUS_INVALID_PARAMETER;
7394 if (req->posix_pathnames) {
7395 srvstr_get_path_posix(ctx,
7396 pdata,
7397 req->flags2,
7398 &newname,
7399 &pdata[12],
7400 len,
7402 &status);
7403 } else {
7404 srvstr_get_path(ctx,
7405 pdata,
7406 req->flags2,
7407 &newname,
7408 &pdata[12],
7409 len,
7411 &status);
7413 if (!NT_STATUS_IS_OK(status)) {
7414 return status;
7417 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7418 newname));
7420 /* Check the new name has no '/' characters. */
7421 if (strchr_m(newname, '/')) {
7422 return NT_STATUS_NOT_SUPPORTED;
7425 if (fsp && fsp->base_fsp) {
7426 /* newname must be a stream name. */
7427 if (newname[0] != ':') {
7428 return NT_STATUS_NOT_SUPPORTED;
7431 /* Create an smb_fname to call rename_internals_fsp() with. */
7432 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7433 fsp->base_fsp->fsp_name->base_name,
7434 newname,
7435 NULL,
7436 fsp->base_fsp->fsp_name->twrp,
7437 fsp->base_fsp->fsp_name->flags);
7438 if (smb_fname_dst == NULL) {
7439 status = NT_STATUS_NO_MEMORY;
7440 goto out;
7444 * Get the original last component, since
7445 * rename_internals_fsp() requires it.
7447 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7448 conn,
7449 newname,
7451 if (dst_original_lcomp == NULL) {
7452 status = NT_STATUS_NO_MEMORY;
7453 goto out;
7456 } else {
7458 * Build up an smb_fname_dst based on the filename passed in.
7459 * We basically just strip off the last component, and put on
7460 * the newname instead.
7462 char *base_name = NULL;
7463 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP|
7464 ucf_flags_from_smb_request(req);
7466 /* newname must *not* be a stream name. */
7467 if (newname[0] == ':') {
7468 return NT_STATUS_NOT_SUPPORTED;
7472 * Strip off the last component (filename) of the path passed
7473 * in.
7475 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7476 if (!base_name) {
7477 return NT_STATUS_NO_MEMORY;
7479 p = strrchr_m(base_name, '/');
7480 if (p) {
7481 p[1] = '\0';
7482 } else {
7483 base_name = talloc_strdup(ctx, "");
7484 if (!base_name) {
7485 return NT_STATUS_NO_MEMORY;
7488 /* Append the new name. */
7489 base_name = talloc_asprintf_append(base_name,
7490 "%s",
7491 newname);
7492 if (!base_name) {
7493 return NT_STATUS_NO_MEMORY;
7496 status = filename_convert(ctx,
7497 conn,
7498 base_name,
7499 ucf_flags,
7501 &smb_fname_dst);
7503 /* If an error we expect this to be
7504 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7506 if (!NT_STATUS_IS_OK(status)) {
7507 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7508 status)) {
7509 goto out;
7511 /* Create an smb_fname to call rename_internals_fsp() */
7512 smb_fname_dst = synthetic_smb_fname(ctx,
7513 base_name,
7514 NULL,
7515 NULL,
7516 smb_fname_src->twrp,
7517 smb_fname_src->flags);
7518 if (smb_fname_dst == NULL) {
7519 status = NT_STATUS_NO_MEMORY;
7520 goto out;
7523 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7524 conn,
7525 newname,
7526 ucf_flags);
7527 if (dst_original_lcomp == NULL) {
7528 status = NT_STATUS_NO_MEMORY;
7529 goto out;
7533 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
7534 DEBUG(10,("smb_file_rename_information: "
7535 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7536 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7537 smb_fname_str_dbg(smb_fname_dst)));
7538 status = rename_internals_fsp(conn,
7539 fsp,
7540 smb_fname_dst,
7541 dst_original_lcomp,
7543 overwrite);
7544 } else {
7545 DEBUG(10,("smb_file_rename_information: "
7546 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7547 smb_fname_str_dbg(smb_fname_src),
7548 smb_fname_str_dbg(smb_fname_dst)));
7549 status = rename_internals(ctx,
7550 conn,
7551 req,
7552 smb_fname_src,
7553 NULL,
7554 smb_fname_dst,
7555 dst_original_lcomp,
7557 overwrite,
7558 FILE_WRITE_ATTRIBUTES);
7560 out:
7561 TALLOC_FREE(smb_fname_dst);
7562 return status;
7565 /****************************************************************************
7566 Deal with SMB_SET_POSIX_ACL.
7567 ****************************************************************************/
7569 #if defined(HAVE_POSIX_ACLS)
7570 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7571 struct smb_request *req,
7572 const char *pdata,
7573 int total_data_in,
7574 files_struct *fsp,
7575 struct smb_filename *smb_fname)
7577 uint16_t posix_acl_version;
7578 uint16_t num_file_acls;
7579 uint16_t num_def_acls;
7580 bool valid_file_acls = true;
7581 bool valid_def_acls = true;
7582 NTSTATUS status;
7583 unsigned int size_needed;
7584 unsigned int total_data;
7585 bool close_fsp = false;
7587 if (total_data_in < 0) {
7588 status = NT_STATUS_INVALID_PARAMETER;
7589 goto out;
7592 total_data = total_data_in;
7594 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7595 status = NT_STATUS_INVALID_PARAMETER;
7596 goto out;
7598 posix_acl_version = SVAL(pdata,0);
7599 num_file_acls = SVAL(pdata,2);
7600 num_def_acls = SVAL(pdata,4);
7602 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7603 valid_file_acls = false;
7604 num_file_acls = 0;
7607 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7608 valid_def_acls = false;
7609 num_def_acls = 0;
7612 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7613 status = NT_STATUS_INVALID_PARAMETER;
7614 goto out;
7617 /* Wrap checks. */
7618 if (num_file_acls + num_def_acls < num_file_acls) {
7619 status = NT_STATUS_INVALID_PARAMETER;
7620 goto out;
7623 size_needed = num_file_acls + num_def_acls;
7626 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7627 * than UINT_MAX, so check by division.
7629 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7630 status = NT_STATUS_INVALID_PARAMETER;
7631 goto out;
7634 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7635 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7636 status = NT_STATUS_INVALID_PARAMETER;
7637 goto out;
7639 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7641 if (total_data < size_needed) {
7642 status = NT_STATUS_INVALID_PARAMETER;
7643 goto out;
7647 * Ensure we always operate on a file descriptor, not just
7648 * the filename.
7650 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
7651 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7652 SEC_STD_WRITE_DAC|
7653 SEC_STD_READ_CONTROL|
7654 FILE_READ_ATTRIBUTES|
7655 FILE_WRITE_ATTRIBUTES;
7657 status = get_posix_fsp(conn,
7658 req,
7659 smb_fname,
7660 access_mask,
7661 &fsp);
7663 if (!NT_STATUS_IS_OK(status)) {
7664 goto out;
7666 close_fsp = true;
7669 /* Here we know fsp != NULL */
7670 SMB_ASSERT(fsp != NULL);
7672 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7673 if (!NT_STATUS_IS_OK(status)) {
7674 goto out;
7677 /* If we have a default acl, this *must* be a directory. */
7678 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7679 DBG_INFO("Can't set default acls on "
7680 "non-directory %s\n",
7681 fsp_str_dbg(fsp));
7682 return NT_STATUS_INVALID_HANDLE;
7685 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7686 "num_def_acls = %"PRIu16"\n",
7687 fsp_str_dbg(fsp),
7688 num_file_acls,
7689 num_def_acls);
7691 /* Move pdata to the start of the file ACL entries. */
7692 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7694 if (valid_file_acls) {
7695 status = set_unix_posix_acl(conn,
7696 fsp,
7697 num_file_acls,
7698 pdata);
7699 if (!NT_STATUS_IS_OK(status)) {
7700 goto out;
7704 /* Move pdata to the start of the default ACL entries. */
7705 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7707 if (valid_def_acls) {
7708 status = set_unix_posix_default_acl(conn,
7709 fsp,
7710 num_def_acls,
7711 pdata);
7712 if (!NT_STATUS_IS_OK(status)) {
7713 goto out;
7717 status = NT_STATUS_OK;
7719 out:
7721 if (close_fsp) {
7722 (void)close_file(req, fsp, NORMAL_CLOSE);
7723 fsp = NULL;
7725 return status;
7727 #endif
7729 /****************************************************************************
7730 Deal with SMB_SET_POSIX_LOCK.
7731 ****************************************************************************/
7733 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7735 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7736 struct smb_request *req,
7737 const char *pdata,
7738 int total_data,
7739 files_struct *fsp)
7741 struct tevent_req *subreq = NULL;
7742 struct smbd_lock_element *lck = NULL;
7743 uint64_t count;
7744 uint64_t offset;
7745 uint64_t smblctx;
7746 bool blocking_lock = False;
7747 enum brl_type lock_type;
7749 NTSTATUS status = NT_STATUS_OK;
7751 if (fsp == NULL ||
7752 fsp->fsp_flags.is_pathref ||
7753 fsp_get_io_fd(fsp) == -1)
7755 return NT_STATUS_INVALID_HANDLE;
7758 if (total_data != POSIX_LOCK_DATA_SIZE) {
7759 return NT_STATUS_INVALID_PARAMETER;
7762 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7763 case POSIX_LOCK_TYPE_READ:
7764 lock_type = READ_LOCK;
7765 break;
7766 case POSIX_LOCK_TYPE_WRITE:
7767 /* Return the right POSIX-mappable error code for files opened read-only. */
7768 if (!fsp->fsp_flags.can_write) {
7769 return NT_STATUS_INVALID_HANDLE;
7771 lock_type = WRITE_LOCK;
7772 break;
7773 case POSIX_LOCK_TYPE_UNLOCK:
7774 lock_type = UNLOCK_LOCK;
7775 break;
7776 default:
7777 return NT_STATUS_INVALID_PARAMETER;
7780 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7781 case POSIX_LOCK_FLAG_NOWAIT:
7782 blocking_lock = false;
7783 break;
7784 case POSIX_LOCK_FLAG_WAIT:
7785 blocking_lock = true;
7786 break;
7787 default:
7788 return NT_STATUS_INVALID_PARAMETER;
7791 if (!lp_blocking_locks(SNUM(conn))) {
7792 blocking_lock = False;
7795 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7796 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7797 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7798 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7799 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7801 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7802 "count = %"PRIu64", offset = %"PRIu64"\n",
7803 fsp_str_dbg(fsp),
7804 (unsigned int)lock_type,
7805 smblctx,
7806 count,
7807 offset);
7809 if (lock_type == UNLOCK_LOCK) {
7810 struct smbd_lock_element l = {
7811 .req_guid = smbd_request_guid(req, 0),
7812 .smblctx = smblctx,
7813 .brltype = UNLOCK_LOCK,
7814 .offset = offset,
7815 .count = count,
7817 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7818 return status;
7821 lck = talloc(req, struct smbd_lock_element);
7822 if (lck == NULL) {
7823 return NT_STATUS_NO_MEMORY;
7826 *lck = (struct smbd_lock_element) {
7827 .req_guid = smbd_request_guid(req, 0),
7828 .smblctx = smblctx,
7829 .brltype = lock_type,
7830 .count = count,
7831 .offset = offset,
7834 subreq = smbd_smb1_do_locks_send(
7835 fsp,
7836 req->sconn->ev_ctx,
7837 &req,
7838 fsp,
7839 blocking_lock ? UINT32_MAX : 0,
7840 true, /* large_offset */
7841 POSIX_LOCK,
7843 lck);
7844 if (subreq == NULL) {
7845 TALLOC_FREE(lck);
7846 return NT_STATUS_NO_MEMORY;
7848 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7849 return NT_STATUS_EVENT_PENDING;
7852 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7854 struct smb_request *req = NULL;
7855 NTSTATUS status;
7856 bool ok;
7858 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7859 SMB_ASSERT(ok);
7861 status = smbd_smb1_do_locks_recv(subreq);
7862 TALLOC_FREE(subreq);
7864 if (NT_STATUS_IS_OK(status)) {
7865 char params[2] = {0};
7866 /* Fake up max_data_bytes here - we know it fits. */
7867 send_trans2_replies(
7868 req->conn,
7869 req,
7870 NT_STATUS_OK,
7871 params,
7873 NULL,
7875 0xffff);
7876 } else {
7877 reply_nterror(req, status);
7878 ok = srv_send_smb(
7879 req->xconn,
7880 (char *)req->outbuf,
7881 true,
7882 req->seqnum+1,
7883 IS_CONN_ENCRYPTED(req->conn),
7884 NULL);
7885 if (!ok) {
7886 exit_server_cleanly("smb_set_posix_lock_done: "
7887 "srv_send_smb failed.");
7891 TALLOC_FREE(req);
7892 return;
7895 /****************************************************************************
7896 Deal with SMB_SET_FILE_BASIC_INFO.
7897 ****************************************************************************/
7899 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7900 const char *pdata,
7901 int total_data,
7902 files_struct *fsp,
7903 struct smb_filename *smb_fname)
7905 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7906 struct smb_file_time ft;
7907 uint32_t dosmode = 0;
7908 NTSTATUS status = NT_STATUS_OK;
7910 init_smb_file_time(&ft);
7912 if (total_data < 36) {
7913 return NT_STATUS_INVALID_PARAMETER;
7916 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7917 if (!NT_STATUS_IS_OK(status)) {
7918 return status;
7921 /* Set the attributes */
7922 dosmode = IVAL(pdata,32);
7923 status = smb_set_file_dosmode(conn, fsp, smb_fname, dosmode);
7924 if (!NT_STATUS_IS_OK(status)) {
7925 return status;
7928 /* create time */
7929 ft.create_time = pull_long_date_full_timespec(pdata);
7931 /* access time */
7932 ft.atime = pull_long_date_full_timespec(pdata+8);
7934 /* write time. */
7935 ft.mtime = pull_long_date_full_timespec(pdata+16);
7937 /* change time. */
7938 ft.ctime = pull_long_date_full_timespec(pdata+24);
7940 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7941 smb_fname_str_dbg(smb_fname)));
7943 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7944 if (!NT_STATUS_IS_OK(status)) {
7945 return status;
7948 if (fsp != NULL && fsp->fsp_flags.modified) {
7949 trigger_write_time_update_immediate(fsp);
7951 return NT_STATUS_OK;
7954 /****************************************************************************
7955 Deal with SMB_INFO_STANDARD.
7956 ****************************************************************************/
7958 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7959 const char *pdata,
7960 int total_data,
7961 files_struct *fsp,
7962 struct smb_filename *smb_fname)
7964 NTSTATUS status;
7965 struct smb_file_time ft;
7967 init_smb_file_time(&ft);
7969 if (total_data < 12) {
7970 return NT_STATUS_INVALID_PARAMETER;
7973 /* create time */
7974 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7975 /* access time */
7976 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7977 /* write time */
7978 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7980 DEBUG(10,("smb_set_info_standard: file %s\n",
7981 smb_fname_str_dbg(smb_fname)));
7983 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7984 if (!NT_STATUS_IS_OK(status)) {
7985 return status;
7988 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7989 if (!NT_STATUS_IS_OK(status)) {
7990 return status;
7993 if (fsp != NULL && fsp->fsp_flags.modified) {
7994 trigger_write_time_update_immediate(fsp);
7996 return NT_STATUS_OK;
7999 /****************************************************************************
8000 Deal with SMB_SET_FILE_ALLOCATION_INFO.
8001 ****************************************************************************/
8003 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
8004 struct smb_request *req,
8005 const char *pdata,
8006 int total_data,
8007 files_struct *fsp,
8008 struct smb_filename *smb_fname)
8010 uint64_t allocation_size = 0;
8011 NTSTATUS status = NT_STATUS_OK;
8012 files_struct *new_fsp = NULL;
8014 if (!VALID_STAT(smb_fname->st)) {
8015 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8018 if (total_data < 8) {
8019 return NT_STATUS_INVALID_PARAMETER;
8022 allocation_size = (uint64_t)IVAL(pdata,0);
8023 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
8024 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
8025 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8026 (double)allocation_size));
8028 if (allocation_size) {
8029 allocation_size = smb_roundup(conn, allocation_size);
8032 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
8033 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
8034 (double)allocation_size));
8036 if (fsp &&
8037 !fsp->fsp_flags.is_pathref &&
8038 fsp_get_io_fd(fsp) != -1)
8040 /* Open file handle. */
8041 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
8042 return NT_STATUS_ACCESS_DENIED;
8045 /* Only change if needed. */
8046 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8047 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
8048 return map_nt_error_from_unix(errno);
8051 /* But always update the time. */
8053 * This is equivalent to a write. Ensure it's seen immediately
8054 * if there are no pending writes.
8056 trigger_write_time_update_immediate(fsp);
8057 return NT_STATUS_OK;
8060 /* Pathname or stat or directory file. */
8061 status = SMB_VFS_CREATE_FILE(
8062 conn, /* conn */
8063 req, /* req */
8064 smb_fname, /* fname */
8065 FILE_WRITE_DATA, /* access_mask */
8066 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8067 FILE_SHARE_DELETE),
8068 FILE_OPEN, /* create_disposition*/
8069 0, /* create_options */
8070 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8071 0, /* oplock_request */
8072 NULL, /* lease */
8073 0, /* allocation_size */
8074 0, /* private_flags */
8075 NULL, /* sd */
8076 NULL, /* ea_list */
8077 &new_fsp, /* result */
8078 NULL, /* pinfo */
8079 NULL, NULL); /* create context */
8081 if (!NT_STATUS_IS_OK(status)) {
8082 /* NB. We check for open_was_deferred in the caller. */
8083 return status;
8086 /* Only change if needed. */
8087 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8088 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8089 status = map_nt_error_from_unix(errno);
8090 close_file(req, new_fsp, NORMAL_CLOSE);
8091 return status;
8095 /* Changing the allocation size should set the last mod time. */
8097 * This is equivalent to a write. Ensure it's seen immediately
8098 * if there are no pending writes.
8100 trigger_write_time_update_immediate(new_fsp);
8101 close_file(req, new_fsp, NORMAL_CLOSE);
8102 return NT_STATUS_OK;
8105 /****************************************************************************
8106 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8107 ****************************************************************************/
8109 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8110 struct smb_request *req,
8111 const char *pdata,
8112 int total_data,
8113 files_struct *fsp,
8114 struct smb_filename *smb_fname,
8115 bool fail_after_createfile)
8117 off_t size;
8119 if (total_data < 8) {
8120 return NT_STATUS_INVALID_PARAMETER;
8123 size = IVAL(pdata,0);
8124 size |= (((off_t)IVAL(pdata,4)) << 32);
8125 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8126 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8127 (double)size));
8129 return smb_set_file_size(conn, req,
8130 fsp,
8131 smb_fname,
8132 &smb_fname->st,
8133 size,
8134 fail_after_createfile);
8137 /****************************************************************************
8138 Allow a UNIX info mknod.
8139 ****************************************************************************/
8141 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8142 const char *pdata,
8143 int total_data,
8144 const struct smb_filename *smb_fname)
8146 uint32_t file_type = IVAL(pdata,56);
8147 #if defined(HAVE_MAKEDEV)
8148 uint32_t dev_major = IVAL(pdata,60);
8149 uint32_t dev_minor = IVAL(pdata,68);
8150 #endif
8151 SMB_DEV_T dev = (SMB_DEV_T)0;
8152 uint32_t raw_unixmode = IVAL(pdata,84);
8153 NTSTATUS status;
8154 mode_t unixmode;
8155 int ret;
8156 struct smb_filename *parent_fname = NULL;
8157 struct smb_filename *base_name = NULL;
8159 if (total_data < 100) {
8160 return NT_STATUS_INVALID_PARAMETER;
8163 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8164 PERM_NEW_FILE, &unixmode);
8165 if (!NT_STATUS_IS_OK(status)) {
8166 return status;
8169 #if defined(HAVE_MAKEDEV)
8170 dev = makedev(dev_major, dev_minor);
8171 #endif
8173 switch (file_type) {
8174 /* We can't create other objects here. */
8175 case UNIX_TYPE_FILE:
8176 case UNIX_TYPE_DIR:
8177 case UNIX_TYPE_SYMLINK:
8178 return NT_STATUS_ACCESS_DENIED;
8179 #if defined(S_IFIFO)
8180 case UNIX_TYPE_FIFO:
8181 unixmode |= S_IFIFO;
8182 break;
8183 #endif
8184 #if defined(S_IFSOCK)
8185 case UNIX_TYPE_SOCKET:
8186 unixmode |= S_IFSOCK;
8187 break;
8188 #endif
8189 #if defined(S_IFCHR)
8190 case UNIX_TYPE_CHARDEV:
8191 /* This is only allowed for root. */
8192 if (get_current_uid(conn) != sec_initial_uid()) {
8193 return NT_STATUS_ACCESS_DENIED;
8195 unixmode |= S_IFCHR;
8196 break;
8197 #endif
8198 #if defined(S_IFBLK)
8199 case UNIX_TYPE_BLKDEV:
8200 if (get_current_uid(conn) != sec_initial_uid()) {
8201 return NT_STATUS_ACCESS_DENIED;
8203 unixmode |= S_IFBLK;
8204 break;
8205 #endif
8206 default:
8207 return NT_STATUS_INVALID_PARAMETER;
8210 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8211 "%.0f mode 0%o for file %s\n", (double)dev,
8212 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8214 status = parent_pathref(talloc_tos(),
8215 conn->cwd_fsp,
8216 smb_fname,
8217 &parent_fname,
8218 &base_name);
8219 if (!NT_STATUS_IS_OK(status)) {
8220 return status;
8223 /* Ok - do the mknod. */
8224 ret = SMB_VFS_MKNODAT(conn,
8225 parent_fname->fsp,
8226 base_name,
8227 unixmode,
8228 dev);
8230 if (ret != 0) {
8231 TALLOC_FREE(parent_fname);
8232 return map_nt_error_from_unix(errno);
8235 /* If any of the other "set" calls fail we
8236 * don't want to end up with a half-constructed mknod.
8239 if (lp_inherit_permissions(SNUM(conn))) {
8240 inherit_access_posix_acl(conn,
8241 parent_fname,
8242 smb_fname,
8243 unixmode);
8245 TALLOC_FREE(parent_fname);
8247 return NT_STATUS_OK;
8250 /****************************************************************************
8251 Deal with SMB_SET_FILE_UNIX_BASIC.
8252 ****************************************************************************/
8254 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8255 struct smb_request *req,
8256 const char *pdata,
8257 int total_data,
8258 files_struct *fsp,
8259 struct smb_filename *smb_fname)
8261 struct smb_file_time ft;
8262 uint32_t raw_unixmode;
8263 mode_t unixmode;
8264 off_t size = 0;
8265 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8266 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8267 NTSTATUS status = NT_STATUS_OK;
8268 enum perm_type ptype;
8269 files_struct *all_fsps = NULL;
8270 bool modify_mtime = true;
8271 struct file_id id;
8272 SMB_STRUCT_STAT sbuf;
8274 init_smb_file_time(&ft);
8276 if (total_data < 100) {
8277 return NT_STATUS_INVALID_PARAMETER;
8280 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8281 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8282 size=IVAL(pdata,0); /* first 8 Bytes are size */
8283 size |= (((off_t)IVAL(pdata,4)) << 32);
8286 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8287 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8288 set_owner = (uid_t)IVAL(pdata,40);
8289 set_grp = (gid_t)IVAL(pdata,48);
8290 raw_unixmode = IVAL(pdata,84);
8292 if (VALID_STAT(smb_fname->st)) {
8293 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8294 ptype = PERM_EXISTING_DIR;
8295 } else {
8296 ptype = PERM_EXISTING_FILE;
8298 } else {
8299 ptype = PERM_NEW_FILE;
8302 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8303 ptype, &unixmode);
8304 if (!NT_STATUS_IS_OK(status)) {
8305 return status;
8308 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8309 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8310 smb_fname_str_dbg(smb_fname), (double)size,
8311 (unsigned int)set_owner, (unsigned int)set_grp,
8312 (int)raw_unixmode));
8314 sbuf = smb_fname->st;
8316 if (!VALID_STAT(sbuf)) {
8318 * The only valid use of this is to create character and block
8319 * devices, and named pipes. This is deprecated (IMHO) and
8320 * a new info level should be used for mknod. JRA.
8323 return smb_unix_mknod(conn,
8324 pdata,
8325 total_data,
8326 smb_fname);
8329 #if 1
8330 /* Horrible backwards compatibility hack as an old server bug
8331 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8332 * */
8334 if (!size) {
8335 size = get_file_size_stat(&sbuf);
8337 #endif
8340 * Deal with the UNIX specific mode set.
8343 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8344 int ret;
8346 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8347 "setting mode 0%o for file %s\n",
8348 (unsigned int)unixmode,
8349 smb_fname_str_dbg(smb_fname)));
8350 if (fsp &&
8351 !fsp->fsp_flags.is_pathref &&
8352 fsp_get_io_fd(fsp) != -1)
8354 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8355 } else {
8356 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8358 if (ret != 0) {
8359 return map_nt_error_from_unix(errno);
8364 * Deal with the UNIX specific uid set.
8367 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8368 (sbuf.st_ex_uid != set_owner)) {
8369 int ret;
8371 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8372 "changing owner %u for path %s\n",
8373 (unsigned int)set_owner,
8374 smb_fname_str_dbg(smb_fname)));
8376 if (fsp &&
8377 !fsp->fsp_flags.is_pathref &&
8378 fsp_get_io_fd(fsp) != -1)
8380 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8381 } else {
8383 * UNIX extensions calls must always operate
8384 * on symlinks.
8386 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8387 set_owner, (gid_t)-1);
8390 if (ret != 0) {
8391 status = map_nt_error_from_unix(errno);
8392 return status;
8397 * Deal with the UNIX specific gid set.
8400 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8401 (sbuf.st_ex_gid != set_grp)) {
8402 int ret;
8404 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8405 "changing group %u for file %s\n",
8406 (unsigned int)set_grp,
8407 smb_fname_str_dbg(smb_fname)));
8408 if (fsp &&
8409 !fsp->fsp_flags.is_pathref &&
8410 fsp_get_io_fd(fsp) != -1)
8412 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8413 } else {
8415 * UNIX extensions calls must always operate
8416 * on symlinks.
8418 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8419 set_grp);
8421 if (ret != 0) {
8422 status = map_nt_error_from_unix(errno);
8423 return status;
8427 /* Deal with any size changes. */
8429 if (S_ISREG(sbuf.st_ex_mode)) {
8430 status = smb_set_file_size(conn, req,
8431 fsp,
8432 smb_fname,
8433 &sbuf,
8434 size,
8435 false);
8436 if (!NT_STATUS_IS_OK(status)) {
8437 return status;
8441 /* Deal with any time changes. */
8442 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8443 /* No change, don't cancel anything. */
8444 return status;
8447 id = vfs_file_id_from_sbuf(conn, &sbuf);
8448 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
8449 all_fsps = file_find_di_next(all_fsps, true)) {
8451 * We're setting the time explicitly for UNIX.
8452 * Cancel any pending changes over all handles.
8454 all_fsps->fsp_flags.update_write_time_on_close = false;
8455 TALLOC_FREE(all_fsps->update_write_time_event);
8459 * Override the "setting_write_time"
8460 * parameter here as it almost does what
8461 * we need. Just remember if we modified
8462 * mtime and send the notify ourselves.
8464 if (is_omit_timespec(&ft.mtime)) {
8465 modify_mtime = false;
8468 status = smb_set_file_time(conn,
8469 fsp,
8470 smb_fname,
8471 &ft,
8472 false);
8473 if (modify_mtime) {
8474 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8475 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8477 return status;
8480 /****************************************************************************
8481 Deal with SMB_SET_FILE_UNIX_INFO2.
8482 ****************************************************************************/
8484 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8485 struct smb_request *req,
8486 const char *pdata,
8487 int total_data,
8488 files_struct *fsp,
8489 struct smb_filename *smb_fname)
8491 NTSTATUS status;
8492 uint32_t smb_fflags;
8493 uint32_t smb_fmask;
8495 if (total_data < 116) {
8496 return NT_STATUS_INVALID_PARAMETER;
8499 /* Start by setting all the fields that are common between UNIX_BASIC
8500 * and UNIX_INFO2.
8502 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8503 fsp, smb_fname);
8504 if (!NT_STATUS_IS_OK(status)) {
8505 return status;
8508 smb_fflags = IVAL(pdata, 108);
8509 smb_fmask = IVAL(pdata, 112);
8511 /* NB: We should only attempt to alter the file flags if the client
8512 * sends a non-zero mask.
8514 if (smb_fmask != 0) {
8515 int stat_fflags = 0;
8517 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8518 smb_fmask, &stat_fflags)) {
8519 /* Client asked to alter a flag we don't understand. */
8520 return NT_STATUS_INVALID_PARAMETER;
8523 if (fsp &&
8524 !fsp->fsp_flags.is_pathref &&
8525 fsp_get_io_fd(fsp) != -1)
8527 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8528 return NT_STATUS_NOT_SUPPORTED;
8529 } else {
8530 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8531 stat_fflags) != 0) {
8532 return map_nt_error_from_unix(errno);
8537 /* XXX: need to add support for changing the create_time here. You
8538 * can do this for paths on Darwin with setattrlist(2). The right way
8539 * to hook this up is probably by extending the VFS utimes interface.
8542 return NT_STATUS_OK;
8545 /****************************************************************************
8546 Create a directory with POSIX semantics.
8547 ****************************************************************************/
8549 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8550 struct smb_request *req,
8551 char **ppdata,
8552 int total_data,
8553 struct smb_filename *smb_fname,
8554 int *pdata_return_size)
8556 NTSTATUS status = NT_STATUS_OK;
8557 uint32_t raw_unixmode = 0;
8558 mode_t unixmode = (mode_t)0;
8559 files_struct *fsp = NULL;
8560 uint16_t info_level_return = 0;
8561 int info;
8562 char *pdata = *ppdata;
8563 struct smb2_create_blobs *posx = NULL;
8565 if (total_data < 18) {
8566 return NT_STATUS_INVALID_PARAMETER;
8569 raw_unixmode = IVAL(pdata,8);
8570 /* Next 4 bytes are not yet defined. */
8572 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8573 PERM_NEW_DIR, &unixmode);
8574 if (!NT_STATUS_IS_OK(status)) {
8575 return status;
8578 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8579 if (!NT_STATUS_IS_OK(status)) {
8580 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8581 nt_errstr(status));
8582 return status;
8585 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8586 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8588 status = SMB_VFS_CREATE_FILE(
8589 conn, /* conn */
8590 req, /* req */
8591 smb_fname, /* fname */
8592 FILE_READ_ATTRIBUTES, /* access_mask */
8593 FILE_SHARE_NONE, /* share_access */
8594 FILE_CREATE, /* create_disposition*/
8595 FILE_DIRECTORY_FILE, /* create_options */
8596 0, /* file_attributes */
8597 0, /* oplock_request */
8598 NULL, /* lease */
8599 0, /* allocation_size */
8600 0, /* private_flags */
8601 NULL, /* sd */
8602 NULL, /* ea_list */
8603 &fsp, /* result */
8604 &info, /* pinfo */
8605 posx, /* in_context_blobs */
8606 NULL); /* out_context_blobs */
8608 TALLOC_FREE(posx);
8610 if (NT_STATUS_IS_OK(status)) {
8611 close_file(req, fsp, NORMAL_CLOSE);
8614 info_level_return = SVAL(pdata,16);
8616 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8617 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8618 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8619 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8620 } else {
8621 *pdata_return_size = 12;
8624 /* Realloc the data size */
8625 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8626 if (*ppdata == NULL) {
8627 *pdata_return_size = 0;
8628 return NT_STATUS_NO_MEMORY;
8630 pdata = *ppdata;
8632 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8633 SSVAL(pdata,2,0); /* No fnum. */
8634 SIVAL(pdata,4,info); /* Was directory created. */
8636 switch (info_level_return) {
8637 case SMB_QUERY_FILE_UNIX_BASIC:
8638 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8639 SSVAL(pdata,10,0); /* Padding. */
8640 store_file_unix_basic(conn, pdata + 12, fsp,
8641 &smb_fname->st);
8642 break;
8643 case SMB_QUERY_FILE_UNIX_INFO2:
8644 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8645 SSVAL(pdata,10,0); /* Padding. */
8646 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8647 &smb_fname->st);
8648 break;
8649 default:
8650 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8651 SSVAL(pdata,10,0); /* Padding. */
8652 break;
8655 return status;
8658 /****************************************************************************
8659 Open/Create a file with POSIX semantics.
8660 ****************************************************************************/
8662 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8663 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8665 static NTSTATUS smb_posix_open(connection_struct *conn,
8666 struct smb_request *req,
8667 char **ppdata,
8668 int total_data,
8669 struct smb_filename *smb_fname,
8670 int *pdata_return_size)
8672 bool extended_oplock_granted = False;
8673 char *pdata = *ppdata;
8674 uint32_t flags = 0;
8675 uint32_t wire_open_mode = 0;
8676 uint32_t raw_unixmode = 0;
8677 uint32_t attributes = 0;
8678 uint32_t create_disp = 0;
8679 uint32_t access_mask = 0;
8680 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8681 NTSTATUS status = NT_STATUS_OK;
8682 mode_t unixmode = (mode_t)0;
8683 files_struct *fsp = NULL;
8684 int oplock_request = 0;
8685 int info = 0;
8686 uint16_t info_level_return = 0;
8687 struct smb2_create_blobs *posx = NULL;
8689 if (total_data < 18) {
8690 return NT_STATUS_INVALID_PARAMETER;
8693 flags = IVAL(pdata,0);
8694 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8695 if (oplock_request) {
8696 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8699 wire_open_mode = IVAL(pdata,4);
8701 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8702 return smb_posix_mkdir(conn, req,
8703 ppdata,
8704 total_data,
8705 smb_fname,
8706 pdata_return_size);
8709 switch (wire_open_mode & SMB_ACCMODE) {
8710 case SMB_O_RDONLY:
8711 access_mask = SMB_O_RDONLY_MAPPING;
8712 break;
8713 case SMB_O_WRONLY:
8714 access_mask = SMB_O_WRONLY_MAPPING;
8715 break;
8716 case SMB_O_RDWR:
8717 access_mask = (SMB_O_RDONLY_MAPPING|
8718 SMB_O_WRONLY_MAPPING);
8719 break;
8720 default:
8721 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8722 (unsigned int)wire_open_mode ));
8723 return NT_STATUS_INVALID_PARAMETER;
8726 wire_open_mode &= ~SMB_ACCMODE;
8728 /* First take care of O_CREAT|O_EXCL interactions. */
8729 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8730 case (SMB_O_CREAT | SMB_O_EXCL):
8731 /* File exists fail. File not exist create. */
8732 create_disp = FILE_CREATE;
8733 break;
8734 case SMB_O_CREAT:
8735 /* File exists open. File not exist create. */
8736 create_disp = FILE_OPEN_IF;
8737 break;
8738 case SMB_O_EXCL:
8739 /* O_EXCL on its own without O_CREAT is undefined.
8740 We deliberately ignore it as some versions of
8741 Linux CIFSFS can send a bare O_EXCL on the
8742 wire which other filesystems in the kernel
8743 ignore. See bug 9519 for details. */
8745 /* Fallthrough. */
8747 case 0:
8748 /* File exists open. File not exist fail. */
8749 create_disp = FILE_OPEN;
8750 break;
8751 default:
8752 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8753 (unsigned int)wire_open_mode ));
8754 return NT_STATUS_INVALID_PARAMETER;
8757 /* Next factor in the effects of O_TRUNC. */
8758 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8760 if (wire_open_mode & SMB_O_TRUNC) {
8761 switch (create_disp) {
8762 case FILE_CREATE:
8763 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8764 /* Leave create_disp alone as
8765 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8767 /* File exists fail. File not exist create. */
8768 break;
8769 case FILE_OPEN_IF:
8770 /* SMB_O_CREAT | SMB_O_TRUNC */
8771 /* File exists overwrite. File not exist create. */
8772 create_disp = FILE_OVERWRITE_IF;
8773 break;
8774 case FILE_OPEN:
8775 /* SMB_O_TRUNC */
8776 /* File exists overwrite. File not exist fail. */
8777 create_disp = FILE_OVERWRITE;
8778 break;
8779 default:
8780 /* Cannot get here. */
8781 smb_panic("smb_posix_open: logic error");
8782 return NT_STATUS_INVALID_PARAMETER;
8786 raw_unixmode = IVAL(pdata,8);
8787 /* Next 4 bytes are not yet defined. */
8789 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8790 (VALID_STAT(smb_fname->st) ?
8791 PERM_EXISTING_FILE : PERM_NEW_FILE),
8792 &unixmode);
8794 if (!NT_STATUS_IS_OK(status)) {
8795 return status;
8798 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8799 if (!NT_STATUS_IS_OK(status)) {
8800 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8801 nt_errstr(status));
8802 return status;
8805 if (wire_open_mode & SMB_O_SYNC) {
8806 create_options |= FILE_WRITE_THROUGH;
8808 if (wire_open_mode & SMB_O_APPEND) {
8809 access_mask |= FILE_APPEND_DATA;
8811 if (wire_open_mode & SMB_O_DIRECT) {
8812 attributes |= FILE_FLAG_NO_BUFFERING;
8815 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8816 VALID_STAT_OF_DIR(smb_fname->st)) {
8817 if (access_mask != SMB_O_RDONLY_MAPPING) {
8818 return NT_STATUS_FILE_IS_A_DIRECTORY;
8820 create_options &= ~FILE_NON_DIRECTORY_FILE;
8821 create_options |= FILE_DIRECTORY_FILE;
8824 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8825 smb_fname_str_dbg(smb_fname),
8826 (unsigned int)wire_open_mode,
8827 (unsigned int)unixmode ));
8829 status = SMB_VFS_CREATE_FILE(
8830 conn, /* conn */
8831 req, /* req */
8832 smb_fname, /* fname */
8833 access_mask, /* access_mask */
8834 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8835 FILE_SHARE_DELETE),
8836 create_disp, /* create_disposition*/
8837 create_options, /* create_options */
8838 attributes, /* file_attributes */
8839 oplock_request, /* oplock_request */
8840 NULL, /* lease */
8841 0, /* allocation_size */
8842 0, /* private_flags */
8843 NULL, /* sd */
8844 NULL, /* ea_list */
8845 &fsp, /* result */
8846 &info, /* pinfo */
8847 posx, /* in_context_blobs */
8848 NULL); /* out_context_blobs */
8850 TALLOC_FREE(posx);
8852 if (!NT_STATUS_IS_OK(status)) {
8853 return status;
8856 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8857 extended_oplock_granted = True;
8860 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8861 extended_oplock_granted = True;
8864 info_level_return = SVAL(pdata,16);
8866 /* Allocate the correct return size. */
8868 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8869 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8870 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8871 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8872 } else {
8873 *pdata_return_size = 12;
8876 /* Realloc the data size */
8877 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8878 if (*ppdata == NULL) {
8879 close_file(req, fsp, ERROR_CLOSE);
8880 *pdata_return_size = 0;
8881 return NT_STATUS_NO_MEMORY;
8883 pdata = *ppdata;
8885 if (extended_oplock_granted) {
8886 if (flags & REQUEST_BATCH_OPLOCK) {
8887 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8888 } else {
8889 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8891 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8892 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8893 } else {
8894 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8897 SSVAL(pdata,2,fsp->fnum);
8898 SIVAL(pdata,4,info); /* Was file created etc. */
8900 switch (info_level_return) {
8901 case SMB_QUERY_FILE_UNIX_BASIC:
8902 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8903 SSVAL(pdata,10,0); /* padding. */
8904 store_file_unix_basic(conn, pdata + 12, fsp,
8905 &smb_fname->st);
8906 break;
8907 case SMB_QUERY_FILE_UNIX_INFO2:
8908 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8909 SSVAL(pdata,10,0); /* padding. */
8910 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8911 &smb_fname->st);
8912 break;
8913 default:
8914 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8915 SSVAL(pdata,10,0); /* padding. */
8916 break;
8918 return NT_STATUS_OK;
8921 /****************************************************************************
8922 Delete a file with POSIX semantics.
8923 ****************************************************************************/
8925 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8926 struct smb_request *req,
8927 const char *pdata,
8928 int total_data,
8929 struct smb_filename *smb_fname)
8931 NTSTATUS status = NT_STATUS_OK;
8932 files_struct *fsp = NULL;
8933 uint16_t flags = 0;
8934 char del = 1;
8935 int info = 0;
8936 int create_options = 0;
8937 struct share_mode_lock *lck = NULL;
8938 bool other_nonposix_opens;
8939 struct smb2_create_blobs *posx = NULL;
8941 if (total_data < 2) {
8942 return NT_STATUS_INVALID_PARAMETER;
8945 flags = SVAL(pdata,0);
8947 if (!VALID_STAT(smb_fname->st)) {
8948 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8951 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8952 !VALID_STAT_OF_DIR(smb_fname->st)) {
8953 return NT_STATUS_NOT_A_DIRECTORY;
8956 DEBUG(10,("smb_posix_unlink: %s %s\n",
8957 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8958 smb_fname_str_dbg(smb_fname)));
8960 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8961 create_options |= FILE_DIRECTORY_FILE;
8964 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8965 if (!NT_STATUS_IS_OK(status)) {
8966 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8967 nt_errstr(status));
8968 return status;
8971 status = SMB_VFS_CREATE_FILE(
8972 conn, /* conn */
8973 req, /* req */
8974 smb_fname, /* fname */
8975 DELETE_ACCESS, /* access_mask */
8976 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8977 FILE_SHARE_DELETE),
8978 FILE_OPEN, /* create_disposition*/
8979 create_options, /* create_options */
8980 0, /* file_attributes */
8981 0, /* oplock_request */
8982 NULL, /* lease */
8983 0, /* allocation_size */
8984 0, /* private_flags */
8985 NULL, /* sd */
8986 NULL, /* ea_list */
8987 &fsp, /* result */
8988 &info, /* pinfo */
8989 posx, /* in_context_blobs */
8990 NULL); /* out_context_blobs */
8992 TALLOC_FREE(posx);
8994 if (!NT_STATUS_IS_OK(status)) {
8995 return status;
8999 * Don't lie to client. If we can't really delete due to
9000 * non-POSIX opens return SHARING_VIOLATION.
9003 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
9004 if (lck == NULL) {
9005 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
9006 "lock for file %s\n", fsp_str_dbg(fsp)));
9007 close_file(req, fsp, NORMAL_CLOSE);
9008 return NT_STATUS_INVALID_PARAMETER;
9011 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
9012 if (other_nonposix_opens) {
9013 /* Fail with sharing violation. */
9014 TALLOC_FREE(lck);
9015 close_file(req, fsp, NORMAL_CLOSE);
9016 return NT_STATUS_SHARING_VIOLATION;
9020 * Set the delete on close.
9022 status = smb_set_file_disposition_info(conn,
9023 &del,
9025 fsp,
9026 smb_fname);
9028 TALLOC_FREE(lck);
9030 if (!NT_STATUS_IS_OK(status)) {
9031 close_file(req, fsp, NORMAL_CLOSE);
9032 return status;
9034 return close_file(req, fsp, NORMAL_CLOSE);
9037 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
9038 struct smb_request *req,
9039 TALLOC_CTX *mem_ctx,
9040 uint16_t info_level,
9041 struct smb_filename *smb_fname,
9042 files_struct *fsp,
9043 char **ppdata,
9044 int total_data,
9045 int *ret_data_size)
9047 char *pdata = *ppdata;
9048 NTSTATUS status = NT_STATUS_OK;
9049 int data_return_size = 0;
9051 *ret_data_size = 0;
9053 if (!CAN_WRITE(conn)) {
9054 /* Allow POSIX opens. The open path will deny
9055 * any non-readonly opens. */
9056 if (info_level != SMB_POSIX_PATH_OPEN) {
9057 return NT_STATUS_DOS(ERRSRV, ERRaccess);
9061 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
9062 smb_fname_str_dbg(smb_fname),
9063 fsp_fnum_dbg(fsp),
9064 info_level,
9065 total_data);
9067 switch (info_level) {
9068 case SMB_SET_FILE_UNIX_BASIC:
9070 status = smb_set_file_unix_basic(conn, req,
9071 pdata,
9072 total_data,
9073 fsp,
9074 smb_fname);
9075 break;
9078 case SMB_SET_FILE_UNIX_INFO2:
9080 status = smb_set_file_unix_info2(conn, req,
9081 pdata,
9082 total_data,
9083 fsp,
9084 smb_fname);
9085 break;
9088 case SMB_SET_FILE_UNIX_LINK:
9090 if (smb_fname == NULL) {
9091 /* We must have a pathname for this. */
9092 return NT_STATUS_INVALID_LEVEL;
9094 status = smb_set_file_unix_link(conn, req, pdata,
9095 total_data, smb_fname);
9096 break;
9099 case SMB_SET_FILE_UNIX_HLINK:
9101 if (smb_fname == NULL) {
9102 /* We must have a pathname for this. */
9103 return NT_STATUS_INVALID_LEVEL;
9105 status = smb_set_file_unix_hlink(conn, req,
9106 pdata, total_data,
9107 smb_fname);
9108 break;
9111 #if defined(HAVE_POSIX_ACLS)
9112 case SMB_SET_POSIX_ACL:
9114 status = smb_set_posix_acl(conn,
9115 req,
9116 pdata,
9117 total_data,
9118 fsp,
9119 smb_fname);
9120 break;
9122 #endif
9124 case SMB_SET_POSIX_LOCK:
9126 if (fsp == NULL) {
9127 return NT_STATUS_INVALID_LEVEL;
9129 status = smb_set_posix_lock(conn, req,
9130 pdata, total_data, fsp);
9131 break;
9134 case SMB_POSIX_PATH_OPEN:
9136 if (smb_fname == NULL) {
9137 /* We must have a pathname for this. */
9138 return NT_STATUS_INVALID_LEVEL;
9141 status = smb_posix_open(conn, req,
9142 ppdata,
9143 total_data,
9144 smb_fname,
9145 &data_return_size);
9146 break;
9149 case SMB_POSIX_PATH_UNLINK:
9151 if (smb_fname == NULL) {
9152 /* We must have a pathname for this. */
9153 return NT_STATUS_INVALID_LEVEL;
9156 status = smb_posix_unlink(conn, req,
9157 pdata,
9158 total_data,
9159 smb_fname);
9160 break;
9163 default:
9164 return NT_STATUS_INVALID_LEVEL;
9167 if (!NT_STATUS_IS_OK(status)) {
9168 return status;
9171 *ret_data_size = data_return_size;
9172 return NT_STATUS_OK;
9175 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
9176 struct smb_request *req,
9177 TALLOC_CTX *mem_ctx,
9178 uint16_t info_level,
9179 files_struct *fsp,
9180 struct smb_filename *smb_fname,
9181 char **ppdata, int total_data,
9182 int *ret_data_size)
9184 char *pdata = *ppdata;
9185 NTSTATUS status = NT_STATUS_OK;
9186 int data_return_size = 0;
9188 if (INFO_LEVEL_IS_UNIX(info_level)) {
9189 if (!lp_unix_extensions()) {
9190 return NT_STATUS_INVALID_LEVEL;
9193 status = smbd_do_posix_setfilepathinfo(conn,
9194 req,
9195 req,
9196 info_level,
9197 smb_fname,
9198 fsp,
9199 ppdata,
9200 total_data,
9201 &data_return_size);
9202 if (!NT_STATUS_IS_OK(status)) {
9203 return status;
9205 *ret_data_size = data_return_size;
9206 return NT_STATUS_OK;
9209 *ret_data_size = 0;
9211 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9212 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9213 fsp_fnum_dbg(fsp),
9214 info_level, total_data));
9216 switch (info_level) {
9218 case SMB_INFO_STANDARD:
9220 status = smb_set_info_standard(conn,
9221 pdata,
9222 total_data,
9223 fsp,
9224 smb_fname);
9225 break;
9228 case SMB_INFO_SET_EA:
9230 status = smb_info_set_ea(conn,
9231 pdata,
9232 total_data,
9233 fsp,
9234 smb_fname);
9235 break;
9238 case SMB_SET_FILE_BASIC_INFO:
9239 case SMB_FILE_BASIC_INFORMATION:
9241 status = smb_set_file_basic_info(conn,
9242 pdata,
9243 total_data,
9244 fsp,
9245 smb_fname);
9246 break;
9249 case SMB_FILE_ALLOCATION_INFORMATION:
9250 case SMB_SET_FILE_ALLOCATION_INFO:
9252 status = smb_set_file_allocation_info(conn, req,
9253 pdata,
9254 total_data,
9255 fsp,
9256 smb_fname);
9257 break;
9260 case SMB_FILE_END_OF_FILE_INFORMATION:
9261 case SMB_SET_FILE_END_OF_FILE_INFO:
9264 * XP/Win7 both fail after the createfile with
9265 * SMB_SET_FILE_END_OF_FILE_INFO but not
9266 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9267 * The level is known here, so pass it down
9268 * appropriately.
9270 bool should_fail =
9271 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9273 status = smb_set_file_end_of_file_info(conn, req,
9274 pdata,
9275 total_data,
9276 fsp,
9277 smb_fname,
9278 should_fail);
9279 break;
9282 case SMB_FILE_DISPOSITION_INFORMATION:
9283 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9285 #if 0
9286 /* JRA - We used to just ignore this on a path ?
9287 * Shouldn't this be invalid level on a pathname
9288 * based call ?
9290 if (tran_call != TRANSACT2_SETFILEINFO) {
9291 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9293 #endif
9294 status = smb_set_file_disposition_info(conn,
9295 pdata,
9296 total_data,
9297 fsp,
9298 smb_fname);
9299 break;
9302 case SMB_FILE_POSITION_INFORMATION:
9304 status = smb_file_position_information(conn,
9305 pdata,
9306 total_data,
9307 fsp);
9308 break;
9311 case SMB_FILE_FULL_EA_INFORMATION:
9313 status = smb_set_file_full_ea_info(conn,
9314 pdata,
9315 total_data,
9316 fsp);
9317 break;
9320 /* From tridge Samba4 :
9321 * MODE_INFORMATION in setfileinfo (I have no
9322 * idea what "mode information" on a file is - it takes a value of 0,
9323 * 2, 4 or 6. What could it be?).
9326 case SMB_FILE_MODE_INFORMATION:
9328 status = smb_file_mode_information(conn,
9329 pdata,
9330 total_data);
9331 break;
9334 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9335 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9336 case SMB_FILE_SHORT_NAME_INFORMATION:
9337 return NT_STATUS_NOT_SUPPORTED;
9339 case SMB_FILE_RENAME_INFORMATION:
9341 status = smb_file_rename_information(conn, req,
9342 pdata, total_data,
9343 fsp, smb_fname);
9344 break;
9347 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9349 /* SMB2 rename information. */
9350 status = smb2_file_rename_information(conn, req,
9351 pdata, total_data,
9352 fsp, smb_fname);
9353 break;
9356 case SMB_FILE_LINK_INFORMATION:
9358 status = smb_file_link_information(conn, req,
9359 pdata, total_data,
9360 fsp, smb_fname);
9361 break;
9364 default:
9365 return NT_STATUS_INVALID_LEVEL;
9368 if (!NT_STATUS_IS_OK(status)) {
9369 return status;
9372 *ret_data_size = data_return_size;
9373 return NT_STATUS_OK;
9376 /****************************************************************************
9377 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9378 ****************************************************************************/
9380 static void call_trans2setfilepathinfo(connection_struct *conn,
9381 struct smb_request *req,
9382 unsigned int tran_call,
9383 char **pparams, int total_params,
9384 char **ppdata, int total_data,
9385 unsigned int max_data_bytes)
9387 char *params = *pparams;
9388 char *pdata = *ppdata;
9389 uint16_t info_level;
9390 struct smb_filename *smb_fname = NULL;
9391 files_struct *fsp = NULL;
9392 NTSTATUS status = NT_STATUS_OK;
9393 int data_return_size = 0;
9395 if (!params) {
9396 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9397 return;
9400 if (tran_call == TRANSACT2_SETFILEINFO) {
9401 if (total_params < 4) {
9402 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9403 return;
9406 fsp = file_fsp(req, SVAL(params,0));
9407 /* Basic check for non-null fsp. */
9408 if (!check_fsp_open(conn, req, fsp)) {
9409 return;
9411 info_level = SVAL(params,2);
9413 smb_fname = fsp->fsp_name;
9415 if (fsp_get_pathref_fd(fsp) == -1) {
9417 * This is actually a SETFILEINFO on a directory
9418 * handle (returned from an NT SMB). NT5.0 seems
9419 * to do this call. JRA.
9421 if (INFO_LEVEL_IS_UNIX(info_level)) {
9422 /* Always do lstat for UNIX calls. */
9423 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9424 DEBUG(3,("call_trans2setfilepathinfo: "
9425 "SMB_VFS_LSTAT of %s failed "
9426 "(%s)\n",
9427 smb_fname_str_dbg(smb_fname),
9428 strerror(errno)));
9429 reply_nterror(req, map_nt_error_from_unix(errno));
9430 return;
9432 } else {
9433 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9434 DEBUG(3,("call_trans2setfilepathinfo: "
9435 "fileinfo of %s failed (%s)\n",
9436 smb_fname_str_dbg(smb_fname),
9437 strerror(errno)));
9438 reply_nterror(req, map_nt_error_from_unix(errno));
9439 return;
9442 } else if (fsp->print_file) {
9444 * Doing a DELETE_ON_CLOSE should cancel a print job.
9446 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9447 uint32_t new_private_options =
9448 fh_get_private_options(fsp->fh);
9449 new_private_options |=
9450 NTCREATEX_FLAG_DELETE_ON_CLOSE;
9451 fh_set_private_options(fsp->fh,
9452 new_private_options);
9454 DEBUG(3,("call_trans2setfilepathinfo: "
9455 "Cancelling print job (%s)\n",
9456 fsp_str_dbg(fsp)));
9458 SSVAL(params,0,0);
9459 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9460 *ppdata, 0,
9461 max_data_bytes);
9462 return;
9463 } else {
9464 reply_nterror(req,
9465 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9466 return;
9468 } else {
9470 * Original code - this is an open file.
9472 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9473 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9474 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9475 strerror(errno)));
9476 reply_nterror(req, map_nt_error_from_unix(errno));
9477 return;
9480 } else {
9481 char *fname = NULL;
9482 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9484 /* set path info */
9485 if (total_params < 7) {
9486 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9487 return;
9490 info_level = SVAL(params,0);
9491 if (req->posix_pathnames) {
9492 srvstr_get_path_posix(req,
9493 params,
9494 req->flags2,
9495 &fname,
9496 &params[6],
9497 total_params - 6,
9498 STR_TERMINATE,
9499 &status);
9500 } else {
9501 srvstr_get_path(req,
9502 params,
9503 req->flags2,
9504 &fname,
9505 &params[6],
9506 total_params - 6,
9507 STR_TERMINATE,
9508 &status);
9510 if (!NT_STATUS_IS_OK(status)) {
9511 reply_nterror(req, status);
9512 return;
9515 status = filename_convert(req, conn,
9516 fname,
9517 ucf_flags,
9519 &smb_fname);
9520 if (!NT_STATUS_IS_OK(status)) {
9521 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9522 reply_botherror(req,
9523 NT_STATUS_PATH_NOT_COVERED,
9524 ERRSRV, ERRbadpath);
9525 return;
9527 reply_nterror(req, status);
9528 return;
9532 * smb_fname->fsp may be NULL if smb_fname points at a symlink
9533 * and we're in POSIX context, so be careful when using fsp
9534 * below, it can still be NULL.
9536 fsp = smb_fname->fsp;
9538 if (INFO_LEVEL_IS_UNIX(info_level)) {
9540 * For CIFS UNIX extensions the target name may not exist.
9543 /* Always do lstat for UNIX calls. */
9544 SMB_VFS_LSTAT(conn, smb_fname);
9546 } else if (!VALID_STAT(smb_fname->st) &&
9547 SMB_VFS_STAT(conn, smb_fname)) {
9548 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9549 "%s failed (%s)\n",
9550 smb_fname_str_dbg(smb_fname),
9551 strerror(errno)));
9552 reply_nterror(req, map_nt_error_from_unix(errno));
9553 return;
9557 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9558 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9559 fsp_fnum_dbg(fsp),
9560 info_level,total_data));
9562 /* Realloc the parameter size */
9563 *pparams = (char *)SMB_REALLOC(*pparams,2);
9564 if (*pparams == NULL) {
9565 reply_nterror(req, NT_STATUS_NO_MEMORY);
9566 return;
9568 params = *pparams;
9570 SSVAL(params,0,0);
9572 status = smbd_do_setfilepathinfo(conn, req, req,
9573 info_level,
9574 fsp,
9575 smb_fname,
9576 ppdata, total_data,
9577 &data_return_size);
9578 if (!NT_STATUS_IS_OK(status)) {
9579 if (open_was_deferred(req->xconn, req->mid)) {
9580 /* We have re-scheduled this call. */
9581 return;
9583 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9584 bool ok = defer_smb1_sharing_violation(req);
9585 if (ok) {
9586 return;
9589 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9590 /* We have re-scheduled this call. */
9591 return;
9593 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9594 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9595 ERRSRV, ERRbadpath);
9596 return;
9598 if (info_level == SMB_POSIX_PATH_OPEN) {
9599 reply_openerror(req, status);
9600 return;
9604 * Invalid EA name needs to return 2 param bytes,
9605 * not a zero-length error packet.
9607 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9608 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9609 max_data_bytes);
9610 } else {
9611 reply_nterror(req, status);
9613 return;
9616 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9617 max_data_bytes);
9619 return;
9622 /****************************************************************************
9623 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9624 ****************************************************************************/
9626 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9627 char **pparams, int total_params,
9628 char **ppdata, int total_data,
9629 unsigned int max_data_bytes)
9631 struct files_struct *fsp = NULL;
9632 struct smb_filename *smb_dname = NULL;
9633 char *params = *pparams;
9634 char *pdata = *ppdata;
9635 char *directory = NULL;
9636 NTSTATUS status = NT_STATUS_OK;
9637 struct ea_list *ea_list = NULL;
9638 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9639 TALLOC_CTX *ctx = talloc_tos();
9641 if (!CAN_WRITE(conn)) {
9642 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9643 return;
9646 if (total_params < 5) {
9647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9648 return;
9651 if (req->posix_pathnames) {
9652 srvstr_get_path_posix(ctx,
9653 params,
9654 req->flags2,
9655 &directory,
9656 &params[4],
9657 total_params - 4,
9658 STR_TERMINATE,
9659 &status);
9660 } else {
9661 srvstr_get_path(ctx,
9662 params,
9663 req->flags2,
9664 &directory,
9665 &params[4],
9666 total_params - 4,
9667 STR_TERMINATE,
9668 &status);
9670 if (!NT_STATUS_IS_OK(status)) {
9671 reply_nterror(req, status);
9672 return;
9675 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9677 status = filename_convert(ctx,
9678 conn,
9679 directory,
9680 ucf_flags,
9682 &smb_dname);
9684 if (!NT_STATUS_IS_OK(status)) {
9685 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9686 reply_botherror(req,
9687 NT_STATUS_PATH_NOT_COVERED,
9688 ERRSRV, ERRbadpath);
9689 return;
9691 reply_nterror(req, status);
9692 return;
9696 * OS/2 workplace shell seems to send SET_EA requests of "null"
9697 * length (4 bytes containing IVAL 4).
9698 * They seem to have no effect. Bug #3212. JRA.
9701 if (total_data && (total_data != 4)) {
9702 /* Any data in this call is an EA list. */
9703 if (total_data < 10) {
9704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9705 goto out;
9708 if (IVAL(pdata,0) > total_data) {
9709 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9710 IVAL(pdata,0), (unsigned int)total_data));
9711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9712 goto out;
9715 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9716 total_data - 4);
9717 if (!ea_list) {
9718 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9719 goto out;
9722 if (!lp_ea_support(SNUM(conn))) {
9723 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9724 goto out;
9727 /* If total_data == 4 Windows doesn't care what values
9728 * are placed in that field, it just ignores them.
9729 * The System i QNTC IBM SMB client puts bad values here,
9730 * so ignore them. */
9732 status = SMB_VFS_CREATE_FILE(
9733 conn, /* conn */
9734 req, /* req */
9735 smb_dname, /* fname */
9736 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
9737 FILE_SHARE_NONE, /* share_access */
9738 FILE_CREATE, /* create_disposition*/
9739 FILE_DIRECTORY_FILE, /* create_options */
9740 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
9741 0, /* oplock_request */
9742 NULL, /* lease */
9743 0, /* allocation_size */
9744 0, /* private_flags */
9745 NULL, /* sd */
9746 NULL, /* ea_list */
9747 &fsp, /* result */
9748 NULL, /* pinfo */
9749 NULL, NULL); /* create context */
9750 if (!NT_STATUS_IS_OK(status)) {
9751 reply_nterror(req, status);
9752 goto out;
9755 /* Try and set any given EA. */
9756 if (ea_list) {
9757 status = set_ea(conn, fsp, ea_list);
9758 if (!NT_STATUS_IS_OK(status)) {
9759 reply_nterror(req, status);
9760 goto out;
9764 /* Realloc the parameter and data sizes */
9765 *pparams = (char *)SMB_REALLOC(*pparams,2);
9766 if(*pparams == NULL) {
9767 reply_nterror(req, NT_STATUS_NO_MEMORY);
9768 goto out;
9770 params = *pparams;
9772 SSVAL(params,0,0);
9774 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9776 out:
9777 if (fsp != NULL) {
9778 close_file(NULL, fsp, NORMAL_CLOSE);
9779 fsp = NULL;
9781 TALLOC_FREE(smb_dname);
9782 return;
9785 /****************************************************************************
9786 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9787 We don't actually do this - we just send a null response.
9788 ****************************************************************************/
9790 static void call_trans2findnotifyfirst(connection_struct *conn,
9791 struct smb_request *req,
9792 char **pparams, int total_params,
9793 char **ppdata, int total_data,
9794 unsigned int max_data_bytes)
9796 char *params = *pparams;
9797 uint16_t info_level;
9799 if (total_params < 6) {
9800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9801 return;
9804 info_level = SVAL(params,4);
9805 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9807 switch (info_level) {
9808 case 1:
9809 case 2:
9810 break;
9811 default:
9812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9813 return;
9816 /* Realloc the parameter and data sizes */
9817 *pparams = (char *)SMB_REALLOC(*pparams,6);
9818 if (*pparams == NULL) {
9819 reply_nterror(req, NT_STATUS_NO_MEMORY);
9820 return;
9822 params = *pparams;
9824 SSVAL(params,0,fnf_handle);
9825 SSVAL(params,2,0); /* No changes */
9826 SSVAL(params,4,0); /* No EA errors */
9828 fnf_handle++;
9830 if(fnf_handle == 0)
9831 fnf_handle = 257;
9833 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9835 return;
9838 /****************************************************************************
9839 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9840 changes). Currently this does nothing.
9841 ****************************************************************************/
9843 static void call_trans2findnotifynext(connection_struct *conn,
9844 struct smb_request *req,
9845 char **pparams, int total_params,
9846 char **ppdata, int total_data,
9847 unsigned int max_data_bytes)
9849 char *params = *pparams;
9851 DEBUG(3,("call_trans2findnotifynext\n"));
9853 /* Realloc the parameter and data sizes */
9854 *pparams = (char *)SMB_REALLOC(*pparams,4);
9855 if (*pparams == NULL) {
9856 reply_nterror(req, NT_STATUS_NO_MEMORY);
9857 return;
9859 params = *pparams;
9861 SSVAL(params,0,0); /* No changes */
9862 SSVAL(params,2,0); /* No EA errors */
9864 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9866 return;
9869 /****************************************************************************
9870 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9871 ****************************************************************************/
9873 static void call_trans2getdfsreferral(connection_struct *conn,
9874 struct smb_request *req,
9875 char **pparams, int total_params,
9876 char **ppdata, int total_data,
9877 unsigned int max_data_bytes)
9879 char *params = *pparams;
9880 char *pathname = NULL;
9881 int reply_size = 0;
9882 int max_referral_level;
9883 NTSTATUS status = NT_STATUS_OK;
9884 TALLOC_CTX *ctx = talloc_tos();
9886 DEBUG(10,("call_trans2getdfsreferral\n"));
9888 if (total_params < 3) {
9889 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9890 return;
9893 max_referral_level = SVAL(params,0);
9895 if(!lp_host_msdfs()) {
9896 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9897 return;
9900 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9901 total_params - 2, STR_TERMINATE);
9902 if (!pathname) {
9903 reply_nterror(req, NT_STATUS_NOT_FOUND);
9904 return;
9906 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9907 ppdata,&status)) < 0) {
9908 reply_nterror(req, status);
9909 return;
9912 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9913 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9914 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9916 return;
9919 #define LMCAT_SPL 0x53
9920 #define LMFUNC_GETJOBID 0x60
9922 /****************************************************************************
9923 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9924 ****************************************************************************/
9926 static void call_trans2ioctl(connection_struct *conn,
9927 struct smb_request *req,
9928 char **pparams, int total_params,
9929 char **ppdata, int total_data,
9930 unsigned int max_data_bytes)
9932 const struct loadparm_substitution *lp_sub =
9933 loadparm_s3_global_substitution();
9934 char *pdata = *ppdata;
9935 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9936 NTSTATUS status;
9937 size_t len = 0;
9939 /* check for an invalid fid before proceeding */
9941 if (!fsp) {
9942 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9943 return;
9946 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9947 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9948 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9949 if (*ppdata == NULL) {
9950 reply_nterror(req, NT_STATUS_NO_MEMORY);
9951 return;
9953 pdata = *ppdata;
9955 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9956 CAN ACCEPT THIS IN UNICODE. JRA. */
9958 /* Job number */
9959 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9961 status = srvstr_push(pdata, req->flags2, pdata + 2,
9962 lp_netbios_name(), 15,
9963 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9964 if (!NT_STATUS_IS_OK(status)) {
9965 reply_nterror(req, status);
9966 return;
9968 status = srvstr_push(pdata, req->flags2, pdata+18,
9969 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9970 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9971 if (!NT_STATUS_IS_OK(status)) {
9972 reply_nterror(req, status);
9973 return;
9975 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9976 max_data_bytes);
9977 return;
9980 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9981 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9984 /****************************************************************************
9985 Reply to a SMBfindclose (stop trans2 directory search).
9986 ****************************************************************************/
9988 void reply_findclose(struct smb_request *req)
9990 int dptr_num;
9991 struct smbd_server_connection *sconn = req->sconn;
9992 files_struct *fsp = NULL;
9994 START_PROFILE(SMBfindclose);
9996 if (req->wct < 1) {
9997 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9998 END_PROFILE(SMBfindclose);
9999 return;
10002 dptr_num = SVALS(req->vwv+0, 0);
10004 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
10007 * OS/2 seems to use -1 to indicate "close all directories"
10008 * This has to mean on this specific connection struct.
10010 if (dptr_num == -1) {
10011 dptr_closecnum(req->conn);
10012 } else {
10013 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
10014 dptr_num = -1;
10015 if (fsp != NULL) {
10016 close_file(NULL, fsp, NORMAL_CLOSE);
10017 fsp = NULL;
10021 reply_outbuf(req, 0, 0);
10023 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
10025 END_PROFILE(SMBfindclose);
10026 return;
10029 /****************************************************************************
10030 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
10031 ****************************************************************************/
10033 void reply_findnclose(struct smb_request *req)
10035 int dptr_num;
10037 START_PROFILE(SMBfindnclose);
10039 if (req->wct < 1) {
10040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10041 END_PROFILE(SMBfindnclose);
10042 return;
10045 dptr_num = SVAL(req->vwv+0, 0);
10047 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
10049 /* We never give out valid handles for a
10050 findnotifyfirst - so any dptr_num is ok here.
10051 Just ignore it. */
10053 reply_outbuf(req, 0, 0);
10055 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
10057 END_PROFILE(SMBfindnclose);
10058 return;
10061 static void handle_trans2(connection_struct *conn, struct smb_request *req,
10062 struct trans_state *state)
10064 if (get_Protocol() >= PROTOCOL_NT1) {
10065 req->flags2 |= 0x40; /* IS_LONG_NAME */
10066 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
10069 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
10070 if (state->call != TRANSACT2_QFSINFO &&
10071 state->call != TRANSACT2_SETFSINFO) {
10072 DEBUG(0,("handle_trans2: encryption required "
10073 "with call 0x%x\n",
10074 (unsigned int)state->call));
10075 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10076 return;
10080 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
10082 /* Now we must call the relevant TRANS2 function */
10083 switch(state->call) {
10084 case TRANSACT2_OPEN:
10086 START_PROFILE(Trans2_open);
10087 call_trans2open(conn, req,
10088 &state->param, state->total_param,
10089 &state->data, state->total_data,
10090 state->max_data_return);
10091 END_PROFILE(Trans2_open);
10092 break;
10095 case TRANSACT2_FINDFIRST:
10097 START_PROFILE(Trans2_findfirst);
10098 call_trans2findfirst(conn, req,
10099 &state->param, state->total_param,
10100 &state->data, state->total_data,
10101 state->max_data_return);
10102 END_PROFILE(Trans2_findfirst);
10103 break;
10106 case TRANSACT2_FINDNEXT:
10108 START_PROFILE(Trans2_findnext);
10109 call_trans2findnext(conn, req,
10110 &state->param, state->total_param,
10111 &state->data, state->total_data,
10112 state->max_data_return);
10113 END_PROFILE(Trans2_findnext);
10114 break;
10117 case TRANSACT2_QFSINFO:
10119 START_PROFILE(Trans2_qfsinfo);
10120 call_trans2qfsinfo(conn, req,
10121 &state->param, state->total_param,
10122 &state->data, state->total_data,
10123 state->max_data_return);
10124 END_PROFILE(Trans2_qfsinfo);
10125 break;
10128 case TRANSACT2_SETFSINFO:
10130 START_PROFILE(Trans2_setfsinfo);
10131 call_trans2setfsinfo(conn, req,
10132 &state->param, state->total_param,
10133 &state->data, state->total_data,
10134 state->max_data_return);
10135 END_PROFILE(Trans2_setfsinfo);
10136 break;
10139 case TRANSACT2_QPATHINFO:
10140 case TRANSACT2_QFILEINFO:
10142 START_PROFILE(Trans2_qpathinfo);
10143 call_trans2qfilepathinfo(conn, req, state->call,
10144 &state->param, state->total_param,
10145 &state->data, state->total_data,
10146 state->max_data_return);
10147 END_PROFILE(Trans2_qpathinfo);
10148 break;
10151 case TRANSACT2_SETPATHINFO:
10152 case TRANSACT2_SETFILEINFO:
10154 START_PROFILE(Trans2_setpathinfo);
10155 call_trans2setfilepathinfo(conn, req, state->call,
10156 &state->param, state->total_param,
10157 &state->data, state->total_data,
10158 state->max_data_return);
10159 END_PROFILE(Trans2_setpathinfo);
10160 break;
10163 case TRANSACT2_FINDNOTIFYFIRST:
10165 START_PROFILE(Trans2_findnotifyfirst);
10166 call_trans2findnotifyfirst(conn, req,
10167 &state->param, state->total_param,
10168 &state->data, state->total_data,
10169 state->max_data_return);
10170 END_PROFILE(Trans2_findnotifyfirst);
10171 break;
10174 case TRANSACT2_FINDNOTIFYNEXT:
10176 START_PROFILE(Trans2_findnotifynext);
10177 call_trans2findnotifynext(conn, req,
10178 &state->param, state->total_param,
10179 &state->data, state->total_data,
10180 state->max_data_return);
10181 END_PROFILE(Trans2_findnotifynext);
10182 break;
10185 case TRANSACT2_MKDIR:
10187 START_PROFILE(Trans2_mkdir);
10188 call_trans2mkdir(conn, req,
10189 &state->param, state->total_param,
10190 &state->data, state->total_data,
10191 state->max_data_return);
10192 END_PROFILE(Trans2_mkdir);
10193 break;
10196 case TRANSACT2_GET_DFS_REFERRAL:
10198 START_PROFILE(Trans2_get_dfs_referral);
10199 call_trans2getdfsreferral(conn, req,
10200 &state->param, state->total_param,
10201 &state->data, state->total_data,
10202 state->max_data_return);
10203 END_PROFILE(Trans2_get_dfs_referral);
10204 break;
10207 case TRANSACT2_IOCTL:
10209 START_PROFILE(Trans2_ioctl);
10210 call_trans2ioctl(conn, req,
10211 &state->param, state->total_param,
10212 &state->data, state->total_data,
10213 state->max_data_return);
10214 END_PROFILE(Trans2_ioctl);
10215 break;
10218 default:
10219 /* Error in request */
10220 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10221 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10225 /****************************************************************************
10226 Reply to a SMBtrans2.
10227 ****************************************************************************/
10229 void reply_trans2(struct smb_request *req)
10231 connection_struct *conn = req->conn;
10232 unsigned int dsoff;
10233 unsigned int dscnt;
10234 unsigned int psoff;
10235 unsigned int pscnt;
10236 unsigned int tran_call;
10237 struct trans_state *state;
10238 NTSTATUS result;
10240 START_PROFILE(SMBtrans2);
10242 if (req->wct < 14) {
10243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10244 END_PROFILE(SMBtrans2);
10245 return;
10248 dsoff = SVAL(req->vwv+12, 0);
10249 dscnt = SVAL(req->vwv+11, 0);
10250 psoff = SVAL(req->vwv+10, 0);
10251 pscnt = SVAL(req->vwv+9, 0);
10252 tran_call = SVAL(req->vwv+14, 0);
10254 result = allow_new_trans(conn->pending_trans, req->mid);
10255 if (!NT_STATUS_IS_OK(result)) {
10256 DEBUG(2, ("Got invalid trans2 request: %s\n",
10257 nt_errstr(result)));
10258 reply_nterror(req, result);
10259 END_PROFILE(SMBtrans2);
10260 return;
10263 if (IS_IPC(conn)) {
10264 switch (tran_call) {
10265 /* List the allowed trans2 calls on IPC$ */
10266 case TRANSACT2_OPEN:
10267 case TRANSACT2_GET_DFS_REFERRAL:
10268 case TRANSACT2_QFILEINFO:
10269 case TRANSACT2_QFSINFO:
10270 case TRANSACT2_SETFSINFO:
10271 break;
10272 default:
10273 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10274 END_PROFILE(SMBtrans2);
10275 return;
10279 if ((state = talloc(conn, struct trans_state)) == NULL) {
10280 DEBUG(0, ("talloc failed\n"));
10281 reply_nterror(req, NT_STATUS_NO_MEMORY);
10282 END_PROFILE(SMBtrans2);
10283 return;
10286 state->cmd = SMBtrans2;
10288 state->mid = req->mid;
10289 state->vuid = req->vuid;
10290 state->setup_count = SVAL(req->vwv+13, 0);
10291 state->setup = NULL;
10292 state->total_param = SVAL(req->vwv+0, 0);
10293 state->param = NULL;
10294 state->total_data = SVAL(req->vwv+1, 0);
10295 state->data = NULL;
10296 state->max_param_return = SVAL(req->vwv+2, 0);
10297 state->max_data_return = SVAL(req->vwv+3, 0);
10298 state->max_setup_return = SVAL(req->vwv+4, 0);
10299 state->close_on_completion = BITSETW(req->vwv+5, 0);
10300 state->one_way = BITSETW(req->vwv+5, 1);
10302 state->call = tran_call;
10304 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10305 is so as a sanity check */
10306 if (state->setup_count != 1) {
10308 * Need to have rc=0 for ioctl to get job id for OS/2.
10309 * Network printing will fail if function is not successful.
10310 * Similar function in reply.c will be used if protocol
10311 * is LANMAN1.0 instead of LM1.2X002.
10312 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10313 * outbuf doesn't have to be set(only job id is used).
10315 if ( (state->setup_count == 4)
10316 && (tran_call == TRANSACT2_IOCTL)
10317 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10318 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10319 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10320 } else {
10321 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10322 DEBUG(2,("Transaction is %d\n",tran_call));
10323 TALLOC_FREE(state);
10324 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10325 END_PROFILE(SMBtrans2);
10326 return;
10330 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10331 goto bad_param;
10333 if (state->total_data) {
10335 if (trans_oob(state->total_data, 0, dscnt)
10336 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10337 goto bad_param;
10340 /* Can't use talloc here, the core routines do realloc on the
10341 * params and data. */
10342 state->data = (char *)SMB_MALLOC(state->total_data);
10343 if (state->data == NULL) {
10344 DEBUG(0,("reply_trans2: data malloc fail for %u "
10345 "bytes !\n", (unsigned int)state->total_data));
10346 TALLOC_FREE(state);
10347 reply_nterror(req, NT_STATUS_NO_MEMORY);
10348 END_PROFILE(SMBtrans2);
10349 return;
10352 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10355 if (state->total_param) {
10357 if (trans_oob(state->total_param, 0, pscnt)
10358 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10359 goto bad_param;
10362 /* Can't use talloc here, the core routines do realloc on the
10363 * params and data. */
10364 state->param = (char *)SMB_MALLOC(state->total_param);
10365 if (state->param == NULL) {
10366 DEBUG(0,("reply_trans: param malloc fail for %u "
10367 "bytes !\n", (unsigned int)state->total_param));
10368 SAFE_FREE(state->data);
10369 TALLOC_FREE(state);
10370 reply_nterror(req, NT_STATUS_NO_MEMORY);
10371 END_PROFILE(SMBtrans2);
10372 return;
10375 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10378 state->received_data = dscnt;
10379 state->received_param = pscnt;
10381 if ((state->received_param == state->total_param) &&
10382 (state->received_data == state->total_data)) {
10384 handle_trans2(conn, req, state);
10386 SAFE_FREE(state->data);
10387 SAFE_FREE(state->param);
10388 TALLOC_FREE(state);
10389 END_PROFILE(SMBtrans2);
10390 return;
10393 DLIST_ADD(conn->pending_trans, state);
10395 /* We need to send an interim response then receive the rest
10396 of the parameter/data bytes */
10397 reply_outbuf(req, 0, 0);
10398 show_msg((char *)req->outbuf);
10399 END_PROFILE(SMBtrans2);
10400 return;
10402 bad_param:
10404 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10405 SAFE_FREE(state->data);
10406 SAFE_FREE(state->param);
10407 TALLOC_FREE(state);
10408 END_PROFILE(SMBtrans2);
10409 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10413 /****************************************************************************
10414 Reply to a SMBtranss2
10415 ****************************************************************************/
10417 void reply_transs2(struct smb_request *req)
10419 connection_struct *conn = req->conn;
10420 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10421 struct trans_state *state;
10423 START_PROFILE(SMBtranss2);
10425 show_msg((const char *)req->inbuf);
10427 /* Windows clients expect all replies to
10428 a transact secondary (SMBtranss2 0x33)
10429 to have a command code of transact
10430 (SMBtrans2 0x32). See bug #8989
10431 and also [MS-CIFS] section 2.2.4.47.2
10432 for details.
10434 req->cmd = SMBtrans2;
10436 if (req->wct < 8) {
10437 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10438 END_PROFILE(SMBtranss2);
10439 return;
10442 for (state = conn->pending_trans; state != NULL;
10443 state = state->next) {
10444 if (state->mid == req->mid) {
10445 break;
10449 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10450 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10451 END_PROFILE(SMBtranss2);
10452 return;
10455 /* Revise state->total_param and state->total_data in case they have
10456 changed downwards */
10458 if (SVAL(req->vwv+0, 0) < state->total_param)
10459 state->total_param = SVAL(req->vwv+0, 0);
10460 if (SVAL(req->vwv+1, 0) < state->total_data)
10461 state->total_data = SVAL(req->vwv+1, 0);
10463 pcnt = SVAL(req->vwv+2, 0);
10464 poff = SVAL(req->vwv+3, 0);
10465 pdisp = SVAL(req->vwv+4, 0);
10467 dcnt = SVAL(req->vwv+5, 0);
10468 doff = SVAL(req->vwv+6, 0);
10469 ddisp = SVAL(req->vwv+7, 0);
10471 state->received_param += pcnt;
10472 state->received_data += dcnt;
10474 if ((state->received_data > state->total_data) ||
10475 (state->received_param > state->total_param))
10476 goto bad_param;
10478 if (pcnt) {
10479 if (trans_oob(state->total_param, pdisp, pcnt)
10480 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10481 goto bad_param;
10483 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10486 if (dcnt) {
10487 if (trans_oob(state->total_data, ddisp, dcnt)
10488 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10489 goto bad_param;
10491 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10494 if ((state->received_param < state->total_param) ||
10495 (state->received_data < state->total_data)) {
10496 END_PROFILE(SMBtranss2);
10497 return;
10500 handle_trans2(conn, req, state);
10502 DLIST_REMOVE(conn->pending_trans, state);
10503 SAFE_FREE(state->data);
10504 SAFE_FREE(state->param);
10505 TALLOC_FREE(state);
10507 END_PROFILE(SMBtranss2);
10508 return;
10510 bad_param:
10512 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10513 DLIST_REMOVE(conn->pending_trans, state);
10514 SAFE_FREE(state->data);
10515 SAFE_FREE(state->param);
10516 TALLOC_FREE(state);
10517 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10518 END_PROFILE(SMBtranss2);
10519 return;