s3/smbd: Adjust estimate_ea_size to take files_struct alone
[Samba.git] / source3 / smbd / trans2.c
blob87bb3d48a61bfa194ed36581d31f6670e58005a6
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 connection_struct *conn,
296 files_struct *fsp,
297 char ***pnames,
298 size_t *pnum_names)
300 char smallbuf[1024];
301 /* Get a list of all xattrs. Max namesize is 64k. */
302 size_t ea_namelist_size = 1024;
303 char *ea_namelist = smallbuf;
304 char *to_free = NULL;
306 char *p;
307 char **names;
308 size_t num_names;
309 ssize_t sizeret = -1;
310 NTSTATUS status;
312 if (pnames) {
313 *pnames = NULL;
315 *pnum_names = 0;
317 if (fsp == NULL) {
319 * Callers may pass fsp == NULL when passing smb_fname->fsp of a
320 * symlink. This is ok, handle it here, by just return no EA's
321 * on a symlink.
323 return NT_STATUS_OK;
326 /* should be the case that fsp != NULL */
327 SMB_ASSERT(fsp != NULL);
329 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
330 ea_namelist_size);
332 if ((sizeret == -1) && (errno == ERANGE)) {
333 ea_namelist_size = 65536;
334 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
335 if (ea_namelist == NULL) {
336 return NT_STATUS_NO_MEMORY;
338 to_free = ea_namelist;
340 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
341 ea_namelist_size);
344 if (sizeret == -1) {
345 status = map_nt_error_from_unix(errno);
346 TALLOC_FREE(to_free);
347 return status;
350 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
352 if (sizeret == 0) {
353 TALLOC_FREE(to_free);
354 return NT_STATUS_OK;
358 * Ensure the result is 0-terminated
361 if (ea_namelist[sizeret-1] != '\0') {
362 TALLOC_FREE(to_free);
363 return NT_STATUS_INTERNAL_ERROR;
367 * count the names
369 num_names = 0;
371 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
372 num_names += 1;
375 *pnum_names = num_names;
377 if (pnames == NULL) {
378 TALLOC_FREE(to_free);
379 return NT_STATUS_OK;
382 names = talloc_array(mem_ctx, char *, num_names);
383 if (names == NULL) {
384 DEBUG(0, ("talloc failed\n"));
385 TALLOC_FREE(to_free);
386 return NT_STATUS_NO_MEMORY;
389 if (ea_namelist == smallbuf) {
390 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
391 if (ea_namelist == NULL) {
392 TALLOC_FREE(names);
393 return NT_STATUS_NO_MEMORY;
395 } else {
396 talloc_steal(names, ea_namelist);
398 ea_namelist = talloc_realloc(names, ea_namelist, char,
399 sizeret);
400 if (ea_namelist == NULL) {
401 TALLOC_FREE(names);
402 return NT_STATUS_NO_MEMORY;
406 num_names = 0;
408 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
409 names[num_names++] = p;
412 *pnames = names;
414 return NT_STATUS_OK;
417 /****************************************************************************
418 Return a linked list of the total EA's. Plus the total size
419 ****************************************************************************/
421 static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
422 files_struct *fsp,
423 size_t *pea_total_len,
424 struct ea_list **ea_list)
426 /* Get a list of all xattrs. Max namesize is 64k. */
427 size_t i, num_names;
428 char **names;
429 struct ea_list *ea_list_head = NULL;
430 bool posix_pathnames = false;
431 NTSTATUS status;
433 *pea_total_len = 0;
434 *ea_list = NULL;
436 /* symlink */
437 if (fsp == NULL) {
438 return NT_STATUS_OK;
441 if (!lp_ea_support(SNUM(fsp->conn))) {
442 return NT_STATUS_OK;
445 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
446 return NT_STATUS_INVALID_PARAMETER;
449 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
451 status = get_ea_names_from_file(talloc_tos(),
452 fsp->conn,
453 fsp,
454 &names,
455 &num_names);
457 if (!NT_STATUS_IS_OK(status)) {
458 return status;
461 if (num_names == 0) {
462 return NT_STATUS_OK;
465 for (i=0; i<num_names; i++) {
466 struct ea_list *listp;
467 fstring dos_ea_name;
469 if (strnequal(names[i], "system.", 7)
470 || samba_private_attr_name(names[i]))
471 continue;
474 * Filter out any underlying POSIX EA names
475 * that a Windows client can't handle.
477 if (!posix_pathnames &&
478 is_invalid_windows_ea_name(names[i])) {
479 continue;
482 listp = talloc(mem_ctx, struct ea_list);
483 if (listp == NULL) {
484 return NT_STATUS_NO_MEMORY;
487 status = get_ea_value(listp,
488 fsp->conn,
489 fsp,
490 fsp->fsp_name,
491 names[i],
492 &listp->ea);
494 if (!NT_STATUS_IS_OK(status)) {
495 TALLOC_FREE(listp);
496 return status;
499 if (listp->ea.value.length == 0) {
501 * We can never return a zero length EA.
502 * Windows reports the EA's as corrupted.
504 TALLOC_FREE(listp);
505 continue;
508 push_ascii_fstring(dos_ea_name, listp->ea.name);
510 *pea_total_len +=
511 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
513 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
514 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
515 (unsigned int)listp->ea.value.length));
517 DLIST_ADD_END(ea_list_head, listp);
521 /* Add on 4 for total length. */
522 if (*pea_total_len) {
523 *pea_total_len += 4;
526 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
527 (unsigned int)*pea_total_len));
529 *ea_list = ea_list_head;
530 return NT_STATUS_OK;
533 /****************************************************************************
534 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
535 that was filled.
536 ****************************************************************************/
538 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
539 connection_struct *conn, struct ea_list *ea_list)
541 unsigned int ret_data_size = 4;
542 char *p = pdata;
544 SMB_ASSERT(total_data_size >= 4);
546 if (!lp_ea_support(SNUM(conn))) {
547 SIVAL(pdata,4,0);
548 return 4;
551 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
552 size_t dos_namelen;
553 fstring dos_ea_name;
554 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
555 dos_namelen = strlen(dos_ea_name);
556 if (dos_namelen > 255 || dos_namelen == 0) {
557 break;
559 if (ea_list->ea.value.length > 65535) {
560 break;
562 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
563 break;
566 /* We know we have room. */
567 SCVAL(p,0,ea_list->ea.flags);
568 SCVAL(p,1,dos_namelen);
569 SSVAL(p,2,ea_list->ea.value.length);
570 strlcpy(p+4, dos_ea_name, dos_namelen+1);
571 if (ea_list->ea.value.length > 0) {
572 memcpy(p + 4 + dos_namelen + 1,
573 ea_list->ea.value.data,
574 ea_list->ea.value.length);
577 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
578 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
581 ret_data_size = PTR_DIFF(p, pdata);
582 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
583 SIVAL(pdata,0,ret_data_size);
584 return ret_data_size;
587 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
588 char *pdata,
589 unsigned int total_data_size,
590 unsigned int *ret_data_size,
591 connection_struct *conn,
592 struct ea_list *ea_list)
594 uint8_t *p = (uint8_t *)pdata;
595 uint8_t *last_start = NULL;
596 bool do_store_data = (pdata != NULL);
598 *ret_data_size = 0;
600 if (!lp_ea_support(SNUM(conn))) {
601 return NT_STATUS_NO_EAS_ON_FILE;
604 for (; ea_list; ea_list = ea_list->next) {
605 size_t dos_namelen;
606 fstring dos_ea_name;
607 size_t this_size;
608 size_t pad = 0;
610 if (last_start != NULL && do_store_data) {
611 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
613 last_start = p;
615 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
616 dos_namelen = strlen(dos_ea_name);
617 if (dos_namelen > 255 || dos_namelen == 0) {
618 return NT_STATUS_INTERNAL_ERROR;
620 if (ea_list->ea.value.length > 65535) {
621 return NT_STATUS_INTERNAL_ERROR;
624 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
626 if (ea_list->next) {
627 pad = (4 - (this_size % 4)) % 4;
628 this_size += pad;
631 if (do_store_data) {
632 if (this_size > total_data_size) {
633 return NT_STATUS_INFO_LENGTH_MISMATCH;
636 /* We know we have room. */
637 SIVAL(p, 0x00, 0); /* next offset */
638 SCVAL(p, 0x04, ea_list->ea.flags);
639 SCVAL(p, 0x05, dos_namelen);
640 SSVAL(p, 0x06, ea_list->ea.value.length);
641 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
642 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
643 if (pad) {
644 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
645 '\0',
646 pad);
648 total_data_size -= this_size;
651 p += this_size;
654 *ret_data_size = PTR_DIFF(p, pdata);
655 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
656 return NT_STATUS_OK;
659 static unsigned int estimate_ea_size(files_struct *fsp)
661 size_t total_ea_len = 0;
662 TALLOC_CTX *mem_ctx;
663 struct ea_list *ea_list = NULL;
664 NTSTATUS status;
666 /* symlink */
667 if (fsp == NULL) {
668 return 0;
671 mem_ctx = talloc_stackframe();
672 if (!lp_ea_support(SNUM(fsp->conn))) {
673 return 0;
676 /* If this is a stream fsp, then we need to instead find the
677 * estimated ea len from the main file, not the stream
678 * (streams cannot have EAs), but the estimate isn't just 0 in
679 * this case! */
680 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
681 fsp = fsp->base_fsp;
683 (void)get_ea_list_from_fsp(mem_ctx,
684 fsp,
685 &total_ea_len,
686 &ea_list);
688 if(fsp->conn->sconn->using_smb2) {
689 unsigned int ret_data_size;
691 * We're going to be using fill_ea_chained_buffer() to
692 * marshall EA's - this size is significantly larger
693 * than the SMB1 buffer. Re-calculate the size without
694 * marshalling.
696 status = fill_ea_chained_buffer(mem_ctx,
697 NULL,
699 &ret_data_size,
700 fsp->conn,
701 ea_list);
702 if (!NT_STATUS_IS_OK(status)) {
703 ret_data_size = 0;
705 total_ea_len = ret_data_size;
707 TALLOC_FREE(mem_ctx);
708 return total_ea_len;
711 /****************************************************************************
712 Ensure the EA name is case insensitive by matching any existing EA name.
713 ****************************************************************************/
715 static void canonicalize_ea_name(files_struct *fsp,
716 fstring unix_ea_name)
718 size_t total_ea_len;
719 TALLOC_CTX *mem_ctx = talloc_tos();
720 struct ea_list *ea_list;
721 NTSTATUS status = get_ea_list_from_fsp(mem_ctx,
722 fsp,
723 &total_ea_len,
724 &ea_list);
725 if (!NT_STATUS_IS_OK(status)) {
726 return;
729 for (; ea_list; ea_list = ea_list->next) {
730 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
731 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
732 &unix_ea_name[5], ea_list->ea.name));
733 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
734 break;
739 /****************************************************************************
740 Set or delete an extended attribute.
741 ****************************************************************************/
743 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
744 struct ea_list *ea_list)
746 NTSTATUS status;
747 bool posix_pathnames = false;
749 if (!lp_ea_support(SNUM(conn))) {
750 return NT_STATUS_EAS_NOT_SUPPORTED;
753 posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
755 status = refuse_symlink(conn, fsp, fsp->fsp_name);
756 if (!NT_STATUS_IS_OK(status)) {
757 return status;
760 status = check_access_fsp(fsp, FILE_WRITE_EA);
761 if (!NT_STATUS_IS_OK(status)) {
762 return status;
765 /* Setting EAs on streams isn't supported. */
766 if (is_ntfs_stream_smb_fname(fsp->fsp_name)) {
767 return NT_STATUS_INVALID_PARAMETER;
771 * Filter out invalid Windows EA names - before
772 * we set *any* of them.
775 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
776 return STATUS_INVALID_EA_NAME;
779 for (;ea_list; ea_list = ea_list->next) {
780 int ret;
781 fstring unix_ea_name;
783 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
784 fstrcat(unix_ea_name, ea_list->ea.name);
786 canonicalize_ea_name(fsp, unix_ea_name);
788 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
790 if (samba_private_attr_name(unix_ea_name)) {
791 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
792 return NT_STATUS_ACCESS_DENIED;
795 if (ea_list->ea.value.length == 0) {
796 /* Remove the attribute. */
797 if (!fsp->fsp_flags.is_pathref &&
798 fsp_get_io_fd(fsp) != -1)
800 DEBUG(10,("set_ea: deleting ea name %s on "
801 "file %s by file descriptor.\n",
802 unix_ea_name, fsp_str_dbg(fsp)));
803 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
804 } else {
805 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
806 unix_ea_name, fsp->fsp_name->base_name));
807 ret = SMB_VFS_REMOVEXATTR(conn,
808 fsp->fsp_name,
809 unix_ea_name);
811 #ifdef ENOATTR
812 /* Removing a non existent attribute always succeeds. */
813 if (ret == -1 && errno == ENOATTR) {
814 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
815 unix_ea_name));
816 ret = 0;
818 #endif
819 } else {
820 if (!fsp->fsp_flags.is_pathref &&
821 fsp_get_io_fd(fsp) != -1)
823 DEBUG(10,("set_ea: setting ea name %s on file "
824 "%s by file descriptor.\n",
825 unix_ea_name, fsp_str_dbg(fsp)));
826 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
827 ea_list->ea.value.data, ea_list->ea.value.length, 0);
828 } else {
829 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
830 unix_ea_name, fsp->fsp_name->base_name));
831 ret = SMB_VFS_SETXATTR(conn,
832 fsp->fsp_name,
833 unix_ea_name,
834 ea_list->ea.value.data,
835 ea_list->ea.value.length,
840 if (ret == -1) {
841 #ifdef ENOTSUP
842 if (errno == ENOTSUP) {
843 return NT_STATUS_EAS_NOT_SUPPORTED;
845 #endif
846 return map_nt_error_from_unix(errno);
850 return NT_STATUS_OK;
852 /****************************************************************************
853 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
854 ****************************************************************************/
856 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
858 struct ea_list *ea_list_head = NULL;
859 size_t converted_size, offset = 0;
861 while (offset + 2 < data_size) {
862 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
863 unsigned int namelen = CVAL(pdata,offset);
865 offset++; /* Go past the namelen byte. */
867 /* integer wrap paranioa. */
868 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
869 (offset > data_size) || (namelen > data_size) ||
870 (offset + namelen >= data_size)) {
871 break;
873 /* Ensure the name is null terminated. */
874 if (pdata[offset + namelen] != '\0') {
875 return NULL;
877 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
878 &converted_size)) {
879 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
880 "failed: %s", strerror(errno)));
882 if (!eal->ea.name) {
883 return NULL;
886 offset += (namelen + 1); /* Go past the name + terminating zero. */
887 DLIST_ADD_END(ea_list_head, eal);
888 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
891 return ea_list_head;
894 /****************************************************************************
895 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
896 ****************************************************************************/
898 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
900 struct ea_list *ea_list_head = NULL;
901 size_t offset = 0;
902 size_t bytes_used = 0;
904 while (offset < data_size) {
905 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
907 if (!eal) {
908 return NULL;
911 DLIST_ADD_END(ea_list_head, eal);
912 offset += bytes_used;
915 return ea_list_head;
918 /****************************************************************************
919 Count the total EA size needed.
920 ****************************************************************************/
922 static size_t ea_list_size(struct ea_list *ealist)
924 fstring dos_ea_name;
925 struct ea_list *listp;
926 size_t ret = 0;
928 for (listp = ealist; listp; listp = listp->next) {
929 push_ascii_fstring(dos_ea_name, listp->ea.name);
930 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
932 /* Add on 4 for total length. */
933 if (ret) {
934 ret += 4;
937 return ret;
940 /****************************************************************************
941 Return a union of EA's from a file list and a list of names.
942 The TALLOC context for the two lists *MUST* be identical as we steal
943 memory from one list to add to another. JRA.
944 ****************************************************************************/
946 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
948 struct ea_list *nlistp, *flistp;
950 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
951 for (flistp = file_list; flistp; flistp = flistp->next) {
952 if (strequal(nlistp->ea.name, flistp->ea.name)) {
953 break;
957 if (flistp) {
958 /* Copy the data from this entry. */
959 nlistp->ea.flags = flistp->ea.flags;
960 nlistp->ea.value = flistp->ea.value;
961 } else {
962 /* Null entry. */
963 nlistp->ea.flags = 0;
964 ZERO_STRUCT(nlistp->ea.value);
968 *total_ea_len = ea_list_size(name_list);
969 return name_list;
972 /****************************************************************************
973 Send the required number of replies back.
974 We assume all fields other than the data fields are
975 set correctly for the type of call.
976 HACK ! Always assumes smb_setup field is zero.
977 ****************************************************************************/
979 void send_trans2_replies(connection_struct *conn,
980 struct smb_request *req,
981 NTSTATUS status,
982 const char *params,
983 int paramsize,
984 const char *pdata,
985 int datasize,
986 int max_data_bytes)
988 /* As we are using a protocol > LANMAN1 then the max_send
989 variable must have been set in the sessetupX call.
990 This takes precedence over the max_xmit field in the
991 global struct. These different max_xmit variables should
992 be merged as this is now too confusing */
994 int data_to_send = datasize;
995 int params_to_send = paramsize;
996 int useable_space;
997 const char *pp = params;
998 const char *pd = pdata;
999 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1000 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1001 int data_alignment_offset = 0;
1002 bool overflow = False;
1003 struct smbXsrv_connection *xconn = req->xconn;
1004 int max_send = xconn->smb1.sessions.max_send;
1006 /* Modify the data_to_send and datasize and set the error if
1007 we're trying to send more than max_data_bytes. We still send
1008 the part of the packet(s) that fit. Strange, but needed
1009 for OS/2. */
1011 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1012 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1013 max_data_bytes, datasize ));
1014 datasize = data_to_send = max_data_bytes;
1015 overflow = True;
1018 /* If there genuinely are no parameters or data to send just send the empty packet */
1020 if(params_to_send == 0 && data_to_send == 0) {
1021 reply_outbuf(req, 10, 0);
1022 if (NT_STATUS_V(status)) {
1023 uint8_t eclass;
1024 uint32_t ecode;
1025 ntstatus_to_dos(status, &eclass, &ecode);
1026 error_packet_set((char *)req->outbuf,
1027 eclass, ecode, status,
1028 __LINE__,__FILE__);
1030 show_msg((char *)req->outbuf);
1031 if (!srv_send_smb(xconn,
1032 (char *)req->outbuf,
1033 true, req->seqnum+1,
1034 IS_CONN_ENCRYPTED(conn),
1035 &req->pcd)) {
1036 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1038 TALLOC_FREE(req->outbuf);
1039 return;
1042 /* When sending params and data ensure that both are nicely aligned */
1043 /* Only do this alignment when there is also data to send - else
1044 can cause NT redirector problems. */
1046 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1047 data_alignment_offset = 4 - (params_to_send % 4);
1049 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1050 /* The alignment_offset is to align the param bytes on an even byte
1051 boundary. NT 4.0 Beta needs this to work correctly. */
1053 useable_space = max_send - (smb_size
1054 + 2 * 10 /* wct */
1055 + alignment_offset
1056 + data_alignment_offset);
1058 if (useable_space < 0) {
1059 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1060 "= %d!!!", useable_space));
1061 exit_server_cleanly("send_trans2_replies: Not enough space");
1064 while (params_to_send || data_to_send) {
1065 /* Calculate whether we will totally or partially fill this packet */
1067 total_sent_thistime = params_to_send + data_to_send;
1069 /* We can never send more than useable_space */
1071 * Note that 'useable_space' does not include the alignment offsets,
1072 * but we must include the alignment offsets in the calculation of
1073 * the length of the data we send over the wire, as the alignment offsets
1074 * are sent here. Fix from Marc_Jacobsen@hp.com.
1077 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1079 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1080 + data_alignment_offset);
1082 /* Set total params and data to be sent */
1083 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1084 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1086 /* Calculate how many parameters and data we can fit into
1087 * this packet. Parameters get precedence
1090 params_sent_thistime = MIN(params_to_send,useable_space);
1091 data_sent_thistime = useable_space - params_sent_thistime;
1092 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1094 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1096 /* smb_proff is the offset from the start of the SMB header to the
1097 parameter bytes, however the first 4 bytes of outbuf are
1098 the Netbios over TCP header. Thus use smb_base() to subtract
1099 them from the calculation */
1101 SSVAL(req->outbuf,smb_proff,
1102 ((smb_buf(req->outbuf)+alignment_offset)
1103 - smb_base(req->outbuf)));
1105 if(params_sent_thistime == 0)
1106 SSVAL(req->outbuf,smb_prdisp,0);
1107 else
1108 /* Absolute displacement of param bytes sent in this packet */
1109 SSVAL(req->outbuf,smb_prdisp,pp - params);
1111 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1112 if(data_sent_thistime == 0) {
1113 SSVAL(req->outbuf,smb_droff,0);
1114 SSVAL(req->outbuf,smb_drdisp, 0);
1115 } else {
1116 /* The offset of the data bytes is the offset of the
1117 parameter bytes plus the number of parameters being sent this time */
1118 SSVAL(req->outbuf, smb_droff,
1119 ((smb_buf(req->outbuf)+alignment_offset)
1120 - smb_base(req->outbuf))
1121 + params_sent_thistime + data_alignment_offset);
1122 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1125 /* Initialize the padding for alignment */
1127 if (alignment_offset != 0) {
1128 memset(smb_buf(req->outbuf), 0, alignment_offset);
1131 /* Copy the param bytes into the packet */
1133 if(params_sent_thistime) {
1134 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1135 params_sent_thistime);
1138 /* Copy in the data bytes */
1139 if(data_sent_thistime) {
1140 if (data_alignment_offset != 0) {
1141 memset((smb_buf(req->outbuf)+alignment_offset+
1142 params_sent_thistime), 0,
1143 data_alignment_offset);
1145 memcpy(smb_buf(req->outbuf)+alignment_offset
1146 +params_sent_thistime+data_alignment_offset,
1147 pd,data_sent_thistime);
1150 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1151 params_sent_thistime, data_sent_thistime, useable_space));
1152 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1153 params_to_send, data_to_send, paramsize, datasize));
1155 if (overflow) {
1156 error_packet_set((char *)req->outbuf,
1157 ERRDOS,ERRbufferoverflow,
1158 STATUS_BUFFER_OVERFLOW,
1159 __LINE__,__FILE__);
1160 } else if (NT_STATUS_V(status)) {
1161 uint8_t eclass;
1162 uint32_t ecode;
1163 ntstatus_to_dos(status, &eclass, &ecode);
1164 error_packet_set((char *)req->outbuf,
1165 eclass, ecode, status,
1166 __LINE__,__FILE__);
1169 /* Send the packet */
1170 show_msg((char *)req->outbuf);
1171 if (!srv_send_smb(xconn,
1172 (char *)req->outbuf,
1173 true, req->seqnum+1,
1174 IS_CONN_ENCRYPTED(conn),
1175 &req->pcd))
1176 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1178 TALLOC_FREE(req->outbuf);
1180 pp += params_sent_thistime;
1181 pd += data_sent_thistime;
1183 params_to_send -= params_sent_thistime;
1184 data_to_send -= data_sent_thistime;
1186 /* Sanity check */
1187 if(params_to_send < 0 || data_to_send < 0) {
1188 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1189 params_to_send, data_to_send));
1190 return;
1194 return;
1197 /****************************************************************************
1198 Reply to a TRANSACT2_OPEN.
1199 ****************************************************************************/
1201 static void call_trans2open(connection_struct *conn,
1202 struct smb_request *req,
1203 char **pparams, int total_params,
1204 char **ppdata, int total_data,
1205 unsigned int max_data_bytes)
1207 struct smb_filename *smb_fname = NULL;
1208 char *params = *pparams;
1209 char *pdata = *ppdata;
1210 int deny_mode;
1211 int32_t open_attr;
1212 bool oplock_request;
1213 #if 0
1214 bool return_additional_info;
1215 int16 open_sattr;
1216 time_t open_time;
1217 #endif
1218 int open_ofun;
1219 uint32_t open_size;
1220 char *pname;
1221 char *fname = NULL;
1222 off_t size=0;
1223 int fattr=0,mtime=0;
1224 SMB_INO_T inode = 0;
1225 int smb_action = 0;
1226 files_struct *fsp;
1227 struct ea_list *ea_list = NULL;
1228 uint16_t flags = 0;
1229 NTSTATUS status;
1230 uint32_t access_mask;
1231 uint32_t share_mode;
1232 uint32_t create_disposition;
1233 uint32_t create_options = 0;
1234 uint32_t private_flags = 0;
1235 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1236 TALLOC_CTX *ctx = talloc_tos();
1239 * Ensure we have enough parameters to perform the operation.
1242 if (total_params < 29) {
1243 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1244 goto out;
1247 flags = SVAL(params, 0);
1248 deny_mode = SVAL(params, 2);
1249 open_attr = SVAL(params,6);
1250 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1251 if (oplock_request) {
1252 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1255 #if 0
1256 return_additional_info = BITSETW(params,0);
1257 open_sattr = SVAL(params, 4);
1258 open_time = make_unix_date3(params+8);
1259 #endif
1260 open_ofun = SVAL(params,12);
1261 open_size = IVAL(params,14);
1262 pname = &params[28];
1264 if (IS_IPC(conn)) {
1265 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1266 goto out;
1269 if (req->posix_pathnames) {
1270 srvstr_get_path_posix(ctx,
1271 params,
1272 req->flags2,
1273 &fname,
1274 pname,
1275 total_params - 28,
1276 STR_TERMINATE,
1277 &status);
1278 } else {
1279 srvstr_get_path(ctx,
1280 params,
1281 req->flags2,
1282 &fname,
1283 pname,
1284 total_params - 28,
1285 STR_TERMINATE,
1286 &status);
1288 if (!NT_STATUS_IS_OK(status)) {
1289 reply_nterror(req, status);
1290 goto out;
1293 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1294 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1295 (unsigned int)open_ofun, open_size));
1297 status = filename_convert(ctx,
1298 conn,
1299 fname,
1300 ucf_flags,
1302 &smb_fname);
1303 if (!NT_STATUS_IS_OK(status)) {
1304 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1305 reply_botherror(req,
1306 NT_STATUS_PATH_NOT_COVERED,
1307 ERRSRV, ERRbadpath);
1308 goto out;
1310 reply_nterror(req, status);
1311 goto out;
1314 if (open_ofun == 0) {
1315 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1316 goto out;
1319 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1320 open_ofun,
1321 &access_mask, &share_mode,
1322 &create_disposition,
1323 &create_options,
1324 &private_flags)) {
1325 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1326 goto out;
1329 /* Any data in this call is an EA list. */
1330 if (total_data && (total_data != 4)) {
1331 if (total_data < 10) {
1332 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1333 goto out;
1336 if (IVAL(pdata,0) > total_data) {
1337 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1338 IVAL(pdata,0), (unsigned int)total_data));
1339 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1340 goto out;
1343 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1344 total_data - 4);
1345 if (!ea_list) {
1346 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1347 goto out;
1350 if (!lp_ea_support(SNUM(conn))) {
1351 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1352 goto out;
1355 if (!req->posix_pathnames &&
1356 ea_list_has_invalid_name(ea_list)) {
1357 int param_len = 30;
1358 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1359 if(*pparams == NULL ) {
1360 reply_nterror(req, NT_STATUS_NO_MEMORY);
1361 goto out;
1363 params = *pparams;
1364 memset(params, '\0', param_len);
1365 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1366 params, param_len, NULL, 0, max_data_bytes);
1367 goto out;
1371 status = SMB_VFS_CREATE_FILE(
1372 conn, /* conn */
1373 req, /* req */
1374 smb_fname, /* fname */
1375 access_mask, /* access_mask */
1376 share_mode, /* share_access */
1377 create_disposition, /* create_disposition*/
1378 create_options, /* create_options */
1379 open_attr, /* file_attributes */
1380 oplock_request, /* oplock_request */
1381 NULL, /* lease */
1382 open_size, /* allocation_size */
1383 private_flags,
1384 NULL, /* sd */
1385 ea_list, /* ea_list */
1386 &fsp, /* result */
1387 &smb_action, /* psbuf */
1388 NULL, NULL); /* create context */
1390 if (!NT_STATUS_IS_OK(status)) {
1391 if (open_was_deferred(req->xconn, req->mid)) {
1392 /* We have re-scheduled this call. */
1393 goto out;
1396 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1397 reply_openerror(req, status);
1398 goto out;
1401 fsp = fcb_or_dos_open(
1402 req,
1403 smb_fname,
1404 access_mask,
1405 create_options,
1406 private_flags);
1407 if (fsp == NULL) {
1408 bool ok = defer_smb1_sharing_violation(req);
1409 if (ok) {
1410 goto out;
1412 reply_openerror(req, status);
1413 goto out;
1416 smb_action = FILE_WAS_OPENED;
1419 size = get_file_size_stat(&smb_fname->st);
1420 fattr = fdos_mode(fsp);
1421 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1422 inode = smb_fname->st.st_ex_ino;
1423 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1424 close_file(req, fsp, ERROR_CLOSE);
1425 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1426 goto out;
1429 /* Realloc the size of parameters and data we will return */
1430 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1431 if(*pparams == NULL ) {
1432 reply_nterror(req, NT_STATUS_NO_MEMORY);
1433 goto out;
1435 params = *pparams;
1437 SSVAL(params,0,fsp->fnum);
1438 SSVAL(params,2,fattr);
1439 srv_put_dos_date2(params,4, mtime);
1440 SIVAL(params,8, (uint32_t)size);
1441 SSVAL(params,12,deny_mode);
1442 SSVAL(params,14,0); /* open_type - file or directory. */
1443 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1445 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1446 smb_action |= EXTENDED_OPLOCK_GRANTED;
1449 SSVAL(params,18,smb_action);
1452 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1454 SIVAL(params,20,inode);
1455 SSVAL(params,24,0); /* Padding. */
1456 if (flags & 8) {
1457 uint32_t ea_size = estimate_ea_size(smb_fname->fsp);
1458 SIVAL(params, 26, ea_size);
1459 } else {
1460 SIVAL(params, 26, 0);
1463 /* Send the required number of replies */
1464 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1465 out:
1466 TALLOC_FREE(smb_fname);
1469 /*********************************************************
1470 Routine to check if a given string matches exactly.
1471 as a special case a mask of "." does NOT match. That
1472 is required for correct wildcard semantics
1473 Case can be significant or not.
1474 **********************************************************/
1476 static bool exact_match(bool has_wild,
1477 bool case_sensitive,
1478 const char *str,
1479 const char *mask)
1481 if (mask[0] == '.' && mask[1] == 0) {
1482 return false;
1485 if (has_wild) {
1486 return false;
1489 if (case_sensitive) {
1490 return strcmp(str,mask)==0;
1491 } else {
1492 return strcasecmp_m(str,mask) == 0;
1496 /****************************************************************************
1497 Return the filetype for UNIX extensions.
1498 ****************************************************************************/
1500 static uint32_t unix_filetype(mode_t mode)
1502 if(S_ISREG(mode))
1503 return UNIX_TYPE_FILE;
1504 else if(S_ISDIR(mode))
1505 return UNIX_TYPE_DIR;
1506 #ifdef S_ISLNK
1507 else if(S_ISLNK(mode))
1508 return UNIX_TYPE_SYMLINK;
1509 #endif
1510 #ifdef S_ISCHR
1511 else if(S_ISCHR(mode))
1512 return UNIX_TYPE_CHARDEV;
1513 #endif
1514 #ifdef S_ISBLK
1515 else if(S_ISBLK(mode))
1516 return UNIX_TYPE_BLKDEV;
1517 #endif
1518 #ifdef S_ISFIFO
1519 else if(S_ISFIFO(mode))
1520 return UNIX_TYPE_FIFO;
1521 #endif
1522 #ifdef S_ISSOCK
1523 else if(S_ISSOCK(mode))
1524 return UNIX_TYPE_SOCKET;
1525 #endif
1527 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1528 return UNIX_TYPE_UNKNOWN;
1531 /****************************************************************************
1532 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1533 ****************************************************************************/
1535 NTSTATUS unix_perms_from_wire(connection_struct *conn,
1536 const SMB_STRUCT_STAT *psbuf,
1537 uint32_t perms,
1538 enum perm_type ptype,
1539 mode_t *ret_perms)
1541 mode_t ret = 0;
1543 if (perms == SMB_MODE_NO_CHANGE) {
1544 if (!VALID_STAT(*psbuf)) {
1545 return NT_STATUS_INVALID_PARAMETER;
1546 } else {
1547 *ret_perms = psbuf->st_ex_mode;
1548 return NT_STATUS_OK;
1552 ret = wire_perms_to_unix(perms);
1554 if (ptype == PERM_NEW_FILE) {
1556 * "create mask"/"force create mode" are
1557 * only applied to new files, not existing ones.
1559 ret &= lp_create_mask(SNUM(conn));
1560 /* Add in force bits */
1561 ret |= lp_force_create_mode(SNUM(conn));
1562 } else if (ptype == PERM_NEW_DIR) {
1564 * "directory mask"/"force directory mode" are
1565 * only applied to new directories, not existing ones.
1567 ret &= lp_directory_mask(SNUM(conn));
1568 /* Add in force bits */
1569 ret |= lp_force_directory_mode(SNUM(conn));
1572 *ret_perms = ret;
1573 return NT_STATUS_OK;
1576 /****************************************************************************
1577 Needed to show the msdfs symlinks as directories. Modifies psbuf
1578 to be a directory if it's a msdfs link.
1579 ****************************************************************************/
1581 static bool check_msdfs_link(connection_struct *conn,
1582 struct smb_filename *smb_fname)
1584 int saved_errno = errno;
1585 if(lp_host_msdfs() &&
1586 lp_msdfs_root(SNUM(conn)) &&
1587 is_msdfs_link(conn, smb_fname)) {
1589 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1590 "as a directory\n",
1591 smb_fname->base_name));
1592 smb_fname->st.st_ex_mode =
1593 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1594 errno = saved_errno;
1595 return true;
1597 errno = saved_errno;
1598 return false;
1602 /****************************************************************************
1603 Get a level dependent lanman2 dir entry.
1604 ****************************************************************************/
1606 struct smbd_dirptr_lanman2_state {
1607 connection_struct *conn;
1608 uint32_t info_level;
1609 bool check_mangled_names;
1610 bool has_wild;
1611 bool got_exact_match;
1614 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1615 void *private_data,
1616 const char *dname,
1617 const char *mask,
1618 char **_fname)
1620 struct smbd_dirptr_lanman2_state *state =
1621 (struct smbd_dirptr_lanman2_state *)private_data;
1622 bool ok;
1623 char mangled_name[13]; /* mangled 8.3 name. */
1624 bool got_match;
1625 const char *fname;
1627 /* Mangle fname if it's an illegal name. */
1628 if (mangle_must_mangle(dname, state->conn->params)) {
1630 * Slow path - ensure we can push the original name as UCS2. If
1631 * not, then just don't return this name.
1633 NTSTATUS status;
1634 size_t ret_len = 0;
1635 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1636 uint8_t *tmp = talloc_array(talloc_tos(),
1637 uint8_t,
1638 len);
1640 status = srvstr_push(NULL,
1641 FLAGS2_UNICODE_STRINGS,
1642 tmp,
1643 dname,
1644 len,
1645 STR_TERMINATE,
1646 &ret_len);
1648 TALLOC_FREE(tmp);
1650 if (!NT_STATUS_IS_OK(status)) {
1651 return false;
1654 ok = name_to_8_3(dname, mangled_name,
1655 true, state->conn->params);
1656 if (!ok) {
1657 return false;
1659 fname = mangled_name;
1660 } else {
1661 fname = dname;
1664 got_match = exact_match(state->has_wild,
1665 state->conn->case_sensitive,
1666 fname, mask);
1667 state->got_exact_match = got_match;
1668 if (!got_match) {
1669 got_match = mask_match(fname, mask,
1670 state->conn->case_sensitive);
1673 if(!got_match && state->check_mangled_names &&
1674 !mangle_is_8_3(fname, false, state->conn->params)) {
1676 * It turns out that NT matches wildcards against
1677 * both long *and* short names. This may explain some
1678 * of the wildcard wierdness from old DOS clients
1679 * that some people have been seeing.... JRA.
1681 /* Force the mangling into 8.3. */
1682 ok = name_to_8_3(fname, mangled_name,
1683 false, state->conn->params);
1684 if (!ok) {
1685 return false;
1688 got_match = exact_match(state->has_wild,
1689 state->conn->case_sensitive,
1690 mangled_name, mask);
1691 state->got_exact_match = got_match;
1692 if (!got_match) {
1693 got_match = mask_match(mangled_name, mask,
1694 state->conn->case_sensitive);
1698 if (!got_match) {
1699 return false;
1702 *_fname = talloc_strdup(ctx, fname);
1703 if (*_fname == NULL) {
1704 return false;
1707 return true;
1710 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1711 void *private_data,
1712 struct smb_filename *smb_fname,
1713 bool get_dosmode,
1714 uint32_t *_mode)
1716 struct smbd_dirptr_lanman2_state *state =
1717 (struct smbd_dirptr_lanman2_state *)private_data;
1718 bool ms_dfs_link = false;
1720 if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
1721 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1722 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1723 "Couldn't lstat [%s] (%s)\n",
1724 smb_fname_str_dbg(smb_fname),
1725 strerror(errno)));
1726 return false;
1728 return true;
1729 } else if (!VALID_STAT(smb_fname->st) &&
1730 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1731 /* Needed to show the msdfs symlinks as
1732 * directories */
1734 ms_dfs_link = check_msdfs_link(state->conn,
1735 smb_fname);
1736 if (!ms_dfs_link) {
1737 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1738 "Couldn't stat [%s] (%s)\n",
1739 smb_fname_str_dbg(smb_fname),
1740 strerror(errno)));
1741 return false;
1744 *_mode = dos_mode_msdfs(state->conn, smb_fname);
1745 return true;
1748 if (!get_dosmode) {
1749 return true;
1752 *_mode = fdos_mode(smb_fname->fsp);
1753 smb_fname->st = smb_fname->fsp->fsp_name->st;
1755 return true;
1758 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1759 connection_struct *conn,
1760 uint16_t flags2,
1761 uint32_t info_level,
1762 struct ea_list *name_list,
1763 bool check_mangled_names,
1764 bool requires_resume_key,
1765 uint32_t mode,
1766 const char *fname,
1767 const struct smb_filename *smb_fname,
1768 int space_remaining,
1769 uint8_t align,
1770 bool do_pad,
1771 char *base_data,
1772 char **ppdata,
1773 char *end_data,
1774 uint64_t *last_entry_off)
1776 char *p, *q, *pdata = *ppdata;
1777 uint32_t reskey=0;
1778 uint64_t file_size = 0;
1779 uint64_t allocation_size = 0;
1780 uint64_t file_id = 0;
1781 size_t len = 0;
1782 struct timespec mdate_ts = {0};
1783 struct timespec adate_ts = {0};
1784 struct timespec cdate_ts = {0};
1785 struct timespec create_date_ts = {0};
1786 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1787 char *nameptr;
1788 char *last_entry_ptr;
1789 bool was_8_3;
1790 int off;
1791 int pad = 0;
1792 NTSTATUS status;
1793 struct readdir_attr_data *readdir_attr_data = NULL;
1795 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1796 file_size = get_file_size_stat(&smb_fname->st);
1798 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1800 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1801 if (!NT_STATUS_IS_OK(status)) {
1802 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1803 return status;
1807 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1809 mdate_ts = smb_fname->st.st_ex_mtime;
1810 adate_ts = smb_fname->st.st_ex_atime;
1811 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1812 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1814 if (lp_dos_filetime_resolution(SNUM(conn))) {
1815 dos_filetime_timespec(&create_date_ts);
1816 dos_filetime_timespec(&mdate_ts);
1817 dos_filetime_timespec(&adate_ts);
1818 dos_filetime_timespec(&cdate_ts);
1821 create_date = convert_timespec_to_time_t(create_date_ts);
1822 mdate = convert_timespec_to_time_t(mdate_ts);
1823 adate = convert_timespec_to_time_t(adate_ts);
1825 /* align the record */
1826 SMB_ASSERT(align >= 1);
1828 off = (int)PTR_DIFF(pdata, base_data);
1829 pad = (off + (align-1)) & ~(align-1);
1830 pad -= off;
1832 if (pad && pad > space_remaining) {
1833 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1834 "for padding (wanted %u, had %d)\n",
1835 (unsigned int)pad,
1836 space_remaining ));
1837 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1840 off += pad;
1841 /* initialize padding to 0 */
1842 if (pad) {
1843 memset(pdata, 0, pad);
1845 space_remaining -= pad;
1847 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1848 space_remaining ));
1850 pdata += pad;
1851 p = pdata;
1852 last_entry_ptr = p;
1854 pad = 0;
1855 off = 0;
1857 switch (info_level) {
1858 case SMB_FIND_INFO_STANDARD:
1859 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1860 if(requires_resume_key) {
1861 SIVAL(p,0,reskey);
1862 p += 4;
1864 srv_put_dos_date2(p,0,create_date);
1865 srv_put_dos_date2(p,4,adate);
1866 srv_put_dos_date2(p,8,mdate);
1867 SIVAL(p,12,(uint32_t)file_size);
1868 SIVAL(p,16,(uint32_t)allocation_size);
1869 SSVAL(p,20,mode);
1870 p += 23;
1871 nameptr = p;
1872 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1873 p += ucs2_align(base_data, p, 0);
1875 status = srvstr_push(base_data, flags2, p,
1876 fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE, &len);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 return status;
1881 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1882 if (len > 2) {
1883 SCVAL(nameptr, -1, len - 2);
1884 } else {
1885 SCVAL(nameptr, -1, 0);
1887 } else {
1888 if (len > 1) {
1889 SCVAL(nameptr, -1, len - 1);
1890 } else {
1891 SCVAL(nameptr, -1, 0);
1894 p += len;
1895 break;
1897 case SMB_FIND_EA_SIZE:
1898 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1899 if (requires_resume_key) {
1900 SIVAL(p,0,reskey);
1901 p += 4;
1903 srv_put_dos_date2(p,0,create_date);
1904 srv_put_dos_date2(p,4,adate);
1905 srv_put_dos_date2(p,8,mdate);
1906 SIVAL(p,12,(uint32_t)file_size);
1907 SIVAL(p,16,(uint32_t)allocation_size);
1908 SSVAL(p,20,mode);
1910 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
1911 SIVAL(p,22,ea_size); /* Extended attributes */
1913 p += 27;
1914 nameptr = p - 1;
1915 status = srvstr_push(base_data, flags2,
1916 p, fname, PTR_DIFF(end_data, p),
1917 STR_TERMINATE | STR_NOALIGN, &len);
1918 if (!NT_STATUS_IS_OK(status)) {
1919 return status;
1921 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1922 if (len > 2) {
1923 len -= 2;
1924 } else {
1925 len = 0;
1927 } else {
1928 if (len > 1) {
1929 len -= 1;
1930 } else {
1931 len = 0;
1934 SCVAL(nameptr,0,len);
1935 p += len;
1936 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1937 break;
1939 case SMB_FIND_EA_LIST:
1941 struct ea_list *file_list = NULL;
1942 size_t ea_len = 0;
1944 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1945 if (!name_list) {
1946 return NT_STATUS_INVALID_PARAMETER;
1948 if (requires_resume_key) {
1949 SIVAL(p,0,reskey);
1950 p += 4;
1952 srv_put_dos_date2(p,0,create_date);
1953 srv_put_dos_date2(p,4,adate);
1954 srv_put_dos_date2(p,8,mdate);
1955 SIVAL(p,12,(uint32_t)file_size);
1956 SIVAL(p,16,(uint32_t)allocation_size);
1957 SSVAL(p,20,mode);
1958 p += 22; /* p now points to the EA area. */
1960 status = get_ea_list_from_fsp(ctx,
1961 smb_fname->fsp,
1962 &ea_len, &file_list);
1963 if (!NT_STATUS_IS_OK(status)) {
1964 file_list = NULL;
1966 name_list = ea_list_union(name_list, file_list, &ea_len);
1968 /* We need to determine if this entry will fit in the space available. */
1969 /* Max string size is 255 bytes. */
1970 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1971 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1972 "(wanted %u, had %d)\n",
1973 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1974 space_remaining ));
1975 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1978 /* Push the ea_data followed by the name. */
1979 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1980 nameptr = p;
1981 status = srvstr_push(base_data, flags2,
1982 p + 1, fname, PTR_DIFF(end_data, p+1),
1983 STR_TERMINATE | STR_NOALIGN, &len);
1984 if (!NT_STATUS_IS_OK(status)) {
1985 return status;
1987 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1988 if (len > 2) {
1989 len -= 2;
1990 } else {
1991 len = 0;
1993 } else {
1994 if (len > 1) {
1995 len -= 1;
1996 } else {
1997 len = 0;
2000 SCVAL(nameptr,0,len);
2001 p += len + 1;
2002 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2003 break;
2006 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2007 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2008 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2009 p += 4;
2010 SIVAL(p,0,reskey); p += 4;
2011 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2012 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2013 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2014 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2015 SOFF_T(p,0,file_size); p += 8;
2016 SOFF_T(p,0,allocation_size); p += 8;
2017 SIVAL(p,0,mode); p += 4;
2018 q = p; p += 4; /* q is placeholder for name length. */
2019 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2020 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2021 } else {
2022 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2023 SIVAL(p,0,ea_size); /* Extended attributes */
2025 p += 4;
2026 /* Clear the short name buffer. This is
2027 * IMPORTANT as not doing so will trigger
2028 * a Win2k client bug. JRA.
2030 if (!was_8_3 && check_mangled_names) {
2031 char mangled_name[13]; /* mangled 8.3 name. */
2032 if (!name_to_8_3(fname,mangled_name,True,
2033 conn->params)) {
2034 /* Error - mangle failed ! */
2035 memset(mangled_name,'\0',12);
2037 mangled_name[12] = 0;
2038 status = srvstr_push(base_data, flags2,
2039 p+2, mangled_name, 24,
2040 STR_UPPER|STR_UNICODE, &len);
2041 if (!NT_STATUS_IS_OK(status)) {
2042 return status;
2044 if (len < 24) {
2045 memset(p + 2 + len,'\0',24 - len);
2047 SSVAL(p, 0, len);
2048 } else {
2049 memset(p,'\0',26);
2051 p += 2 + 24;
2052 status = srvstr_push(base_data, flags2, p,
2053 fname, PTR_DIFF(end_data, p),
2054 STR_TERMINATE_ASCII, &len);
2055 if (!NT_STATUS_IS_OK(status)) {
2056 return status;
2058 SIVAL(q,0,len);
2059 p += len;
2061 len = PTR_DIFF(p, pdata);
2062 pad = (len + (align-1)) & ~(align-1);
2064 * offset to the next entry, the caller
2065 * will overwrite it for the last entry
2066 * that's why we always include the padding
2068 SIVAL(pdata,0,pad);
2070 * set padding to zero
2072 if (do_pad) {
2073 memset(p, 0, pad - len);
2074 p = pdata + pad;
2075 } else {
2076 p = pdata + len;
2078 break;
2080 case SMB_FIND_FILE_DIRECTORY_INFO:
2081 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2082 p += 4;
2083 SIVAL(p,0,reskey); p += 4;
2084 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2085 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2086 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2087 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2088 SOFF_T(p,0,file_size); p += 8;
2089 SOFF_T(p,0,allocation_size); p += 8;
2090 SIVAL(p,0,mode); p += 4;
2091 status = srvstr_push(base_data, flags2,
2092 p + 4, fname, PTR_DIFF(end_data, p+4),
2093 STR_TERMINATE_ASCII, &len);
2094 if (!NT_STATUS_IS_OK(status)) {
2095 return status;
2097 SIVAL(p,0,len);
2098 p += 4 + len;
2100 len = PTR_DIFF(p, pdata);
2101 pad = (len + (align-1)) & ~(align-1);
2103 * offset to the next entry, the caller
2104 * will overwrite it for the last entry
2105 * that's why we always include the padding
2107 SIVAL(pdata,0,pad);
2109 * set padding to zero
2111 if (do_pad) {
2112 memset(p, 0, pad - len);
2113 p = pdata + pad;
2114 } else {
2115 p = pdata + len;
2117 break;
2119 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2120 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2121 p += 4;
2122 SIVAL(p,0,reskey); p += 4;
2123 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2124 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2125 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2126 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2127 SOFF_T(p,0,file_size); p += 8;
2128 SOFF_T(p,0,allocation_size); p += 8;
2129 SIVAL(p,0,mode); p += 4;
2130 q = p; p += 4; /* q is placeholder for name length. */
2131 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2132 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2133 } else {
2134 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2135 SIVAL(p,0,ea_size); /* Extended attributes */
2137 p +=4;
2138 status = srvstr_push(base_data, flags2, p,
2139 fname, PTR_DIFF(end_data, p),
2140 STR_TERMINATE_ASCII, &len);
2141 if (!NT_STATUS_IS_OK(status)) {
2142 return status;
2144 SIVAL(q, 0, len);
2145 p += len;
2147 len = PTR_DIFF(p, pdata);
2148 pad = (len + (align-1)) & ~(align-1);
2150 * offset to the next entry, the caller
2151 * will overwrite it for the last entry
2152 * that's why we always include the padding
2154 SIVAL(pdata,0,pad);
2156 * set padding to zero
2158 if (do_pad) {
2159 memset(p, 0, pad - len);
2160 p = pdata + pad;
2161 } else {
2162 p = pdata + len;
2164 break;
2166 case SMB_FIND_FILE_NAMES_INFO:
2167 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2168 p += 4;
2169 SIVAL(p,0,reskey); p += 4;
2170 p += 4;
2171 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2172 acl on a dir (tridge) */
2173 status = srvstr_push(base_data, flags2, p,
2174 fname, PTR_DIFF(end_data, p),
2175 STR_TERMINATE_ASCII, &len);
2176 if (!NT_STATUS_IS_OK(status)) {
2177 return status;
2179 SIVAL(p, -4, len);
2180 p += len;
2182 len = PTR_DIFF(p, pdata);
2183 pad = (len + (align-1)) & ~(align-1);
2185 * offset to the next entry, the caller
2186 * will overwrite it for the last entry
2187 * that's why we always include the padding
2189 SIVAL(pdata,0,pad);
2191 * set padding to zero
2193 if (do_pad) {
2194 memset(p, 0, pad - len);
2195 p = pdata + pad;
2196 } else {
2197 p = pdata + len;
2199 break;
2201 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2202 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2203 p += 4;
2204 SIVAL(p,0,reskey); p += 4;
2205 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2206 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2207 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2208 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2209 SOFF_T(p,0,file_size); p += 8;
2210 SOFF_T(p,0,allocation_size); p += 8;
2211 SIVAL(p,0,mode); p += 4;
2212 q = p; p += 4; /* q is placeholder for name length. */
2213 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2214 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2215 } else {
2216 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2217 SIVAL(p,0,ea_size); /* Extended attributes */
2219 p += 4;
2220 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2221 SBVAL(p,0,file_id); p += 8;
2222 status = srvstr_push(base_data, flags2, p,
2223 fname, PTR_DIFF(end_data, p),
2224 STR_TERMINATE_ASCII, &len);
2225 if (!NT_STATUS_IS_OK(status)) {
2226 return status;
2228 SIVAL(q, 0, len);
2229 p += len;
2231 len = PTR_DIFF(p, pdata);
2232 pad = (len + (align-1)) & ~(align-1);
2234 * offset to the next entry, the caller
2235 * will overwrite it for the last entry
2236 * that's why we always include the padding
2238 SIVAL(pdata,0,pad);
2240 * set padding to zero
2242 if (do_pad) {
2243 memset(p, 0, pad - len);
2244 p = pdata + pad;
2245 } else {
2246 p = pdata + len;
2248 break;
2250 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2251 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2252 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2253 p += 4;
2254 SIVAL(p,0,reskey); p += 4;
2255 put_long_date_full_timespec(conn->ts_res,p,&create_date_ts); p += 8;
2256 put_long_date_full_timespec(conn->ts_res,p,&adate_ts); p += 8;
2257 put_long_date_full_timespec(conn->ts_res,p,&mdate_ts); p += 8;
2258 put_long_date_full_timespec(conn->ts_res,p,&cdate_ts); p += 8;
2259 SOFF_T(p,0,file_size); p += 8;
2260 SOFF_T(p,0,allocation_size); p += 8;
2261 SIVAL(p,0,mode); p += 4;
2262 q = p; p += 4; /* q is placeholder for name length */
2263 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2264 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2265 } else if (readdir_attr_data &&
2266 readdir_attr_data->type == RDATTR_AAPL) {
2268 * OS X specific SMB2 extension negotiated via
2269 * AAPL create context: return max_access in
2270 * ea_size field.
2272 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2273 } else {
2274 unsigned int ea_size = estimate_ea_size(smb_fname->fsp);
2275 SIVAL(p,0,ea_size); /* Extended attributes */
2277 p += 4;
2279 if (readdir_attr_data &&
2280 readdir_attr_data->type == RDATTR_AAPL) {
2282 * OS X specific SMB2 extension negotiated via
2283 * AAPL create context: return resource fork
2284 * length and compressed FinderInfo in
2285 * shortname field.
2287 * According to documentation short_name_len
2288 * should be 0, but on the wire behaviour
2289 * shows its set to 24 by clients.
2291 SSVAL(p, 0, 24);
2293 /* Resourefork length */
2294 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2296 /* Compressed FinderInfo */
2297 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2298 } else if (!was_8_3 && check_mangled_names) {
2299 char mangled_name[13]; /* mangled 8.3 name. */
2300 if (!name_to_8_3(fname,mangled_name,True,
2301 conn->params)) {
2302 /* Error - mangle failed ! */
2303 memset(mangled_name,'\0',12);
2305 mangled_name[12] = 0;
2306 status = srvstr_push(base_data, flags2,
2307 p+2, mangled_name, 24,
2308 STR_UPPER|STR_UNICODE, &len);
2309 if (!NT_STATUS_IS_OK(status)) {
2310 return status;
2312 SSVAL(p, 0, len);
2313 if (len < 24) {
2314 memset(p + 2 + len,'\0',24 - len);
2316 SSVAL(p, 0, len);
2317 } else {
2318 /* Clear the short name buffer. This is
2319 * IMPORTANT as not doing so will trigger
2320 * a Win2k client bug. JRA.
2322 memset(p,'\0',26);
2324 p += 26;
2326 /* Reserved ? */
2327 if (readdir_attr_data &&
2328 readdir_attr_data->type == RDATTR_AAPL) {
2330 * OS X specific SMB2 extension negotiated via
2331 * AAPL create context: return UNIX mode in
2332 * reserved field.
2334 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2335 SSVAL(p, 0, aapl_mode);
2336 } else {
2337 SSVAL(p, 0, 0);
2339 p += 2;
2341 SBVAL(p,0,file_id); p += 8;
2342 status = srvstr_push(base_data, flags2, p,
2343 fname, PTR_DIFF(end_data, p),
2344 STR_TERMINATE_ASCII, &len);
2345 if (!NT_STATUS_IS_OK(status)) {
2346 return status;
2348 SIVAL(q,0,len);
2349 p += len;
2351 len = PTR_DIFF(p, pdata);
2352 pad = (len + (align-1)) & ~(align-1);
2354 * offset to the next entry, the caller
2355 * will overwrite it for the last entry
2356 * that's why we always include the padding
2358 SIVAL(pdata,0,pad);
2360 * set padding to zero
2362 if (do_pad) {
2363 memset(p, 0, pad - len);
2364 p = pdata + pad;
2365 } else {
2366 p = pdata + len;
2368 break;
2370 /* CIFS UNIX Extension. */
2372 case SMB_FIND_FILE_UNIX:
2373 case SMB_FIND_FILE_UNIX_INFO2:
2374 p+= 4;
2375 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2377 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2379 if (info_level == SMB_FIND_FILE_UNIX) {
2380 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2381 p = store_file_unix_basic(conn, p,
2382 NULL, &smb_fname->st);
2383 status = srvstr_push(base_data, flags2, p,
2384 fname, PTR_DIFF(end_data, p),
2385 STR_TERMINATE, &len);
2386 if (!NT_STATUS_IS_OK(status)) {
2387 return status;
2389 } else {
2390 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2391 p = store_file_unix_basic_info2(conn, p,
2392 NULL, &smb_fname->st);
2393 nameptr = p;
2394 p += 4;
2395 status = srvstr_push(base_data, flags2, p, fname,
2396 PTR_DIFF(end_data, p), 0, &len);
2397 if (!NT_STATUS_IS_OK(status)) {
2398 return status;
2400 SIVAL(nameptr, 0, len);
2403 p += len;
2405 len = PTR_DIFF(p, pdata);
2406 pad = (len + (align-1)) & ~(align-1);
2408 * offset to the next entry, the caller
2409 * will overwrite it for the last entry
2410 * that's why we always include the padding
2412 SIVAL(pdata,0,pad);
2414 * set padding to zero
2416 if (do_pad) {
2417 memset(p, 0, pad - len);
2418 p = pdata + pad;
2419 } else {
2420 p = pdata + len;
2422 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2424 break;
2426 default:
2427 return NT_STATUS_INVALID_LEVEL;
2430 if (PTR_DIFF(p,pdata) > space_remaining) {
2431 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2432 "(wanted %u, had %d)\n",
2433 (unsigned int)PTR_DIFF(p,pdata),
2434 space_remaining ));
2435 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2438 /* Setup the last entry pointer, as an offset from base_data */
2439 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2440 /* Advance the data pointer to the next slot */
2441 *ppdata = p;
2443 return NT_STATUS_OK;
2446 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2447 connection_struct *conn,
2448 struct dptr_struct *dirptr,
2449 uint16_t flags2,
2450 const char *path_mask,
2451 uint32_t dirtype,
2452 int info_level,
2453 int requires_resume_key,
2454 bool dont_descend,
2455 bool ask_sharemode,
2456 bool get_dosmode,
2457 uint8_t align,
2458 bool do_pad,
2459 char **ppdata,
2460 char *base_data,
2461 char *end_data,
2462 int space_remaining,
2463 struct smb_filename **_smb_fname,
2464 bool *got_exact_match,
2465 int *_last_entry_off,
2466 struct ea_list *name_list,
2467 struct file_id *file_id)
2469 const char *p;
2470 const char *mask = NULL;
2471 long prev_dirpos = 0;
2472 uint32_t mode = 0;
2473 char *fname = NULL;
2474 struct smb_filename *smb_fname = NULL;
2475 struct smbd_dirptr_lanman2_state state;
2476 bool ok;
2477 uint64_t last_entry_off = 0;
2478 NTSTATUS status;
2479 enum mangled_names_options mangled_names;
2480 bool marshall_with_83_names;
2482 mangled_names = lp_mangled_names(conn->params);
2484 ZERO_STRUCT(state);
2485 state.conn = conn;
2486 state.info_level = info_level;
2487 if (mangled_names != MANGLED_NAMES_NO) {
2488 state.check_mangled_names = true;
2490 state.has_wild = dptr_has_wild(dirptr);
2491 state.got_exact_match = false;
2493 *got_exact_match = false;
2495 p = strrchr_m(path_mask,'/');
2496 if(p != NULL) {
2497 if(p[1] == '\0') {
2498 mask = "*.*";
2499 } else {
2500 mask = p+1;
2502 } else {
2503 mask = path_mask;
2506 ok = smbd_dirptr_get_entry(ctx,
2507 dirptr,
2508 mask,
2509 dirtype,
2510 dont_descend,
2511 ask_sharemode,
2512 get_dosmode,
2513 smbd_dirptr_lanman2_match_fn,
2514 smbd_dirptr_lanman2_mode_fn,
2515 &state,
2516 &fname,
2517 &smb_fname,
2518 &mode,
2519 &prev_dirpos);
2520 if (!ok) {
2521 return NT_STATUS_END_OF_FILE;
2524 *got_exact_match = state.got_exact_match;
2526 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2528 status = smbd_marshall_dir_entry(ctx,
2529 conn,
2530 flags2,
2531 info_level,
2532 name_list,
2533 marshall_with_83_names,
2534 requires_resume_key,
2535 mode,
2536 fname,
2537 smb_fname,
2538 space_remaining,
2539 align,
2540 do_pad,
2541 base_data,
2542 ppdata,
2543 end_data,
2544 &last_entry_off);
2545 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2546 DEBUG(1,("Conversion error: illegal character: %s\n",
2547 smb_fname_str_dbg(smb_fname)));
2550 if (file_id != NULL) {
2551 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2554 if (!NT_STATUS_IS_OK(status) &&
2555 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2557 TALLOC_FREE(smb_fname);
2558 TALLOC_FREE(fname);
2559 return status;
2562 if (_smb_fname != NULL) {
2563 struct smb_filename *name = NULL;
2565 name = synthetic_smb_fname(ctx,
2566 fname,
2567 NULL,
2568 &smb_fname->st,
2569 smb_fname->twrp,
2571 if (name == NULL) {
2572 TALLOC_FREE(smb_fname);
2573 TALLOC_FREE(fname);
2574 return NT_STATUS_NO_MEMORY;
2576 *_smb_fname = name;
2579 TALLOC_FREE(smb_fname);
2580 TALLOC_FREE(fname);
2582 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2583 dptr_SeekDir(dirptr, prev_dirpos);
2584 return status;
2587 *_last_entry_off = last_entry_off;
2588 return NT_STATUS_OK;
2591 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2592 connection_struct *conn,
2593 struct dptr_struct *dirptr,
2594 uint16_t flags2,
2595 const char *path_mask,
2596 uint32_t dirtype,
2597 int info_level,
2598 bool requires_resume_key,
2599 bool dont_descend,
2600 bool ask_sharemode,
2601 char **ppdata,
2602 char *base_data,
2603 char *end_data,
2604 int space_remaining,
2605 bool *got_exact_match,
2606 int *last_entry_off,
2607 struct ea_list *name_list)
2609 uint8_t align = 4;
2610 const bool do_pad = true;
2612 if (info_level >= 1 && info_level <= 3) {
2613 /* No alignment on earlier info levels. */
2614 align = 1;
2617 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2618 path_mask, dirtype, info_level,
2619 requires_resume_key, dont_descend, ask_sharemode,
2620 true, align, do_pad,
2621 ppdata, base_data, end_data,
2622 space_remaining,
2623 NULL,
2624 got_exact_match,
2625 last_entry_off, name_list, NULL);
2628 /****************************************************************************
2629 Reply to a TRANS2_FINDFIRST.
2630 ****************************************************************************/
2632 static void call_trans2findfirst(connection_struct *conn,
2633 struct smb_request *req,
2634 char **pparams, int total_params,
2635 char **ppdata, int total_data,
2636 unsigned int max_data_bytes)
2638 /* We must be careful here that we don't return more than the
2639 allowed number of data bytes. If this means returning fewer than
2640 maxentries then so be it. We assume that the redirector has
2641 enough room for the fixed number of parameter bytes it has
2642 requested. */
2643 struct smb_filename *smb_dname = NULL;
2644 char *params = *pparams;
2645 char *pdata = *ppdata;
2646 char *data_end;
2647 uint32_t dirtype;
2648 int maxentries;
2649 uint16_t findfirst_flags;
2650 bool close_after_first;
2651 bool close_if_end;
2652 bool requires_resume_key;
2653 int info_level;
2654 char *directory = NULL;
2655 char *mask = NULL;
2656 char *p;
2657 int last_entry_off=0;
2658 int dptr_num = -1;
2659 int numentries = 0;
2660 int i;
2661 bool finished = False;
2662 bool dont_descend = False;
2663 bool out_of_space = False;
2664 int space_remaining;
2665 struct ea_list *ea_list = NULL;
2666 NTSTATUS ntstatus = NT_STATUS_OK;
2667 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
2668 struct smbd_server_connection *sconn = req->sconn;
2669 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2670 ucf_flags_from_smb_request(req);
2671 bool backup_priv = false;
2672 bool as_root = false;
2673 files_struct *fsp = NULL;
2674 const struct loadparm_substitution *lp_sub =
2675 loadparm_s3_global_substitution();
2676 int ret;
2678 if (total_params < 13) {
2679 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2680 goto out;
2683 dirtype = SVAL(params,0);
2684 maxentries = SVAL(params,2);
2685 findfirst_flags = SVAL(params,4);
2686 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2687 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2688 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2689 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2690 security_token_has_privilege(get_current_nttok(conn),
2691 SEC_PRIV_BACKUP));
2693 info_level = SVAL(params,6);
2695 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2696 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2697 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2698 (int)backup_priv,
2699 info_level, max_data_bytes));
2701 if (!maxentries) {
2702 /* W2K3 seems to treat zero as 1. */
2703 maxentries = 1;
2706 switch (info_level) {
2707 case SMB_FIND_INFO_STANDARD:
2708 case SMB_FIND_EA_SIZE:
2709 case SMB_FIND_EA_LIST:
2710 case SMB_FIND_FILE_DIRECTORY_INFO:
2711 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2712 case SMB_FIND_FILE_NAMES_INFO:
2713 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2714 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2715 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2716 break;
2717 case SMB_FIND_FILE_UNIX:
2718 case SMB_FIND_FILE_UNIX_INFO2:
2719 if (!lp_unix_extensions()) {
2720 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2721 goto out;
2723 break;
2724 default:
2725 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2726 goto out;
2729 if (req->posix_pathnames) {
2730 /* Always use filesystem for UNIX mtime query. */
2731 ask_sharemode = false;
2734 if (req->posix_pathnames) {
2735 srvstr_get_path_posix(talloc_tos(),
2736 params,
2737 req->flags2,
2738 &directory,
2739 params+12,
2740 total_params - 12,
2741 STR_TERMINATE,
2742 &ntstatus);
2743 } else {
2744 srvstr_get_path(talloc_tos(),
2745 params,
2746 req->flags2,
2747 &directory,
2748 params+12,
2749 total_params - 12,
2750 STR_TERMINATE,
2751 &ntstatus);
2753 if (!NT_STATUS_IS_OK(ntstatus)) {
2754 reply_nterror(req, ntstatus);
2755 goto out;
2758 if (backup_priv) {
2759 become_root();
2760 as_root = true;
2761 ntstatus = filename_convert_with_privilege(talloc_tos(),
2762 conn,
2763 req,
2764 directory,
2765 ucf_flags,
2766 &smb_dname);
2767 } else {
2768 ntstatus = filename_convert(talloc_tos(), conn,
2769 directory,
2770 ucf_flags,
2772 &smb_dname);
2775 if (!NT_STATUS_IS_OK(ntstatus)) {
2776 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2777 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2778 ERRSRV, ERRbadpath);
2779 goto out;
2781 reply_nterror(req, ntstatus);
2782 goto out;
2786 * The above call to filename_convert() is on the path from the client
2787 * including the search mask. Until the code that chops of the search
2788 * mask from the path below is moved before the call to
2789 * filename_convert(), we close a possible pathref fsp to ensure
2790 * SMB_VFS_CREATE_FILE() below will internally open a pathref fsp on the
2791 * correct path.
2793 if (smb_dname->fsp != NULL) {
2794 ntstatus = fd_close(smb_dname->fsp);
2795 if (!NT_STATUS_IS_OK(ntstatus)) {
2796 reply_nterror(req, ntstatus);
2797 goto out;
2800 * The pathref fsp link destructor will set smb_dname->fsp to
2801 * NULL. Turning this into an assert to give a hint at readers
2802 * of the code trying to understand the mechanics.
2804 file_free(req, smb_dname->fsp);
2805 SMB_ASSERT(smb_dname->fsp == NULL);
2808 mask = get_original_lcomp(talloc_tos(),
2809 conn,
2810 directory,
2811 ucf_flags);
2812 if (mask == NULL) {
2813 reply_nterror(req, NT_STATUS_NO_MEMORY);
2814 goto out;
2817 directory = smb_dname->base_name;
2819 p = strrchr_m(directory,'/');
2820 if(p == NULL) {
2821 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2822 if((directory[0] == '.') && (directory[1] == '\0')) {
2823 mask = talloc_strdup(talloc_tos(),"*");
2824 if (!mask) {
2825 reply_nterror(req, NT_STATUS_NO_MEMORY);
2826 goto out;
2829 } else {
2830 *p = 0;
2833 if (p == NULL || p == directory) {
2834 struct smb_filename *old_name = smb_dname;
2836 /* Ensure we don't have a directory name of "". */
2837 smb_dname = synthetic_smb_fname(talloc_tos(),
2838 ".",
2839 NULL,
2840 &old_name->st,
2841 old_name->twrp,
2842 old_name->flags);
2843 TALLOC_FREE(old_name);
2844 if (smb_dname == NULL) {
2845 reply_nterror(req, NT_STATUS_NO_MEMORY);
2846 goto out;
2848 directory = smb_dname->base_name;
2851 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2853 if (info_level == SMB_FIND_EA_LIST) {
2854 uint32_t ea_size;
2856 if (total_data < 4) {
2857 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2858 goto out;
2861 ea_size = IVAL(pdata,0);
2862 if (ea_size != total_data) {
2863 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2864 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2865 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2866 goto out;
2869 if (!lp_ea_support(SNUM(conn))) {
2870 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2871 goto out;
2874 /* Pull out the list of names. */
2875 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2876 if (!ea_list) {
2877 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2878 goto out;
2882 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2883 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2884 goto out;
2887 *ppdata = (char *)SMB_REALLOC(
2888 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2889 if(*ppdata == NULL ) {
2890 reply_nterror(req, NT_STATUS_NO_MEMORY);
2891 goto out;
2893 pdata = *ppdata;
2894 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2896 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2897 * error.
2899 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2900 /* Realloc the params space */
2901 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2902 if (*pparams == NULL) {
2903 reply_nterror(req, NT_STATUS_NO_MEMORY);
2904 goto out;
2906 params = *pparams;
2909 * As we've cut off the last component from
2910 * smb_fname we need to re-stat smb_dname
2911 * so FILE_OPEN disposition knows the directory
2912 * exists.
2914 ret = vfs_stat(conn, smb_dname);
2915 if (ret == -1) {
2916 ntstatus = map_nt_error_from_unix(errno);
2917 reply_nterror(req, ntstatus);
2918 goto out;
2921 ntstatus = openat_pathref_fsp(conn->cwd_fsp, smb_dname);
2922 if (!NT_STATUS_IS_OK(ntstatus)) {
2923 reply_nterror(req, ntstatus);
2924 goto out;
2928 * Open an fsp on this directory for the dptr.
2930 ntstatus = SMB_VFS_CREATE_FILE(
2931 conn, /* conn */
2932 req, /* req */
2933 smb_dname, /* dname */
2934 FILE_LIST_DIRECTORY, /* access_mask */
2935 FILE_SHARE_READ|
2936 FILE_SHARE_WRITE, /* share_access */
2937 FILE_OPEN, /* create_disposition*/
2938 FILE_DIRECTORY_FILE, /* create_options */
2939 FILE_ATTRIBUTE_DIRECTORY,/* file_attributes */
2940 NO_OPLOCK, /* oplock_request */
2941 NULL, /* lease */
2942 0, /* allocation_size */
2943 0, /* private_flags */
2944 NULL, /* sd */
2945 NULL, /* ea_list */
2946 &fsp, /* result */
2947 NULL, /* pinfo */
2948 NULL, /* in_context */
2949 NULL);/* out_context */
2951 if (!NT_STATUS_IS_OK(ntstatus)) {
2952 DBG_ERR("failed to open directory %s\n",
2953 smb_fname_str_dbg(smb_dname));
2954 reply_nterror(req, ntstatus);
2955 goto out;
2958 /* Save the wildcard match and attribs we are using on this directory -
2959 needed as lanman2 assumes these are being saved between calls */
2961 ntstatus = dptr_create(conn,
2962 req,
2963 fsp, /* fsp */
2964 False,
2965 True,
2966 req->smbpid,
2967 mask,
2968 dirtype,
2969 &fsp->dptr);
2971 if (!NT_STATUS_IS_OK(ntstatus)) {
2973 * Use NULL here for the first parameter (req)
2974 * as this is not a client visible handle so
2975 * can'tbe part of an SMB1 chain.
2977 close_file(NULL, fsp, NORMAL_CLOSE);
2978 fsp = NULL;
2979 reply_nterror(req, ntstatus);
2980 goto out;
2983 if (backup_priv) {
2984 /* Remember this in case we have
2985 to do a findnext. */
2986 dptr_set_priv(fsp->dptr);
2989 dptr_num = dptr_dnum(fsp->dptr);
2990 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2992 /* We don't need to check for VOL here as this is returned by
2993 a different TRANS2 call. */
2995 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2996 directory,lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn))));
2997 if (in_list(directory,
2998 lp_dont_descend(talloc_tos(), lp_sub, SNUM(conn)),
2999 conn->case_sensitive)) {
3000 dont_descend = True;
3003 p = pdata;
3004 space_remaining = max_data_bytes;
3005 out_of_space = False;
3007 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
3008 bool got_exact_match = False;
3010 /* this is a heuristic to avoid seeking the dirptr except when
3011 absolutely necessary. It allows for a filename of about 40 chars */
3012 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3013 out_of_space = True;
3014 finished = False;
3015 } else {
3016 ntstatus = get_lanman2_dir_entry(talloc_tos(),
3017 conn,
3018 fsp->dptr,
3019 req->flags2,
3020 mask,dirtype,info_level,
3021 requires_resume_key,dont_descend,
3022 ask_sharemode,
3023 &p,pdata,data_end,
3024 space_remaining,
3025 &got_exact_match,
3026 &last_entry_off, ea_list);
3027 if (NT_STATUS_EQUAL(ntstatus,
3028 NT_STATUS_ILLEGAL_CHARACTER)) {
3030 * Bad character conversion on name. Ignore this
3031 * entry.
3033 continue;
3035 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3036 out_of_space = true;
3037 } else {
3038 finished = !NT_STATUS_IS_OK(ntstatus);
3042 if (!finished && !out_of_space)
3043 numentries++;
3046 * As an optimisation if we know we aren't looking
3047 * for a wildcard name (ie. the name matches the wildcard exactly)
3048 * then we can finish on any (first) match.
3049 * This speeds up large directory searches. JRA.
3052 if(got_exact_match)
3053 finished = True;
3055 /* Ensure space_remaining never goes -ve. */
3056 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3057 space_remaining = 0;
3058 out_of_space = true;
3059 } else {
3060 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3064 /* Check if we can close the dirptr */
3065 if(close_after_first || (finished && close_if_end)) {
3066 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3067 dptr_num = -1;
3068 close_file(NULL, fsp, NORMAL_CLOSE);
3069 fsp = NULL;
3073 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3074 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3075 * the protocol level is less than NT1. Tested with smbclient. JRA.
3076 * This should fix the OS/2 client bug #2335.
3079 if(numentries == 0) {
3080 dptr_num = -1;
3082 * We may have already closed the file in the
3083 * close_after_first or finished case above.
3085 if (fsp != NULL) {
3086 close_file(NULL, fsp, NORMAL_CLOSE);
3087 fsp = NULL;
3089 if (get_Protocol() < PROTOCOL_NT1) {
3090 reply_force_doserror(req, ERRDOS, ERRnofiles);
3091 goto out;
3092 } else {
3093 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3094 ERRDOS, ERRbadfile);
3095 goto out;
3099 /* At this point pdata points to numentries directory entries. */
3101 /* Set up the return parameter block */
3102 SSVAL(params,0,dptr_num);
3103 SSVAL(params,2,numentries);
3104 SSVAL(params,4,finished);
3105 SSVAL(params,6,0); /* Never an EA error */
3106 SSVAL(params,8,last_entry_off);
3108 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3109 max_data_bytes);
3111 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3112 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3113 if (!directory) {
3114 reply_nterror(req, NT_STATUS_NO_MEMORY);
3118 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3119 smb_fn_name(req->cmd),
3120 mask, directory, dirtype, numentries ) );
3123 * Force a name mangle here to ensure that the
3124 * mask as an 8.3 name is top of the mangled cache.
3125 * The reasons for this are subtle. Don't remove
3126 * this code unless you know what you are doing
3127 * (see PR#13758). JRA.
3130 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3131 char mangled_name[13];
3132 name_to_8_3(mask, mangled_name, True, conn->params);
3134 out:
3136 if (as_root) {
3137 unbecome_root();
3140 TALLOC_FREE(smb_dname);
3141 return;
3144 /****************************************************************************
3145 Reply to a TRANS2_FINDNEXT.
3146 ****************************************************************************/
3148 static void call_trans2findnext(connection_struct *conn,
3149 struct smb_request *req,
3150 char **pparams, int total_params,
3151 char **ppdata, int total_data,
3152 unsigned int max_data_bytes)
3154 /* We must be careful here that we don't return more than the
3155 allowed number of data bytes. If this means returning fewer than
3156 maxentries then so be it. We assume that the redirector has
3157 enough room for the fixed number of parameter bytes it has
3158 requested. */
3159 char *params = *pparams;
3160 char *pdata = *ppdata;
3161 char *data_end;
3162 int dptr_num;
3163 int maxentries;
3164 uint16_t info_level;
3165 uint32_t resume_key;
3166 uint16_t findnext_flags;
3167 bool close_after_request;
3168 bool close_if_end;
3169 bool requires_resume_key;
3170 bool continue_bit;
3171 char *resume_name = NULL;
3172 const char *mask = NULL;
3173 const char *directory = NULL;
3174 char *p = NULL;
3175 uint16_t dirtype;
3176 int numentries = 0;
3177 int i, last_entry_off=0;
3178 bool finished = False;
3179 bool dont_descend = False;
3180 bool out_of_space = False;
3181 int space_remaining;
3182 struct ea_list *ea_list = NULL;
3183 NTSTATUS ntstatus = NT_STATUS_OK;
3184 bool ask_sharemode = lp_smbd_search_ask_sharemode(SNUM(conn));
3185 TALLOC_CTX *ctx = talloc_tos();
3186 struct smbd_server_connection *sconn = req->sconn;
3187 bool backup_priv = false;
3188 bool as_root = false;
3189 files_struct *fsp = NULL;
3190 const struct loadparm_substitution *lp_sub =
3191 loadparm_s3_global_substitution();
3193 if (total_params < 13) {
3194 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3195 return;
3198 dptr_num = SVAL(params,0);
3199 maxentries = SVAL(params,2);
3200 info_level = SVAL(params,4);
3201 resume_key = IVAL(params,6);
3202 findnext_flags = SVAL(params,10);
3203 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3204 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3205 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3206 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3208 if (!continue_bit) {
3209 /* We only need resume_name if continue_bit is zero. */
3210 if (req->posix_pathnames) {
3211 srvstr_get_path_posix(ctx,
3212 params,
3213 req->flags2,
3214 &resume_name,
3215 params+12,
3216 total_params - 12,
3217 STR_TERMINATE,
3218 &ntstatus);
3219 } else {
3220 srvstr_get_path(ctx,
3221 params,
3222 req->flags2,
3223 &resume_name,
3224 params+12,
3225 total_params - 12,
3226 STR_TERMINATE,
3227 &ntstatus);
3229 if (!NT_STATUS_IS_OK(ntstatus)) {
3230 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3231 complain (it thinks we're asking for the directory above the shared
3232 path or an invalid name). Catch this as the resume name is only compared, never used in
3233 a file access. JRA. */
3234 srvstr_pull_talloc(ctx, params, req->flags2,
3235 &resume_name, params+12,
3236 total_params - 12,
3237 STR_TERMINATE);
3239 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3240 reply_nterror(req, ntstatus);
3241 return;
3246 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3247 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3248 resume_key = %d resume name = %s continue=%d level = %d\n",
3249 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3250 requires_resume_key, resume_key,
3251 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3253 if (!maxentries) {
3254 /* W2K3 seems to treat zero as 1. */
3255 maxentries = 1;
3258 switch (info_level) {
3259 case SMB_FIND_INFO_STANDARD:
3260 case SMB_FIND_EA_SIZE:
3261 case SMB_FIND_EA_LIST:
3262 case SMB_FIND_FILE_DIRECTORY_INFO:
3263 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3264 case SMB_FIND_FILE_NAMES_INFO:
3265 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3266 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3267 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3268 break;
3269 case SMB_FIND_FILE_UNIX:
3270 case SMB_FIND_FILE_UNIX_INFO2:
3271 /* Always use filesystem for UNIX mtime query. */
3272 ask_sharemode = false;
3273 if (!lp_unix_extensions()) {
3274 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3275 return;
3277 break;
3278 default:
3279 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3280 return;
3283 if (info_level == SMB_FIND_EA_LIST) {
3284 uint32_t ea_size;
3286 if (total_data < 4) {
3287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3288 return;
3291 ea_size = IVAL(pdata,0);
3292 if (ea_size != total_data) {
3293 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3294 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3295 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3296 return;
3299 if (!lp_ea_support(SNUM(conn))) {
3300 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3301 return;
3304 /* Pull out the list of names. */
3305 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3306 if (!ea_list) {
3307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3308 return;
3312 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3314 return;
3317 *ppdata = (char *)SMB_REALLOC(
3318 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3319 if(*ppdata == NULL) {
3320 reply_nterror(req, NT_STATUS_NO_MEMORY);
3321 return;
3324 pdata = *ppdata;
3325 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3328 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3329 * error.
3331 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3332 /* Realloc the params space */
3333 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3334 if(*pparams == NULL ) {
3335 reply_nterror(req, NT_STATUS_NO_MEMORY);
3336 return;
3339 params = *pparams;
3341 /* Check that the dptr is valid */
3342 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
3343 if (fsp == NULL) {
3344 reply_nterror(req, STATUS_NO_MORE_FILES);
3345 return;
3348 directory = dptr_path(sconn, dptr_num);
3350 /* Get the wildcard mask from the dptr */
3351 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3352 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3353 reply_nterror(req, STATUS_NO_MORE_FILES);
3354 return;
3357 /* Get the attr mask from the dptr */
3358 dirtype = dptr_attr(sconn, dptr_num);
3360 backup_priv = dptr_get_priv(fsp->dptr);
3362 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3363 "backup_priv = %d\n",
3364 dptr_num, mask, dirtype,
3365 (long)fsp->dptr,
3366 dptr_TellDir(fsp->dptr),
3367 (int)backup_priv));
3369 /* We don't need to check for VOL here as this is returned by
3370 a different TRANS2 call. */
3372 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3373 directory,lp_dont_descend(ctx, lp_sub, SNUM(conn))));
3374 if (in_list(directory,lp_dont_descend(ctx, lp_sub, SNUM(conn)),conn->case_sensitive))
3375 dont_descend = True;
3377 p = pdata;
3378 space_remaining = max_data_bytes;
3379 out_of_space = False;
3381 if (backup_priv) {
3382 become_root();
3383 as_root = true;
3387 * Seek to the correct position. We no longer use the resume key but
3388 * depend on the last file name instead.
3391 if(!continue_bit && resume_name && *resume_name) {
3392 SMB_STRUCT_STAT st;
3394 long current_pos = 0;
3396 * Remember, name_to_8_3 is called by
3397 * get_lanman2_dir_entry(), so the resume name
3398 * could be mangled. Ensure we check the unmangled name.
3401 if (mangle_is_mangled(resume_name, conn->params)) {
3402 char *new_resume_name = NULL;
3403 mangle_lookup_name_from_8_3(ctx,
3404 resume_name,
3405 &new_resume_name,
3406 conn->params);
3407 if (new_resume_name) {
3408 resume_name = new_resume_name;
3413 * Fix for NT redirector problem triggered by resume key indexes
3414 * changing between directory scans. We now return a resume key of 0
3415 * and instead look for the filename to continue from (also given
3416 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3417 * findfirst/findnext (as is usual) then the directory pointer
3418 * should already be at the correct place.
3421 finished = !dptr_SearchDir(fsp->dptr, resume_name, &current_pos, &st);
3422 } /* end if resume_name && !continue_bit */
3424 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3425 bool got_exact_match = False;
3427 /* this is a heuristic to avoid seeking the fsp->dptr except when
3428 absolutely necessary. It allows for a filename of about 40 chars */
3429 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3430 out_of_space = True;
3431 finished = False;
3432 } else {
3433 ntstatus = get_lanman2_dir_entry(ctx,
3434 conn,
3435 fsp->dptr,
3436 req->flags2,
3437 mask,dirtype,info_level,
3438 requires_resume_key,dont_descend,
3439 ask_sharemode,
3440 &p,pdata,data_end,
3441 space_remaining,
3442 &got_exact_match,
3443 &last_entry_off, ea_list);
3444 if (NT_STATUS_EQUAL(ntstatus,
3445 NT_STATUS_ILLEGAL_CHARACTER)) {
3447 * Bad character conversion on name. Ignore this
3448 * entry.
3450 continue;
3452 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3453 out_of_space = true;
3454 } else {
3455 finished = !NT_STATUS_IS_OK(ntstatus);
3459 if (!finished && !out_of_space)
3460 numentries++;
3463 * As an optimisation if we know we aren't looking
3464 * for a wildcard name (ie. the name matches the wildcard exactly)
3465 * then we can finish on any (first) match.
3466 * This speeds up large directory searches. JRA.
3469 if(got_exact_match)
3470 finished = True;
3472 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3475 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3476 smb_fn_name(req->cmd),
3477 mask, directory, dirtype, numentries ) );
3479 /* Check if we can close the fsp->dptr */
3480 if(close_after_request || (finished && close_if_end)) {
3481 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3482 dptr_num = -1;
3483 close_file(NULL, fsp, NORMAL_CLOSE);
3484 fsp = NULL;
3487 if (as_root) {
3488 unbecome_root();
3491 /* Set up the return parameter block */
3492 SSVAL(params,0,numentries);
3493 SSVAL(params,2,finished);
3494 SSVAL(params,4,0); /* Never an EA error */
3495 SSVAL(params,6,last_entry_off);
3497 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3498 max_data_bytes);
3500 return;
3503 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3505 const struct loadparm_substitution *lp_sub =
3506 loadparm_s3_global_substitution();
3508 E_md4hash(lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),objid);
3509 return objid;
3512 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3514 SMB_ASSERT(extended_info != NULL);
3516 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3517 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3518 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3519 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3520 #ifdef SAMBA_VERSION_REVISION
3521 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3522 #endif
3523 extended_info->samba_subversion = 0;
3524 #ifdef SAMBA_VERSION_RC_RELEASE
3525 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3526 #else
3527 #ifdef SAMBA_VERSION_PRE_RELEASE
3528 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3529 #endif
3530 #endif
3531 #ifdef SAMBA_VERSION_VENDOR_PATCH
3532 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3533 #endif
3534 extended_info->samba_gitcommitdate = 0;
3535 #ifdef SAMBA_VERSION_COMMIT_TIME
3536 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3537 #endif
3539 memset(extended_info->samba_version_string, 0,
3540 sizeof(extended_info->samba_version_string));
3542 snprintf (extended_info->samba_version_string,
3543 sizeof(extended_info->samba_version_string),
3544 "%s", samba_version_string());
3547 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3548 connection_struct *conn,
3549 TALLOC_CTX *mem_ctx,
3550 uint16_t info_level,
3551 uint16_t flags2,
3552 unsigned int max_data_bytes,
3553 size_t *fixed_portion,
3554 struct smb_filename *fname,
3555 char **ppdata,
3556 int *ret_data_len)
3558 const struct loadparm_substitution *lp_sub =
3559 loadparm_s3_global_substitution();
3560 char *pdata, *end_data;
3561 int data_len = 0;
3562 size_t len = 0;
3563 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3564 int snum = SNUM(conn);
3565 const char *fstype = lp_fstype(SNUM(conn));
3566 const char *filename = NULL;
3567 const uint64_t bytes_per_sector = 512;
3568 uint32_t additional_flags = 0;
3569 struct smb_filename smb_fname;
3570 SMB_STRUCT_STAT st;
3571 NTSTATUS status = NT_STATUS_OK;
3572 uint64_t df_ret;
3574 if (fname == NULL || fname->base_name == NULL) {
3575 filename = ".";
3576 } else {
3577 filename = fname->base_name;
3580 if (IS_IPC(conn)) {
3581 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3582 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3583 "info level (0x%x) on IPC$.\n",
3584 (unsigned int)info_level));
3585 return NT_STATUS_ACCESS_DENIED;
3589 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3591 smb_fname = (struct smb_filename) {
3592 .base_name = discard_const_p(char, filename),
3593 .flags = fname ? fname->flags : 0,
3594 .twrp = fname ? fname->twrp : 0,
3597 if(info_level != SMB_FS_QUOTA_INFORMATION
3598 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3599 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3600 return map_nt_error_from_unix(errno);
3603 st = smb_fname.st;
3605 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3606 return NT_STATUS_INVALID_PARAMETER;
3609 *ppdata = (char *)SMB_REALLOC(
3610 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3611 if (*ppdata == NULL) {
3612 return NT_STATUS_NO_MEMORY;
3615 pdata = *ppdata;
3616 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3617 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3619 *fixed_portion = 0;
3621 switch (info_level) {
3622 case SMB_INFO_ALLOCATION:
3624 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3625 data_len = 18;
3626 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3627 &dfree, &dsize);
3628 if (df_ret == (uint64_t)-1) {
3629 return map_nt_error_from_unix(errno);
3632 block_size = lp_block_size(snum);
3633 if (bsize < block_size) {
3634 uint64_t factor = block_size/bsize;
3635 bsize = block_size;
3636 dsize /= factor;
3637 dfree /= factor;
3639 if (bsize > block_size) {
3640 uint64_t factor = bsize/block_size;
3641 bsize = block_size;
3642 dsize *= factor;
3643 dfree *= factor;
3645 sectors_per_unit = bsize/bytes_per_sector;
3647 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3648 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3649 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3652 * For large drives, return max values and not modulo.
3654 dsize = MIN(dsize, UINT32_MAX);
3655 dfree = MIN(dfree, UINT32_MAX);
3657 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3658 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3659 SIVAL(pdata,l1_cUnit,dsize);
3660 SIVAL(pdata,l1_cUnitAvail,dfree);
3661 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3662 break;
3665 case SMB_INFO_VOLUME:
3666 /* Return volume name */
3668 * Add volume serial number - hash of a combination of
3669 * the called hostname and the service name.
3671 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3673 * Win2k3 and previous mess this up by sending a name length
3674 * one byte short. I believe only older clients (OS/2 Win9x) use
3675 * this call so try fixing this by adding a terminating null to
3676 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3678 status = srvstr_push(
3679 pdata, flags2,
3680 pdata+l2_vol_szVolLabel, vname,
3681 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3682 STR_NOALIGN|STR_TERMINATE, &len);
3683 if (!NT_STATUS_IS_OK(status)) {
3684 return status;
3686 SCVAL(pdata,l2_vol_cch,len);
3687 data_len = l2_vol_szVolLabel + len;
3688 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3689 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3690 (unsigned)len, vname));
3691 break;
3693 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3694 case SMB_FS_ATTRIBUTE_INFORMATION:
3696 additional_flags = 0;
3697 #if defined(HAVE_SYS_QUOTAS)
3698 additional_flags |= FILE_VOLUME_QUOTAS;
3699 #endif
3701 if(lp_nt_acl_support(SNUM(conn))) {
3702 additional_flags |= FILE_PERSISTENT_ACLS;
3705 /* Capabilities are filled in at connection time through STATVFS call */
3706 additional_flags |= conn->fs_capabilities;
3707 additional_flags |= lp_parm_int(conn->params->service,
3708 "share", "fake_fscaps",
3711 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3712 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3713 additional_flags); /* FS ATTRIBUTES */
3715 SIVAL(pdata,4,255); /* Max filename component length */
3716 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3717 and will think we can't do long filenames */
3718 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3719 PTR_DIFF(end_data, pdata+12),
3720 STR_UNICODE, &len);
3721 if (!NT_STATUS_IS_OK(status)) {
3722 return status;
3724 SIVAL(pdata,8,len);
3725 data_len = 12 + len;
3726 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3727 /* the client only requested a portion of the
3728 file system name */
3729 data_len = max_data_bytes;
3730 status = STATUS_BUFFER_OVERFLOW;
3732 *fixed_portion = 16;
3733 break;
3735 case SMB_QUERY_FS_LABEL_INFO:
3736 case SMB_FS_LABEL_INFORMATION:
3737 status = srvstr_push(pdata, flags2, pdata+4, vname,
3738 PTR_DIFF(end_data, pdata+4), 0, &len);
3739 if (!NT_STATUS_IS_OK(status)) {
3740 return status;
3742 data_len = 4 + len;
3743 SIVAL(pdata,0,len);
3744 break;
3746 case SMB_QUERY_FS_VOLUME_INFO:
3747 case SMB_FS_VOLUME_INFORMATION:
3750 * Add volume serial number - hash of a combination of
3751 * the called hostname and the service name.
3753 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), lp_sub, snum)) ^
3754 (str_checksum(get_local_machine_name())<<16));
3756 /* Max label len is 32 characters. */
3757 status = srvstr_push(pdata, flags2, pdata+18, vname,
3758 PTR_DIFF(end_data, pdata+18),
3759 STR_UNICODE, &len);
3760 if (!NT_STATUS_IS_OK(status)) {
3761 return status;
3763 SIVAL(pdata,12,len);
3764 data_len = 18+len;
3766 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3767 (int)strlen(vname),vname,
3768 lp_servicename(talloc_tos(), lp_sub, snum)));
3769 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3770 /* the client only requested a portion of the
3771 volume label */
3772 data_len = max_data_bytes;
3773 status = STATUS_BUFFER_OVERFLOW;
3775 *fixed_portion = 24;
3776 break;
3778 case SMB_QUERY_FS_SIZE_INFO:
3779 case SMB_FS_SIZE_INFORMATION:
3781 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3782 data_len = 24;
3783 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3784 &dfree, &dsize);
3785 if (df_ret == (uint64_t)-1) {
3786 return map_nt_error_from_unix(errno);
3788 block_size = lp_block_size(snum);
3789 if (bsize < block_size) {
3790 uint64_t factor = block_size/bsize;
3791 bsize = block_size;
3792 dsize /= factor;
3793 dfree /= factor;
3795 if (bsize > block_size) {
3796 uint64_t factor = bsize/block_size;
3797 bsize = block_size;
3798 dsize *= factor;
3799 dfree *= factor;
3801 sectors_per_unit = bsize/bytes_per_sector;
3802 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3803 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3804 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3805 SBIG_UINT(pdata,0,dsize);
3806 SBIG_UINT(pdata,8,dfree);
3807 SIVAL(pdata,16,sectors_per_unit);
3808 SIVAL(pdata,20,bytes_per_sector);
3809 *fixed_portion = 24;
3810 break;
3813 case SMB_FS_FULL_SIZE_INFORMATION:
3815 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3816 data_len = 32;
3817 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3818 &dfree, &dsize);
3819 if (df_ret == (uint64_t)-1) {
3820 return map_nt_error_from_unix(errno);
3822 block_size = lp_block_size(snum);
3823 if (bsize < block_size) {
3824 uint64_t factor = block_size/bsize;
3825 bsize = block_size;
3826 dsize /= factor;
3827 dfree /= factor;
3829 if (bsize > block_size) {
3830 uint64_t factor = bsize/block_size;
3831 bsize = block_size;
3832 dsize *= factor;
3833 dfree *= factor;
3835 sectors_per_unit = bsize/bytes_per_sector;
3836 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3837 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3838 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3839 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3840 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3841 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3842 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3843 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3844 *fixed_portion = 32;
3845 break;
3848 case SMB_QUERY_FS_DEVICE_INFO:
3849 case SMB_FS_DEVICE_INFORMATION:
3851 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3853 if (!CAN_WRITE(conn)) {
3854 characteristics |= FILE_READ_ONLY_DEVICE;
3856 data_len = 8;
3857 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3858 SIVAL(pdata,4,characteristics);
3859 *fixed_portion = 8;
3860 break;
3863 #ifdef HAVE_SYS_QUOTAS
3864 case SMB_FS_QUOTA_INFORMATION:
3866 * what we have to send --metze:
3868 * Unknown1: 24 NULL bytes
3869 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3870 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3871 * Quota Flags: 2 byte :
3872 * Unknown3: 6 NULL bytes
3874 * 48 bytes total
3876 * details for Quota Flags:
3878 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3879 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3880 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3881 * 0x0001 Enable Quotas: enable quota for this fs
3885 /* we need to fake up a fsp here,
3886 * because its not send in this call
3888 files_struct fsp;
3889 SMB_NTQUOTA_STRUCT quotas;
3891 ZERO_STRUCT(fsp);
3892 ZERO_STRUCT(quotas);
3894 fsp.conn = conn;
3895 fsp.fnum = FNUM_FIELD_INVALID;
3897 /* access check */
3898 if (get_current_uid(conn) != 0) {
3899 DEBUG(0,("get_user_quota: access_denied "
3900 "service [%s] user [%s]\n",
3901 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
3902 conn->session_info->unix_info->unix_name));
3903 return NT_STATUS_ACCESS_DENIED;
3906 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3907 NULL, &quotas);
3908 if (!NT_STATUS_IS_OK(status)) {
3909 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3910 return status;
3913 data_len = 48;
3915 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3916 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
3918 /* Unknown1 24 NULL bytes*/
3919 SBIG_UINT(pdata,0,(uint64_t)0);
3920 SBIG_UINT(pdata,8,(uint64_t)0);
3921 SBIG_UINT(pdata,16,(uint64_t)0);
3923 /* Default Soft Quota 8 bytes */
3924 SBIG_UINT(pdata,24,quotas.softlim);
3926 /* Default Hard Quota 8 bytes */
3927 SBIG_UINT(pdata,32,quotas.hardlim);
3929 /* Quota flag 2 bytes */
3930 SSVAL(pdata,40,quotas.qflags);
3932 /* Unknown3 6 NULL bytes */
3933 SSVAL(pdata,42,0);
3934 SIVAL(pdata,44,0);
3936 break;
3938 #endif /* HAVE_SYS_QUOTAS */
3939 case SMB_FS_OBJECTID_INFORMATION:
3941 unsigned char objid[16];
3942 struct smb_extended_info extended_info;
3943 memcpy(pdata,create_volume_objectid(conn, objid),16);
3944 samba_extended_info_version (&extended_info);
3945 SIVAL(pdata,16,extended_info.samba_magic);
3946 SIVAL(pdata,20,extended_info.samba_version);
3947 SIVAL(pdata,24,extended_info.samba_subversion);
3948 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3949 memcpy(pdata+36,extended_info.samba_version_string,28);
3950 data_len = 64;
3951 break;
3954 case SMB_FS_SECTOR_SIZE_INFORMATION:
3956 data_len = 28;
3958 * These values match a physical Windows Server 2012
3959 * share backed by NTFS atop spinning rust.
3961 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3962 /* logical_bytes_per_sector */
3963 SIVAL(pdata, 0, bytes_per_sector);
3964 /* phys_bytes_per_sector_atomic */
3965 SIVAL(pdata, 4, bytes_per_sector);
3966 /* phys_bytes_per_sector_perf */
3967 SIVAL(pdata, 8, bytes_per_sector);
3968 /* fs_effective_phys_bytes_per_sector_atomic */
3969 SIVAL(pdata, 12, bytes_per_sector);
3970 /* flags */
3971 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3972 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3973 /* byte_off_sector_align */
3974 SIVAL(pdata, 20, 0);
3975 /* byte_off_partition_align */
3976 SIVAL(pdata, 24, 0);
3977 *fixed_portion = 28;
3978 break;
3983 * Query the version and capabilities of the CIFS UNIX extensions
3984 * in use.
3987 case SMB_QUERY_CIFS_UNIX_INFO:
3989 bool large_write = lp_min_receive_file_size() &&
3990 !srv_is_signing_active(xconn);
3991 bool large_read = !srv_is_signing_active(xconn);
3992 int encrypt_caps = 0;
3994 if (!lp_unix_extensions()) {
3995 return NT_STATUS_INVALID_LEVEL;
3998 switch (conn->encrypt_level) {
3999 case SMB_SIGNING_OFF:
4000 encrypt_caps = 0;
4001 break;
4002 case SMB_SIGNING_DESIRED:
4003 case SMB_SIGNING_IF_REQUIRED:
4004 case SMB_SIGNING_DEFAULT:
4005 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
4006 break;
4007 case SMB_SIGNING_REQUIRED:
4008 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
4009 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
4010 large_write = false;
4011 large_read = false;
4012 break;
4015 data_len = 12;
4016 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
4017 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
4019 /* We have POSIX ACLs, pathname, encryption,
4020 * large read/write, and locking capability. */
4022 SBIG_UINT(pdata,4,((uint64_t)(
4023 CIFS_UNIX_POSIX_ACLS_CAP|
4024 CIFS_UNIX_POSIX_PATHNAMES_CAP|
4025 CIFS_UNIX_FCNTL_LOCKS_CAP|
4026 CIFS_UNIX_EXTATTR_CAP|
4027 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
4028 encrypt_caps|
4029 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
4030 (large_write ?
4031 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
4032 break;
4035 case SMB_QUERY_POSIX_FS_INFO:
4037 int rc;
4038 vfs_statvfs_struct svfs;
4040 if (!lp_unix_extensions()) {
4041 return NT_STATUS_INVALID_LEVEL;
4044 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
4046 if (!rc) {
4047 data_len = 56;
4048 SIVAL(pdata,0,svfs.OptimalTransferSize);
4049 SIVAL(pdata,4,svfs.BlockSize);
4050 SBIG_UINT(pdata,8,svfs.TotalBlocks);
4051 SBIG_UINT(pdata,16,svfs.BlocksAvail);
4052 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
4053 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
4054 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
4055 SBIG_UINT(pdata,48,svfs.FsIdentifier);
4056 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
4057 #ifdef EOPNOTSUPP
4058 } else if (rc == EOPNOTSUPP) {
4059 return NT_STATUS_INVALID_LEVEL;
4060 #endif /* EOPNOTSUPP */
4061 } else {
4062 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4063 return NT_STATUS_DOS(ERRSRV, ERRerror);
4065 break;
4068 case SMB_QUERY_POSIX_WHOAMI:
4070 uint32_t flags = 0;
4071 uint32_t sid_bytes;
4072 int i;
4074 if (!lp_unix_extensions()) {
4075 return NT_STATUS_INVALID_LEVEL;
4078 if (max_data_bytes < 40) {
4079 return NT_STATUS_BUFFER_TOO_SMALL;
4082 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4083 flags |= SMB_WHOAMI_GUEST;
4086 /* NOTE: 8 bytes for UID/GID, irrespective of native
4087 * platform size. This matches
4088 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4090 data_len = 4 /* flags */
4091 + 4 /* flag mask */
4092 + 8 /* uid */
4093 + 8 /* gid */
4094 + 4 /* ngroups */
4095 + 4 /* num_sids */
4096 + 4 /* SID bytes */
4097 + 4 /* pad/reserved */
4098 + (conn->session_info->unix_token->ngroups * 8)
4099 /* groups list */
4100 + (conn->session_info->security_token->num_sids *
4101 SID_MAX_SIZE)
4102 /* SID list */;
4104 SIVAL(pdata, 0, flags);
4105 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4106 SBIG_UINT(pdata, 8,
4107 (uint64_t)conn->session_info->unix_token->uid);
4108 SBIG_UINT(pdata, 16,
4109 (uint64_t)conn->session_info->unix_token->gid);
4112 if (data_len >= max_data_bytes) {
4113 /* Potential overflow, skip the GIDs and SIDs. */
4115 SIVAL(pdata, 24, 0); /* num_groups */
4116 SIVAL(pdata, 28, 0); /* num_sids */
4117 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4118 SIVAL(pdata, 36, 0); /* reserved */
4120 data_len = 40;
4121 break;
4124 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4125 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4127 /* We walk the SID list twice, but this call is fairly
4128 * infrequent, and I don't expect that it's performance
4129 * sensitive -- jpeach
4131 for (i = 0, sid_bytes = 0;
4132 i < conn->session_info->security_token->num_sids; ++i) {
4133 sid_bytes += ndr_size_dom_sid(
4134 &conn->session_info->security_token->sids[i],
4138 /* SID list byte count */
4139 SIVAL(pdata, 32, sid_bytes);
4141 /* 4 bytes pad/reserved - must be zero */
4142 SIVAL(pdata, 36, 0);
4143 data_len = 40;
4145 /* GID list */
4146 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4147 SBIG_UINT(pdata, data_len,
4148 (uint64_t)conn->session_info->unix_token->groups[i]);
4149 data_len += 8;
4152 /* SID list */
4153 for (i = 0;
4154 i < conn->session_info->security_token->num_sids; ++i) {
4155 int sid_len = ndr_size_dom_sid(
4156 &conn->session_info->security_token->sids[i],
4159 sid_linearize((uint8_t *)(pdata + data_len),
4160 sid_len,
4161 &conn->session_info->security_token->sids[i]);
4162 data_len += sid_len;
4165 break;
4168 case SMB_MAC_QUERY_FS_INFO:
4170 * Thursby MAC extension... ONLY on NTFS filesystems
4171 * once we do streams then we don't need this
4173 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4174 data_len = 88;
4175 SIVAL(pdata,84,0x100); /* Don't support mac... */
4176 break;
4179 FALL_THROUGH;
4180 default:
4181 return NT_STATUS_INVALID_LEVEL;
4184 *ret_data_len = data_len;
4185 return status;
4188 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4189 struct smb_request *req,
4190 files_struct *fsp,
4191 const DATA_BLOB *qdata)
4193 const struct loadparm_substitution *lp_sub =
4194 loadparm_s3_global_substitution();
4195 NTSTATUS status;
4196 SMB_NTQUOTA_STRUCT quotas;
4198 ZERO_STRUCT(quotas);
4200 /* access check */
4201 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4202 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4203 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
4204 conn->session_info->unix_info->unix_name));
4205 return NT_STATUS_ACCESS_DENIED;
4208 if (!check_fsp_ntquota_handle(conn, req,
4209 fsp)) {
4210 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4211 return NT_STATUS_INVALID_HANDLE;
4214 /* note: normally there're 48 bytes,
4215 * but we didn't use the last 6 bytes for now
4216 * --metze
4218 if (qdata->length < 42) {
4219 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4220 (unsigned int)qdata->length));
4221 return NT_STATUS_INVALID_PARAMETER;
4224 /* unknown_1 24 NULL bytes in pdata*/
4226 /* the soft quotas 8 bytes (uint64_t)*/
4227 quotas.softlim = BVAL(qdata->data,24);
4229 /* the hard quotas 8 bytes (uint64_t)*/
4230 quotas.hardlim = BVAL(qdata->data,32);
4232 /* quota_flags 2 bytes **/
4233 quotas.qflags = SVAL(qdata->data,40);
4235 /* unknown_2 6 NULL bytes follow*/
4237 /* now set the quotas */
4238 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4239 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4240 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4241 status = map_nt_error_from_unix(errno);
4242 } else {
4243 status = NT_STATUS_OK;
4245 return status;
4248 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4249 struct smb_request *req,
4250 TALLOC_CTX *mem_ctx,
4251 uint16_t info_level,
4252 files_struct *fsp,
4253 const DATA_BLOB *pdata)
4255 switch (info_level) {
4256 case SMB_FS_QUOTA_INFORMATION:
4258 return smb_set_fsquota(conn,
4259 req,
4260 fsp,
4261 pdata);
4264 default:
4265 break;
4267 return NT_STATUS_INVALID_LEVEL;
4270 /****************************************************************************
4271 Reply to a TRANS2_QFSINFO (query filesystem info).
4272 ****************************************************************************/
4274 static void call_trans2qfsinfo(connection_struct *conn,
4275 struct smb_request *req,
4276 char **pparams, int total_params,
4277 char **ppdata, int total_data,
4278 unsigned int max_data_bytes)
4280 char *params = *pparams;
4281 uint16_t info_level;
4282 int data_len = 0;
4283 size_t fixed_portion;
4284 NTSTATUS status;
4286 if (total_params < 2) {
4287 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4288 return;
4291 info_level = SVAL(params,0);
4293 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4294 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4295 DEBUG(0,("call_trans2qfsinfo: encryption required "
4296 "and info level 0x%x sent.\n",
4297 (unsigned int)info_level));
4298 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4299 return;
4303 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4305 status = smbd_do_qfsinfo(req->xconn, conn, req,
4306 info_level,
4307 req->flags2,
4308 max_data_bytes,
4309 &fixed_portion,
4310 NULL,
4311 ppdata, &data_len);
4312 if (!NT_STATUS_IS_OK(status)) {
4313 reply_nterror(req, status);
4314 return;
4317 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4318 max_data_bytes);
4320 DEBUG( 4, ( "%s info_level = %d\n",
4321 smb_fn_name(req->cmd), info_level) );
4323 return;
4326 /****************************************************************************
4327 Reply to a TRANS2_SETFSINFO (set filesystem info).
4328 ****************************************************************************/
4330 static void call_trans2setfsinfo(connection_struct *conn,
4331 struct smb_request *req,
4332 char **pparams, int total_params,
4333 char **ppdata, int total_data,
4334 unsigned int max_data_bytes)
4336 const struct loadparm_substitution *lp_sub =
4337 loadparm_s3_global_substitution();
4338 struct smbXsrv_connection *xconn = req->xconn;
4339 char *pdata = *ppdata;
4340 char *params = *pparams;
4341 uint16_t info_level;
4343 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4344 lp_servicename(talloc_tos(), lp_sub, SNUM(conn))));
4346 /* */
4347 if (total_params < 4) {
4348 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4349 total_params));
4350 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4351 return;
4354 info_level = SVAL(params,2);
4356 if (IS_IPC(conn)) {
4357 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4358 info_level != SMB_SET_CIFS_UNIX_INFO) {
4359 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4360 "info level (0x%x) on IPC$.\n",
4361 (unsigned int)info_level));
4362 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4363 return;
4367 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4368 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4369 DEBUG(0,("call_trans2setfsinfo: encryption required "
4370 "and info level 0x%x sent.\n",
4371 (unsigned int)info_level));
4372 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4373 return;
4377 switch(info_level) {
4378 case SMB_SET_CIFS_UNIX_INFO:
4379 if (!lp_unix_extensions()) {
4380 DEBUG(2,("call_trans2setfsinfo: "
4381 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4382 "unix extensions off\n"));
4383 reply_nterror(req,
4384 NT_STATUS_INVALID_LEVEL);
4385 return;
4388 /* There should be 12 bytes of capabilities set. */
4389 if (total_data < 12) {
4390 reply_nterror(
4391 req,
4392 NT_STATUS_INVALID_PARAMETER);
4393 return;
4395 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4396 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4397 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4398 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4399 /* Just print these values for now. */
4400 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4401 "major = %u, minor = %u cap_low = 0x%x, "
4402 "cap_high = 0x%xn",
4403 (unsigned int)xconn->
4404 smb1.unix_info.client_major,
4405 (unsigned int)xconn->
4406 smb1.unix_info.client_minor,
4407 (unsigned int)xconn->
4408 smb1.unix_info.client_cap_low,
4409 (unsigned int)xconn->
4410 smb1.unix_info.client_cap_high));
4412 /* Here is where we must switch to posix pathname processing... */
4413 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4414 lp_set_posix_pathnames();
4415 mangle_change_to_posix();
4418 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4419 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4420 /* Client that knows how to do posix locks,
4421 * but not posix open/mkdir operations. Set a
4422 * default type for read/write checks. */
4424 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4427 break;
4429 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4431 NTSTATUS status;
4432 size_t param_len = 0;
4433 size_t data_len = total_data;
4435 if (!lp_unix_extensions()) {
4436 reply_nterror(
4437 req,
4438 NT_STATUS_INVALID_LEVEL);
4439 return;
4442 if (lp_server_smb_encrypt(SNUM(conn)) ==
4443 SMB_ENCRYPTION_OFF) {
4444 reply_nterror(
4445 req,
4446 NT_STATUS_NOT_SUPPORTED);
4447 return;
4450 if (xconn->smb1.echo_handler.trusted_fde) {
4451 DEBUG( 2,("call_trans2setfsinfo: "
4452 "request transport encryption disabled"
4453 "with 'fork echo handler = yes'\n"));
4454 reply_nterror(
4455 req,
4456 NT_STATUS_NOT_SUPPORTED);
4457 return;
4460 DEBUG( 4,("call_trans2setfsinfo: "
4461 "request transport encryption.\n"));
4463 status = srv_request_encryption_setup(conn,
4464 (unsigned char **)ppdata,
4465 &data_len,
4466 (unsigned char **)pparams,
4467 &param_len);
4469 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4470 !NT_STATUS_IS_OK(status)) {
4471 reply_nterror(req, status);
4472 return;
4475 send_trans2_replies(conn, req,
4476 NT_STATUS_OK,
4477 *pparams,
4478 param_len,
4479 *ppdata,
4480 data_len,
4481 max_data_bytes);
4483 if (NT_STATUS_IS_OK(status)) {
4484 /* Server-side transport
4485 * encryption is now *on*. */
4486 status = srv_encryption_start(conn);
4487 if (!NT_STATUS_IS_OK(status)) {
4488 char *reason = talloc_asprintf(talloc_tos(),
4489 "Failure in setting "
4490 "up encrypted transport: %s",
4491 nt_errstr(status));
4492 exit_server_cleanly(reason);
4495 return;
4498 case SMB_FS_QUOTA_INFORMATION:
4500 NTSTATUS status;
4501 DATA_BLOB qdata = {
4502 .data = (uint8_t *)pdata,
4503 .length = total_data
4505 files_struct *fsp = NULL;
4506 fsp = file_fsp(req, SVAL(params,0));
4508 status = smb_set_fsquota(conn,
4509 req,
4510 fsp,
4511 &qdata);
4512 if (!NT_STATUS_IS_OK(status)) {
4513 reply_nterror(req, status);
4514 return;
4516 break;
4518 default:
4519 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4520 info_level));
4521 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4522 return;
4523 break;
4527 * sending this reply works fine,
4528 * but I'm not sure it's the same
4529 * like windows do...
4530 * --metze
4532 reply_outbuf(req, 10, 0);
4535 #if defined(HAVE_POSIX_ACLS)
4536 /****************************************************************************
4537 Utility function to count the number of entries in a POSIX acl.
4538 ****************************************************************************/
4540 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4542 unsigned int ace_count = 0;
4543 int entry_id = SMB_ACL_FIRST_ENTRY;
4544 SMB_ACL_ENTRY_T entry;
4546 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4547 /* get_next... */
4548 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4549 entry_id = SMB_ACL_NEXT_ENTRY;
4551 ace_count++;
4553 return ace_count;
4556 /****************************************************************************
4557 Utility function to marshall a POSIX acl into wire format.
4558 ****************************************************************************/
4560 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4562 int entry_id = SMB_ACL_FIRST_ENTRY;
4563 SMB_ACL_ENTRY_T entry;
4565 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4566 SMB_ACL_TAG_T tagtype;
4567 SMB_ACL_PERMSET_T permset;
4568 unsigned char perms = 0;
4569 unsigned int own_grp;
4571 /* get_next... */
4572 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4573 entry_id = SMB_ACL_NEXT_ENTRY;
4576 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4577 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4578 return False;
4581 if (sys_acl_get_permset(entry, &permset) == -1) {
4582 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4583 return False;
4586 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4587 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4588 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4590 SCVAL(pdata,1,perms);
4592 switch (tagtype) {
4593 case SMB_ACL_USER_OBJ:
4594 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4595 own_grp = (unsigned int)pst->st_ex_uid;
4596 SIVAL(pdata,2,own_grp);
4597 SIVAL(pdata,6,0);
4598 break;
4599 case SMB_ACL_USER:
4601 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4602 if (!puid) {
4603 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4604 return False;
4606 own_grp = (unsigned int)*puid;
4607 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4608 SIVAL(pdata,2,own_grp);
4609 SIVAL(pdata,6,0);
4610 break;
4612 case SMB_ACL_GROUP_OBJ:
4613 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4614 own_grp = (unsigned int)pst->st_ex_gid;
4615 SIVAL(pdata,2,own_grp);
4616 SIVAL(pdata,6,0);
4617 break;
4618 case SMB_ACL_GROUP:
4620 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4621 if (!pgid) {
4622 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4623 return False;
4625 own_grp = (unsigned int)*pgid;
4626 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4627 SIVAL(pdata,2,own_grp);
4628 SIVAL(pdata,6,0);
4629 break;
4631 case SMB_ACL_MASK:
4632 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4633 SIVAL(pdata,2,0xFFFFFFFF);
4634 SIVAL(pdata,6,0xFFFFFFFF);
4635 break;
4636 case SMB_ACL_OTHER:
4637 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4638 SIVAL(pdata,2,0xFFFFFFFF);
4639 SIVAL(pdata,6,0xFFFFFFFF);
4640 break;
4641 default:
4642 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4643 return False;
4645 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4648 return True;
4650 #endif
4652 /****************************************************************************
4653 Store the FILE_UNIX_BASIC info.
4654 ****************************************************************************/
4656 static char *store_file_unix_basic(connection_struct *conn,
4657 char *pdata,
4658 files_struct *fsp,
4659 const SMB_STRUCT_STAT *psbuf)
4661 dev_t devno;
4663 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4664 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4666 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4667 pdata += 8;
4669 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4670 pdata += 8;
4672 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, &psbuf->st_ex_ctime); /* Change Time 64 Bit */
4673 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, &psbuf->st_ex_atime); /* Last access time 64 Bit */
4674 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, &psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4675 pdata += 24;
4677 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4678 SIVAL(pdata,4,0);
4679 pdata += 8;
4681 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4682 SIVAL(pdata,4,0);
4683 pdata += 8;
4685 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4686 pdata += 4;
4688 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4689 devno = psbuf->st_ex_rdev;
4690 } else {
4691 devno = psbuf->st_ex_dev;
4694 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4695 SIVAL(pdata,4,0);
4696 pdata += 8;
4698 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4699 SIVAL(pdata,4,0);
4700 pdata += 8;
4702 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4703 pdata += 8;
4705 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4706 SIVAL(pdata,4,0);
4707 pdata += 8;
4709 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4710 SIVAL(pdata,4,0);
4711 pdata += 8;
4713 return pdata;
4716 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4717 * the chflags(2) (or equivalent) flags.
4719 * XXX: this really should be behind the VFS interface. To do this, we would
4720 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4721 * Each VFS module could then implement its own mapping as appropriate for the
4722 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4724 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4725 info2_flags_map[] =
4727 #ifdef UF_NODUMP
4728 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4729 #endif
4731 #ifdef UF_IMMUTABLE
4732 { UF_IMMUTABLE, EXT_IMMUTABLE },
4733 #endif
4735 #ifdef UF_APPEND
4736 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4737 #endif
4739 #ifdef UF_HIDDEN
4740 { UF_HIDDEN, EXT_HIDDEN },
4741 #endif
4743 /* Do not remove. We need to guarantee that this array has at least one
4744 * entry to build on HP-UX.
4746 { 0, 0 }
4750 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4751 uint32_t *smb_fflags, uint32_t *smb_fmask)
4753 int i;
4755 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4756 *smb_fmask |= info2_flags_map[i].smb_fflag;
4757 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4758 *smb_fflags |= info2_flags_map[i].smb_fflag;
4763 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4764 const uint32_t smb_fflags,
4765 const uint32_t smb_fmask,
4766 int *stat_fflags)
4768 uint32_t max_fmask = 0;
4769 int i;
4771 *stat_fflags = psbuf->st_ex_flags;
4773 /* For each flags requested in smb_fmask, check the state of the
4774 * corresponding flag in smb_fflags and set or clear the matching
4775 * stat flag.
4778 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4779 max_fmask |= info2_flags_map[i].smb_fflag;
4780 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4781 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4782 *stat_fflags |= info2_flags_map[i].stat_fflag;
4783 } else {
4784 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4789 /* If smb_fmask is asking to set any bits that are not supported by
4790 * our flag mappings, we should fail.
4792 if ((smb_fmask & max_fmask) != smb_fmask) {
4793 return False;
4796 return True;
4800 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4801 * of file flags and birth (create) time.
4803 static char *store_file_unix_basic_info2(connection_struct *conn,
4804 char *pdata,
4805 files_struct *fsp,
4806 const SMB_STRUCT_STAT *psbuf)
4808 uint32_t file_flags = 0;
4809 uint32_t flags_mask = 0;
4811 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4813 /* Create (birth) time 64 bit */
4814 put_long_date_full_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, &psbuf->st_ex_btime);
4815 pdata += 8;
4817 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4818 SIVAL(pdata, 0, file_flags); /* flags */
4819 SIVAL(pdata, 4, flags_mask); /* mask */
4820 pdata += 8;
4822 return pdata;
4825 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4826 const struct stream_struct *streams,
4827 char *data,
4828 unsigned int max_data_bytes,
4829 unsigned int *data_size)
4831 unsigned int i;
4832 unsigned int ofs = 0;
4834 if (max_data_bytes < 32) {
4835 return NT_STATUS_INFO_LENGTH_MISMATCH;
4838 for (i = 0; i < num_streams; i++) {
4839 unsigned int next_offset;
4840 size_t namelen;
4841 smb_ucs2_t *namebuf;
4843 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4844 streams[i].name, &namelen) ||
4845 namelen <= 2)
4847 return NT_STATUS_INVALID_PARAMETER;
4851 * name_buf is now null-terminated, we need to marshall as not
4852 * terminated
4855 namelen -= 2;
4858 * We cannot overflow ...
4860 if ((ofs + 24 + namelen) > max_data_bytes) {
4861 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4862 i));
4863 TALLOC_FREE(namebuf);
4864 return STATUS_BUFFER_OVERFLOW;
4867 SIVAL(data, ofs+4, namelen);
4868 SOFF_T(data, ofs+8, streams[i].size);
4869 SOFF_T(data, ofs+16, streams[i].alloc_size);
4870 memcpy(data+ofs+24, namebuf, namelen);
4871 TALLOC_FREE(namebuf);
4873 next_offset = ofs + 24 + namelen;
4875 if (i == num_streams-1) {
4876 SIVAL(data, ofs, 0);
4878 else {
4879 unsigned int align = ndr_align_size(next_offset, 8);
4881 if ((next_offset + align) > max_data_bytes) {
4882 DEBUG(10, ("refusing to overflow align "
4883 "reply at stream %u\n",
4884 i));
4885 TALLOC_FREE(namebuf);
4886 return STATUS_BUFFER_OVERFLOW;
4889 memset(data+next_offset, 0, align);
4890 next_offset += align;
4892 SIVAL(data, ofs, next_offset - ofs);
4893 ofs = next_offset;
4896 ofs = next_offset;
4899 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4901 *data_size = ofs;
4903 return NT_STATUS_OK;
4906 static NTSTATUS smb_unix_read_symlink(connection_struct *conn,
4907 struct smb_request *req,
4908 struct smb_filename *smb_fname,
4909 char *pdata,
4910 unsigned int data_size_in,
4911 unsigned int *pdata_size_out)
4913 NTSTATUS status;
4914 size_t len = 0;
4915 int link_len = 0;
4916 struct smb_filename *parent_fname = NULL;
4917 struct smb_filename *base_name = NULL;
4919 char *buffer = talloc_array(talloc_tos(), char, PATH_MAX+1);
4921 if (!buffer) {
4922 return NT_STATUS_NO_MEMORY;
4925 DBG_DEBUG("SMB_QUERY_FILE_UNIX_LINK for file %s\n",
4926 smb_fname_str_dbg(smb_fname));
4928 if(!S_ISLNK(smb_fname->st.st_ex_mode)) {
4929 TALLOC_FREE(buffer);
4930 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
4933 status = parent_pathref(talloc_tos(),
4934 conn->cwd_fsp,
4935 smb_fname,
4936 &parent_fname,
4937 &base_name);
4938 if (!NT_STATUS_IS_OK(status)) {
4939 TALLOC_FREE(buffer);
4940 return status;
4943 link_len = SMB_VFS_READLINKAT(conn,
4944 parent_fname->fsp,
4945 base_name,
4946 buffer,
4947 PATH_MAX);
4949 TALLOC_FREE(parent_fname);
4951 if (link_len == -1) {
4952 TALLOC_FREE(buffer);
4953 return map_nt_error_from_unix(errno);
4956 buffer[link_len] = 0;
4957 status = srvstr_push(pdata,
4958 req->flags2,
4959 pdata,
4960 buffer,
4961 data_size_in,
4962 STR_TERMINATE,
4963 &len);
4964 TALLOC_FREE(buffer);
4965 if (!NT_STATUS_IS_OK(status)) {
4966 return status;
4968 *pdata_size_out = len;
4970 return NT_STATUS_OK;
4973 #if defined(HAVE_POSIX_ACLS)
4974 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4975 struct smb_request *req,
4976 files_struct *fsp,
4977 struct smb_filename *smb_fname,
4978 char *pdata,
4979 unsigned int data_size_in,
4980 unsigned int *pdata_size_out)
4982 SMB_ACL_T file_acl = NULL;
4983 SMB_ACL_T def_acl = NULL;
4984 uint16_t num_file_acls = 0;
4985 uint16_t num_def_acls = 0;
4986 unsigned int size_needed = 0;
4987 NTSTATUS status;
4988 bool ok;
4989 bool close_fsp = false;
4992 * Ensure we always operate on a file descriptor, not just
4993 * the filename.
4995 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
4996 uint32_t access_mask = SEC_STD_READ_CONTROL|
4997 FILE_READ_ATTRIBUTES|
4998 FILE_WRITE_ATTRIBUTES;
5000 status = get_posix_fsp(conn,
5001 req,
5002 smb_fname,
5003 access_mask,
5004 &fsp);
5006 if (!NT_STATUS_IS_OK(status)) {
5007 goto out;
5009 close_fsp = true;
5012 SMB_ASSERT(fsp != NULL);
5014 status = refuse_symlink(conn,
5015 fsp,
5016 fsp->fsp_name);
5017 if (!NT_STATUS_IS_OK(status)) {
5018 goto out;
5021 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5022 talloc_tos());
5024 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5025 DBG_INFO("ACLs not implemented on "
5026 "filesystem containing %s\n",
5027 fsp_str_dbg(fsp));
5028 status = NT_STATUS_NOT_IMPLEMENTED;
5029 goto out;
5032 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
5034 * We can only have default POSIX ACLs on
5035 * directories.
5037 if (!fsp->fsp_flags.is_directory) {
5038 DBG_INFO("Non-directory open %s\n",
5039 fsp_str_dbg(fsp));
5040 status = NT_STATUS_INVALID_HANDLE;
5041 goto out;
5043 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
5044 fsp->fsp_name,
5045 SMB_ACL_TYPE_DEFAULT,
5046 talloc_tos());
5047 def_acl = free_empty_sys_acl(conn, def_acl);
5050 num_file_acls = count_acl_entries(conn, file_acl);
5051 num_def_acls = count_acl_entries(conn, def_acl);
5053 /* Wrap checks. */
5054 if (num_file_acls + num_def_acls < num_file_acls) {
5055 status = NT_STATUS_INVALID_PARAMETER;
5056 goto out;
5059 size_needed = num_file_acls + num_def_acls;
5062 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
5063 * than UINT_MAX, so check by division.
5065 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
5066 status = NT_STATUS_INVALID_PARAMETER;
5067 goto out;
5070 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
5071 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
5072 status = NT_STATUS_INVALID_PARAMETER;
5073 goto out;
5075 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
5077 if ( data_size_in < size_needed) {
5078 DBG_INFO("data_size too small (%u) need %u\n",
5079 data_size_in,
5080 size_needed);
5081 status = NT_STATUS_BUFFER_TOO_SMALL;
5082 goto out;
5085 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5086 SSVAL(pdata,2,num_file_acls);
5087 SSVAL(pdata,4,num_def_acls);
5088 pdata += SMB_POSIX_ACL_HEADER_SIZE;
5090 ok = marshall_posix_acl(conn,
5091 pdata,
5092 &fsp->fsp_name->st,
5093 file_acl);
5094 if (!ok) {
5095 status = NT_STATUS_INTERNAL_ERROR;
5096 goto out;
5098 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
5100 ok = marshall_posix_acl(conn,
5101 pdata,
5102 &fsp->fsp_name->st,
5103 def_acl);
5104 if (!ok) {
5105 status = NT_STATUS_INTERNAL_ERROR;
5106 goto out;
5109 *pdata_size_out = size_needed;
5110 status = NT_STATUS_OK;
5112 out:
5114 if (close_fsp) {
5116 * Ensure the stat struct in smb_fname is up to
5117 * date. Structure copy.
5119 smb_fname->st = fsp->fsp_name->st;
5120 (void)close_file(req, fsp, NORMAL_CLOSE);
5121 fsp = NULL;
5124 TALLOC_FREE(file_acl);
5125 TALLOC_FREE(def_acl);
5126 return status;
5128 #endif
5130 /****************************************************************************
5131 Reply to a TRANSACT2_QFILEINFO on a PIPE !
5132 ****************************************************************************/
5134 static void call_trans2qpipeinfo(connection_struct *conn,
5135 struct smb_request *req,
5136 unsigned int tran_call,
5137 char **pparams, int total_params,
5138 char **ppdata, int total_data,
5139 unsigned int max_data_bytes)
5141 char *params = *pparams;
5142 char *pdata = *ppdata;
5143 unsigned int data_size = 0;
5144 unsigned int param_size = 2;
5145 uint16_t info_level;
5146 files_struct *fsp;
5148 if (!params) {
5149 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5150 return;
5153 if (total_params < 4) {
5154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5155 return;
5158 fsp = file_fsp(req, SVAL(params,0));
5159 if (!fsp_is_np(fsp)) {
5160 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5161 return;
5164 info_level = SVAL(params,2);
5166 *pparams = (char *)SMB_REALLOC(*pparams,2);
5167 if (*pparams == NULL) {
5168 reply_nterror(req, NT_STATUS_NO_MEMORY);
5169 return;
5171 params = *pparams;
5172 SSVAL(params,0,0);
5173 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5175 return;
5177 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5178 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5179 if (*ppdata == NULL ) {
5180 reply_nterror(req, NT_STATUS_NO_MEMORY);
5181 return;
5183 pdata = *ppdata;
5185 switch (info_level) {
5186 case SMB_FILE_STANDARD_INFORMATION:
5187 memset(pdata,0,24);
5188 SOFF_T(pdata,0,4096LL);
5189 SIVAL(pdata,16,1);
5190 SIVAL(pdata,20,1);
5191 data_size = 24;
5192 break;
5194 default:
5195 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5196 return;
5199 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5200 max_data_bytes);
5202 return;
5205 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5206 TALLOC_CTX *mem_ctx,
5207 struct smb_request *req,
5208 uint16_t info_level,
5209 files_struct *fsp,
5210 struct smb_filename *smb_fname,
5211 bool delete_pending,
5212 struct timespec write_time_ts,
5213 struct ea_list *ea_list,
5214 int lock_data_count,
5215 char *lock_data,
5216 uint16_t flags2,
5217 unsigned int max_data_bytes,
5218 size_t *fixed_portion,
5219 char **ppdata,
5220 unsigned int *pdata_size)
5222 char *pdata = *ppdata;
5223 char *dstart, *dend;
5224 unsigned int data_size;
5225 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5226 time_t create_time, mtime, atime, c_time;
5227 SMB_STRUCT_STAT *psbuf = NULL;
5228 char *p;
5229 char *base_name;
5230 char *dos_fname;
5231 int mode;
5232 int nlink;
5233 NTSTATUS status;
5234 uint64_t file_size = 0;
5235 uint64_t pos = 0;
5236 uint64_t allocation_size = 0;
5237 uint64_t file_id = 0;
5238 uint32_t access_mask = 0;
5239 size_t len = 0;
5241 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5242 return NT_STATUS_INVALID_LEVEL;
5245 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5246 smb_fname_str_dbg(smb_fname),
5247 fsp_fnum_dbg(fsp),
5248 info_level, max_data_bytes));
5251 * In case of querying a symlink in POSIX context,
5252 * fsp will be NULL. fdos_mode() deals with it.
5254 if (fsp != NULL) {
5255 smb_fname = fsp->fsp_name;
5257 mode = fdos_mode(fsp);
5258 psbuf = &smb_fname->st;
5260 nlink = psbuf->st_ex_nlink;
5262 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5263 nlink = 1;
5266 if ((nlink > 0) && delete_pending) {
5267 nlink -= 1;
5270 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5271 return NT_STATUS_INVALID_PARAMETER;
5274 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5275 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5276 if (*ppdata == NULL) {
5277 return NT_STATUS_NO_MEMORY;
5279 pdata = *ppdata;
5280 dstart = pdata;
5281 dend = dstart + data_size - 1;
5283 if (!is_omit_timespec(&write_time_ts) &&
5284 !INFO_LEVEL_IS_UNIX(info_level))
5286 update_stat_ex_mtime(psbuf, write_time_ts);
5289 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5290 mtime_ts = psbuf->st_ex_mtime;
5291 atime_ts = psbuf->st_ex_atime;
5292 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5294 if (lp_dos_filetime_resolution(SNUM(conn))) {
5295 dos_filetime_timespec(&create_time_ts);
5296 dos_filetime_timespec(&mtime_ts);
5297 dos_filetime_timespec(&atime_ts);
5298 dos_filetime_timespec(&ctime_ts);
5301 create_time = convert_timespec_to_time_t(create_time_ts);
5302 mtime = convert_timespec_to_time_t(mtime_ts);
5303 atime = convert_timespec_to_time_t(atime_ts);
5304 c_time = convert_timespec_to_time_t(ctime_ts);
5306 p = strrchr_m(smb_fname->base_name,'/');
5307 if (!p)
5308 base_name = smb_fname->base_name;
5309 else
5310 base_name = p+1;
5312 /* NT expects the name to be in an exact form of the *full*
5313 filename. See the trans2 torture test */
5314 if (ISDOT(base_name)) {
5315 dos_fname = talloc_strdup(mem_ctx, "\\");
5316 if (!dos_fname) {
5317 return NT_STATUS_NO_MEMORY;
5319 } else {
5320 dos_fname = talloc_asprintf(mem_ctx,
5321 "\\%s",
5322 smb_fname->base_name);
5323 if (!dos_fname) {
5324 return NT_STATUS_NO_MEMORY;
5326 if (is_ntfs_stream_smb_fname(smb_fname)) {
5327 dos_fname = talloc_asprintf(dos_fname, "%s",
5328 smb_fname->stream_name);
5329 if (!dos_fname) {
5330 return NT_STATUS_NO_MEMORY;
5334 string_replace(dos_fname, '/', '\\');
5337 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5339 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
5340 /* Do we have this path open ? */
5341 files_struct *fsp1;
5342 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5343 fsp1 = file_find_di_first(conn->sconn, fileid, true);
5344 if (fsp1 && fsp1->initial_allocation_size) {
5345 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5349 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5350 file_size = get_file_size_stat(psbuf);
5353 if (fsp) {
5354 pos = fh_get_position_information(fsp->fh);
5357 if (fsp) {
5358 access_mask = fsp->access_mask;
5359 } else {
5360 /* GENERIC_EXECUTE mapping from Windows */
5361 access_mask = 0x12019F;
5364 /* This should be an index number - looks like
5365 dev/ino to me :-)
5367 I think this causes us to fail the IFSKIT
5368 BasicFileInformationTest. -tpot */
5369 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5371 *fixed_portion = 0;
5373 switch (info_level) {
5374 case SMB_INFO_STANDARD:
5375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5376 data_size = 22;
5377 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5378 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5379 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5380 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5381 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5382 SSVAL(pdata,l1_attrFile,mode);
5383 break;
5385 case SMB_INFO_QUERY_EA_SIZE:
5387 unsigned int ea_size =
5388 estimate_ea_size(smb_fname->fsp);
5389 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5390 data_size = 26;
5391 srv_put_dos_date2(pdata,0,create_time);
5392 srv_put_dos_date2(pdata,4,atime);
5393 srv_put_dos_date2(pdata,8,mtime); /* write time */
5394 SIVAL(pdata,12,(uint32_t)file_size);
5395 SIVAL(pdata,16,(uint32_t)allocation_size);
5396 SSVAL(pdata,20,mode);
5397 SIVAL(pdata,22,ea_size);
5398 break;
5401 case SMB_INFO_IS_NAME_VALID:
5402 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5403 if (fsp) {
5404 /* os/2 needs this ? really ?*/
5405 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5407 /* This is only reached for qpathinfo */
5408 data_size = 0;
5409 break;
5411 case SMB_INFO_QUERY_EAS_FROM_LIST:
5413 size_t total_ea_len = 0;
5414 struct ea_list *ea_file_list = NULL;
5415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5417 status =
5418 get_ea_list_from_fsp(mem_ctx,
5419 smb_fname->fsp,
5420 &total_ea_len, &ea_file_list);
5421 if (!NT_STATUS_IS_OK(status)) {
5422 return status;
5425 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5427 if (!ea_list || (total_ea_len > data_size)) {
5428 data_size = 4;
5429 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5430 break;
5433 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5434 break;
5437 case SMB_INFO_QUERY_ALL_EAS:
5439 /* We have data_size bytes to put EA's into. */
5440 size_t total_ea_len = 0;
5441 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5443 status = get_ea_list_from_fsp(mem_ctx,
5444 smb_fname->fsp,
5445 &total_ea_len, &ea_list);
5446 if (!NT_STATUS_IS_OK(status)) {
5447 return status;
5450 if (!ea_list || (total_ea_len > data_size)) {
5451 data_size = 4;
5452 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5453 break;
5456 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5457 break;
5460 case SMB2_FILE_FULL_EA_INFORMATION:
5462 /* We have data_size bytes to put EA's into. */
5463 size_t total_ea_len = 0;
5464 struct ea_list *ea_file_list = NULL;
5466 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5468 /*TODO: add filtering and index handling */
5470 status =
5471 get_ea_list_from_fsp(mem_ctx,
5472 smb_fname->fsp,
5473 &total_ea_len, &ea_file_list);
5474 if (!NT_STATUS_IS_OK(status)) {
5475 return status;
5477 if (!ea_file_list) {
5478 return NT_STATUS_NO_EAS_ON_FILE;
5481 status = fill_ea_chained_buffer(mem_ctx,
5482 pdata,
5483 data_size,
5484 &data_size,
5485 conn, ea_file_list);
5486 if (!NT_STATUS_IS_OK(status)) {
5487 return status;
5489 break;
5492 case SMB_FILE_BASIC_INFORMATION:
5493 case SMB_QUERY_FILE_BASIC_INFO:
5495 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5496 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5497 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5498 } else {
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5500 data_size = 40;
5501 SIVAL(pdata,36,0);
5503 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5504 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5505 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5506 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5507 SIVAL(pdata,32,mode);
5509 DEBUG(5,("SMB_QFBI - "));
5510 DEBUG(5,("create: %s ", ctime(&create_time)));
5511 DEBUG(5,("access: %s ", ctime(&atime)));
5512 DEBUG(5,("write: %s ", ctime(&mtime)));
5513 DEBUG(5,("change: %s ", ctime(&c_time)));
5514 DEBUG(5,("mode: %x\n", mode));
5515 *fixed_portion = data_size;
5516 break;
5518 case SMB_FILE_STANDARD_INFORMATION:
5519 case SMB_QUERY_FILE_STANDARD_INFO:
5521 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5522 data_size = 24;
5523 SOFF_T(pdata,0,allocation_size);
5524 SOFF_T(pdata,8,file_size);
5525 SIVAL(pdata,16,nlink);
5526 SCVAL(pdata,20,delete_pending?1:0);
5527 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5528 SSVAL(pdata,22,0); /* Padding. */
5529 *fixed_portion = 24;
5530 break;
5532 case SMB_FILE_EA_INFORMATION:
5533 case SMB_QUERY_FILE_EA_INFO:
5535 unsigned int ea_size =
5536 estimate_ea_size(smb_fname->fsp);
5537 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5538 data_size = 4;
5539 *fixed_portion = 4;
5540 SIVAL(pdata,0,ea_size);
5541 break;
5544 /* Get the 8.3 name - used if NT SMB was negotiated. */
5545 case SMB_QUERY_FILE_ALT_NAME_INFO:
5546 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5548 char mangled_name[13];
5549 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5550 if (!name_to_8_3(base_name,mangled_name,
5551 True,conn->params)) {
5552 return NT_STATUS_NO_MEMORY;
5554 status = srvstr_push(dstart, flags2,
5555 pdata+4, mangled_name,
5556 PTR_DIFF(dend, pdata+4),
5557 STR_UNICODE, &len);
5558 if (!NT_STATUS_IS_OK(status)) {
5559 return status;
5561 data_size = 4 + len;
5562 SIVAL(pdata,0,len);
5563 *fixed_portion = 8;
5564 break;
5567 case SMB_QUERY_FILE_NAME_INFO:
5570 this must be *exactly* right for ACLs on mapped drives to work
5572 status = srvstr_push(dstart, flags2,
5573 pdata+4, dos_fname,
5574 PTR_DIFF(dend, pdata+4),
5575 STR_UNICODE, &len);
5576 if (!NT_STATUS_IS_OK(status)) {
5577 return status;
5579 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5580 data_size = 4 + len;
5581 SIVAL(pdata,0,len);
5582 break;
5585 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5587 char *nfname = NULL;
5589 if (fsp == NULL || !fsp->conn->sconn->using_smb2) {
5590 return NT_STATUS_INVALID_LEVEL;
5593 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5594 if (nfname == NULL) {
5595 return NT_STATUS_NO_MEMORY;
5598 if (ISDOT(nfname)) {
5599 nfname[0] = '\0';
5601 string_replace(nfname, '/', '\\');
5603 if (smb_fname->stream_name != NULL) {
5604 const char *s = smb_fname->stream_name;
5605 const char *e = NULL;
5606 size_t n;
5608 SMB_ASSERT(s[0] != '\0');
5611 * smb_fname->stream_name is in form
5612 * of ':StrEam:$DATA', but we should only
5613 * append ':StrEam' here.
5616 e = strchr(&s[1], ':');
5617 if (e == NULL) {
5618 n = strlen(s);
5619 } else {
5620 n = PTR_DIFF(e, s);
5622 nfname = talloc_strndup_append(nfname, s, n);
5623 if (nfname == NULL) {
5624 return NT_STATUS_NO_MEMORY;
5628 status = srvstr_push(dstart, flags2,
5629 pdata+4, nfname,
5630 PTR_DIFF(dend, pdata+4),
5631 STR_UNICODE, &len);
5632 if (!NT_STATUS_IS_OK(status)) {
5633 return status;
5635 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5636 data_size = 4 + len;
5637 SIVAL(pdata,0,len);
5638 *fixed_portion = 8;
5639 break;
5642 case SMB_FILE_ALLOCATION_INFORMATION:
5643 case SMB_QUERY_FILE_ALLOCATION_INFO:
5644 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5645 data_size = 8;
5646 SOFF_T(pdata,0,allocation_size);
5647 break;
5649 case SMB_FILE_END_OF_FILE_INFORMATION:
5650 case SMB_QUERY_FILE_END_OF_FILEINFO:
5651 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5652 data_size = 8;
5653 SOFF_T(pdata,0,file_size);
5654 break;
5656 case SMB_QUERY_FILE_ALL_INFO:
5657 case SMB_FILE_ALL_INFORMATION:
5659 unsigned int ea_size =
5660 estimate_ea_size(smb_fname->fsp);
5661 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5662 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5663 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5664 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5665 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5666 SIVAL(pdata,32,mode);
5667 SIVAL(pdata,36,0); /* padding. */
5668 pdata += 40;
5669 SOFF_T(pdata,0,allocation_size);
5670 SOFF_T(pdata,8,file_size);
5671 SIVAL(pdata,16,nlink);
5672 SCVAL(pdata,20,delete_pending);
5673 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5674 SSVAL(pdata,22,0);
5675 pdata += 24;
5676 SIVAL(pdata,0,ea_size);
5677 pdata += 4; /* EA info */
5678 status = srvstr_push(dstart, flags2,
5679 pdata+4, dos_fname,
5680 PTR_DIFF(dend, pdata+4),
5681 STR_UNICODE, &len);
5682 if (!NT_STATUS_IS_OK(status)) {
5683 return status;
5685 SIVAL(pdata,0,len);
5686 pdata += 4 + len;
5687 data_size = PTR_DIFF(pdata,(*ppdata));
5688 *fixed_portion = 10;
5689 break;
5692 case SMB2_FILE_ALL_INFORMATION:
5694 unsigned int ea_size =
5695 estimate_ea_size(smb_fname->fsp);
5696 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5697 put_long_date_full_timespec(conn->ts_res,pdata+0x00,&create_time_ts);
5698 put_long_date_full_timespec(conn->ts_res,pdata+0x08,&atime_ts);
5699 put_long_date_full_timespec(conn->ts_res,pdata+0x10,&mtime_ts); /* write time */
5700 put_long_date_full_timespec(conn->ts_res,pdata+0x18,&ctime_ts); /* change time */
5701 SIVAL(pdata, 0x20, mode);
5702 SIVAL(pdata, 0x24, 0); /* padding. */
5703 SBVAL(pdata, 0x28, allocation_size);
5704 SBVAL(pdata, 0x30, file_size);
5705 SIVAL(pdata, 0x38, nlink);
5706 SCVAL(pdata, 0x3C, delete_pending);
5707 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5708 SSVAL(pdata, 0x3E, 0); /* padding */
5709 SBVAL(pdata, 0x40, file_id);
5710 SIVAL(pdata, 0x48, ea_size);
5711 SIVAL(pdata, 0x4C, access_mask);
5712 SBVAL(pdata, 0x50, pos);
5713 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5714 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5716 pdata += 0x60;
5718 status = srvstr_push(dstart, flags2,
5719 pdata+4, dos_fname,
5720 PTR_DIFF(dend, pdata+4),
5721 STR_UNICODE, &len);
5722 if (!NT_STATUS_IS_OK(status)) {
5723 return status;
5725 SIVAL(pdata,0,len);
5726 pdata += 4 + len;
5727 data_size = PTR_DIFF(pdata,(*ppdata));
5728 *fixed_portion = 104;
5729 break;
5731 case SMB_FILE_INTERNAL_INFORMATION:
5733 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5734 SBVAL(pdata, 0, file_id);
5735 data_size = 8;
5736 *fixed_portion = 8;
5737 break;
5739 case SMB_FILE_ACCESS_INFORMATION:
5740 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5741 SIVAL(pdata, 0, access_mask);
5742 data_size = 4;
5743 *fixed_portion = 4;
5744 break;
5746 case SMB_FILE_NAME_INFORMATION:
5747 /* Pathname with leading '\'. */
5749 size_t byte_len;
5750 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5751 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5752 SIVAL(pdata,0,byte_len);
5753 data_size = 4 + byte_len;
5754 break;
5757 case SMB_FILE_DISPOSITION_INFORMATION:
5758 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5759 data_size = 1;
5760 SCVAL(pdata,0,delete_pending);
5761 *fixed_portion = 1;
5762 break;
5764 case SMB_FILE_POSITION_INFORMATION:
5765 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5766 data_size = 8;
5767 SOFF_T(pdata,0,pos);
5768 *fixed_portion = 8;
5769 break;
5771 case SMB_FILE_MODE_INFORMATION:
5772 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5773 SIVAL(pdata,0,mode);
5774 data_size = 4;
5775 *fixed_portion = 4;
5776 break;
5778 case SMB_FILE_ALIGNMENT_INFORMATION:
5779 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5780 SIVAL(pdata,0,0); /* No alignment needed. */
5781 data_size = 4;
5782 *fixed_portion = 4;
5783 break;
5786 * NT4 server just returns "invalid query" to this - if we try
5787 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5788 * want this. JRA.
5790 /* The first statement above is false - verified using Thursby
5791 * client against NT4 -- gcolley.
5793 case SMB_QUERY_FILE_STREAM_INFO:
5794 case SMB_FILE_STREAM_INFORMATION: {
5795 unsigned int num_streams = 0;
5796 struct stream_struct *streams = NULL;
5798 DEBUG(10,("smbd_do_qfilepathinfo: "
5799 "SMB_FILE_STREAM_INFORMATION\n"));
5801 if (is_ntfs_stream_smb_fname(smb_fname)) {
5802 return NT_STATUS_INVALID_PARAMETER;
5805 status = vfs_streaminfo(conn,
5806 fsp,
5807 smb_fname,
5808 talloc_tos(),
5809 &num_streams,
5810 &streams);
5812 if (!NT_STATUS_IS_OK(status)) {
5813 DEBUG(10, ("could not get stream info: %s\n",
5814 nt_errstr(status)));
5815 return status;
5818 status = marshall_stream_info(num_streams, streams,
5819 pdata, max_data_bytes,
5820 &data_size);
5822 if (!NT_STATUS_IS_OK(status)) {
5823 DEBUG(10, ("marshall_stream_info failed: %s\n",
5824 nt_errstr(status)));
5825 TALLOC_FREE(streams);
5826 return status;
5829 TALLOC_FREE(streams);
5831 *fixed_portion = 32;
5833 break;
5835 case SMB_QUERY_COMPRESSION_INFO:
5836 case SMB_FILE_COMPRESSION_INFORMATION:
5837 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5838 SOFF_T(pdata,0,file_size);
5839 SIVAL(pdata,8,0); /* ??? */
5840 SIVAL(pdata,12,0); /* ??? */
5841 data_size = 16;
5842 *fixed_portion = 16;
5843 break;
5845 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5846 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5847 put_long_date_full_timespec(conn->ts_res,pdata,&create_time_ts);
5848 put_long_date_full_timespec(conn->ts_res,pdata+8,&atime_ts);
5849 put_long_date_full_timespec(conn->ts_res,pdata+16,&mtime_ts); /* write time */
5850 put_long_date_full_timespec(conn->ts_res,pdata+24,&ctime_ts); /* change time */
5851 SOFF_T(pdata,32,allocation_size);
5852 SOFF_T(pdata,40,file_size);
5853 SIVAL(pdata,48,mode);
5854 SIVAL(pdata,52,0); /* ??? */
5855 data_size = 56;
5856 *fixed_portion = 56;
5857 break;
5859 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5860 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5861 SIVAL(pdata,0,mode);
5862 SIVAL(pdata,4,0);
5863 data_size = 8;
5864 *fixed_portion = 8;
5865 break;
5868 * CIFS UNIX Extensions.
5871 case SMB_QUERY_FILE_UNIX_BASIC:
5873 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5874 data_size = PTR_DIFF(pdata,(*ppdata));
5876 DEBUG(4,("smbd_do_qfilepathinfo: "
5877 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5878 dump_data(4, (uint8_t *)(*ppdata), data_size);
5880 break;
5882 case SMB_QUERY_FILE_UNIX_INFO2:
5884 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5885 data_size = PTR_DIFF(pdata,(*ppdata));
5888 int i;
5889 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5891 for (i=0; i<100; i++)
5892 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5893 DEBUG(4,("\n"));
5896 break;
5898 case SMB_QUERY_FILE_UNIX_LINK:
5900 status = smb_unix_read_symlink(conn,
5901 req,
5902 smb_fname,
5903 pdata,
5904 data_size,
5905 &data_size);
5906 if (!NT_STATUS_IS_OK(status)) {
5907 return status;
5909 break;
5912 #if defined(HAVE_POSIX_ACLS)
5913 case SMB_QUERY_POSIX_ACL:
5915 status = smb_query_posix_acl(conn,
5916 req,
5917 fsp,
5918 smb_fname,
5919 pdata,
5920 data_size,
5921 &data_size);
5922 if (!NT_STATUS_IS_OK(status)) {
5923 return status;
5925 break;
5927 #endif
5930 case SMB_QUERY_POSIX_LOCK:
5932 uint64_t count;
5933 uint64_t offset;
5934 uint64_t smblctx;
5935 enum brl_type lock_type;
5937 /* We need an open file with a real fd for this. */
5938 if (fsp == NULL ||
5939 fsp->fsp_flags.is_pathref ||
5940 fsp_get_io_fd(fsp) == -1)
5942 return NT_STATUS_INVALID_LEVEL;
5945 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5946 return NT_STATUS_INVALID_PARAMETER;
5949 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5950 case POSIX_LOCK_TYPE_READ:
5951 lock_type = READ_LOCK;
5952 break;
5953 case POSIX_LOCK_TYPE_WRITE:
5954 lock_type = WRITE_LOCK;
5955 break;
5956 case POSIX_LOCK_TYPE_UNLOCK:
5957 default:
5958 /* There's no point in asking for an unlock... */
5959 return NT_STATUS_INVALID_PARAMETER;
5962 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5963 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5964 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5966 status = query_lock(fsp,
5967 &smblctx,
5968 &count,
5969 &offset,
5970 &lock_type,
5971 POSIX_LOCK);
5973 if (ERROR_WAS_LOCK_DENIED(status)) {
5974 /* Here we need to report who has it locked... */
5975 data_size = POSIX_LOCK_DATA_SIZE;
5977 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5978 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5979 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5980 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5981 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5983 } else if (NT_STATUS_IS_OK(status)) {
5984 /* For success we just return a copy of what we sent
5985 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5986 data_size = POSIX_LOCK_DATA_SIZE;
5987 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5988 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5989 } else {
5990 return status;
5992 break;
5995 default:
5996 return NT_STATUS_INVALID_LEVEL;
5999 *pdata_size = data_size;
6000 return NT_STATUS_OK;
6003 /****************************************************************************
6004 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
6005 file name or file id).
6006 ****************************************************************************/
6008 static void call_trans2qfilepathinfo(connection_struct *conn,
6009 struct smb_request *req,
6010 unsigned int tran_call,
6011 char **pparams, int total_params,
6012 char **ppdata, int total_data,
6013 unsigned int max_data_bytes)
6015 char *params = *pparams;
6016 char *pdata = *ppdata;
6017 uint16_t info_level;
6018 unsigned int data_size = 0;
6019 unsigned int param_size = 2;
6020 struct smb_filename *smb_fname = NULL;
6021 bool delete_pending = False;
6022 struct timespec write_time_ts;
6023 files_struct *fsp = NULL;
6024 struct file_id fileid;
6025 struct ea_list *ea_list = NULL;
6026 int lock_data_count = 0;
6027 char *lock_data = NULL;
6028 size_t fixed_portion;
6029 NTSTATUS status = NT_STATUS_OK;
6031 if (!params) {
6032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6033 return;
6036 ZERO_STRUCT(write_time_ts);
6038 if (tran_call == TRANSACT2_QFILEINFO) {
6039 if (total_params < 4) {
6040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6041 return;
6044 if (IS_IPC(conn)) {
6045 call_trans2qpipeinfo(conn, req, tran_call,
6046 pparams, total_params,
6047 ppdata, total_data,
6048 max_data_bytes);
6049 return;
6052 fsp = file_fsp(req, SVAL(params,0));
6053 info_level = SVAL(params,2);
6055 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
6057 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
6058 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6059 return;
6062 /* Initial check for valid fsp ptr. */
6063 if (!check_fsp_open(conn, req, fsp)) {
6064 return;
6067 smb_fname = fsp->fsp_name;
6069 if(fsp->fake_file_handle) {
6071 * This is actually for the QUOTA_FAKE_FILE --metze
6074 /* We know this name is ok, it's already passed the checks. */
6076 } else if(fsp_get_pathref_fd(fsp) == -1) {
6078 * This is actually a QFILEINFO on a directory
6079 * handle (returned from an NT SMB). NT5.0 seems
6080 * to do this call. JRA.
6083 if (INFO_LEVEL_IS_UNIX(info_level)) {
6084 /* Always do lstat for UNIX calls. */
6085 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6086 DEBUG(3,("call_trans2qfilepathinfo: "
6087 "SMB_VFS_LSTAT of %s failed "
6088 "(%s)\n",
6089 smb_fname_str_dbg(smb_fname),
6090 strerror(errno)));
6091 reply_nterror(req,
6092 map_nt_error_from_unix(errno));
6093 return;
6095 } else if (SMB_VFS_STAT(conn, smb_fname)) {
6096 DEBUG(3,("call_trans2qfilepathinfo: "
6097 "SMB_VFS_STAT of %s failed (%s)\n",
6098 smb_fname_str_dbg(smb_fname),
6099 strerror(errno)));
6100 reply_nterror(req,
6101 map_nt_error_from_unix(errno));
6102 return;
6105 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6106 fileid = vfs_file_id_from_sbuf(
6107 conn, &smb_fname->st);
6108 get_file_infos(fileid, fsp->name_hash,
6109 &delete_pending,
6110 &write_time_ts);
6112 } else {
6114 * Original code - this is an open file.
6116 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
6117 DEBUG(3, ("fstat of %s failed (%s)\n",
6118 fsp_fnum_dbg(fsp), strerror(errno)));
6119 reply_nterror(req,
6120 map_nt_error_from_unix(errno));
6121 return;
6123 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6124 fileid = vfs_file_id_from_sbuf(
6125 conn, &smb_fname->st);
6126 get_file_infos(fileid, fsp->name_hash,
6127 &delete_pending,
6128 &write_time_ts);
6132 } else {
6133 uint32_t name_hash;
6134 char *fname = NULL;
6135 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6137 /* qpathinfo */
6138 if (total_params < 7) {
6139 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6140 return;
6143 info_level = SVAL(params,0);
6145 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6147 if (INFO_LEVEL_IS_UNIX(info_level)) {
6148 if (!lp_unix_extensions()) {
6149 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6150 return;
6154 if (req->posix_pathnames) {
6155 srvstr_get_path_posix(req,
6156 params,
6157 req->flags2,
6158 &fname,
6159 &params[6],
6160 total_params - 6,
6161 STR_TERMINATE,
6162 &status);
6163 } else {
6164 srvstr_get_path(req,
6165 params,
6166 req->flags2,
6167 &fname,
6168 &params[6],
6169 total_params - 6,
6170 STR_TERMINATE,
6171 &status);
6173 if (!NT_STATUS_IS_OK(status)) {
6174 reply_nterror(req, status);
6175 return;
6178 status = filename_convert(req,
6179 conn,
6180 fname,
6181 ucf_flags,
6183 &smb_fname);
6184 if (!NT_STATUS_IS_OK(status)) {
6185 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6186 reply_botherror(req,
6187 NT_STATUS_PATH_NOT_COVERED,
6188 ERRSRV, ERRbadpath);
6189 return;
6191 reply_nterror(req, status);
6192 return;
6196 * smb_fname->fsp may be NULL if smb_fname points at a symlink
6197 * and we're in POSIX context, so be careful when using fsp
6198 * below, it can still be NULL.
6200 fsp = smb_fname->fsp;
6202 /* If this is a stream, check if there is a delete_pending. */
6203 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6204 && is_ntfs_stream_smb_fname(smb_fname)) {
6205 struct smb_filename *smb_fname_base;
6207 /* Create an smb_filename with stream_name == NULL. */
6208 smb_fname_base = synthetic_smb_fname(
6209 talloc_tos(),
6210 smb_fname->base_name,
6211 NULL,
6212 NULL,
6213 smb_fname->twrp,
6214 smb_fname->flags);
6215 if (smb_fname_base == NULL) {
6216 reply_nterror(req, NT_STATUS_NO_MEMORY);
6217 return;
6220 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6221 /* Always do lstat for UNIX calls. */
6222 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6223 DEBUG(3,("call_trans2qfilepathinfo: "
6224 "SMB_VFS_LSTAT of %s failed "
6225 "(%s)\n",
6226 smb_fname_str_dbg(smb_fname_base),
6227 strerror(errno)));
6228 TALLOC_FREE(smb_fname_base);
6229 reply_nterror(req,
6230 map_nt_error_from_unix(errno));
6231 return;
6233 } else {
6234 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6235 DEBUG(3,("call_trans2qfilepathinfo: "
6236 "fileinfo of %s failed "
6237 "(%s)\n",
6238 smb_fname_str_dbg(smb_fname_base),
6239 strerror(errno)));
6240 TALLOC_FREE(smb_fname_base);
6241 reply_nterror(req,
6242 map_nt_error_from_unix(errno));
6243 return;
6247 status = file_name_hash(conn,
6248 smb_fname_str_dbg(smb_fname_base),
6249 &name_hash);
6250 if (!NT_STATUS_IS_OK(status)) {
6251 TALLOC_FREE(smb_fname_base);
6252 reply_nterror(req, status);
6253 return;
6256 fileid = vfs_file_id_from_sbuf(conn,
6257 &smb_fname_base->st);
6258 TALLOC_FREE(smb_fname_base);
6259 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6260 if (delete_pending) {
6261 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6262 return;
6266 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6267 /* Always do lstat for UNIX calls. */
6268 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6269 DEBUG(3,("call_trans2qfilepathinfo: "
6270 "SMB_VFS_LSTAT of %s failed (%s)\n",
6271 smb_fname_str_dbg(smb_fname),
6272 strerror(errno)));
6273 reply_nterror(req,
6274 map_nt_error_from_unix(errno));
6275 return;
6278 } else {
6279 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6280 DEBUG(3,("call_trans2qfilepathinfo: "
6281 "SMB_VFS_STAT of %s failed (%s)\n",
6282 smb_fname_str_dbg(smb_fname),
6283 strerror(errno)));
6284 reply_nterror(req,
6285 map_nt_error_from_unix(errno));
6286 return;
6290 status = file_name_hash(conn,
6291 smb_fname_str_dbg(smb_fname),
6292 &name_hash);
6293 if (!NT_STATUS_IS_OK(status)) {
6294 reply_nterror(req, status);
6295 return;
6298 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6299 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6300 get_file_infos(fileid, name_hash, &delete_pending,
6301 &write_time_ts);
6304 if (delete_pending) {
6305 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6306 return;
6310 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6311 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6312 fsp_fnum_dbg(fsp),
6313 info_level,tran_call,total_data));
6315 /* Pull out any data sent here before we realloc. */
6316 switch (info_level) {
6317 case SMB_INFO_QUERY_EAS_FROM_LIST:
6319 /* Pull any EA list from the data portion. */
6320 uint32_t ea_size;
6322 if (total_data < 4) {
6323 reply_nterror(
6324 req, NT_STATUS_INVALID_PARAMETER);
6325 return;
6327 ea_size = IVAL(pdata,0);
6329 if (total_data > 0 && ea_size != total_data) {
6330 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6331 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6332 reply_nterror(
6333 req, NT_STATUS_INVALID_PARAMETER);
6334 return;
6337 if (!lp_ea_support(SNUM(conn))) {
6338 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6339 return;
6342 /* Pull out the list of names. */
6343 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6344 if (!ea_list) {
6345 reply_nterror(
6346 req, NT_STATUS_INVALID_PARAMETER);
6347 return;
6349 break;
6352 case SMB_QUERY_POSIX_LOCK:
6354 if (fsp == NULL ||
6355 fsp->fsp_flags.is_pathref ||
6356 fsp_get_io_fd(fsp) == -1)
6358 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6359 return;
6362 if (total_data != POSIX_LOCK_DATA_SIZE) {
6363 reply_nterror(
6364 req, NT_STATUS_INVALID_PARAMETER);
6365 return;
6368 /* Copy the lock range data. */
6369 lock_data = (char *)talloc_memdup(
6370 req, pdata, total_data);
6371 if (!lock_data) {
6372 reply_nterror(req, NT_STATUS_NO_MEMORY);
6373 return;
6375 lock_data_count = total_data;
6376 break;
6378 default:
6379 break;
6382 *pparams = (char *)SMB_REALLOC(*pparams,2);
6383 if (*pparams == NULL) {
6384 reply_nterror(req, NT_STATUS_NO_MEMORY);
6385 return;
6387 params = *pparams;
6388 SSVAL(params,0,0);
6391 * draft-leach-cifs-v1-spec-02.txt
6392 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6393 * says:
6395 * The requested information is placed in the Data portion of the
6396 * transaction response. For the information levels greater than 0x100,
6397 * the transaction response has 1 parameter word which should be
6398 * ignored by the client.
6400 * However Windows only follows this rule for the IS_NAME_VALID call.
6402 switch (info_level) {
6403 case SMB_INFO_IS_NAME_VALID:
6404 param_size = 0;
6405 break;
6408 if ((info_level & SMB2_INFO_SPECIAL) == SMB2_INFO_SPECIAL) {
6410 * We use levels that start with 0xFF00
6411 * internally to represent SMB2 specific levels
6413 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6414 return;
6417 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6418 fsp, smb_fname,
6419 delete_pending, write_time_ts,
6420 ea_list,
6421 lock_data_count, lock_data,
6422 req->flags2, max_data_bytes,
6423 &fixed_portion,
6424 ppdata, &data_size);
6425 if (!NT_STATUS_IS_OK(status)) {
6426 if (open_was_deferred(req->xconn, req->mid)) {
6427 /* We have re-scheduled this call. */
6428 return;
6430 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
6431 bool ok = defer_smb1_sharing_violation(req);
6432 if (ok) {
6433 return;
6436 reply_nterror(req, status);
6437 return;
6439 if (fixed_portion > max_data_bytes) {
6440 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6441 return;
6444 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6445 max_data_bytes);
6447 return;
6450 /****************************************************************************
6451 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6452 code.
6453 ****************************************************************************/
6455 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6456 connection_struct *conn,
6457 struct smb_request *req,
6458 bool overwrite_if_exists,
6459 const struct smb_filename *smb_fname_old,
6460 struct smb_filename *smb_fname_new)
6462 NTSTATUS status = NT_STATUS_OK;
6463 int ret;
6464 bool ok;
6465 struct smb_filename *parent_fname_old = NULL;
6466 struct smb_filename *base_name_old = NULL;
6467 struct smb_filename *parent_fname_new = NULL;
6468 struct smb_filename *base_name_new = NULL;
6470 /* source must already exist. */
6471 if (!VALID_STAT(smb_fname_old->st)) {
6472 status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
6473 goto out;
6476 /* No links from a directory. */
6477 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6478 status = NT_STATUS_FILE_IS_A_DIRECTORY;
6479 goto out;
6482 /* Setting a hardlink to/from a stream isn't currently supported. */
6483 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6484 if (ok) {
6485 DBG_DEBUG("Old name has streams\n");
6486 status = NT_STATUS_INVALID_PARAMETER;
6487 goto out;
6489 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6490 if (ok) {
6491 DBG_DEBUG("New name has streams\n");
6492 status = NT_STATUS_INVALID_PARAMETER;
6493 goto out;
6496 status = parent_pathref(talloc_tos(),
6497 conn->cwd_fsp,
6498 smb_fname_old,
6499 &parent_fname_old,
6500 &base_name_old);
6501 if (!NT_STATUS_IS_OK(status)) {
6502 goto out;
6505 status = parent_pathref(talloc_tos(),
6506 conn->cwd_fsp,
6507 smb_fname_new,
6508 &parent_fname_new,
6509 &base_name_new);
6510 if (!NT_STATUS_IS_OK(status)) {
6511 goto out;
6514 if (VALID_STAT(smb_fname_new->st)) {
6515 if (overwrite_if_exists) {
6516 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6517 status = NT_STATUS_FILE_IS_A_DIRECTORY;
6518 goto out;
6520 status = unlink_internals(conn,
6521 req,
6522 FILE_ATTRIBUTE_NORMAL,
6523 smb_fname_new,
6524 false);
6525 if (!NT_STATUS_IS_OK(status)) {
6526 goto out;
6528 } else {
6529 /* Disallow if newname already exists. */
6530 status = NT_STATUS_OBJECT_NAME_COLLISION;
6531 goto out;
6535 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6536 smb_fname_old->base_name, smb_fname_new->base_name));
6538 ret = SMB_VFS_LINKAT(conn,
6539 parent_fname_old->fsp,
6540 base_name_old,
6541 parent_fname_new->fsp,
6542 base_name_new,
6545 if (ret != 0) {
6546 status = map_nt_error_from_unix(errno);
6547 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6548 nt_errstr(status), smb_fname_old->base_name,
6549 smb_fname_new->base_name));
6552 out:
6554 TALLOC_FREE(parent_fname_old);
6555 TALLOC_FREE(parent_fname_new);
6556 return status;
6559 /****************************************************************************
6560 Deal with setting the time from any of the setfilepathinfo functions.
6561 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6562 calling this function.
6563 ****************************************************************************/
6565 NTSTATUS smb_set_file_time(connection_struct *conn,
6566 files_struct *fsp,
6567 struct smb_filename *smb_fname,
6568 struct smb_file_time *ft,
6569 bool setting_write_time)
6571 struct files_struct *set_fsp = NULL;
6572 struct timeval_buf tbuf[4];
6573 uint32_t action =
6574 FILE_NOTIFY_CHANGE_LAST_ACCESS
6575 |FILE_NOTIFY_CHANGE_LAST_WRITE
6576 |FILE_NOTIFY_CHANGE_CREATION;
6577 int ret;
6579 if (!VALID_STAT(smb_fname->st)) {
6580 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6583 if (fsp == NULL) {
6584 /* A symlink */
6585 return NT_STATUS_OK;
6588 set_fsp = fsp->base_fsp == NULL ? fsp : fsp->base_fsp;
6590 /* get some defaults (no modifications) if any info is zero or -1. */
6591 if (is_omit_timespec(&ft->create_time)) {
6592 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6595 if (is_omit_timespec(&ft->atime)) {
6596 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6599 if (is_omit_timespec(&ft->mtime)) {
6600 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6603 if (!setting_write_time) {
6604 /* ft->mtime comes from change time, not write time. */
6605 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6608 /* Ensure the resolution is the correct for
6609 * what we can store on this filesystem. */
6611 round_timespec(conn->ts_res, &ft->create_time);
6612 round_timespec(conn->ts_res, &ft->ctime);
6613 round_timespec(conn->ts_res, &ft->atime);
6614 round_timespec(conn->ts_res, &ft->mtime);
6616 DBG_DEBUG("smb_set_filetime: actime: %s\n ",
6617 timespec_string_buf(&ft->atime, true, &tbuf[0]));
6618 DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
6619 timespec_string_buf(&ft->mtime, true, &tbuf[1]));
6620 DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
6621 timespec_string_buf(&ft->ctime, true, &tbuf[2]));
6622 DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
6623 timespec_string_buf(&ft->create_time, true, &tbuf[3]));
6625 if (setting_write_time) {
6627 * This was a Windows setfileinfo on an open file.
6628 * NT does this a lot. We also need to
6629 * set the time here, as it can be read by
6630 * FindFirst/FindNext and with the patch for bug #2045
6631 * in smbd/fileio.c it ensures that this timestamp is
6632 * kept sticky even after a write. We save the request
6633 * away and will set it on file close and after a write. JRA.
6636 DBG_DEBUG("setting pending modtime to %s\n",
6637 timespec_string_buf(&ft->mtime, true, &tbuf[0]));
6639 if (set_fsp != NULL) {
6640 set_sticky_write_time_fsp(set_fsp, ft->mtime);
6641 } else {
6642 set_sticky_write_time_path(
6643 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6644 ft->mtime);
6648 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6650 ret = file_ntimes(conn, set_fsp->fsp_name, ft);
6651 if (ret != 0) {
6652 return map_nt_error_from_unix(errno);
6655 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6656 smb_fname->base_name);
6657 return NT_STATUS_OK;
6660 /****************************************************************************
6661 Deal with setting the dosmode from any of the setfilepathinfo functions.
6662 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6663 done before calling this function.
6664 ****************************************************************************/
6666 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6667 struct files_struct *fsp,
6668 struct smb_filename *smb_fname,
6669 uint32_t dosmode)
6671 struct smb_filename *smb_fname_base;
6672 NTSTATUS status;
6674 if (!VALID_STAT(smb_fname->st)) {
6675 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6678 /* Always operate on the base_name, even if a stream was passed in. */
6679 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6680 smb_fname->base_name,
6681 NULL,
6682 &smb_fname->st,
6683 smb_fname->twrp,
6684 smb_fname->flags);
6685 if (smb_fname_base == NULL) {
6686 return NT_STATUS_NO_MEMORY;
6689 if (dosmode) {
6690 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6691 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6692 } else {
6693 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6697 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6699 /* check the mode isn't different, before changing it */
6700 if ((dosmode != 0) && (dosmode != fdos_mode(fsp))) {
6701 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6702 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6703 (unsigned int)dosmode));
6705 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6706 false)) {
6707 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6708 "%s failed (%s)\n",
6709 smb_fname_str_dbg(smb_fname_base),
6710 strerror(errno)));
6711 status = map_nt_error_from_unix(errno);
6712 goto out;
6715 status = NT_STATUS_OK;
6716 out:
6717 TALLOC_FREE(smb_fname_base);
6718 return status;
6721 /****************************************************************************
6722 Deal with setting the size from any of the setfilepathinfo functions.
6723 ****************************************************************************/
6725 static NTSTATUS smb_set_file_size(connection_struct *conn,
6726 struct smb_request *req,
6727 files_struct *fsp,
6728 struct smb_filename *smb_fname,
6729 const SMB_STRUCT_STAT *psbuf,
6730 off_t size,
6731 bool fail_after_createfile)
6733 NTSTATUS status = NT_STATUS_OK;
6734 files_struct *new_fsp = NULL;
6736 if (!VALID_STAT(*psbuf)) {
6737 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6740 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6741 (uint64_t)size,
6742 get_file_size_stat(psbuf));
6744 if (size == get_file_size_stat(psbuf)) {
6745 if (fsp == NULL) {
6746 return NT_STATUS_OK;
6748 if (!fsp->fsp_flags.modified) {
6749 return NT_STATUS_OK;
6751 trigger_write_time_update_immediate(fsp);
6752 return NT_STATUS_OK;
6755 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6756 smb_fname_str_dbg(smb_fname), (double)size));
6758 if (fsp &&
6759 !fsp->fsp_flags.is_pathref &&
6760 fsp_get_io_fd(fsp) != -1)
6762 /* Handle based call. */
6763 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6764 return NT_STATUS_ACCESS_DENIED;
6767 if (vfs_set_filelen(fsp, size) == -1) {
6768 return map_nt_error_from_unix(errno);
6770 trigger_write_time_update_immediate(fsp);
6771 return NT_STATUS_OK;
6774 status = SMB_VFS_CREATE_FILE(
6775 conn, /* conn */
6776 req, /* req */
6777 smb_fname, /* fname */
6778 FILE_WRITE_DATA, /* access_mask */
6779 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6780 FILE_SHARE_DELETE),
6781 FILE_OPEN, /* create_disposition*/
6782 0, /* create_options */
6783 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6784 0, /* oplock_request */
6785 NULL, /* lease */
6786 0, /* allocation_size */
6787 0, /* private_flags */
6788 NULL, /* sd */
6789 NULL, /* ea_list */
6790 &new_fsp, /* result */
6791 NULL, /* pinfo */
6792 NULL, NULL); /* create context */
6794 if (!NT_STATUS_IS_OK(status)) {
6795 /* NB. We check for open_was_deferred in the caller. */
6796 return status;
6799 /* See RAW-SFILEINFO-END-OF-FILE */
6800 if (fail_after_createfile) {
6801 close_file(req, new_fsp,NORMAL_CLOSE);
6802 return NT_STATUS_INVALID_LEVEL;
6805 if (vfs_set_filelen(new_fsp, size) == -1) {
6806 status = map_nt_error_from_unix(errno);
6807 close_file(req, new_fsp,NORMAL_CLOSE);
6808 return status;
6811 trigger_write_time_update_immediate(new_fsp);
6812 close_file(req, new_fsp,NORMAL_CLOSE);
6813 return NT_STATUS_OK;
6816 /****************************************************************************
6817 Deal with SMB_INFO_SET_EA.
6818 ****************************************************************************/
6820 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6821 const char *pdata,
6822 int total_data,
6823 files_struct *fsp,
6824 struct smb_filename *smb_fname)
6826 struct ea_list *ea_list = NULL;
6827 TALLOC_CTX *ctx = NULL;
6828 NTSTATUS status = NT_STATUS_OK;
6830 if (total_data < 10) {
6832 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6833 length. They seem to have no effect. Bug #3212. JRA */
6835 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6836 /* We're done. We only get EA info in this call. */
6837 return NT_STATUS_OK;
6840 return NT_STATUS_INVALID_PARAMETER;
6843 if (IVAL(pdata,0) > total_data) {
6844 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6845 IVAL(pdata,0), (unsigned int)total_data));
6846 return NT_STATUS_INVALID_PARAMETER;
6849 ctx = talloc_tos();
6850 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6851 if (!ea_list) {
6852 return NT_STATUS_INVALID_PARAMETER;
6855 if (fsp == NULL) {
6857 * The only way fsp can be NULL here is if
6858 * smb_fname points at a symlink and
6859 * and we're in POSIX context.
6860 * Ensure this is the case.
6862 * There is still a race condition in that
6863 * the symlink could be changed after we
6864 * checked it, so ensure we only operate
6865 * EA setting on a file handle.
6867 SMB_ASSERT(smb_fname->flags & SMB_FILENAME_POSIX_PATH);
6868 if (!(smb_fname->flags & SMB_FILENAME_POSIX_PATH)) {
6869 return NT_STATUS_ACCESS_DENIED;
6871 status = refuse_symlink(conn, NULL, smb_fname);
6872 SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED));
6873 return NT_STATUS_ACCESS_DENIED;
6876 status = set_ea(conn, fsp, ea_list);
6878 return status;
6881 /****************************************************************************
6882 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6883 ****************************************************************************/
6885 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6886 const char *pdata,
6887 int total_data,
6888 files_struct *fsp)
6890 struct ea_list *ea_list = NULL;
6891 NTSTATUS status;
6893 if (!fsp) {
6894 return NT_STATUS_INVALID_HANDLE;
6897 if (!lp_ea_support(SNUM(conn))) {
6898 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6899 "EA's not supported.\n",
6900 (unsigned int)total_data));
6901 return NT_STATUS_EAS_NOT_SUPPORTED;
6904 if (total_data < 10) {
6905 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6906 "too small.\n",
6907 (unsigned int)total_data));
6908 return NT_STATUS_INVALID_PARAMETER;
6911 ea_list = read_nttrans_ea_list(talloc_tos(),
6912 pdata,
6913 total_data);
6915 if (!ea_list) {
6916 return NT_STATUS_INVALID_PARAMETER;
6919 status = set_ea(conn, fsp, ea_list);
6921 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6922 smb_fname_str_dbg(fsp->fsp_name),
6923 nt_errstr(status) ));
6925 return status;
6929 /****************************************************************************
6930 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6931 ****************************************************************************/
6933 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6934 const char *pdata,
6935 int total_data,
6936 files_struct *fsp,
6937 struct smb_filename *smb_fname)
6939 NTSTATUS status = NT_STATUS_OK;
6940 bool delete_on_close;
6941 uint32_t dosmode = 0;
6943 if (total_data < 1) {
6944 return NT_STATUS_INVALID_PARAMETER;
6947 if (fsp == NULL) {
6948 return NT_STATUS_INVALID_HANDLE;
6951 delete_on_close = (CVAL(pdata,0) ? True : False);
6952 dosmode = fdos_mode(fsp);
6954 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6955 "delete_on_close = %u\n",
6956 smb_fname_str_dbg(smb_fname),
6957 (unsigned int)dosmode,
6958 (unsigned int)delete_on_close ));
6960 if (delete_on_close) {
6961 status = can_set_delete_on_close(fsp, dosmode);
6962 if (!NT_STATUS_IS_OK(status)) {
6963 return status;
6967 /* The set is across all open files on this dev/inode pair. */
6968 if (!set_delete_on_close(fsp, delete_on_close,
6969 conn->session_info->security_token,
6970 conn->session_info->unix_token)) {
6971 return NT_STATUS_ACCESS_DENIED;
6973 return NT_STATUS_OK;
6976 /****************************************************************************
6977 Deal with SMB_FILE_POSITION_INFORMATION.
6978 ****************************************************************************/
6980 static NTSTATUS smb_file_position_information(connection_struct *conn,
6981 const char *pdata,
6982 int total_data,
6983 files_struct *fsp)
6985 uint64_t position_information;
6987 if (total_data < 8) {
6988 return NT_STATUS_INVALID_PARAMETER;
6991 if (fsp == NULL) {
6992 /* Ignore on pathname based set. */
6993 return NT_STATUS_OK;
6996 position_information = (uint64_t)IVAL(pdata,0);
6997 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6999 DEBUG(10,("smb_file_position_information: Set file position "
7000 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
7001 (double)position_information));
7002 fh_set_position_information(fsp->fh, position_information);
7003 return NT_STATUS_OK;
7006 /****************************************************************************
7007 Deal with SMB_FILE_MODE_INFORMATION.
7008 ****************************************************************************/
7010 static NTSTATUS smb_file_mode_information(connection_struct *conn,
7011 const char *pdata,
7012 int total_data)
7014 uint32_t mode;
7016 if (total_data < 4) {
7017 return NT_STATUS_INVALID_PARAMETER;
7019 mode = IVAL(pdata,0);
7020 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
7021 return NT_STATUS_INVALID_PARAMETER;
7023 return NT_STATUS_OK;
7026 /****************************************************************************
7027 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
7028 ****************************************************************************/
7030 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
7031 struct smb_request *req,
7032 const char *pdata,
7033 int total_data,
7034 struct smb_filename *new_smb_fname)
7036 char *link_target = NULL;
7037 struct smb_filename target_fname;
7038 TALLOC_CTX *ctx = talloc_tos();
7039 NTSTATUS status;
7040 int ret;
7041 struct smb_filename *parent_fname = NULL;
7042 struct smb_filename *base_name = NULL;
7044 /* Set a symbolic link. */
7045 /* Don't allow this if follow links is false. */
7047 if (total_data == 0) {
7048 return NT_STATUS_INVALID_PARAMETER;
7051 if (!lp_follow_symlinks(SNUM(conn))) {
7052 return NT_STATUS_ACCESS_DENIED;
7055 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
7056 total_data, STR_TERMINATE);
7058 if (!link_target) {
7059 return NT_STATUS_INVALID_PARAMETER;
7062 target_fname = (struct smb_filename) {
7063 .base_name = link_target,
7066 /* Removes @GMT tokens if any */
7067 status = canonicalize_snapshot_path(&target_fname, UCF_GMT_PATHNAME, 0);
7068 if (!NT_STATUS_IS_OK(status)) {
7069 return status;
7072 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
7073 new_smb_fname->base_name, link_target ));
7075 status = parent_pathref(talloc_tos(),
7076 conn->cwd_fsp,
7077 new_smb_fname,
7078 &parent_fname,
7079 &base_name);
7080 if (!NT_STATUS_IS_OK(status)) {
7081 return status;
7084 ret = SMB_VFS_SYMLINKAT(conn,
7085 &target_fname,
7086 parent_fname->fsp,
7087 base_name);
7088 if (ret != 0) {
7089 TALLOC_FREE(parent_fname);
7090 return map_nt_error_from_unix(errno);
7093 TALLOC_FREE(parent_fname);
7094 return NT_STATUS_OK;
7097 /****************************************************************************
7098 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
7099 ****************************************************************************/
7101 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
7102 struct smb_request *req,
7103 const char *pdata, int total_data,
7104 struct smb_filename *smb_fname_new)
7106 char *oldname = NULL;
7107 struct smb_filename *smb_fname_old = NULL;
7108 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7109 TALLOC_CTX *ctx = talloc_tos();
7110 NTSTATUS status = NT_STATUS_OK;
7112 /* Set a hard link. */
7113 if (total_data == 0) {
7114 return NT_STATUS_INVALID_PARAMETER;
7117 if (req->posix_pathnames) {
7118 srvstr_get_path_posix(ctx,
7119 pdata,
7120 req->flags2,
7121 &oldname,
7122 pdata,
7123 total_data,
7124 STR_TERMINATE,
7125 &status);
7126 } else {
7127 srvstr_get_path(ctx,
7128 pdata,
7129 req->flags2,
7130 &oldname,
7131 pdata,
7132 total_data,
7133 STR_TERMINATE,
7134 &status);
7136 if (!NT_STATUS_IS_OK(status)) {
7137 return status;
7140 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
7141 smb_fname_str_dbg(smb_fname_new), oldname));
7143 status = filename_convert(ctx,
7144 conn,
7145 oldname,
7146 ucf_flags,
7148 &smb_fname_old);
7149 if (!NT_STATUS_IS_OK(status)) {
7150 return status;
7153 return hardlink_internals(ctx, conn, req, false,
7154 smb_fname_old, smb_fname_new);
7157 /****************************************************************************
7158 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
7159 ****************************************************************************/
7161 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
7162 struct smb_request *req,
7163 const char *pdata,
7164 int total_data,
7165 files_struct *fsp,
7166 struct smb_filename *smb_fname_src)
7168 bool overwrite;
7169 uint32_t len;
7170 char *newname = NULL;
7171 struct smb_filename *smb_fname_dst = NULL;
7172 const char *dst_original_lcomp = NULL;
7173 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7174 NTSTATUS status = NT_STATUS_OK;
7175 TALLOC_CTX *ctx = talloc_tos();
7177 if (!fsp) {
7178 return NT_STATUS_INVALID_HANDLE;
7181 if (total_data < 20) {
7182 return NT_STATUS_INVALID_PARAMETER;
7185 overwrite = (CVAL(pdata,0) ? True : False);
7186 len = IVAL(pdata,16);
7188 if (len > (total_data - 20) || (len == 0)) {
7189 return NT_STATUS_INVALID_PARAMETER;
7192 if (req->posix_pathnames) {
7193 srvstr_get_path_posix(ctx,
7194 pdata,
7195 req->flags2,
7196 &newname,
7197 &pdata[20],
7198 len,
7199 STR_TERMINATE,
7200 &status);
7201 } else {
7202 srvstr_get_path(ctx,
7203 pdata,
7204 req->flags2,
7205 &newname,
7206 &pdata[20],
7207 len,
7208 STR_TERMINATE,
7209 &status);
7211 if (!NT_STATUS_IS_OK(status)) {
7212 return status;
7215 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
7216 newname));
7218 status = filename_convert(ctx,
7219 conn,
7220 newname,
7221 ucf_flags,
7223 &smb_fname_dst);
7224 if (!NT_STATUS_IS_OK(status)) {
7225 return status;
7228 if (fsp->base_fsp) {
7229 /* newname must be a stream name. */
7230 if (newname[0] != ':') {
7231 return NT_STATUS_NOT_SUPPORTED;
7234 /* Create an smb_fname to call rename_internals_fsp() with. */
7235 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7236 fsp->base_fsp->fsp_name->base_name,
7237 newname,
7238 NULL,
7239 fsp->base_fsp->fsp_name->twrp,
7240 fsp->base_fsp->fsp_name->flags);
7241 if (smb_fname_dst == NULL) {
7242 status = NT_STATUS_NO_MEMORY;
7243 goto out;
7248 * Set the original last component, since
7249 * rename_internals_fsp() requires it.
7251 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7252 conn,
7253 newname,
7254 ucf_flags);
7255 if (dst_original_lcomp == NULL) {
7256 status = NT_STATUS_NO_MEMORY;
7257 goto out;
7260 DEBUG(10,("smb2_file_rename_information: "
7261 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7262 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7263 smb_fname_str_dbg(smb_fname_dst)));
7264 status = rename_internals_fsp(conn,
7265 fsp,
7266 smb_fname_dst,
7267 dst_original_lcomp,
7268 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7269 overwrite);
7271 out:
7272 TALLOC_FREE(smb_fname_dst);
7273 return status;
7276 static NTSTATUS smb_file_link_information(connection_struct *conn,
7277 struct smb_request *req,
7278 const char *pdata,
7279 int total_data,
7280 files_struct *fsp,
7281 struct smb_filename *smb_fname_src)
7283 bool overwrite;
7284 uint32_t len;
7285 char *newname = NULL;
7286 struct smb_filename *smb_fname_dst = NULL;
7287 NTSTATUS status = NT_STATUS_OK;
7288 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
7289 TALLOC_CTX *ctx = talloc_tos();
7291 if (!fsp) {
7292 return NT_STATUS_INVALID_HANDLE;
7295 if (total_data < 20) {
7296 return NT_STATUS_INVALID_PARAMETER;
7299 overwrite = (CVAL(pdata,0) ? true : false);
7300 len = IVAL(pdata,16);
7302 if (len > (total_data - 20) || (len == 0)) {
7303 return NT_STATUS_INVALID_PARAMETER;
7306 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7307 srvstr_get_path_posix(ctx,
7308 pdata,
7309 req->flags2,
7310 &newname,
7311 &pdata[20],
7312 len,
7313 STR_TERMINATE,
7314 &status);
7315 ucf_flags |= UCF_POSIX_PATHNAMES;
7316 } else {
7317 srvstr_get_path(ctx,
7318 pdata,
7319 req->flags2,
7320 &newname,
7321 &pdata[20],
7322 len,
7323 STR_TERMINATE,
7324 &status);
7326 if (!NT_STATUS_IS_OK(status)) {
7327 return status;
7330 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7331 newname));
7333 status = filename_convert(ctx,
7334 conn,
7335 newname,
7336 ucf_flags,
7338 &smb_fname_dst);
7339 if (!NT_STATUS_IS_OK(status)) {
7340 return status;
7343 if (fsp->base_fsp) {
7344 /* No stream names. */
7345 return NT_STATUS_NOT_SUPPORTED;
7348 DEBUG(10,("smb_file_link_information: "
7349 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7350 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7351 smb_fname_str_dbg(smb_fname_dst)));
7352 status = hardlink_internals(ctx,
7353 conn,
7354 req,
7355 overwrite,
7356 fsp->fsp_name,
7357 smb_fname_dst);
7359 TALLOC_FREE(smb_fname_dst);
7360 return status;
7363 /****************************************************************************
7364 Deal with SMB_FILE_RENAME_INFORMATION.
7365 ****************************************************************************/
7367 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7368 struct smb_request *req,
7369 const char *pdata,
7370 int total_data,
7371 files_struct *fsp,
7372 struct smb_filename *smb_fname_src)
7374 bool overwrite;
7375 uint32_t root_fid;
7376 uint32_t len;
7377 char *newname = NULL;
7378 struct smb_filename *smb_fname_dst = NULL;
7379 const char *dst_original_lcomp = NULL;
7380 NTSTATUS status = NT_STATUS_OK;
7381 char *p;
7382 TALLOC_CTX *ctx = talloc_tos();
7384 if (total_data < 13) {
7385 return NT_STATUS_INVALID_PARAMETER;
7388 overwrite = (CVAL(pdata,0) ? True : False);
7389 root_fid = IVAL(pdata,4);
7390 len = IVAL(pdata,8);
7392 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7393 return NT_STATUS_INVALID_PARAMETER;
7396 if (req->posix_pathnames) {
7397 srvstr_get_path_posix(ctx,
7398 pdata,
7399 req->flags2,
7400 &newname,
7401 &pdata[12],
7402 len,
7404 &status);
7405 } else {
7406 srvstr_get_path(ctx,
7407 pdata,
7408 req->flags2,
7409 &newname,
7410 &pdata[12],
7411 len,
7413 &status);
7415 if (!NT_STATUS_IS_OK(status)) {
7416 return status;
7419 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7420 newname));
7422 /* Check the new name has no '/' characters. */
7423 if (strchr_m(newname, '/')) {
7424 return NT_STATUS_NOT_SUPPORTED;
7427 if (fsp && fsp->base_fsp) {
7428 /* newname must be a stream name. */
7429 if (newname[0] != ':') {
7430 return NT_STATUS_NOT_SUPPORTED;
7433 /* Create an smb_fname to call rename_internals_fsp() with. */
7434 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7435 fsp->base_fsp->fsp_name->base_name,
7436 newname,
7437 NULL,
7438 fsp->base_fsp->fsp_name->twrp,
7439 fsp->base_fsp->fsp_name->flags);
7440 if (smb_fname_dst == NULL) {
7441 status = NT_STATUS_NO_MEMORY;
7442 goto out;
7446 * Get the original last component, since
7447 * rename_internals_fsp() requires it.
7449 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7450 conn,
7451 newname,
7453 if (dst_original_lcomp == NULL) {
7454 status = NT_STATUS_NO_MEMORY;
7455 goto out;
7458 } else {
7460 * Build up an smb_fname_dst based on the filename passed in.
7461 * We basically just strip off the last component, and put on
7462 * the newname instead.
7464 char *base_name = NULL;
7465 uint32_t ucf_flags = UCF_ALWAYS_ALLOW_WCARD_LCOMP|
7466 ucf_flags_from_smb_request(req);
7468 /* newname must *not* be a stream name. */
7469 if (newname[0] == ':') {
7470 return NT_STATUS_NOT_SUPPORTED;
7474 * Strip off the last component (filename) of the path passed
7475 * in.
7477 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7478 if (!base_name) {
7479 return NT_STATUS_NO_MEMORY;
7481 p = strrchr_m(base_name, '/');
7482 if (p) {
7483 p[1] = '\0';
7484 } else {
7485 base_name = talloc_strdup(ctx, "");
7486 if (!base_name) {
7487 return NT_STATUS_NO_MEMORY;
7490 /* Append the new name. */
7491 base_name = talloc_asprintf_append(base_name,
7492 "%s",
7493 newname);
7494 if (!base_name) {
7495 return NT_STATUS_NO_MEMORY;
7498 status = filename_convert(ctx,
7499 conn,
7500 base_name,
7501 ucf_flags,
7503 &smb_fname_dst);
7505 /* If an error we expect this to be
7506 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7508 if (!NT_STATUS_IS_OK(status)) {
7509 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7510 status)) {
7511 goto out;
7513 /* Create an smb_fname to call rename_internals_fsp() */
7514 smb_fname_dst = synthetic_smb_fname(ctx,
7515 base_name,
7516 NULL,
7517 NULL,
7518 smb_fname_src->twrp,
7519 smb_fname_src->flags);
7520 if (smb_fname_dst == NULL) {
7521 status = NT_STATUS_NO_MEMORY;
7522 goto out;
7525 dst_original_lcomp = get_original_lcomp(smb_fname_dst,
7526 conn,
7527 newname,
7528 ucf_flags);
7529 if (dst_original_lcomp == NULL) {
7530 status = NT_STATUS_NO_MEMORY;
7531 goto out;
7535 if (fsp != NULL && fsp->fsp_flags.is_fsa) {
7536 DEBUG(10,("smb_file_rename_information: "
7537 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7538 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7539 smb_fname_str_dbg(smb_fname_dst)));
7540 status = rename_internals_fsp(conn,
7541 fsp,
7542 smb_fname_dst,
7543 dst_original_lcomp,
7545 overwrite);
7546 } else {
7547 DEBUG(10,("smb_file_rename_information: "
7548 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7549 smb_fname_str_dbg(smb_fname_src),
7550 smb_fname_str_dbg(smb_fname_dst)));
7551 status = rename_internals(ctx,
7552 conn,
7553 req,
7554 smb_fname_src,
7555 NULL,
7556 smb_fname_dst,
7557 dst_original_lcomp,
7559 overwrite,
7560 FILE_WRITE_ATTRIBUTES);
7562 out:
7563 TALLOC_FREE(smb_fname_dst);
7564 return status;
7567 /****************************************************************************
7568 Deal with SMB_SET_POSIX_ACL.
7569 ****************************************************************************/
7571 #if defined(HAVE_POSIX_ACLS)
7572 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7573 struct smb_request *req,
7574 const char *pdata,
7575 int total_data_in,
7576 files_struct *fsp,
7577 struct smb_filename *smb_fname)
7579 uint16_t posix_acl_version;
7580 uint16_t num_file_acls;
7581 uint16_t num_def_acls;
7582 bool valid_file_acls = true;
7583 bool valid_def_acls = true;
7584 NTSTATUS status;
7585 unsigned int size_needed;
7586 unsigned int total_data;
7587 bool close_fsp = false;
7589 if (total_data_in < 0) {
7590 status = NT_STATUS_INVALID_PARAMETER;
7591 goto out;
7594 total_data = total_data_in;
7596 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7597 status = NT_STATUS_INVALID_PARAMETER;
7598 goto out;
7600 posix_acl_version = SVAL(pdata,0);
7601 num_file_acls = SVAL(pdata,2);
7602 num_def_acls = SVAL(pdata,4);
7604 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7605 valid_file_acls = false;
7606 num_file_acls = 0;
7609 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7610 valid_def_acls = false;
7611 num_def_acls = 0;
7614 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7615 status = NT_STATUS_INVALID_PARAMETER;
7616 goto out;
7619 /* Wrap checks. */
7620 if (num_file_acls + num_def_acls < num_file_acls) {
7621 status = NT_STATUS_INVALID_PARAMETER;
7622 goto out;
7625 size_needed = num_file_acls + num_def_acls;
7628 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7629 * than UINT_MAX, so check by division.
7631 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7632 status = NT_STATUS_INVALID_PARAMETER;
7633 goto out;
7636 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7637 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7638 status = NT_STATUS_INVALID_PARAMETER;
7639 goto out;
7641 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7643 if (total_data < size_needed) {
7644 status = NT_STATUS_INVALID_PARAMETER;
7645 goto out;
7649 * Ensure we always operate on a file descriptor, not just
7650 * the filename.
7652 if (fsp == NULL || !fsp->fsp_flags.is_fsa) {
7653 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7654 SEC_STD_WRITE_DAC|
7655 SEC_STD_READ_CONTROL|
7656 FILE_READ_ATTRIBUTES|
7657 FILE_WRITE_ATTRIBUTES;
7659 status = get_posix_fsp(conn,
7660 req,
7661 smb_fname,
7662 access_mask,
7663 &fsp);
7665 if (!NT_STATUS_IS_OK(status)) {
7666 goto out;
7668 close_fsp = true;
7671 /* Here we know fsp != NULL */
7672 SMB_ASSERT(fsp != NULL);
7674 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7675 if (!NT_STATUS_IS_OK(status)) {
7676 goto out;
7679 /* If we have a default acl, this *must* be a directory. */
7680 if (valid_def_acls && !fsp->fsp_flags.is_directory) {
7681 DBG_INFO("Can't set default acls on "
7682 "non-directory %s\n",
7683 fsp_str_dbg(fsp));
7684 return NT_STATUS_INVALID_HANDLE;
7687 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7688 "num_def_acls = %"PRIu16"\n",
7689 fsp_str_dbg(fsp),
7690 num_file_acls,
7691 num_def_acls);
7693 /* Move pdata to the start of the file ACL entries. */
7694 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7696 if (valid_file_acls) {
7697 status = set_unix_posix_acl(conn,
7698 fsp,
7699 num_file_acls,
7700 pdata);
7701 if (!NT_STATUS_IS_OK(status)) {
7702 goto out;
7706 /* Move pdata to the start of the default ACL entries. */
7707 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7709 if (valid_def_acls) {
7710 status = set_unix_posix_default_acl(conn,
7711 fsp,
7712 num_def_acls,
7713 pdata);
7714 if (!NT_STATUS_IS_OK(status)) {
7715 goto out;
7719 status = NT_STATUS_OK;
7721 out:
7723 if (close_fsp) {
7724 (void)close_file(req, fsp, NORMAL_CLOSE);
7725 fsp = NULL;
7727 return status;
7729 #endif
7731 /****************************************************************************
7732 Deal with SMB_SET_POSIX_LOCK.
7733 ****************************************************************************/
7735 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7737 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7738 struct smb_request *req,
7739 const char *pdata,
7740 int total_data,
7741 files_struct *fsp)
7743 struct tevent_req *subreq = NULL;
7744 struct smbd_lock_element *lck = NULL;
7745 uint64_t count;
7746 uint64_t offset;
7747 uint64_t smblctx;
7748 bool blocking_lock = False;
7749 enum brl_type lock_type;
7751 NTSTATUS status = NT_STATUS_OK;
7753 if (fsp == NULL ||
7754 fsp->fsp_flags.is_pathref ||
7755 fsp_get_io_fd(fsp) == -1)
7757 return NT_STATUS_INVALID_HANDLE;
7760 if (total_data != POSIX_LOCK_DATA_SIZE) {
7761 return NT_STATUS_INVALID_PARAMETER;
7764 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7765 case POSIX_LOCK_TYPE_READ:
7766 lock_type = READ_LOCK;
7767 break;
7768 case POSIX_LOCK_TYPE_WRITE:
7769 /* Return the right POSIX-mappable error code for files opened read-only. */
7770 if (!fsp->fsp_flags.can_write) {
7771 return NT_STATUS_INVALID_HANDLE;
7773 lock_type = WRITE_LOCK;
7774 break;
7775 case POSIX_LOCK_TYPE_UNLOCK:
7776 lock_type = UNLOCK_LOCK;
7777 break;
7778 default:
7779 return NT_STATUS_INVALID_PARAMETER;
7782 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7783 case POSIX_LOCK_FLAG_NOWAIT:
7784 blocking_lock = false;
7785 break;
7786 case POSIX_LOCK_FLAG_WAIT:
7787 blocking_lock = true;
7788 break;
7789 default:
7790 return NT_STATUS_INVALID_PARAMETER;
7793 if (!lp_blocking_locks(SNUM(conn))) {
7794 blocking_lock = False;
7797 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7798 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7799 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7800 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7801 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7803 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7804 "count = %"PRIu64", offset = %"PRIu64"\n",
7805 fsp_str_dbg(fsp),
7806 (unsigned int)lock_type,
7807 smblctx,
7808 count,
7809 offset);
7811 if (lock_type == UNLOCK_LOCK) {
7812 struct smbd_lock_element l = {
7813 .req_guid = smbd_request_guid(req, 0),
7814 .smblctx = smblctx,
7815 .brltype = UNLOCK_LOCK,
7816 .offset = offset,
7817 .count = count,
7819 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7820 return status;
7823 lck = talloc(req, struct smbd_lock_element);
7824 if (lck == NULL) {
7825 return NT_STATUS_NO_MEMORY;
7828 *lck = (struct smbd_lock_element) {
7829 .req_guid = smbd_request_guid(req, 0),
7830 .smblctx = smblctx,
7831 .brltype = lock_type,
7832 .count = count,
7833 .offset = offset,
7836 subreq = smbd_smb1_do_locks_send(
7837 fsp,
7838 req->sconn->ev_ctx,
7839 &req,
7840 fsp,
7841 blocking_lock ? UINT32_MAX : 0,
7842 true, /* large_offset */
7843 POSIX_LOCK,
7845 lck);
7846 if (subreq == NULL) {
7847 TALLOC_FREE(lck);
7848 return NT_STATUS_NO_MEMORY;
7850 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7851 return NT_STATUS_EVENT_PENDING;
7854 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7856 struct smb_request *req = NULL;
7857 NTSTATUS status;
7858 bool ok;
7860 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7861 SMB_ASSERT(ok);
7863 status = smbd_smb1_do_locks_recv(subreq);
7864 TALLOC_FREE(subreq);
7866 if (NT_STATUS_IS_OK(status)) {
7867 char params[2] = {0};
7868 /* Fake up max_data_bytes here - we know it fits. */
7869 send_trans2_replies(
7870 req->conn,
7871 req,
7872 NT_STATUS_OK,
7873 params,
7875 NULL,
7877 0xffff);
7878 } else {
7879 reply_nterror(req, status);
7880 ok = srv_send_smb(
7881 req->xconn,
7882 (char *)req->outbuf,
7883 true,
7884 req->seqnum+1,
7885 IS_CONN_ENCRYPTED(req->conn),
7886 NULL);
7887 if (!ok) {
7888 exit_server_cleanly("smb_set_posix_lock_done: "
7889 "srv_send_smb failed.");
7893 TALLOC_FREE(req);
7894 return;
7897 /****************************************************************************
7898 Deal with SMB_SET_FILE_BASIC_INFO.
7899 ****************************************************************************/
7901 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7902 const char *pdata,
7903 int total_data,
7904 files_struct *fsp,
7905 struct smb_filename *smb_fname)
7907 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7908 struct smb_file_time ft;
7909 uint32_t dosmode = 0;
7910 NTSTATUS status = NT_STATUS_OK;
7912 init_smb_file_time(&ft);
7914 if (total_data < 36) {
7915 return NT_STATUS_INVALID_PARAMETER;
7918 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7919 if (!NT_STATUS_IS_OK(status)) {
7920 return status;
7923 /* Set the attributes */
7924 dosmode = IVAL(pdata,32);
7925 status = smb_set_file_dosmode(conn, fsp, smb_fname, dosmode);
7926 if (!NT_STATUS_IS_OK(status)) {
7927 return status;
7930 /* create time */
7931 ft.create_time = pull_long_date_full_timespec(pdata);
7933 /* access time */
7934 ft.atime = pull_long_date_full_timespec(pdata+8);
7936 /* write time. */
7937 ft.mtime = pull_long_date_full_timespec(pdata+16);
7939 /* change time. */
7940 ft.ctime = pull_long_date_full_timespec(pdata+24);
7942 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7943 smb_fname_str_dbg(smb_fname)));
7945 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7946 if (!NT_STATUS_IS_OK(status)) {
7947 return status;
7950 if (fsp != NULL && fsp->fsp_flags.modified) {
7951 trigger_write_time_update_immediate(fsp);
7953 return NT_STATUS_OK;
7956 /****************************************************************************
7957 Deal with SMB_INFO_STANDARD.
7958 ****************************************************************************/
7960 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7961 const char *pdata,
7962 int total_data,
7963 files_struct *fsp,
7964 struct smb_filename *smb_fname)
7966 NTSTATUS status;
7967 struct smb_file_time ft;
7969 init_smb_file_time(&ft);
7971 if (total_data < 12) {
7972 return NT_STATUS_INVALID_PARAMETER;
7975 /* create time */
7976 ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
7977 /* access time */
7978 ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
7979 /* write time */
7980 ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
7982 DEBUG(10,("smb_set_info_standard: file %s\n",
7983 smb_fname_str_dbg(smb_fname)));
7985 status = check_access_fsp(fsp, FILE_WRITE_ATTRIBUTES);
7986 if (!NT_STATUS_IS_OK(status)) {
7987 return status;
7990 status = smb_set_file_time(conn, fsp, smb_fname, &ft, true);
7991 if (!NT_STATUS_IS_OK(status)) {
7992 return status;
7995 if (fsp != NULL && fsp->fsp_flags.modified) {
7996 trigger_write_time_update_immediate(fsp);
7998 return NT_STATUS_OK;
8001 /****************************************************************************
8002 Deal with SMB_SET_FILE_ALLOCATION_INFO.
8003 ****************************************************************************/
8005 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
8006 struct smb_request *req,
8007 const char *pdata,
8008 int total_data,
8009 files_struct *fsp,
8010 struct smb_filename *smb_fname)
8012 uint64_t allocation_size = 0;
8013 NTSTATUS status = NT_STATUS_OK;
8014 files_struct *new_fsp = NULL;
8016 if (!VALID_STAT(smb_fname->st)) {
8017 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8020 if (total_data < 8) {
8021 return NT_STATUS_INVALID_PARAMETER;
8024 allocation_size = (uint64_t)IVAL(pdata,0);
8025 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
8026 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
8027 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8028 (double)allocation_size));
8030 if (allocation_size) {
8031 allocation_size = smb_roundup(conn, allocation_size);
8034 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
8035 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
8036 (double)allocation_size));
8038 if (fsp &&
8039 !fsp->fsp_flags.is_pathref &&
8040 fsp_get_io_fd(fsp) != -1)
8042 /* Open file handle. */
8043 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
8044 return NT_STATUS_ACCESS_DENIED;
8047 /* Only change if needed. */
8048 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8049 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
8050 return map_nt_error_from_unix(errno);
8053 /* But always update the time. */
8055 * This is equivalent to a write. Ensure it's seen immediately
8056 * if there are no pending writes.
8058 trigger_write_time_update_immediate(fsp);
8059 return NT_STATUS_OK;
8062 /* Pathname or stat or directory file. */
8063 status = SMB_VFS_CREATE_FILE(
8064 conn, /* conn */
8065 req, /* req */
8066 smb_fname, /* fname */
8067 FILE_WRITE_DATA, /* access_mask */
8068 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8069 FILE_SHARE_DELETE),
8070 FILE_OPEN, /* create_disposition*/
8071 0, /* create_options */
8072 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
8073 0, /* oplock_request */
8074 NULL, /* lease */
8075 0, /* allocation_size */
8076 0, /* private_flags */
8077 NULL, /* sd */
8078 NULL, /* ea_list */
8079 &new_fsp, /* result */
8080 NULL, /* pinfo */
8081 NULL, NULL); /* create context */
8083 if (!NT_STATUS_IS_OK(status)) {
8084 /* NB. We check for open_was_deferred in the caller. */
8085 return status;
8088 /* Only change if needed. */
8089 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
8090 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
8091 status = map_nt_error_from_unix(errno);
8092 close_file(req, new_fsp, NORMAL_CLOSE);
8093 return status;
8097 /* Changing the allocation size should set the last mod time. */
8099 * This is equivalent to a write. Ensure it's seen immediately
8100 * if there are no pending writes.
8102 trigger_write_time_update_immediate(new_fsp);
8103 close_file(req, new_fsp, NORMAL_CLOSE);
8104 return NT_STATUS_OK;
8107 /****************************************************************************
8108 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
8109 ****************************************************************************/
8111 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
8112 struct smb_request *req,
8113 const char *pdata,
8114 int total_data,
8115 files_struct *fsp,
8116 struct smb_filename *smb_fname,
8117 bool fail_after_createfile)
8119 off_t size;
8121 if (total_data < 8) {
8122 return NT_STATUS_INVALID_PARAMETER;
8125 size = IVAL(pdata,0);
8126 size |= (((off_t)IVAL(pdata,4)) << 32);
8127 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
8128 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
8129 (double)size));
8131 return smb_set_file_size(conn, req,
8132 fsp,
8133 smb_fname,
8134 &smb_fname->st,
8135 size,
8136 fail_after_createfile);
8139 /****************************************************************************
8140 Allow a UNIX info mknod.
8141 ****************************************************************************/
8143 static NTSTATUS smb_unix_mknod(connection_struct *conn,
8144 const char *pdata,
8145 int total_data,
8146 const struct smb_filename *smb_fname)
8148 uint32_t file_type = IVAL(pdata,56);
8149 #if defined(HAVE_MAKEDEV)
8150 uint32_t dev_major = IVAL(pdata,60);
8151 uint32_t dev_minor = IVAL(pdata,68);
8152 #endif
8153 SMB_DEV_T dev = (SMB_DEV_T)0;
8154 uint32_t raw_unixmode = IVAL(pdata,84);
8155 NTSTATUS status;
8156 mode_t unixmode;
8157 int ret;
8158 struct smb_filename *parent_fname = NULL;
8159 struct smb_filename *base_name = NULL;
8161 if (total_data < 100) {
8162 return NT_STATUS_INVALID_PARAMETER;
8165 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8166 PERM_NEW_FILE, &unixmode);
8167 if (!NT_STATUS_IS_OK(status)) {
8168 return status;
8171 #if defined(HAVE_MAKEDEV)
8172 dev = makedev(dev_major, dev_minor);
8173 #endif
8175 switch (file_type) {
8176 /* We can't create other objects here. */
8177 case UNIX_TYPE_FILE:
8178 case UNIX_TYPE_DIR:
8179 case UNIX_TYPE_SYMLINK:
8180 return NT_STATUS_ACCESS_DENIED;
8181 #if defined(S_IFIFO)
8182 case UNIX_TYPE_FIFO:
8183 unixmode |= S_IFIFO;
8184 break;
8185 #endif
8186 #if defined(S_IFSOCK)
8187 case UNIX_TYPE_SOCKET:
8188 unixmode |= S_IFSOCK;
8189 break;
8190 #endif
8191 #if defined(S_IFCHR)
8192 case UNIX_TYPE_CHARDEV:
8193 /* This is only allowed for root. */
8194 if (get_current_uid(conn) != sec_initial_uid()) {
8195 return NT_STATUS_ACCESS_DENIED;
8197 unixmode |= S_IFCHR;
8198 break;
8199 #endif
8200 #if defined(S_IFBLK)
8201 case UNIX_TYPE_BLKDEV:
8202 if (get_current_uid(conn) != sec_initial_uid()) {
8203 return NT_STATUS_ACCESS_DENIED;
8205 unixmode |= S_IFBLK;
8206 break;
8207 #endif
8208 default:
8209 return NT_STATUS_INVALID_PARAMETER;
8212 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
8213 "%.0f mode 0%o for file %s\n", (double)dev,
8214 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
8216 status = parent_pathref(talloc_tos(),
8217 conn->cwd_fsp,
8218 smb_fname,
8219 &parent_fname,
8220 &base_name);
8221 if (!NT_STATUS_IS_OK(status)) {
8222 return status;
8225 /* Ok - do the mknod. */
8226 ret = SMB_VFS_MKNODAT(conn,
8227 parent_fname->fsp,
8228 base_name,
8229 unixmode,
8230 dev);
8232 if (ret != 0) {
8233 TALLOC_FREE(parent_fname);
8234 return map_nt_error_from_unix(errno);
8237 /* If any of the other "set" calls fail we
8238 * don't want to end up with a half-constructed mknod.
8241 if (lp_inherit_permissions(SNUM(conn))) {
8242 inherit_access_posix_acl(conn,
8243 parent_fname,
8244 smb_fname,
8245 unixmode);
8247 TALLOC_FREE(parent_fname);
8249 return NT_STATUS_OK;
8252 /****************************************************************************
8253 Deal with SMB_SET_FILE_UNIX_BASIC.
8254 ****************************************************************************/
8256 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
8257 struct smb_request *req,
8258 const char *pdata,
8259 int total_data,
8260 files_struct *fsp,
8261 struct smb_filename *smb_fname)
8263 struct smb_file_time ft;
8264 uint32_t raw_unixmode;
8265 mode_t unixmode;
8266 off_t size = 0;
8267 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
8268 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
8269 NTSTATUS status = NT_STATUS_OK;
8270 enum perm_type ptype;
8271 files_struct *all_fsps = NULL;
8272 bool modify_mtime = true;
8273 struct file_id id;
8274 SMB_STRUCT_STAT sbuf;
8276 init_smb_file_time(&ft);
8278 if (total_data < 100) {
8279 return NT_STATUS_INVALID_PARAMETER;
8282 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8283 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8284 size=IVAL(pdata,0); /* first 8 Bytes are size */
8285 size |= (((off_t)IVAL(pdata,4)) << 32);
8288 ft.atime = pull_long_date_full_timespec(pdata+24); /* access_time */
8289 ft.mtime = pull_long_date_full_timespec(pdata+32); /* modification_time */
8290 set_owner = (uid_t)IVAL(pdata,40);
8291 set_grp = (gid_t)IVAL(pdata,48);
8292 raw_unixmode = IVAL(pdata,84);
8294 if (VALID_STAT(smb_fname->st)) {
8295 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8296 ptype = PERM_EXISTING_DIR;
8297 } else {
8298 ptype = PERM_EXISTING_FILE;
8300 } else {
8301 ptype = PERM_NEW_FILE;
8304 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8305 ptype, &unixmode);
8306 if (!NT_STATUS_IS_OK(status)) {
8307 return status;
8310 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8311 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8312 smb_fname_str_dbg(smb_fname), (double)size,
8313 (unsigned int)set_owner, (unsigned int)set_grp,
8314 (int)raw_unixmode));
8316 sbuf = smb_fname->st;
8318 if (!VALID_STAT(sbuf)) {
8320 * The only valid use of this is to create character and block
8321 * devices, and named pipes. This is deprecated (IMHO) and
8322 * a new info level should be used for mknod. JRA.
8325 return smb_unix_mknod(conn,
8326 pdata,
8327 total_data,
8328 smb_fname);
8331 #if 1
8332 /* Horrible backwards compatibility hack as an old server bug
8333 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8334 * */
8336 if (!size) {
8337 size = get_file_size_stat(&sbuf);
8339 #endif
8342 * Deal with the UNIX specific mode set.
8345 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8346 int ret;
8348 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8349 "setting mode 0%o for file %s\n",
8350 (unsigned int)unixmode,
8351 smb_fname_str_dbg(smb_fname)));
8352 if (fsp &&
8353 !fsp->fsp_flags.is_pathref &&
8354 fsp_get_io_fd(fsp) != -1)
8356 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8357 } else {
8358 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8360 if (ret != 0) {
8361 return map_nt_error_from_unix(errno);
8366 * Deal with the UNIX specific uid set.
8369 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8370 (sbuf.st_ex_uid != set_owner)) {
8371 int ret;
8373 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8374 "changing owner %u for path %s\n",
8375 (unsigned int)set_owner,
8376 smb_fname_str_dbg(smb_fname)));
8378 if (fsp &&
8379 !fsp->fsp_flags.is_pathref &&
8380 fsp_get_io_fd(fsp) != -1)
8382 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8383 } else {
8385 * UNIX extensions calls must always operate
8386 * on symlinks.
8388 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8389 set_owner, (gid_t)-1);
8392 if (ret != 0) {
8393 status = map_nt_error_from_unix(errno);
8394 return status;
8399 * Deal with the UNIX specific gid set.
8402 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8403 (sbuf.st_ex_gid != set_grp)) {
8404 int ret;
8406 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8407 "changing group %u for file %s\n",
8408 (unsigned int)set_grp,
8409 smb_fname_str_dbg(smb_fname)));
8410 if (fsp &&
8411 !fsp->fsp_flags.is_pathref &&
8412 fsp_get_io_fd(fsp) != -1)
8414 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8415 } else {
8417 * UNIX extensions calls must always operate
8418 * on symlinks.
8420 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8421 set_grp);
8423 if (ret != 0) {
8424 status = map_nt_error_from_unix(errno);
8425 return status;
8429 /* Deal with any size changes. */
8431 if (S_ISREG(sbuf.st_ex_mode)) {
8432 status = smb_set_file_size(conn, req,
8433 fsp,
8434 smb_fname,
8435 &sbuf,
8436 size,
8437 false);
8438 if (!NT_STATUS_IS_OK(status)) {
8439 return status;
8443 /* Deal with any time changes. */
8444 if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
8445 /* No change, don't cancel anything. */
8446 return status;
8449 id = vfs_file_id_from_sbuf(conn, &sbuf);
8450 for(all_fsps = file_find_di_first(conn->sconn, id, true); all_fsps;
8451 all_fsps = file_find_di_next(all_fsps, true)) {
8453 * We're setting the time explicitly for UNIX.
8454 * Cancel any pending changes over all handles.
8456 all_fsps->fsp_flags.update_write_time_on_close = false;
8457 TALLOC_FREE(all_fsps->update_write_time_event);
8461 * Override the "setting_write_time"
8462 * parameter here as it almost does what
8463 * we need. Just remember if we modified
8464 * mtime and send the notify ourselves.
8466 if (is_omit_timespec(&ft.mtime)) {
8467 modify_mtime = false;
8470 status = smb_set_file_time(conn,
8471 fsp,
8472 smb_fname,
8473 &ft,
8474 false);
8475 if (modify_mtime) {
8476 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8477 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8479 return status;
8482 /****************************************************************************
8483 Deal with SMB_SET_FILE_UNIX_INFO2.
8484 ****************************************************************************/
8486 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8487 struct smb_request *req,
8488 const char *pdata,
8489 int total_data,
8490 files_struct *fsp,
8491 struct smb_filename *smb_fname)
8493 NTSTATUS status;
8494 uint32_t smb_fflags;
8495 uint32_t smb_fmask;
8497 if (total_data < 116) {
8498 return NT_STATUS_INVALID_PARAMETER;
8501 /* Start by setting all the fields that are common between UNIX_BASIC
8502 * and UNIX_INFO2.
8504 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8505 fsp, smb_fname);
8506 if (!NT_STATUS_IS_OK(status)) {
8507 return status;
8510 smb_fflags = IVAL(pdata, 108);
8511 smb_fmask = IVAL(pdata, 112);
8513 /* NB: We should only attempt to alter the file flags if the client
8514 * sends a non-zero mask.
8516 if (smb_fmask != 0) {
8517 int stat_fflags = 0;
8519 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8520 smb_fmask, &stat_fflags)) {
8521 /* Client asked to alter a flag we don't understand. */
8522 return NT_STATUS_INVALID_PARAMETER;
8525 if (fsp &&
8526 !fsp->fsp_flags.is_pathref &&
8527 fsp_get_io_fd(fsp) != -1)
8529 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8530 return NT_STATUS_NOT_SUPPORTED;
8531 } else {
8532 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8533 stat_fflags) != 0) {
8534 return map_nt_error_from_unix(errno);
8539 /* XXX: need to add support for changing the create_time here. You
8540 * can do this for paths on Darwin with setattrlist(2). The right way
8541 * to hook this up is probably by extending the VFS utimes interface.
8544 return NT_STATUS_OK;
8547 /****************************************************************************
8548 Create a directory with POSIX semantics.
8549 ****************************************************************************/
8551 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8552 struct smb_request *req,
8553 char **ppdata,
8554 int total_data,
8555 struct smb_filename *smb_fname,
8556 int *pdata_return_size)
8558 NTSTATUS status = NT_STATUS_OK;
8559 uint32_t raw_unixmode = 0;
8560 mode_t unixmode = (mode_t)0;
8561 files_struct *fsp = NULL;
8562 uint16_t info_level_return = 0;
8563 int info;
8564 char *pdata = *ppdata;
8565 struct smb2_create_blobs *posx = NULL;
8567 if (total_data < 18) {
8568 return NT_STATUS_INVALID_PARAMETER;
8571 raw_unixmode = IVAL(pdata,8);
8572 /* Next 4 bytes are not yet defined. */
8574 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8575 PERM_NEW_DIR, &unixmode);
8576 if (!NT_STATUS_IS_OK(status)) {
8577 return status;
8580 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8581 if (!NT_STATUS_IS_OK(status)) {
8582 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8583 nt_errstr(status));
8584 return status;
8587 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8588 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8590 status = SMB_VFS_CREATE_FILE(
8591 conn, /* conn */
8592 req, /* req */
8593 smb_fname, /* fname */
8594 FILE_READ_ATTRIBUTES, /* access_mask */
8595 FILE_SHARE_NONE, /* share_access */
8596 FILE_CREATE, /* create_disposition*/
8597 FILE_DIRECTORY_FILE, /* create_options */
8598 0, /* file_attributes */
8599 0, /* oplock_request */
8600 NULL, /* lease */
8601 0, /* allocation_size */
8602 0, /* private_flags */
8603 NULL, /* sd */
8604 NULL, /* ea_list */
8605 &fsp, /* result */
8606 &info, /* pinfo */
8607 posx, /* in_context_blobs */
8608 NULL); /* out_context_blobs */
8610 TALLOC_FREE(posx);
8612 if (NT_STATUS_IS_OK(status)) {
8613 close_file(req, fsp, NORMAL_CLOSE);
8616 info_level_return = SVAL(pdata,16);
8618 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8619 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8620 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8621 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8622 } else {
8623 *pdata_return_size = 12;
8626 /* Realloc the data size */
8627 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8628 if (*ppdata == NULL) {
8629 *pdata_return_size = 0;
8630 return NT_STATUS_NO_MEMORY;
8632 pdata = *ppdata;
8634 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8635 SSVAL(pdata,2,0); /* No fnum. */
8636 SIVAL(pdata,4,info); /* Was directory created. */
8638 switch (info_level_return) {
8639 case SMB_QUERY_FILE_UNIX_BASIC:
8640 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8641 SSVAL(pdata,10,0); /* Padding. */
8642 store_file_unix_basic(conn, pdata + 12, fsp,
8643 &smb_fname->st);
8644 break;
8645 case SMB_QUERY_FILE_UNIX_INFO2:
8646 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8647 SSVAL(pdata,10,0); /* Padding. */
8648 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8649 &smb_fname->st);
8650 break;
8651 default:
8652 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8653 SSVAL(pdata,10,0); /* Padding. */
8654 break;
8657 return status;
8660 /****************************************************************************
8661 Open/Create a file with POSIX semantics.
8662 ****************************************************************************/
8664 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8665 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8667 static NTSTATUS smb_posix_open(connection_struct *conn,
8668 struct smb_request *req,
8669 char **ppdata,
8670 int total_data,
8671 struct smb_filename *smb_fname,
8672 int *pdata_return_size)
8674 bool extended_oplock_granted = False;
8675 char *pdata = *ppdata;
8676 uint32_t flags = 0;
8677 uint32_t wire_open_mode = 0;
8678 uint32_t raw_unixmode = 0;
8679 uint32_t attributes = 0;
8680 uint32_t create_disp = 0;
8681 uint32_t access_mask = 0;
8682 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8683 NTSTATUS status = NT_STATUS_OK;
8684 mode_t unixmode = (mode_t)0;
8685 files_struct *fsp = NULL;
8686 int oplock_request = 0;
8687 int info = 0;
8688 uint16_t info_level_return = 0;
8689 struct smb2_create_blobs *posx = NULL;
8691 if (total_data < 18) {
8692 return NT_STATUS_INVALID_PARAMETER;
8695 flags = IVAL(pdata,0);
8696 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8697 if (oplock_request) {
8698 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8701 wire_open_mode = IVAL(pdata,4);
8703 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8704 return smb_posix_mkdir(conn, req,
8705 ppdata,
8706 total_data,
8707 smb_fname,
8708 pdata_return_size);
8711 switch (wire_open_mode & SMB_ACCMODE) {
8712 case SMB_O_RDONLY:
8713 access_mask = SMB_O_RDONLY_MAPPING;
8714 break;
8715 case SMB_O_WRONLY:
8716 access_mask = SMB_O_WRONLY_MAPPING;
8717 break;
8718 case SMB_O_RDWR:
8719 access_mask = (SMB_O_RDONLY_MAPPING|
8720 SMB_O_WRONLY_MAPPING);
8721 break;
8722 default:
8723 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8724 (unsigned int)wire_open_mode ));
8725 return NT_STATUS_INVALID_PARAMETER;
8728 wire_open_mode &= ~SMB_ACCMODE;
8730 /* First take care of O_CREAT|O_EXCL interactions. */
8731 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8732 case (SMB_O_CREAT | SMB_O_EXCL):
8733 /* File exists fail. File not exist create. */
8734 create_disp = FILE_CREATE;
8735 break;
8736 case SMB_O_CREAT:
8737 /* File exists open. File not exist create. */
8738 create_disp = FILE_OPEN_IF;
8739 break;
8740 case SMB_O_EXCL:
8741 /* O_EXCL on its own without O_CREAT is undefined.
8742 We deliberately ignore it as some versions of
8743 Linux CIFSFS can send a bare O_EXCL on the
8744 wire which other filesystems in the kernel
8745 ignore. See bug 9519 for details. */
8747 /* Fallthrough. */
8749 case 0:
8750 /* File exists open. File not exist fail. */
8751 create_disp = FILE_OPEN;
8752 break;
8753 default:
8754 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8755 (unsigned int)wire_open_mode ));
8756 return NT_STATUS_INVALID_PARAMETER;
8759 /* Next factor in the effects of O_TRUNC. */
8760 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8762 if (wire_open_mode & SMB_O_TRUNC) {
8763 switch (create_disp) {
8764 case FILE_CREATE:
8765 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8766 /* Leave create_disp alone as
8767 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8769 /* File exists fail. File not exist create. */
8770 break;
8771 case FILE_OPEN_IF:
8772 /* SMB_O_CREAT | SMB_O_TRUNC */
8773 /* File exists overwrite. File not exist create. */
8774 create_disp = FILE_OVERWRITE_IF;
8775 break;
8776 case FILE_OPEN:
8777 /* SMB_O_TRUNC */
8778 /* File exists overwrite. File not exist fail. */
8779 create_disp = FILE_OVERWRITE;
8780 break;
8781 default:
8782 /* Cannot get here. */
8783 smb_panic("smb_posix_open: logic error");
8784 return NT_STATUS_INVALID_PARAMETER;
8788 raw_unixmode = IVAL(pdata,8);
8789 /* Next 4 bytes are not yet defined. */
8791 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8792 (VALID_STAT(smb_fname->st) ?
8793 PERM_EXISTING_FILE : PERM_NEW_FILE),
8794 &unixmode);
8796 if (!NT_STATUS_IS_OK(status)) {
8797 return status;
8800 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, unixmode);
8801 if (!NT_STATUS_IS_OK(status)) {
8802 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8803 nt_errstr(status));
8804 return status;
8807 if (wire_open_mode & SMB_O_SYNC) {
8808 create_options |= FILE_WRITE_THROUGH;
8810 if (wire_open_mode & SMB_O_APPEND) {
8811 access_mask |= FILE_APPEND_DATA;
8813 if (wire_open_mode & SMB_O_DIRECT) {
8814 attributes |= FILE_FLAG_NO_BUFFERING;
8817 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8818 VALID_STAT_OF_DIR(smb_fname->st)) {
8819 if (access_mask != SMB_O_RDONLY_MAPPING) {
8820 return NT_STATUS_FILE_IS_A_DIRECTORY;
8822 create_options &= ~FILE_NON_DIRECTORY_FILE;
8823 create_options |= FILE_DIRECTORY_FILE;
8826 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8827 smb_fname_str_dbg(smb_fname),
8828 (unsigned int)wire_open_mode,
8829 (unsigned int)unixmode ));
8831 status = SMB_VFS_CREATE_FILE(
8832 conn, /* conn */
8833 req, /* req */
8834 smb_fname, /* fname */
8835 access_mask, /* access_mask */
8836 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8837 FILE_SHARE_DELETE),
8838 create_disp, /* create_disposition*/
8839 create_options, /* create_options */
8840 attributes, /* file_attributes */
8841 oplock_request, /* oplock_request */
8842 NULL, /* lease */
8843 0, /* allocation_size */
8844 0, /* private_flags */
8845 NULL, /* sd */
8846 NULL, /* ea_list */
8847 &fsp, /* result */
8848 &info, /* pinfo */
8849 posx, /* in_context_blobs */
8850 NULL); /* out_context_blobs */
8852 TALLOC_FREE(posx);
8854 if (!NT_STATUS_IS_OK(status)) {
8855 return status;
8858 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8859 extended_oplock_granted = True;
8862 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8863 extended_oplock_granted = True;
8866 info_level_return = SVAL(pdata,16);
8868 /* Allocate the correct return size. */
8870 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8871 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8872 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8873 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8874 } else {
8875 *pdata_return_size = 12;
8878 /* Realloc the data size */
8879 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8880 if (*ppdata == NULL) {
8881 close_file(req, fsp, ERROR_CLOSE);
8882 *pdata_return_size = 0;
8883 return NT_STATUS_NO_MEMORY;
8885 pdata = *ppdata;
8887 if (extended_oplock_granted) {
8888 if (flags & REQUEST_BATCH_OPLOCK) {
8889 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8890 } else {
8891 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8893 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8894 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8895 } else {
8896 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8899 SSVAL(pdata,2,fsp->fnum);
8900 SIVAL(pdata,4,info); /* Was file created etc. */
8902 switch (info_level_return) {
8903 case SMB_QUERY_FILE_UNIX_BASIC:
8904 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8905 SSVAL(pdata,10,0); /* padding. */
8906 store_file_unix_basic(conn, pdata + 12, fsp,
8907 &smb_fname->st);
8908 break;
8909 case SMB_QUERY_FILE_UNIX_INFO2:
8910 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8911 SSVAL(pdata,10,0); /* padding. */
8912 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8913 &smb_fname->st);
8914 break;
8915 default:
8916 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8917 SSVAL(pdata,10,0); /* padding. */
8918 break;
8920 return NT_STATUS_OK;
8923 /****************************************************************************
8924 Delete a file with POSIX semantics.
8925 ****************************************************************************/
8927 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8928 struct smb_request *req,
8929 const char *pdata,
8930 int total_data,
8931 struct smb_filename *smb_fname)
8933 NTSTATUS status = NT_STATUS_OK;
8934 files_struct *fsp = NULL;
8935 uint16_t flags = 0;
8936 char del = 1;
8937 int info = 0;
8938 int create_options = 0;
8939 struct share_mode_lock *lck = NULL;
8940 bool other_nonposix_opens;
8941 struct smb2_create_blobs *posx = NULL;
8943 if (total_data < 2) {
8944 return NT_STATUS_INVALID_PARAMETER;
8947 flags = SVAL(pdata,0);
8949 if (!VALID_STAT(smb_fname->st)) {
8950 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8953 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8954 !VALID_STAT_OF_DIR(smb_fname->st)) {
8955 return NT_STATUS_NOT_A_DIRECTORY;
8958 DEBUG(10,("smb_posix_unlink: %s %s\n",
8959 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8960 smb_fname_str_dbg(smb_fname)));
8962 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8963 create_options |= FILE_DIRECTORY_FILE;
8966 status = make_smb2_posix_create_ctx(talloc_tos(), &posx, 0777);
8967 if (!NT_STATUS_IS_OK(status)) {
8968 DBG_WARNING("make_smb2_posix_create_ctx failed: %s\n",
8969 nt_errstr(status));
8970 return status;
8973 status = SMB_VFS_CREATE_FILE(
8974 conn, /* conn */
8975 req, /* req */
8976 smb_fname, /* fname */
8977 DELETE_ACCESS, /* access_mask */
8978 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8979 FILE_SHARE_DELETE),
8980 FILE_OPEN, /* create_disposition*/
8981 create_options, /* create_options */
8982 0, /* file_attributes */
8983 0, /* oplock_request */
8984 NULL, /* lease */
8985 0, /* allocation_size */
8986 0, /* private_flags */
8987 NULL, /* sd */
8988 NULL, /* ea_list */
8989 &fsp, /* result */
8990 &info, /* pinfo */
8991 posx, /* in_context_blobs */
8992 NULL); /* out_context_blobs */
8994 TALLOC_FREE(posx);
8996 if (!NT_STATUS_IS_OK(status)) {
8997 return status;
9001 * Don't lie to client. If we can't really delete due to
9002 * non-POSIX opens return SHARING_VIOLATION.
9005 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
9006 if (lck == NULL) {
9007 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
9008 "lock for file %s\n", fsp_str_dbg(fsp)));
9009 close_file(req, fsp, NORMAL_CLOSE);
9010 return NT_STATUS_INVALID_PARAMETER;
9013 other_nonposix_opens = has_other_nonposix_opens(lck, fsp);
9014 if (other_nonposix_opens) {
9015 /* Fail with sharing violation. */
9016 TALLOC_FREE(lck);
9017 close_file(req, fsp, NORMAL_CLOSE);
9018 return NT_STATUS_SHARING_VIOLATION;
9022 * Set the delete on close.
9024 status = smb_set_file_disposition_info(conn,
9025 &del,
9027 fsp,
9028 smb_fname);
9030 TALLOC_FREE(lck);
9032 if (!NT_STATUS_IS_OK(status)) {
9033 close_file(req, fsp, NORMAL_CLOSE);
9034 return status;
9036 return close_file(req, fsp, NORMAL_CLOSE);
9039 static NTSTATUS smbd_do_posix_setfilepathinfo(struct connection_struct *conn,
9040 struct smb_request *req,
9041 TALLOC_CTX *mem_ctx,
9042 uint16_t info_level,
9043 struct smb_filename *smb_fname,
9044 files_struct *fsp,
9045 char **ppdata,
9046 int total_data,
9047 int *ret_data_size)
9049 char *pdata = *ppdata;
9050 NTSTATUS status = NT_STATUS_OK;
9051 int data_return_size = 0;
9053 *ret_data_size = 0;
9055 if (!CAN_WRITE(conn)) {
9056 /* Allow POSIX opens. The open path will deny
9057 * any non-readonly opens. */
9058 if (info_level != SMB_POSIX_PATH_OPEN) {
9059 return NT_STATUS_DOS(ERRSRV, ERRaccess);
9063 DBG_DEBUG("file=%s (%s) info_level=%d totdata=%d\n",
9064 smb_fname_str_dbg(smb_fname),
9065 fsp_fnum_dbg(fsp),
9066 info_level,
9067 total_data);
9069 switch (info_level) {
9070 case SMB_SET_FILE_UNIX_BASIC:
9072 status = smb_set_file_unix_basic(conn, req,
9073 pdata,
9074 total_data,
9075 fsp,
9076 smb_fname);
9077 break;
9080 case SMB_SET_FILE_UNIX_INFO2:
9082 status = smb_set_file_unix_info2(conn, req,
9083 pdata,
9084 total_data,
9085 fsp,
9086 smb_fname);
9087 break;
9090 case SMB_SET_FILE_UNIX_LINK:
9092 if (smb_fname == NULL) {
9093 /* We must have a pathname for this. */
9094 return NT_STATUS_INVALID_LEVEL;
9096 status = smb_set_file_unix_link(conn, req, pdata,
9097 total_data, smb_fname);
9098 break;
9101 case SMB_SET_FILE_UNIX_HLINK:
9103 if (smb_fname == NULL) {
9104 /* We must have a pathname for this. */
9105 return NT_STATUS_INVALID_LEVEL;
9107 status = smb_set_file_unix_hlink(conn, req,
9108 pdata, total_data,
9109 smb_fname);
9110 break;
9113 #if defined(HAVE_POSIX_ACLS)
9114 case SMB_SET_POSIX_ACL:
9116 status = smb_set_posix_acl(conn,
9117 req,
9118 pdata,
9119 total_data,
9120 fsp,
9121 smb_fname);
9122 break;
9124 #endif
9126 case SMB_SET_POSIX_LOCK:
9128 if (fsp == NULL) {
9129 return NT_STATUS_INVALID_LEVEL;
9131 status = smb_set_posix_lock(conn, req,
9132 pdata, total_data, fsp);
9133 break;
9136 case SMB_POSIX_PATH_OPEN:
9138 if (smb_fname == NULL) {
9139 /* We must have a pathname for this. */
9140 return NT_STATUS_INVALID_LEVEL;
9143 status = smb_posix_open(conn, req,
9144 ppdata,
9145 total_data,
9146 smb_fname,
9147 &data_return_size);
9148 break;
9151 case SMB_POSIX_PATH_UNLINK:
9153 if (smb_fname == NULL) {
9154 /* We must have a pathname for this. */
9155 return NT_STATUS_INVALID_LEVEL;
9158 status = smb_posix_unlink(conn, req,
9159 pdata,
9160 total_data,
9161 smb_fname);
9162 break;
9165 default:
9166 return NT_STATUS_INVALID_LEVEL;
9169 if (!NT_STATUS_IS_OK(status)) {
9170 return status;
9173 *ret_data_size = data_return_size;
9174 return NT_STATUS_OK;
9177 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
9178 struct smb_request *req,
9179 TALLOC_CTX *mem_ctx,
9180 uint16_t info_level,
9181 files_struct *fsp,
9182 struct smb_filename *smb_fname,
9183 char **ppdata, int total_data,
9184 int *ret_data_size)
9186 char *pdata = *ppdata;
9187 NTSTATUS status = NT_STATUS_OK;
9188 int data_return_size = 0;
9190 if (INFO_LEVEL_IS_UNIX(info_level)) {
9191 if (!lp_unix_extensions()) {
9192 return NT_STATUS_INVALID_LEVEL;
9195 status = smbd_do_posix_setfilepathinfo(conn,
9196 req,
9197 req,
9198 info_level,
9199 smb_fname,
9200 fsp,
9201 ppdata,
9202 total_data,
9203 &data_return_size);
9204 if (!NT_STATUS_IS_OK(status)) {
9205 return status;
9207 *ret_data_size = data_return_size;
9208 return NT_STATUS_OK;
9211 *ret_data_size = 0;
9213 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
9214 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
9215 fsp_fnum_dbg(fsp),
9216 info_level, total_data));
9218 switch (info_level) {
9220 case SMB_INFO_STANDARD:
9222 status = smb_set_info_standard(conn,
9223 pdata,
9224 total_data,
9225 fsp,
9226 smb_fname);
9227 break;
9230 case SMB_INFO_SET_EA:
9232 status = smb_info_set_ea(conn,
9233 pdata,
9234 total_data,
9235 fsp,
9236 smb_fname);
9237 break;
9240 case SMB_SET_FILE_BASIC_INFO:
9241 case SMB_FILE_BASIC_INFORMATION:
9243 status = smb_set_file_basic_info(conn,
9244 pdata,
9245 total_data,
9246 fsp,
9247 smb_fname);
9248 break;
9251 case SMB_FILE_ALLOCATION_INFORMATION:
9252 case SMB_SET_FILE_ALLOCATION_INFO:
9254 status = smb_set_file_allocation_info(conn, req,
9255 pdata,
9256 total_data,
9257 fsp,
9258 smb_fname);
9259 break;
9262 case SMB_FILE_END_OF_FILE_INFORMATION:
9263 case SMB_SET_FILE_END_OF_FILE_INFO:
9266 * XP/Win7 both fail after the createfile with
9267 * SMB_SET_FILE_END_OF_FILE_INFO but not
9268 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
9269 * The level is known here, so pass it down
9270 * appropriately.
9272 bool should_fail =
9273 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
9275 status = smb_set_file_end_of_file_info(conn, req,
9276 pdata,
9277 total_data,
9278 fsp,
9279 smb_fname,
9280 should_fail);
9281 break;
9284 case SMB_FILE_DISPOSITION_INFORMATION:
9285 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
9287 #if 0
9288 /* JRA - We used to just ignore this on a path ?
9289 * Shouldn't this be invalid level on a pathname
9290 * based call ?
9292 if (tran_call != TRANSACT2_SETFILEINFO) {
9293 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
9295 #endif
9296 status = smb_set_file_disposition_info(conn,
9297 pdata,
9298 total_data,
9299 fsp,
9300 smb_fname);
9301 break;
9304 case SMB_FILE_POSITION_INFORMATION:
9306 status = smb_file_position_information(conn,
9307 pdata,
9308 total_data,
9309 fsp);
9310 break;
9313 case SMB_FILE_FULL_EA_INFORMATION:
9315 status = smb_set_file_full_ea_info(conn,
9316 pdata,
9317 total_data,
9318 fsp);
9319 break;
9322 /* From tridge Samba4 :
9323 * MODE_INFORMATION in setfileinfo (I have no
9324 * idea what "mode information" on a file is - it takes a value of 0,
9325 * 2, 4 or 6. What could it be?).
9328 case SMB_FILE_MODE_INFORMATION:
9330 status = smb_file_mode_information(conn,
9331 pdata,
9332 total_data);
9333 break;
9336 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
9337 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
9338 case SMB_FILE_SHORT_NAME_INFORMATION:
9339 return NT_STATUS_NOT_SUPPORTED;
9341 case SMB_FILE_RENAME_INFORMATION:
9343 status = smb_file_rename_information(conn, req,
9344 pdata, total_data,
9345 fsp, smb_fname);
9346 break;
9349 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
9351 /* SMB2 rename information. */
9352 status = smb2_file_rename_information(conn, req,
9353 pdata, total_data,
9354 fsp, smb_fname);
9355 break;
9358 case SMB_FILE_LINK_INFORMATION:
9360 status = smb_file_link_information(conn, req,
9361 pdata, total_data,
9362 fsp, smb_fname);
9363 break;
9366 default:
9367 return NT_STATUS_INVALID_LEVEL;
9370 if (!NT_STATUS_IS_OK(status)) {
9371 return status;
9374 *ret_data_size = data_return_size;
9375 return NT_STATUS_OK;
9378 /****************************************************************************
9379 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9380 ****************************************************************************/
9382 static void call_trans2setfilepathinfo(connection_struct *conn,
9383 struct smb_request *req,
9384 unsigned int tran_call,
9385 char **pparams, int total_params,
9386 char **ppdata, int total_data,
9387 unsigned int max_data_bytes)
9389 char *params = *pparams;
9390 char *pdata = *ppdata;
9391 uint16_t info_level;
9392 struct smb_filename *smb_fname = NULL;
9393 files_struct *fsp = NULL;
9394 NTSTATUS status = NT_STATUS_OK;
9395 int data_return_size = 0;
9397 if (!params) {
9398 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9399 return;
9402 if (tran_call == TRANSACT2_SETFILEINFO) {
9403 if (total_params < 4) {
9404 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9405 return;
9408 fsp = file_fsp(req, SVAL(params,0));
9409 /* Basic check for non-null fsp. */
9410 if (!check_fsp_open(conn, req, fsp)) {
9411 return;
9413 info_level = SVAL(params,2);
9415 smb_fname = fsp->fsp_name;
9417 if (fsp_get_pathref_fd(fsp) == -1) {
9419 * This is actually a SETFILEINFO on a directory
9420 * handle (returned from an NT SMB). NT5.0 seems
9421 * to do this call. JRA.
9423 if (INFO_LEVEL_IS_UNIX(info_level)) {
9424 /* Always do lstat for UNIX calls. */
9425 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9426 DEBUG(3,("call_trans2setfilepathinfo: "
9427 "SMB_VFS_LSTAT of %s failed "
9428 "(%s)\n",
9429 smb_fname_str_dbg(smb_fname),
9430 strerror(errno)));
9431 reply_nterror(req, map_nt_error_from_unix(errno));
9432 return;
9434 } else {
9435 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9436 DEBUG(3,("call_trans2setfilepathinfo: "
9437 "fileinfo of %s failed (%s)\n",
9438 smb_fname_str_dbg(smb_fname),
9439 strerror(errno)));
9440 reply_nterror(req, map_nt_error_from_unix(errno));
9441 return;
9444 } else if (fsp->print_file) {
9446 * Doing a DELETE_ON_CLOSE should cancel a print job.
9448 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9449 uint32_t new_private_options =
9450 fh_get_private_options(fsp->fh);
9451 new_private_options |=
9452 NTCREATEX_FLAG_DELETE_ON_CLOSE;
9453 fh_set_private_options(fsp->fh,
9454 new_private_options);
9456 DEBUG(3,("call_trans2setfilepathinfo: "
9457 "Cancelling print job (%s)\n",
9458 fsp_str_dbg(fsp)));
9460 SSVAL(params,0,0);
9461 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9462 *ppdata, 0,
9463 max_data_bytes);
9464 return;
9465 } else {
9466 reply_nterror(req,
9467 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9468 return;
9470 } else {
9472 * Original code - this is an open file.
9474 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9475 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9476 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9477 strerror(errno)));
9478 reply_nterror(req, map_nt_error_from_unix(errno));
9479 return;
9482 } else {
9483 char *fname = NULL;
9484 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9486 /* set path info */
9487 if (total_params < 7) {
9488 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9489 return;
9492 info_level = SVAL(params,0);
9493 if (req->posix_pathnames) {
9494 srvstr_get_path_posix(req,
9495 params,
9496 req->flags2,
9497 &fname,
9498 &params[6],
9499 total_params - 6,
9500 STR_TERMINATE,
9501 &status);
9502 } else {
9503 srvstr_get_path(req,
9504 params,
9505 req->flags2,
9506 &fname,
9507 &params[6],
9508 total_params - 6,
9509 STR_TERMINATE,
9510 &status);
9512 if (!NT_STATUS_IS_OK(status)) {
9513 reply_nterror(req, status);
9514 return;
9517 status = filename_convert(req, conn,
9518 fname,
9519 ucf_flags,
9521 &smb_fname);
9522 if (!NT_STATUS_IS_OK(status)) {
9523 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9524 reply_botherror(req,
9525 NT_STATUS_PATH_NOT_COVERED,
9526 ERRSRV, ERRbadpath);
9527 return;
9529 reply_nterror(req, status);
9530 return;
9534 * smb_fname->fsp may be NULL if smb_fname points at a symlink
9535 * and we're in POSIX context, so be careful when using fsp
9536 * below, it can still be NULL.
9538 fsp = smb_fname->fsp;
9540 if (INFO_LEVEL_IS_UNIX(info_level)) {
9542 * For CIFS UNIX extensions the target name may not exist.
9545 /* Always do lstat for UNIX calls. */
9546 SMB_VFS_LSTAT(conn, smb_fname);
9548 } else if (!VALID_STAT(smb_fname->st) &&
9549 SMB_VFS_STAT(conn, smb_fname)) {
9550 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9551 "%s failed (%s)\n",
9552 smb_fname_str_dbg(smb_fname),
9553 strerror(errno)));
9554 reply_nterror(req, map_nt_error_from_unix(errno));
9555 return;
9559 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9560 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9561 fsp_fnum_dbg(fsp),
9562 info_level,total_data));
9564 /* Realloc the parameter size */
9565 *pparams = (char *)SMB_REALLOC(*pparams,2);
9566 if (*pparams == NULL) {
9567 reply_nterror(req, NT_STATUS_NO_MEMORY);
9568 return;
9570 params = *pparams;
9572 SSVAL(params,0,0);
9574 status = smbd_do_setfilepathinfo(conn, req, req,
9575 info_level,
9576 fsp,
9577 smb_fname,
9578 ppdata, total_data,
9579 &data_return_size);
9580 if (!NT_STATUS_IS_OK(status)) {
9581 if (open_was_deferred(req->xconn, req->mid)) {
9582 /* We have re-scheduled this call. */
9583 return;
9585 if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
9586 bool ok = defer_smb1_sharing_violation(req);
9587 if (ok) {
9588 return;
9591 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9592 /* We have re-scheduled this call. */
9593 return;
9595 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9596 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9597 ERRSRV, ERRbadpath);
9598 return;
9600 if (info_level == SMB_POSIX_PATH_OPEN) {
9601 reply_openerror(req, status);
9602 return;
9606 * Invalid EA name needs to return 2 param bytes,
9607 * not a zero-length error packet.
9609 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9610 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9611 max_data_bytes);
9612 } else {
9613 reply_nterror(req, status);
9615 return;
9618 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9619 max_data_bytes);
9621 return;
9624 /****************************************************************************
9625 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9626 ****************************************************************************/
9628 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9629 char **pparams, int total_params,
9630 char **ppdata, int total_data,
9631 unsigned int max_data_bytes)
9633 struct files_struct *fsp = NULL;
9634 struct smb_filename *smb_dname = NULL;
9635 char *params = *pparams;
9636 char *pdata = *ppdata;
9637 char *directory = NULL;
9638 NTSTATUS status = NT_STATUS_OK;
9639 struct ea_list *ea_list = NULL;
9640 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9641 TALLOC_CTX *ctx = talloc_tos();
9643 if (!CAN_WRITE(conn)) {
9644 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9645 return;
9648 if (total_params < 5) {
9649 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9650 return;
9653 if (req->posix_pathnames) {
9654 srvstr_get_path_posix(ctx,
9655 params,
9656 req->flags2,
9657 &directory,
9658 &params[4],
9659 total_params - 4,
9660 STR_TERMINATE,
9661 &status);
9662 } else {
9663 srvstr_get_path(ctx,
9664 params,
9665 req->flags2,
9666 &directory,
9667 &params[4],
9668 total_params - 4,
9669 STR_TERMINATE,
9670 &status);
9672 if (!NT_STATUS_IS_OK(status)) {
9673 reply_nterror(req, status);
9674 return;
9677 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9679 status = filename_convert(ctx,
9680 conn,
9681 directory,
9682 ucf_flags,
9684 &smb_dname);
9686 if (!NT_STATUS_IS_OK(status)) {
9687 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9688 reply_botherror(req,
9689 NT_STATUS_PATH_NOT_COVERED,
9690 ERRSRV, ERRbadpath);
9691 return;
9693 reply_nterror(req, status);
9694 return;
9698 * OS/2 workplace shell seems to send SET_EA requests of "null"
9699 * length (4 bytes containing IVAL 4).
9700 * They seem to have no effect. Bug #3212. JRA.
9703 if (total_data && (total_data != 4)) {
9704 /* Any data in this call is an EA list. */
9705 if (total_data < 10) {
9706 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9707 goto out;
9710 if (IVAL(pdata,0) > total_data) {
9711 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9712 IVAL(pdata,0), (unsigned int)total_data));
9713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9714 goto out;
9717 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9718 total_data - 4);
9719 if (!ea_list) {
9720 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9721 goto out;
9724 if (!lp_ea_support(SNUM(conn))) {
9725 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9726 goto out;
9729 /* If total_data == 4 Windows doesn't care what values
9730 * are placed in that field, it just ignores them.
9731 * The System i QNTC IBM SMB client puts bad values here,
9732 * so ignore them. */
9734 status = SMB_VFS_CREATE_FILE(
9735 conn, /* conn */
9736 req, /* req */
9737 smb_dname, /* fname */
9738 MAXIMUM_ALLOWED_ACCESS, /* access_mask */
9739 FILE_SHARE_NONE, /* share_access */
9740 FILE_CREATE, /* create_disposition*/
9741 FILE_DIRECTORY_FILE, /* create_options */
9742 FILE_ATTRIBUTE_DIRECTORY, /* file_attributes */
9743 0, /* oplock_request */
9744 NULL, /* lease */
9745 0, /* allocation_size */
9746 0, /* private_flags */
9747 NULL, /* sd */
9748 NULL, /* ea_list */
9749 &fsp, /* result */
9750 NULL, /* pinfo */
9751 NULL, NULL); /* create context */
9752 if (!NT_STATUS_IS_OK(status)) {
9753 reply_nterror(req, status);
9754 goto out;
9757 /* Try and set any given EA. */
9758 if (ea_list) {
9759 status = set_ea(conn, fsp, ea_list);
9760 if (!NT_STATUS_IS_OK(status)) {
9761 reply_nterror(req, status);
9762 goto out;
9766 /* Realloc the parameter and data sizes */
9767 *pparams = (char *)SMB_REALLOC(*pparams,2);
9768 if(*pparams == NULL) {
9769 reply_nterror(req, NT_STATUS_NO_MEMORY);
9770 goto out;
9772 params = *pparams;
9774 SSVAL(params,0,0);
9776 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9778 out:
9779 if (fsp != NULL) {
9780 close_file(NULL, fsp, NORMAL_CLOSE);
9781 fsp = NULL;
9783 TALLOC_FREE(smb_dname);
9784 return;
9787 /****************************************************************************
9788 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9789 We don't actually do this - we just send a null response.
9790 ****************************************************************************/
9792 static void call_trans2findnotifyfirst(connection_struct *conn,
9793 struct smb_request *req,
9794 char **pparams, int total_params,
9795 char **ppdata, int total_data,
9796 unsigned int max_data_bytes)
9798 char *params = *pparams;
9799 uint16_t info_level;
9801 if (total_params < 6) {
9802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9803 return;
9806 info_level = SVAL(params,4);
9807 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9809 switch (info_level) {
9810 case 1:
9811 case 2:
9812 break;
9813 default:
9814 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9815 return;
9818 /* Realloc the parameter and data sizes */
9819 *pparams = (char *)SMB_REALLOC(*pparams,6);
9820 if (*pparams == NULL) {
9821 reply_nterror(req, NT_STATUS_NO_MEMORY);
9822 return;
9824 params = *pparams;
9826 SSVAL(params,0,fnf_handle);
9827 SSVAL(params,2,0); /* No changes */
9828 SSVAL(params,4,0); /* No EA errors */
9830 fnf_handle++;
9832 if(fnf_handle == 0)
9833 fnf_handle = 257;
9835 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9837 return;
9840 /****************************************************************************
9841 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9842 changes). Currently this does nothing.
9843 ****************************************************************************/
9845 static void call_trans2findnotifynext(connection_struct *conn,
9846 struct smb_request *req,
9847 char **pparams, int total_params,
9848 char **ppdata, int total_data,
9849 unsigned int max_data_bytes)
9851 char *params = *pparams;
9853 DEBUG(3,("call_trans2findnotifynext\n"));
9855 /* Realloc the parameter and data sizes */
9856 *pparams = (char *)SMB_REALLOC(*pparams,4);
9857 if (*pparams == NULL) {
9858 reply_nterror(req, NT_STATUS_NO_MEMORY);
9859 return;
9861 params = *pparams;
9863 SSVAL(params,0,0); /* No changes */
9864 SSVAL(params,2,0); /* No EA errors */
9866 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9868 return;
9871 /****************************************************************************
9872 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9873 ****************************************************************************/
9875 static void call_trans2getdfsreferral(connection_struct *conn,
9876 struct smb_request *req,
9877 char **pparams, int total_params,
9878 char **ppdata, int total_data,
9879 unsigned int max_data_bytes)
9881 char *params = *pparams;
9882 char *pathname = NULL;
9883 int reply_size = 0;
9884 int max_referral_level;
9885 NTSTATUS status = NT_STATUS_OK;
9886 TALLOC_CTX *ctx = talloc_tos();
9888 DEBUG(10,("call_trans2getdfsreferral\n"));
9890 if (total_params < 3) {
9891 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9892 return;
9895 max_referral_level = SVAL(params,0);
9897 if(!lp_host_msdfs()) {
9898 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9899 return;
9902 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9903 total_params - 2, STR_TERMINATE);
9904 if (!pathname) {
9905 reply_nterror(req, NT_STATUS_NOT_FOUND);
9906 return;
9908 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9909 ppdata,&status)) < 0) {
9910 reply_nterror(req, status);
9911 return;
9914 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9915 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9916 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9918 return;
9921 #define LMCAT_SPL 0x53
9922 #define LMFUNC_GETJOBID 0x60
9924 /****************************************************************************
9925 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9926 ****************************************************************************/
9928 static void call_trans2ioctl(connection_struct *conn,
9929 struct smb_request *req,
9930 char **pparams, int total_params,
9931 char **ppdata, int total_data,
9932 unsigned int max_data_bytes)
9934 const struct loadparm_substitution *lp_sub =
9935 loadparm_s3_global_substitution();
9936 char *pdata = *ppdata;
9937 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9938 NTSTATUS status;
9939 size_t len = 0;
9941 /* check for an invalid fid before proceeding */
9943 if (!fsp) {
9944 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9945 return;
9948 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9949 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9950 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9951 if (*ppdata == NULL) {
9952 reply_nterror(req, NT_STATUS_NO_MEMORY);
9953 return;
9955 pdata = *ppdata;
9957 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9958 CAN ACCEPT THIS IN UNICODE. JRA. */
9960 /* Job number */
9961 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9963 status = srvstr_push(pdata, req->flags2, pdata + 2,
9964 lp_netbios_name(), 15,
9965 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9966 if (!NT_STATUS_IS_OK(status)) {
9967 reply_nterror(req, status);
9968 return;
9970 status = srvstr_push(pdata, req->flags2, pdata+18,
9971 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), 13,
9972 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9973 if (!NT_STATUS_IS_OK(status)) {
9974 reply_nterror(req, status);
9975 return;
9977 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9978 max_data_bytes);
9979 return;
9982 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9983 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9986 /****************************************************************************
9987 Reply to a SMBfindclose (stop trans2 directory search).
9988 ****************************************************************************/
9990 void reply_findclose(struct smb_request *req)
9992 int dptr_num;
9993 struct smbd_server_connection *sconn = req->sconn;
9994 files_struct *fsp = NULL;
9996 START_PROFILE(SMBfindclose);
9998 if (req->wct < 1) {
9999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10000 END_PROFILE(SMBfindclose);
10001 return;
10004 dptr_num = SVALS(req->vwv+0, 0);
10006 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
10009 * OS/2 seems to use -1 to indicate "close all directories"
10010 * This has to mean on this specific connection struct.
10012 if (dptr_num == -1) {
10013 dptr_closecnum(req->conn);
10014 } else {
10015 fsp = dptr_fetch_lanman2_fsp(sconn, dptr_num);
10016 dptr_num = -1;
10017 if (fsp != NULL) {
10018 close_file(NULL, fsp, NORMAL_CLOSE);
10019 fsp = NULL;
10023 reply_outbuf(req, 0, 0);
10025 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
10027 END_PROFILE(SMBfindclose);
10028 return;
10031 /****************************************************************************
10032 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
10033 ****************************************************************************/
10035 void reply_findnclose(struct smb_request *req)
10037 int dptr_num;
10039 START_PROFILE(SMBfindnclose);
10041 if (req->wct < 1) {
10042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10043 END_PROFILE(SMBfindnclose);
10044 return;
10047 dptr_num = SVAL(req->vwv+0, 0);
10049 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
10051 /* We never give out valid handles for a
10052 findnotifyfirst - so any dptr_num is ok here.
10053 Just ignore it. */
10055 reply_outbuf(req, 0, 0);
10057 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
10059 END_PROFILE(SMBfindnclose);
10060 return;
10063 static void handle_trans2(connection_struct *conn, struct smb_request *req,
10064 struct trans_state *state)
10066 if (get_Protocol() >= PROTOCOL_NT1) {
10067 req->flags2 |= 0x40; /* IS_LONG_NAME */
10068 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
10071 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
10072 if (state->call != TRANSACT2_QFSINFO &&
10073 state->call != TRANSACT2_SETFSINFO) {
10074 DEBUG(0,("handle_trans2: encryption required "
10075 "with call 0x%x\n",
10076 (unsigned int)state->call));
10077 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10078 return;
10082 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
10084 /* Now we must call the relevant TRANS2 function */
10085 switch(state->call) {
10086 case TRANSACT2_OPEN:
10088 START_PROFILE(Trans2_open);
10089 call_trans2open(conn, req,
10090 &state->param, state->total_param,
10091 &state->data, state->total_data,
10092 state->max_data_return);
10093 END_PROFILE(Trans2_open);
10094 break;
10097 case TRANSACT2_FINDFIRST:
10099 START_PROFILE(Trans2_findfirst);
10100 call_trans2findfirst(conn, req,
10101 &state->param, state->total_param,
10102 &state->data, state->total_data,
10103 state->max_data_return);
10104 END_PROFILE(Trans2_findfirst);
10105 break;
10108 case TRANSACT2_FINDNEXT:
10110 START_PROFILE(Trans2_findnext);
10111 call_trans2findnext(conn, req,
10112 &state->param, state->total_param,
10113 &state->data, state->total_data,
10114 state->max_data_return);
10115 END_PROFILE(Trans2_findnext);
10116 break;
10119 case TRANSACT2_QFSINFO:
10121 START_PROFILE(Trans2_qfsinfo);
10122 call_trans2qfsinfo(conn, req,
10123 &state->param, state->total_param,
10124 &state->data, state->total_data,
10125 state->max_data_return);
10126 END_PROFILE(Trans2_qfsinfo);
10127 break;
10130 case TRANSACT2_SETFSINFO:
10132 START_PROFILE(Trans2_setfsinfo);
10133 call_trans2setfsinfo(conn, req,
10134 &state->param, state->total_param,
10135 &state->data, state->total_data,
10136 state->max_data_return);
10137 END_PROFILE(Trans2_setfsinfo);
10138 break;
10141 case TRANSACT2_QPATHINFO:
10142 case TRANSACT2_QFILEINFO:
10144 START_PROFILE(Trans2_qpathinfo);
10145 call_trans2qfilepathinfo(conn, req, state->call,
10146 &state->param, state->total_param,
10147 &state->data, state->total_data,
10148 state->max_data_return);
10149 END_PROFILE(Trans2_qpathinfo);
10150 break;
10153 case TRANSACT2_SETPATHINFO:
10154 case TRANSACT2_SETFILEINFO:
10156 START_PROFILE(Trans2_setpathinfo);
10157 call_trans2setfilepathinfo(conn, req, state->call,
10158 &state->param, state->total_param,
10159 &state->data, state->total_data,
10160 state->max_data_return);
10161 END_PROFILE(Trans2_setpathinfo);
10162 break;
10165 case TRANSACT2_FINDNOTIFYFIRST:
10167 START_PROFILE(Trans2_findnotifyfirst);
10168 call_trans2findnotifyfirst(conn, req,
10169 &state->param, state->total_param,
10170 &state->data, state->total_data,
10171 state->max_data_return);
10172 END_PROFILE(Trans2_findnotifyfirst);
10173 break;
10176 case TRANSACT2_FINDNOTIFYNEXT:
10178 START_PROFILE(Trans2_findnotifynext);
10179 call_trans2findnotifynext(conn, req,
10180 &state->param, state->total_param,
10181 &state->data, state->total_data,
10182 state->max_data_return);
10183 END_PROFILE(Trans2_findnotifynext);
10184 break;
10187 case TRANSACT2_MKDIR:
10189 START_PROFILE(Trans2_mkdir);
10190 call_trans2mkdir(conn, req,
10191 &state->param, state->total_param,
10192 &state->data, state->total_data,
10193 state->max_data_return);
10194 END_PROFILE(Trans2_mkdir);
10195 break;
10198 case TRANSACT2_GET_DFS_REFERRAL:
10200 START_PROFILE(Trans2_get_dfs_referral);
10201 call_trans2getdfsreferral(conn, req,
10202 &state->param, state->total_param,
10203 &state->data, state->total_data,
10204 state->max_data_return);
10205 END_PROFILE(Trans2_get_dfs_referral);
10206 break;
10209 case TRANSACT2_IOCTL:
10211 START_PROFILE(Trans2_ioctl);
10212 call_trans2ioctl(conn, req,
10213 &state->param, state->total_param,
10214 &state->data, state->total_data,
10215 state->max_data_return);
10216 END_PROFILE(Trans2_ioctl);
10217 break;
10220 default:
10221 /* Error in request */
10222 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
10223 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
10227 /****************************************************************************
10228 Reply to a SMBtrans2.
10229 ****************************************************************************/
10231 void reply_trans2(struct smb_request *req)
10233 connection_struct *conn = req->conn;
10234 unsigned int dsoff;
10235 unsigned int dscnt;
10236 unsigned int psoff;
10237 unsigned int pscnt;
10238 unsigned int tran_call;
10239 struct trans_state *state;
10240 NTSTATUS result;
10242 START_PROFILE(SMBtrans2);
10244 if (req->wct < 14) {
10245 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10246 END_PROFILE(SMBtrans2);
10247 return;
10250 dsoff = SVAL(req->vwv+12, 0);
10251 dscnt = SVAL(req->vwv+11, 0);
10252 psoff = SVAL(req->vwv+10, 0);
10253 pscnt = SVAL(req->vwv+9, 0);
10254 tran_call = SVAL(req->vwv+14, 0);
10256 result = allow_new_trans(conn->pending_trans, req->mid);
10257 if (!NT_STATUS_IS_OK(result)) {
10258 DEBUG(2, ("Got invalid trans2 request: %s\n",
10259 nt_errstr(result)));
10260 reply_nterror(req, result);
10261 END_PROFILE(SMBtrans2);
10262 return;
10265 if (IS_IPC(conn)) {
10266 switch (tran_call) {
10267 /* List the allowed trans2 calls on IPC$ */
10268 case TRANSACT2_OPEN:
10269 case TRANSACT2_GET_DFS_REFERRAL:
10270 case TRANSACT2_QFILEINFO:
10271 case TRANSACT2_QFSINFO:
10272 case TRANSACT2_SETFSINFO:
10273 break;
10274 default:
10275 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
10276 END_PROFILE(SMBtrans2);
10277 return;
10281 if ((state = talloc(conn, struct trans_state)) == NULL) {
10282 DEBUG(0, ("talloc failed\n"));
10283 reply_nterror(req, NT_STATUS_NO_MEMORY);
10284 END_PROFILE(SMBtrans2);
10285 return;
10288 state->cmd = SMBtrans2;
10290 state->mid = req->mid;
10291 state->vuid = req->vuid;
10292 state->setup_count = SVAL(req->vwv+13, 0);
10293 state->setup = NULL;
10294 state->total_param = SVAL(req->vwv+0, 0);
10295 state->param = NULL;
10296 state->total_data = SVAL(req->vwv+1, 0);
10297 state->data = NULL;
10298 state->max_param_return = SVAL(req->vwv+2, 0);
10299 state->max_data_return = SVAL(req->vwv+3, 0);
10300 state->max_setup_return = SVAL(req->vwv+4, 0);
10301 state->close_on_completion = BITSETW(req->vwv+5, 0);
10302 state->one_way = BITSETW(req->vwv+5, 1);
10304 state->call = tran_call;
10306 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
10307 is so as a sanity check */
10308 if (state->setup_count != 1) {
10310 * Need to have rc=0 for ioctl to get job id for OS/2.
10311 * Network printing will fail if function is not successful.
10312 * Similar function in reply.c will be used if protocol
10313 * is LANMAN1.0 instead of LM1.2X002.
10314 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
10315 * outbuf doesn't have to be set(only job id is used).
10317 if ( (state->setup_count == 4)
10318 && (tran_call == TRANSACT2_IOCTL)
10319 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
10320 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
10321 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
10322 } else {
10323 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
10324 DEBUG(2,("Transaction is %d\n",tran_call));
10325 TALLOC_FREE(state);
10326 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10327 END_PROFILE(SMBtrans2);
10328 return;
10332 if ((dscnt > state->total_data) || (pscnt > state->total_param))
10333 goto bad_param;
10335 if (state->total_data) {
10337 if (trans_oob(state->total_data, 0, dscnt)
10338 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
10339 goto bad_param;
10342 /* Can't use talloc here, the core routines do realloc on the
10343 * params and data. */
10344 state->data = (char *)SMB_MALLOC(state->total_data);
10345 if (state->data == NULL) {
10346 DEBUG(0,("reply_trans2: data malloc fail for %u "
10347 "bytes !\n", (unsigned int)state->total_data));
10348 TALLOC_FREE(state);
10349 reply_nterror(req, NT_STATUS_NO_MEMORY);
10350 END_PROFILE(SMBtrans2);
10351 return;
10354 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
10357 if (state->total_param) {
10359 if (trans_oob(state->total_param, 0, pscnt)
10360 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
10361 goto bad_param;
10364 /* Can't use talloc here, the core routines do realloc on the
10365 * params and data. */
10366 state->param = (char *)SMB_MALLOC(state->total_param);
10367 if (state->param == NULL) {
10368 DEBUG(0,("reply_trans: param malloc fail for %u "
10369 "bytes !\n", (unsigned int)state->total_param));
10370 SAFE_FREE(state->data);
10371 TALLOC_FREE(state);
10372 reply_nterror(req, NT_STATUS_NO_MEMORY);
10373 END_PROFILE(SMBtrans2);
10374 return;
10377 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10380 state->received_data = dscnt;
10381 state->received_param = pscnt;
10383 if ((state->received_param == state->total_param) &&
10384 (state->received_data == state->total_data)) {
10386 handle_trans2(conn, req, state);
10388 SAFE_FREE(state->data);
10389 SAFE_FREE(state->param);
10390 TALLOC_FREE(state);
10391 END_PROFILE(SMBtrans2);
10392 return;
10395 DLIST_ADD(conn->pending_trans, state);
10397 /* We need to send an interim response then receive the rest
10398 of the parameter/data bytes */
10399 reply_outbuf(req, 0, 0);
10400 show_msg((char *)req->outbuf);
10401 END_PROFILE(SMBtrans2);
10402 return;
10404 bad_param:
10406 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10407 SAFE_FREE(state->data);
10408 SAFE_FREE(state->param);
10409 TALLOC_FREE(state);
10410 END_PROFILE(SMBtrans2);
10411 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10415 /****************************************************************************
10416 Reply to a SMBtranss2
10417 ****************************************************************************/
10419 void reply_transs2(struct smb_request *req)
10421 connection_struct *conn = req->conn;
10422 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10423 struct trans_state *state;
10425 START_PROFILE(SMBtranss2);
10427 show_msg((const char *)req->inbuf);
10429 /* Windows clients expect all replies to
10430 a transact secondary (SMBtranss2 0x33)
10431 to have a command code of transact
10432 (SMBtrans2 0x32). See bug #8989
10433 and also [MS-CIFS] section 2.2.4.47.2
10434 for details.
10436 req->cmd = SMBtrans2;
10438 if (req->wct < 8) {
10439 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10440 END_PROFILE(SMBtranss2);
10441 return;
10444 for (state = conn->pending_trans; state != NULL;
10445 state = state->next) {
10446 if (state->mid == req->mid) {
10447 break;
10451 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10452 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10453 END_PROFILE(SMBtranss2);
10454 return;
10457 /* Revise state->total_param and state->total_data in case they have
10458 changed downwards */
10460 if (SVAL(req->vwv+0, 0) < state->total_param)
10461 state->total_param = SVAL(req->vwv+0, 0);
10462 if (SVAL(req->vwv+1, 0) < state->total_data)
10463 state->total_data = SVAL(req->vwv+1, 0);
10465 pcnt = SVAL(req->vwv+2, 0);
10466 poff = SVAL(req->vwv+3, 0);
10467 pdisp = SVAL(req->vwv+4, 0);
10469 dcnt = SVAL(req->vwv+5, 0);
10470 doff = SVAL(req->vwv+6, 0);
10471 ddisp = SVAL(req->vwv+7, 0);
10473 state->received_param += pcnt;
10474 state->received_data += dcnt;
10476 if ((state->received_data > state->total_data) ||
10477 (state->received_param > state->total_param))
10478 goto bad_param;
10480 if (pcnt) {
10481 if (trans_oob(state->total_param, pdisp, pcnt)
10482 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10483 goto bad_param;
10485 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10488 if (dcnt) {
10489 if (trans_oob(state->total_data, ddisp, dcnt)
10490 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10491 goto bad_param;
10493 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10496 if ((state->received_param < state->total_param) ||
10497 (state->received_data < state->total_data)) {
10498 END_PROFILE(SMBtranss2);
10499 return;
10502 handle_trans2(conn, req, state);
10504 DLIST_REMOVE(conn->pending_trans, state);
10505 SAFE_FREE(state->data);
10506 SAFE_FREE(state->param);
10507 TALLOC_FREE(state);
10509 END_PROFILE(SMBtranss2);
10510 return;
10512 bad_param:
10514 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10515 DLIST_REMOVE(conn->pending_trans, state);
10516 SAFE_FREE(state->data);
10517 SAFE_FREE(state->param);
10518 TALLOC_FREE(state);
10519 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10520 END_PROFILE(SMBtranss2);
10521 return;