prefork tests: re-enable restart tests for MIT Kerberos
[Samba.git] / source3 / smbd / trans2.c
blob5b99240e9e88e890acaf4b4ade4aec28f6139bbf
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 "version.h"
30 #include "smbd/smbd.h"
31 #include "smbd/globals.h"
32 #include "../libcli/auth/libcli_auth.h"
33 #include "../librpc/gen_ndr/xattr.h"
34 #include "../librpc/gen_ndr/ndr_security.h"
35 #include "libcli/security/security.h"
36 #include "trans2.h"
37 #include "auth.h"
38 #include "smbprofile.h"
39 #include "rpc_server/srv_pipe_hnd.h"
40 #include "printing.h"
41 #include "lib/util_ea.h"
42 #include "lib/readdir_attr.h"
43 #include "messages.h"
44 #include "smb1_utils.h"
46 #define DIR_ENTRY_SAFETY_MARGIN 4096
48 static char *store_file_unix_basic(connection_struct *conn,
49 char *pdata,
50 files_struct *fsp,
51 const SMB_STRUCT_STAT *psbuf);
53 static char *store_file_unix_basic_info2(connection_struct *conn,
54 char *pdata,
55 files_struct *fsp,
56 const SMB_STRUCT_STAT *psbuf);
58 /****************************************************************************
59 Check if an open file handle or smb_fname is a symlink.
60 ****************************************************************************/
62 static NTSTATUS refuse_symlink(connection_struct *conn,
63 const files_struct *fsp,
64 const struct smb_filename *smb_fname)
66 SMB_STRUCT_STAT sbuf;
67 const SMB_STRUCT_STAT *pst = NULL;
69 if (fsp) {
70 pst = &fsp->fsp_name->st;
71 } else {
72 pst = &smb_fname->st;
75 if (!VALID_STAT(*pst)) {
76 int ret = vfs_stat_smb_basename(conn,
77 smb_fname,
78 &sbuf);
79 if (ret == -1 && errno != ENOENT) {
80 return map_nt_error_from_unix(errno);
81 } else if (ret == -1) {
82 /* it's not a symlink.. */
83 return NT_STATUS_OK;
85 pst = &sbuf;
88 if (S_ISLNK(pst->st_ex_mode)) {
89 return NT_STATUS_ACCESS_DENIED;
91 return NT_STATUS_OK;
94 NTSTATUS check_access_fsp(const struct files_struct *fsp,
95 uint32_t access_mask)
97 if (!(fsp->access_mask & access_mask)) {
98 return NT_STATUS_ACCESS_DENIED;
100 return NT_STATUS_OK;
103 #if defined(HAVE_POSIX_ACLS)
104 /****************************************************************************
105 Utility function to open a fsp for a POSIX handle operation.
106 ****************************************************************************/
108 static NTSTATUS get_posix_fsp(connection_struct *conn,
109 struct smb_request *req,
110 const struct smb_filename *smb_fname,
111 uint32_t access_mask,
112 files_struct **ret_fsp)
114 NTSTATUS status;
115 struct smb_filename *smb_fname_tmp = NULL;
116 uint32_t create_disposition = FILE_OPEN;
117 uint32_t share_access = FILE_SHARE_READ|
118 FILE_SHARE_WRITE|
119 FILE_SHARE_DELETE;
121 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing files,
122 * but set reasonable defaults.
124 uint32_t file_attributes = 0664|FILE_FLAG_POSIX_SEMANTICS;
125 uint32_t oplock = NO_OPLOCK;
126 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
128 /* File or directory must exist. */
129 if (!VALID_STAT(smb_fname->st)) {
130 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
132 /* Cannot be a symlink. */
133 if (S_ISLNK(smb_fname->st.st_ex_mode)) {
134 return NT_STATUS_ACCESS_DENIED;
136 /* Set options correctly for directory open. */
137 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
139 * Only FILE_FLAG_POSIX_SEMANTICS matters on existing
140 * directories, but set reasonable defaults.
142 file_attributes = 0775|FILE_FLAG_POSIX_SEMANTICS;
143 create_options = FILE_DIRECTORY_FILE;
146 /* Createfile uses a non-const smb_fname. */
147 smb_fname_tmp = cp_smb_filename(talloc_tos(),
148 smb_fname);
149 if (smb_fname_tmp == NULL) {
150 return NT_STATUS_NO_MEMORY;
153 status = SMB_VFS_CREATE_FILE(
154 conn, /* conn */
155 req, /* req */
156 0, /* root_dir_fid */
157 smb_fname_tmp, /* fname */
158 access_mask, /* access_mask */
159 share_access, /* share_access */
160 create_disposition,/* create_disposition*/
161 create_options, /* create_options */
162 file_attributes,/* file_attributes */
163 oplock, /* oplock_request */
164 NULL, /* lease */
165 0, /* allocation_size */
166 0, /* private_flags */
167 NULL, /* sd */
168 NULL, /* ea_list */
169 ret_fsp, /* result */
170 NULL, /* pinfo */
171 NULL, /* in_context */
172 NULL); /* out_context */
174 TALLOC_FREE(smb_fname_tmp);
175 return status;
177 #endif
179 /********************************************************************
180 The canonical "check access" based on object handle or path function.
181 ********************************************************************/
183 static NTSTATUS check_access(connection_struct *conn,
184 files_struct *fsp,
185 const struct smb_filename *smb_fname,
186 uint32_t access_mask)
188 NTSTATUS status;
190 if (fsp) {
191 status = check_access_fsp(fsp, access_mask);
192 } else {
193 status = smbd_check_access_rights(conn, smb_fname,
194 false, access_mask);
197 return status;
200 /********************************************************************
201 Roundup a value to the nearest allocation roundup size boundary.
202 Only do this for Windows clients.
203 ********************************************************************/
205 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
207 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
209 /* Only roundup for Windows clients. */
210 enum remote_arch_types ra_type = get_remote_arch();
211 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
212 val = SMB_ROUNDUP(val,rval);
214 return val;
217 /****************************************************************************
218 Utility functions for dealing with extended attributes.
219 ****************************************************************************/
221 /****************************************************************************
222 Refuse to allow clients to overwrite our private xattrs.
223 ****************************************************************************/
225 bool samba_private_attr_name(const char *unix_ea_name)
227 static const char * const prohibited_ea_names[] = {
228 SAMBA_POSIX_INHERITANCE_EA_NAME,
229 SAMBA_XATTR_DOS_ATTRIB,
230 SAMBA_XATTR_MARKER,
231 XATTR_NTACL_NAME,
232 NULL
235 int i;
237 for (i = 0; prohibited_ea_names[i]; i++) {
238 if (strequal( prohibited_ea_names[i], unix_ea_name))
239 return true;
241 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
242 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
243 return true;
245 return false;
248 /****************************************************************************
249 Get one EA value. Fill in a struct ea_struct.
250 ****************************************************************************/
252 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
253 connection_struct *conn,
254 files_struct *fsp,
255 const struct smb_filename *smb_fname,
256 const char *ea_name,
257 struct ea_struct *pea)
259 /* Get the value of this xattr. Max size is 64k. */
260 size_t attr_size = 256;
261 char *val = NULL;
262 ssize_t sizeret;
264 again:
266 val = talloc_realloc(mem_ctx, val, char, attr_size);
267 if (!val) {
268 return NT_STATUS_NO_MEMORY;
271 if (fsp && fsp->fh->fd != -1) {
272 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
273 } else {
274 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
275 ea_name, val, attr_size);
278 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
279 attr_size = 65536;
280 goto again;
283 if (sizeret == -1) {
284 return map_nt_error_from_unix(errno);
287 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
288 dump_data(10, (uint8_t *)val, sizeret);
290 pea->flags = 0;
291 if (strnequal(ea_name, "user.", 5)) {
292 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
293 } else {
294 pea->name = talloc_strdup(mem_ctx, ea_name);
296 if (pea->name == NULL) {
297 TALLOC_FREE(val);
298 return NT_STATUS_NO_MEMORY;
300 pea->value.data = (unsigned char *)val;
301 pea->value.length = (size_t)sizeret;
302 return NT_STATUS_OK;
305 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
306 connection_struct *conn,
307 files_struct *fsp,
308 const struct smb_filename *smb_fname,
309 char ***pnames,
310 size_t *pnum_names)
312 char smallbuf[1024];
313 /* Get a list of all xattrs. Max namesize is 64k. */
314 size_t ea_namelist_size = 1024;
315 char *ea_namelist = smallbuf;
316 char *to_free = NULL;
318 char *p;
319 char **names;
320 size_t num_names;
321 ssize_t sizeret = -1;
322 NTSTATUS status;
324 if (pnames) {
325 *pnames = NULL;
327 *pnum_names = 0;
329 status = refuse_symlink(conn, fsp, smb_fname);
330 if (!NT_STATUS_IS_OK(status)) {
332 * Just return no EA's on a symlink.
334 return NT_STATUS_OK;
337 if (fsp && fsp->fh->fd != -1) {
338 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
339 ea_namelist_size);
340 } else {
341 sizeret = SMB_VFS_LISTXATTR(conn,
342 smb_fname,
343 ea_namelist,
344 ea_namelist_size);
347 if ((sizeret == -1) && (errno == ERANGE)) {
348 ea_namelist_size = 65536;
349 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
350 if (ea_namelist == NULL) {
351 return NT_STATUS_NO_MEMORY;
353 to_free = ea_namelist;
355 if (fsp && fsp->fh->fd != -1) {
356 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
357 ea_namelist_size);
358 } else {
359 sizeret = SMB_VFS_LISTXATTR(conn,
360 smb_fname,
361 ea_namelist,
362 ea_namelist_size);
366 if (sizeret == -1) {
367 status = map_nt_error_from_unix(errno);
368 TALLOC_FREE(to_free);
369 return status;
372 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
374 if (sizeret == 0) {
375 TALLOC_FREE(to_free);
376 return NT_STATUS_OK;
380 * Ensure the result is 0-terminated
383 if (ea_namelist[sizeret-1] != '\0') {
384 TALLOC_FREE(to_free);
385 return NT_STATUS_INTERNAL_ERROR;
389 * count the names
391 num_names = 0;
393 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
394 num_names += 1;
397 *pnum_names = num_names;
399 if (pnames == NULL) {
400 TALLOC_FREE(to_free);
401 return NT_STATUS_OK;
404 names = talloc_array(mem_ctx, char *, num_names);
405 if (names == NULL) {
406 DEBUG(0, ("talloc failed\n"));
407 TALLOC_FREE(to_free);
408 return NT_STATUS_NO_MEMORY;
411 if (ea_namelist == smallbuf) {
412 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
413 if (ea_namelist == NULL) {
414 TALLOC_FREE(names);
415 return NT_STATUS_NO_MEMORY;
417 } else {
418 talloc_steal(names, ea_namelist);
420 ea_namelist = talloc_realloc(names, ea_namelist, char,
421 sizeret);
422 if (ea_namelist == NULL) {
423 TALLOC_FREE(names);
424 return NT_STATUS_NO_MEMORY;
428 num_names = 0;
430 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
431 names[num_names++] = p;
434 *pnames = names;
436 return NT_STATUS_OK;
439 /****************************************************************************
440 Return a linked list of the total EA's. Plus the total size
441 ****************************************************************************/
443 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
444 connection_struct *conn,
445 files_struct *fsp,
446 const struct smb_filename *smb_fname,
447 size_t *pea_total_len,
448 struct ea_list **ea_list)
450 /* Get a list of all xattrs. Max namesize is 64k. */
451 size_t i, num_names;
452 char **names;
453 struct ea_list *ea_list_head = NULL;
454 bool posix_pathnames = false;
455 NTSTATUS status;
457 *pea_total_len = 0;
458 *ea_list = NULL;
460 if (!lp_ea_support(SNUM(conn))) {
461 return NT_STATUS_OK;
464 if (fsp) {
465 posix_pathnames =
466 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
467 } else {
468 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
471 status = get_ea_names_from_file(talloc_tos(),
472 conn,
473 fsp,
474 smb_fname,
475 &names,
476 &num_names);
478 if (!NT_STATUS_IS_OK(status)) {
479 return status;
482 if (num_names == 0) {
483 return NT_STATUS_OK;
486 for (i=0; i<num_names; i++) {
487 struct ea_list *listp;
488 fstring dos_ea_name;
490 if (strnequal(names[i], "system.", 7)
491 || samba_private_attr_name(names[i]))
492 continue;
495 * Filter out any underlying POSIX EA names
496 * that a Windows client can't handle.
498 if (!posix_pathnames &&
499 is_invalid_windows_ea_name(names[i])) {
500 continue;
503 listp = talloc(mem_ctx, struct ea_list);
504 if (listp == NULL) {
505 return NT_STATUS_NO_MEMORY;
508 status = get_ea_value(listp,
509 conn,
510 fsp,
511 smb_fname,
512 names[i],
513 &listp->ea);
515 if (!NT_STATUS_IS_OK(status)) {
516 TALLOC_FREE(listp);
517 return status;
520 if (listp->ea.value.length == 0) {
522 * We can never return a zero length EA.
523 * Windows reports the EA's as corrupted.
525 TALLOC_FREE(listp);
526 continue;
529 push_ascii_fstring(dos_ea_name, listp->ea.name);
531 *pea_total_len +=
532 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
534 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
535 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
536 (unsigned int)listp->ea.value.length));
538 DLIST_ADD_END(ea_list_head, listp);
542 /* Add on 4 for total length. */
543 if (*pea_total_len) {
544 *pea_total_len += 4;
547 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
548 (unsigned int)*pea_total_len));
550 *ea_list = ea_list_head;
551 return NT_STATUS_OK;
554 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
555 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
557 *pea_total_len = 0;
558 *ea_list = NULL;
560 if (!lp_ea_support(SNUM(conn))) {
561 return NT_STATUS_OK;
564 if (is_ntfs_stream_smb_fname(smb_fname)) {
565 return NT_STATUS_INVALID_PARAMETER;
568 return get_ea_list_from_file_path(mem_ctx,
569 conn,
570 fsp,
571 smb_fname,
572 pea_total_len,
573 ea_list);
576 /****************************************************************************
577 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
578 that was filled.
579 ****************************************************************************/
581 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
582 connection_struct *conn, struct ea_list *ea_list)
584 unsigned int ret_data_size = 4;
585 char *p = pdata;
587 SMB_ASSERT(total_data_size >= 4);
589 if (!lp_ea_support(SNUM(conn))) {
590 SIVAL(pdata,4,0);
591 return 4;
594 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
595 size_t dos_namelen;
596 fstring dos_ea_name;
597 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
598 dos_namelen = strlen(dos_ea_name);
599 if (dos_namelen > 255 || dos_namelen == 0) {
600 break;
602 if (ea_list->ea.value.length > 65535) {
603 break;
605 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
606 break;
609 /* We know we have room. */
610 SCVAL(p,0,ea_list->ea.flags);
611 SCVAL(p,1,dos_namelen);
612 SSVAL(p,2,ea_list->ea.value.length);
613 strlcpy(p+4, dos_ea_name, dos_namelen+1);
614 if (ea_list->ea.value.length > 0) {
615 memcpy(p + 4 + dos_namelen + 1,
616 ea_list->ea.value.data,
617 ea_list->ea.value.length);
620 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
621 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
624 ret_data_size = PTR_DIFF(p, pdata);
625 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
626 SIVAL(pdata,0,ret_data_size);
627 return ret_data_size;
630 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
631 char *pdata,
632 unsigned int total_data_size,
633 unsigned int *ret_data_size,
634 connection_struct *conn,
635 struct ea_list *ea_list)
637 uint8_t *p = (uint8_t *)pdata;
638 uint8_t *last_start = NULL;
639 bool do_store_data = (pdata != NULL);
641 *ret_data_size = 0;
643 if (!lp_ea_support(SNUM(conn))) {
644 return NT_STATUS_NO_EAS_ON_FILE;
647 for (; ea_list; ea_list = ea_list->next) {
648 size_t dos_namelen;
649 fstring dos_ea_name;
650 size_t this_size;
651 size_t pad = 0;
653 if (last_start != NULL && do_store_data) {
654 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
656 last_start = p;
658 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
659 dos_namelen = strlen(dos_ea_name);
660 if (dos_namelen > 255 || dos_namelen == 0) {
661 return NT_STATUS_INTERNAL_ERROR;
663 if (ea_list->ea.value.length > 65535) {
664 return NT_STATUS_INTERNAL_ERROR;
667 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
669 if (ea_list->next) {
670 pad = (4 - (this_size % 4)) % 4;
671 this_size += pad;
674 if (do_store_data) {
675 if (this_size > total_data_size) {
676 return NT_STATUS_INFO_LENGTH_MISMATCH;
679 /* We know we have room. */
680 SIVAL(p, 0x00, 0); /* next offset */
681 SCVAL(p, 0x04, ea_list->ea.flags);
682 SCVAL(p, 0x05, dos_namelen);
683 SSVAL(p, 0x06, ea_list->ea.value.length);
684 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
685 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
686 if (pad) {
687 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
688 '\0',
689 pad);
691 total_data_size -= this_size;
694 p += this_size;
697 *ret_data_size = PTR_DIFF(p, pdata);
698 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
699 return NT_STATUS_OK;
702 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
704 size_t total_ea_len = 0;
705 TALLOC_CTX *mem_ctx;
706 struct ea_list *ea_list = NULL;
708 if (!lp_ea_support(SNUM(conn))) {
709 return 0;
711 mem_ctx = talloc_stackframe();
713 /* If this is a stream fsp, then we need to instead find the
714 * estimated ea len from the main file, not the stream
715 * (streams cannot have EAs), but the estimate isn't just 0 in
716 * this case! */
717 if (is_ntfs_stream_smb_fname(smb_fname)) {
718 fsp = NULL;
720 (void)get_ea_list_from_file_path(mem_ctx,
721 conn,
722 fsp,
723 smb_fname,
724 &total_ea_len,
725 &ea_list);
726 if(conn->sconn->using_smb2) {
727 NTSTATUS status;
728 unsigned int ret_data_size;
730 * We're going to be using fill_ea_chained_buffer() to
731 * marshall EA's - this size is significantly larger
732 * than the SMB1 buffer. Re-calculate the size without
733 * marshalling.
735 status = fill_ea_chained_buffer(mem_ctx,
736 NULL,
738 &ret_data_size,
739 conn,
740 ea_list);
741 if (!NT_STATUS_IS_OK(status)) {
742 ret_data_size = 0;
744 total_ea_len = ret_data_size;
746 TALLOC_FREE(mem_ctx);
747 return total_ea_len;
750 /****************************************************************************
751 Ensure the EA name is case insensitive by matching any existing EA name.
752 ****************************************************************************/
754 static void canonicalize_ea_name(connection_struct *conn,
755 files_struct *fsp,
756 const struct smb_filename *smb_fname,
757 fstring unix_ea_name)
759 size_t total_ea_len;
760 TALLOC_CTX *mem_ctx = talloc_tos();
761 struct ea_list *ea_list;
762 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
763 conn,
764 fsp,
765 smb_fname,
766 &total_ea_len,
767 &ea_list);
768 if (!NT_STATUS_IS_OK(status)) {
769 return;
772 for (; ea_list; ea_list = ea_list->next) {
773 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
774 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
775 &unix_ea_name[5], ea_list->ea.name));
776 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
777 break;
782 /****************************************************************************
783 Set or delete an extended attribute.
784 ****************************************************************************/
786 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
787 const struct smb_filename *smb_fname, struct ea_list *ea_list)
789 NTSTATUS status;
790 bool posix_pathnames = false;
792 if (!lp_ea_support(SNUM(conn))) {
793 return NT_STATUS_EAS_NOT_SUPPORTED;
796 if (fsp) {
797 posix_pathnames =
798 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
799 } else {
800 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
803 status = refuse_symlink(conn, fsp, smb_fname);
804 if (!NT_STATUS_IS_OK(status)) {
805 return status;
808 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
809 if (!NT_STATUS_IS_OK(status)) {
810 return status;
813 /* Setting EAs on streams isn't supported. */
814 if (is_ntfs_stream_smb_fname(smb_fname)) {
815 return NT_STATUS_INVALID_PARAMETER;
819 * Filter out invalid Windows EA names - before
820 * we set *any* of them.
823 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
824 return STATUS_INVALID_EA_NAME;
827 for (;ea_list; ea_list = ea_list->next) {
828 int ret;
829 fstring unix_ea_name;
831 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
832 fstrcat(unix_ea_name, ea_list->ea.name);
834 canonicalize_ea_name(conn,
835 fsp,
836 smb_fname,
837 unix_ea_name);
839 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
841 if (samba_private_attr_name(unix_ea_name)) {
842 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
843 return NT_STATUS_ACCESS_DENIED;
846 if (ea_list->ea.value.length == 0) {
847 /* Remove the attribute. */
848 if (fsp && (fsp->fh->fd != -1)) {
849 DEBUG(10,("set_ea: deleting ea name %s on "
850 "file %s by file descriptor.\n",
851 unix_ea_name, fsp_str_dbg(fsp)));
852 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
853 } else {
854 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
855 unix_ea_name, smb_fname->base_name));
856 ret = SMB_VFS_REMOVEXATTR(conn,
857 smb_fname,
858 unix_ea_name);
860 #ifdef ENOATTR
861 /* Removing a non existent attribute always succeeds. */
862 if (ret == -1 && errno == ENOATTR) {
863 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
864 unix_ea_name));
865 ret = 0;
867 #endif
868 } else {
869 if (fsp && (fsp->fh->fd != -1)) {
870 DEBUG(10,("set_ea: setting ea name %s on file "
871 "%s by file descriptor.\n",
872 unix_ea_name, fsp_str_dbg(fsp)));
873 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
874 ea_list->ea.value.data, ea_list->ea.value.length, 0);
875 } else {
876 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
877 unix_ea_name, smb_fname->base_name));
878 ret = SMB_VFS_SETXATTR(conn,
879 smb_fname,
880 unix_ea_name,
881 ea_list->ea.value.data,
882 ea_list->ea.value.length,
887 if (ret == -1) {
888 #ifdef ENOTSUP
889 if (errno == ENOTSUP) {
890 return NT_STATUS_EAS_NOT_SUPPORTED;
892 #endif
893 return map_nt_error_from_unix(errno);
897 return NT_STATUS_OK;
899 /****************************************************************************
900 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
901 ****************************************************************************/
903 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
905 struct ea_list *ea_list_head = NULL;
906 size_t converted_size, offset = 0;
908 while (offset + 2 < data_size) {
909 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
910 unsigned int namelen = CVAL(pdata,offset);
912 offset++; /* Go past the namelen byte. */
914 /* integer wrap paranioa. */
915 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
916 (offset > data_size) || (namelen > data_size) ||
917 (offset + namelen >= data_size)) {
918 break;
920 /* Ensure the name is null terminated. */
921 if (pdata[offset + namelen] != '\0') {
922 return NULL;
924 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
925 &converted_size)) {
926 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
927 "failed: %s", strerror(errno)));
929 if (!eal->ea.name) {
930 return NULL;
933 offset += (namelen + 1); /* Go past the name + terminating zero. */
934 DLIST_ADD_END(ea_list_head, eal);
935 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
938 return ea_list_head;
941 /****************************************************************************
942 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
943 ****************************************************************************/
945 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
947 struct ea_list *ea_list_head = NULL;
948 size_t offset = 0;
949 size_t bytes_used = 0;
951 while (offset < data_size) {
952 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
954 if (!eal) {
955 return NULL;
958 DLIST_ADD_END(ea_list_head, eal);
959 offset += bytes_used;
962 return ea_list_head;
965 /****************************************************************************
966 Count the total EA size needed.
967 ****************************************************************************/
969 static size_t ea_list_size(struct ea_list *ealist)
971 fstring dos_ea_name;
972 struct ea_list *listp;
973 size_t ret = 0;
975 for (listp = ealist; listp; listp = listp->next) {
976 push_ascii_fstring(dos_ea_name, listp->ea.name);
977 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
979 /* Add on 4 for total length. */
980 if (ret) {
981 ret += 4;
984 return ret;
987 /****************************************************************************
988 Return a union of EA's from a file list and a list of names.
989 The TALLOC context for the two lists *MUST* be identical as we steal
990 memory from one list to add to another. JRA.
991 ****************************************************************************/
993 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
995 struct ea_list *nlistp, *flistp;
997 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
998 for (flistp = file_list; flistp; flistp = flistp->next) {
999 if (strequal(nlistp->ea.name, flistp->ea.name)) {
1000 break;
1004 if (flistp) {
1005 /* Copy the data from this entry. */
1006 nlistp->ea.flags = flistp->ea.flags;
1007 nlistp->ea.value = flistp->ea.value;
1008 } else {
1009 /* Null entry. */
1010 nlistp->ea.flags = 0;
1011 ZERO_STRUCT(nlistp->ea.value);
1015 *total_ea_len = ea_list_size(name_list);
1016 return name_list;
1019 /****************************************************************************
1020 Send the required number of replies back.
1021 We assume all fields other than the data fields are
1022 set correctly for the type of call.
1023 HACK ! Always assumes smb_setup field is zero.
1024 ****************************************************************************/
1026 void send_trans2_replies(connection_struct *conn,
1027 struct smb_request *req,
1028 NTSTATUS status,
1029 const char *params,
1030 int paramsize,
1031 const char *pdata,
1032 int datasize,
1033 int max_data_bytes)
1035 /* As we are using a protocol > LANMAN1 then the max_send
1036 variable must have been set in the sessetupX call.
1037 This takes precedence over the max_xmit field in the
1038 global struct. These different max_xmit variables should
1039 be merged as this is now too confusing */
1041 int data_to_send = datasize;
1042 int params_to_send = paramsize;
1043 int useable_space;
1044 const char *pp = params;
1045 const char *pd = pdata;
1046 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
1047 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
1048 int data_alignment_offset = 0;
1049 bool overflow = False;
1050 struct smbXsrv_connection *xconn = req->xconn;
1051 int max_send = xconn->smb1.sessions.max_send;
1053 /* Modify the data_to_send and datasize and set the error if
1054 we're trying to send more than max_data_bytes. We still send
1055 the part of the packet(s) that fit. Strange, but needed
1056 for OS/2. */
1058 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1059 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1060 max_data_bytes, datasize ));
1061 datasize = data_to_send = max_data_bytes;
1062 overflow = True;
1065 /* If there genuinely are no parameters or data to send just send the empty packet */
1067 if(params_to_send == 0 && data_to_send == 0) {
1068 reply_outbuf(req, 10, 0);
1069 if (NT_STATUS_V(status)) {
1070 uint8_t eclass;
1071 uint32_t ecode;
1072 ntstatus_to_dos(status, &eclass, &ecode);
1073 error_packet_set((char *)req->outbuf,
1074 eclass, ecode, status,
1075 __LINE__,__FILE__);
1077 show_msg((char *)req->outbuf);
1078 if (!srv_send_smb(xconn,
1079 (char *)req->outbuf,
1080 true, req->seqnum+1,
1081 IS_CONN_ENCRYPTED(conn),
1082 &req->pcd)) {
1083 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1085 TALLOC_FREE(req->outbuf);
1086 return;
1089 /* When sending params and data ensure that both are nicely aligned */
1090 /* Only do this alignment when there is also data to send - else
1091 can cause NT redirector problems. */
1093 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1094 data_alignment_offset = 4 - (params_to_send % 4);
1096 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1097 /* The alignment_offset is to align the param bytes on an even byte
1098 boundary. NT 4.0 Beta needs this to work correctly. */
1100 useable_space = max_send - (smb_size
1101 + 2 * 10 /* wct */
1102 + alignment_offset
1103 + data_alignment_offset);
1105 if (useable_space < 0) {
1106 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1107 "= %d!!!", useable_space));
1108 exit_server_cleanly("send_trans2_replies: Not enough space");
1111 while (params_to_send || data_to_send) {
1112 /* Calculate whether we will totally or partially fill this packet */
1114 total_sent_thistime = params_to_send + data_to_send;
1116 /* We can never send more than useable_space */
1118 * Note that 'useable_space' does not include the alignment offsets,
1119 * but we must include the alignment offsets in the calculation of
1120 * the length of the data we send over the wire, as the alignment offsets
1121 * are sent here. Fix from Marc_Jacobsen@hp.com.
1124 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1126 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1127 + data_alignment_offset);
1129 /* Set total params and data to be sent */
1130 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1131 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1133 /* Calculate how many parameters and data we can fit into
1134 * this packet. Parameters get precedence
1137 params_sent_thistime = MIN(params_to_send,useable_space);
1138 data_sent_thistime = useable_space - params_sent_thistime;
1139 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1141 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1143 /* smb_proff is the offset from the start of the SMB header to the
1144 parameter bytes, however the first 4 bytes of outbuf are
1145 the Netbios over TCP header. Thus use smb_base() to subtract
1146 them from the calculation */
1148 SSVAL(req->outbuf,smb_proff,
1149 ((smb_buf(req->outbuf)+alignment_offset)
1150 - smb_base(req->outbuf)));
1152 if(params_sent_thistime == 0)
1153 SSVAL(req->outbuf,smb_prdisp,0);
1154 else
1155 /* Absolute displacement of param bytes sent in this packet */
1156 SSVAL(req->outbuf,smb_prdisp,pp - params);
1158 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1159 if(data_sent_thistime == 0) {
1160 SSVAL(req->outbuf,smb_droff,0);
1161 SSVAL(req->outbuf,smb_drdisp, 0);
1162 } else {
1163 /* The offset of the data bytes is the offset of the
1164 parameter bytes plus the number of parameters being sent this time */
1165 SSVAL(req->outbuf, smb_droff,
1166 ((smb_buf(req->outbuf)+alignment_offset)
1167 - smb_base(req->outbuf))
1168 + params_sent_thistime + data_alignment_offset);
1169 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1172 /* Initialize the padding for alignment */
1174 if (alignment_offset != 0) {
1175 memset(smb_buf(req->outbuf), 0, alignment_offset);
1178 /* Copy the param bytes into the packet */
1180 if(params_sent_thistime) {
1181 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1182 params_sent_thistime);
1185 /* Copy in the data bytes */
1186 if(data_sent_thistime) {
1187 if (data_alignment_offset != 0) {
1188 memset((smb_buf(req->outbuf)+alignment_offset+
1189 params_sent_thistime), 0,
1190 data_alignment_offset);
1192 memcpy(smb_buf(req->outbuf)+alignment_offset
1193 +params_sent_thistime+data_alignment_offset,
1194 pd,data_sent_thistime);
1197 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1198 params_sent_thistime, data_sent_thistime, useable_space));
1199 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1200 params_to_send, data_to_send, paramsize, datasize));
1202 if (overflow) {
1203 error_packet_set((char *)req->outbuf,
1204 ERRDOS,ERRbufferoverflow,
1205 STATUS_BUFFER_OVERFLOW,
1206 __LINE__,__FILE__);
1207 } else if (NT_STATUS_V(status)) {
1208 uint8_t eclass;
1209 uint32_t ecode;
1210 ntstatus_to_dos(status, &eclass, &ecode);
1211 error_packet_set((char *)req->outbuf,
1212 eclass, ecode, status,
1213 __LINE__,__FILE__);
1216 /* Send the packet */
1217 show_msg((char *)req->outbuf);
1218 if (!srv_send_smb(xconn,
1219 (char *)req->outbuf,
1220 true, req->seqnum+1,
1221 IS_CONN_ENCRYPTED(conn),
1222 &req->pcd))
1223 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1225 TALLOC_FREE(req->outbuf);
1227 pp += params_sent_thistime;
1228 pd += data_sent_thistime;
1230 params_to_send -= params_sent_thistime;
1231 data_to_send -= data_sent_thistime;
1233 /* Sanity check */
1234 if(params_to_send < 0 || data_to_send < 0) {
1235 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1236 params_to_send, data_to_send));
1237 return;
1241 return;
1244 /****************************************************************************
1245 Reply to a TRANSACT2_OPEN.
1246 ****************************************************************************/
1248 static void call_trans2open(connection_struct *conn,
1249 struct smb_request *req,
1250 char **pparams, int total_params,
1251 char **ppdata, int total_data,
1252 unsigned int max_data_bytes)
1254 struct smb_filename *smb_fname = NULL;
1255 char *params = *pparams;
1256 char *pdata = *ppdata;
1257 int deny_mode;
1258 int32_t open_attr;
1259 bool oplock_request;
1260 #if 0
1261 bool return_additional_info;
1262 int16 open_sattr;
1263 time_t open_time;
1264 #endif
1265 int open_ofun;
1266 uint32_t open_size;
1267 char *pname;
1268 char *fname = NULL;
1269 off_t size=0;
1270 int fattr=0,mtime=0;
1271 SMB_INO_T inode = 0;
1272 int smb_action = 0;
1273 files_struct *fsp;
1274 struct ea_list *ea_list = NULL;
1275 uint16_t flags = 0;
1276 NTSTATUS status;
1277 uint32_t access_mask;
1278 uint32_t share_mode;
1279 uint32_t create_disposition;
1280 uint32_t create_options = 0;
1281 uint32_t private_flags = 0;
1282 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1283 TALLOC_CTX *ctx = talloc_tos();
1286 * Ensure we have enough parameters to perform the operation.
1289 if (total_params < 29) {
1290 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1291 goto out;
1294 flags = SVAL(params, 0);
1295 deny_mode = SVAL(params, 2);
1296 open_attr = SVAL(params,6);
1297 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1298 if (oplock_request) {
1299 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1302 #if 0
1303 return_additional_info = BITSETW(params,0);
1304 open_sattr = SVAL(params, 4);
1305 open_time = make_unix_date3(params+8);
1306 #endif
1307 open_ofun = SVAL(params,12);
1308 open_size = IVAL(params,14);
1309 pname = &params[28];
1311 if (IS_IPC(conn)) {
1312 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1313 goto out;
1316 if (req->posix_pathnames) {
1317 srvstr_get_path_posix(ctx,
1318 params,
1319 req->flags2,
1320 &fname,
1321 pname,
1322 total_params - 28,
1323 STR_TERMINATE,
1324 &status);
1325 } else {
1326 srvstr_get_path(ctx,
1327 params,
1328 req->flags2,
1329 &fname,
1330 pname,
1331 total_params - 28,
1332 STR_TERMINATE,
1333 &status);
1335 if (!NT_STATUS_IS_OK(status)) {
1336 reply_nterror(req, status);
1337 goto out;
1340 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1341 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1342 (unsigned int)open_ofun, open_size));
1344 status = filename_convert(ctx,
1345 conn,
1346 fname,
1347 ucf_flags,
1348 NULL,
1349 NULL,
1350 &smb_fname);
1351 if (!NT_STATUS_IS_OK(status)) {
1352 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1353 reply_botherror(req,
1354 NT_STATUS_PATH_NOT_COVERED,
1355 ERRSRV, ERRbadpath);
1356 goto out;
1358 reply_nterror(req, status);
1359 goto out;
1362 if (open_ofun == 0) {
1363 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1364 goto out;
1367 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1368 open_ofun,
1369 &access_mask, &share_mode,
1370 &create_disposition,
1371 &create_options,
1372 &private_flags)) {
1373 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1374 goto out;
1377 /* Any data in this call is an EA list. */
1378 if (total_data && (total_data != 4)) {
1379 if (total_data < 10) {
1380 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1381 goto out;
1384 if (IVAL(pdata,0) > total_data) {
1385 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1386 IVAL(pdata,0), (unsigned int)total_data));
1387 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1388 goto out;
1391 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1392 total_data - 4);
1393 if (!ea_list) {
1394 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1395 goto out;
1398 if (!lp_ea_support(SNUM(conn))) {
1399 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1400 goto out;
1403 if (!req->posix_pathnames &&
1404 ea_list_has_invalid_name(ea_list)) {
1405 int param_len = 30;
1406 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1407 if(*pparams == NULL ) {
1408 reply_nterror(req, NT_STATUS_NO_MEMORY);
1409 goto out;
1411 params = *pparams;
1412 memset(params, '\0', param_len);
1413 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1414 params, param_len, NULL, 0, max_data_bytes);
1415 goto out;
1419 status = SMB_VFS_CREATE_FILE(
1420 conn, /* conn */
1421 req, /* req */
1422 0, /* root_dir_fid */
1423 smb_fname, /* fname */
1424 access_mask, /* access_mask */
1425 share_mode, /* share_access */
1426 create_disposition, /* create_disposition*/
1427 create_options, /* create_options */
1428 open_attr, /* file_attributes */
1429 oplock_request, /* oplock_request */
1430 NULL, /* lease */
1431 open_size, /* allocation_size */
1432 private_flags,
1433 NULL, /* sd */
1434 ea_list, /* ea_list */
1435 &fsp, /* result */
1436 &smb_action, /* psbuf */
1437 NULL, NULL); /* create context */
1439 if (!NT_STATUS_IS_OK(status)) {
1440 if (open_was_deferred(req->xconn, req->mid)) {
1441 /* We have re-scheduled this call. */
1442 goto out;
1445 if (!NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)) {
1446 reply_openerror(req, status);
1447 goto out;
1450 fsp = fcb_or_dos_open(
1451 req,
1452 smb_fname,
1453 access_mask,
1454 share_mode,
1455 create_options,
1456 private_flags);
1457 if (fsp == NULL) {
1458 reply_openerror(req, status);
1459 goto out;
1461 smb_action = FILE_WAS_OPENED;
1464 size = get_file_size_stat(&smb_fname->st);
1465 fattr = dos_mode(conn, smb_fname);
1466 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1467 inode = smb_fname->st.st_ex_ino;
1468 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1469 close_file(req, fsp, ERROR_CLOSE);
1470 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1471 goto out;
1474 /* Realloc the size of parameters and data we will return */
1475 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1476 if(*pparams == NULL ) {
1477 reply_nterror(req, NT_STATUS_NO_MEMORY);
1478 goto out;
1480 params = *pparams;
1482 SSVAL(params,0,fsp->fnum);
1483 SSVAL(params,2,fattr);
1484 srv_put_dos_date2(params,4, mtime);
1485 SIVAL(params,8, (uint32_t)size);
1486 SSVAL(params,12,deny_mode);
1487 SSVAL(params,14,0); /* open_type - file or directory. */
1488 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1490 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1491 smb_action |= EXTENDED_OPLOCK_GRANTED;
1494 SSVAL(params,18,smb_action);
1497 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1499 SIVAL(params,20,inode);
1500 SSVAL(params,24,0); /* Padding. */
1501 if (flags & 8) {
1502 uint32_t ea_size = estimate_ea_size(conn, fsp,
1503 smb_fname);
1504 SIVAL(params, 26, ea_size);
1505 } else {
1506 SIVAL(params, 26, 0);
1509 /* Send the required number of replies */
1510 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1511 out:
1512 TALLOC_FREE(smb_fname);
1515 /*********************************************************
1516 Routine to check if a given string matches exactly.
1517 as a special case a mask of "." does NOT match. That
1518 is required for correct wildcard semantics
1519 Case can be significant or not.
1520 **********************************************************/
1522 static bool exact_match(bool has_wild,
1523 bool case_sensitive,
1524 const char *str,
1525 const char *mask)
1527 if (mask[0] == '.' && mask[1] == 0) {
1528 return false;
1531 if (has_wild) {
1532 return false;
1535 if (case_sensitive) {
1536 return strcmp(str,mask)==0;
1537 } else {
1538 return strcasecmp_m(str,mask) == 0;
1542 /****************************************************************************
1543 Return the filetype for UNIX extensions.
1544 ****************************************************************************/
1546 static uint32_t unix_filetype(mode_t mode)
1548 if(S_ISREG(mode))
1549 return UNIX_TYPE_FILE;
1550 else if(S_ISDIR(mode))
1551 return UNIX_TYPE_DIR;
1552 #ifdef S_ISLNK
1553 else if(S_ISLNK(mode))
1554 return UNIX_TYPE_SYMLINK;
1555 #endif
1556 #ifdef S_ISCHR
1557 else if(S_ISCHR(mode))
1558 return UNIX_TYPE_CHARDEV;
1559 #endif
1560 #ifdef S_ISBLK
1561 else if(S_ISBLK(mode))
1562 return UNIX_TYPE_BLKDEV;
1563 #endif
1564 #ifdef S_ISFIFO
1565 else if(S_ISFIFO(mode))
1566 return UNIX_TYPE_FIFO;
1567 #endif
1568 #ifdef S_ISSOCK
1569 else if(S_ISSOCK(mode))
1570 return UNIX_TYPE_SOCKET;
1571 #endif
1573 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1574 return UNIX_TYPE_UNKNOWN;
1577 /****************************************************************************
1578 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1579 ****************************************************************************/
1581 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1583 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1584 const SMB_STRUCT_STAT *psbuf,
1585 uint32_t perms,
1586 enum perm_type ptype,
1587 mode_t *ret_perms)
1589 mode_t ret = 0;
1591 if (perms == SMB_MODE_NO_CHANGE) {
1592 if (!VALID_STAT(*psbuf)) {
1593 return NT_STATUS_INVALID_PARAMETER;
1594 } else {
1595 *ret_perms = psbuf->st_ex_mode;
1596 return NT_STATUS_OK;
1600 ret = wire_perms_to_unix(perms);
1602 if (ptype == PERM_NEW_FILE) {
1604 * "create mask"/"force create mode" are
1605 * only applied to new files, not existing ones.
1607 ret &= lp_create_mask(SNUM(conn));
1608 /* Add in force bits */
1609 ret |= lp_force_create_mode(SNUM(conn));
1610 } else if (ptype == PERM_NEW_DIR) {
1612 * "directory mask"/"force directory mode" are
1613 * only applied to new directories, not existing ones.
1615 ret &= lp_directory_mask(SNUM(conn));
1616 /* Add in force bits */
1617 ret |= lp_force_directory_mode(SNUM(conn));
1620 *ret_perms = ret;
1621 return NT_STATUS_OK;
1624 /****************************************************************************
1625 Needed to show the msdfs symlinks as directories. Modifies psbuf
1626 to be a directory if it's a msdfs link.
1627 ****************************************************************************/
1629 static bool check_msdfs_link(connection_struct *conn,
1630 struct smb_filename *smb_fname)
1632 int saved_errno = errno;
1633 if(lp_host_msdfs() &&
1634 lp_msdfs_root(SNUM(conn)) &&
1635 is_msdfs_link(conn, smb_fname)) {
1637 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1638 "as a directory\n",
1639 smb_fname->base_name));
1640 smb_fname->st.st_ex_mode =
1641 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1642 errno = saved_errno;
1643 return true;
1645 errno = saved_errno;
1646 return false;
1650 /****************************************************************************
1651 Get a level dependent lanman2 dir entry.
1652 ****************************************************************************/
1654 struct smbd_dirptr_lanman2_state {
1655 connection_struct *conn;
1656 uint32_t info_level;
1657 bool check_mangled_names;
1658 bool has_wild;
1659 bool got_exact_match;
1662 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1663 void *private_data,
1664 const char *dname,
1665 const char *mask,
1666 char **_fname)
1668 struct smbd_dirptr_lanman2_state *state =
1669 (struct smbd_dirptr_lanman2_state *)private_data;
1670 bool ok;
1671 char mangled_name[13]; /* mangled 8.3 name. */
1672 bool got_match;
1673 const char *fname;
1675 /* Mangle fname if it's an illegal name. */
1676 if (mangle_must_mangle(dname, state->conn->params)) {
1678 * Slow path - ensure we can push the original name as UCS2. If
1679 * not, then just don't return this name.
1681 NTSTATUS status;
1682 size_t ret_len = 0;
1683 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1684 uint8_t *tmp = talloc_array(talloc_tos(),
1685 uint8_t,
1686 len);
1688 status = srvstr_push(NULL,
1689 FLAGS2_UNICODE_STRINGS,
1690 tmp,
1691 dname,
1692 len,
1693 STR_TERMINATE,
1694 &ret_len);
1696 TALLOC_FREE(tmp);
1698 if (!NT_STATUS_IS_OK(status)) {
1699 return false;
1702 ok = name_to_8_3(dname, mangled_name,
1703 true, state->conn->params);
1704 if (!ok) {
1705 return false;
1707 fname = mangled_name;
1708 } else {
1709 fname = dname;
1712 got_match = exact_match(state->has_wild,
1713 state->conn->case_sensitive,
1714 fname, mask);
1715 state->got_exact_match = got_match;
1716 if (!got_match) {
1717 got_match = mask_match(fname, mask,
1718 state->conn->case_sensitive);
1721 if(!got_match && state->check_mangled_names &&
1722 !mangle_is_8_3(fname, false, state->conn->params)) {
1724 * It turns out that NT matches wildcards against
1725 * both long *and* short names. This may explain some
1726 * of the wildcard wierdness from old DOS clients
1727 * that some people have been seeing.... JRA.
1729 /* Force the mangling into 8.3. */
1730 ok = name_to_8_3(fname, mangled_name,
1731 false, state->conn->params);
1732 if (!ok) {
1733 return false;
1736 got_match = exact_match(state->has_wild,
1737 state->conn->case_sensitive,
1738 mangled_name, mask);
1739 state->got_exact_match = got_match;
1740 if (!got_match) {
1741 got_match = mask_match(mangled_name, mask,
1742 state->conn->case_sensitive);
1746 if (!got_match) {
1747 return false;
1750 *_fname = talloc_strdup(ctx, fname);
1751 if (*_fname == NULL) {
1752 return false;
1755 return true;
1758 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1759 void *private_data,
1760 struct smb_filename *smb_fname,
1761 bool get_dosmode,
1762 uint32_t *_mode)
1764 struct smbd_dirptr_lanman2_state *state =
1765 (struct smbd_dirptr_lanman2_state *)private_data;
1766 bool ms_dfs_link = false;
1767 uint32_t mode = 0;
1769 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1770 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1771 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1772 "Couldn't lstat [%s] (%s)\n",
1773 smb_fname_str_dbg(smb_fname),
1774 strerror(errno)));
1775 return false;
1777 } else if (!VALID_STAT(smb_fname->st) &&
1778 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1779 /* Needed to show the msdfs symlinks as
1780 * directories */
1782 ms_dfs_link = check_msdfs_link(state->conn,
1783 smb_fname);
1784 if (!ms_dfs_link) {
1785 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1786 "Couldn't stat [%s] (%s)\n",
1787 smb_fname_str_dbg(smb_fname),
1788 strerror(errno)));
1789 return false;
1793 if (ms_dfs_link) {
1794 mode = dos_mode_msdfs(state->conn, smb_fname);
1795 } else if (get_dosmode) {
1796 mode = dos_mode(state->conn, smb_fname);
1799 *_mode = mode;
1800 return true;
1803 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1804 connection_struct *conn,
1805 uint16_t flags2,
1806 uint32_t info_level,
1807 struct ea_list *name_list,
1808 bool check_mangled_names,
1809 bool requires_resume_key,
1810 uint32_t mode,
1811 const char *fname,
1812 const struct smb_filename *smb_fname,
1813 int space_remaining,
1814 uint8_t align,
1815 bool do_pad,
1816 char *base_data,
1817 char **ppdata,
1818 char *end_data,
1819 uint64_t *last_entry_off)
1821 char *p, *q, *pdata = *ppdata;
1822 uint32_t reskey=0;
1823 uint64_t file_size = 0;
1824 uint64_t allocation_size = 0;
1825 uint64_t file_id = 0;
1826 size_t len = 0;
1827 struct timespec mdate_ts = {0};
1828 struct timespec adate_ts = {0};
1829 struct timespec cdate_ts = {0};
1830 struct timespec create_date_ts = {0};
1831 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1832 char *nameptr;
1833 char *last_entry_ptr;
1834 bool was_8_3;
1835 int off;
1836 int pad = 0;
1837 NTSTATUS status;
1838 struct readdir_attr_data *readdir_attr_data = NULL;
1840 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1841 file_size = get_file_size_stat(&smb_fname->st);
1843 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1845 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1846 if (!NT_STATUS_IS_OK(status)) {
1847 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1848 return status;
1852 file_id = SMB_VFS_FS_FILE_ID(conn, &smb_fname->st);
1854 mdate_ts = smb_fname->st.st_ex_mtime;
1855 adate_ts = smb_fname->st.st_ex_atime;
1856 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1857 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1859 if (lp_dos_filetime_resolution(SNUM(conn))) {
1860 dos_filetime_timespec(&create_date_ts);
1861 dos_filetime_timespec(&mdate_ts);
1862 dos_filetime_timespec(&adate_ts);
1863 dos_filetime_timespec(&cdate_ts);
1866 create_date = convert_timespec_to_time_t(create_date_ts);
1867 mdate = convert_timespec_to_time_t(mdate_ts);
1868 adate = convert_timespec_to_time_t(adate_ts);
1870 /* align the record */
1871 SMB_ASSERT(align >= 1);
1873 off = (int)PTR_DIFF(pdata, base_data);
1874 pad = (off + (align-1)) & ~(align-1);
1875 pad -= off;
1877 if (pad && pad > space_remaining) {
1878 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1879 "for padding (wanted %u, had %d)\n",
1880 (unsigned int)pad,
1881 space_remaining ));
1882 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1885 off += pad;
1886 /* initialize padding to 0 */
1887 if (pad) {
1888 memset(pdata, 0, pad);
1890 space_remaining -= pad;
1892 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1893 space_remaining ));
1895 pdata += pad;
1896 p = pdata;
1897 last_entry_ptr = p;
1899 pad = 0;
1900 off = 0;
1902 switch (info_level) {
1903 case SMB_FIND_INFO_STANDARD:
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1905 if(requires_resume_key) {
1906 SIVAL(p,0,reskey);
1907 p += 4;
1909 srv_put_dos_date2(p,0,create_date);
1910 srv_put_dos_date2(p,4,adate);
1911 srv_put_dos_date2(p,8,mdate);
1912 SIVAL(p,12,(uint32_t)file_size);
1913 SIVAL(p,16,(uint32_t)allocation_size);
1914 SSVAL(p,20,mode);
1915 p += 23;
1916 nameptr = p;
1917 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1918 p += ucs2_align(base_data, p, 0);
1920 status = srvstr_push(base_data, flags2, p,
1921 fname, PTR_DIFF(end_data, p),
1922 STR_TERMINATE, &len);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 return status;
1926 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1927 if (len > 2) {
1928 SCVAL(nameptr, -1, len - 2);
1929 } else {
1930 SCVAL(nameptr, -1, 0);
1932 } else {
1933 if (len > 1) {
1934 SCVAL(nameptr, -1, len - 1);
1935 } else {
1936 SCVAL(nameptr, -1, 0);
1939 p += len;
1940 break;
1942 case SMB_FIND_EA_SIZE:
1943 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1944 if (requires_resume_key) {
1945 SIVAL(p,0,reskey);
1946 p += 4;
1948 srv_put_dos_date2(p,0,create_date);
1949 srv_put_dos_date2(p,4,adate);
1950 srv_put_dos_date2(p,8,mdate);
1951 SIVAL(p,12,(uint32_t)file_size);
1952 SIVAL(p,16,(uint32_t)allocation_size);
1953 SSVAL(p,20,mode);
1955 unsigned int ea_size = estimate_ea_size(conn, NULL,
1956 smb_fname);
1957 SIVAL(p,22,ea_size); /* Extended attributes */
1959 p += 27;
1960 nameptr = p - 1;
1961 status = srvstr_push(base_data, flags2,
1962 p, fname, PTR_DIFF(end_data, p),
1963 STR_TERMINATE | STR_NOALIGN, &len);
1964 if (!NT_STATUS_IS_OK(status)) {
1965 return status;
1967 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1968 if (len > 2) {
1969 len -= 2;
1970 } else {
1971 len = 0;
1973 } else {
1974 if (len > 1) {
1975 len -= 1;
1976 } else {
1977 len = 0;
1980 SCVAL(nameptr,0,len);
1981 p += len;
1982 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1983 break;
1985 case SMB_FIND_EA_LIST:
1987 struct ea_list *file_list = NULL;
1988 size_t ea_len = 0;
1990 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1991 if (!name_list) {
1992 return NT_STATUS_INVALID_PARAMETER;
1994 if (requires_resume_key) {
1995 SIVAL(p,0,reskey);
1996 p += 4;
1998 srv_put_dos_date2(p,0,create_date);
1999 srv_put_dos_date2(p,4,adate);
2000 srv_put_dos_date2(p,8,mdate);
2001 SIVAL(p,12,(uint32_t)file_size);
2002 SIVAL(p,16,(uint32_t)allocation_size);
2003 SSVAL(p,20,mode);
2004 p += 22; /* p now points to the EA area. */
2006 status = get_ea_list_from_file(ctx, conn, NULL,
2007 smb_fname,
2008 &ea_len, &file_list);
2009 if (!NT_STATUS_IS_OK(status)) {
2010 file_list = NULL;
2012 name_list = ea_list_union(name_list, file_list, &ea_len);
2014 /* We need to determine if this entry will fit in the space available. */
2015 /* Max string size is 255 bytes. */
2016 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
2017 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2018 "(wanted %u, had %d)\n",
2019 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
2020 space_remaining ));
2021 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2024 /* Push the ea_data followed by the name. */
2025 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
2026 nameptr = p;
2027 status = srvstr_push(base_data, flags2,
2028 p + 1, fname, PTR_DIFF(end_data, p+1),
2029 STR_TERMINATE | STR_NOALIGN, &len);
2030 if (!NT_STATUS_IS_OK(status)) {
2031 return status;
2033 if (flags2 & FLAGS2_UNICODE_STRINGS) {
2034 if (len > 2) {
2035 len -= 2;
2036 } else {
2037 len = 0;
2039 } else {
2040 if (len > 1) {
2041 len -= 1;
2042 } else {
2043 len = 0;
2046 SCVAL(nameptr,0,len);
2047 p += len + 1;
2048 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
2049 break;
2052 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2053 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2054 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2055 p += 4;
2056 SIVAL(p,0,reskey); p += 4;
2057 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2058 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2059 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2060 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2061 SOFF_T(p,0,file_size); p += 8;
2062 SOFF_T(p,0,allocation_size); p += 8;
2063 SIVAL(p,0,mode); p += 4;
2064 q = p; p += 4; /* q is placeholder for name length. */
2065 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2066 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2067 } else {
2068 unsigned int ea_size = estimate_ea_size(conn, NULL,
2069 smb_fname);
2070 SIVAL(p,0,ea_size); /* Extended attributes */
2072 p += 4;
2073 /* Clear the short name buffer. This is
2074 * IMPORTANT as not doing so will trigger
2075 * a Win2k client bug. JRA.
2077 if (!was_8_3 && check_mangled_names) {
2078 char mangled_name[13]; /* mangled 8.3 name. */
2079 if (!name_to_8_3(fname,mangled_name,True,
2080 conn->params)) {
2081 /* Error - mangle failed ! */
2082 memset(mangled_name,'\0',12);
2084 mangled_name[12] = 0;
2085 status = srvstr_push(base_data, flags2,
2086 p+2, mangled_name, 24,
2087 STR_UPPER|STR_UNICODE, &len);
2088 if (!NT_STATUS_IS_OK(status)) {
2089 return status;
2091 if (len < 24) {
2092 memset(p + 2 + len,'\0',24 - len);
2094 SSVAL(p, 0, len);
2095 } else {
2096 memset(p,'\0',26);
2098 p += 2 + 24;
2099 status = srvstr_push(base_data, flags2, p,
2100 fname, PTR_DIFF(end_data, p),
2101 STR_TERMINATE_ASCII, &len);
2102 if (!NT_STATUS_IS_OK(status)) {
2103 return status;
2105 SIVAL(q,0,len);
2106 p += len;
2108 len = PTR_DIFF(p, pdata);
2109 pad = (len + (align-1)) & ~(align-1);
2111 * offset to the next entry, the caller
2112 * will overwrite it for the last entry
2113 * that's why we always include the padding
2115 SIVAL(pdata,0,pad);
2117 * set padding to zero
2119 if (do_pad) {
2120 memset(p, 0, pad - len);
2121 p = pdata + pad;
2122 } else {
2123 p = pdata + len;
2125 break;
2127 case SMB_FIND_FILE_DIRECTORY_INFO:
2128 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2129 p += 4;
2130 SIVAL(p,0,reskey); p += 4;
2131 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2132 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2133 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2134 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2135 SOFF_T(p,0,file_size); p += 8;
2136 SOFF_T(p,0,allocation_size); p += 8;
2137 SIVAL(p,0,mode); p += 4;
2138 status = srvstr_push(base_data, flags2,
2139 p + 4, fname, PTR_DIFF(end_data, p+4),
2140 STR_TERMINATE_ASCII, &len);
2141 if (!NT_STATUS_IS_OK(status)) {
2142 return status;
2144 SIVAL(p,0,len);
2145 p += 4 + 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_FULL_DIRECTORY_INFO:
2167 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2168 p += 4;
2169 SIVAL(p,0,reskey); p += 4;
2170 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2171 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2172 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2173 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2174 SOFF_T(p,0,file_size); p += 8;
2175 SOFF_T(p,0,allocation_size); p += 8;
2176 SIVAL(p,0,mode); p += 4;
2177 q = p; p += 4; /* q is placeholder for name length. */
2178 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2179 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2180 } else {
2181 unsigned int ea_size = estimate_ea_size(conn, NULL,
2182 smb_fname);
2183 SIVAL(p,0,ea_size); /* Extended attributes */
2185 p +=4;
2186 status = srvstr_push(base_data, flags2, p,
2187 fname, PTR_DIFF(end_data, p),
2188 STR_TERMINATE_ASCII, &len);
2189 if (!NT_STATUS_IS_OK(status)) {
2190 return status;
2192 SIVAL(q, 0, len);
2193 p += len;
2195 len = PTR_DIFF(p, pdata);
2196 pad = (len + (align-1)) & ~(align-1);
2198 * offset to the next entry, the caller
2199 * will overwrite it for the last entry
2200 * that's why we always include the padding
2202 SIVAL(pdata,0,pad);
2204 * set padding to zero
2206 if (do_pad) {
2207 memset(p, 0, pad - len);
2208 p = pdata + pad;
2209 } else {
2210 p = pdata + len;
2212 break;
2214 case SMB_FIND_FILE_NAMES_INFO:
2215 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2216 p += 4;
2217 SIVAL(p,0,reskey); p += 4;
2218 p += 4;
2219 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2220 acl on a dir (tridge) */
2221 status = srvstr_push(base_data, flags2, p,
2222 fname, PTR_DIFF(end_data, p),
2223 STR_TERMINATE_ASCII, &len);
2224 if (!NT_STATUS_IS_OK(status)) {
2225 return status;
2227 SIVAL(p, -4, len);
2228 p += len;
2230 len = PTR_DIFF(p, pdata);
2231 pad = (len + (align-1)) & ~(align-1);
2233 * offset to the next entry, the caller
2234 * will overwrite it for the last entry
2235 * that's why we always include the padding
2237 SIVAL(pdata,0,pad);
2239 * set padding to zero
2241 if (do_pad) {
2242 memset(p, 0, pad - len);
2243 p = pdata + pad;
2244 } else {
2245 p = pdata + len;
2247 break;
2249 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2250 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2251 p += 4;
2252 SIVAL(p,0,reskey); p += 4;
2253 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2254 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2255 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2256 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2257 SOFF_T(p,0,file_size); p += 8;
2258 SOFF_T(p,0,allocation_size); p += 8;
2259 SIVAL(p,0,mode); p += 4;
2260 q = p; p += 4; /* q is placeholder for name length. */
2261 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2262 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2263 } else {
2264 unsigned int ea_size = estimate_ea_size(conn, NULL,
2265 smb_fname);
2266 SIVAL(p,0,ea_size); /* Extended attributes */
2268 p += 4;
2269 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2270 SBVAL(p,0,file_id); p += 8;
2271 status = srvstr_push(base_data, flags2, p,
2272 fname, PTR_DIFF(end_data, p),
2273 STR_TERMINATE_ASCII, &len);
2274 if (!NT_STATUS_IS_OK(status)) {
2275 return status;
2277 SIVAL(q, 0, len);
2278 p += len;
2280 len = PTR_DIFF(p, pdata);
2281 pad = (len + (align-1)) & ~(align-1);
2283 * offset to the next entry, the caller
2284 * will overwrite it for the last entry
2285 * that's why we always include the padding
2287 SIVAL(pdata,0,pad);
2289 * set padding to zero
2291 if (do_pad) {
2292 memset(p, 0, pad - len);
2293 p = pdata + pad;
2294 } else {
2295 p = pdata + len;
2297 break;
2299 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2300 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2301 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2302 p += 4;
2303 SIVAL(p,0,reskey); p += 4;
2304 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2305 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2306 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2307 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2308 SOFF_T(p,0,file_size); p += 8;
2309 SOFF_T(p,0,allocation_size); p += 8;
2310 SIVAL(p,0,mode); p += 4;
2311 q = p; p += 4; /* q is placeholder for name length */
2312 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2313 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2314 } else if (readdir_attr_data &&
2315 readdir_attr_data->type == RDATTR_AAPL) {
2317 * OS X specific SMB2 extension negotiated via
2318 * AAPL create context: return max_access in
2319 * ea_size field.
2321 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2322 } else {
2323 unsigned int ea_size = estimate_ea_size(conn, NULL,
2324 smb_fname);
2325 SIVAL(p,0,ea_size); /* Extended attributes */
2327 p += 4;
2329 if (readdir_attr_data &&
2330 readdir_attr_data->type == RDATTR_AAPL) {
2332 * OS X specific SMB2 extension negotiated via
2333 * AAPL create context: return resource fork
2334 * length and compressed FinderInfo in
2335 * shortname field.
2337 * According to documentation short_name_len
2338 * should be 0, but on the wire behaviour
2339 * shows its set to 24 by clients.
2341 SSVAL(p, 0, 24);
2343 /* Resourefork length */
2344 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2346 /* Compressed FinderInfo */
2347 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2348 } else if (!was_8_3 && check_mangled_names) {
2349 char mangled_name[13]; /* mangled 8.3 name. */
2350 if (!name_to_8_3(fname,mangled_name,True,
2351 conn->params)) {
2352 /* Error - mangle failed ! */
2353 memset(mangled_name,'\0',12);
2355 mangled_name[12] = 0;
2356 status = srvstr_push(base_data, flags2,
2357 p+2, mangled_name, 24,
2358 STR_UPPER|STR_UNICODE, &len);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 return status;
2362 SSVAL(p, 0, len);
2363 if (len < 24) {
2364 memset(p + 2 + len,'\0',24 - len);
2366 SSVAL(p, 0, len);
2367 } else {
2368 /* Clear the short name buffer. This is
2369 * IMPORTANT as not doing so will trigger
2370 * a Win2k client bug. JRA.
2372 memset(p,'\0',26);
2374 p += 26;
2376 /* Reserved ? */
2377 if (readdir_attr_data &&
2378 readdir_attr_data->type == RDATTR_AAPL) {
2380 * OS X specific SMB2 extension negotiated via
2381 * AAPL create context: return UNIX mode in
2382 * reserved field.
2384 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2385 SSVAL(p, 0, aapl_mode);
2386 } else {
2387 SSVAL(p, 0, 0);
2389 p += 2;
2391 SBVAL(p,0,file_id); p += 8;
2392 status = srvstr_push(base_data, flags2, p,
2393 fname, PTR_DIFF(end_data, p),
2394 STR_TERMINATE_ASCII, &len);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 return status;
2398 SIVAL(q,0,len);
2399 p += len;
2401 len = PTR_DIFF(p, pdata);
2402 pad = (len + (align-1)) & ~(align-1);
2404 * offset to the next entry, the caller
2405 * will overwrite it for the last entry
2406 * that's why we always include the padding
2408 SIVAL(pdata,0,pad);
2410 * set padding to zero
2412 if (do_pad) {
2413 memset(p, 0, pad - len);
2414 p = pdata + pad;
2415 } else {
2416 p = pdata + len;
2418 break;
2420 /* CIFS UNIX Extension. */
2422 case SMB_FIND_FILE_UNIX:
2423 case SMB_FIND_FILE_UNIX_INFO2:
2424 p+= 4;
2425 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2427 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2429 if (info_level == SMB_FIND_FILE_UNIX) {
2430 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2431 p = store_file_unix_basic(conn, p,
2432 NULL, &smb_fname->st);
2433 status = srvstr_push(base_data, flags2, p,
2434 fname, PTR_DIFF(end_data, p),
2435 STR_TERMINATE, &len);
2436 if (!NT_STATUS_IS_OK(status)) {
2437 return status;
2439 } else {
2440 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2441 p = store_file_unix_basic_info2(conn, p,
2442 NULL, &smb_fname->st);
2443 nameptr = p;
2444 p += 4;
2445 status = srvstr_push(base_data, flags2, p, fname,
2446 PTR_DIFF(end_data, p), 0, &len);
2447 if (!NT_STATUS_IS_OK(status)) {
2448 return status;
2450 SIVAL(nameptr, 0, len);
2453 p += len;
2455 len = PTR_DIFF(p, pdata);
2456 pad = (len + (align-1)) & ~(align-1);
2458 * offset to the next entry, the caller
2459 * will overwrite it for the last entry
2460 * that's why we always include the padding
2462 SIVAL(pdata,0,pad);
2464 * set padding to zero
2466 if (do_pad) {
2467 memset(p, 0, pad - len);
2468 p = pdata + pad;
2469 } else {
2470 p = pdata + len;
2472 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2474 break;
2476 default:
2477 return NT_STATUS_INVALID_LEVEL;
2480 if (PTR_DIFF(p,pdata) > space_remaining) {
2481 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2482 "(wanted %u, had %d)\n",
2483 (unsigned int)PTR_DIFF(p,pdata),
2484 space_remaining ));
2485 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2488 /* Setup the last entry pointer, as an offset from base_data */
2489 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2490 /* Advance the data pointer to the next slot */
2491 *ppdata = p;
2493 return NT_STATUS_OK;
2496 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2497 connection_struct *conn,
2498 struct dptr_struct *dirptr,
2499 uint16_t flags2,
2500 const char *path_mask,
2501 uint32_t dirtype,
2502 int info_level,
2503 int requires_resume_key,
2504 bool dont_descend,
2505 bool ask_sharemode,
2506 bool get_dosmode,
2507 uint8_t align,
2508 bool do_pad,
2509 char **ppdata,
2510 char *base_data,
2511 char *end_data,
2512 int space_remaining,
2513 struct smb_filename **_smb_fname,
2514 bool *got_exact_match,
2515 int *_last_entry_off,
2516 struct ea_list *name_list,
2517 struct file_id *file_id)
2519 const char *p;
2520 const char *mask = NULL;
2521 long prev_dirpos = 0;
2522 uint32_t mode = 0;
2523 char *fname = NULL;
2524 struct smb_filename *smb_fname = NULL;
2525 struct smbd_dirptr_lanman2_state state;
2526 bool ok;
2527 uint64_t last_entry_off = 0;
2528 NTSTATUS status;
2529 enum mangled_names_options mangled_names;
2530 bool marshall_with_83_names;
2532 mangled_names = lp_mangled_names(conn->params);
2534 ZERO_STRUCT(state);
2535 state.conn = conn;
2536 state.info_level = info_level;
2537 if (mangled_names != MANGLED_NAMES_NO) {
2538 state.check_mangled_names = true;
2540 state.has_wild = dptr_has_wild(dirptr);
2541 state.got_exact_match = false;
2543 *got_exact_match = false;
2545 p = strrchr_m(path_mask,'/');
2546 if(p != NULL) {
2547 if(p[1] == '\0') {
2548 mask = "*.*";
2549 } else {
2550 mask = p+1;
2552 } else {
2553 mask = path_mask;
2556 ok = smbd_dirptr_get_entry(ctx,
2557 dirptr,
2558 mask,
2559 dirtype,
2560 dont_descend,
2561 ask_sharemode,
2562 get_dosmode,
2563 smbd_dirptr_lanman2_match_fn,
2564 smbd_dirptr_lanman2_mode_fn,
2565 &state,
2566 &fname,
2567 &smb_fname,
2568 &mode,
2569 &prev_dirpos);
2570 if (!ok) {
2571 return NT_STATUS_END_OF_FILE;
2574 *got_exact_match = state.got_exact_match;
2576 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2578 status = smbd_marshall_dir_entry(ctx,
2579 conn,
2580 flags2,
2581 info_level,
2582 name_list,
2583 marshall_with_83_names,
2584 requires_resume_key,
2585 mode,
2586 fname,
2587 smb_fname,
2588 space_remaining,
2589 align,
2590 do_pad,
2591 base_data,
2592 ppdata,
2593 end_data,
2594 &last_entry_off);
2595 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2596 DEBUG(1,("Conversion error: illegal character: %s\n",
2597 smb_fname_str_dbg(smb_fname)));
2600 if (file_id != NULL) {
2601 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2604 if (!NT_STATUS_IS_OK(status) &&
2605 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2607 TALLOC_FREE(smb_fname);
2608 TALLOC_FREE(fname);
2609 return status;
2612 if (_smb_fname != NULL) {
2613 struct smb_filename *name = NULL;
2615 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2616 if (name == NULL) {
2617 TALLOC_FREE(smb_fname);
2618 TALLOC_FREE(fname);
2619 return NT_STATUS_NO_MEMORY;
2621 *_smb_fname = name;
2624 TALLOC_FREE(smb_fname);
2625 TALLOC_FREE(fname);
2627 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2628 dptr_SeekDir(dirptr, prev_dirpos);
2629 return status;
2632 *_last_entry_off = last_entry_off;
2633 return NT_STATUS_OK;
2636 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2637 connection_struct *conn,
2638 struct dptr_struct *dirptr,
2639 uint16_t flags2,
2640 const char *path_mask,
2641 uint32_t dirtype,
2642 int info_level,
2643 bool requires_resume_key,
2644 bool dont_descend,
2645 bool ask_sharemode,
2646 char **ppdata,
2647 char *base_data,
2648 char *end_data,
2649 int space_remaining,
2650 bool *got_exact_match,
2651 int *last_entry_off,
2652 struct ea_list *name_list)
2654 uint8_t align = 4;
2655 const bool do_pad = true;
2657 if (info_level >= 1 && info_level <= 3) {
2658 /* No alignment on earlier info levels. */
2659 align = 1;
2662 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2663 path_mask, dirtype, info_level,
2664 requires_resume_key, dont_descend, ask_sharemode,
2665 true, align, do_pad,
2666 ppdata, base_data, end_data,
2667 space_remaining,
2668 NULL,
2669 got_exact_match,
2670 last_entry_off, name_list, NULL);
2673 /****************************************************************************
2674 Reply to a TRANS2_FINDFIRST.
2675 ****************************************************************************/
2677 static void call_trans2findfirst(connection_struct *conn,
2678 struct smb_request *req,
2679 char **pparams, int total_params,
2680 char **ppdata, int total_data,
2681 unsigned int max_data_bytes)
2683 /* We must be careful here that we don't return more than the
2684 allowed number of data bytes. If this means returning fewer than
2685 maxentries then so be it. We assume that the redirector has
2686 enough room for the fixed number of parameter bytes it has
2687 requested. */
2688 struct smb_filename *smb_dname = NULL;
2689 char *params = *pparams;
2690 char *pdata = *ppdata;
2691 char *data_end;
2692 uint32_t dirtype;
2693 int maxentries;
2694 uint16_t findfirst_flags;
2695 bool close_after_first;
2696 bool close_if_end;
2697 bool requires_resume_key;
2698 int info_level;
2699 char *directory = NULL;
2700 char *mask = NULL;
2701 char *p;
2702 int last_entry_off=0;
2703 int dptr_num = -1;
2704 int numentries = 0;
2705 int i;
2706 bool finished = False;
2707 bool dont_descend = False;
2708 bool out_of_space = False;
2709 int space_remaining;
2710 bool mask_contains_wcard = False;
2711 struct ea_list *ea_list = NULL;
2712 NTSTATUS ntstatus = NT_STATUS_OK;
2713 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2714 struct dptr_struct *dirptr = NULL;
2715 struct smbd_server_connection *sconn = req->sconn;
2716 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2717 ucf_flags_from_smb_request(req);
2718 bool backup_priv = false;
2719 bool as_root = false;
2721 if (total_params < 13) {
2722 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2723 goto out;
2726 dirtype = SVAL(params,0);
2727 maxentries = SVAL(params,2);
2728 findfirst_flags = SVAL(params,4);
2729 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2730 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2731 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2732 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2733 security_token_has_privilege(get_current_nttok(conn),
2734 SEC_PRIV_BACKUP));
2736 info_level = SVAL(params,6);
2738 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2739 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2740 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2741 (int)backup_priv,
2742 info_level, max_data_bytes));
2744 if (!maxentries) {
2745 /* W2K3 seems to treat zero as 1. */
2746 maxentries = 1;
2749 switch (info_level) {
2750 case SMB_FIND_INFO_STANDARD:
2751 case SMB_FIND_EA_SIZE:
2752 case SMB_FIND_EA_LIST:
2753 case SMB_FIND_FILE_DIRECTORY_INFO:
2754 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2755 case SMB_FIND_FILE_NAMES_INFO:
2756 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2757 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2758 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2759 break;
2760 case SMB_FIND_FILE_UNIX:
2761 case SMB_FIND_FILE_UNIX_INFO2:
2762 /* Always use filesystem for UNIX mtime query. */
2763 ask_sharemode = false;
2764 if (!lp_unix_extensions()) {
2765 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2766 goto out;
2768 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2769 break;
2770 default:
2771 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2772 goto out;
2775 if (req->posix_pathnames) {
2776 srvstr_get_path_wcard_posix(talloc_tos(),
2777 params,
2778 req->flags2,
2779 &directory,
2780 params+12,
2781 total_params - 12,
2782 STR_TERMINATE,
2783 &ntstatus,
2784 &mask_contains_wcard);
2785 } else {
2786 srvstr_get_path_wcard(talloc_tos(),
2787 params,
2788 req->flags2,
2789 &directory,
2790 params+12,
2791 total_params - 12,
2792 STR_TERMINATE,
2793 &ntstatus,
2794 &mask_contains_wcard);
2796 if (!NT_STATUS_IS_OK(ntstatus)) {
2797 reply_nterror(req, ntstatus);
2798 goto out;
2801 if (backup_priv) {
2802 become_root();
2803 as_root = true;
2804 ntstatus = filename_convert_with_privilege(talloc_tos(),
2805 conn,
2806 req,
2807 directory,
2808 ucf_flags,
2809 &mask_contains_wcard,
2810 &smb_dname);
2811 } else {
2812 ntstatus = filename_convert(talloc_tos(), conn,
2813 directory,
2814 ucf_flags,
2815 NULL,
2816 &mask_contains_wcard,
2817 &smb_dname);
2820 if (!NT_STATUS_IS_OK(ntstatus)) {
2821 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2822 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2823 ERRSRV, ERRbadpath);
2824 goto out;
2826 reply_nterror(req, ntstatus);
2827 goto out;
2830 mask = smb_dname->original_lcomp;
2832 directory = smb_dname->base_name;
2834 p = strrchr_m(directory,'/');
2835 if(p == NULL) {
2836 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2837 if((directory[0] == '.') && (directory[1] == '\0')) {
2838 mask = talloc_strdup(talloc_tos(),"*");
2839 if (!mask) {
2840 reply_nterror(req, NT_STATUS_NO_MEMORY);
2841 goto out;
2843 mask_contains_wcard = True;
2845 } else {
2846 *p = 0;
2849 if (p == NULL || p == directory) {
2850 /* Ensure we don't have a directory name of "". */
2851 directory = talloc_strdup(talloc_tos(), ".");
2852 if (!directory) {
2853 reply_nterror(req, NT_STATUS_NO_MEMORY);
2854 goto out;
2856 /* Ensure smb_dname->base_name matches. */
2857 smb_dname->base_name = directory;
2860 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2862 if (info_level == SMB_FIND_EA_LIST) {
2863 uint32_t ea_size;
2865 if (total_data < 4) {
2866 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2867 goto out;
2870 ea_size = IVAL(pdata,0);
2871 if (ea_size != total_data) {
2872 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2873 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2875 goto out;
2878 if (!lp_ea_support(SNUM(conn))) {
2879 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2880 goto out;
2883 /* Pull out the list of names. */
2884 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2885 if (!ea_list) {
2886 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2887 goto out;
2891 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2892 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2893 goto out;
2896 *ppdata = (char *)SMB_REALLOC(
2897 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2898 if(*ppdata == NULL ) {
2899 reply_nterror(req, NT_STATUS_NO_MEMORY);
2900 goto out;
2902 pdata = *ppdata;
2903 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2905 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2906 * error.
2908 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2909 /* Realloc the params space */
2910 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2911 if (*pparams == NULL) {
2912 reply_nterror(req, NT_STATUS_NO_MEMORY);
2913 goto out;
2915 params = *pparams;
2917 /* Save the wildcard match and attribs we are using on this directory -
2918 needed as lanman2 assumes these are being saved between calls */
2920 ntstatus = dptr_create(conn,
2921 req,
2922 NULL, /* fsp */
2923 smb_dname,
2924 False,
2925 True,
2926 req->smbpid,
2927 mask,
2928 mask_contains_wcard,
2929 dirtype,
2930 &dirptr);
2932 if (!NT_STATUS_IS_OK(ntstatus)) {
2933 reply_nterror(req, ntstatus);
2934 goto out;
2937 if (backup_priv) {
2938 /* Remember this in case we have
2939 to do a findnext. */
2940 dptr_set_priv(dirptr);
2943 dptr_num = dptr_dnum(dirptr);
2944 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2946 /* We don't need to check for VOL here as this is returned by
2947 a different TRANS2 call. */
2949 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2950 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2951 if (in_list(directory,
2952 lp_dont_descend(talloc_tos(), SNUM(conn)),
2953 conn->case_sensitive)) {
2954 dont_descend = True;
2957 p = pdata;
2958 space_remaining = max_data_bytes;
2959 out_of_space = False;
2961 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2962 bool got_exact_match = False;
2964 /* this is a heuristic to avoid seeking the dirptr except when
2965 absolutely necessary. It allows for a filename of about 40 chars */
2966 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2967 out_of_space = True;
2968 finished = False;
2969 } else {
2970 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2971 conn,
2972 dirptr,
2973 req->flags2,
2974 mask,dirtype,info_level,
2975 requires_resume_key,dont_descend,
2976 ask_sharemode,
2977 &p,pdata,data_end,
2978 space_remaining,
2979 &got_exact_match,
2980 &last_entry_off, ea_list);
2981 if (NT_STATUS_EQUAL(ntstatus,
2982 NT_STATUS_ILLEGAL_CHARACTER)) {
2984 * Bad character conversion on name. Ignore this
2985 * entry.
2987 continue;
2989 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2990 out_of_space = true;
2991 } else {
2992 finished = !NT_STATUS_IS_OK(ntstatus);
2996 if (!finished && !out_of_space)
2997 numentries++;
3000 * As an optimisation if we know we aren't looking
3001 * for a wildcard name (ie. the name matches the wildcard exactly)
3002 * then we can finish on any (first) match.
3003 * This speeds up large directory searches. JRA.
3006 if(got_exact_match)
3007 finished = True;
3009 /* Ensure space_remaining never goes -ve. */
3010 if (PTR_DIFF(p,pdata) > max_data_bytes) {
3011 space_remaining = 0;
3012 out_of_space = true;
3013 } else {
3014 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3018 /* Check if we can close the dirptr */
3019 if(close_after_first || (finished && close_if_end)) {
3020 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
3021 dptr_close(sconn, &dptr_num);
3025 * If there are no matching entries we must return ERRDOS/ERRbadfile -
3026 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
3027 * the protocol level is less than NT1. Tested with smbclient. JRA.
3028 * This should fix the OS/2 client bug #2335.
3031 if(numentries == 0) {
3032 dptr_close(sconn, &dptr_num);
3033 if (get_Protocol() < PROTOCOL_NT1) {
3034 reply_force_doserror(req, ERRDOS, ERRnofiles);
3035 goto out;
3036 } else {
3037 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
3038 ERRDOS, ERRbadfile);
3039 goto out;
3043 /* At this point pdata points to numentries directory entries. */
3045 /* Set up the return parameter block */
3046 SSVAL(params,0,dptr_num);
3047 SSVAL(params,2,numentries);
3048 SSVAL(params,4,finished);
3049 SSVAL(params,6,0); /* Never an EA error */
3050 SSVAL(params,8,last_entry_off);
3052 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
3053 max_data_bytes);
3055 if ((! *directory) && dptr_path(sconn, dptr_num)) {
3056 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
3057 if (!directory) {
3058 reply_nterror(req, NT_STATUS_NO_MEMORY);
3062 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3063 smb_fn_name(req->cmd),
3064 mask, directory, dirtype, numentries ) );
3067 * Force a name mangle here to ensure that the
3068 * mask as an 8.3 name is top of the mangled cache.
3069 * The reasons for this are subtle. Don't remove
3070 * this code unless you know what you are doing
3071 * (see PR#13758). JRA.
3074 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3075 char mangled_name[13];
3076 name_to_8_3(mask, mangled_name, True, conn->params);
3078 out:
3080 if (as_root) {
3081 unbecome_root();
3084 TALLOC_FREE(smb_dname);
3085 return;
3088 /****************************************************************************
3089 Reply to a TRANS2_FINDNEXT.
3090 ****************************************************************************/
3092 static void call_trans2findnext(connection_struct *conn,
3093 struct smb_request *req,
3094 char **pparams, int total_params,
3095 char **ppdata, int total_data,
3096 unsigned int max_data_bytes)
3098 /* We must be careful here that we don't return more than the
3099 allowed number of data bytes. If this means returning fewer than
3100 maxentries then so be it. We assume that the redirector has
3101 enough room for the fixed number of parameter bytes it has
3102 requested. */
3103 char *params = *pparams;
3104 char *pdata = *ppdata;
3105 char *data_end;
3106 int dptr_num;
3107 int maxentries;
3108 uint16_t info_level;
3109 uint32_t resume_key;
3110 uint16_t findnext_flags;
3111 bool close_after_request;
3112 bool close_if_end;
3113 bool requires_resume_key;
3114 bool continue_bit;
3115 bool mask_contains_wcard = False;
3116 char *resume_name = NULL;
3117 const char *mask = NULL;
3118 const char *directory = NULL;
3119 char *p = NULL;
3120 uint16_t dirtype;
3121 int numentries = 0;
3122 int i, last_entry_off=0;
3123 bool finished = False;
3124 bool dont_descend = False;
3125 bool out_of_space = False;
3126 int space_remaining;
3127 struct ea_list *ea_list = NULL;
3128 NTSTATUS ntstatus = NT_STATUS_OK;
3129 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3130 TALLOC_CTX *ctx = talloc_tos();
3131 struct dptr_struct *dirptr;
3132 struct smbd_server_connection *sconn = req->sconn;
3133 bool backup_priv = false;
3134 bool as_root = false;
3136 if (total_params < 13) {
3137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3138 return;
3141 dptr_num = SVAL(params,0);
3142 maxentries = SVAL(params,2);
3143 info_level = SVAL(params,4);
3144 resume_key = IVAL(params,6);
3145 findnext_flags = SVAL(params,10);
3146 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3147 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3148 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3149 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3151 if (!continue_bit) {
3152 /* We only need resume_name if continue_bit is zero. */
3153 if (req->posix_pathnames) {
3154 srvstr_get_path_wcard_posix(ctx,
3155 params,
3156 req->flags2,
3157 &resume_name,
3158 params+12,
3159 total_params - 12,
3160 STR_TERMINATE,
3161 &ntstatus,
3162 &mask_contains_wcard);
3163 } else {
3164 srvstr_get_path_wcard(ctx,
3165 params,
3166 req->flags2,
3167 &resume_name,
3168 params+12,
3169 total_params - 12,
3170 STR_TERMINATE,
3171 &ntstatus,
3172 &mask_contains_wcard);
3174 if (!NT_STATUS_IS_OK(ntstatus)) {
3175 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3176 complain (it thinks we're asking for the directory above the shared
3177 path or an invalid name). Catch this as the resume name is only compared, never used in
3178 a file access. JRA. */
3179 srvstr_pull_talloc(ctx, params, req->flags2,
3180 &resume_name, params+12,
3181 total_params - 12,
3182 STR_TERMINATE);
3184 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3185 reply_nterror(req, ntstatus);
3186 return;
3191 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3192 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3193 resume_key = %d resume name = %s continue=%d level = %d\n",
3194 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3195 requires_resume_key, resume_key,
3196 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3198 if (!maxentries) {
3199 /* W2K3 seems to treat zero as 1. */
3200 maxentries = 1;
3203 switch (info_level) {
3204 case SMB_FIND_INFO_STANDARD:
3205 case SMB_FIND_EA_SIZE:
3206 case SMB_FIND_EA_LIST:
3207 case SMB_FIND_FILE_DIRECTORY_INFO:
3208 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3209 case SMB_FIND_FILE_NAMES_INFO:
3210 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3211 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3212 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3213 break;
3214 case SMB_FIND_FILE_UNIX:
3215 case SMB_FIND_FILE_UNIX_INFO2:
3216 /* Always use filesystem for UNIX mtime query. */
3217 ask_sharemode = false;
3218 if (!lp_unix_extensions()) {
3219 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3220 return;
3222 break;
3223 default:
3224 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3225 return;
3228 if (info_level == SMB_FIND_EA_LIST) {
3229 uint32_t ea_size;
3231 if (total_data < 4) {
3232 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3233 return;
3236 ea_size = IVAL(pdata,0);
3237 if (ea_size != total_data) {
3238 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3239 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3241 return;
3244 if (!lp_ea_support(SNUM(conn))) {
3245 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3246 return;
3249 /* Pull out the list of names. */
3250 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3251 if (!ea_list) {
3252 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3253 return;
3257 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3258 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3259 return;
3262 *ppdata = (char *)SMB_REALLOC(
3263 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3264 if(*ppdata == NULL) {
3265 reply_nterror(req, NT_STATUS_NO_MEMORY);
3266 return;
3269 pdata = *ppdata;
3270 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3273 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3274 * error.
3276 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3277 /* Realloc the params space */
3278 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3279 if(*pparams == NULL ) {
3280 reply_nterror(req, NT_STATUS_NO_MEMORY);
3281 return;
3284 params = *pparams;
3286 /* Check that the dptr is valid */
3287 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3288 reply_nterror(req, STATUS_NO_MORE_FILES);
3289 return;
3292 directory = dptr_path(sconn, dptr_num);
3294 /* Get the wildcard mask from the dptr */
3295 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3296 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3297 reply_nterror(req, STATUS_NO_MORE_FILES);
3298 return;
3301 /* Get the attr mask from the dptr */
3302 dirtype = dptr_attr(sconn, dptr_num);
3304 backup_priv = dptr_get_priv(dirptr);
3306 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3307 "backup_priv = %d\n",
3308 dptr_num, mask, dirtype,
3309 (long)dirptr,
3310 dptr_TellDir(dirptr),
3311 (int)backup_priv));
3313 /* We don't need to check for VOL here as this is returned by
3314 a different TRANS2 call. */
3316 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3317 directory,lp_dont_descend(ctx, SNUM(conn))));
3318 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3319 dont_descend = True;
3321 p = pdata;
3322 space_remaining = max_data_bytes;
3323 out_of_space = False;
3325 if (backup_priv) {
3326 become_root();
3327 as_root = true;
3331 * Seek to the correct position. We no longer use the resume key but
3332 * depend on the last file name instead.
3335 if(!continue_bit && resume_name && *resume_name) {
3336 SMB_STRUCT_STAT st;
3338 long current_pos = 0;
3340 * Remember, name_to_8_3 is called by
3341 * get_lanman2_dir_entry(), so the resume name
3342 * could be mangled. Ensure we check the unmangled name.
3345 if (mangle_is_mangled(resume_name, conn->params)) {
3346 char *new_resume_name = NULL;
3347 mangle_lookup_name_from_8_3(ctx,
3348 resume_name,
3349 &new_resume_name,
3350 conn->params);
3351 if (new_resume_name) {
3352 resume_name = new_resume_name;
3357 * Fix for NT redirector problem triggered by resume key indexes
3358 * changing between directory scans. We now return a resume key of 0
3359 * and instead look for the filename to continue from (also given
3360 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3361 * findfirst/findnext (as is usual) then the directory pointer
3362 * should already be at the correct place.
3365 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3366 } /* end if resume_name && !continue_bit */
3368 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3369 bool got_exact_match = False;
3371 /* this is a heuristic to avoid seeking the dirptr except when
3372 absolutely necessary. It allows for a filename of about 40 chars */
3373 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3374 out_of_space = True;
3375 finished = False;
3376 } else {
3377 ntstatus = get_lanman2_dir_entry(ctx,
3378 conn,
3379 dirptr,
3380 req->flags2,
3381 mask,dirtype,info_level,
3382 requires_resume_key,dont_descend,
3383 ask_sharemode,
3384 &p,pdata,data_end,
3385 space_remaining,
3386 &got_exact_match,
3387 &last_entry_off, ea_list);
3388 if (NT_STATUS_EQUAL(ntstatus,
3389 NT_STATUS_ILLEGAL_CHARACTER)) {
3391 * Bad character conversion on name. Ignore this
3392 * entry.
3394 continue;
3396 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3397 out_of_space = true;
3398 } else {
3399 finished = !NT_STATUS_IS_OK(ntstatus);
3403 if (!finished && !out_of_space)
3404 numentries++;
3407 * As an optimisation if we know we aren't looking
3408 * for a wildcard name (ie. the name matches the wildcard exactly)
3409 * then we can finish on any (first) match.
3410 * This speeds up large directory searches. JRA.
3413 if(got_exact_match)
3414 finished = True;
3416 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3419 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3420 smb_fn_name(req->cmd),
3421 mask, directory, dirtype, numentries ) );
3423 /* Check if we can close the dirptr */
3424 if(close_after_request || (finished && close_if_end)) {
3425 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3426 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3429 if (as_root) {
3430 unbecome_root();
3433 /* Set up the return parameter block */
3434 SSVAL(params,0,numentries);
3435 SSVAL(params,2,finished);
3436 SSVAL(params,4,0); /* Never an EA error */
3437 SSVAL(params,6,last_entry_off);
3439 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3440 max_data_bytes);
3442 return;
3445 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3447 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3448 return objid;
3451 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3453 SMB_ASSERT(extended_info != NULL);
3455 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3456 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3457 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3458 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3459 #ifdef SAMBA_VERSION_REVISION
3460 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3461 #endif
3462 extended_info->samba_subversion = 0;
3463 #ifdef SAMBA_VERSION_RC_RELEASE
3464 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3465 #else
3466 #ifdef SAMBA_VERSION_PRE_RELEASE
3467 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3468 #endif
3469 #endif
3470 #ifdef SAMBA_VERSION_VENDOR_PATCH
3471 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3472 #endif
3473 extended_info->samba_gitcommitdate = 0;
3474 #ifdef SAMBA_VERSION_COMMIT_TIME
3475 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3476 #endif
3478 memset(extended_info->samba_version_string, 0,
3479 sizeof(extended_info->samba_version_string));
3481 snprintf (extended_info->samba_version_string,
3482 sizeof(extended_info->samba_version_string),
3483 "%s", samba_version_string());
3486 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3487 connection_struct *conn,
3488 TALLOC_CTX *mem_ctx,
3489 uint16_t info_level,
3490 uint16_t flags2,
3491 unsigned int max_data_bytes,
3492 size_t *fixed_portion,
3493 struct smb_filename *fname,
3494 char **ppdata,
3495 int *ret_data_len)
3497 char *pdata, *end_data;
3498 int data_len = 0;
3499 size_t len = 0;
3500 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3501 int snum = SNUM(conn);
3502 const char *fstype = lp_fstype(SNUM(conn));
3503 const char *filename = NULL;
3504 const uint64_t bytes_per_sector = 512;
3505 uint32_t additional_flags = 0;
3506 struct smb_filename smb_fname;
3507 SMB_STRUCT_STAT st;
3508 NTSTATUS status = NT_STATUS_OK;
3509 uint64_t df_ret;
3511 if (fname == NULL || fname->base_name == NULL) {
3512 filename = ".";
3513 } else {
3514 filename = fname->base_name;
3517 if (IS_IPC(conn)) {
3518 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3519 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3520 "info level (0x%x) on IPC$.\n",
3521 (unsigned int)info_level));
3522 return NT_STATUS_ACCESS_DENIED;
3526 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3528 ZERO_STRUCT(smb_fname);
3529 smb_fname.base_name = discard_const_p(char, filename);
3531 if(info_level != SMB_FS_QUOTA_INFORMATION
3532 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3533 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3534 return map_nt_error_from_unix(errno);
3537 st = smb_fname.st;
3539 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3540 return NT_STATUS_INVALID_PARAMETER;
3543 *ppdata = (char *)SMB_REALLOC(
3544 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3545 if (*ppdata == NULL) {
3546 return NT_STATUS_NO_MEMORY;
3549 pdata = *ppdata;
3550 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3551 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3553 *fixed_portion = 0;
3555 switch (info_level) {
3556 case SMB_INFO_ALLOCATION:
3558 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3559 data_len = 18;
3560 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3561 &dfree, &dsize);
3562 if (df_ret == (uint64_t)-1) {
3563 return map_nt_error_from_unix(errno);
3566 block_size = lp_block_size(snum);
3567 if (bsize < block_size) {
3568 uint64_t factor = block_size/bsize;
3569 bsize = block_size;
3570 dsize /= factor;
3571 dfree /= factor;
3573 if (bsize > block_size) {
3574 uint64_t factor = bsize/block_size;
3575 bsize = block_size;
3576 dsize *= factor;
3577 dfree *= factor;
3579 sectors_per_unit = bsize/bytes_per_sector;
3581 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3582 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3583 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3586 * For large drives, return max values and not modulo.
3588 dsize = MIN(dsize, UINT32_MAX);
3589 dfree = MIN(dfree, UINT32_MAX);
3591 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3592 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3593 SIVAL(pdata,l1_cUnit,dsize);
3594 SIVAL(pdata,l1_cUnitAvail,dfree);
3595 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3596 break;
3599 case SMB_INFO_VOLUME:
3600 /* Return volume name */
3602 * Add volume serial number - hash of a combination of
3603 * the called hostname and the service name.
3605 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3607 * Win2k3 and previous mess this up by sending a name length
3608 * one byte short. I believe only older clients (OS/2 Win9x) use
3609 * this call so try fixing this by adding a terminating null to
3610 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3612 status = srvstr_push(
3613 pdata, flags2,
3614 pdata+l2_vol_szVolLabel, vname,
3615 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3616 STR_NOALIGN|STR_TERMINATE, &len);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 return status;
3620 SCVAL(pdata,l2_vol_cch,len);
3621 data_len = l2_vol_szVolLabel + len;
3622 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3623 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3624 (unsigned)len, vname));
3625 break;
3627 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3628 case SMB_FS_ATTRIBUTE_INFORMATION:
3630 additional_flags = 0;
3631 #if defined(HAVE_SYS_QUOTAS)
3632 additional_flags |= FILE_VOLUME_QUOTAS;
3633 #endif
3635 if(lp_nt_acl_support(SNUM(conn))) {
3636 additional_flags |= FILE_PERSISTENT_ACLS;
3639 /* Capabilities are filled in at connection time through STATVFS call */
3640 additional_flags |= conn->fs_capabilities;
3641 additional_flags |= lp_parm_int(conn->params->service,
3642 "share", "fake_fscaps",
3645 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3646 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3647 additional_flags); /* FS ATTRIBUTES */
3649 SIVAL(pdata,4,255); /* Max filename component length */
3650 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3651 and will think we can't do long filenames */
3652 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3653 PTR_DIFF(end_data, pdata+12),
3654 STR_UNICODE, &len);
3655 if (!NT_STATUS_IS_OK(status)) {
3656 return status;
3658 SIVAL(pdata,8,len);
3659 data_len = 12 + len;
3660 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3661 /* the client only requested a portion of the
3662 file system name */
3663 data_len = max_data_bytes;
3664 status = STATUS_BUFFER_OVERFLOW;
3666 *fixed_portion = 16;
3667 break;
3669 case SMB_QUERY_FS_LABEL_INFO:
3670 case SMB_FS_LABEL_INFORMATION:
3671 status = srvstr_push(pdata, flags2, pdata+4, vname,
3672 PTR_DIFF(end_data, pdata+4), 0, &len);
3673 if (!NT_STATUS_IS_OK(status)) {
3674 return status;
3676 data_len = 4 + len;
3677 SIVAL(pdata,0,len);
3678 break;
3680 case SMB_QUERY_FS_VOLUME_INFO:
3681 case SMB_FS_VOLUME_INFORMATION:
3684 * Add volume serial number - hash of a combination of
3685 * the called hostname and the service name.
3687 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3688 (str_checksum(get_local_machine_name())<<16));
3690 /* Max label len is 32 characters. */
3691 status = srvstr_push(pdata, flags2, pdata+18, vname,
3692 PTR_DIFF(end_data, pdata+18),
3693 STR_UNICODE, &len);
3694 if (!NT_STATUS_IS_OK(status)) {
3695 return status;
3697 SIVAL(pdata,12,len);
3698 data_len = 18+len;
3700 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3701 (int)strlen(vname),vname,
3702 lp_servicename(talloc_tos(), snum)));
3703 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3704 /* the client only requested a portion of the
3705 volume label */
3706 data_len = max_data_bytes;
3707 status = STATUS_BUFFER_OVERFLOW;
3709 *fixed_portion = 24;
3710 break;
3712 case SMB_QUERY_FS_SIZE_INFO:
3713 case SMB_FS_SIZE_INFORMATION:
3715 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3716 data_len = 24;
3717 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3718 &dfree, &dsize);
3719 if (df_ret == (uint64_t)-1) {
3720 return map_nt_error_from_unix(errno);
3722 block_size = lp_block_size(snum);
3723 if (bsize < block_size) {
3724 uint64_t factor = block_size/bsize;
3725 bsize = block_size;
3726 dsize /= factor;
3727 dfree /= factor;
3729 if (bsize > block_size) {
3730 uint64_t factor = bsize/block_size;
3731 bsize = block_size;
3732 dsize *= factor;
3733 dfree *= factor;
3735 sectors_per_unit = bsize/bytes_per_sector;
3736 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3737 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3738 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3739 SBIG_UINT(pdata,0,dsize);
3740 SBIG_UINT(pdata,8,dfree);
3741 SIVAL(pdata,16,sectors_per_unit);
3742 SIVAL(pdata,20,bytes_per_sector);
3743 *fixed_portion = 24;
3744 break;
3747 case SMB_FS_FULL_SIZE_INFORMATION:
3749 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3750 data_len = 32;
3751 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3752 &dfree, &dsize);
3753 if (df_ret == (uint64_t)-1) {
3754 return map_nt_error_from_unix(errno);
3756 block_size = lp_block_size(snum);
3757 if (bsize < block_size) {
3758 uint64_t factor = block_size/bsize;
3759 bsize = block_size;
3760 dsize /= factor;
3761 dfree /= factor;
3763 if (bsize > block_size) {
3764 uint64_t factor = bsize/block_size;
3765 bsize = block_size;
3766 dsize *= factor;
3767 dfree *= factor;
3769 sectors_per_unit = bsize/bytes_per_sector;
3770 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3771 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3772 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3773 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3774 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3775 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3776 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3777 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3778 *fixed_portion = 32;
3779 break;
3782 case SMB_QUERY_FS_DEVICE_INFO:
3783 case SMB_FS_DEVICE_INFORMATION:
3785 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3787 if (!CAN_WRITE(conn)) {
3788 characteristics |= FILE_READ_ONLY_DEVICE;
3790 data_len = 8;
3791 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3792 SIVAL(pdata,4,characteristics);
3793 *fixed_portion = 8;
3794 break;
3797 #ifdef HAVE_SYS_QUOTAS
3798 case SMB_FS_QUOTA_INFORMATION:
3800 * what we have to send --metze:
3802 * Unknown1: 24 NULL bytes
3803 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3804 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3805 * Quota Flags: 2 byte :
3806 * Unknown3: 6 NULL bytes
3808 * 48 bytes total
3810 * details for Quota Flags:
3812 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3813 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3814 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3815 * 0x0001 Enable Quotas: enable quota for this fs
3819 /* we need to fake up a fsp here,
3820 * because its not send in this call
3822 files_struct fsp;
3823 SMB_NTQUOTA_STRUCT quotas;
3825 ZERO_STRUCT(fsp);
3826 ZERO_STRUCT(quotas);
3828 fsp.conn = conn;
3829 fsp.fnum = FNUM_FIELD_INVALID;
3831 /* access check */
3832 if (get_current_uid(conn) != 0) {
3833 DEBUG(0,("get_user_quota: access_denied "
3834 "service [%s] user [%s]\n",
3835 lp_servicename(talloc_tos(), SNUM(conn)),
3836 conn->session_info->unix_info->unix_name));
3837 return NT_STATUS_ACCESS_DENIED;
3840 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3841 NULL, &quotas);
3842 if (!NT_STATUS_IS_OK(status)) {
3843 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3844 return status;
3847 data_len = 48;
3849 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3850 lp_servicename(talloc_tos(), SNUM(conn))));
3852 /* Unknown1 24 NULL bytes*/
3853 SBIG_UINT(pdata,0,(uint64_t)0);
3854 SBIG_UINT(pdata,8,(uint64_t)0);
3855 SBIG_UINT(pdata,16,(uint64_t)0);
3857 /* Default Soft Quota 8 bytes */
3858 SBIG_UINT(pdata,24,quotas.softlim);
3860 /* Default Hard Quota 8 bytes */
3861 SBIG_UINT(pdata,32,quotas.hardlim);
3863 /* Quota flag 2 bytes */
3864 SSVAL(pdata,40,quotas.qflags);
3866 /* Unknown3 6 NULL bytes */
3867 SSVAL(pdata,42,0);
3868 SIVAL(pdata,44,0);
3870 break;
3872 #endif /* HAVE_SYS_QUOTAS */
3873 case SMB_FS_OBJECTID_INFORMATION:
3875 unsigned char objid[16];
3876 struct smb_extended_info extended_info;
3877 memcpy(pdata,create_volume_objectid(conn, objid),16);
3878 samba_extended_info_version (&extended_info);
3879 SIVAL(pdata,16,extended_info.samba_magic);
3880 SIVAL(pdata,20,extended_info.samba_version);
3881 SIVAL(pdata,24,extended_info.samba_subversion);
3882 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3883 memcpy(pdata+36,extended_info.samba_version_string,28);
3884 data_len = 64;
3885 break;
3888 case SMB_FS_SECTOR_SIZE_INFORMATION:
3890 data_len = 28;
3892 * These values match a physical Windows Server 2012
3893 * share backed by NTFS atop spinning rust.
3895 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3896 /* logical_bytes_per_sector */
3897 SIVAL(pdata, 0, bytes_per_sector);
3898 /* phys_bytes_per_sector_atomic */
3899 SIVAL(pdata, 4, bytes_per_sector);
3900 /* phys_bytes_per_sector_perf */
3901 SIVAL(pdata, 8, bytes_per_sector);
3902 /* fs_effective_phys_bytes_per_sector_atomic */
3903 SIVAL(pdata, 12, bytes_per_sector);
3904 /* flags */
3905 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3906 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3907 /* byte_off_sector_align */
3908 SIVAL(pdata, 20, 0);
3909 /* byte_off_partition_align */
3910 SIVAL(pdata, 24, 0);
3911 *fixed_portion = 28;
3912 break;
3917 * Query the version and capabilities of the CIFS UNIX extensions
3918 * in use.
3921 case SMB_QUERY_CIFS_UNIX_INFO:
3923 bool large_write = lp_min_receive_file_size() &&
3924 !srv_is_signing_active(xconn);
3925 bool large_read = !srv_is_signing_active(xconn);
3926 int encrypt_caps = 0;
3928 if (!lp_unix_extensions()) {
3929 return NT_STATUS_INVALID_LEVEL;
3932 switch (conn->encrypt_level) {
3933 case SMB_SIGNING_OFF:
3934 encrypt_caps = 0;
3935 break;
3936 case SMB_SIGNING_DESIRED:
3937 case SMB_SIGNING_IF_REQUIRED:
3938 case SMB_SIGNING_DEFAULT:
3939 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3940 break;
3941 case SMB_SIGNING_REQUIRED:
3942 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3943 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3944 large_write = false;
3945 large_read = false;
3946 break;
3949 data_len = 12;
3950 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3951 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3953 /* We have POSIX ACLs, pathname, encryption,
3954 * large read/write, and locking capability. */
3956 SBIG_UINT(pdata,4,((uint64_t)(
3957 CIFS_UNIX_POSIX_ACLS_CAP|
3958 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3959 CIFS_UNIX_FCNTL_LOCKS_CAP|
3960 CIFS_UNIX_EXTATTR_CAP|
3961 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3962 encrypt_caps|
3963 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3964 (large_write ?
3965 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3966 break;
3969 case SMB_QUERY_POSIX_FS_INFO:
3971 int rc;
3972 vfs_statvfs_struct svfs;
3974 if (!lp_unix_extensions()) {
3975 return NT_STATUS_INVALID_LEVEL;
3978 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3980 if (!rc) {
3981 data_len = 56;
3982 SIVAL(pdata,0,svfs.OptimalTransferSize);
3983 SIVAL(pdata,4,svfs.BlockSize);
3984 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3985 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3986 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3987 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3988 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3989 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3990 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3991 #ifdef EOPNOTSUPP
3992 } else if (rc == EOPNOTSUPP) {
3993 return NT_STATUS_INVALID_LEVEL;
3994 #endif /* EOPNOTSUPP */
3995 } else {
3996 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3997 return NT_STATUS_DOS(ERRSRV, ERRerror);
3999 break;
4002 case SMB_QUERY_POSIX_WHOAMI:
4004 uint32_t flags = 0;
4005 uint32_t sid_bytes;
4006 int i;
4008 if (!lp_unix_extensions()) {
4009 return NT_STATUS_INVALID_LEVEL;
4012 if (max_data_bytes < 40) {
4013 return NT_STATUS_BUFFER_TOO_SMALL;
4016 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
4017 flags |= SMB_WHOAMI_GUEST;
4020 /* NOTE: 8 bytes for UID/GID, irrespective of native
4021 * platform size. This matches
4022 * SMB_QUERY_FILE_UNIX_BASIC and friends.
4024 data_len = 4 /* flags */
4025 + 4 /* flag mask */
4026 + 8 /* uid */
4027 + 8 /* gid */
4028 + 4 /* ngroups */
4029 + 4 /* num_sids */
4030 + 4 /* SID bytes */
4031 + 4 /* pad/reserved */
4032 + (conn->session_info->unix_token->ngroups * 8)
4033 /* groups list */
4034 + (conn->session_info->security_token->num_sids *
4035 SID_MAX_SIZE)
4036 /* SID list */;
4038 SIVAL(pdata, 0, flags);
4039 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
4040 SBIG_UINT(pdata, 8,
4041 (uint64_t)conn->session_info->unix_token->uid);
4042 SBIG_UINT(pdata, 16,
4043 (uint64_t)conn->session_info->unix_token->gid);
4046 if (data_len >= max_data_bytes) {
4047 /* Potential overflow, skip the GIDs and SIDs. */
4049 SIVAL(pdata, 24, 0); /* num_groups */
4050 SIVAL(pdata, 28, 0); /* num_sids */
4051 SIVAL(pdata, 32, 0); /* num_sid_bytes */
4052 SIVAL(pdata, 36, 0); /* reserved */
4054 data_len = 40;
4055 break;
4058 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
4059 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
4061 /* We walk the SID list twice, but this call is fairly
4062 * infrequent, and I don't expect that it's performance
4063 * sensitive -- jpeach
4065 for (i = 0, sid_bytes = 0;
4066 i < conn->session_info->security_token->num_sids; ++i) {
4067 sid_bytes += ndr_size_dom_sid(
4068 &conn->session_info->security_token->sids[i],
4072 /* SID list byte count */
4073 SIVAL(pdata, 32, sid_bytes);
4075 /* 4 bytes pad/reserved - must be zero */
4076 SIVAL(pdata, 36, 0);
4077 data_len = 40;
4079 /* GID list */
4080 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4081 SBIG_UINT(pdata, data_len,
4082 (uint64_t)conn->session_info->unix_token->groups[i]);
4083 data_len += 8;
4086 /* SID list */
4087 for (i = 0;
4088 i < conn->session_info->security_token->num_sids; ++i) {
4089 int sid_len = ndr_size_dom_sid(
4090 &conn->session_info->security_token->sids[i],
4093 sid_linearize((uint8_t *)(pdata + data_len),
4094 sid_len,
4095 &conn->session_info->security_token->sids[i]);
4096 data_len += sid_len;
4099 break;
4102 case SMB_MAC_QUERY_FS_INFO:
4104 * Thursby MAC extension... ONLY on NTFS filesystems
4105 * once we do streams then we don't need this
4107 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4108 data_len = 88;
4109 SIVAL(pdata,84,0x100); /* Don't support mac... */
4110 break;
4113 FALL_THROUGH;
4114 default:
4115 return NT_STATUS_INVALID_LEVEL;
4118 *ret_data_len = data_len;
4119 return status;
4122 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4123 struct smb_request *req,
4124 files_struct *fsp,
4125 const DATA_BLOB *qdata)
4127 NTSTATUS status;
4128 SMB_NTQUOTA_STRUCT quotas;
4130 ZERO_STRUCT(quotas);
4132 /* access check */
4133 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4134 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4135 lp_servicename(talloc_tos(), SNUM(conn)),
4136 conn->session_info->unix_info->unix_name));
4137 return NT_STATUS_ACCESS_DENIED;
4140 if (!check_fsp_ntquota_handle(conn, req,
4141 fsp)) {
4142 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4143 return NT_STATUS_INVALID_HANDLE;
4146 /* note: normally there're 48 bytes,
4147 * but we didn't use the last 6 bytes for now
4148 * --metze
4150 if (qdata->length < 42) {
4151 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4152 (unsigned int)qdata->length));
4153 return NT_STATUS_INVALID_PARAMETER;
4156 /* unknown_1 24 NULL bytes in pdata*/
4158 /* the soft quotas 8 bytes (uint64_t)*/
4159 quotas.softlim = BVAL(qdata->data,24);
4161 /* the hard quotas 8 bytes (uint64_t)*/
4162 quotas.hardlim = BVAL(qdata->data,32);
4164 /* quota_flags 2 bytes **/
4165 quotas.qflags = SVAL(qdata->data,40);
4167 /* unknown_2 6 NULL bytes follow*/
4169 /* now set the quotas */
4170 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4171 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4172 lp_servicename(talloc_tos(), SNUM(conn))));
4173 status = map_nt_error_from_unix(errno);
4174 } else {
4175 status = NT_STATUS_OK;
4177 return status;
4180 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4181 struct smb_request *req,
4182 TALLOC_CTX *mem_ctx,
4183 uint16_t info_level,
4184 files_struct *fsp,
4185 const DATA_BLOB *pdata)
4187 switch (info_level) {
4188 case SMB_FS_QUOTA_INFORMATION:
4190 return smb_set_fsquota(conn,
4191 req,
4192 fsp,
4193 pdata);
4196 default:
4197 break;
4199 return NT_STATUS_INVALID_LEVEL;
4202 /****************************************************************************
4203 Reply to a TRANS2_QFSINFO (query filesystem info).
4204 ****************************************************************************/
4206 static void call_trans2qfsinfo(connection_struct *conn,
4207 struct smb_request *req,
4208 char **pparams, int total_params,
4209 char **ppdata, int total_data,
4210 unsigned int max_data_bytes)
4212 char *params = *pparams;
4213 uint16_t info_level;
4214 int data_len = 0;
4215 size_t fixed_portion;
4216 NTSTATUS status;
4218 if (total_params < 2) {
4219 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4220 return;
4223 info_level = SVAL(params,0);
4225 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4226 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4227 DEBUG(0,("call_trans2qfsinfo: encryption required "
4228 "and info level 0x%x sent.\n",
4229 (unsigned int)info_level));
4230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4231 return;
4235 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4237 status = smbd_do_qfsinfo(req->xconn, conn, req,
4238 info_level,
4239 req->flags2,
4240 max_data_bytes,
4241 &fixed_portion,
4242 NULL,
4243 ppdata, &data_len);
4244 if (!NT_STATUS_IS_OK(status)) {
4245 reply_nterror(req, status);
4246 return;
4249 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4250 max_data_bytes);
4252 DEBUG( 4, ( "%s info_level = %d\n",
4253 smb_fn_name(req->cmd), info_level) );
4255 return;
4258 /****************************************************************************
4259 Reply to a TRANS2_SETFSINFO (set filesystem info).
4260 ****************************************************************************/
4262 static void call_trans2setfsinfo(connection_struct *conn,
4263 struct smb_request *req,
4264 char **pparams, int total_params,
4265 char **ppdata, int total_data,
4266 unsigned int max_data_bytes)
4268 struct smbXsrv_connection *xconn = req->xconn;
4269 char *pdata = *ppdata;
4270 char *params = *pparams;
4271 uint16_t info_level;
4273 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4274 lp_servicename(talloc_tos(), SNUM(conn))));
4276 /* */
4277 if (total_params < 4) {
4278 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4279 total_params));
4280 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4281 return;
4284 info_level = SVAL(params,2);
4286 if (IS_IPC(conn)) {
4287 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4288 info_level != SMB_SET_CIFS_UNIX_INFO) {
4289 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4290 "info level (0x%x) on IPC$.\n",
4291 (unsigned int)info_level));
4292 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4293 return;
4297 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4298 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4299 DEBUG(0,("call_trans2setfsinfo: encryption required "
4300 "and info level 0x%x sent.\n",
4301 (unsigned int)info_level));
4302 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4303 return;
4307 switch(info_level) {
4308 case SMB_SET_CIFS_UNIX_INFO:
4309 if (!lp_unix_extensions()) {
4310 DEBUG(2,("call_trans2setfsinfo: "
4311 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4312 "unix extensions off\n"));
4313 reply_nterror(req,
4314 NT_STATUS_INVALID_LEVEL);
4315 return;
4318 /* There should be 12 bytes of capabilities set. */
4319 if (total_data < 12) {
4320 reply_nterror(
4321 req,
4322 NT_STATUS_INVALID_PARAMETER);
4323 return;
4325 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4326 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4327 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4328 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4329 /* Just print these values for now. */
4330 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4331 "major = %u, minor = %u cap_low = 0x%x, "
4332 "cap_high = 0x%xn",
4333 (unsigned int)xconn->
4334 smb1.unix_info.client_major,
4335 (unsigned int)xconn->
4336 smb1.unix_info.client_minor,
4337 (unsigned int)xconn->
4338 smb1.unix_info.client_cap_low,
4339 (unsigned int)xconn->
4340 smb1.unix_info.client_cap_high));
4342 /* Here is where we must switch to posix pathname processing... */
4343 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4344 lp_set_posix_pathnames();
4345 mangle_change_to_posix();
4348 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4349 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4350 /* Client that knows how to do posix locks,
4351 * but not posix open/mkdir operations. Set a
4352 * default type for read/write checks. */
4354 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4357 break;
4359 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4361 NTSTATUS status;
4362 size_t param_len = 0;
4363 size_t data_len = total_data;
4365 if (!lp_unix_extensions()) {
4366 reply_nterror(
4367 req,
4368 NT_STATUS_INVALID_LEVEL);
4369 return;
4372 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4373 reply_nterror(
4374 req,
4375 NT_STATUS_NOT_SUPPORTED);
4376 return;
4379 if (xconn->smb1.echo_handler.trusted_fde) {
4380 DEBUG( 2,("call_trans2setfsinfo: "
4381 "request transport encryption disabled"
4382 "with 'fork echo handler = yes'\n"));
4383 reply_nterror(
4384 req,
4385 NT_STATUS_NOT_SUPPORTED);
4386 return;
4389 DEBUG( 4,("call_trans2setfsinfo: "
4390 "request transport encryption.\n"));
4392 status = srv_request_encryption_setup(conn,
4393 (unsigned char **)ppdata,
4394 &data_len,
4395 (unsigned char **)pparams,
4396 &param_len);
4398 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4399 !NT_STATUS_IS_OK(status)) {
4400 reply_nterror(req, status);
4401 return;
4404 send_trans2_replies(conn, req,
4405 NT_STATUS_OK,
4406 *pparams,
4407 param_len,
4408 *ppdata,
4409 data_len,
4410 max_data_bytes);
4412 if (NT_STATUS_IS_OK(status)) {
4413 /* Server-side transport
4414 * encryption is now *on*. */
4415 status = srv_encryption_start(conn);
4416 if (!NT_STATUS_IS_OK(status)) {
4417 char *reason = talloc_asprintf(talloc_tos(),
4418 "Failure in setting "
4419 "up encrypted transport: %s",
4420 nt_errstr(status));
4421 exit_server_cleanly(reason);
4424 return;
4427 case SMB_FS_QUOTA_INFORMATION:
4429 NTSTATUS status;
4430 DATA_BLOB qdata = {
4431 .data = (uint8_t *)pdata,
4432 .length = total_data
4434 files_struct *fsp = NULL;
4435 fsp = file_fsp(req, SVAL(params,0));
4437 status = smb_set_fsquota(conn,
4438 req,
4439 fsp,
4440 &qdata);
4441 if (!NT_STATUS_IS_OK(status)) {
4442 reply_nterror(req, status);
4443 return;
4445 break;
4447 default:
4448 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4449 info_level));
4450 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4451 return;
4452 break;
4456 * sending this reply works fine,
4457 * but I'm not sure it's the same
4458 * like windows do...
4459 * --metze
4461 reply_outbuf(req, 10, 0);
4464 #if defined(HAVE_POSIX_ACLS)
4465 /****************************************************************************
4466 Utility function to count the number of entries in a POSIX acl.
4467 ****************************************************************************/
4469 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4471 unsigned int ace_count = 0;
4472 int entry_id = SMB_ACL_FIRST_ENTRY;
4473 SMB_ACL_ENTRY_T entry;
4475 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4476 /* get_next... */
4477 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4478 entry_id = SMB_ACL_NEXT_ENTRY;
4480 ace_count++;
4482 return ace_count;
4485 /****************************************************************************
4486 Utility function to marshall a POSIX acl into wire format.
4487 ****************************************************************************/
4489 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4491 int entry_id = SMB_ACL_FIRST_ENTRY;
4492 SMB_ACL_ENTRY_T entry;
4494 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4495 SMB_ACL_TAG_T tagtype;
4496 SMB_ACL_PERMSET_T permset;
4497 unsigned char perms = 0;
4498 unsigned int own_grp;
4500 /* get_next... */
4501 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4502 entry_id = SMB_ACL_NEXT_ENTRY;
4505 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4506 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4507 return False;
4510 if (sys_acl_get_permset(entry, &permset) == -1) {
4511 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4512 return False;
4515 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4516 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4517 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4519 SCVAL(pdata,1,perms);
4521 switch (tagtype) {
4522 case SMB_ACL_USER_OBJ:
4523 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4524 own_grp = (unsigned int)pst->st_ex_uid;
4525 SIVAL(pdata,2,own_grp);
4526 SIVAL(pdata,6,0);
4527 break;
4528 case SMB_ACL_USER:
4530 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4531 if (!puid) {
4532 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4533 return False;
4535 own_grp = (unsigned int)*puid;
4536 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4537 SIVAL(pdata,2,own_grp);
4538 SIVAL(pdata,6,0);
4539 break;
4541 case SMB_ACL_GROUP_OBJ:
4542 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4543 own_grp = (unsigned int)pst->st_ex_gid;
4544 SIVAL(pdata,2,own_grp);
4545 SIVAL(pdata,6,0);
4546 break;
4547 case SMB_ACL_GROUP:
4549 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4550 if (!pgid) {
4551 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4552 return False;
4554 own_grp = (unsigned int)*pgid;
4555 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4556 SIVAL(pdata,2,own_grp);
4557 SIVAL(pdata,6,0);
4558 break;
4560 case SMB_ACL_MASK:
4561 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4562 SIVAL(pdata,2,0xFFFFFFFF);
4563 SIVAL(pdata,6,0xFFFFFFFF);
4564 break;
4565 case SMB_ACL_OTHER:
4566 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4567 SIVAL(pdata,2,0xFFFFFFFF);
4568 SIVAL(pdata,6,0xFFFFFFFF);
4569 break;
4570 default:
4571 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4572 return False;
4574 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4577 return True;
4579 #endif
4581 /****************************************************************************
4582 Store the FILE_UNIX_BASIC info.
4583 ****************************************************************************/
4585 static char *store_file_unix_basic(connection_struct *conn,
4586 char *pdata,
4587 files_struct *fsp,
4588 const SMB_STRUCT_STAT *psbuf)
4590 dev_t devno;
4592 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4593 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4595 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4596 pdata += 8;
4598 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4599 pdata += 8;
4601 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4602 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4603 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4604 pdata += 24;
4606 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4607 SIVAL(pdata,4,0);
4608 pdata += 8;
4610 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4611 SIVAL(pdata,4,0);
4612 pdata += 8;
4614 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4615 pdata += 4;
4617 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4618 devno = psbuf->st_ex_rdev;
4619 } else {
4620 devno = psbuf->st_ex_dev;
4623 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4624 SIVAL(pdata,4,0);
4625 pdata += 8;
4627 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4628 SIVAL(pdata,4,0);
4629 pdata += 8;
4631 SINO_T_VAL(pdata, 0, psbuf->st_ex_ino); /* inode number */
4632 pdata += 8;
4634 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4635 SIVAL(pdata,4,0);
4636 pdata += 8;
4638 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4639 SIVAL(pdata,4,0);
4640 pdata += 8;
4642 return pdata;
4645 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4646 * the chflags(2) (or equivalent) flags.
4648 * XXX: this really should be behind the VFS interface. To do this, we would
4649 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4650 * Each VFS module could then implement its own mapping as appropriate for the
4651 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4653 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4654 info2_flags_map[] =
4656 #ifdef UF_NODUMP
4657 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4658 #endif
4660 #ifdef UF_IMMUTABLE
4661 { UF_IMMUTABLE, EXT_IMMUTABLE },
4662 #endif
4664 #ifdef UF_APPEND
4665 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4666 #endif
4668 #ifdef UF_HIDDEN
4669 { UF_HIDDEN, EXT_HIDDEN },
4670 #endif
4672 /* Do not remove. We need to guarantee that this array has at least one
4673 * entry to build on HP-UX.
4675 { 0, 0 }
4679 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4680 uint32_t *smb_fflags, uint32_t *smb_fmask)
4682 int i;
4684 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4685 *smb_fmask |= info2_flags_map[i].smb_fflag;
4686 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4687 *smb_fflags |= info2_flags_map[i].smb_fflag;
4692 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4693 const uint32_t smb_fflags,
4694 const uint32_t smb_fmask,
4695 int *stat_fflags)
4697 uint32_t max_fmask = 0;
4698 int i;
4700 *stat_fflags = psbuf->st_ex_flags;
4702 /* For each flags requested in smb_fmask, check the state of the
4703 * corresponding flag in smb_fflags and set or clear the matching
4704 * stat flag.
4707 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4708 max_fmask |= info2_flags_map[i].smb_fflag;
4709 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4710 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4711 *stat_fflags |= info2_flags_map[i].stat_fflag;
4712 } else {
4713 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4718 /* If smb_fmask is asking to set any bits that are not supported by
4719 * our flag mappings, we should fail.
4721 if ((smb_fmask & max_fmask) != smb_fmask) {
4722 return False;
4725 return True;
4729 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4730 * of file flags and birth (create) time.
4732 static char *store_file_unix_basic_info2(connection_struct *conn,
4733 char *pdata,
4734 files_struct *fsp,
4735 const SMB_STRUCT_STAT *psbuf)
4737 uint32_t file_flags = 0;
4738 uint32_t flags_mask = 0;
4740 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4742 /* Create (birth) time 64 bit */
4743 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4744 pdata += 8;
4746 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4747 SIVAL(pdata, 0, file_flags); /* flags */
4748 SIVAL(pdata, 4, flags_mask); /* mask */
4749 pdata += 8;
4751 return pdata;
4754 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4755 const struct stream_struct *streams,
4756 char *data,
4757 unsigned int max_data_bytes,
4758 unsigned int *data_size)
4760 unsigned int i;
4761 unsigned int ofs = 0;
4763 if (max_data_bytes < 32) {
4764 return NT_STATUS_INFO_LENGTH_MISMATCH;
4767 for (i = 0; i < num_streams; i++) {
4768 unsigned int next_offset;
4769 size_t namelen;
4770 smb_ucs2_t *namebuf;
4772 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4773 streams[i].name, &namelen) ||
4774 namelen <= 2)
4776 return NT_STATUS_INVALID_PARAMETER;
4780 * name_buf is now null-terminated, we need to marshall as not
4781 * terminated
4784 namelen -= 2;
4787 * We cannot overflow ...
4789 if ((ofs + 24 + namelen) > max_data_bytes) {
4790 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4791 i));
4792 TALLOC_FREE(namebuf);
4793 return STATUS_BUFFER_OVERFLOW;
4796 SIVAL(data, ofs+4, namelen);
4797 SOFF_T(data, ofs+8, streams[i].size);
4798 SOFF_T(data, ofs+16, streams[i].alloc_size);
4799 memcpy(data+ofs+24, namebuf, namelen);
4800 TALLOC_FREE(namebuf);
4802 next_offset = ofs + 24 + namelen;
4804 if (i == num_streams-1) {
4805 SIVAL(data, ofs, 0);
4807 else {
4808 unsigned int align = ndr_align_size(next_offset, 8);
4810 if ((next_offset + align) > max_data_bytes) {
4811 DEBUG(10, ("refusing to overflow align "
4812 "reply at stream %u\n",
4813 i));
4814 TALLOC_FREE(namebuf);
4815 return STATUS_BUFFER_OVERFLOW;
4818 memset(data+next_offset, 0, align);
4819 next_offset += align;
4821 SIVAL(data, ofs, next_offset - ofs);
4822 ofs = next_offset;
4825 ofs = next_offset;
4828 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4830 *data_size = ofs;
4832 return NT_STATUS_OK;
4835 #if defined(HAVE_POSIX_ACLS)
4836 static NTSTATUS smb_query_posix_acl(connection_struct *conn,
4837 struct smb_request *req,
4838 files_struct *fsp,
4839 struct smb_filename *smb_fname,
4840 char *pdata,
4841 unsigned int data_size_in,
4842 unsigned int *pdata_size_out)
4844 SMB_ACL_T file_acl = NULL;
4845 SMB_ACL_T def_acl = NULL;
4846 uint16_t num_file_acls = 0;
4847 uint16_t num_def_acls = 0;
4848 unsigned int size_needed = 0;
4849 NTSTATUS status;
4850 bool ok;
4851 bool close_fsp;
4854 * Ensure we always operate on a file descriptor, not just
4855 * the filename.
4857 if (fsp == NULL) {
4858 uint32_t access_mask = SEC_STD_READ_CONTROL|
4859 FILE_READ_ATTRIBUTES|
4860 FILE_WRITE_ATTRIBUTES;
4862 status = get_posix_fsp(conn,
4863 req,
4864 smb_fname,
4865 access_mask,
4866 &fsp);
4868 if (!NT_STATUS_IS_OK(status)) {
4869 goto out;
4871 close_fsp = true;
4874 SMB_ASSERT(fsp != NULL);
4876 status = refuse_symlink(conn,
4877 fsp,
4878 fsp->fsp_name);
4879 if (!NT_STATUS_IS_OK(status)) {
4880 goto out;
4883 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
4884 talloc_tos());
4886 if (file_acl == NULL && no_acl_syscall_error(errno)) {
4887 DBG_INFO("ACLs not implemented on "
4888 "filesystem containing %s\n",
4889 fsp_str_dbg(fsp));
4890 status = NT_STATUS_NOT_IMPLEMENTED;
4891 goto out;
4894 if (S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
4896 * We can only have default POSIX ACLs on
4897 * directories.
4899 if (!fsp->is_directory) {
4900 DBG_INFO("Non-directory open %s\n",
4901 fsp_str_dbg(fsp));
4902 status = NT_STATUS_INVALID_HANDLE;
4903 goto out;
4905 def_acl = SMB_VFS_SYS_ACL_GET_FILE(conn,
4906 fsp->fsp_name,
4907 SMB_ACL_TYPE_DEFAULT,
4908 talloc_tos());
4909 def_acl = free_empty_sys_acl(conn, def_acl);
4912 num_file_acls = count_acl_entries(conn, file_acl);
4913 num_def_acls = count_acl_entries(conn, def_acl);
4915 /* Wrap checks. */
4916 if (num_file_acls + num_def_acls < num_file_acls) {
4917 status = NT_STATUS_INVALID_PARAMETER;
4918 goto out;
4921 size_needed = num_file_acls + num_def_acls;
4924 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
4925 * than UINT_MAX, so check by division.
4927 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
4928 status = NT_STATUS_INVALID_PARAMETER;
4929 goto out;
4932 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
4933 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
4934 status = NT_STATUS_INVALID_PARAMETER;
4935 goto out;
4937 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
4939 if ( data_size_in < size_needed) {
4940 DBG_INFO("data_size too small (%u) need %u\n",
4941 data_size_in,
4942 size_needed);
4943 status = NT_STATUS_BUFFER_TOO_SMALL;
4944 goto out;
4947 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
4948 SSVAL(pdata,2,num_file_acls);
4949 SSVAL(pdata,4,num_def_acls);
4950 pdata += SMB_POSIX_ACL_HEADER_SIZE;
4952 ok = marshall_posix_acl(conn,
4953 pdata,
4954 &fsp->fsp_name->st,
4955 file_acl);
4956 if (!ok) {
4957 status = NT_STATUS_INTERNAL_ERROR;
4958 goto out;
4960 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
4962 ok = marshall_posix_acl(conn,
4963 pdata,
4964 &fsp->fsp_name->st,
4965 def_acl);
4966 if (!ok) {
4967 status = NT_STATUS_INTERNAL_ERROR;
4968 goto out;
4971 *pdata_size_out = size_needed;
4972 status = NT_STATUS_OK;
4974 out:
4976 if (close_fsp) {
4978 * Ensure the stat struct in smb_fname is up to
4979 * date. Structure copy.
4981 smb_fname->st = fsp->fsp_name->st;
4982 (void)close_file(req, fsp, NORMAL_CLOSE);
4983 fsp = NULL;
4986 TALLOC_FREE(file_acl);
4987 TALLOC_FREE(def_acl);
4988 return status;
4990 #endif
4992 /****************************************************************************
4993 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4994 ****************************************************************************/
4996 static void call_trans2qpipeinfo(connection_struct *conn,
4997 struct smb_request *req,
4998 unsigned int tran_call,
4999 char **pparams, int total_params,
5000 char **ppdata, int total_data,
5001 unsigned int max_data_bytes)
5003 char *params = *pparams;
5004 char *pdata = *ppdata;
5005 unsigned int data_size = 0;
5006 unsigned int param_size = 2;
5007 uint16_t info_level;
5008 files_struct *fsp;
5010 if (!params) {
5011 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5012 return;
5015 if (total_params < 4) {
5016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5017 return;
5020 fsp = file_fsp(req, SVAL(params,0));
5021 if (!fsp_is_np(fsp)) {
5022 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5023 return;
5026 info_level = SVAL(params,2);
5028 *pparams = (char *)SMB_REALLOC(*pparams,2);
5029 if (*pparams == NULL) {
5030 reply_nterror(req, NT_STATUS_NO_MEMORY);
5031 return;
5033 params = *pparams;
5034 SSVAL(params,0,0);
5035 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5036 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5037 return;
5039 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5040 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5041 if (*ppdata == NULL ) {
5042 reply_nterror(req, NT_STATUS_NO_MEMORY);
5043 return;
5045 pdata = *ppdata;
5047 switch (info_level) {
5048 case SMB_FILE_STANDARD_INFORMATION:
5049 memset(pdata,0,24);
5050 SOFF_T(pdata,0,4096LL);
5051 SIVAL(pdata,16,1);
5052 SIVAL(pdata,20,1);
5053 data_size = 24;
5054 break;
5056 default:
5057 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5058 return;
5061 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
5062 max_data_bytes);
5064 return;
5067 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
5068 TALLOC_CTX *mem_ctx,
5069 struct smb_request *req,
5070 uint16_t info_level,
5071 files_struct *fsp,
5072 struct smb_filename *smb_fname,
5073 bool delete_pending,
5074 struct timespec write_time_ts,
5075 struct ea_list *ea_list,
5076 int lock_data_count,
5077 char *lock_data,
5078 uint16_t flags2,
5079 unsigned int max_data_bytes,
5080 size_t *fixed_portion,
5081 char **ppdata,
5082 unsigned int *pdata_size)
5084 char *pdata = *ppdata;
5085 char *dstart, *dend;
5086 unsigned int data_size;
5087 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
5088 time_t create_time, mtime, atime, c_time;
5089 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
5090 char *p;
5091 char *base_name;
5092 char *dos_fname;
5093 int mode;
5094 int nlink;
5095 NTSTATUS status;
5096 uint64_t file_size = 0;
5097 uint64_t pos = 0;
5098 uint64_t allocation_size = 0;
5099 uint64_t file_id = 0;
5100 uint32_t access_mask = 0;
5101 size_t len = 0;
5103 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5104 return NT_STATUS_INVALID_LEVEL;
5107 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
5108 smb_fname_str_dbg(smb_fname),
5109 fsp_fnum_dbg(fsp),
5110 info_level, max_data_bytes));
5112 mode = dos_mode(conn, smb_fname);
5113 nlink = psbuf->st_ex_nlink;
5115 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
5116 nlink = 1;
5119 if ((nlink > 0) && delete_pending) {
5120 nlink -= 1;
5123 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
5124 return NT_STATUS_INVALID_PARAMETER;
5127 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
5128 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
5129 if (*ppdata == NULL) {
5130 return NT_STATUS_NO_MEMORY;
5132 pdata = *ppdata;
5133 dstart = pdata;
5134 dend = dstart + data_size - 1;
5136 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
5137 update_stat_ex_mtime(psbuf, write_time_ts);
5140 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
5141 mtime_ts = psbuf->st_ex_mtime;
5142 atime_ts = psbuf->st_ex_atime;
5143 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
5145 if (lp_dos_filetime_resolution(SNUM(conn))) {
5146 dos_filetime_timespec(&create_time_ts);
5147 dos_filetime_timespec(&mtime_ts);
5148 dos_filetime_timespec(&atime_ts);
5149 dos_filetime_timespec(&ctime_ts);
5152 create_time = convert_timespec_to_time_t(create_time_ts);
5153 mtime = convert_timespec_to_time_t(mtime_ts);
5154 atime = convert_timespec_to_time_t(atime_ts);
5155 c_time = convert_timespec_to_time_t(ctime_ts);
5157 p = strrchr_m(smb_fname->base_name,'/');
5158 if (!p)
5159 base_name = smb_fname->base_name;
5160 else
5161 base_name = p+1;
5163 /* NT expects the name to be in an exact form of the *full*
5164 filename. See the trans2 torture test */
5165 if (ISDOT(base_name)) {
5166 dos_fname = talloc_strdup(mem_ctx, "\\");
5167 if (!dos_fname) {
5168 return NT_STATUS_NO_MEMORY;
5170 } else {
5171 dos_fname = talloc_asprintf(mem_ctx,
5172 "\\%s",
5173 smb_fname->base_name);
5174 if (!dos_fname) {
5175 return NT_STATUS_NO_MEMORY;
5177 if (is_ntfs_stream_smb_fname(smb_fname)) {
5178 dos_fname = talloc_asprintf(dos_fname, "%s",
5179 smb_fname->stream_name);
5180 if (!dos_fname) {
5181 return NT_STATUS_NO_MEMORY;
5185 string_replace(dos_fname, '/', '\\');
5188 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
5190 if (!fsp) {
5191 /* Do we have this path open ? */
5192 files_struct *fsp1;
5193 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
5194 fsp1 = file_find_di_first(conn->sconn, fileid);
5195 if (fsp1 && fsp1->initial_allocation_size) {
5196 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
5200 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
5201 file_size = get_file_size_stat(psbuf);
5204 if (fsp) {
5205 pos = fsp->fh->position_information;
5208 if (fsp) {
5209 access_mask = fsp->access_mask;
5210 } else {
5211 /* GENERIC_EXECUTE mapping from Windows */
5212 access_mask = 0x12019F;
5215 /* This should be an index number - looks like
5216 dev/ino to me :-)
5218 I think this causes us to fail the IFSKIT
5219 BasicFileInformationTest. -tpot */
5220 file_id = SMB_VFS_FS_FILE_ID(conn, psbuf);
5222 *fixed_portion = 0;
5224 switch (info_level) {
5225 case SMB_INFO_STANDARD:
5226 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5227 data_size = 22;
5228 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5229 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5230 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5231 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5232 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5233 SSVAL(pdata,l1_attrFile,mode);
5234 break;
5236 case SMB_INFO_QUERY_EA_SIZE:
5238 unsigned int ea_size =
5239 estimate_ea_size(conn, fsp,
5240 smb_fname);
5241 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5242 data_size = 26;
5243 srv_put_dos_date2(pdata,0,create_time);
5244 srv_put_dos_date2(pdata,4,atime);
5245 srv_put_dos_date2(pdata,8,mtime); /* write time */
5246 SIVAL(pdata,12,(uint32_t)file_size);
5247 SIVAL(pdata,16,(uint32_t)allocation_size);
5248 SSVAL(pdata,20,mode);
5249 SIVAL(pdata,22,ea_size);
5250 break;
5253 case SMB_INFO_IS_NAME_VALID:
5254 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5255 if (fsp) {
5256 /* os/2 needs this ? really ?*/
5257 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5259 /* This is only reached for qpathinfo */
5260 data_size = 0;
5261 break;
5263 case SMB_INFO_QUERY_EAS_FROM_LIST:
5265 size_t total_ea_len = 0;
5266 struct ea_list *ea_file_list = NULL;
5267 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5269 status =
5270 get_ea_list_from_file(mem_ctx, conn, fsp,
5271 smb_fname,
5272 &total_ea_len, &ea_file_list);
5273 if (!NT_STATUS_IS_OK(status)) {
5274 return status;
5277 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5279 if (!ea_list || (total_ea_len > data_size)) {
5280 data_size = 4;
5281 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5282 break;
5285 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5286 break;
5289 case SMB_INFO_QUERY_ALL_EAS:
5291 /* We have data_size bytes to put EA's into. */
5292 size_t total_ea_len = 0;
5293 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5295 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5296 smb_fname,
5297 &total_ea_len, &ea_list);
5298 if (!NT_STATUS_IS_OK(status)) {
5299 return status;
5302 if (!ea_list || (total_ea_len > data_size)) {
5303 data_size = 4;
5304 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5305 break;
5308 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5309 break;
5312 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5314 /* This is FileFullEaInformation - 0xF which maps to
5315 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5317 /* We have data_size bytes to put EA's into. */
5318 size_t total_ea_len = 0;
5319 struct ea_list *ea_file_list = NULL;
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5323 /*TODO: add filtering and index handling */
5325 status =
5326 get_ea_list_from_file(mem_ctx, conn, fsp,
5327 smb_fname,
5328 &total_ea_len, &ea_file_list);
5329 if (!NT_STATUS_IS_OK(status)) {
5330 return status;
5332 if (!ea_file_list) {
5333 return NT_STATUS_NO_EAS_ON_FILE;
5336 status = fill_ea_chained_buffer(mem_ctx,
5337 pdata,
5338 data_size,
5339 &data_size,
5340 conn, ea_file_list);
5341 if (!NT_STATUS_IS_OK(status)) {
5342 return status;
5344 break;
5347 case SMB_FILE_BASIC_INFORMATION:
5348 case SMB_QUERY_FILE_BASIC_INFO:
5350 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5351 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5352 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5353 } else {
5354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5355 data_size = 40;
5356 SIVAL(pdata,36,0);
5358 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5359 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5360 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5361 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5362 SIVAL(pdata,32,mode);
5364 DEBUG(5,("SMB_QFBI - "));
5365 DEBUG(5,("create: %s ", ctime(&create_time)));
5366 DEBUG(5,("access: %s ", ctime(&atime)));
5367 DEBUG(5,("write: %s ", ctime(&mtime)));
5368 DEBUG(5,("change: %s ", ctime(&c_time)));
5369 DEBUG(5,("mode: %x\n", mode));
5370 *fixed_portion = data_size;
5371 break;
5373 case SMB_FILE_STANDARD_INFORMATION:
5374 case SMB_QUERY_FILE_STANDARD_INFO:
5376 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5377 data_size = 24;
5378 SOFF_T(pdata,0,allocation_size);
5379 SOFF_T(pdata,8,file_size);
5380 SIVAL(pdata,16,nlink);
5381 SCVAL(pdata,20,delete_pending?1:0);
5382 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5383 SSVAL(pdata,22,0); /* Padding. */
5384 *fixed_portion = 24;
5385 break;
5387 case SMB_FILE_EA_INFORMATION:
5388 case SMB_QUERY_FILE_EA_INFO:
5390 unsigned int ea_size =
5391 estimate_ea_size(conn, fsp, smb_fname);
5392 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5393 data_size = 4;
5394 *fixed_portion = 4;
5395 SIVAL(pdata,0,ea_size);
5396 break;
5399 /* Get the 8.3 name - used if NT SMB was negotiated. */
5400 case SMB_QUERY_FILE_ALT_NAME_INFO:
5401 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5403 char mangled_name[13];
5404 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5405 if (!name_to_8_3(base_name,mangled_name,
5406 True,conn->params)) {
5407 return NT_STATUS_NO_MEMORY;
5409 status = srvstr_push(dstart, flags2,
5410 pdata+4, mangled_name,
5411 PTR_DIFF(dend, pdata+4),
5412 STR_UNICODE, &len);
5413 if (!NT_STATUS_IS_OK(status)) {
5414 return status;
5416 data_size = 4 + len;
5417 SIVAL(pdata,0,len);
5418 *fixed_portion = 8;
5419 break;
5422 case SMB_QUERY_FILE_NAME_INFO:
5425 this must be *exactly* right for ACLs on mapped drives to work
5427 status = srvstr_push(dstart, flags2,
5428 pdata+4, dos_fname,
5429 PTR_DIFF(dend, pdata+4),
5430 STR_UNICODE, &len);
5431 if (!NT_STATUS_IS_OK(status)) {
5432 return status;
5434 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5435 data_size = 4 + len;
5436 SIVAL(pdata,0,len);
5437 break;
5440 case SMB_FILE_NORMALIZED_NAME_INFORMATION:
5442 char *nfname = NULL;
5444 if (!fsp->conn->sconn->using_smb2) {
5445 return NT_STATUS_INVALID_LEVEL;
5448 nfname = talloc_strdup(mem_ctx, smb_fname->base_name);
5449 if (nfname == NULL) {
5450 return NT_STATUS_NO_MEMORY;
5453 if (ISDOT(nfname)) {
5454 nfname[0] = '\0';
5456 string_replace(nfname, '/', '\\');
5458 if (smb_fname->stream_name != NULL) {
5459 const char *s = smb_fname->stream_name;
5460 const char *e = NULL;
5461 size_t n;
5463 SMB_ASSERT(s[0] != '\0');
5466 * smb_fname->stream_name is in form
5467 * of ':StrEam:$DATA', but we should only
5468 * append ':StrEam' here.
5471 e = strchr(&s[1], ':');
5472 if (e == NULL) {
5473 n = strlen(s);
5474 } else {
5475 n = PTR_DIFF(e, s);
5477 nfname = talloc_strndup_append(nfname, s, n);
5478 if (nfname == NULL) {
5479 return NT_STATUS_NO_MEMORY;
5483 status = srvstr_push(dstart, flags2,
5484 pdata+4, nfname,
5485 PTR_DIFF(dend, pdata+4),
5486 STR_UNICODE, &len);
5487 if (!NT_STATUS_IS_OK(status)) {
5488 return status;
5490 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NORMALIZED_NAME_INFORMATION\n"));
5491 data_size = 4 + len;
5492 SIVAL(pdata,0,len);
5493 *fixed_portion = 8;
5494 break;
5497 case SMB_FILE_ALLOCATION_INFORMATION:
5498 case SMB_QUERY_FILE_ALLOCATION_INFO:
5499 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5500 data_size = 8;
5501 SOFF_T(pdata,0,allocation_size);
5502 break;
5504 case SMB_FILE_END_OF_FILE_INFORMATION:
5505 case SMB_QUERY_FILE_END_OF_FILEINFO:
5506 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5507 data_size = 8;
5508 SOFF_T(pdata,0,file_size);
5509 break;
5511 case SMB_QUERY_FILE_ALL_INFO:
5512 case SMB_FILE_ALL_INFORMATION:
5514 unsigned int ea_size =
5515 estimate_ea_size(conn, fsp, smb_fname);
5516 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5517 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5518 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5519 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5520 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5521 SIVAL(pdata,32,mode);
5522 SIVAL(pdata,36,0); /* padding. */
5523 pdata += 40;
5524 SOFF_T(pdata,0,allocation_size);
5525 SOFF_T(pdata,8,file_size);
5526 SIVAL(pdata,16,nlink);
5527 SCVAL(pdata,20,delete_pending);
5528 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5529 SSVAL(pdata,22,0);
5530 pdata += 24;
5531 SIVAL(pdata,0,ea_size);
5532 pdata += 4; /* EA info */
5533 status = srvstr_push(dstart, flags2,
5534 pdata+4, dos_fname,
5535 PTR_DIFF(dend, pdata+4),
5536 STR_UNICODE, &len);
5537 if (!NT_STATUS_IS_OK(status)) {
5538 return status;
5540 SIVAL(pdata,0,len);
5541 pdata += 4 + len;
5542 data_size = PTR_DIFF(pdata,(*ppdata));
5543 *fixed_portion = 10;
5544 break;
5547 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5549 unsigned int ea_size =
5550 estimate_ea_size(conn, fsp, smb_fname);
5551 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5552 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5553 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5554 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5555 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5556 SIVAL(pdata, 0x20, mode);
5557 SIVAL(pdata, 0x24, 0); /* padding. */
5558 SBVAL(pdata, 0x28, allocation_size);
5559 SBVAL(pdata, 0x30, file_size);
5560 SIVAL(pdata, 0x38, nlink);
5561 SCVAL(pdata, 0x3C, delete_pending);
5562 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5563 SSVAL(pdata, 0x3E, 0); /* padding */
5564 SBVAL(pdata, 0x40, file_id);
5565 SIVAL(pdata, 0x48, ea_size);
5566 SIVAL(pdata, 0x4C, access_mask);
5567 SBVAL(pdata, 0x50, pos);
5568 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5569 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5571 pdata += 0x60;
5573 status = srvstr_push(dstart, flags2,
5574 pdata+4, dos_fname,
5575 PTR_DIFF(dend, pdata+4),
5576 STR_UNICODE, &len);
5577 if (!NT_STATUS_IS_OK(status)) {
5578 return status;
5580 SIVAL(pdata,0,len);
5581 pdata += 4 + len;
5582 data_size = PTR_DIFF(pdata,(*ppdata));
5583 *fixed_portion = 104;
5584 break;
5586 case SMB_FILE_INTERNAL_INFORMATION:
5588 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5589 SBVAL(pdata, 0, file_id);
5590 data_size = 8;
5591 *fixed_portion = 8;
5592 break;
5594 case SMB_FILE_ACCESS_INFORMATION:
5595 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5596 SIVAL(pdata, 0, access_mask);
5597 data_size = 4;
5598 *fixed_portion = 4;
5599 break;
5601 case SMB_FILE_NAME_INFORMATION:
5602 /* Pathname with leading '\'. */
5604 size_t byte_len;
5605 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5606 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5607 SIVAL(pdata,0,byte_len);
5608 data_size = 4 + byte_len;
5609 break;
5612 case SMB_FILE_DISPOSITION_INFORMATION:
5613 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5614 data_size = 1;
5615 SCVAL(pdata,0,delete_pending);
5616 *fixed_portion = 1;
5617 break;
5619 case SMB_FILE_POSITION_INFORMATION:
5620 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5621 data_size = 8;
5622 SOFF_T(pdata,0,pos);
5623 *fixed_portion = 8;
5624 break;
5626 case SMB_FILE_MODE_INFORMATION:
5627 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5628 SIVAL(pdata,0,mode);
5629 data_size = 4;
5630 *fixed_portion = 4;
5631 break;
5633 case SMB_FILE_ALIGNMENT_INFORMATION:
5634 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5635 SIVAL(pdata,0,0); /* No alignment needed. */
5636 data_size = 4;
5637 *fixed_portion = 4;
5638 break;
5641 * NT4 server just returns "invalid query" to this - if we try
5642 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5643 * want this. JRA.
5645 /* The first statement above is false - verified using Thursby
5646 * client against NT4 -- gcolley.
5648 case SMB_QUERY_FILE_STREAM_INFO:
5649 case SMB_FILE_STREAM_INFORMATION: {
5650 unsigned int num_streams = 0;
5651 struct stream_struct *streams = NULL;
5653 DEBUG(10,("smbd_do_qfilepathinfo: "
5654 "SMB_FILE_STREAM_INFORMATION\n"));
5656 if (is_ntfs_stream_smb_fname(smb_fname)) {
5657 return NT_STATUS_INVALID_PARAMETER;
5660 status = vfs_streaminfo(conn,
5661 fsp,
5662 smb_fname,
5663 talloc_tos(),
5664 &num_streams,
5665 &streams);
5667 if (!NT_STATUS_IS_OK(status)) {
5668 DEBUG(10, ("could not get stream info: %s\n",
5669 nt_errstr(status)));
5670 return status;
5673 status = marshall_stream_info(num_streams, streams,
5674 pdata, max_data_bytes,
5675 &data_size);
5677 if (!NT_STATUS_IS_OK(status)) {
5678 DEBUG(10, ("marshall_stream_info failed: %s\n",
5679 nt_errstr(status)));
5680 TALLOC_FREE(streams);
5681 return status;
5684 TALLOC_FREE(streams);
5686 *fixed_portion = 32;
5688 break;
5690 case SMB_QUERY_COMPRESSION_INFO:
5691 case SMB_FILE_COMPRESSION_INFORMATION:
5692 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5693 SOFF_T(pdata,0,file_size);
5694 SIVAL(pdata,8,0); /* ??? */
5695 SIVAL(pdata,12,0); /* ??? */
5696 data_size = 16;
5697 *fixed_portion = 16;
5698 break;
5700 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5701 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5702 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5703 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5704 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5705 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5706 SOFF_T(pdata,32,allocation_size);
5707 SOFF_T(pdata,40,file_size);
5708 SIVAL(pdata,48,mode);
5709 SIVAL(pdata,52,0); /* ??? */
5710 data_size = 56;
5711 *fixed_portion = 56;
5712 break;
5714 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5715 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5716 SIVAL(pdata,0,mode);
5717 SIVAL(pdata,4,0);
5718 data_size = 8;
5719 *fixed_portion = 8;
5720 break;
5723 * CIFS UNIX Extensions.
5726 case SMB_QUERY_FILE_UNIX_BASIC:
5728 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5729 data_size = PTR_DIFF(pdata,(*ppdata));
5731 DEBUG(4,("smbd_do_qfilepathinfo: "
5732 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5733 dump_data(4, (uint8_t *)(*ppdata), data_size);
5735 break;
5737 case SMB_QUERY_FILE_UNIX_INFO2:
5739 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5740 data_size = PTR_DIFF(pdata,(*ppdata));
5743 int i;
5744 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5746 for (i=0; i<100; i++)
5747 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5748 DEBUG(4,("\n"));
5751 break;
5753 case SMB_QUERY_FILE_UNIX_LINK:
5755 int link_len = 0;
5756 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5758 if (!buffer) {
5759 return NT_STATUS_NO_MEMORY;
5762 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5763 #ifdef S_ISLNK
5764 if(!S_ISLNK(psbuf->st_ex_mode)) {
5765 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5767 #else
5768 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5769 #endif
5770 link_len = SMB_VFS_READLINK(conn,
5771 smb_fname,
5772 buffer, PATH_MAX);
5773 if (link_len == -1) {
5774 return map_nt_error_from_unix(errno);
5776 buffer[link_len] = 0;
5777 status = srvstr_push(dstart, flags2,
5778 pdata, buffer,
5779 PTR_DIFF(dend, pdata),
5780 STR_TERMINATE, &len);
5781 if (!NT_STATUS_IS_OK(status)) {
5782 return status;
5784 pdata += len;
5785 data_size = PTR_DIFF(pdata,(*ppdata));
5787 break;
5790 #if defined(HAVE_POSIX_ACLS)
5791 case SMB_QUERY_POSIX_ACL:
5793 status = smb_query_posix_acl(conn,
5794 req,
5795 fsp,
5796 smb_fname,
5797 pdata,
5798 data_size,
5799 &data_size);
5800 if (!NT_STATUS_IS_OK(status)) {
5801 return status;
5803 break;
5805 #endif
5808 case SMB_QUERY_POSIX_LOCK:
5810 uint64_t count;
5811 uint64_t offset;
5812 uint64_t smblctx;
5813 enum brl_type lock_type;
5815 /* We need an open file with a real fd for this. */
5816 if (!fsp || fsp->fh->fd == -1) {
5817 return NT_STATUS_INVALID_LEVEL;
5820 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5821 return NT_STATUS_INVALID_PARAMETER;
5824 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5825 case POSIX_LOCK_TYPE_READ:
5826 lock_type = READ_LOCK;
5827 break;
5828 case POSIX_LOCK_TYPE_WRITE:
5829 lock_type = WRITE_LOCK;
5830 break;
5831 case POSIX_LOCK_TYPE_UNLOCK:
5832 default:
5833 /* There's no point in asking for an unlock... */
5834 return NT_STATUS_INVALID_PARAMETER;
5837 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5838 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5839 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5841 status = query_lock(fsp,
5842 &smblctx,
5843 &count,
5844 &offset,
5845 &lock_type,
5846 POSIX_LOCK);
5848 if (ERROR_WAS_LOCK_DENIED(status)) {
5849 /* Here we need to report who has it locked... */
5850 data_size = POSIX_LOCK_DATA_SIZE;
5852 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5853 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5854 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5855 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5856 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5858 } else if (NT_STATUS_IS_OK(status)) {
5859 /* For success we just return a copy of what we sent
5860 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5861 data_size = POSIX_LOCK_DATA_SIZE;
5862 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5863 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5864 } else {
5865 return status;
5867 break;
5870 default:
5871 return NT_STATUS_INVALID_LEVEL;
5874 *pdata_size = data_size;
5875 return NT_STATUS_OK;
5878 /****************************************************************************
5879 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5880 file name or file id).
5881 ****************************************************************************/
5883 static void call_trans2qfilepathinfo(connection_struct *conn,
5884 struct smb_request *req,
5885 unsigned int tran_call,
5886 char **pparams, int total_params,
5887 char **ppdata, int total_data,
5888 unsigned int max_data_bytes)
5890 char *params = *pparams;
5891 char *pdata = *ppdata;
5892 uint16_t info_level;
5893 unsigned int data_size = 0;
5894 unsigned int param_size = 2;
5895 struct smb_filename *smb_fname = NULL;
5896 bool delete_pending = False;
5897 struct timespec write_time_ts;
5898 files_struct *fsp = NULL;
5899 struct file_id fileid;
5900 struct ea_list *ea_list = NULL;
5901 int lock_data_count = 0;
5902 char *lock_data = NULL;
5903 size_t fixed_portion;
5904 NTSTATUS status = NT_STATUS_OK;
5906 if (!params) {
5907 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5908 return;
5911 ZERO_STRUCT(write_time_ts);
5913 if (tran_call == TRANSACT2_QFILEINFO) {
5914 if (total_params < 4) {
5915 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5916 return;
5919 if (IS_IPC(conn)) {
5920 call_trans2qpipeinfo(conn, req, tran_call,
5921 pparams, total_params,
5922 ppdata, total_data,
5923 max_data_bytes);
5924 return;
5927 fsp = file_fsp(req, SVAL(params,0));
5928 info_level = SVAL(params,2);
5930 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5932 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5933 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5934 return;
5937 /* Initial check for valid fsp ptr. */
5938 if (!check_fsp_open(conn, req, fsp)) {
5939 return;
5942 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5943 if (smb_fname == NULL) {
5944 reply_nterror(req, NT_STATUS_NO_MEMORY);
5945 return;
5948 if(fsp->fake_file_handle) {
5950 * This is actually for the QUOTA_FAKE_FILE --metze
5953 /* We know this name is ok, it's already passed the checks. */
5955 } else if(fsp->fh->fd == -1) {
5957 * This is actually a QFILEINFO on a directory
5958 * handle (returned from an NT SMB). NT5.0 seems
5959 * to do this call. JRA.
5962 if (INFO_LEVEL_IS_UNIX(info_level)) {
5963 /* Always do lstat for UNIX calls. */
5964 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5965 DEBUG(3,("call_trans2qfilepathinfo: "
5966 "SMB_VFS_LSTAT of %s failed "
5967 "(%s)\n",
5968 smb_fname_str_dbg(smb_fname),
5969 strerror(errno)));
5970 reply_nterror(req,
5971 map_nt_error_from_unix(errno));
5972 return;
5974 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5975 DEBUG(3,("call_trans2qfilepathinfo: "
5976 "SMB_VFS_STAT of %s failed (%s)\n",
5977 smb_fname_str_dbg(smb_fname),
5978 strerror(errno)));
5979 reply_nterror(req,
5980 map_nt_error_from_unix(errno));
5981 return;
5984 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5985 fileid = vfs_file_id_from_sbuf(
5986 conn, &smb_fname->st);
5987 get_file_infos(fileid, fsp->name_hash,
5988 &delete_pending,
5989 &write_time_ts);
5991 } else {
5993 * Original code - this is an open file.
5995 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5996 DEBUG(3, ("fstat of %s failed (%s)\n",
5997 fsp_fnum_dbg(fsp), strerror(errno)));
5998 reply_nterror(req,
5999 map_nt_error_from_unix(errno));
6000 return;
6002 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6003 fileid = vfs_file_id_from_sbuf(
6004 conn, &smb_fname->st);
6005 get_file_infos(fileid, fsp->name_hash,
6006 &delete_pending,
6007 &write_time_ts);
6011 } else {
6012 uint32_t name_hash;
6013 char *fname = NULL;
6014 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6016 /* qpathinfo */
6017 if (total_params < 7) {
6018 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
6019 return;
6022 info_level = SVAL(params,0);
6024 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
6026 if (INFO_LEVEL_IS_UNIX(info_level)) {
6027 if (!lp_unix_extensions()) {
6028 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6029 return;
6031 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
6032 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
6033 info_level == SMB_QUERY_FILE_UNIX_LINK ||
6034 req->posix_pathnames) {
6035 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
6039 if (req->posix_pathnames) {
6040 srvstr_get_path_posix(req,
6041 params,
6042 req->flags2,
6043 &fname,
6044 &params[6],
6045 total_params - 6,
6046 STR_TERMINATE,
6047 &status);
6048 } else {
6049 srvstr_get_path(req,
6050 params,
6051 req->flags2,
6052 &fname,
6053 &params[6],
6054 total_params - 6,
6055 STR_TERMINATE,
6056 &status);
6058 if (!NT_STATUS_IS_OK(status)) {
6059 reply_nterror(req, status);
6060 return;
6063 status = filename_convert(req,
6064 conn,
6065 fname,
6066 ucf_flags,
6067 NULL,
6068 NULL,
6069 &smb_fname);
6070 if (!NT_STATUS_IS_OK(status)) {
6071 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
6072 reply_botherror(req,
6073 NT_STATUS_PATH_NOT_COVERED,
6074 ERRSRV, ERRbadpath);
6075 return;
6077 reply_nterror(req, status);
6078 return;
6081 /* If this is a stream, check if there is a delete_pending. */
6082 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
6083 && is_ntfs_stream_smb_fname(smb_fname)) {
6084 struct smb_filename *smb_fname_base;
6086 /* Create an smb_filename with stream_name == NULL. */
6087 smb_fname_base = synthetic_smb_fname(
6088 talloc_tos(),
6089 smb_fname->base_name,
6090 NULL,
6091 NULL,
6092 smb_fname->flags);
6093 if (smb_fname_base == NULL) {
6094 reply_nterror(req, NT_STATUS_NO_MEMORY);
6095 return;
6098 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6099 /* Always do lstat for UNIX calls. */
6100 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
6101 DEBUG(3,("call_trans2qfilepathinfo: "
6102 "SMB_VFS_LSTAT of %s failed "
6103 "(%s)\n",
6104 smb_fname_str_dbg(smb_fname_base),
6105 strerror(errno)));
6106 TALLOC_FREE(smb_fname_base);
6107 reply_nterror(req,
6108 map_nt_error_from_unix(errno));
6109 return;
6111 } else {
6112 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
6113 DEBUG(3,("call_trans2qfilepathinfo: "
6114 "fileinfo of %s failed "
6115 "(%s)\n",
6116 smb_fname_str_dbg(smb_fname_base),
6117 strerror(errno)));
6118 TALLOC_FREE(smb_fname_base);
6119 reply_nterror(req,
6120 map_nt_error_from_unix(errno));
6121 return;
6125 status = file_name_hash(conn,
6126 smb_fname_str_dbg(smb_fname_base),
6127 &name_hash);
6128 if (!NT_STATUS_IS_OK(status)) {
6129 TALLOC_FREE(smb_fname_base);
6130 reply_nterror(req, status);
6131 return;
6134 fileid = vfs_file_id_from_sbuf(conn,
6135 &smb_fname_base->st);
6136 TALLOC_FREE(smb_fname_base);
6137 get_file_infos(fileid, name_hash, &delete_pending, NULL);
6138 if (delete_pending) {
6139 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6140 return;
6144 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
6145 /* Always do lstat for UNIX calls. */
6146 if (SMB_VFS_LSTAT(conn, smb_fname)) {
6147 DEBUG(3,("call_trans2qfilepathinfo: "
6148 "SMB_VFS_LSTAT of %s failed (%s)\n",
6149 smb_fname_str_dbg(smb_fname),
6150 strerror(errno)));
6151 reply_nterror(req,
6152 map_nt_error_from_unix(errno));
6153 return;
6156 } else {
6157 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
6158 DEBUG(3,("call_trans2qfilepathinfo: "
6159 "SMB_VFS_STAT of %s failed (%s)\n",
6160 smb_fname_str_dbg(smb_fname),
6161 strerror(errno)));
6162 reply_nterror(req,
6163 map_nt_error_from_unix(errno));
6164 return;
6168 status = file_name_hash(conn,
6169 smb_fname_str_dbg(smb_fname),
6170 &name_hash);
6171 if (!NT_STATUS_IS_OK(status)) {
6172 reply_nterror(req, status);
6173 return;
6176 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
6177 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
6178 get_file_infos(fileid, name_hash, &delete_pending,
6179 &write_time_ts);
6182 if (delete_pending) {
6183 reply_nterror(req, NT_STATUS_DELETE_PENDING);
6184 return;
6188 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
6189 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
6190 fsp_fnum_dbg(fsp),
6191 info_level,tran_call,total_data));
6193 /* Pull out any data sent here before we realloc. */
6194 switch (info_level) {
6195 case SMB_INFO_QUERY_EAS_FROM_LIST:
6197 /* Pull any EA list from the data portion. */
6198 uint32_t ea_size;
6200 if (total_data < 4) {
6201 reply_nterror(
6202 req, NT_STATUS_INVALID_PARAMETER);
6203 return;
6205 ea_size = IVAL(pdata,0);
6207 if (total_data > 0 && ea_size != total_data) {
6208 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6209 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6210 reply_nterror(
6211 req, NT_STATUS_INVALID_PARAMETER);
6212 return;
6215 if (!lp_ea_support(SNUM(conn))) {
6216 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6217 return;
6220 /* Pull out the list of names. */
6221 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6222 if (!ea_list) {
6223 reply_nterror(
6224 req, NT_STATUS_INVALID_PARAMETER);
6225 return;
6227 break;
6230 case SMB_QUERY_POSIX_LOCK:
6232 if (fsp == NULL || fsp->fh->fd == -1) {
6233 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6234 return;
6237 if (total_data != POSIX_LOCK_DATA_SIZE) {
6238 reply_nterror(
6239 req, NT_STATUS_INVALID_PARAMETER);
6240 return;
6243 /* Copy the lock range data. */
6244 lock_data = (char *)talloc_memdup(
6245 req, pdata, total_data);
6246 if (!lock_data) {
6247 reply_nterror(req, NT_STATUS_NO_MEMORY);
6248 return;
6250 lock_data_count = total_data;
6252 default:
6253 break;
6256 *pparams = (char *)SMB_REALLOC(*pparams,2);
6257 if (*pparams == NULL) {
6258 reply_nterror(req, NT_STATUS_NO_MEMORY);
6259 return;
6261 params = *pparams;
6262 SSVAL(params,0,0);
6265 * draft-leach-cifs-v1-spec-02.txt
6266 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6267 * says:
6269 * The requested information is placed in the Data portion of the
6270 * transaction response. For the information levels greater than 0x100,
6271 * the transaction response has 1 parameter word which should be
6272 * ignored by the client.
6274 * However Windows only follows this rule for the IS_NAME_VALID call.
6276 switch (info_level) {
6277 case SMB_INFO_IS_NAME_VALID:
6278 param_size = 0;
6279 break;
6282 if ((info_level & 0xFF00) == 0xFF00) {
6284 * We use levels that start with 0xFF00
6285 * internally to represent SMB2 specific levels
6287 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6288 return;
6291 status = smbd_do_qfilepathinfo(conn, req, req, info_level,
6292 fsp, smb_fname,
6293 delete_pending, write_time_ts,
6294 ea_list,
6295 lock_data_count, lock_data,
6296 req->flags2, max_data_bytes,
6297 &fixed_portion,
6298 ppdata, &data_size);
6299 if (!NT_STATUS_IS_OK(status)) {
6300 if (open_was_deferred(req->xconn, req->mid)) {
6301 /* We have re-scheduled this call. */
6302 return;
6304 reply_nterror(req, status);
6305 return;
6307 if (fixed_portion > max_data_bytes) {
6308 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6309 return;
6312 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6313 max_data_bytes);
6315 return;
6318 /****************************************************************************
6319 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6320 code.
6321 ****************************************************************************/
6323 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6324 connection_struct *conn,
6325 struct smb_request *req,
6326 bool overwrite_if_exists,
6327 const struct smb_filename *smb_fname_old,
6328 struct smb_filename *smb_fname_new)
6330 NTSTATUS status = NT_STATUS_OK;
6331 bool ok;
6333 /* source must already exist. */
6334 if (!VALID_STAT(smb_fname_old->st)) {
6335 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6338 if (VALID_STAT(smb_fname_new->st)) {
6339 if (overwrite_if_exists) {
6340 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6341 return NT_STATUS_FILE_IS_A_DIRECTORY;
6343 status = unlink_internals(conn,
6344 req,
6345 FILE_ATTRIBUTE_NORMAL,
6346 smb_fname_new,
6347 false);
6348 if (!NT_STATUS_IS_OK(status)) {
6349 return status;
6351 } else {
6352 /* Disallow if newname already exists. */
6353 return NT_STATUS_OBJECT_NAME_COLLISION;
6357 /* No links from a directory. */
6358 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6359 return NT_STATUS_FILE_IS_A_DIRECTORY;
6362 /* Setting a hardlink to/from a stream isn't currently supported. */
6363 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6364 if (ok) {
6365 DBG_DEBUG("Old name has streams\n");
6366 return NT_STATUS_INVALID_PARAMETER;
6368 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6369 if (ok) {
6370 DBG_DEBUG("New name has streams\n");
6371 return NT_STATUS_INVALID_PARAMETER;
6374 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6375 smb_fname_old->base_name, smb_fname_new->base_name));
6377 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6378 status = map_nt_error_from_unix(errno);
6379 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6380 nt_errstr(status), smb_fname_old->base_name,
6381 smb_fname_new->base_name));
6383 return status;
6386 /****************************************************************************
6387 Deal with setting the time from any of the setfilepathinfo functions.
6388 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6389 calling this function.
6390 ****************************************************************************/
6392 NTSTATUS smb_set_file_time(connection_struct *conn,
6393 files_struct *fsp,
6394 const struct smb_filename *smb_fname,
6395 struct smb_file_time *ft,
6396 bool setting_write_time)
6398 struct smb_filename smb_fname_base;
6399 uint32_t action =
6400 FILE_NOTIFY_CHANGE_LAST_ACCESS
6401 |FILE_NOTIFY_CHANGE_LAST_WRITE
6402 |FILE_NOTIFY_CHANGE_CREATION;
6404 if (!VALID_STAT(smb_fname->st)) {
6405 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6408 /* get some defaults (no modifications) if any info is zero or -1. */
6409 if (null_timespec(ft->create_time)) {
6410 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6413 if (null_timespec(ft->atime)) {
6414 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6417 if (null_timespec(ft->mtime)) {
6418 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6421 if (!setting_write_time) {
6422 /* ft->mtime comes from change time, not write time. */
6423 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6426 /* Ensure the resolution is the correct for
6427 * what we can store on this filesystem. */
6429 round_timespec(conn->ts_res, &ft->create_time);
6430 round_timespec(conn->ts_res, &ft->ctime);
6431 round_timespec(conn->ts_res, &ft->atime);
6432 round_timespec(conn->ts_res, &ft->mtime);
6434 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6435 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6436 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6437 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6438 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6439 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6440 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6441 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6443 if (setting_write_time) {
6445 * This was a Windows setfileinfo on an open file.
6446 * NT does this a lot. We also need to
6447 * set the time here, as it can be read by
6448 * FindFirst/FindNext and with the patch for bug #2045
6449 * in smbd/fileio.c it ensures that this timestamp is
6450 * kept sticky even after a write. We save the request
6451 * away and will set it on file close and after a write. JRA.
6454 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6455 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6457 if (fsp != NULL) {
6458 if (fsp->base_fsp) {
6459 set_sticky_write_time_fsp(fsp->base_fsp,
6460 ft->mtime);
6461 } else {
6462 set_sticky_write_time_fsp(fsp, ft->mtime);
6464 } else {
6465 set_sticky_write_time_path(
6466 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6467 ft->mtime);
6471 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6473 /* Always call ntimes on the base, even if a stream was passed in. */
6474 smb_fname_base = *smb_fname;
6475 smb_fname_base.stream_name = NULL;
6477 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6478 return map_nt_error_from_unix(errno);
6481 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6482 smb_fname->base_name);
6483 return NT_STATUS_OK;
6486 /****************************************************************************
6487 Deal with setting the dosmode from any of the setfilepathinfo functions.
6488 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6489 done before calling this function.
6490 ****************************************************************************/
6492 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6493 const struct smb_filename *smb_fname,
6494 uint32_t dosmode)
6496 struct smb_filename *smb_fname_base;
6497 NTSTATUS status;
6499 if (!VALID_STAT(smb_fname->st)) {
6500 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6503 /* Always operate on the base_name, even if a stream was passed in. */
6504 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6505 smb_fname->base_name,
6506 NULL,
6507 &smb_fname->st,
6508 smb_fname->flags);
6509 if (smb_fname_base == NULL) {
6510 return NT_STATUS_NO_MEMORY;
6513 if (dosmode) {
6514 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6515 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6516 } else {
6517 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6521 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6523 /* check the mode isn't different, before changing it */
6524 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6525 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6526 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6527 (unsigned int)dosmode));
6529 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6530 false)) {
6531 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6532 "%s failed (%s)\n",
6533 smb_fname_str_dbg(smb_fname_base),
6534 strerror(errno)));
6535 status = map_nt_error_from_unix(errno);
6536 goto out;
6539 status = NT_STATUS_OK;
6540 out:
6541 TALLOC_FREE(smb_fname_base);
6542 return status;
6545 /****************************************************************************
6546 Deal with setting the size from any of the setfilepathinfo functions.
6547 ****************************************************************************/
6549 static NTSTATUS smb_set_file_size(connection_struct *conn,
6550 struct smb_request *req,
6551 files_struct *fsp,
6552 const struct smb_filename *smb_fname,
6553 const SMB_STRUCT_STAT *psbuf,
6554 off_t size,
6555 bool fail_after_createfile)
6557 NTSTATUS status = NT_STATUS_OK;
6558 struct smb_filename *smb_fname_tmp = NULL;
6559 files_struct *new_fsp = NULL;
6561 if (!VALID_STAT(*psbuf)) {
6562 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6565 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6566 (uint64_t)size,
6567 get_file_size_stat(psbuf));
6569 if (size == get_file_size_stat(psbuf)) {
6570 return NT_STATUS_OK;
6573 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6574 smb_fname_str_dbg(smb_fname), (double)size));
6576 if (fsp && fsp->fh->fd != -1) {
6577 /* Handle based call. */
6578 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6579 return NT_STATUS_ACCESS_DENIED;
6582 if (vfs_set_filelen(fsp, size) == -1) {
6583 return map_nt_error_from_unix(errno);
6585 trigger_write_time_update_immediate(fsp);
6586 return NT_STATUS_OK;
6589 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6590 if (smb_fname_tmp == NULL) {
6591 return NT_STATUS_NO_MEMORY;
6594 smb_fname_tmp->st = *psbuf;
6596 status = SMB_VFS_CREATE_FILE(
6597 conn, /* conn */
6598 req, /* req */
6599 0, /* root_dir_fid */
6600 smb_fname_tmp, /* fname */
6601 FILE_WRITE_DATA, /* access_mask */
6602 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6603 FILE_SHARE_DELETE),
6604 FILE_OPEN, /* create_disposition*/
6605 0, /* create_options */
6606 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6607 0, /* oplock_request */
6608 NULL, /* lease */
6609 0, /* allocation_size */
6610 0, /* private_flags */
6611 NULL, /* sd */
6612 NULL, /* ea_list */
6613 &new_fsp, /* result */
6614 NULL, /* pinfo */
6615 NULL, NULL); /* create context */
6617 TALLOC_FREE(smb_fname_tmp);
6619 if (!NT_STATUS_IS_OK(status)) {
6620 /* NB. We check for open_was_deferred in the caller. */
6621 return status;
6624 /* See RAW-SFILEINFO-END-OF-FILE */
6625 if (fail_after_createfile) {
6626 close_file(req, new_fsp,NORMAL_CLOSE);
6627 return NT_STATUS_INVALID_LEVEL;
6630 if (vfs_set_filelen(new_fsp, size) == -1) {
6631 status = map_nt_error_from_unix(errno);
6632 close_file(req, new_fsp,NORMAL_CLOSE);
6633 return status;
6636 trigger_write_time_update_immediate(new_fsp);
6637 close_file(req, new_fsp,NORMAL_CLOSE);
6638 return NT_STATUS_OK;
6641 /****************************************************************************
6642 Deal with SMB_INFO_SET_EA.
6643 ****************************************************************************/
6645 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6646 const char *pdata,
6647 int total_data,
6648 files_struct *fsp,
6649 const struct smb_filename *smb_fname)
6651 struct ea_list *ea_list = NULL;
6652 TALLOC_CTX *ctx = NULL;
6653 NTSTATUS status = NT_STATUS_OK;
6655 if (total_data < 10) {
6657 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6658 length. They seem to have no effect. Bug #3212. JRA */
6660 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6661 /* We're done. We only get EA info in this call. */
6662 return NT_STATUS_OK;
6665 return NT_STATUS_INVALID_PARAMETER;
6668 if (IVAL(pdata,0) > total_data) {
6669 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6670 IVAL(pdata,0), (unsigned int)total_data));
6671 return NT_STATUS_INVALID_PARAMETER;
6674 ctx = talloc_tos();
6675 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6676 if (!ea_list) {
6677 return NT_STATUS_INVALID_PARAMETER;
6680 status = set_ea(conn, fsp, smb_fname, ea_list);
6682 return status;
6685 /****************************************************************************
6686 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6687 ****************************************************************************/
6689 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6690 const char *pdata,
6691 int total_data,
6692 files_struct *fsp)
6694 struct ea_list *ea_list = NULL;
6695 NTSTATUS status;
6697 if (!fsp) {
6698 return NT_STATUS_INVALID_HANDLE;
6701 if (!lp_ea_support(SNUM(conn))) {
6702 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6703 "EA's not supported.\n",
6704 (unsigned int)total_data));
6705 return NT_STATUS_EAS_NOT_SUPPORTED;
6708 if (total_data < 10) {
6709 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6710 "too small.\n",
6711 (unsigned int)total_data));
6712 return NT_STATUS_INVALID_PARAMETER;
6715 ea_list = read_nttrans_ea_list(talloc_tos(),
6716 pdata,
6717 total_data);
6719 if (!ea_list) {
6720 return NT_STATUS_INVALID_PARAMETER;
6723 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6725 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6726 smb_fname_str_dbg(fsp->fsp_name),
6727 nt_errstr(status) ));
6729 return status;
6733 /****************************************************************************
6734 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6735 ****************************************************************************/
6737 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6738 const char *pdata,
6739 int total_data,
6740 files_struct *fsp,
6741 struct smb_filename *smb_fname)
6743 NTSTATUS status = NT_STATUS_OK;
6744 bool delete_on_close;
6745 uint32_t dosmode = 0;
6747 if (total_data < 1) {
6748 return NT_STATUS_INVALID_PARAMETER;
6751 if (fsp == NULL) {
6752 return NT_STATUS_INVALID_HANDLE;
6755 delete_on_close = (CVAL(pdata,0) ? True : False);
6756 dosmode = dos_mode(conn, smb_fname);
6758 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6759 "delete_on_close = %u\n",
6760 smb_fname_str_dbg(smb_fname),
6761 (unsigned int)dosmode,
6762 (unsigned int)delete_on_close ));
6764 if (delete_on_close) {
6765 status = can_set_delete_on_close(fsp, dosmode);
6766 if (!NT_STATUS_IS_OK(status)) {
6767 return status;
6771 /* The set is across all open files on this dev/inode pair. */
6772 if (!set_delete_on_close(fsp, delete_on_close,
6773 conn->session_info->security_token,
6774 conn->session_info->unix_token)) {
6775 return NT_STATUS_ACCESS_DENIED;
6777 return NT_STATUS_OK;
6780 /****************************************************************************
6781 Deal with SMB_FILE_POSITION_INFORMATION.
6782 ****************************************************************************/
6784 static NTSTATUS smb_file_position_information(connection_struct *conn,
6785 const char *pdata,
6786 int total_data,
6787 files_struct *fsp)
6789 uint64_t position_information;
6791 if (total_data < 8) {
6792 return NT_STATUS_INVALID_PARAMETER;
6795 if (fsp == NULL) {
6796 /* Ignore on pathname based set. */
6797 return NT_STATUS_OK;
6800 position_information = (uint64_t)IVAL(pdata,0);
6801 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6803 DEBUG(10,("smb_file_position_information: Set file position "
6804 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6805 (double)position_information));
6806 fsp->fh->position_information = position_information;
6807 return NT_STATUS_OK;
6810 /****************************************************************************
6811 Deal with SMB_FILE_MODE_INFORMATION.
6812 ****************************************************************************/
6814 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6815 const char *pdata,
6816 int total_data)
6818 uint32_t mode;
6820 if (total_data < 4) {
6821 return NT_STATUS_INVALID_PARAMETER;
6823 mode = IVAL(pdata,0);
6824 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6825 return NT_STATUS_INVALID_PARAMETER;
6827 return NT_STATUS_OK;
6830 /****************************************************************************
6831 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6832 ****************************************************************************/
6834 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6835 struct smb_request *req,
6836 const char *pdata,
6837 int total_data,
6838 const struct smb_filename *new_smb_fname)
6840 char *link_target = NULL;
6841 TALLOC_CTX *ctx = talloc_tos();
6843 /* Set a symbolic link. */
6844 /* Don't allow this if follow links is false. */
6846 if (total_data == 0) {
6847 return NT_STATUS_INVALID_PARAMETER;
6850 if (!lp_follow_symlinks(SNUM(conn))) {
6851 return NT_STATUS_ACCESS_DENIED;
6854 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6855 total_data, STR_TERMINATE);
6857 if (!link_target) {
6858 return NT_STATUS_INVALID_PARAMETER;
6861 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6862 new_smb_fname->base_name, link_target ));
6864 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6865 return map_nt_error_from_unix(errno);
6868 return NT_STATUS_OK;
6871 /****************************************************************************
6872 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6873 ****************************************************************************/
6875 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6876 struct smb_request *req,
6877 const char *pdata, int total_data,
6878 struct smb_filename *smb_fname_new)
6880 char *oldname = NULL;
6881 struct smb_filename *smb_fname_old = NULL;
6882 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6883 TALLOC_CTX *ctx = talloc_tos();
6884 NTSTATUS status = NT_STATUS_OK;
6886 /* Set a hard link. */
6887 if (total_data == 0) {
6888 return NT_STATUS_INVALID_PARAMETER;
6891 if (req->posix_pathnames) {
6892 srvstr_get_path_posix(ctx,
6893 pdata,
6894 req->flags2,
6895 &oldname,
6896 pdata,
6897 total_data,
6898 STR_TERMINATE,
6899 &status);
6900 } else {
6901 srvstr_get_path(ctx,
6902 pdata,
6903 req->flags2,
6904 &oldname,
6905 pdata,
6906 total_data,
6907 STR_TERMINATE,
6908 &status);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 return status;
6914 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6915 smb_fname_str_dbg(smb_fname_new), oldname));
6917 status = filename_convert(ctx,
6918 conn,
6919 oldname,
6920 ucf_flags,
6921 NULL,
6922 NULL,
6923 &smb_fname_old);
6924 if (!NT_STATUS_IS_OK(status)) {
6925 return status;
6928 return hardlink_internals(ctx, conn, req, false,
6929 smb_fname_old, smb_fname_new);
6932 /****************************************************************************
6933 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6934 ****************************************************************************/
6936 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6937 struct smb_request *req,
6938 const char *pdata,
6939 int total_data,
6940 files_struct *fsp,
6941 struct smb_filename *smb_fname_src)
6943 bool overwrite;
6944 uint32_t len;
6945 char *newname = NULL;
6946 struct smb_filename *smb_fname_dst = NULL;
6947 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6948 ucf_flags_from_smb_request(req);
6949 NTSTATUS status = NT_STATUS_OK;
6950 TALLOC_CTX *ctx = talloc_tos();
6952 if (!fsp) {
6953 return NT_STATUS_INVALID_HANDLE;
6956 if (total_data < 20) {
6957 return NT_STATUS_INVALID_PARAMETER;
6960 overwrite = (CVAL(pdata,0) ? True : False);
6961 len = IVAL(pdata,16);
6963 if (len > (total_data - 20) || (len == 0)) {
6964 return NT_STATUS_INVALID_PARAMETER;
6967 if (req->posix_pathnames) {
6968 srvstr_get_path_posix(ctx,
6969 pdata,
6970 req->flags2,
6971 &newname,
6972 &pdata[20],
6973 len,
6974 STR_TERMINATE,
6975 &status);
6976 } else {
6977 srvstr_get_path(ctx,
6978 pdata,
6979 req->flags2,
6980 &newname,
6981 &pdata[20],
6982 len,
6983 STR_TERMINATE,
6984 &status);
6986 if (!NT_STATUS_IS_OK(status)) {
6987 return status;
6990 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6991 newname));
6993 status = filename_convert(ctx,
6994 conn,
6995 newname,
6996 ucf_flags,
6997 NULL,
6998 NULL,
6999 &smb_fname_dst);
7000 if (!NT_STATUS_IS_OK(status)) {
7001 return status;
7004 if (fsp->base_fsp) {
7005 /* newname must be a stream name. */
7006 if (newname[0] != ':') {
7007 return NT_STATUS_NOT_SUPPORTED;
7010 /* Create an smb_fname to call rename_internals_fsp() with. */
7011 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7012 fsp->base_fsp->fsp_name->base_name,
7013 newname,
7014 NULL,
7015 fsp->base_fsp->fsp_name->flags);
7016 if (smb_fname_dst == NULL) {
7017 status = NT_STATUS_NO_MEMORY;
7018 goto out;
7022 * Set the original last component, since
7023 * rename_internals_fsp() requires it.
7025 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7026 newname);
7027 if (smb_fname_dst->original_lcomp == NULL) {
7028 status = NT_STATUS_NO_MEMORY;
7029 goto out;
7034 DEBUG(10,("smb2_file_rename_information: "
7035 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7036 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7037 smb_fname_str_dbg(smb_fname_dst)));
7038 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
7039 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
7040 overwrite);
7042 out:
7043 TALLOC_FREE(smb_fname_dst);
7044 return status;
7047 static NTSTATUS smb_file_link_information(connection_struct *conn,
7048 struct smb_request *req,
7049 const char *pdata,
7050 int total_data,
7051 files_struct *fsp,
7052 struct smb_filename *smb_fname_src)
7054 bool overwrite;
7055 uint32_t len;
7056 char *newname = NULL;
7057 struct smb_filename *smb_fname_dst = NULL;
7058 NTSTATUS status = NT_STATUS_OK;
7059 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7060 ucf_flags_from_smb_request(req);
7061 TALLOC_CTX *ctx = talloc_tos();
7063 if (!fsp) {
7064 return NT_STATUS_INVALID_HANDLE;
7067 if (total_data < 20) {
7068 return NT_STATUS_INVALID_PARAMETER;
7071 overwrite = (CVAL(pdata,0) ? true : false);
7072 len = IVAL(pdata,16);
7074 if (len > (total_data - 20) || (len == 0)) {
7075 return NT_STATUS_INVALID_PARAMETER;
7078 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
7079 srvstr_get_path_posix(ctx,
7080 pdata,
7081 req->flags2,
7082 &newname,
7083 &pdata[20],
7084 len,
7085 STR_TERMINATE,
7086 &status);
7087 ucf_flags |= UCF_POSIX_PATHNAMES;
7088 } else {
7089 srvstr_get_path(ctx,
7090 pdata,
7091 req->flags2,
7092 &newname,
7093 &pdata[20],
7094 len,
7095 STR_TERMINATE,
7096 &status);
7098 if (!NT_STATUS_IS_OK(status)) {
7099 return status;
7102 DEBUG(10,("smb_file_link_information: got name |%s|\n",
7103 newname));
7105 status = filename_convert(ctx,
7106 conn,
7107 newname,
7108 ucf_flags,
7109 NULL,
7110 NULL,
7111 &smb_fname_dst);
7112 if (!NT_STATUS_IS_OK(status)) {
7113 return status;
7116 if (fsp->base_fsp) {
7117 /* No stream names. */
7118 return NT_STATUS_NOT_SUPPORTED;
7121 DEBUG(10,("smb_file_link_information: "
7122 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
7123 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7124 smb_fname_str_dbg(smb_fname_dst)));
7125 status = hardlink_internals(ctx,
7126 conn,
7127 req,
7128 overwrite,
7129 fsp->fsp_name,
7130 smb_fname_dst);
7132 TALLOC_FREE(smb_fname_dst);
7133 return status;
7136 /****************************************************************************
7137 Deal with SMB_FILE_RENAME_INFORMATION.
7138 ****************************************************************************/
7140 static NTSTATUS smb_file_rename_information(connection_struct *conn,
7141 struct smb_request *req,
7142 const char *pdata,
7143 int total_data,
7144 files_struct *fsp,
7145 struct smb_filename *smb_fname_src)
7147 bool overwrite;
7148 uint32_t root_fid;
7149 uint32_t len;
7150 char *newname = NULL;
7151 struct smb_filename *smb_fname_dst = NULL;
7152 bool dest_has_wcard = False;
7153 NTSTATUS status = NT_STATUS_OK;
7154 char *p;
7155 TALLOC_CTX *ctx = talloc_tos();
7157 if (total_data < 13) {
7158 return NT_STATUS_INVALID_PARAMETER;
7161 overwrite = (CVAL(pdata,0) ? True : False);
7162 root_fid = IVAL(pdata,4);
7163 len = IVAL(pdata,8);
7165 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
7166 return NT_STATUS_INVALID_PARAMETER;
7169 if (req->posix_pathnames) {
7170 srvstr_get_path_wcard_posix(ctx,
7171 pdata,
7172 req->flags2,
7173 &newname,
7174 &pdata[12],
7175 len,
7177 &status,
7178 &dest_has_wcard);
7179 } else {
7180 srvstr_get_path_wcard(ctx,
7181 pdata,
7182 req->flags2,
7183 &newname,
7184 &pdata[12],
7185 len,
7187 &status,
7188 &dest_has_wcard);
7190 if (!NT_STATUS_IS_OK(status)) {
7191 return status;
7194 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
7195 newname));
7197 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7198 status = resolve_dfspath_wcard(ctx, conn,
7199 newname,
7200 UCF_COND_ALLOW_WCARD_LCOMP,
7201 !conn->sconn->using_smb2,
7202 &newname,
7203 &dest_has_wcard);
7204 if (!NT_STATUS_IS_OK(status)) {
7205 return status;
7209 /* Check the new name has no '/' characters. */
7210 if (strchr_m(newname, '/')) {
7211 return NT_STATUS_NOT_SUPPORTED;
7214 if (fsp && fsp->base_fsp) {
7215 /* newname must be a stream name. */
7216 if (newname[0] != ':') {
7217 return NT_STATUS_NOT_SUPPORTED;
7220 /* Create an smb_fname to call rename_internals_fsp() with. */
7221 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7222 fsp->base_fsp->fsp_name->base_name,
7223 newname,
7224 NULL,
7225 fsp->base_fsp->fsp_name->flags);
7226 if (smb_fname_dst == NULL) {
7227 status = NT_STATUS_NO_MEMORY;
7228 goto out;
7232 * Set the original last component, since
7233 * rename_internals_fsp() requires it.
7235 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7236 newname);
7237 if (smb_fname_dst->original_lcomp == NULL) {
7238 status = NT_STATUS_NO_MEMORY;
7239 goto out;
7242 } else {
7244 * Build up an smb_fname_dst based on the filename passed in.
7245 * We basically just strip off the last component, and put on
7246 * the newname instead.
7248 char *base_name = NULL;
7249 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7250 ucf_flags_from_smb_request(req);
7252 if (dest_has_wcard) {
7253 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7256 /* newname must *not* be a stream name. */
7257 if (newname[0] == ':') {
7258 return NT_STATUS_NOT_SUPPORTED;
7262 * Strip off the last component (filename) of the path passed
7263 * in.
7265 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7266 if (!base_name) {
7267 return NT_STATUS_NO_MEMORY;
7269 p = strrchr_m(base_name, '/');
7270 if (p) {
7271 p[1] = '\0';
7272 } else {
7273 base_name = talloc_strdup(ctx, "");
7274 if (!base_name) {
7275 return NT_STATUS_NO_MEMORY;
7278 /* Append the new name. */
7279 base_name = talloc_asprintf_append(base_name,
7280 "%s",
7281 newname);
7282 if (!base_name) {
7283 return NT_STATUS_NO_MEMORY;
7286 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7287 ucf_flags);
7289 /* If an error we expect this to be
7290 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7292 if (!NT_STATUS_IS_OK(status)) {
7293 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7294 status)) {
7295 goto out;
7297 /* Create an smb_fname to call rename_internals_fsp() */
7298 smb_fname_dst = synthetic_smb_fname(ctx,
7299 base_name,
7300 NULL,
7301 NULL,
7302 smb_fname_src->flags);
7303 if (smb_fname_dst == NULL) {
7304 status = NT_STATUS_NO_MEMORY;
7305 goto out;
7310 if (fsp) {
7311 DEBUG(10,("smb_file_rename_information: "
7312 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7313 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7314 smb_fname_str_dbg(smb_fname_dst)));
7315 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7316 overwrite);
7317 } else {
7318 DEBUG(10,("smb_file_rename_information: "
7319 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7320 smb_fname_str_dbg(smb_fname_src),
7321 smb_fname_str_dbg(smb_fname_dst)));
7322 status = rename_internals(ctx, conn, req, smb_fname_src,
7323 smb_fname_dst, 0, overwrite, false,
7324 dest_has_wcard,
7325 FILE_WRITE_ATTRIBUTES);
7327 out:
7328 TALLOC_FREE(smb_fname_dst);
7329 return status;
7332 /****************************************************************************
7333 Deal with SMB_SET_POSIX_ACL.
7334 ****************************************************************************/
7336 #if defined(HAVE_POSIX_ACLS)
7337 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7338 struct smb_request *req,
7339 const char *pdata,
7340 int total_data_in,
7341 files_struct *fsp,
7342 const struct smb_filename *smb_fname)
7344 uint16_t posix_acl_version;
7345 uint16_t num_file_acls;
7346 uint16_t num_def_acls;
7347 bool valid_file_acls = true;
7348 bool valid_def_acls = true;
7349 NTSTATUS status;
7350 unsigned int size_needed;
7351 unsigned int total_data;
7352 bool close_fsp = false;
7354 if (total_data_in < 0) {
7355 status = NT_STATUS_INVALID_PARAMETER;
7356 goto out;
7359 total_data = total_data_in;
7361 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7362 status = NT_STATUS_INVALID_PARAMETER;
7363 goto out;
7365 posix_acl_version = SVAL(pdata,0);
7366 num_file_acls = SVAL(pdata,2);
7367 num_def_acls = SVAL(pdata,4);
7369 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7370 valid_file_acls = false;
7371 num_file_acls = 0;
7374 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7375 valid_def_acls = false;
7376 num_def_acls = 0;
7379 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7380 status = NT_STATUS_INVALID_PARAMETER;
7381 goto out;
7384 /* Wrap checks. */
7385 if (num_file_acls + num_def_acls < num_file_acls) {
7386 status = NT_STATUS_INVALID_PARAMETER;
7387 goto out;
7390 size_needed = num_file_acls + num_def_acls;
7393 * (size_needed * SMB_POSIX_ACL_ENTRY_SIZE) must be less
7394 * than UINT_MAX, so check by division.
7396 if (size_needed > (UINT_MAX/SMB_POSIX_ACL_ENTRY_SIZE)) {
7397 status = NT_STATUS_INVALID_PARAMETER;
7398 goto out;
7401 size_needed = size_needed*SMB_POSIX_ACL_ENTRY_SIZE;
7402 if (size_needed + SMB_POSIX_ACL_HEADER_SIZE < size_needed) {
7403 status = NT_STATUS_INVALID_PARAMETER;
7404 goto out;
7406 size_needed += SMB_POSIX_ACL_HEADER_SIZE;
7408 if (total_data < size_needed) {
7409 status = NT_STATUS_INVALID_PARAMETER;
7410 goto out;
7414 * Ensure we always operate on a file descriptor, not just
7415 * the filename.
7417 if (fsp == NULL) {
7418 uint32_t access_mask = SEC_STD_WRITE_OWNER|
7419 SEC_STD_WRITE_DAC|
7420 SEC_STD_READ_CONTROL|
7421 FILE_READ_ATTRIBUTES|
7422 FILE_WRITE_ATTRIBUTES;
7424 status = get_posix_fsp(conn,
7425 req,
7426 smb_fname,
7427 access_mask,
7428 &fsp);
7430 if (!NT_STATUS_IS_OK(status)) {
7431 goto out;
7433 close_fsp = true;
7436 /* Here we know fsp != NULL */
7437 SMB_ASSERT(fsp != NULL);
7439 status = refuse_symlink(conn, fsp, fsp->fsp_name);
7440 if (!NT_STATUS_IS_OK(status)) {
7441 goto out;
7444 /* If we have a default acl, this *must* be a directory. */
7445 if (valid_def_acls && !fsp->is_directory) {
7446 DBG_INFO("Can't set default acls on "
7447 "non-directory %s\n",
7448 fsp_str_dbg(fsp));
7449 return NT_STATUS_INVALID_HANDLE;
7452 DBG_DEBUG("file %s num_file_acls = %"PRIu16", "
7453 "num_def_acls = %"PRIu16"\n",
7454 fsp_str_dbg(fsp),
7455 num_file_acls,
7456 num_def_acls);
7458 /* Move pdata to the start of the file ACL entries. */
7459 pdata += SMB_POSIX_ACL_HEADER_SIZE;
7461 if (valid_file_acls) {
7462 status = set_unix_posix_acl(conn,
7463 fsp,
7464 num_file_acls,
7465 pdata);
7466 if (!NT_STATUS_IS_OK(status)) {
7467 goto out;
7471 /* Move pdata to the start of the default ACL entries. */
7472 pdata += (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE);
7474 if (valid_def_acls) {
7475 status = set_unix_posix_default_acl(conn,
7476 fsp,
7477 num_def_acls,
7478 pdata);
7479 if (!NT_STATUS_IS_OK(status)) {
7480 goto out;
7484 status = NT_STATUS_OK;
7486 out:
7488 if (close_fsp) {
7489 (void)close_file(req, fsp, NORMAL_CLOSE);
7490 fsp = NULL;
7492 return status;
7494 #endif
7496 /****************************************************************************
7497 Deal with SMB_SET_POSIX_LOCK.
7498 ****************************************************************************/
7500 static void smb_set_posix_lock_done(struct tevent_req *subreq);
7502 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7503 struct smb_request *req,
7504 const char *pdata,
7505 int total_data,
7506 files_struct *fsp)
7508 struct tevent_req *subreq = NULL;
7509 struct smbd_lock_element *lck = NULL;
7510 uint64_t count;
7511 uint64_t offset;
7512 uint64_t smblctx;
7513 bool blocking_lock = False;
7514 enum brl_type lock_type;
7516 NTSTATUS status = NT_STATUS_OK;
7518 if (fsp == NULL || fsp->fh->fd == -1) {
7519 return NT_STATUS_INVALID_HANDLE;
7522 if (total_data != POSIX_LOCK_DATA_SIZE) {
7523 return NT_STATUS_INVALID_PARAMETER;
7526 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7527 case POSIX_LOCK_TYPE_READ:
7528 lock_type = READ_LOCK;
7529 break;
7530 case POSIX_LOCK_TYPE_WRITE:
7531 /* Return the right POSIX-mappable error code for files opened read-only. */
7532 if (!fsp->can_write) {
7533 return NT_STATUS_INVALID_HANDLE;
7535 lock_type = WRITE_LOCK;
7536 break;
7537 case POSIX_LOCK_TYPE_UNLOCK:
7538 lock_type = UNLOCK_LOCK;
7539 break;
7540 default:
7541 return NT_STATUS_INVALID_PARAMETER;
7544 switch (SVAL(pdata, POSIX_LOCK_FLAGS_OFFSET)) {
7545 case POSIX_LOCK_FLAG_NOWAIT:
7546 blocking_lock = false;
7547 break;
7548 case POSIX_LOCK_FLAG_WAIT:
7549 blocking_lock = true;
7550 break;
7551 default:
7552 return NT_STATUS_INVALID_PARAMETER;
7555 if (!lp_blocking_locks(SNUM(conn))) {
7556 blocking_lock = False;
7559 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7560 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7561 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7562 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7563 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7565 DBG_DEBUG("file %s, lock_type = %u, smblctx = %"PRIu64", "
7566 "count = %"PRIu64", offset = %"PRIu64"\n",
7567 fsp_str_dbg(fsp),
7568 (unsigned int)lock_type,
7569 smblctx,
7570 count,
7571 offset);
7573 if (lock_type == UNLOCK_LOCK) {
7574 struct smbd_lock_element l = {
7575 .smblctx = smblctx,
7576 .brltype = UNLOCK_LOCK,
7577 .offset = offset,
7578 .count = count,
7580 status = smbd_do_unlocking(req, fsp, 1, &l, POSIX_LOCK);
7581 return status;
7584 lck = talloc(req, struct smbd_lock_element);
7585 if (lck == NULL) {
7586 return NT_STATUS_NO_MEMORY;
7589 *lck = (struct smbd_lock_element) {
7590 .smblctx = smblctx,
7591 .brltype = lock_type,
7592 .count = count,
7593 .offset = offset,
7596 subreq = smbd_smb1_do_locks_send(
7597 fsp,
7598 req->sconn->ev_ctx,
7599 &req,
7600 fsp,
7601 blocking_lock ? UINT32_MAX : 0,
7602 true, /* large_offset */
7603 POSIX_LOCK,
7605 lck);
7606 if (subreq == NULL) {
7607 TALLOC_FREE(lck);
7608 return NT_STATUS_NO_MEMORY;
7610 tevent_req_set_callback(subreq, smb_set_posix_lock_done, req);
7611 return NT_STATUS_EVENT_PENDING;
7614 static void smb_set_posix_lock_done(struct tevent_req *subreq)
7616 struct smb_request *req = NULL;
7617 NTSTATUS status;
7618 bool ok;
7620 ok = smbd_smb1_do_locks_extract_smbreq(subreq, talloc_tos(), &req);
7621 SMB_ASSERT(ok);
7623 status = smbd_smb1_do_locks_recv(subreq);
7624 TALLOC_FREE(subreq);
7626 if (NT_STATUS_IS_OK(status)) {
7627 char params[2] = {0};
7628 /* Fake up max_data_bytes here - we know it fits. */
7629 send_trans2_replies(
7630 req->conn,
7631 req,
7632 NT_STATUS_OK,
7633 params,
7635 NULL,
7637 0xffff);
7638 } else {
7639 reply_nterror(req, status);
7640 ok = srv_send_smb(
7641 req->xconn,
7642 (char *)req->outbuf,
7643 true,
7644 req->seqnum+1,
7645 IS_CONN_ENCRYPTED(req->conn),
7646 NULL);
7647 if (!ok) {
7648 exit_server_cleanly("smb_set_posix_lock_done: "
7649 "srv_send_smb failed.");
7653 TALLOC_FREE(req);
7654 return;
7657 /****************************************************************************
7658 Deal with SMB_SET_FILE_BASIC_INFO.
7659 ****************************************************************************/
7661 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7662 const char *pdata,
7663 int total_data,
7664 files_struct *fsp,
7665 const struct smb_filename *smb_fname)
7667 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7668 struct smb_file_time ft;
7669 uint32_t dosmode = 0;
7670 NTSTATUS status = NT_STATUS_OK;
7672 ZERO_STRUCT(ft);
7674 if (total_data < 36) {
7675 return NT_STATUS_INVALID_PARAMETER;
7678 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7679 if (!NT_STATUS_IS_OK(status)) {
7680 return status;
7683 /* Set the attributes */
7684 dosmode = IVAL(pdata,32);
7685 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7686 if (!NT_STATUS_IS_OK(status)) {
7687 return status;
7690 /* create time */
7691 ft.create_time = interpret_long_date(pdata);
7693 /* access time */
7694 ft.atime = interpret_long_date(pdata+8);
7696 /* write time. */
7697 ft.mtime = interpret_long_date(pdata+16);
7699 /* change time. */
7700 ft.ctime = interpret_long_date(pdata+24);
7702 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7703 smb_fname_str_dbg(smb_fname)));
7705 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7706 true);
7709 /****************************************************************************
7710 Deal with SMB_INFO_STANDARD.
7711 ****************************************************************************/
7713 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7714 const char *pdata,
7715 int total_data,
7716 files_struct *fsp,
7717 const struct smb_filename *smb_fname)
7719 NTSTATUS status;
7720 struct smb_file_time ft;
7722 ZERO_STRUCT(ft);
7724 if (total_data < 12) {
7725 return NT_STATUS_INVALID_PARAMETER;
7728 /* create time */
7729 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7730 /* access time */
7731 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7732 /* write time */
7733 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7735 DEBUG(10,("smb_set_info_standard: file %s\n",
7736 smb_fname_str_dbg(smb_fname)));
7738 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7739 if (!NT_STATUS_IS_OK(status)) {
7740 return status;
7743 return smb_set_file_time(conn,
7744 fsp,
7745 smb_fname,
7746 &ft,
7747 true);
7750 /****************************************************************************
7751 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7752 ****************************************************************************/
7754 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7755 struct smb_request *req,
7756 const char *pdata,
7757 int total_data,
7758 files_struct *fsp,
7759 struct smb_filename *smb_fname)
7761 uint64_t allocation_size = 0;
7762 NTSTATUS status = NT_STATUS_OK;
7763 files_struct *new_fsp = NULL;
7765 if (!VALID_STAT(smb_fname->st)) {
7766 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7769 if (total_data < 8) {
7770 return NT_STATUS_INVALID_PARAMETER;
7773 allocation_size = (uint64_t)IVAL(pdata,0);
7774 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7775 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7776 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7777 (double)allocation_size));
7779 if (allocation_size) {
7780 allocation_size = smb_roundup(conn, allocation_size);
7783 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7784 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7785 (double)allocation_size));
7787 if (fsp && fsp->fh->fd != -1) {
7788 /* Open file handle. */
7789 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7790 return NT_STATUS_ACCESS_DENIED;
7793 /* Only change if needed. */
7794 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7795 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7796 return map_nt_error_from_unix(errno);
7799 /* But always update the time. */
7801 * This is equivalent to a write. Ensure it's seen immediately
7802 * if there are no pending writes.
7804 trigger_write_time_update_immediate(fsp);
7805 return NT_STATUS_OK;
7808 /* Pathname or stat or directory file. */
7809 status = SMB_VFS_CREATE_FILE(
7810 conn, /* conn */
7811 req, /* req */
7812 0, /* root_dir_fid */
7813 smb_fname, /* fname */
7814 FILE_WRITE_DATA, /* access_mask */
7815 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7816 FILE_SHARE_DELETE),
7817 FILE_OPEN, /* create_disposition*/
7818 0, /* create_options */
7819 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7820 0, /* oplock_request */
7821 NULL, /* lease */
7822 0, /* allocation_size */
7823 0, /* private_flags */
7824 NULL, /* sd */
7825 NULL, /* ea_list */
7826 &new_fsp, /* result */
7827 NULL, /* pinfo */
7828 NULL, NULL); /* create context */
7830 if (!NT_STATUS_IS_OK(status)) {
7831 /* NB. We check for open_was_deferred in the caller. */
7832 return status;
7835 /* Only change if needed. */
7836 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7837 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7838 status = map_nt_error_from_unix(errno);
7839 close_file(req, new_fsp, NORMAL_CLOSE);
7840 return status;
7844 /* Changing the allocation size should set the last mod time. */
7846 * This is equivalent to a write. Ensure it's seen immediately
7847 * if there are no pending writes.
7849 trigger_write_time_update_immediate(new_fsp);
7850 close_file(req, new_fsp, NORMAL_CLOSE);
7851 return NT_STATUS_OK;
7854 /****************************************************************************
7855 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7856 ****************************************************************************/
7858 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7859 struct smb_request *req,
7860 const char *pdata,
7861 int total_data,
7862 files_struct *fsp,
7863 const struct smb_filename *smb_fname,
7864 bool fail_after_createfile)
7866 off_t size;
7868 if (total_data < 8) {
7869 return NT_STATUS_INVALID_PARAMETER;
7872 size = IVAL(pdata,0);
7873 size |= (((off_t)IVAL(pdata,4)) << 32);
7874 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7875 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7876 (double)size));
7878 return smb_set_file_size(conn, req,
7879 fsp,
7880 smb_fname,
7881 &smb_fname->st,
7882 size,
7883 fail_after_createfile);
7886 /****************************************************************************
7887 Allow a UNIX info mknod.
7888 ****************************************************************************/
7890 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7891 const char *pdata,
7892 int total_data,
7893 const struct smb_filename *smb_fname)
7895 uint32_t file_type = IVAL(pdata,56);
7896 #if defined(HAVE_MAKEDEV)
7897 uint32_t dev_major = IVAL(pdata,60);
7898 uint32_t dev_minor = IVAL(pdata,68);
7899 #endif
7900 SMB_DEV_T dev = (SMB_DEV_T)0;
7901 uint32_t raw_unixmode = IVAL(pdata,84);
7902 NTSTATUS status;
7903 mode_t unixmode;
7905 if (total_data < 100) {
7906 return NT_STATUS_INVALID_PARAMETER;
7909 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7910 PERM_NEW_FILE, &unixmode);
7911 if (!NT_STATUS_IS_OK(status)) {
7912 return status;
7915 #if defined(HAVE_MAKEDEV)
7916 dev = makedev(dev_major, dev_minor);
7917 #endif
7919 switch (file_type) {
7920 #if defined(S_IFIFO)
7921 case UNIX_TYPE_FIFO:
7922 unixmode |= S_IFIFO;
7923 break;
7924 #endif
7925 #if defined(S_IFSOCK)
7926 case UNIX_TYPE_SOCKET:
7927 unixmode |= S_IFSOCK;
7928 break;
7929 #endif
7930 #if defined(S_IFCHR)
7931 case UNIX_TYPE_CHARDEV:
7932 unixmode |= S_IFCHR;
7933 break;
7934 #endif
7935 #if defined(S_IFBLK)
7936 case UNIX_TYPE_BLKDEV:
7937 unixmode |= S_IFBLK;
7938 break;
7939 #endif
7940 default:
7941 return NT_STATUS_INVALID_PARAMETER;
7944 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7945 "%.0f mode 0%o for file %s\n", (double)dev,
7946 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7948 /* Ok - do the mknod. */
7949 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7950 return map_nt_error_from_unix(errno);
7953 /* If any of the other "set" calls fail we
7954 * don't want to end up with a half-constructed mknod.
7957 if (lp_inherit_permissions(SNUM(conn))) {
7958 char *parent;
7959 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7960 &parent, NULL)) {
7961 return NT_STATUS_NO_MEMORY;
7963 inherit_access_posix_acl(conn, parent, smb_fname,
7964 unixmode);
7965 TALLOC_FREE(parent);
7968 return NT_STATUS_OK;
7971 /****************************************************************************
7972 Deal with SMB_SET_FILE_UNIX_BASIC.
7973 ****************************************************************************/
7975 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7976 struct smb_request *req,
7977 const char *pdata,
7978 int total_data,
7979 files_struct *fsp,
7980 const struct smb_filename *smb_fname)
7982 struct smb_file_time ft;
7983 uint32_t raw_unixmode;
7984 mode_t unixmode;
7985 off_t size = 0;
7986 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7987 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7988 NTSTATUS status = NT_STATUS_OK;
7989 bool delete_on_fail = False;
7990 enum perm_type ptype;
7991 files_struct *all_fsps = NULL;
7992 bool modify_mtime = true;
7993 struct file_id id;
7994 struct smb_filename *smb_fname_tmp = NULL;
7995 SMB_STRUCT_STAT sbuf;
7997 ZERO_STRUCT(ft);
7999 if (total_data < 100) {
8000 return NT_STATUS_INVALID_PARAMETER;
8003 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
8004 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
8005 size=IVAL(pdata,0); /* first 8 Bytes are size */
8006 size |= (((off_t)IVAL(pdata,4)) << 32);
8009 ft.atime = interpret_long_date(pdata+24); /* access_time */
8010 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
8011 set_owner = (uid_t)IVAL(pdata,40);
8012 set_grp = (gid_t)IVAL(pdata,48);
8013 raw_unixmode = IVAL(pdata,84);
8015 if (VALID_STAT(smb_fname->st)) {
8016 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
8017 ptype = PERM_EXISTING_DIR;
8018 } else {
8019 ptype = PERM_EXISTING_FILE;
8021 } else {
8022 ptype = PERM_NEW_FILE;
8025 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8026 ptype, &unixmode);
8027 if (!NT_STATUS_IS_OK(status)) {
8028 return status;
8031 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
8032 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
8033 smb_fname_str_dbg(smb_fname), (double)size,
8034 (unsigned int)set_owner, (unsigned int)set_grp,
8035 (int)raw_unixmode));
8037 sbuf = smb_fname->st;
8039 if (!VALID_STAT(sbuf)) {
8041 * The only valid use of this is to create character and block
8042 * devices, and named pipes. This is deprecated (IMHO) and
8043 * a new info level should be used for mknod. JRA.
8046 status = smb_unix_mknod(conn,
8047 pdata,
8048 total_data,
8049 smb_fname);
8050 if (!NT_STATUS_IS_OK(status)) {
8051 return status;
8054 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
8055 if (smb_fname_tmp == NULL) {
8056 return NT_STATUS_NO_MEMORY;
8059 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
8060 status = map_nt_error_from_unix(errno);
8061 TALLOC_FREE(smb_fname_tmp);
8062 SMB_VFS_UNLINK(conn, smb_fname);
8063 return status;
8066 sbuf = smb_fname_tmp->st;
8067 smb_fname = smb_fname_tmp;
8069 /* Ensure we don't try and change anything else. */
8070 raw_unixmode = SMB_MODE_NO_CHANGE;
8071 size = get_file_size_stat(&sbuf);
8072 ft.atime = sbuf.st_ex_atime;
8073 ft.mtime = sbuf.st_ex_mtime;
8075 * We continue here as we might want to change the
8076 * owner uid/gid.
8078 delete_on_fail = True;
8081 #if 1
8082 /* Horrible backwards compatibility hack as an old server bug
8083 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
8084 * */
8086 if (!size) {
8087 size = get_file_size_stat(&sbuf);
8089 #endif
8092 * Deal with the UNIX specific mode set.
8095 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
8096 int ret;
8098 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8099 "setting mode 0%o for file %s\n",
8100 (unsigned int)unixmode,
8101 smb_fname_str_dbg(smb_fname)));
8102 if (fsp && fsp->fh->fd != -1) {
8103 ret = SMB_VFS_FCHMOD(fsp, unixmode);
8104 } else {
8105 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
8107 if (ret != 0) {
8108 return map_nt_error_from_unix(errno);
8113 * Deal with the UNIX specific uid set.
8116 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
8117 (sbuf.st_ex_uid != set_owner)) {
8118 int ret;
8120 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8121 "changing owner %u for path %s\n",
8122 (unsigned int)set_owner,
8123 smb_fname_str_dbg(smb_fname)));
8125 if (fsp && fsp->fh->fd != -1) {
8126 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
8127 } else {
8129 * UNIX extensions calls must always operate
8130 * on symlinks.
8132 ret = SMB_VFS_LCHOWN(conn, smb_fname,
8133 set_owner, (gid_t)-1);
8136 if (ret != 0) {
8137 status = map_nt_error_from_unix(errno);
8138 if (delete_on_fail) {
8139 SMB_VFS_UNLINK(conn, smb_fname);
8141 return status;
8146 * Deal with the UNIX specific gid set.
8149 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
8150 (sbuf.st_ex_gid != set_grp)) {
8151 int ret;
8153 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
8154 "changing group %u for file %s\n",
8155 (unsigned int)set_grp,
8156 smb_fname_str_dbg(smb_fname)));
8157 if (fsp && fsp->fh->fd != -1) {
8158 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
8159 } else {
8161 * UNIX extensions calls must always operate
8162 * on symlinks.
8164 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
8165 set_grp);
8167 if (ret != 0) {
8168 status = map_nt_error_from_unix(errno);
8169 if (delete_on_fail) {
8170 SMB_VFS_UNLINK(conn, smb_fname);
8172 return status;
8176 /* Deal with any size changes. */
8178 status = smb_set_file_size(conn, req,
8179 fsp,
8180 smb_fname,
8181 &sbuf,
8182 size,
8183 false);
8184 if (!NT_STATUS_IS_OK(status)) {
8185 return status;
8188 /* Deal with any time changes. */
8189 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
8190 /* No change, don't cancel anything. */
8191 return status;
8194 id = vfs_file_id_from_sbuf(conn, &sbuf);
8195 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
8196 all_fsps = file_find_di_next(all_fsps)) {
8198 * We're setting the time explicitly for UNIX.
8199 * Cancel any pending changes over all handles.
8201 all_fsps->update_write_time_on_close = false;
8202 TALLOC_FREE(all_fsps->update_write_time_event);
8206 * Override the "setting_write_time"
8207 * parameter here as it almost does what
8208 * we need. Just remember if we modified
8209 * mtime and send the notify ourselves.
8211 if (null_timespec(ft.mtime)) {
8212 modify_mtime = false;
8215 status = smb_set_file_time(conn,
8216 fsp,
8217 smb_fname,
8218 &ft,
8219 false);
8220 if (modify_mtime) {
8221 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
8222 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
8224 return status;
8227 /****************************************************************************
8228 Deal with SMB_SET_FILE_UNIX_INFO2.
8229 ****************************************************************************/
8231 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
8232 struct smb_request *req,
8233 const char *pdata,
8234 int total_data,
8235 files_struct *fsp,
8236 const struct smb_filename *smb_fname)
8238 NTSTATUS status;
8239 uint32_t smb_fflags;
8240 uint32_t smb_fmask;
8242 if (total_data < 116) {
8243 return NT_STATUS_INVALID_PARAMETER;
8246 /* Start by setting all the fields that are common between UNIX_BASIC
8247 * and UNIX_INFO2.
8249 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
8250 fsp, smb_fname);
8251 if (!NT_STATUS_IS_OK(status)) {
8252 return status;
8255 smb_fflags = IVAL(pdata, 108);
8256 smb_fmask = IVAL(pdata, 112);
8258 /* NB: We should only attempt to alter the file flags if the client
8259 * sends a non-zero mask.
8261 if (smb_fmask != 0) {
8262 int stat_fflags = 0;
8264 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
8265 smb_fmask, &stat_fflags)) {
8266 /* Client asked to alter a flag we don't understand. */
8267 return NT_STATUS_INVALID_PARAMETER;
8270 if (fsp && fsp->fh->fd != -1) {
8271 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
8272 return NT_STATUS_NOT_SUPPORTED;
8273 } else {
8274 if (SMB_VFS_CHFLAGS(conn, smb_fname,
8275 stat_fflags) != 0) {
8276 return map_nt_error_from_unix(errno);
8281 /* XXX: need to add support for changing the create_time here. You
8282 * can do this for paths on Darwin with setattrlist(2). The right way
8283 * to hook this up is probably by extending the VFS utimes interface.
8286 return NT_STATUS_OK;
8289 /****************************************************************************
8290 Create a directory with POSIX semantics.
8291 ****************************************************************************/
8293 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
8294 struct smb_request *req,
8295 char **ppdata,
8296 int total_data,
8297 struct smb_filename *smb_fname,
8298 int *pdata_return_size)
8300 NTSTATUS status = NT_STATUS_OK;
8301 uint32_t raw_unixmode = 0;
8302 uint32_t mod_unixmode = 0;
8303 mode_t unixmode = (mode_t)0;
8304 files_struct *fsp = NULL;
8305 uint16_t info_level_return = 0;
8306 int info;
8307 char *pdata = *ppdata;
8309 if (total_data < 18) {
8310 return NT_STATUS_INVALID_PARAMETER;
8313 raw_unixmode = IVAL(pdata,8);
8314 /* Next 4 bytes are not yet defined. */
8316 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8317 PERM_NEW_DIR, &unixmode);
8318 if (!NT_STATUS_IS_OK(status)) {
8319 return status;
8322 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8324 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
8325 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
8327 status = SMB_VFS_CREATE_FILE(
8328 conn, /* conn */
8329 req, /* req */
8330 0, /* root_dir_fid */
8331 smb_fname, /* fname */
8332 FILE_READ_ATTRIBUTES, /* access_mask */
8333 FILE_SHARE_NONE, /* share_access */
8334 FILE_CREATE, /* create_disposition*/
8335 FILE_DIRECTORY_FILE, /* create_options */
8336 mod_unixmode, /* file_attributes */
8337 0, /* oplock_request */
8338 NULL, /* lease */
8339 0, /* allocation_size */
8340 0, /* private_flags */
8341 NULL, /* sd */
8342 NULL, /* ea_list */
8343 &fsp, /* result */
8344 &info, /* pinfo */
8345 NULL, NULL); /* create context */
8347 if (NT_STATUS_IS_OK(status)) {
8348 close_file(req, fsp, NORMAL_CLOSE);
8351 info_level_return = SVAL(pdata,16);
8353 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8354 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8355 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8356 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8357 } else {
8358 *pdata_return_size = 12;
8361 /* Realloc the data size */
8362 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8363 if (*ppdata == NULL) {
8364 *pdata_return_size = 0;
8365 return NT_STATUS_NO_MEMORY;
8367 pdata = *ppdata;
8369 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8370 SSVAL(pdata,2,0); /* No fnum. */
8371 SIVAL(pdata,4,info); /* Was directory created. */
8373 switch (info_level_return) {
8374 case SMB_QUERY_FILE_UNIX_BASIC:
8375 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8376 SSVAL(pdata,10,0); /* Padding. */
8377 store_file_unix_basic(conn, pdata + 12, fsp,
8378 &smb_fname->st);
8379 break;
8380 case SMB_QUERY_FILE_UNIX_INFO2:
8381 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8382 SSVAL(pdata,10,0); /* Padding. */
8383 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8384 &smb_fname->st);
8385 break;
8386 default:
8387 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8388 SSVAL(pdata,10,0); /* Padding. */
8389 break;
8392 return status;
8395 /****************************************************************************
8396 Open/Create a file with POSIX semantics.
8397 ****************************************************************************/
8399 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8400 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8402 static NTSTATUS smb_posix_open(connection_struct *conn,
8403 struct smb_request *req,
8404 char **ppdata,
8405 int total_data,
8406 struct smb_filename *smb_fname,
8407 int *pdata_return_size)
8409 bool extended_oplock_granted = False;
8410 char *pdata = *ppdata;
8411 uint32_t flags = 0;
8412 uint32_t wire_open_mode = 0;
8413 uint32_t raw_unixmode = 0;
8414 uint32_t mod_unixmode = 0;
8415 uint32_t create_disp = 0;
8416 uint32_t access_mask = 0;
8417 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8418 NTSTATUS status = NT_STATUS_OK;
8419 mode_t unixmode = (mode_t)0;
8420 files_struct *fsp = NULL;
8421 int oplock_request = 0;
8422 int info = 0;
8423 uint16_t info_level_return = 0;
8425 if (total_data < 18) {
8426 return NT_STATUS_INVALID_PARAMETER;
8429 flags = IVAL(pdata,0);
8430 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8431 if (oplock_request) {
8432 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8435 wire_open_mode = IVAL(pdata,4);
8437 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8438 return smb_posix_mkdir(conn, req,
8439 ppdata,
8440 total_data,
8441 smb_fname,
8442 pdata_return_size);
8445 switch (wire_open_mode & SMB_ACCMODE) {
8446 case SMB_O_RDONLY:
8447 access_mask = SMB_O_RDONLY_MAPPING;
8448 break;
8449 case SMB_O_WRONLY:
8450 access_mask = SMB_O_WRONLY_MAPPING;
8451 break;
8452 case SMB_O_RDWR:
8453 access_mask = (SMB_O_RDONLY_MAPPING|
8454 SMB_O_WRONLY_MAPPING);
8455 break;
8456 default:
8457 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8458 (unsigned int)wire_open_mode ));
8459 return NT_STATUS_INVALID_PARAMETER;
8462 wire_open_mode &= ~SMB_ACCMODE;
8464 /* First take care of O_CREAT|O_EXCL interactions. */
8465 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8466 case (SMB_O_CREAT | SMB_O_EXCL):
8467 /* File exists fail. File not exist create. */
8468 create_disp = FILE_CREATE;
8469 break;
8470 case SMB_O_CREAT:
8471 /* File exists open. File not exist create. */
8472 create_disp = FILE_OPEN_IF;
8473 break;
8474 case SMB_O_EXCL:
8475 /* O_EXCL on its own without O_CREAT is undefined.
8476 We deliberately ignore it as some versions of
8477 Linux CIFSFS can send a bare O_EXCL on the
8478 wire which other filesystems in the kernel
8479 ignore. See bug 9519 for details. */
8481 /* Fallthrough. */
8483 case 0:
8484 /* File exists open. File not exist fail. */
8485 create_disp = FILE_OPEN;
8486 break;
8487 default:
8488 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8489 (unsigned int)wire_open_mode ));
8490 return NT_STATUS_INVALID_PARAMETER;
8493 /* Next factor in the effects of O_TRUNC. */
8494 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8496 if (wire_open_mode & SMB_O_TRUNC) {
8497 switch (create_disp) {
8498 case FILE_CREATE:
8499 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8500 /* Leave create_disp alone as
8501 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8503 /* File exists fail. File not exist create. */
8504 break;
8505 case FILE_OPEN_IF:
8506 /* SMB_O_CREAT | SMB_O_TRUNC */
8507 /* File exists overwrite. File not exist create. */
8508 create_disp = FILE_OVERWRITE_IF;
8509 break;
8510 case FILE_OPEN:
8511 /* SMB_O_TRUNC */
8512 /* File exists overwrite. File not exist fail. */
8513 create_disp = FILE_OVERWRITE;
8514 break;
8515 default:
8516 /* Cannot get here. */
8517 smb_panic("smb_posix_open: logic error");
8518 return NT_STATUS_INVALID_PARAMETER;
8522 raw_unixmode = IVAL(pdata,8);
8523 /* Next 4 bytes are not yet defined. */
8525 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8526 (VALID_STAT(smb_fname->st) ?
8527 PERM_EXISTING_FILE : PERM_NEW_FILE),
8528 &unixmode);
8530 if (!NT_STATUS_IS_OK(status)) {
8531 return status;
8534 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8536 if (wire_open_mode & SMB_O_SYNC) {
8537 create_options |= FILE_WRITE_THROUGH;
8539 if (wire_open_mode & SMB_O_APPEND) {
8540 access_mask |= FILE_APPEND_DATA;
8542 if (wire_open_mode & SMB_O_DIRECT) {
8543 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8546 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8547 VALID_STAT_OF_DIR(smb_fname->st)) {
8548 if (access_mask != SMB_O_RDONLY_MAPPING) {
8549 return NT_STATUS_FILE_IS_A_DIRECTORY;
8551 create_options &= ~FILE_NON_DIRECTORY_FILE;
8552 create_options |= FILE_DIRECTORY_FILE;
8555 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8556 smb_fname_str_dbg(smb_fname),
8557 (unsigned int)wire_open_mode,
8558 (unsigned int)unixmode ));
8560 status = SMB_VFS_CREATE_FILE(
8561 conn, /* conn */
8562 req, /* req */
8563 0, /* root_dir_fid */
8564 smb_fname, /* fname */
8565 access_mask, /* access_mask */
8566 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8567 FILE_SHARE_DELETE),
8568 create_disp, /* create_disposition*/
8569 create_options, /* create_options */
8570 mod_unixmode, /* file_attributes */
8571 oplock_request, /* oplock_request */
8572 NULL, /* lease */
8573 0, /* allocation_size */
8574 0, /* private_flags */
8575 NULL, /* sd */
8576 NULL, /* ea_list */
8577 &fsp, /* result */
8578 &info, /* pinfo */
8579 NULL, NULL); /* create context */
8581 if (!NT_STATUS_IS_OK(status)) {
8582 return status;
8585 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8586 extended_oplock_granted = True;
8589 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8590 extended_oplock_granted = True;
8593 info_level_return = SVAL(pdata,16);
8595 /* Allocate the correct return size. */
8597 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8598 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8599 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8600 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8601 } else {
8602 *pdata_return_size = 12;
8605 /* Realloc the data size */
8606 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8607 if (*ppdata == NULL) {
8608 close_file(req, fsp, ERROR_CLOSE);
8609 *pdata_return_size = 0;
8610 return NT_STATUS_NO_MEMORY;
8612 pdata = *ppdata;
8614 if (extended_oplock_granted) {
8615 if (flags & REQUEST_BATCH_OPLOCK) {
8616 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8617 } else {
8618 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8620 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8621 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8622 } else {
8623 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8626 SSVAL(pdata,2,fsp->fnum);
8627 SIVAL(pdata,4,info); /* Was file created etc. */
8629 switch (info_level_return) {
8630 case SMB_QUERY_FILE_UNIX_BASIC:
8631 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8632 SSVAL(pdata,10,0); /* padding. */
8633 store_file_unix_basic(conn, pdata + 12, fsp,
8634 &smb_fname->st);
8635 break;
8636 case SMB_QUERY_FILE_UNIX_INFO2:
8637 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8638 SSVAL(pdata,10,0); /* padding. */
8639 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8640 &smb_fname->st);
8641 break;
8642 default:
8643 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8644 SSVAL(pdata,10,0); /* padding. */
8645 break;
8647 return NT_STATUS_OK;
8650 /****************************************************************************
8651 Delete a file with POSIX semantics.
8652 ****************************************************************************/
8654 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8655 struct smb_request *req,
8656 const char *pdata,
8657 int total_data,
8658 struct smb_filename *smb_fname)
8660 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8661 NTSTATUS status = NT_STATUS_OK;
8662 files_struct *fsp = NULL;
8663 uint16_t flags = 0;
8664 char del = 1;
8665 int info = 0;
8666 int create_options = 0;
8667 struct share_mode_lock *lck = NULL;
8668 bool other_nonposix_opens;
8670 if (total_data < 2) {
8671 return NT_STATUS_INVALID_PARAMETER;
8674 flags = SVAL(pdata,0);
8676 if (!VALID_STAT(smb_fname->st)) {
8677 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8680 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8681 !VALID_STAT_OF_DIR(smb_fname->st)) {
8682 return NT_STATUS_NOT_A_DIRECTORY;
8685 DEBUG(10,("smb_posix_unlink: %s %s\n",
8686 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8687 smb_fname_str_dbg(smb_fname)));
8689 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8690 create_options |= FILE_DIRECTORY_FILE;
8693 status = SMB_VFS_CREATE_FILE(
8694 conn, /* conn */
8695 req, /* req */
8696 0, /* root_dir_fid */
8697 smb_fname, /* fname */
8698 DELETE_ACCESS, /* access_mask */
8699 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8700 FILE_SHARE_DELETE),
8701 FILE_OPEN, /* create_disposition*/
8702 create_options, /* create_options */
8703 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8704 0, /* oplock_request */
8705 NULL, /* lease */
8706 0, /* allocation_size */
8707 0, /* private_flags */
8708 NULL, /* sd */
8709 NULL, /* ea_list */
8710 &fsp, /* result */
8711 &info, /* pinfo */
8712 NULL, NULL); /* create context */
8714 if (!NT_STATUS_IS_OK(status)) {
8715 return status;
8719 * Don't lie to client. If we can't really delete due to
8720 * non-POSIX opens return SHARING_VIOLATION.
8723 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8724 if (lck == NULL) {
8725 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8726 "lock for file %s\n", fsp_str_dbg(fsp)));
8727 close_file(req, fsp, NORMAL_CLOSE);
8728 return NT_STATUS_INVALID_PARAMETER;
8731 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8732 if (other_nonposix_opens) {
8733 /* Fail with sharing violation. */
8734 TALLOC_FREE(lck);
8735 close_file(req, fsp, NORMAL_CLOSE);
8736 return NT_STATUS_SHARING_VIOLATION;
8740 * Set the delete on close.
8742 status = smb_set_file_disposition_info(conn,
8743 &del,
8745 fsp,
8746 smb_fname);
8748 TALLOC_FREE(lck);
8750 if (!NT_STATUS_IS_OK(status)) {
8751 close_file(req, fsp, NORMAL_CLOSE);
8752 return status;
8754 return close_file(req, fsp, NORMAL_CLOSE);
8757 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8758 struct smb_request *req,
8759 TALLOC_CTX *mem_ctx,
8760 uint16_t info_level,
8761 files_struct *fsp,
8762 struct smb_filename *smb_fname,
8763 char **ppdata, int total_data,
8764 int *ret_data_size)
8766 char *pdata = *ppdata;
8767 NTSTATUS status = NT_STATUS_OK;
8768 int data_return_size = 0;
8770 *ret_data_size = 0;
8772 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8773 return NT_STATUS_INVALID_LEVEL;
8776 if (!CAN_WRITE(conn)) {
8777 /* Allow POSIX opens. The open path will deny
8778 * any non-readonly opens. */
8779 if (info_level != SMB_POSIX_PATH_OPEN) {
8780 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8784 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8785 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8786 fsp_fnum_dbg(fsp),
8787 info_level, total_data));
8789 switch (info_level) {
8791 case SMB_INFO_STANDARD:
8793 status = smb_set_info_standard(conn,
8794 pdata,
8795 total_data,
8796 fsp,
8797 smb_fname);
8798 break;
8801 case SMB_INFO_SET_EA:
8803 status = smb_info_set_ea(conn,
8804 pdata,
8805 total_data,
8806 fsp,
8807 smb_fname);
8808 break;
8811 case SMB_SET_FILE_BASIC_INFO:
8812 case SMB_FILE_BASIC_INFORMATION:
8814 status = smb_set_file_basic_info(conn,
8815 pdata,
8816 total_data,
8817 fsp,
8818 smb_fname);
8819 break;
8822 case SMB_FILE_ALLOCATION_INFORMATION:
8823 case SMB_SET_FILE_ALLOCATION_INFO:
8825 status = smb_set_file_allocation_info(conn, req,
8826 pdata,
8827 total_data,
8828 fsp,
8829 smb_fname);
8830 break;
8833 case SMB_FILE_END_OF_FILE_INFORMATION:
8834 case SMB_SET_FILE_END_OF_FILE_INFO:
8837 * XP/Win7 both fail after the createfile with
8838 * SMB_SET_FILE_END_OF_FILE_INFO but not
8839 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8840 * The level is known here, so pass it down
8841 * appropriately.
8843 bool should_fail =
8844 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8846 status = smb_set_file_end_of_file_info(conn, req,
8847 pdata,
8848 total_data,
8849 fsp,
8850 smb_fname,
8851 should_fail);
8852 break;
8855 case SMB_FILE_DISPOSITION_INFORMATION:
8856 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8858 #if 0
8859 /* JRA - We used to just ignore this on a path ?
8860 * Shouldn't this be invalid level on a pathname
8861 * based call ?
8863 if (tran_call != TRANSACT2_SETFILEINFO) {
8864 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8866 #endif
8867 status = smb_set_file_disposition_info(conn,
8868 pdata,
8869 total_data,
8870 fsp,
8871 smb_fname);
8872 break;
8875 case SMB_FILE_POSITION_INFORMATION:
8877 status = smb_file_position_information(conn,
8878 pdata,
8879 total_data,
8880 fsp);
8881 break;
8884 case SMB_FILE_FULL_EA_INFORMATION:
8886 status = smb_set_file_full_ea_info(conn,
8887 pdata,
8888 total_data,
8889 fsp);
8890 break;
8893 /* From tridge Samba4 :
8894 * MODE_INFORMATION in setfileinfo (I have no
8895 * idea what "mode information" on a file is - it takes a value of 0,
8896 * 2, 4 or 6. What could it be?).
8899 case SMB_FILE_MODE_INFORMATION:
8901 status = smb_file_mode_information(conn,
8902 pdata,
8903 total_data);
8904 break;
8907 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8908 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8909 case SMB_FILE_SHORT_NAME_INFORMATION:
8910 return NT_STATUS_NOT_SUPPORTED;
8913 * CIFS UNIX extensions.
8916 case SMB_SET_FILE_UNIX_BASIC:
8918 status = smb_set_file_unix_basic(conn, req,
8919 pdata,
8920 total_data,
8921 fsp,
8922 smb_fname);
8923 break;
8926 case SMB_SET_FILE_UNIX_INFO2:
8928 status = smb_set_file_unix_info2(conn, req,
8929 pdata,
8930 total_data,
8931 fsp,
8932 smb_fname);
8933 break;
8936 case SMB_SET_FILE_UNIX_LINK:
8938 if (fsp) {
8939 /* We must have a pathname for this. */
8940 return NT_STATUS_INVALID_LEVEL;
8942 status = smb_set_file_unix_link(conn, req, pdata,
8943 total_data, smb_fname);
8944 break;
8947 case SMB_SET_FILE_UNIX_HLINK:
8949 if (fsp) {
8950 /* We must have a pathname for this. */
8951 return NT_STATUS_INVALID_LEVEL;
8953 status = smb_set_file_unix_hlink(conn, req,
8954 pdata, total_data,
8955 smb_fname);
8956 break;
8959 case SMB_FILE_RENAME_INFORMATION:
8961 status = smb_file_rename_information(conn, req,
8962 pdata, total_data,
8963 fsp, smb_fname);
8964 break;
8967 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8969 /* SMB2 rename information. */
8970 status = smb2_file_rename_information(conn, req,
8971 pdata, total_data,
8972 fsp, smb_fname);
8973 break;
8976 case SMB_FILE_LINK_INFORMATION:
8978 status = smb_file_link_information(conn, req,
8979 pdata, total_data,
8980 fsp, smb_fname);
8981 break;
8984 #if defined(HAVE_POSIX_ACLS)
8985 case SMB_SET_POSIX_ACL:
8987 status = smb_set_posix_acl(conn,
8988 req,
8989 pdata,
8990 total_data,
8991 fsp,
8992 smb_fname);
8993 break;
8995 #endif
8997 case SMB_SET_POSIX_LOCK:
8999 if (!fsp) {
9000 return NT_STATUS_INVALID_LEVEL;
9002 status = smb_set_posix_lock(conn, req,
9003 pdata, total_data, fsp);
9004 break;
9007 case SMB_POSIX_PATH_OPEN:
9009 if (fsp) {
9010 /* We must have a pathname for this. */
9011 return NT_STATUS_INVALID_LEVEL;
9014 status = smb_posix_open(conn, req,
9015 ppdata,
9016 total_data,
9017 smb_fname,
9018 &data_return_size);
9019 break;
9022 case SMB_POSIX_PATH_UNLINK:
9024 if (fsp) {
9025 /* We must have a pathname for this. */
9026 return NT_STATUS_INVALID_LEVEL;
9029 status = smb_posix_unlink(conn, req,
9030 pdata,
9031 total_data,
9032 smb_fname);
9033 break;
9036 default:
9037 return NT_STATUS_INVALID_LEVEL;
9040 if (!NT_STATUS_IS_OK(status)) {
9041 return status;
9044 *ret_data_size = data_return_size;
9045 return NT_STATUS_OK;
9048 /****************************************************************************
9049 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
9050 ****************************************************************************/
9052 static void call_trans2setfilepathinfo(connection_struct *conn,
9053 struct smb_request *req,
9054 unsigned int tran_call,
9055 char **pparams, int total_params,
9056 char **ppdata, int total_data,
9057 unsigned int max_data_bytes)
9059 char *params = *pparams;
9060 char *pdata = *ppdata;
9061 uint16_t info_level;
9062 struct smb_filename *smb_fname = NULL;
9063 files_struct *fsp = NULL;
9064 NTSTATUS status = NT_STATUS_OK;
9065 int data_return_size = 0;
9067 if (!params) {
9068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9069 return;
9072 if (tran_call == TRANSACT2_SETFILEINFO) {
9073 if (total_params < 4) {
9074 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9075 return;
9078 fsp = file_fsp(req, SVAL(params,0));
9079 /* Basic check for non-null fsp. */
9080 if (!check_fsp_open(conn, req, fsp)) {
9081 return;
9083 info_level = SVAL(params,2);
9085 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
9086 if (smb_fname == NULL) {
9087 reply_nterror(req, NT_STATUS_NO_MEMORY);
9088 return;
9091 if(fsp->fh->fd == -1) {
9093 * This is actually a SETFILEINFO on a directory
9094 * handle (returned from an NT SMB). NT5.0 seems
9095 * to do this call. JRA.
9097 if (INFO_LEVEL_IS_UNIX(info_level)) {
9098 /* Always do lstat for UNIX calls. */
9099 if (SMB_VFS_LSTAT(conn, smb_fname)) {
9100 DEBUG(3,("call_trans2setfilepathinfo: "
9101 "SMB_VFS_LSTAT of %s failed "
9102 "(%s)\n",
9103 smb_fname_str_dbg(smb_fname),
9104 strerror(errno)));
9105 reply_nterror(req, map_nt_error_from_unix(errno));
9106 return;
9108 } else {
9109 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
9110 DEBUG(3,("call_trans2setfilepathinfo: "
9111 "fileinfo of %s failed (%s)\n",
9112 smb_fname_str_dbg(smb_fname),
9113 strerror(errno)));
9114 reply_nterror(req, map_nt_error_from_unix(errno));
9115 return;
9118 } else if (fsp->print_file) {
9120 * Doing a DELETE_ON_CLOSE should cancel a print job.
9122 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
9123 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
9125 DEBUG(3,("call_trans2setfilepathinfo: "
9126 "Cancelling print job (%s)\n",
9127 fsp_str_dbg(fsp)));
9129 SSVAL(params,0,0);
9130 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
9131 *ppdata, 0,
9132 max_data_bytes);
9133 return;
9134 } else {
9135 reply_nterror(req,
9136 NT_STATUS_OBJECT_PATH_NOT_FOUND);
9137 return;
9139 } else {
9141 * Original code - this is an open file.
9143 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
9144 DEBUG(3,("call_trans2setfilepathinfo: fstat "
9145 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
9146 strerror(errno)));
9147 reply_nterror(req, map_nt_error_from_unix(errno));
9148 return;
9151 } else {
9152 char *fname = NULL;
9153 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9155 /* set path info */
9156 if (total_params < 7) {
9157 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9158 return;
9161 info_level = SVAL(params,0);
9162 if (req->posix_pathnames) {
9163 srvstr_get_path_posix(req,
9164 params,
9165 req->flags2,
9166 &fname,
9167 &params[6],
9168 total_params - 6,
9169 STR_TERMINATE,
9170 &status);
9171 } else {
9172 srvstr_get_path(req,
9173 params,
9174 req->flags2,
9175 &fname,
9176 &params[6],
9177 total_params - 6,
9178 STR_TERMINATE,
9179 &status);
9181 if (!NT_STATUS_IS_OK(status)) {
9182 reply_nterror(req, status);
9183 return;
9186 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
9187 info_level == SMB_SET_FILE_UNIX_INFO2 ||
9188 info_level == SMB_FILE_RENAME_INFORMATION ||
9189 info_level == SMB_POSIX_PATH_OPEN ||
9190 info_level == SMB_POSIX_PATH_UNLINK) {
9191 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
9194 status = filename_convert(req, conn,
9195 fname,
9196 ucf_flags,
9197 NULL,
9198 NULL,
9199 &smb_fname);
9200 if (!NT_STATUS_IS_OK(status)) {
9201 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9202 reply_botherror(req,
9203 NT_STATUS_PATH_NOT_COVERED,
9204 ERRSRV, ERRbadpath);
9205 return;
9207 reply_nterror(req, status);
9208 return;
9211 if (INFO_LEVEL_IS_UNIX(info_level)) {
9213 * For CIFS UNIX extensions the target name may not exist.
9216 /* Always do lstat for UNIX calls. */
9217 SMB_VFS_LSTAT(conn, smb_fname);
9219 } else if (!VALID_STAT(smb_fname->st) &&
9220 SMB_VFS_STAT(conn, smb_fname)) {
9221 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
9222 "%s failed (%s)\n",
9223 smb_fname_str_dbg(smb_fname),
9224 strerror(errno)));
9225 reply_nterror(req, map_nt_error_from_unix(errno));
9226 return;
9230 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
9231 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
9232 fsp_fnum_dbg(fsp),
9233 info_level,total_data));
9235 /* Realloc the parameter size */
9236 *pparams = (char *)SMB_REALLOC(*pparams,2);
9237 if (*pparams == NULL) {
9238 reply_nterror(req, NT_STATUS_NO_MEMORY);
9239 return;
9241 params = *pparams;
9243 SSVAL(params,0,0);
9245 status = smbd_do_setfilepathinfo(conn, req, req,
9246 info_level,
9247 fsp,
9248 smb_fname,
9249 ppdata, total_data,
9250 &data_return_size);
9251 if (!NT_STATUS_IS_OK(status)) {
9252 if (open_was_deferred(req->xconn, req->mid)) {
9253 /* We have re-scheduled this call. */
9254 return;
9256 if (NT_STATUS_EQUAL(status, NT_STATUS_EVENT_PENDING)) {
9257 /* We have re-scheduled this call. */
9258 return;
9260 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9261 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
9262 ERRSRV, ERRbadpath);
9263 return;
9265 if (info_level == SMB_POSIX_PATH_OPEN) {
9266 reply_openerror(req, status);
9267 return;
9271 * Invalid EA name needs to return 2 param bytes,
9272 * not a zero-length error packet.
9274 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
9275 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
9276 max_data_bytes);
9277 } else {
9278 reply_nterror(req, status);
9280 return;
9283 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
9284 max_data_bytes);
9286 return;
9289 /****************************************************************************
9290 Reply to a TRANS2_MKDIR (make directory with extended attributes).
9291 ****************************************************************************/
9293 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
9294 char **pparams, int total_params,
9295 char **ppdata, int total_data,
9296 unsigned int max_data_bytes)
9298 struct smb_filename *smb_dname = NULL;
9299 char *params = *pparams;
9300 char *pdata = *ppdata;
9301 char *directory = NULL;
9302 NTSTATUS status = NT_STATUS_OK;
9303 struct ea_list *ea_list = NULL;
9304 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
9305 TALLOC_CTX *ctx = talloc_tos();
9307 if (!CAN_WRITE(conn)) {
9308 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9309 return;
9312 if (total_params < 5) {
9313 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9314 return;
9317 if (req->posix_pathnames) {
9318 srvstr_get_path_posix(ctx,
9319 params,
9320 req->flags2,
9321 &directory,
9322 &params[4],
9323 total_params - 4,
9324 STR_TERMINATE,
9325 &status);
9326 } else {
9327 srvstr_get_path(ctx,
9328 params,
9329 req->flags2,
9330 &directory,
9331 &params[4],
9332 total_params - 4,
9333 STR_TERMINATE,
9334 &status);
9336 if (!NT_STATUS_IS_OK(status)) {
9337 reply_nterror(req, status);
9338 return;
9341 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9343 status = filename_convert(ctx,
9344 conn,
9345 directory,
9346 ucf_flags,
9347 NULL,
9348 NULL,
9349 &smb_dname);
9351 if (!NT_STATUS_IS_OK(status)) {
9352 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9353 reply_botherror(req,
9354 NT_STATUS_PATH_NOT_COVERED,
9355 ERRSRV, ERRbadpath);
9356 return;
9358 reply_nterror(req, status);
9359 return;
9363 * OS/2 workplace shell seems to send SET_EA requests of "null"
9364 * length (4 bytes containing IVAL 4).
9365 * They seem to have no effect. Bug #3212. JRA.
9368 if (total_data && (total_data != 4)) {
9369 /* Any data in this call is an EA list. */
9370 if (total_data < 10) {
9371 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9372 goto out;
9375 if (IVAL(pdata,0) > total_data) {
9376 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9377 IVAL(pdata,0), (unsigned int)total_data));
9378 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9379 goto out;
9382 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9383 total_data - 4);
9384 if (!ea_list) {
9385 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9386 goto out;
9389 if (!lp_ea_support(SNUM(conn))) {
9390 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9391 goto out;
9394 /* If total_data == 4 Windows doesn't care what values
9395 * are placed in that field, it just ignores them.
9396 * The System i QNTC IBM SMB client puts bad values here,
9397 * so ignore them. */
9399 status = create_directory(conn, req, smb_dname);
9401 if (!NT_STATUS_IS_OK(status)) {
9402 reply_nterror(req, status);
9403 goto out;
9406 /* Try and set any given EA. */
9407 if (ea_list) {
9408 status = set_ea(conn, NULL, smb_dname, ea_list);
9409 if (!NT_STATUS_IS_OK(status)) {
9410 reply_nterror(req, status);
9411 goto out;
9415 /* Realloc the parameter and data sizes */
9416 *pparams = (char *)SMB_REALLOC(*pparams,2);
9417 if(*pparams == NULL) {
9418 reply_nterror(req, NT_STATUS_NO_MEMORY);
9419 goto out;
9421 params = *pparams;
9423 SSVAL(params,0,0);
9425 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9427 out:
9428 TALLOC_FREE(smb_dname);
9429 return;
9432 /****************************************************************************
9433 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9434 We don't actually do this - we just send a null response.
9435 ****************************************************************************/
9437 static void call_trans2findnotifyfirst(connection_struct *conn,
9438 struct smb_request *req,
9439 char **pparams, int total_params,
9440 char **ppdata, int total_data,
9441 unsigned int max_data_bytes)
9443 char *params = *pparams;
9444 uint16_t info_level;
9446 if (total_params < 6) {
9447 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9448 return;
9451 info_level = SVAL(params,4);
9452 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9454 switch (info_level) {
9455 case 1:
9456 case 2:
9457 break;
9458 default:
9459 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9460 return;
9463 /* Realloc the parameter and data sizes */
9464 *pparams = (char *)SMB_REALLOC(*pparams,6);
9465 if (*pparams == NULL) {
9466 reply_nterror(req, NT_STATUS_NO_MEMORY);
9467 return;
9469 params = *pparams;
9471 SSVAL(params,0,fnf_handle);
9472 SSVAL(params,2,0); /* No changes */
9473 SSVAL(params,4,0); /* No EA errors */
9475 fnf_handle++;
9477 if(fnf_handle == 0)
9478 fnf_handle = 257;
9480 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9482 return;
9485 /****************************************************************************
9486 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9487 changes). Currently this does nothing.
9488 ****************************************************************************/
9490 static void call_trans2findnotifynext(connection_struct *conn,
9491 struct smb_request *req,
9492 char **pparams, int total_params,
9493 char **ppdata, int total_data,
9494 unsigned int max_data_bytes)
9496 char *params = *pparams;
9498 DEBUG(3,("call_trans2findnotifynext\n"));
9500 /* Realloc the parameter and data sizes */
9501 *pparams = (char *)SMB_REALLOC(*pparams,4);
9502 if (*pparams == NULL) {
9503 reply_nterror(req, NT_STATUS_NO_MEMORY);
9504 return;
9506 params = *pparams;
9508 SSVAL(params,0,0); /* No changes */
9509 SSVAL(params,2,0); /* No EA errors */
9511 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9513 return;
9516 /****************************************************************************
9517 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9518 ****************************************************************************/
9520 static void call_trans2getdfsreferral(connection_struct *conn,
9521 struct smb_request *req,
9522 char **pparams, int total_params,
9523 char **ppdata, int total_data,
9524 unsigned int max_data_bytes)
9526 char *params = *pparams;
9527 char *pathname = NULL;
9528 int reply_size = 0;
9529 int max_referral_level;
9530 NTSTATUS status = NT_STATUS_OK;
9531 TALLOC_CTX *ctx = talloc_tos();
9533 DEBUG(10,("call_trans2getdfsreferral\n"));
9535 if (total_params < 3) {
9536 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9537 return;
9540 max_referral_level = SVAL(params,0);
9542 if(!lp_host_msdfs()) {
9543 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9544 return;
9547 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9548 total_params - 2, STR_TERMINATE);
9549 if (!pathname) {
9550 reply_nterror(req, NT_STATUS_NOT_FOUND);
9551 return;
9553 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9554 ppdata,&status)) < 0) {
9555 reply_nterror(req, status);
9556 return;
9559 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9560 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9561 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9563 return;
9566 #define LMCAT_SPL 0x53
9567 #define LMFUNC_GETJOBID 0x60
9569 /****************************************************************************
9570 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9571 ****************************************************************************/
9573 static void call_trans2ioctl(connection_struct *conn,
9574 struct smb_request *req,
9575 char **pparams, int total_params,
9576 char **ppdata, int total_data,
9577 unsigned int max_data_bytes)
9579 char *pdata = *ppdata;
9580 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9581 NTSTATUS status;
9582 size_t len = 0;
9584 /* check for an invalid fid before proceeding */
9586 if (!fsp) {
9587 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9588 return;
9591 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9592 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9593 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9594 if (*ppdata == NULL) {
9595 reply_nterror(req, NT_STATUS_NO_MEMORY);
9596 return;
9598 pdata = *ppdata;
9600 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9601 CAN ACCEPT THIS IN UNICODE. JRA. */
9603 /* Job number */
9604 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9606 status = srvstr_push(pdata, req->flags2, pdata + 2,
9607 lp_netbios_name(), 15,
9608 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9609 if (!NT_STATUS_IS_OK(status)) {
9610 reply_nterror(req, status);
9611 return;
9613 status = srvstr_push(pdata, req->flags2, pdata+18,
9614 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9615 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9616 if (!NT_STATUS_IS_OK(status)) {
9617 reply_nterror(req, status);
9618 return;
9620 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9621 max_data_bytes);
9622 return;
9625 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9626 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9629 /****************************************************************************
9630 Reply to a SMBfindclose (stop trans2 directory search).
9631 ****************************************************************************/
9633 void reply_findclose(struct smb_request *req)
9635 int dptr_num;
9636 struct smbd_server_connection *sconn = req->sconn;
9638 START_PROFILE(SMBfindclose);
9640 if (req->wct < 1) {
9641 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9642 END_PROFILE(SMBfindclose);
9643 return;
9646 dptr_num = SVALS(req->vwv+0, 0);
9648 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9650 dptr_close(sconn, &dptr_num);
9652 reply_outbuf(req, 0, 0);
9654 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9656 END_PROFILE(SMBfindclose);
9657 return;
9660 /****************************************************************************
9661 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9662 ****************************************************************************/
9664 void reply_findnclose(struct smb_request *req)
9666 int dptr_num;
9668 START_PROFILE(SMBfindnclose);
9670 if (req->wct < 1) {
9671 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9672 END_PROFILE(SMBfindnclose);
9673 return;
9676 dptr_num = SVAL(req->vwv+0, 0);
9678 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9680 /* We never give out valid handles for a
9681 findnotifyfirst - so any dptr_num is ok here.
9682 Just ignore it. */
9684 reply_outbuf(req, 0, 0);
9686 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9688 END_PROFILE(SMBfindnclose);
9689 return;
9692 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9693 struct trans_state *state)
9695 if (get_Protocol() >= PROTOCOL_NT1) {
9696 req->flags2 |= 0x40; /* IS_LONG_NAME */
9697 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9700 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9701 if (state->call != TRANSACT2_QFSINFO &&
9702 state->call != TRANSACT2_SETFSINFO) {
9703 DEBUG(0,("handle_trans2: encryption required "
9704 "with call 0x%x\n",
9705 (unsigned int)state->call));
9706 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9707 return;
9711 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9713 /* Now we must call the relevant TRANS2 function */
9714 switch(state->call) {
9715 case TRANSACT2_OPEN:
9717 START_PROFILE(Trans2_open);
9718 call_trans2open(conn, req,
9719 &state->param, state->total_param,
9720 &state->data, state->total_data,
9721 state->max_data_return);
9722 END_PROFILE(Trans2_open);
9723 break;
9726 case TRANSACT2_FINDFIRST:
9728 START_PROFILE(Trans2_findfirst);
9729 call_trans2findfirst(conn, req,
9730 &state->param, state->total_param,
9731 &state->data, state->total_data,
9732 state->max_data_return);
9733 END_PROFILE(Trans2_findfirst);
9734 break;
9737 case TRANSACT2_FINDNEXT:
9739 START_PROFILE(Trans2_findnext);
9740 call_trans2findnext(conn, req,
9741 &state->param, state->total_param,
9742 &state->data, state->total_data,
9743 state->max_data_return);
9744 END_PROFILE(Trans2_findnext);
9745 break;
9748 case TRANSACT2_QFSINFO:
9750 START_PROFILE(Trans2_qfsinfo);
9751 call_trans2qfsinfo(conn, req,
9752 &state->param, state->total_param,
9753 &state->data, state->total_data,
9754 state->max_data_return);
9755 END_PROFILE(Trans2_qfsinfo);
9756 break;
9759 case TRANSACT2_SETFSINFO:
9761 START_PROFILE(Trans2_setfsinfo);
9762 call_trans2setfsinfo(conn, req,
9763 &state->param, state->total_param,
9764 &state->data, state->total_data,
9765 state->max_data_return);
9766 END_PROFILE(Trans2_setfsinfo);
9767 break;
9770 case TRANSACT2_QPATHINFO:
9771 case TRANSACT2_QFILEINFO:
9773 START_PROFILE(Trans2_qpathinfo);
9774 call_trans2qfilepathinfo(conn, req, state->call,
9775 &state->param, state->total_param,
9776 &state->data, state->total_data,
9777 state->max_data_return);
9778 END_PROFILE(Trans2_qpathinfo);
9779 break;
9782 case TRANSACT2_SETPATHINFO:
9783 case TRANSACT2_SETFILEINFO:
9785 START_PROFILE(Trans2_setpathinfo);
9786 call_trans2setfilepathinfo(conn, req, state->call,
9787 &state->param, state->total_param,
9788 &state->data, state->total_data,
9789 state->max_data_return);
9790 END_PROFILE(Trans2_setpathinfo);
9791 break;
9794 case TRANSACT2_FINDNOTIFYFIRST:
9796 START_PROFILE(Trans2_findnotifyfirst);
9797 call_trans2findnotifyfirst(conn, req,
9798 &state->param, state->total_param,
9799 &state->data, state->total_data,
9800 state->max_data_return);
9801 END_PROFILE(Trans2_findnotifyfirst);
9802 break;
9805 case TRANSACT2_FINDNOTIFYNEXT:
9807 START_PROFILE(Trans2_findnotifynext);
9808 call_trans2findnotifynext(conn, req,
9809 &state->param, state->total_param,
9810 &state->data, state->total_data,
9811 state->max_data_return);
9812 END_PROFILE(Trans2_findnotifynext);
9813 break;
9816 case TRANSACT2_MKDIR:
9818 START_PROFILE(Trans2_mkdir);
9819 call_trans2mkdir(conn, req,
9820 &state->param, state->total_param,
9821 &state->data, state->total_data,
9822 state->max_data_return);
9823 END_PROFILE(Trans2_mkdir);
9824 break;
9827 case TRANSACT2_GET_DFS_REFERRAL:
9829 START_PROFILE(Trans2_get_dfs_referral);
9830 call_trans2getdfsreferral(conn, req,
9831 &state->param, state->total_param,
9832 &state->data, state->total_data,
9833 state->max_data_return);
9834 END_PROFILE(Trans2_get_dfs_referral);
9835 break;
9838 case TRANSACT2_IOCTL:
9840 START_PROFILE(Trans2_ioctl);
9841 call_trans2ioctl(conn, req,
9842 &state->param, state->total_param,
9843 &state->data, state->total_data,
9844 state->max_data_return);
9845 END_PROFILE(Trans2_ioctl);
9846 break;
9849 default:
9850 /* Error in request */
9851 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9852 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9856 /****************************************************************************
9857 Reply to a SMBtrans2.
9858 ****************************************************************************/
9860 void reply_trans2(struct smb_request *req)
9862 connection_struct *conn = req->conn;
9863 unsigned int dsoff;
9864 unsigned int dscnt;
9865 unsigned int psoff;
9866 unsigned int pscnt;
9867 unsigned int tran_call;
9868 struct trans_state *state;
9869 NTSTATUS result;
9871 START_PROFILE(SMBtrans2);
9873 if (req->wct < 14) {
9874 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9875 END_PROFILE(SMBtrans2);
9876 return;
9879 dsoff = SVAL(req->vwv+12, 0);
9880 dscnt = SVAL(req->vwv+11, 0);
9881 psoff = SVAL(req->vwv+10, 0);
9882 pscnt = SVAL(req->vwv+9, 0);
9883 tran_call = SVAL(req->vwv+14, 0);
9885 result = allow_new_trans(conn->pending_trans, req->mid);
9886 if (!NT_STATUS_IS_OK(result)) {
9887 DEBUG(2, ("Got invalid trans2 request: %s\n",
9888 nt_errstr(result)));
9889 reply_nterror(req, result);
9890 END_PROFILE(SMBtrans2);
9891 return;
9894 if (IS_IPC(conn)) {
9895 switch (tran_call) {
9896 /* List the allowed trans2 calls on IPC$ */
9897 case TRANSACT2_OPEN:
9898 case TRANSACT2_GET_DFS_REFERRAL:
9899 case TRANSACT2_QFILEINFO:
9900 case TRANSACT2_QFSINFO:
9901 case TRANSACT2_SETFSINFO:
9902 break;
9903 default:
9904 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9905 END_PROFILE(SMBtrans2);
9906 return;
9910 if ((state = talloc(conn, struct trans_state)) == NULL) {
9911 DEBUG(0, ("talloc failed\n"));
9912 reply_nterror(req, NT_STATUS_NO_MEMORY);
9913 END_PROFILE(SMBtrans2);
9914 return;
9917 state->cmd = SMBtrans2;
9919 state->mid = req->mid;
9920 state->vuid = req->vuid;
9921 state->setup_count = SVAL(req->vwv+13, 0);
9922 state->setup = NULL;
9923 state->total_param = SVAL(req->vwv+0, 0);
9924 state->param = NULL;
9925 state->total_data = SVAL(req->vwv+1, 0);
9926 state->data = NULL;
9927 state->max_param_return = SVAL(req->vwv+2, 0);
9928 state->max_data_return = SVAL(req->vwv+3, 0);
9929 state->max_setup_return = SVAL(req->vwv+4, 0);
9930 state->close_on_completion = BITSETW(req->vwv+5, 0);
9931 state->one_way = BITSETW(req->vwv+5, 1);
9933 state->call = tran_call;
9935 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9936 is so as a sanity check */
9937 if (state->setup_count != 1) {
9939 * Need to have rc=0 for ioctl to get job id for OS/2.
9940 * Network printing will fail if function is not successful.
9941 * Similar function in reply.c will be used if protocol
9942 * is LANMAN1.0 instead of LM1.2X002.
9943 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9944 * outbuf doesn't have to be set(only job id is used).
9946 if ( (state->setup_count == 4)
9947 && (tran_call == TRANSACT2_IOCTL)
9948 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9949 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9950 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9951 } else {
9952 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9953 DEBUG(2,("Transaction is %d\n",tran_call));
9954 TALLOC_FREE(state);
9955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9956 END_PROFILE(SMBtrans2);
9957 return;
9961 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9962 goto bad_param;
9964 if (state->total_data) {
9966 if (trans_oob(state->total_data, 0, dscnt)
9967 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9968 goto bad_param;
9971 /* Can't use talloc here, the core routines do realloc on the
9972 * params and data. */
9973 state->data = (char *)SMB_MALLOC(state->total_data);
9974 if (state->data == NULL) {
9975 DEBUG(0,("reply_trans2: data malloc fail for %u "
9976 "bytes !\n", (unsigned int)state->total_data));
9977 TALLOC_FREE(state);
9978 reply_nterror(req, NT_STATUS_NO_MEMORY);
9979 END_PROFILE(SMBtrans2);
9980 return;
9983 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9986 if (state->total_param) {
9988 if (trans_oob(state->total_param, 0, pscnt)
9989 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9990 goto bad_param;
9993 /* Can't use talloc here, the core routines do realloc on the
9994 * params and data. */
9995 state->param = (char *)SMB_MALLOC(state->total_param);
9996 if (state->param == NULL) {
9997 DEBUG(0,("reply_trans: param malloc fail for %u "
9998 "bytes !\n", (unsigned int)state->total_param));
9999 SAFE_FREE(state->data);
10000 TALLOC_FREE(state);
10001 reply_nterror(req, NT_STATUS_NO_MEMORY);
10002 END_PROFILE(SMBtrans2);
10003 return;
10006 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
10009 state->received_data = dscnt;
10010 state->received_param = pscnt;
10012 if ((state->received_param == state->total_param) &&
10013 (state->received_data == state->total_data)) {
10015 handle_trans2(conn, req, state);
10017 SAFE_FREE(state->data);
10018 SAFE_FREE(state->param);
10019 TALLOC_FREE(state);
10020 END_PROFILE(SMBtrans2);
10021 return;
10024 DLIST_ADD(conn->pending_trans, state);
10026 /* We need to send an interim response then receive the rest
10027 of the parameter/data bytes */
10028 reply_outbuf(req, 0, 0);
10029 show_msg((char *)req->outbuf);
10030 END_PROFILE(SMBtrans2);
10031 return;
10033 bad_param:
10035 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
10036 SAFE_FREE(state->data);
10037 SAFE_FREE(state->param);
10038 TALLOC_FREE(state);
10039 END_PROFILE(SMBtrans2);
10040 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10044 /****************************************************************************
10045 Reply to a SMBtranss2
10046 ****************************************************************************/
10048 void reply_transs2(struct smb_request *req)
10050 connection_struct *conn = req->conn;
10051 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
10052 struct trans_state *state;
10054 START_PROFILE(SMBtranss2);
10056 show_msg((const char *)req->inbuf);
10058 /* Windows clients expect all replies to
10059 a transact secondary (SMBtranss2 0x33)
10060 to have a command code of transact
10061 (SMBtrans2 0x32). See bug #8989
10062 and also [MS-CIFS] section 2.2.4.47.2
10063 for details.
10065 req->cmd = SMBtrans2;
10067 if (req->wct < 8) {
10068 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10069 END_PROFILE(SMBtranss2);
10070 return;
10073 for (state = conn->pending_trans; state != NULL;
10074 state = state->next) {
10075 if (state->mid == req->mid) {
10076 break;
10080 if ((state == NULL) || (state->cmd != SMBtrans2)) {
10081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10082 END_PROFILE(SMBtranss2);
10083 return;
10086 /* Revise state->total_param and state->total_data in case they have
10087 changed downwards */
10089 if (SVAL(req->vwv+0, 0) < state->total_param)
10090 state->total_param = SVAL(req->vwv+0, 0);
10091 if (SVAL(req->vwv+1, 0) < state->total_data)
10092 state->total_data = SVAL(req->vwv+1, 0);
10094 pcnt = SVAL(req->vwv+2, 0);
10095 poff = SVAL(req->vwv+3, 0);
10096 pdisp = SVAL(req->vwv+4, 0);
10098 dcnt = SVAL(req->vwv+5, 0);
10099 doff = SVAL(req->vwv+6, 0);
10100 ddisp = SVAL(req->vwv+7, 0);
10102 state->received_param += pcnt;
10103 state->received_data += dcnt;
10105 if ((state->received_data > state->total_data) ||
10106 (state->received_param > state->total_param))
10107 goto bad_param;
10109 if (pcnt) {
10110 if (trans_oob(state->total_param, pdisp, pcnt)
10111 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
10112 goto bad_param;
10114 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
10117 if (dcnt) {
10118 if (trans_oob(state->total_data, ddisp, dcnt)
10119 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
10120 goto bad_param;
10122 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
10125 if ((state->received_param < state->total_param) ||
10126 (state->received_data < state->total_data)) {
10127 END_PROFILE(SMBtranss2);
10128 return;
10131 handle_trans2(conn, req, state);
10133 DLIST_REMOVE(conn->pending_trans, state);
10134 SAFE_FREE(state->data);
10135 SAFE_FREE(state->param);
10136 TALLOC_FREE(state);
10138 END_PROFILE(SMBtranss2);
10139 return;
10141 bad_param:
10143 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
10144 DLIST_REMOVE(conn->pending_trans, state);
10145 SAFE_FREE(state->data);
10146 SAFE_FREE(state->param);
10147 TALLOC_FREE(state);
10148 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
10149 END_PROFILE(SMBtranss2);
10150 return;