s3:smbd: handle IO_REPARSE_TAG_DFS in SMB_FIND_FILE_FULL_DIRECTORY_INFO
[Samba.git] / source3 / smbd / trans2.c
blob017ad068877e1d146975e548238bdf6a7e81bd42
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"
45 #define DIR_ENTRY_SAFETY_MARGIN 4096
47 static char *store_file_unix_basic(connection_struct *conn,
48 char *pdata,
49 files_struct *fsp,
50 const SMB_STRUCT_STAT *psbuf);
52 static char *store_file_unix_basic_info2(connection_struct *conn,
53 char *pdata,
54 files_struct *fsp,
55 const SMB_STRUCT_STAT *psbuf);
57 /****************************************************************************
58 Check if an open file handle or smb_fname is a symlink.
59 ****************************************************************************/
61 static NTSTATUS refuse_symlink(connection_struct *conn,
62 const files_struct *fsp,
63 const struct smb_filename *smb_fname)
65 SMB_STRUCT_STAT sbuf;
66 const SMB_STRUCT_STAT *pst = NULL;
68 if (fsp) {
69 pst = &fsp->fsp_name->st;
70 } else {
71 pst = &smb_fname->st;
74 if (!VALID_STAT(*pst)) {
75 int ret = vfs_stat_smb_basename(conn,
76 smb_fname,
77 &sbuf);
78 if (ret == -1 && errno != ENOENT) {
79 return map_nt_error_from_unix(errno);
80 } else if (ret == -1) {
81 /* it's not a symlink.. */
82 return NT_STATUS_OK;
84 pst = &sbuf;
87 if (S_ISLNK(pst->st_ex_mode)) {
88 return NT_STATUS_ACCESS_DENIED;
90 return NT_STATUS_OK;
93 NTSTATUS check_access_fsp(const struct files_struct *fsp,
94 uint32_t access_mask)
96 if (!(fsp->access_mask & access_mask)) {
97 return NT_STATUS_ACCESS_DENIED;
99 return NT_STATUS_OK;
102 /********************************************************************
103 The canonical "check access" based on object handle or path function.
104 ********************************************************************/
106 NTSTATUS check_access(connection_struct *conn,
107 files_struct *fsp,
108 const struct smb_filename *smb_fname,
109 uint32_t access_mask)
111 NTSTATUS status;
113 if (fsp) {
114 status = check_access_fsp(fsp, access_mask);
115 } else {
116 status = smbd_check_access_rights(conn, smb_fname,
117 false, access_mask);
120 return status;
123 /********************************************************************
124 Roundup a value to the nearest allocation roundup size boundary.
125 Only do this for Windows clients.
126 ********************************************************************/
128 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
130 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
132 /* Only roundup for Windows clients. */
133 enum remote_arch_types ra_type = get_remote_arch();
134 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
135 val = SMB_ROUNDUP(val,rval);
137 return val;
140 /********************************************************************
141 Create a 64 bit FileIndex. If the file is on the same device as
142 the root of the share, just return the 64-bit inode. If it isn't,
143 mangle as we used to do.
144 ********************************************************************/
146 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
148 uint64_t file_index;
149 if (conn->sconn->aapl_zero_file_id) {
150 return 0;
152 if (conn->base_share_dev == psbuf->st_ex_dev) {
153 return (uint64_t)psbuf->st_ex_ino;
155 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
156 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
157 return file_index;
161 /********************************************************************
162 Globally (for this connection / multi-channel) disable file-ID
163 calculation. This is required to be global because it serves
164 Macs in AAPL mode, which is globally set.
165 ********************************************************************/
166 void aapl_force_zero_file_id(struct smbd_server_connection *sconn)
168 sconn->aapl_zero_file_id = true;
171 /****************************************************************************
172 Utility functions for dealing with extended attributes.
173 ****************************************************************************/
175 /****************************************************************************
176 Refuse to allow clients to overwrite our private xattrs.
177 ****************************************************************************/
179 bool samba_private_attr_name(const char *unix_ea_name)
181 static const char * const prohibited_ea_names[] = {
182 SAMBA_POSIX_INHERITANCE_EA_NAME,
183 SAMBA_XATTR_DOS_ATTRIB,
184 SAMBA_XATTR_MARKER,
185 XATTR_NTACL_NAME,
186 NULL
189 int i;
191 for (i = 0; prohibited_ea_names[i]; i++) {
192 if (strequal( prohibited_ea_names[i], unix_ea_name))
193 return true;
195 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
196 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
197 return true;
199 return false;
202 /****************************************************************************
203 Get one EA value. Fill in a struct ea_struct.
204 ****************************************************************************/
206 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx,
207 connection_struct *conn,
208 files_struct *fsp,
209 const struct smb_filename *smb_fname,
210 const char *ea_name,
211 struct ea_struct *pea)
213 /* Get the value of this xattr. Max size is 64k. */
214 size_t attr_size = 256;
215 char *val = NULL;
216 ssize_t sizeret;
218 again:
220 val = talloc_realloc(mem_ctx, val, char, attr_size);
221 if (!val) {
222 return NT_STATUS_NO_MEMORY;
225 if (fsp && fsp->fh->fd != -1) {
226 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
227 } else {
228 sizeret = SMB_VFS_GETXATTR(conn, smb_fname,
229 ea_name, val, attr_size);
232 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
233 attr_size = 65536;
234 goto again;
237 if (sizeret == -1) {
238 return map_nt_error_from_unix(errno);
241 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
242 dump_data(10, (uint8_t *)val, sizeret);
244 pea->flags = 0;
245 if (strnequal(ea_name, "user.", 5)) {
246 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
247 } else {
248 pea->name = talloc_strdup(mem_ctx, ea_name);
250 if (pea->name == NULL) {
251 TALLOC_FREE(val);
252 return NT_STATUS_NO_MEMORY;
254 pea->value.data = (unsigned char *)val;
255 pea->value.length = (size_t)sizeret;
256 return NT_STATUS_OK;
259 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
260 connection_struct *conn,
261 files_struct *fsp,
262 const struct smb_filename *smb_fname,
263 char ***pnames,
264 size_t *pnum_names)
266 char smallbuf[1024];
267 /* Get a list of all xattrs. Max namesize is 64k. */
268 size_t ea_namelist_size = 1024;
269 char *ea_namelist = smallbuf;
270 char *to_free = NULL;
272 char *p;
273 char **names;
274 size_t num_names;
275 ssize_t sizeret = -1;
276 NTSTATUS status;
278 if (pnames) {
279 *pnames = NULL;
281 *pnum_names = 0;
283 status = refuse_symlink(conn, fsp, smb_fname);
284 if (!NT_STATUS_IS_OK(status)) {
286 * Just return no EA's on a symlink.
288 return NT_STATUS_OK;
291 if (fsp && fsp->fh->fd != -1) {
292 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
293 ea_namelist_size);
294 } else {
295 sizeret = SMB_VFS_LISTXATTR(conn,
296 smb_fname,
297 ea_namelist,
298 ea_namelist_size);
301 if ((sizeret == -1) && (errno == ERANGE)) {
302 ea_namelist_size = 65536;
303 ea_namelist = talloc_array(mem_ctx, char, ea_namelist_size);
304 if (ea_namelist == NULL) {
305 return NT_STATUS_NO_MEMORY;
307 to_free = ea_namelist;
309 if (fsp && fsp->fh->fd != -1) {
310 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
311 ea_namelist_size);
312 } else {
313 sizeret = SMB_VFS_LISTXATTR(conn,
314 smb_fname,
315 ea_namelist,
316 ea_namelist_size);
320 if (sizeret == -1) {
321 status = map_nt_error_from_unix(errno);
322 TALLOC_FREE(to_free);
323 return status;
326 DBG_DEBUG("ea_namelist size = %zd\n", sizeret);
328 if (sizeret == 0) {
329 TALLOC_FREE(to_free);
330 return NT_STATUS_OK;
334 * Ensure the result is 0-terminated
337 if (ea_namelist[sizeret-1] != '\0') {
338 TALLOC_FREE(to_free);
339 return NT_STATUS_INTERNAL_ERROR;
343 * count the names
345 num_names = 0;
347 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
348 num_names += 1;
351 *pnum_names = num_names;
353 if (pnames == NULL) {
354 TALLOC_FREE(to_free);
355 return NT_STATUS_OK;
358 names = talloc_array(mem_ctx, char *, num_names);
359 if (names == NULL) {
360 DEBUG(0, ("talloc failed\n"));
361 TALLOC_FREE(to_free);
362 return NT_STATUS_NO_MEMORY;
365 if (ea_namelist == smallbuf) {
366 ea_namelist = talloc_memdup(names, smallbuf, sizeret);
367 if (ea_namelist == NULL) {
368 TALLOC_FREE(names);
369 return NT_STATUS_NO_MEMORY;
371 } else {
372 talloc_steal(names, ea_namelist);
374 ea_namelist = talloc_realloc(names, ea_namelist, char,
375 sizeret);
376 if (ea_namelist == NULL) {
377 TALLOC_FREE(names);
378 return NT_STATUS_NO_MEMORY;
382 num_names = 0;
384 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
385 names[num_names++] = p;
388 *pnames = names;
390 return NT_STATUS_OK;
393 /****************************************************************************
394 Return a linked list of the total EA's. Plus the total size
395 ****************************************************************************/
397 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
398 connection_struct *conn,
399 files_struct *fsp,
400 const struct smb_filename *smb_fname,
401 size_t *pea_total_len,
402 struct ea_list **ea_list)
404 /* Get a list of all xattrs. Max namesize is 64k. */
405 size_t i, num_names;
406 char **names;
407 struct ea_list *ea_list_head = NULL;
408 bool posix_pathnames = false;
409 NTSTATUS status;
411 *pea_total_len = 0;
412 *ea_list = NULL;
414 if (!lp_ea_support(SNUM(conn))) {
415 return NT_STATUS_OK;
418 if (fsp) {
419 posix_pathnames =
420 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
421 } else {
422 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
425 status = get_ea_names_from_file(talloc_tos(),
426 conn,
427 fsp,
428 smb_fname,
429 &names,
430 &num_names);
432 if (!NT_STATUS_IS_OK(status)) {
433 return status;
436 if (num_names == 0) {
437 return NT_STATUS_OK;
440 for (i=0; i<num_names; i++) {
441 struct ea_list *listp;
442 fstring dos_ea_name;
444 if (strnequal(names[i], "system.", 7)
445 || samba_private_attr_name(names[i]))
446 continue;
449 * Filter out any underlying POSIX EA names
450 * that a Windows client can't handle.
452 if (!posix_pathnames &&
453 is_invalid_windows_ea_name(names[i])) {
454 continue;
457 listp = talloc(mem_ctx, struct ea_list);
458 if (listp == NULL) {
459 return NT_STATUS_NO_MEMORY;
462 status = get_ea_value(listp,
463 conn,
464 fsp,
465 smb_fname,
466 names[i],
467 &listp->ea);
469 if (!NT_STATUS_IS_OK(status)) {
470 TALLOC_FREE(listp);
471 return status;
474 if (listp->ea.value.length == 0) {
476 * We can never return a zero length EA.
477 * Windows reports the EA's as corrupted.
479 TALLOC_FREE(listp);
480 continue;
483 push_ascii_fstring(dos_ea_name, listp->ea.name);
485 *pea_total_len +=
486 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
488 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
489 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
490 (unsigned int)listp->ea.value.length));
492 DLIST_ADD_END(ea_list_head, listp);
496 /* Add on 4 for total length. */
497 if (*pea_total_len) {
498 *pea_total_len += 4;
501 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
502 (unsigned int)*pea_total_len));
504 *ea_list = ea_list_head;
505 return NT_STATUS_OK;
508 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
509 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
511 *pea_total_len = 0;
512 *ea_list = NULL;
514 if (!lp_ea_support(SNUM(conn))) {
515 return NT_STATUS_OK;
518 if (is_ntfs_stream_smb_fname(smb_fname)) {
519 return NT_STATUS_INVALID_PARAMETER;
522 return get_ea_list_from_file_path(mem_ctx,
523 conn,
524 fsp,
525 smb_fname,
526 pea_total_len,
527 ea_list);
530 /****************************************************************************
531 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
532 that was filled.
533 ****************************************************************************/
535 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
536 connection_struct *conn, struct ea_list *ea_list)
538 unsigned int ret_data_size = 4;
539 char *p = pdata;
541 SMB_ASSERT(total_data_size >= 4);
543 if (!lp_ea_support(SNUM(conn))) {
544 SIVAL(pdata,4,0);
545 return 4;
548 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
549 size_t dos_namelen;
550 fstring dos_ea_name;
551 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
552 dos_namelen = strlen(dos_ea_name);
553 if (dos_namelen > 255 || dos_namelen == 0) {
554 break;
556 if (ea_list->ea.value.length > 65535) {
557 break;
559 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
560 break;
563 /* We know we have room. */
564 SCVAL(p,0,ea_list->ea.flags);
565 SCVAL(p,1,dos_namelen);
566 SSVAL(p,2,ea_list->ea.value.length);
567 strlcpy(p+4, dos_ea_name, dos_namelen+1);
568 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
570 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
571 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
574 ret_data_size = PTR_DIFF(p, pdata);
575 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
576 SIVAL(pdata,0,ret_data_size);
577 return ret_data_size;
580 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
581 char *pdata,
582 unsigned int total_data_size,
583 unsigned int *ret_data_size,
584 connection_struct *conn,
585 struct ea_list *ea_list)
587 uint8_t *p = (uint8_t *)pdata;
588 uint8_t *last_start = NULL;
589 bool do_store_data = (pdata != NULL);
591 *ret_data_size = 0;
593 if (!lp_ea_support(SNUM(conn))) {
594 return NT_STATUS_NO_EAS_ON_FILE;
597 for (; ea_list; ea_list = ea_list->next) {
598 size_t dos_namelen;
599 fstring dos_ea_name;
600 size_t this_size;
601 size_t pad = 0;
603 if (last_start != NULL && do_store_data) {
604 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
606 last_start = p;
608 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
609 dos_namelen = strlen(dos_ea_name);
610 if (dos_namelen > 255 || dos_namelen == 0) {
611 return NT_STATUS_INTERNAL_ERROR;
613 if (ea_list->ea.value.length > 65535) {
614 return NT_STATUS_INTERNAL_ERROR;
617 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
619 if (ea_list->next) {
620 pad = (4 - (this_size % 4)) % 4;
621 this_size += pad;
624 if (do_store_data) {
625 if (this_size > total_data_size) {
626 return NT_STATUS_INFO_LENGTH_MISMATCH;
629 /* We know we have room. */
630 SIVAL(p, 0x00, 0); /* next offset */
631 SCVAL(p, 0x04, ea_list->ea.flags);
632 SCVAL(p, 0x05, dos_namelen);
633 SSVAL(p, 0x06, ea_list->ea.value.length);
634 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
635 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
636 if (pad) {
637 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
638 '\0',
639 pad);
641 total_data_size -= this_size;
644 p += this_size;
647 *ret_data_size = PTR_DIFF(p, pdata);
648 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
649 return NT_STATUS_OK;
652 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
654 size_t total_ea_len = 0;
655 TALLOC_CTX *mem_ctx;
656 struct ea_list *ea_list = NULL;
658 if (!lp_ea_support(SNUM(conn))) {
659 return 0;
661 mem_ctx = talloc_stackframe();
663 /* If this is a stream fsp, then we need to instead find the
664 * estimated ea len from the main file, not the stream
665 * (streams cannot have EAs), but the estimate isn't just 0 in
666 * this case! */
667 if (is_ntfs_stream_smb_fname(smb_fname)) {
668 fsp = NULL;
670 (void)get_ea_list_from_file_path(mem_ctx,
671 conn,
672 fsp,
673 smb_fname,
674 &total_ea_len,
675 &ea_list);
676 if(conn->sconn->using_smb2) {
677 NTSTATUS status;
678 unsigned int ret_data_size;
680 * We're going to be using fill_ea_chained_buffer() to
681 * marshall EA's - this size is significantly larger
682 * than the SMB1 buffer. Re-calculate the size without
683 * marshalling.
685 status = fill_ea_chained_buffer(mem_ctx,
686 NULL,
688 &ret_data_size,
689 conn,
690 ea_list);
691 if (!NT_STATUS_IS_OK(status)) {
692 ret_data_size = 0;
694 total_ea_len = ret_data_size;
696 TALLOC_FREE(mem_ctx);
697 return total_ea_len;
700 /****************************************************************************
701 Ensure the EA name is case insensitive by matching any existing EA name.
702 ****************************************************************************/
704 static void canonicalize_ea_name(connection_struct *conn,
705 files_struct *fsp,
706 const struct smb_filename *smb_fname,
707 fstring unix_ea_name)
709 size_t total_ea_len;
710 TALLOC_CTX *mem_ctx = talloc_tos();
711 struct ea_list *ea_list;
712 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
713 conn,
714 fsp,
715 smb_fname,
716 &total_ea_len,
717 &ea_list);
718 if (!NT_STATUS_IS_OK(status)) {
719 return;
722 for (; ea_list; ea_list = ea_list->next) {
723 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
724 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
725 &unix_ea_name[5], ea_list->ea.name));
726 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
727 break;
732 /****************************************************************************
733 Set or delete an extended attribute.
734 ****************************************************************************/
736 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
737 const struct smb_filename *smb_fname, struct ea_list *ea_list)
739 NTSTATUS status;
740 bool posix_pathnames = false;
742 if (!lp_ea_support(SNUM(conn))) {
743 return NT_STATUS_EAS_NOT_SUPPORTED;
746 if (fsp) {
747 posix_pathnames =
748 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
749 } else {
750 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
753 status = refuse_symlink(conn, fsp, smb_fname);
754 if (!NT_STATUS_IS_OK(status)) {
755 return status;
758 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
759 if (!NT_STATUS_IS_OK(status)) {
760 return status;
763 /* Setting EAs on streams isn't supported. */
764 if (is_ntfs_stream_smb_fname(smb_fname)) {
765 return NT_STATUS_INVALID_PARAMETER;
769 * Filter out invalid Windows EA names - before
770 * we set *any* of them.
773 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
774 return STATUS_INVALID_EA_NAME;
777 for (;ea_list; ea_list = ea_list->next) {
778 int ret;
779 fstring unix_ea_name;
781 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
782 fstrcat(unix_ea_name, ea_list->ea.name);
784 canonicalize_ea_name(conn,
785 fsp,
786 smb_fname,
787 unix_ea_name);
789 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
791 if (samba_private_attr_name(unix_ea_name)) {
792 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
793 return NT_STATUS_ACCESS_DENIED;
796 if (ea_list->ea.value.length == 0) {
797 /* Remove the attribute. */
798 if (fsp && (fsp->fh->fd != -1)) {
799 DEBUG(10,("set_ea: deleting ea name %s on "
800 "file %s by file descriptor.\n",
801 unix_ea_name, fsp_str_dbg(fsp)));
802 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
803 } else {
804 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
805 unix_ea_name, smb_fname->base_name));
806 ret = SMB_VFS_REMOVEXATTR(conn,
807 smb_fname,
808 unix_ea_name);
810 #ifdef ENOATTR
811 /* Removing a non existent attribute always succeeds. */
812 if (ret == -1 && errno == ENOATTR) {
813 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
814 unix_ea_name));
815 ret = 0;
817 #endif
818 } else {
819 if (fsp && (fsp->fh->fd != -1)) {
820 DEBUG(10,("set_ea: setting ea name %s on file "
821 "%s by file descriptor.\n",
822 unix_ea_name, fsp_str_dbg(fsp)));
823 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
824 ea_list->ea.value.data, ea_list->ea.value.length, 0);
825 } else {
826 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
827 unix_ea_name, smb_fname->base_name));
828 ret = SMB_VFS_SETXATTR(conn,
829 smb_fname,
830 unix_ea_name,
831 ea_list->ea.value.data,
832 ea_list->ea.value.length,
837 if (ret == -1) {
838 #ifdef ENOTSUP
839 if (errno == ENOTSUP) {
840 return NT_STATUS_EAS_NOT_SUPPORTED;
842 #endif
843 return map_nt_error_from_unix(errno);
847 return NT_STATUS_OK;
849 /****************************************************************************
850 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
851 ****************************************************************************/
853 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
855 struct ea_list *ea_list_head = NULL;
856 size_t converted_size, offset = 0;
858 while (offset + 2 < data_size) {
859 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
860 unsigned int namelen = CVAL(pdata,offset);
862 offset++; /* Go past the namelen byte. */
864 /* integer wrap paranioa. */
865 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
866 (offset > data_size) || (namelen > data_size) ||
867 (offset + namelen >= data_size)) {
868 break;
870 /* Ensure the name is null terminated. */
871 if (pdata[offset + namelen] != '\0') {
872 return NULL;
874 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
875 &converted_size)) {
876 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
877 "failed: %s", strerror(errno)));
879 if (!eal->ea.name) {
880 return NULL;
883 offset += (namelen + 1); /* Go past the name + terminating zero. */
884 DLIST_ADD_END(ea_list_head, eal);
885 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
888 return ea_list_head;
891 /****************************************************************************
892 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
893 ****************************************************************************/
895 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
897 struct ea_list *ea_list_head = NULL;
898 size_t offset = 0;
899 size_t bytes_used = 0;
901 while (offset < data_size) {
902 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
904 if (!eal) {
905 return NULL;
908 DLIST_ADD_END(ea_list_head, eal);
909 offset += bytes_used;
912 return ea_list_head;
915 /****************************************************************************
916 Count the total EA size needed.
917 ****************************************************************************/
919 static size_t ea_list_size(struct ea_list *ealist)
921 fstring dos_ea_name;
922 struct ea_list *listp;
923 size_t ret = 0;
925 for (listp = ealist; listp; listp = listp->next) {
926 push_ascii_fstring(dos_ea_name, listp->ea.name);
927 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
929 /* Add on 4 for total length. */
930 if (ret) {
931 ret += 4;
934 return ret;
937 /****************************************************************************
938 Return a union of EA's from a file list and a list of names.
939 The TALLOC context for the two lists *MUST* be identical as we steal
940 memory from one list to add to another. JRA.
941 ****************************************************************************/
943 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
945 struct ea_list *nlistp, *flistp;
947 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
948 for (flistp = file_list; flistp; flistp = flistp->next) {
949 if (strequal(nlistp->ea.name, flistp->ea.name)) {
950 break;
954 if (flistp) {
955 /* Copy the data from this entry. */
956 nlistp->ea.flags = flistp->ea.flags;
957 nlistp->ea.value = flistp->ea.value;
958 } else {
959 /* Null entry. */
960 nlistp->ea.flags = 0;
961 ZERO_STRUCT(nlistp->ea.value);
965 *total_ea_len = ea_list_size(name_list);
966 return name_list;
969 /****************************************************************************
970 Send the required number of replies back.
971 We assume all fields other than the data fields are
972 set correctly for the type of call.
973 HACK ! Always assumes smb_setup field is zero.
974 ****************************************************************************/
976 void send_trans2_replies(connection_struct *conn,
977 struct smb_request *req,
978 NTSTATUS status,
979 const char *params,
980 int paramsize,
981 const char *pdata,
982 int datasize,
983 int max_data_bytes)
985 /* As we are using a protocol > LANMAN1 then the max_send
986 variable must have been set in the sessetupX call.
987 This takes precedence over the max_xmit field in the
988 global struct. These different max_xmit variables should
989 be merged as this is now too confusing */
991 int data_to_send = datasize;
992 int params_to_send = paramsize;
993 int useable_space;
994 const char *pp = params;
995 const char *pd = pdata;
996 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
997 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
998 int data_alignment_offset = 0;
999 bool overflow = False;
1000 struct smbXsrv_connection *xconn = req->xconn;
1001 int max_send = xconn->smb1.sessions.max_send;
1003 /* Modify the data_to_send and datasize and set the error if
1004 we're trying to send more than max_data_bytes. We still send
1005 the part of the packet(s) that fit. Strange, but needed
1006 for OS/2. */
1008 if (max_data_bytes > 0 && datasize > max_data_bytes) {
1009 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
1010 max_data_bytes, datasize ));
1011 datasize = data_to_send = max_data_bytes;
1012 overflow = True;
1015 /* If there genuinely are no parameters or data to send just send the empty packet */
1017 if(params_to_send == 0 && data_to_send == 0) {
1018 reply_outbuf(req, 10, 0);
1019 if (NT_STATUS_V(status)) {
1020 uint8_t eclass;
1021 uint32_t ecode;
1022 ntstatus_to_dos(status, &eclass, &ecode);
1023 error_packet_set((char *)req->outbuf,
1024 eclass, ecode, status,
1025 __LINE__,__FILE__);
1027 show_msg((char *)req->outbuf);
1028 if (!srv_send_smb(xconn,
1029 (char *)req->outbuf,
1030 true, req->seqnum+1,
1031 IS_CONN_ENCRYPTED(conn),
1032 &req->pcd)) {
1033 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1035 TALLOC_FREE(req->outbuf);
1036 return;
1039 /* When sending params and data ensure that both are nicely aligned */
1040 /* Only do this alignment when there is also data to send - else
1041 can cause NT redirector problems. */
1043 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1044 data_alignment_offset = 4 - (params_to_send % 4);
1046 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1047 /* The alignment_offset is to align the param bytes on an even byte
1048 boundary. NT 4.0 Beta needs this to work correctly. */
1050 useable_space = max_send - (smb_size
1051 + 2 * 10 /* wct */
1052 + alignment_offset
1053 + data_alignment_offset);
1055 if (useable_space < 0) {
1056 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1057 "= %d!!!", useable_space));
1058 exit_server_cleanly("send_trans2_replies: Not enough space");
1061 while (params_to_send || data_to_send) {
1062 /* Calculate whether we will totally or partially fill this packet */
1064 total_sent_thistime = params_to_send + data_to_send;
1066 /* We can never send more than useable_space */
1068 * Note that 'useable_space' does not include the alignment offsets,
1069 * but we must include the alignment offsets in the calculation of
1070 * the length of the data we send over the wire, as the alignment offsets
1071 * are sent here. Fix from Marc_Jacobsen@hp.com.
1074 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1076 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1077 + data_alignment_offset);
1079 /* Set total params and data to be sent */
1080 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1081 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1083 /* Calculate how many parameters and data we can fit into
1084 * this packet. Parameters get precedence
1087 params_sent_thistime = MIN(params_to_send,useable_space);
1088 data_sent_thistime = useable_space - params_sent_thistime;
1089 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1091 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1093 /* smb_proff is the offset from the start of the SMB header to the
1094 parameter bytes, however the first 4 bytes of outbuf are
1095 the Netbios over TCP header. Thus use smb_base() to subtract
1096 them from the calculation */
1098 SSVAL(req->outbuf,smb_proff,
1099 ((smb_buf(req->outbuf)+alignment_offset)
1100 - smb_base(req->outbuf)));
1102 if(params_sent_thistime == 0)
1103 SSVAL(req->outbuf,smb_prdisp,0);
1104 else
1105 /* Absolute displacement of param bytes sent in this packet */
1106 SSVAL(req->outbuf,smb_prdisp,pp - params);
1108 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1109 if(data_sent_thistime == 0) {
1110 SSVAL(req->outbuf,smb_droff,0);
1111 SSVAL(req->outbuf,smb_drdisp, 0);
1112 } else {
1113 /* The offset of the data bytes is the offset of the
1114 parameter bytes plus the number of parameters being sent this time */
1115 SSVAL(req->outbuf, smb_droff,
1116 ((smb_buf(req->outbuf)+alignment_offset)
1117 - smb_base(req->outbuf))
1118 + params_sent_thistime + data_alignment_offset);
1119 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1122 /* Initialize the padding for alignment */
1124 if (alignment_offset != 0) {
1125 memset(smb_buf(req->outbuf), 0, alignment_offset);
1128 /* Copy the param bytes into the packet */
1130 if(params_sent_thistime) {
1131 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1132 params_sent_thistime);
1135 /* Copy in the data bytes */
1136 if(data_sent_thistime) {
1137 if (data_alignment_offset != 0) {
1138 memset((smb_buf(req->outbuf)+alignment_offset+
1139 params_sent_thistime), 0,
1140 data_alignment_offset);
1142 memcpy(smb_buf(req->outbuf)+alignment_offset
1143 +params_sent_thistime+data_alignment_offset,
1144 pd,data_sent_thistime);
1147 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1148 params_sent_thistime, data_sent_thistime, useable_space));
1149 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1150 params_to_send, data_to_send, paramsize, datasize));
1152 if (overflow) {
1153 error_packet_set((char *)req->outbuf,
1154 ERRDOS,ERRbufferoverflow,
1155 STATUS_BUFFER_OVERFLOW,
1156 __LINE__,__FILE__);
1157 } else if (NT_STATUS_V(status)) {
1158 uint8_t eclass;
1159 uint32_t ecode;
1160 ntstatus_to_dos(status, &eclass, &ecode);
1161 error_packet_set((char *)req->outbuf,
1162 eclass, ecode, status,
1163 __LINE__,__FILE__);
1166 /* Send the packet */
1167 show_msg((char *)req->outbuf);
1168 if (!srv_send_smb(xconn,
1169 (char *)req->outbuf,
1170 true, req->seqnum+1,
1171 IS_CONN_ENCRYPTED(conn),
1172 &req->pcd))
1173 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1175 TALLOC_FREE(req->outbuf);
1177 pp += params_sent_thistime;
1178 pd += data_sent_thistime;
1180 params_to_send -= params_sent_thistime;
1181 data_to_send -= data_sent_thistime;
1183 /* Sanity check */
1184 if(params_to_send < 0 || data_to_send < 0) {
1185 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1186 params_to_send, data_to_send));
1187 return;
1191 return;
1194 /****************************************************************************
1195 Reply to a TRANSACT2_OPEN.
1196 ****************************************************************************/
1198 static void call_trans2open(connection_struct *conn,
1199 struct smb_request *req,
1200 char **pparams, int total_params,
1201 char **ppdata, int total_data,
1202 unsigned int max_data_bytes)
1204 struct smb_filename *smb_fname = NULL;
1205 char *params = *pparams;
1206 char *pdata = *ppdata;
1207 int deny_mode;
1208 int32_t open_attr;
1209 bool oplock_request;
1210 #if 0
1211 bool return_additional_info;
1212 int16 open_sattr;
1213 time_t open_time;
1214 #endif
1215 int open_ofun;
1216 uint32_t open_size;
1217 char *pname;
1218 char *fname = NULL;
1219 off_t size=0;
1220 int fattr=0,mtime=0;
1221 SMB_INO_T inode = 0;
1222 int smb_action = 0;
1223 files_struct *fsp;
1224 struct ea_list *ea_list = NULL;
1225 uint16_t flags = 0;
1226 NTSTATUS status;
1227 uint32_t access_mask;
1228 uint32_t share_mode;
1229 uint32_t create_disposition;
1230 uint32_t create_options = 0;
1231 uint32_t private_flags = 0;
1232 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
1233 TALLOC_CTX *ctx = talloc_tos();
1236 * Ensure we have enough parameters to perform the operation.
1239 if (total_params < 29) {
1240 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1241 goto out;
1244 flags = SVAL(params, 0);
1245 deny_mode = SVAL(params, 2);
1246 open_attr = SVAL(params,6);
1247 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1248 if (oplock_request) {
1249 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1252 #if 0
1253 return_additional_info = BITSETW(params,0);
1254 open_sattr = SVAL(params, 4);
1255 open_time = make_unix_date3(params+8);
1256 #endif
1257 open_ofun = SVAL(params,12);
1258 open_size = IVAL(params,14);
1259 pname = &params[28];
1261 if (IS_IPC(conn)) {
1262 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1263 goto out;
1266 if (req->posix_pathnames) {
1267 srvstr_get_path_posix(ctx,
1268 params,
1269 req->flags2,
1270 &fname,
1271 pname,
1272 total_params - 28,
1273 STR_TERMINATE,
1274 &status);
1275 } else {
1276 srvstr_get_path(ctx,
1277 params,
1278 req->flags2,
1279 &fname,
1280 pname,
1281 total_params - 28,
1282 STR_TERMINATE,
1283 &status);
1285 if (!NT_STATUS_IS_OK(status)) {
1286 reply_nterror(req, status);
1287 goto out;
1290 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1291 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1292 (unsigned int)open_ofun, open_size));
1294 status = filename_convert(ctx,
1295 conn,
1296 fname,
1297 ucf_flags,
1298 NULL,
1299 NULL,
1300 &smb_fname);
1301 if (!NT_STATUS_IS_OK(status)) {
1302 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1303 reply_botherror(req,
1304 NT_STATUS_PATH_NOT_COVERED,
1305 ERRSRV, ERRbadpath);
1306 goto out;
1308 reply_nterror(req, status);
1309 goto out;
1312 if (open_ofun == 0) {
1313 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1314 goto out;
1317 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1318 open_ofun,
1319 &access_mask, &share_mode,
1320 &create_disposition,
1321 &create_options,
1322 &private_flags)) {
1323 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1324 goto out;
1327 /* Any data in this call is an EA list. */
1328 if (total_data && (total_data != 4)) {
1329 if (total_data < 10) {
1330 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1331 goto out;
1334 if (IVAL(pdata,0) > total_data) {
1335 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1336 IVAL(pdata,0), (unsigned int)total_data));
1337 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1338 goto out;
1341 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1342 total_data - 4);
1343 if (!ea_list) {
1344 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1345 goto out;
1348 if (!lp_ea_support(SNUM(conn))) {
1349 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1350 goto out;
1353 if (!req->posix_pathnames &&
1354 ea_list_has_invalid_name(ea_list)) {
1355 int param_len = 30;
1356 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1357 if(*pparams == NULL ) {
1358 reply_nterror(req, NT_STATUS_NO_MEMORY);
1359 goto out;
1361 params = *pparams;
1362 memset(params, '\0', param_len);
1363 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1364 params, param_len, NULL, 0, max_data_bytes);
1365 goto out;
1369 status = SMB_VFS_CREATE_FILE(
1370 conn, /* conn */
1371 req, /* req */
1372 0, /* root_dir_fid */
1373 smb_fname, /* fname */
1374 access_mask, /* access_mask */
1375 share_mode, /* share_access */
1376 create_disposition, /* create_disposition*/
1377 create_options, /* create_options */
1378 open_attr, /* file_attributes */
1379 oplock_request, /* oplock_request */
1380 NULL, /* lease */
1381 open_size, /* allocation_size */
1382 private_flags,
1383 NULL, /* sd */
1384 ea_list, /* ea_list */
1385 &fsp, /* result */
1386 &smb_action, /* psbuf */
1387 NULL, NULL); /* create context */
1389 if (!NT_STATUS_IS_OK(status)) {
1390 if (open_was_deferred(req->xconn, req->mid)) {
1391 /* We have re-scheduled this call. */
1392 goto out;
1394 reply_openerror(req, status);
1395 goto out;
1398 size = get_file_size_stat(&smb_fname->st);
1399 fattr = dos_mode(conn, smb_fname);
1400 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1401 inode = smb_fname->st.st_ex_ino;
1402 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1403 close_file(req, fsp, ERROR_CLOSE);
1404 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1405 goto out;
1408 /* Realloc the size of parameters and data we will return */
1409 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1410 if(*pparams == NULL ) {
1411 reply_nterror(req, NT_STATUS_NO_MEMORY);
1412 goto out;
1414 params = *pparams;
1416 SSVAL(params,0,fsp->fnum);
1417 SSVAL(params,2,fattr);
1418 srv_put_dos_date2(params,4, mtime);
1419 SIVAL(params,8, (uint32_t)size);
1420 SSVAL(params,12,deny_mode);
1421 SSVAL(params,14,0); /* open_type - file or directory. */
1422 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1424 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1425 smb_action |= EXTENDED_OPLOCK_GRANTED;
1428 SSVAL(params,18,smb_action);
1431 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1433 SIVAL(params,20,inode);
1434 SSVAL(params,24,0); /* Padding. */
1435 if (flags & 8) {
1436 uint32_t ea_size = estimate_ea_size(conn, fsp,
1437 smb_fname);
1438 SIVAL(params, 26, ea_size);
1439 } else {
1440 SIVAL(params, 26, 0);
1443 /* Send the required number of replies */
1444 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1445 out:
1446 TALLOC_FREE(smb_fname);
1449 /*********************************************************
1450 Routine to check if a given string matches exactly.
1451 as a special case a mask of "." does NOT match. That
1452 is required for correct wildcard semantics
1453 Case can be significant or not.
1454 **********************************************************/
1456 static bool exact_match(bool has_wild,
1457 bool case_sensitive,
1458 const char *str,
1459 const char *mask)
1461 if (mask[0] == '.' && mask[1] == 0) {
1462 return false;
1465 if (has_wild) {
1466 return false;
1469 if (case_sensitive) {
1470 return strcmp(str,mask)==0;
1471 } else {
1472 return strcasecmp_m(str,mask) == 0;
1476 /****************************************************************************
1477 Return the filetype for UNIX extensions.
1478 ****************************************************************************/
1480 static uint32_t unix_filetype(mode_t mode)
1482 if(S_ISREG(mode))
1483 return UNIX_TYPE_FILE;
1484 else if(S_ISDIR(mode))
1485 return UNIX_TYPE_DIR;
1486 #ifdef S_ISLNK
1487 else if(S_ISLNK(mode))
1488 return UNIX_TYPE_SYMLINK;
1489 #endif
1490 #ifdef S_ISCHR
1491 else if(S_ISCHR(mode))
1492 return UNIX_TYPE_CHARDEV;
1493 #endif
1494 #ifdef S_ISBLK
1495 else if(S_ISBLK(mode))
1496 return UNIX_TYPE_BLKDEV;
1497 #endif
1498 #ifdef S_ISFIFO
1499 else if(S_ISFIFO(mode))
1500 return UNIX_TYPE_FIFO;
1501 #endif
1502 #ifdef S_ISSOCK
1503 else if(S_ISSOCK(mode))
1504 return UNIX_TYPE_SOCKET;
1505 #endif
1507 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1508 return UNIX_TYPE_UNKNOWN;
1511 /****************************************************************************
1512 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1513 ****************************************************************************/
1515 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1517 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1518 const SMB_STRUCT_STAT *psbuf,
1519 uint32_t perms,
1520 enum perm_type ptype,
1521 mode_t *ret_perms)
1523 mode_t ret = 0;
1525 if (perms == SMB_MODE_NO_CHANGE) {
1526 if (!VALID_STAT(*psbuf)) {
1527 return NT_STATUS_INVALID_PARAMETER;
1528 } else {
1529 *ret_perms = psbuf->st_ex_mode;
1530 return NT_STATUS_OK;
1534 ret = wire_perms_to_unix(perms);
1536 if (ptype == PERM_NEW_FILE) {
1538 * "create mask"/"force create mode" are
1539 * only applied to new files, not existing ones.
1541 ret &= lp_create_mask(SNUM(conn));
1542 /* Add in force bits */
1543 ret |= lp_force_create_mode(SNUM(conn));
1544 } else if (ptype == PERM_NEW_DIR) {
1546 * "directory mask"/"force directory mode" are
1547 * only applied to new directories, not existing ones.
1549 ret &= lp_directory_mask(SNUM(conn));
1550 /* Add in force bits */
1551 ret |= lp_force_directory_mode(SNUM(conn));
1554 *ret_perms = ret;
1555 return NT_STATUS_OK;
1558 /****************************************************************************
1559 Needed to show the msdfs symlinks as directories. Modifies psbuf
1560 to be a directory if it's a msdfs link.
1561 ****************************************************************************/
1563 static bool check_msdfs_link(connection_struct *conn,
1564 struct smb_filename *smb_fname)
1566 int saved_errno = errno;
1567 if(lp_host_msdfs() &&
1568 lp_msdfs_root(SNUM(conn)) &&
1569 is_msdfs_link(conn, smb_fname)) {
1571 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1572 "as a directory\n",
1573 smb_fname->base_name));
1574 smb_fname->st.st_ex_mode =
1575 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1576 errno = saved_errno;
1577 return true;
1579 errno = saved_errno;
1580 return false;
1584 /****************************************************************************
1585 Get a level dependent lanman2 dir entry.
1586 ****************************************************************************/
1588 struct smbd_dirptr_lanman2_state {
1589 connection_struct *conn;
1590 uint32_t info_level;
1591 bool check_mangled_names;
1592 bool has_wild;
1593 bool got_exact_match;
1596 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1597 void *private_data,
1598 const char *dname,
1599 const char *mask,
1600 char **_fname)
1602 struct smbd_dirptr_lanman2_state *state =
1603 (struct smbd_dirptr_lanman2_state *)private_data;
1604 bool ok;
1605 char mangled_name[13]; /* mangled 8.3 name. */
1606 bool got_match;
1607 const char *fname;
1609 /* Mangle fname if it's an illegal name. */
1610 if (mangle_must_mangle(dname, state->conn->params)) {
1612 * Slow path - ensure we can push the original name as UCS2. If
1613 * not, then just don't return this name.
1615 NTSTATUS status;
1616 size_t ret_len = 0;
1617 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1618 uint8_t *tmp = talloc_array(talloc_tos(),
1619 uint8_t,
1620 len);
1622 status = srvstr_push(NULL,
1623 FLAGS2_UNICODE_STRINGS,
1624 tmp,
1625 dname,
1626 len,
1627 STR_TERMINATE,
1628 &ret_len);
1630 TALLOC_FREE(tmp);
1632 if (!NT_STATUS_IS_OK(status)) {
1633 return false;
1636 ok = name_to_8_3(dname, mangled_name,
1637 true, state->conn->params);
1638 if (!ok) {
1639 return false;
1641 fname = mangled_name;
1642 } else {
1643 fname = dname;
1646 got_match = exact_match(state->has_wild,
1647 state->conn->case_sensitive,
1648 fname, mask);
1649 state->got_exact_match = got_match;
1650 if (!got_match) {
1651 got_match = mask_match(fname, mask,
1652 state->conn->case_sensitive);
1655 if(!got_match && state->check_mangled_names &&
1656 !mangle_is_8_3(fname, false, state->conn->params)) {
1658 * It turns out that NT matches wildcards against
1659 * both long *and* short names. This may explain some
1660 * of the wildcard wierdness from old DOS clients
1661 * that some people have been seeing.... JRA.
1663 /* Force the mangling into 8.3. */
1664 ok = name_to_8_3(fname, mangled_name,
1665 false, state->conn->params);
1666 if (!ok) {
1667 return false;
1670 got_match = exact_match(state->has_wild,
1671 state->conn->case_sensitive,
1672 mangled_name, mask);
1673 state->got_exact_match = got_match;
1674 if (!got_match) {
1675 got_match = mask_match(mangled_name, mask,
1676 state->conn->case_sensitive);
1680 if (!got_match) {
1681 return false;
1684 *_fname = talloc_strdup(ctx, fname);
1685 if (*_fname == NULL) {
1686 return false;
1689 return true;
1692 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1693 void *private_data,
1694 struct smb_filename *smb_fname,
1695 bool get_dosmode,
1696 uint32_t *_mode)
1698 struct smbd_dirptr_lanman2_state *state =
1699 (struct smbd_dirptr_lanman2_state *)private_data;
1700 bool ms_dfs_link = false;
1701 uint32_t mode = 0;
1703 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1704 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1705 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1706 "Couldn't lstat [%s] (%s)\n",
1707 smb_fname_str_dbg(smb_fname),
1708 strerror(errno)));
1709 return false;
1711 } else if (!VALID_STAT(smb_fname->st) &&
1712 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1713 /* Needed to show the msdfs symlinks as
1714 * directories */
1716 ms_dfs_link = check_msdfs_link(state->conn,
1717 smb_fname);
1718 if (!ms_dfs_link) {
1719 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1720 "Couldn't stat [%s] (%s)\n",
1721 smb_fname_str_dbg(smb_fname),
1722 strerror(errno)));
1723 return false;
1727 if (ms_dfs_link) {
1728 mode = dos_mode_msdfs(state->conn, smb_fname);
1729 } else if (get_dosmode) {
1730 mode = dos_mode(state->conn, smb_fname);
1733 *_mode = mode;
1734 return true;
1737 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1738 connection_struct *conn,
1739 uint16_t flags2,
1740 uint32_t info_level,
1741 struct ea_list *name_list,
1742 bool check_mangled_names,
1743 bool requires_resume_key,
1744 uint32_t mode,
1745 const char *fname,
1746 const struct smb_filename *smb_fname,
1747 int space_remaining,
1748 uint8_t align,
1749 bool do_pad,
1750 char *base_data,
1751 char **ppdata,
1752 char *end_data,
1753 uint64_t *last_entry_off)
1755 char *p, *q, *pdata = *ppdata;
1756 uint32_t reskey=0;
1757 uint64_t file_size = 0;
1758 uint64_t allocation_size = 0;
1759 uint64_t file_index = 0;
1760 size_t len = 0;
1761 struct timespec mdate_ts = {0};
1762 struct timespec adate_ts = {0};
1763 struct timespec cdate_ts = {0};
1764 struct timespec create_date_ts = {0};
1765 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1766 char *nameptr;
1767 char *last_entry_ptr;
1768 bool was_8_3;
1769 int off;
1770 int pad = 0;
1771 NTSTATUS status;
1772 struct readdir_attr_data *readdir_attr_data = NULL;
1774 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1775 file_size = get_file_size_stat(&smb_fname->st);
1777 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1779 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1780 if (!NT_STATUS_IS_OK(status)) {
1781 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1782 return status;
1786 file_index = get_FileIndex(conn, &smb_fname->st);
1788 mdate_ts = smb_fname->st.st_ex_mtime;
1789 adate_ts = smb_fname->st.st_ex_atime;
1790 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1791 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1793 if (lp_dos_filetime_resolution(SNUM(conn))) {
1794 dos_filetime_timespec(&create_date_ts);
1795 dos_filetime_timespec(&mdate_ts);
1796 dos_filetime_timespec(&adate_ts);
1797 dos_filetime_timespec(&cdate_ts);
1800 create_date = convert_timespec_to_time_t(create_date_ts);
1801 mdate = convert_timespec_to_time_t(mdate_ts);
1802 adate = convert_timespec_to_time_t(adate_ts);
1804 /* align the record */
1805 SMB_ASSERT(align >= 1);
1807 off = (int)PTR_DIFF(pdata, base_data);
1808 pad = (off + (align-1)) & ~(align-1);
1809 pad -= off;
1811 if (pad && pad > space_remaining) {
1812 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1813 "for padding (wanted %u, had %d)\n",
1814 (unsigned int)pad,
1815 space_remaining ));
1816 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1819 off += pad;
1820 /* initialize padding to 0 */
1821 if (pad) {
1822 memset(pdata, 0, pad);
1824 space_remaining -= pad;
1826 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1827 space_remaining ));
1829 pdata += pad;
1830 p = pdata;
1831 last_entry_ptr = p;
1833 pad = 0;
1834 off = 0;
1836 switch (info_level) {
1837 case SMB_FIND_INFO_STANDARD:
1838 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1839 if(requires_resume_key) {
1840 SIVAL(p,0,reskey);
1841 p += 4;
1843 srv_put_dos_date2(p,0,create_date);
1844 srv_put_dos_date2(p,4,adate);
1845 srv_put_dos_date2(p,8,mdate);
1846 SIVAL(p,12,(uint32_t)file_size);
1847 SIVAL(p,16,(uint32_t)allocation_size);
1848 SSVAL(p,20,mode);
1849 p += 23;
1850 nameptr = p;
1851 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1852 p += ucs2_align(base_data, p, 0);
1854 status = srvstr_push(base_data, flags2, p,
1855 fname, PTR_DIFF(end_data, p),
1856 STR_TERMINATE, &len);
1857 if (!NT_STATUS_IS_OK(status)) {
1858 return status;
1860 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1861 if (len > 2) {
1862 SCVAL(nameptr, -1, len - 2);
1863 } else {
1864 SCVAL(nameptr, -1, 0);
1866 } else {
1867 if (len > 1) {
1868 SCVAL(nameptr, -1, len - 1);
1869 } else {
1870 SCVAL(nameptr, -1, 0);
1873 p += len;
1874 break;
1876 case SMB_FIND_EA_SIZE:
1877 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1878 if (requires_resume_key) {
1879 SIVAL(p,0,reskey);
1880 p += 4;
1882 srv_put_dos_date2(p,0,create_date);
1883 srv_put_dos_date2(p,4,adate);
1884 srv_put_dos_date2(p,8,mdate);
1885 SIVAL(p,12,(uint32_t)file_size);
1886 SIVAL(p,16,(uint32_t)allocation_size);
1887 SSVAL(p,20,mode);
1889 unsigned int ea_size = estimate_ea_size(conn, NULL,
1890 smb_fname);
1891 SIVAL(p,22,ea_size); /* Extended attributes */
1893 p += 27;
1894 nameptr = p - 1;
1895 status = srvstr_push(base_data, flags2,
1896 p, fname, PTR_DIFF(end_data, p),
1897 STR_TERMINATE | STR_NOALIGN, &len);
1898 if (!NT_STATUS_IS_OK(status)) {
1899 return status;
1901 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1902 if (len > 2) {
1903 len -= 2;
1904 } else {
1905 len = 0;
1907 } else {
1908 if (len > 1) {
1909 len -= 1;
1910 } else {
1911 len = 0;
1914 SCVAL(nameptr,0,len);
1915 p += len;
1916 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1917 break;
1919 case SMB_FIND_EA_LIST:
1921 struct ea_list *file_list = NULL;
1922 size_t ea_len = 0;
1924 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1925 if (!name_list) {
1926 return NT_STATUS_INVALID_PARAMETER;
1928 if (requires_resume_key) {
1929 SIVAL(p,0,reskey);
1930 p += 4;
1932 srv_put_dos_date2(p,0,create_date);
1933 srv_put_dos_date2(p,4,adate);
1934 srv_put_dos_date2(p,8,mdate);
1935 SIVAL(p,12,(uint32_t)file_size);
1936 SIVAL(p,16,(uint32_t)allocation_size);
1937 SSVAL(p,20,mode);
1938 p += 22; /* p now points to the EA area. */
1940 status = get_ea_list_from_file(ctx, conn, NULL,
1941 smb_fname,
1942 &ea_len, &file_list);
1943 if (!NT_STATUS_IS_OK(status)) {
1944 file_list = NULL;
1946 name_list = ea_list_union(name_list, file_list, &ea_len);
1948 /* We need to determine if this entry will fit in the space available. */
1949 /* Max string size is 255 bytes. */
1950 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1951 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1952 "(wanted %u, had %d)\n",
1953 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1954 space_remaining ));
1955 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1958 /* Push the ea_data followed by the name. */
1959 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1960 nameptr = p;
1961 status = srvstr_push(base_data, flags2,
1962 p + 1, fname, PTR_DIFF(end_data, p+1),
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 + 1;
1982 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1983 break;
1986 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1987 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1988 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1989 p += 4;
1990 SIVAL(p,0,reskey); p += 4;
1991 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1992 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1993 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1994 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1995 SOFF_T(p,0,file_size); p += 8;
1996 SOFF_T(p,0,allocation_size); p += 8;
1997 SIVAL(p,0,mode); p += 4;
1998 q = p; p += 4; /* q is placeholder for name length. */
1999 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2000 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2001 } else {
2002 unsigned int ea_size = estimate_ea_size(conn, NULL,
2003 smb_fname);
2004 SIVAL(p,0,ea_size); /* Extended attributes */
2006 p += 4;
2007 /* Clear the short name buffer. This is
2008 * IMPORTANT as not doing so will trigger
2009 * a Win2k client bug. JRA.
2011 if (!was_8_3 && check_mangled_names) {
2012 char mangled_name[13]; /* mangled 8.3 name. */
2013 if (!name_to_8_3(fname,mangled_name,True,
2014 conn->params)) {
2015 /* Error - mangle failed ! */
2016 memset(mangled_name,'\0',12);
2018 mangled_name[12] = 0;
2019 status = srvstr_push(base_data, flags2,
2020 p+2, mangled_name, 24,
2021 STR_UPPER|STR_UNICODE, &len);
2022 if (!NT_STATUS_IS_OK(status)) {
2023 return status;
2025 if (len < 24) {
2026 memset(p + 2 + len,'\0',24 - len);
2028 SSVAL(p, 0, len);
2029 } else {
2030 memset(p,'\0',26);
2032 p += 2 + 24;
2033 status = srvstr_push(base_data, flags2, p,
2034 fname, PTR_DIFF(end_data, p),
2035 STR_TERMINATE_ASCII, &len);
2036 if (!NT_STATUS_IS_OK(status)) {
2037 return status;
2039 SIVAL(q,0,len);
2040 p += len;
2042 len = PTR_DIFF(p, pdata);
2043 pad = (len + (align-1)) & ~(align-1);
2045 * offset to the next entry, the caller
2046 * will overwrite it for the last entry
2047 * that's why we always include the padding
2049 SIVAL(pdata,0,pad);
2051 * set padding to zero
2053 if (do_pad) {
2054 memset(p, 0, pad - len);
2055 p = pdata + pad;
2056 } else {
2057 p = pdata + len;
2059 break;
2061 case SMB_FIND_FILE_DIRECTORY_INFO:
2062 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2063 p += 4;
2064 SIVAL(p,0,reskey); p += 4;
2065 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2066 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2067 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2068 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2069 SOFF_T(p,0,file_size); p += 8;
2070 SOFF_T(p,0,allocation_size); p += 8;
2071 SIVAL(p,0,mode); p += 4;
2072 status = srvstr_push(base_data, flags2,
2073 p + 4, fname, PTR_DIFF(end_data, p+4),
2074 STR_TERMINATE_ASCII, &len);
2075 if (!NT_STATUS_IS_OK(status)) {
2076 return status;
2078 SIVAL(p,0,len);
2079 p += 4 + len;
2081 len = PTR_DIFF(p, pdata);
2082 pad = (len + (align-1)) & ~(align-1);
2084 * offset to the next entry, the caller
2085 * will overwrite it for the last entry
2086 * that's why we always include the padding
2088 SIVAL(pdata,0,pad);
2090 * set padding to zero
2092 if (do_pad) {
2093 memset(p, 0, pad - len);
2094 p = pdata + pad;
2095 } else {
2096 p = pdata + len;
2098 break;
2100 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2101 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2102 p += 4;
2103 SIVAL(p,0,reskey); p += 4;
2104 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2105 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2106 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2107 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2108 SOFF_T(p,0,file_size); p += 8;
2109 SOFF_T(p,0,allocation_size); p += 8;
2110 SIVAL(p,0,mode); p += 4;
2111 q = p; p += 4; /* q is placeholder for name length. */
2112 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2113 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2114 } else {
2115 unsigned int ea_size = estimate_ea_size(conn, NULL,
2116 smb_fname);
2117 SIVAL(p,0,ea_size); /* Extended attributes */
2119 p +=4;
2120 status = srvstr_push(base_data, flags2, p,
2121 fname, PTR_DIFF(end_data, p),
2122 STR_TERMINATE_ASCII, &len);
2123 if (!NT_STATUS_IS_OK(status)) {
2124 return status;
2126 SIVAL(q, 0, len);
2127 p += len;
2129 len = PTR_DIFF(p, pdata);
2130 pad = (len + (align-1)) & ~(align-1);
2132 * offset to the next entry, the caller
2133 * will overwrite it for the last entry
2134 * that's why we always include the padding
2136 SIVAL(pdata,0,pad);
2138 * set padding to zero
2140 if (do_pad) {
2141 memset(p, 0, pad - len);
2142 p = pdata + pad;
2143 } else {
2144 p = pdata + len;
2146 break;
2148 case SMB_FIND_FILE_NAMES_INFO:
2149 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2150 p += 4;
2151 SIVAL(p,0,reskey); p += 4;
2152 p += 4;
2153 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2154 acl on a dir (tridge) */
2155 status = srvstr_push(base_data, flags2, p,
2156 fname, PTR_DIFF(end_data, p),
2157 STR_TERMINATE_ASCII, &len);
2158 if (!NT_STATUS_IS_OK(status)) {
2159 return status;
2161 SIVAL(p, -4, len);
2162 p += len;
2164 len = PTR_DIFF(p, pdata);
2165 pad = (len + (align-1)) & ~(align-1);
2167 * offset to the next entry, the caller
2168 * will overwrite it for the last entry
2169 * that's why we always include the padding
2171 SIVAL(pdata,0,pad);
2173 * set padding to zero
2175 if (do_pad) {
2176 memset(p, 0, pad - len);
2177 p = pdata + pad;
2178 } else {
2179 p = pdata + len;
2181 break;
2183 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2184 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2185 p += 4;
2186 SIVAL(p,0,reskey); p += 4;
2187 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2188 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2189 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2190 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2191 SOFF_T(p,0,file_size); p += 8;
2192 SOFF_T(p,0,allocation_size); p += 8;
2193 SIVAL(p,0,mode); p += 4;
2194 q = p; p += 4; /* q is placeholder for name length. */
2195 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2196 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2197 } else {
2198 unsigned int ea_size = estimate_ea_size(conn, NULL,
2199 smb_fname);
2200 SIVAL(p,0,ea_size); /* Extended attributes */
2202 p += 4;
2203 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2204 SBVAL(p,0,file_index); p += 8;
2205 status = srvstr_push(base_data, flags2, p,
2206 fname, PTR_DIFF(end_data, p),
2207 STR_TERMINATE_ASCII, &len);
2208 if (!NT_STATUS_IS_OK(status)) {
2209 return status;
2211 SIVAL(q, 0, len);
2212 p += len;
2214 len = PTR_DIFF(p, pdata);
2215 pad = (len + (align-1)) & ~(align-1);
2217 * offset to the next entry, the caller
2218 * will overwrite it for the last entry
2219 * that's why we always include the padding
2221 SIVAL(pdata,0,pad);
2223 * set padding to zero
2225 if (do_pad) {
2226 memset(p, 0, pad - len);
2227 p = pdata + pad;
2228 } else {
2229 p = pdata + len;
2231 break;
2233 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2234 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2235 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2236 p += 4;
2237 SIVAL(p,0,reskey); p += 4;
2238 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2239 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2240 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2241 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2242 SOFF_T(p,0,file_size); p += 8;
2243 SOFF_T(p,0,allocation_size); p += 8;
2244 SIVAL(p,0,mode); p += 4;
2245 q = p; p += 4; /* q is placeholder for name length */
2246 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2247 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2248 } else if (readdir_attr_data &&
2249 readdir_attr_data->type == RDATTR_AAPL) {
2251 * OS X specific SMB2 extension negotiated via
2252 * AAPL create context: return max_access in
2253 * ea_size field.
2255 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2256 } else {
2257 unsigned int ea_size = estimate_ea_size(conn, NULL,
2258 smb_fname);
2259 SIVAL(p,0,ea_size); /* Extended attributes */
2261 p += 4;
2263 if (readdir_attr_data &&
2264 readdir_attr_data->type == RDATTR_AAPL) {
2266 * OS X specific SMB2 extension negotiated via
2267 * AAPL create context: return resource fork
2268 * length and compressed FinderInfo in
2269 * shortname field.
2271 * According to documentation short_name_len
2272 * should be 0, but on the wire behaviour
2273 * shows its set to 24 by clients.
2275 SSVAL(p, 0, 24);
2277 /* Resourefork length */
2278 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2280 /* Compressed FinderInfo */
2281 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2282 } else if (!was_8_3 && check_mangled_names) {
2283 char mangled_name[13]; /* mangled 8.3 name. */
2284 if (!name_to_8_3(fname,mangled_name,True,
2285 conn->params)) {
2286 /* Error - mangle failed ! */
2287 memset(mangled_name,'\0',12);
2289 mangled_name[12] = 0;
2290 status = srvstr_push(base_data, flags2,
2291 p+2, mangled_name, 24,
2292 STR_UPPER|STR_UNICODE, &len);
2293 if (!NT_STATUS_IS_OK(status)) {
2294 return status;
2296 SSVAL(p, 0, len);
2297 if (len < 24) {
2298 memset(p + 2 + len,'\0',24 - len);
2300 SSVAL(p, 0, len);
2301 } else {
2302 /* Clear the short name buffer. This is
2303 * IMPORTANT as not doing so will trigger
2304 * a Win2k client bug. JRA.
2306 memset(p,'\0',26);
2308 p += 26;
2310 /* Reserved ? */
2311 if (readdir_attr_data &&
2312 readdir_attr_data->type == RDATTR_AAPL) {
2314 * OS X specific SMB2 extension negotiated via
2315 * AAPL create context: return UNIX mode in
2316 * reserved field.
2318 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2319 SSVAL(p, 0, aapl_mode);
2320 } else {
2321 SSVAL(p, 0, 0);
2323 p += 2;
2325 SBVAL(p,0,file_index); p += 8;
2326 status = srvstr_push(base_data, flags2, p,
2327 fname, PTR_DIFF(end_data, p),
2328 STR_TERMINATE_ASCII, &len);
2329 if (!NT_STATUS_IS_OK(status)) {
2330 return status;
2332 SIVAL(q,0,len);
2333 p += len;
2335 len = PTR_DIFF(p, pdata);
2336 pad = (len + (align-1)) & ~(align-1);
2338 * offset to the next entry, the caller
2339 * will overwrite it for the last entry
2340 * that's why we always include the padding
2342 SIVAL(pdata,0,pad);
2344 * set padding to zero
2346 if (do_pad) {
2347 memset(p, 0, pad - len);
2348 p = pdata + pad;
2349 } else {
2350 p = pdata + len;
2352 break;
2354 /* CIFS UNIX Extension. */
2356 case SMB_FIND_FILE_UNIX:
2357 case SMB_FIND_FILE_UNIX_INFO2:
2358 p+= 4;
2359 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2361 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2363 if (info_level == SMB_FIND_FILE_UNIX) {
2364 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2365 p = store_file_unix_basic(conn, p,
2366 NULL, &smb_fname->st);
2367 status = srvstr_push(base_data, flags2, p,
2368 fname, PTR_DIFF(end_data, p),
2369 STR_TERMINATE, &len);
2370 if (!NT_STATUS_IS_OK(status)) {
2371 return status;
2373 } else {
2374 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2375 p = store_file_unix_basic_info2(conn, p,
2376 NULL, &smb_fname->st);
2377 nameptr = p;
2378 p += 4;
2379 status = srvstr_push(base_data, flags2, p, fname,
2380 PTR_DIFF(end_data, p), 0, &len);
2381 if (!NT_STATUS_IS_OK(status)) {
2382 return status;
2384 SIVAL(nameptr, 0, len);
2387 p += len;
2389 len = PTR_DIFF(p, pdata);
2390 pad = (len + (align-1)) & ~(align-1);
2392 * offset to the next entry, the caller
2393 * will overwrite it for the last entry
2394 * that's why we always include the padding
2396 SIVAL(pdata,0,pad);
2398 * set padding to zero
2400 if (do_pad) {
2401 memset(p, 0, pad - len);
2402 p = pdata + pad;
2403 } else {
2404 p = pdata + len;
2406 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2408 break;
2410 default:
2411 return NT_STATUS_INVALID_LEVEL;
2414 if (PTR_DIFF(p,pdata) > space_remaining) {
2415 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2416 "(wanted %u, had %d)\n",
2417 (unsigned int)PTR_DIFF(p,pdata),
2418 space_remaining ));
2419 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2422 /* Setup the last entry pointer, as an offset from base_data */
2423 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2424 /* Advance the data pointer to the next slot */
2425 *ppdata = p;
2427 return NT_STATUS_OK;
2430 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2431 connection_struct *conn,
2432 struct dptr_struct *dirptr,
2433 uint16_t flags2,
2434 const char *path_mask,
2435 uint32_t dirtype,
2436 int info_level,
2437 int requires_resume_key,
2438 bool dont_descend,
2439 bool ask_sharemode,
2440 bool get_dosmode,
2441 uint8_t align,
2442 bool do_pad,
2443 char **ppdata,
2444 char *base_data,
2445 char *end_data,
2446 int space_remaining,
2447 struct smb_filename **_smb_fname,
2448 bool *got_exact_match,
2449 int *_last_entry_off,
2450 struct ea_list *name_list,
2451 struct file_id *file_id)
2453 const char *p;
2454 const char *mask = NULL;
2455 long prev_dirpos = 0;
2456 uint32_t mode = 0;
2457 char *fname = NULL;
2458 struct smb_filename *smb_fname = NULL;
2459 struct smbd_dirptr_lanman2_state state;
2460 bool ok;
2461 uint64_t last_entry_off = 0;
2462 NTSTATUS status;
2463 enum mangled_names_options mangled_names;
2464 bool marshall_with_83_names;
2466 mangled_names = lp_mangled_names(conn->params);
2468 ZERO_STRUCT(state);
2469 state.conn = conn;
2470 state.info_level = info_level;
2471 if (mangled_names != MANGLED_NAMES_NO) {
2472 state.check_mangled_names = true;
2474 state.has_wild = dptr_has_wild(dirptr);
2475 state.got_exact_match = false;
2477 *got_exact_match = false;
2479 p = strrchr_m(path_mask,'/');
2480 if(p != NULL) {
2481 if(p[1] == '\0') {
2482 mask = "*.*";
2483 } else {
2484 mask = p+1;
2486 } else {
2487 mask = path_mask;
2490 ok = smbd_dirptr_get_entry(ctx,
2491 dirptr,
2492 mask,
2493 dirtype,
2494 dont_descend,
2495 ask_sharemode,
2496 get_dosmode,
2497 smbd_dirptr_lanman2_match_fn,
2498 smbd_dirptr_lanman2_mode_fn,
2499 &state,
2500 &fname,
2501 &smb_fname,
2502 &mode,
2503 &prev_dirpos);
2504 if (!ok) {
2505 return NT_STATUS_END_OF_FILE;
2508 *got_exact_match = state.got_exact_match;
2510 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2512 status = smbd_marshall_dir_entry(ctx,
2513 conn,
2514 flags2,
2515 info_level,
2516 name_list,
2517 marshall_with_83_names,
2518 requires_resume_key,
2519 mode,
2520 fname,
2521 smb_fname,
2522 space_remaining,
2523 align,
2524 do_pad,
2525 base_data,
2526 ppdata,
2527 end_data,
2528 &last_entry_off);
2529 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2530 DEBUG(1,("Conversion error: illegal character: %s\n",
2531 smb_fname_str_dbg(smb_fname)));
2534 if (file_id != NULL) {
2535 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2538 if (!NT_STATUS_IS_OK(status) &&
2539 !NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES))
2541 TALLOC_FREE(smb_fname);
2542 TALLOC_FREE(fname);
2543 return status;
2546 if (_smb_fname != NULL) {
2547 struct smb_filename *name = NULL;
2549 name = synthetic_smb_fname(ctx, fname, NULL, &smb_fname->st, 0);
2550 if (name == NULL) {
2551 TALLOC_FREE(smb_fname);
2552 TALLOC_FREE(fname);
2553 return NT_STATUS_NO_MEMORY;
2555 *_smb_fname = name;
2558 TALLOC_FREE(smb_fname);
2559 TALLOC_FREE(fname);
2561 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2562 dptr_SeekDir(dirptr, prev_dirpos);
2563 return status;
2566 *_last_entry_off = last_entry_off;
2567 return NT_STATUS_OK;
2570 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2571 connection_struct *conn,
2572 struct dptr_struct *dirptr,
2573 uint16_t flags2,
2574 const char *path_mask,
2575 uint32_t dirtype,
2576 int info_level,
2577 bool requires_resume_key,
2578 bool dont_descend,
2579 bool ask_sharemode,
2580 char **ppdata,
2581 char *base_data,
2582 char *end_data,
2583 int space_remaining,
2584 bool *got_exact_match,
2585 int *last_entry_off,
2586 struct ea_list *name_list)
2588 uint8_t align = 4;
2589 const bool do_pad = true;
2591 if (info_level >= 1 && info_level <= 3) {
2592 /* No alignment on earlier info levels. */
2593 align = 1;
2596 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2597 path_mask, dirtype, info_level,
2598 requires_resume_key, dont_descend, ask_sharemode,
2599 true, align, do_pad,
2600 ppdata, base_data, end_data,
2601 space_remaining,
2602 NULL,
2603 got_exact_match,
2604 last_entry_off, name_list, NULL);
2607 /****************************************************************************
2608 Reply to a TRANS2_FINDFIRST.
2609 ****************************************************************************/
2611 static void call_trans2findfirst(connection_struct *conn,
2612 struct smb_request *req,
2613 char **pparams, int total_params,
2614 char **ppdata, int total_data,
2615 unsigned int max_data_bytes)
2617 /* We must be careful here that we don't return more than the
2618 allowed number of data bytes. If this means returning fewer than
2619 maxentries then so be it. We assume that the redirector has
2620 enough room for the fixed number of parameter bytes it has
2621 requested. */
2622 struct smb_filename *smb_dname = NULL;
2623 char *params = *pparams;
2624 char *pdata = *ppdata;
2625 char *data_end;
2626 uint32_t dirtype;
2627 int maxentries;
2628 uint16_t findfirst_flags;
2629 bool close_after_first;
2630 bool close_if_end;
2631 bool requires_resume_key;
2632 int info_level;
2633 char *directory = NULL;
2634 char *mask = NULL;
2635 char *p;
2636 int last_entry_off=0;
2637 int dptr_num = -1;
2638 int numentries = 0;
2639 int i;
2640 bool finished = False;
2641 bool dont_descend = False;
2642 bool out_of_space = False;
2643 int space_remaining;
2644 bool mask_contains_wcard = False;
2645 struct ea_list *ea_list = NULL;
2646 NTSTATUS ntstatus = NT_STATUS_OK;
2647 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2648 struct dptr_struct *dirptr = NULL;
2649 struct smbd_server_connection *sconn = req->sconn;
2650 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2651 ucf_flags_from_smb_request(req);
2652 bool backup_priv = false;
2653 bool as_root = false;
2655 if (total_params < 13) {
2656 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2657 goto out;
2660 dirtype = SVAL(params,0);
2661 maxentries = SVAL(params,2);
2662 findfirst_flags = SVAL(params,4);
2663 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2664 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2665 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2666 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2667 security_token_has_privilege(get_current_nttok(conn),
2668 SEC_PRIV_BACKUP));
2670 info_level = SVAL(params,6);
2672 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2673 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2674 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2675 (int)backup_priv,
2676 info_level, max_data_bytes));
2678 if (!maxentries) {
2679 /* W2K3 seems to treat zero as 1. */
2680 maxentries = 1;
2683 switch (info_level) {
2684 case SMB_FIND_INFO_STANDARD:
2685 case SMB_FIND_EA_SIZE:
2686 case SMB_FIND_EA_LIST:
2687 case SMB_FIND_FILE_DIRECTORY_INFO:
2688 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2689 case SMB_FIND_FILE_NAMES_INFO:
2690 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2691 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2692 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2693 break;
2694 case SMB_FIND_FILE_UNIX:
2695 case SMB_FIND_FILE_UNIX_INFO2:
2696 /* Always use filesystem for UNIX mtime query. */
2697 ask_sharemode = false;
2698 if (!lp_unix_extensions()) {
2699 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2700 goto out;
2702 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2703 break;
2704 default:
2705 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2706 goto out;
2709 if (req->posix_pathnames) {
2710 srvstr_get_path_wcard_posix(talloc_tos(),
2711 params,
2712 req->flags2,
2713 &directory,
2714 params+12,
2715 total_params - 12,
2716 STR_TERMINATE,
2717 &ntstatus,
2718 &mask_contains_wcard);
2719 } else {
2720 srvstr_get_path_wcard(talloc_tos(),
2721 params,
2722 req->flags2,
2723 &directory,
2724 params+12,
2725 total_params - 12,
2726 STR_TERMINATE,
2727 &ntstatus,
2728 &mask_contains_wcard);
2730 if (!NT_STATUS_IS_OK(ntstatus)) {
2731 reply_nterror(req, ntstatus);
2732 goto out;
2735 if (backup_priv) {
2736 become_root();
2737 as_root = true;
2738 ntstatus = filename_convert_with_privilege(talloc_tos(),
2739 conn,
2740 req,
2741 directory,
2742 ucf_flags,
2743 &mask_contains_wcard,
2744 &smb_dname);
2745 } else {
2746 ntstatus = filename_convert(talloc_tos(), conn,
2747 directory,
2748 ucf_flags,
2749 NULL,
2750 &mask_contains_wcard,
2751 &smb_dname);
2754 if (!NT_STATUS_IS_OK(ntstatus)) {
2755 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2756 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2757 ERRSRV, ERRbadpath);
2758 goto out;
2760 reply_nterror(req, ntstatus);
2761 goto out;
2764 mask = smb_dname->original_lcomp;
2766 directory = smb_dname->base_name;
2768 p = strrchr_m(directory,'/');
2769 if(p == NULL) {
2770 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2771 if((directory[0] == '.') && (directory[1] == '\0')) {
2772 mask = talloc_strdup(talloc_tos(),"*");
2773 if (!mask) {
2774 reply_nterror(req, NT_STATUS_NO_MEMORY);
2775 goto out;
2777 mask_contains_wcard = True;
2779 } else {
2780 *p = 0;
2783 if (p == NULL || p == directory) {
2784 /* Ensure we don't have a directory name of "". */
2785 directory = talloc_strdup(talloc_tos(), ".");
2786 if (!directory) {
2787 reply_nterror(req, NT_STATUS_NO_MEMORY);
2788 goto out;
2790 /* Ensure smb_dname->base_name matches. */
2791 smb_dname->base_name = directory;
2794 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2796 if (info_level == SMB_FIND_EA_LIST) {
2797 uint32_t ea_size;
2799 if (total_data < 4) {
2800 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2801 goto out;
2804 ea_size = IVAL(pdata,0);
2805 if (ea_size != total_data) {
2806 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2807 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2809 goto out;
2812 if (!lp_ea_support(SNUM(conn))) {
2813 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2814 goto out;
2817 /* Pull out the list of names. */
2818 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2819 if (!ea_list) {
2820 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2821 goto out;
2825 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2826 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2827 goto out;
2830 *ppdata = (char *)SMB_REALLOC(
2831 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2832 if(*ppdata == NULL ) {
2833 reply_nterror(req, NT_STATUS_NO_MEMORY);
2834 goto out;
2836 pdata = *ppdata;
2837 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2839 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2840 * error.
2842 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2843 /* Realloc the params space */
2844 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2845 if (*pparams == NULL) {
2846 reply_nterror(req, NT_STATUS_NO_MEMORY);
2847 goto out;
2849 params = *pparams;
2851 /* Save the wildcard match and attribs we are using on this directory -
2852 needed as lanman2 assumes these are being saved between calls */
2854 ntstatus = dptr_create(conn,
2855 req,
2856 NULL, /* fsp */
2857 smb_dname,
2858 False,
2859 True,
2860 req->smbpid,
2861 mask,
2862 mask_contains_wcard,
2863 dirtype,
2864 &dirptr);
2866 if (!NT_STATUS_IS_OK(ntstatus)) {
2867 reply_nterror(req, ntstatus);
2868 goto out;
2871 if (backup_priv) {
2872 /* Remember this in case we have
2873 to do a findnext. */
2874 dptr_set_priv(dirptr);
2877 dptr_num = dptr_dnum(dirptr);
2878 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2880 /* We don't need to check for VOL here as this is returned by
2881 a different TRANS2 call. */
2883 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2884 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2885 if (in_list(directory,
2886 lp_dont_descend(talloc_tos(), SNUM(conn)),
2887 conn->case_sensitive)) {
2888 dont_descend = True;
2891 p = pdata;
2892 space_remaining = max_data_bytes;
2893 out_of_space = False;
2895 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2896 bool got_exact_match = False;
2898 /* this is a heuristic to avoid seeking the dirptr except when
2899 absolutely necessary. It allows for a filename of about 40 chars */
2900 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2901 out_of_space = True;
2902 finished = False;
2903 } else {
2904 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2905 conn,
2906 dirptr,
2907 req->flags2,
2908 mask,dirtype,info_level,
2909 requires_resume_key,dont_descend,
2910 ask_sharemode,
2911 &p,pdata,data_end,
2912 space_remaining,
2913 &got_exact_match,
2914 &last_entry_off, ea_list);
2915 if (NT_STATUS_EQUAL(ntstatus,
2916 NT_STATUS_ILLEGAL_CHARACTER)) {
2918 * Bad character conversion on name. Ignore this
2919 * entry.
2921 continue;
2923 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2924 out_of_space = true;
2925 } else {
2926 finished = !NT_STATUS_IS_OK(ntstatus);
2930 if (!finished && !out_of_space)
2931 numentries++;
2934 * As an optimisation if we know we aren't looking
2935 * for a wildcard name (ie. the name matches the wildcard exactly)
2936 * then we can finish on any (first) match.
2937 * This speeds up large directory searches. JRA.
2940 if(got_exact_match)
2941 finished = True;
2943 /* Ensure space_remaining never goes -ve. */
2944 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2945 space_remaining = 0;
2946 out_of_space = true;
2947 } else {
2948 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2952 /* Check if we can close the dirptr */
2953 if(close_after_first || (finished && close_if_end)) {
2954 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2955 dptr_close(sconn, &dptr_num);
2959 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2960 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2961 * the protocol level is less than NT1. Tested with smbclient. JRA.
2962 * This should fix the OS/2 client bug #2335.
2965 if(numentries == 0) {
2966 dptr_close(sconn, &dptr_num);
2967 if (get_Protocol() < PROTOCOL_NT1) {
2968 reply_force_doserror(req, ERRDOS, ERRnofiles);
2969 goto out;
2970 } else {
2971 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2972 ERRDOS, ERRbadfile);
2973 goto out;
2977 /* At this point pdata points to numentries directory entries. */
2979 /* Set up the return parameter block */
2980 SSVAL(params,0,dptr_num);
2981 SSVAL(params,2,numentries);
2982 SSVAL(params,4,finished);
2983 SSVAL(params,6,0); /* Never an EA error */
2984 SSVAL(params,8,last_entry_off);
2986 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2987 max_data_bytes);
2989 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2990 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2991 if (!directory) {
2992 reply_nterror(req, NT_STATUS_NO_MEMORY);
2996 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2997 smb_fn_name(req->cmd),
2998 mask, directory, dirtype, numentries ) );
3001 * Force a name mangle here to ensure that the
3002 * mask as an 8.3 name is top of the mangled cache.
3003 * The reasons for this are subtle. Don't remove
3004 * this code unless you know what you are doing
3005 * (see PR#13758). JRA.
3008 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3009 char mangled_name[13];
3010 name_to_8_3(mask, mangled_name, True, conn->params);
3012 out:
3014 if (as_root) {
3015 unbecome_root();
3018 TALLOC_FREE(smb_dname);
3019 return;
3022 /****************************************************************************
3023 Reply to a TRANS2_FINDNEXT.
3024 ****************************************************************************/
3026 static void call_trans2findnext(connection_struct *conn,
3027 struct smb_request *req,
3028 char **pparams, int total_params,
3029 char **ppdata, int total_data,
3030 unsigned int max_data_bytes)
3032 /* We must be careful here that we don't return more than the
3033 allowed number of data bytes. If this means returning fewer than
3034 maxentries then so be it. We assume that the redirector has
3035 enough room for the fixed number of parameter bytes it has
3036 requested. */
3037 char *params = *pparams;
3038 char *pdata = *ppdata;
3039 char *data_end;
3040 int dptr_num;
3041 int maxentries;
3042 uint16_t info_level;
3043 uint32_t resume_key;
3044 uint16_t findnext_flags;
3045 bool close_after_request;
3046 bool close_if_end;
3047 bool requires_resume_key;
3048 bool continue_bit;
3049 bool mask_contains_wcard = False;
3050 char *resume_name = NULL;
3051 const char *mask = NULL;
3052 const char *directory = NULL;
3053 char *p = NULL;
3054 uint16_t dirtype;
3055 int numentries = 0;
3056 int i, last_entry_off=0;
3057 bool finished = False;
3058 bool dont_descend = False;
3059 bool out_of_space = False;
3060 int space_remaining;
3061 struct ea_list *ea_list = NULL;
3062 NTSTATUS ntstatus = NT_STATUS_OK;
3063 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3064 TALLOC_CTX *ctx = talloc_tos();
3065 struct dptr_struct *dirptr;
3066 struct smbd_server_connection *sconn = req->sconn;
3067 bool backup_priv = false;
3068 bool as_root = false;
3070 if (total_params < 13) {
3071 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3072 return;
3075 dptr_num = SVAL(params,0);
3076 maxentries = SVAL(params,2);
3077 info_level = SVAL(params,4);
3078 resume_key = IVAL(params,6);
3079 findnext_flags = SVAL(params,10);
3080 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3081 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3082 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3083 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3085 if (!continue_bit) {
3086 /* We only need resume_name if continue_bit is zero. */
3087 if (req->posix_pathnames) {
3088 srvstr_get_path_wcard_posix(ctx,
3089 params,
3090 req->flags2,
3091 &resume_name,
3092 params+12,
3093 total_params - 12,
3094 STR_TERMINATE,
3095 &ntstatus,
3096 &mask_contains_wcard);
3097 } else {
3098 srvstr_get_path_wcard(ctx,
3099 params,
3100 req->flags2,
3101 &resume_name,
3102 params+12,
3103 total_params - 12,
3104 STR_TERMINATE,
3105 &ntstatus,
3106 &mask_contains_wcard);
3108 if (!NT_STATUS_IS_OK(ntstatus)) {
3109 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3110 complain (it thinks we're asking for the directory above the shared
3111 path or an invalid name). Catch this as the resume name is only compared, never used in
3112 a file access. JRA. */
3113 srvstr_pull_talloc(ctx, params, req->flags2,
3114 &resume_name, params+12,
3115 total_params - 12,
3116 STR_TERMINATE);
3118 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3119 reply_nterror(req, ntstatus);
3120 return;
3125 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3126 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3127 resume_key = %d resume name = %s continue=%d level = %d\n",
3128 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3129 requires_resume_key, resume_key,
3130 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3132 if (!maxentries) {
3133 /* W2K3 seems to treat zero as 1. */
3134 maxentries = 1;
3137 switch (info_level) {
3138 case SMB_FIND_INFO_STANDARD:
3139 case SMB_FIND_EA_SIZE:
3140 case SMB_FIND_EA_LIST:
3141 case SMB_FIND_FILE_DIRECTORY_INFO:
3142 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3143 case SMB_FIND_FILE_NAMES_INFO:
3144 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3145 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3146 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3147 break;
3148 case SMB_FIND_FILE_UNIX:
3149 case SMB_FIND_FILE_UNIX_INFO2:
3150 /* Always use filesystem for UNIX mtime query. */
3151 ask_sharemode = false;
3152 if (!lp_unix_extensions()) {
3153 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3154 return;
3156 break;
3157 default:
3158 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3159 return;
3162 if (info_level == SMB_FIND_EA_LIST) {
3163 uint32_t ea_size;
3165 if (total_data < 4) {
3166 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3167 return;
3170 ea_size = IVAL(pdata,0);
3171 if (ea_size != total_data) {
3172 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3173 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3174 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3175 return;
3178 if (!lp_ea_support(SNUM(conn))) {
3179 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3180 return;
3183 /* Pull out the list of names. */
3184 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3185 if (!ea_list) {
3186 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3187 return;
3191 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3192 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3193 return;
3196 *ppdata = (char *)SMB_REALLOC(
3197 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3198 if(*ppdata == NULL) {
3199 reply_nterror(req, NT_STATUS_NO_MEMORY);
3200 return;
3203 pdata = *ppdata;
3204 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3207 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3208 * error.
3210 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3211 /* Realloc the params space */
3212 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3213 if(*pparams == NULL ) {
3214 reply_nterror(req, NT_STATUS_NO_MEMORY);
3215 return;
3218 params = *pparams;
3220 /* Check that the dptr is valid */
3221 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3222 reply_nterror(req, STATUS_NO_MORE_FILES);
3223 return;
3226 directory = dptr_path(sconn, dptr_num);
3228 /* Get the wildcard mask from the dptr */
3229 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3230 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3231 reply_nterror(req, STATUS_NO_MORE_FILES);
3232 return;
3235 /* Get the attr mask from the dptr */
3236 dirtype = dptr_attr(sconn, dptr_num);
3238 backup_priv = dptr_get_priv(dirptr);
3240 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3241 "backup_priv = %d\n",
3242 dptr_num, mask, dirtype,
3243 (long)dirptr,
3244 dptr_TellDir(dirptr),
3245 (int)backup_priv));
3247 /* We don't need to check for VOL here as this is returned by
3248 a different TRANS2 call. */
3250 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3251 directory,lp_dont_descend(ctx, SNUM(conn))));
3252 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3253 dont_descend = True;
3255 p = pdata;
3256 space_remaining = max_data_bytes;
3257 out_of_space = False;
3259 if (backup_priv) {
3260 become_root();
3261 as_root = true;
3265 * Seek to the correct position. We no longer use the resume key but
3266 * depend on the last file name instead.
3269 if(!continue_bit && resume_name && *resume_name) {
3270 SMB_STRUCT_STAT st;
3272 long current_pos = 0;
3274 * Remember, name_to_8_3 is called by
3275 * get_lanman2_dir_entry(), so the resume name
3276 * could be mangled. Ensure we check the unmangled name.
3279 if (mangle_is_mangled(resume_name, conn->params)) {
3280 char *new_resume_name = NULL;
3281 mangle_lookup_name_from_8_3(ctx,
3282 resume_name,
3283 &new_resume_name,
3284 conn->params);
3285 if (new_resume_name) {
3286 resume_name = new_resume_name;
3291 * Fix for NT redirector problem triggered by resume key indexes
3292 * changing between directory scans. We now return a resume key of 0
3293 * and instead look for the filename to continue from (also given
3294 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3295 * findfirst/findnext (as is usual) then the directory pointer
3296 * should already be at the correct place.
3299 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3300 } /* end if resume_name && !continue_bit */
3302 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3303 bool got_exact_match = False;
3305 /* this is a heuristic to avoid seeking the dirptr except when
3306 absolutely necessary. It allows for a filename of about 40 chars */
3307 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3308 out_of_space = True;
3309 finished = False;
3310 } else {
3311 ntstatus = get_lanman2_dir_entry(ctx,
3312 conn,
3313 dirptr,
3314 req->flags2,
3315 mask,dirtype,info_level,
3316 requires_resume_key,dont_descend,
3317 ask_sharemode,
3318 &p,pdata,data_end,
3319 space_remaining,
3320 &got_exact_match,
3321 &last_entry_off, ea_list);
3322 if (NT_STATUS_EQUAL(ntstatus,
3323 NT_STATUS_ILLEGAL_CHARACTER)) {
3325 * Bad character conversion on name. Ignore this
3326 * entry.
3328 continue;
3330 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3331 out_of_space = true;
3332 } else {
3333 finished = !NT_STATUS_IS_OK(ntstatus);
3337 if (!finished && !out_of_space)
3338 numentries++;
3341 * As an optimisation if we know we aren't looking
3342 * for a wildcard name (ie. the name matches the wildcard exactly)
3343 * then we can finish on any (first) match.
3344 * This speeds up large directory searches. JRA.
3347 if(got_exact_match)
3348 finished = True;
3350 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3353 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3354 smb_fn_name(req->cmd),
3355 mask, directory, dirtype, numentries ) );
3357 /* Check if we can close the dirptr */
3358 if(close_after_request || (finished && close_if_end)) {
3359 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3360 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3363 if (as_root) {
3364 unbecome_root();
3367 /* Set up the return parameter block */
3368 SSVAL(params,0,numentries);
3369 SSVAL(params,2,finished);
3370 SSVAL(params,4,0); /* Never an EA error */
3371 SSVAL(params,6,last_entry_off);
3373 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3374 max_data_bytes);
3376 return;
3379 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3381 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3382 return objid;
3385 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3387 SMB_ASSERT(extended_info != NULL);
3389 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3390 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3391 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3392 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3393 #ifdef SAMBA_VERSION_REVISION
3394 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3395 #endif
3396 extended_info->samba_subversion = 0;
3397 #ifdef SAMBA_VERSION_RC_RELEASE
3398 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3399 #else
3400 #ifdef SAMBA_VERSION_PRE_RELEASE
3401 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3402 #endif
3403 #endif
3404 #ifdef SAMBA_VERSION_VENDOR_PATCH
3405 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3406 #endif
3407 extended_info->samba_gitcommitdate = 0;
3408 #ifdef SAMBA_VERSION_COMMIT_TIME
3409 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3410 #endif
3412 memset(extended_info->samba_version_string, 0,
3413 sizeof(extended_info->samba_version_string));
3415 snprintf (extended_info->samba_version_string,
3416 sizeof(extended_info->samba_version_string),
3417 "%s", samba_version_string());
3420 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3421 connection_struct *conn,
3422 TALLOC_CTX *mem_ctx,
3423 uint16_t info_level,
3424 uint16_t flags2,
3425 unsigned int max_data_bytes,
3426 size_t *fixed_portion,
3427 struct smb_filename *fname,
3428 char **ppdata,
3429 int *ret_data_len)
3431 char *pdata, *end_data;
3432 int data_len = 0;
3433 size_t len = 0;
3434 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3435 int snum = SNUM(conn);
3436 const char *fstype = lp_fstype(SNUM(conn));
3437 const char *filename = NULL;
3438 const uint64_t bytes_per_sector = 512;
3439 uint32_t additional_flags = 0;
3440 struct smb_filename smb_fname;
3441 SMB_STRUCT_STAT st;
3442 NTSTATUS status = NT_STATUS_OK;
3443 uint64_t df_ret;
3445 if (fname == NULL || fname->base_name == NULL) {
3446 filename = ".";
3447 } else {
3448 filename = fname->base_name;
3451 if (IS_IPC(conn)) {
3452 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3453 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3454 "info level (0x%x) on IPC$.\n",
3455 (unsigned int)info_level));
3456 return NT_STATUS_ACCESS_DENIED;
3460 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3462 ZERO_STRUCT(smb_fname);
3463 smb_fname.base_name = discard_const_p(char, filename);
3465 if(info_level != SMB_FS_QUOTA_INFORMATION
3466 && SMB_VFS_STAT(conn, &smb_fname) != 0) {
3467 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3468 return map_nt_error_from_unix(errno);
3471 st = smb_fname.st;
3473 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3474 return NT_STATUS_INVALID_PARAMETER;
3477 *ppdata = (char *)SMB_REALLOC(
3478 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3479 if (*ppdata == NULL) {
3480 return NT_STATUS_NO_MEMORY;
3483 pdata = *ppdata;
3484 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3485 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3487 *fixed_portion = 0;
3489 switch (info_level) {
3490 case SMB_INFO_ALLOCATION:
3492 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3493 data_len = 18;
3494 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3495 &dfree, &dsize);
3496 if (df_ret == (uint64_t)-1) {
3497 return map_nt_error_from_unix(errno);
3500 block_size = lp_block_size(snum);
3501 if (bsize < block_size) {
3502 uint64_t factor = block_size/bsize;
3503 bsize = block_size;
3504 dsize /= factor;
3505 dfree /= factor;
3507 if (bsize > block_size) {
3508 uint64_t factor = bsize/block_size;
3509 bsize = block_size;
3510 dsize *= factor;
3511 dfree *= factor;
3513 sectors_per_unit = bsize/bytes_per_sector;
3515 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3516 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3517 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3520 * For large drives, return max values and not modulo.
3522 dsize = MIN(dsize, UINT32_MAX);
3523 dfree = MIN(dfree, UINT32_MAX);
3525 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3526 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3527 SIVAL(pdata,l1_cUnit,dsize);
3528 SIVAL(pdata,l1_cUnitAvail,dfree);
3529 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3530 break;
3533 case SMB_INFO_VOLUME:
3534 /* Return volume name */
3536 * Add volume serial number - hash of a combination of
3537 * the called hostname and the service name.
3539 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3541 * Win2k3 and previous mess this up by sending a name length
3542 * one byte short. I believe only older clients (OS/2 Win9x) use
3543 * this call so try fixing this by adding a terminating null to
3544 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3546 status = srvstr_push(
3547 pdata, flags2,
3548 pdata+l2_vol_szVolLabel, vname,
3549 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3550 STR_NOALIGN|STR_TERMINATE, &len);
3551 if (!NT_STATUS_IS_OK(status)) {
3552 return status;
3554 SCVAL(pdata,l2_vol_cch,len);
3555 data_len = l2_vol_szVolLabel + len;
3556 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3557 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3558 (unsigned)len, vname));
3559 break;
3561 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3562 case SMB_FS_ATTRIBUTE_INFORMATION:
3564 additional_flags = 0;
3565 #if defined(HAVE_SYS_QUOTAS)
3566 additional_flags |= FILE_VOLUME_QUOTAS;
3567 #endif
3569 if(lp_nt_acl_support(SNUM(conn))) {
3570 additional_flags |= FILE_PERSISTENT_ACLS;
3573 /* Capabilities are filled in at connection time through STATVFS call */
3574 additional_flags |= conn->fs_capabilities;
3575 additional_flags |= lp_parm_int(conn->params->service,
3576 "share", "fake_fscaps",
3579 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3580 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3581 additional_flags); /* FS ATTRIBUTES */
3583 SIVAL(pdata,4,255); /* Max filename component length */
3584 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3585 and will think we can't do long filenames */
3586 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3587 PTR_DIFF(end_data, pdata+12),
3588 STR_UNICODE, &len);
3589 if (!NT_STATUS_IS_OK(status)) {
3590 return status;
3592 SIVAL(pdata,8,len);
3593 data_len = 12 + len;
3594 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3595 /* the client only requested a portion of the
3596 file system name */
3597 data_len = max_data_bytes;
3598 status = STATUS_BUFFER_OVERFLOW;
3600 *fixed_portion = 16;
3601 break;
3603 case SMB_QUERY_FS_LABEL_INFO:
3604 case SMB_FS_LABEL_INFORMATION:
3605 status = srvstr_push(pdata, flags2, pdata+4, vname,
3606 PTR_DIFF(end_data, pdata+4), 0, &len);
3607 if (!NT_STATUS_IS_OK(status)) {
3608 return status;
3610 data_len = 4 + len;
3611 SIVAL(pdata,0,len);
3612 break;
3614 case SMB_QUERY_FS_VOLUME_INFO:
3615 case SMB_FS_VOLUME_INFORMATION:
3618 * Add volume serial number - hash of a combination of
3619 * the called hostname and the service name.
3621 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3622 (str_checksum(get_local_machine_name())<<16));
3624 /* Max label len is 32 characters. */
3625 status = srvstr_push(pdata, flags2, pdata+18, vname,
3626 PTR_DIFF(end_data, pdata+18),
3627 STR_UNICODE, &len);
3628 if (!NT_STATUS_IS_OK(status)) {
3629 return status;
3631 SIVAL(pdata,12,len);
3632 data_len = 18+len;
3634 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3635 (int)strlen(vname),vname,
3636 lp_servicename(talloc_tos(), snum)));
3637 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3638 /* the client only requested a portion of the
3639 volume label */
3640 data_len = max_data_bytes;
3641 status = STATUS_BUFFER_OVERFLOW;
3643 *fixed_portion = 24;
3644 break;
3646 case SMB_QUERY_FS_SIZE_INFO:
3647 case SMB_FS_SIZE_INFORMATION:
3649 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3650 data_len = 24;
3651 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3652 &dfree, &dsize);
3653 if (df_ret == (uint64_t)-1) {
3654 return map_nt_error_from_unix(errno);
3656 block_size = lp_block_size(snum);
3657 if (bsize < block_size) {
3658 uint64_t factor = block_size/bsize;
3659 bsize = block_size;
3660 dsize /= factor;
3661 dfree /= factor;
3663 if (bsize > block_size) {
3664 uint64_t factor = bsize/block_size;
3665 bsize = block_size;
3666 dsize *= factor;
3667 dfree *= factor;
3669 sectors_per_unit = bsize/bytes_per_sector;
3670 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3671 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3672 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3673 SBIG_UINT(pdata,0,dsize);
3674 SBIG_UINT(pdata,8,dfree);
3675 SIVAL(pdata,16,sectors_per_unit);
3676 SIVAL(pdata,20,bytes_per_sector);
3677 *fixed_portion = 24;
3678 break;
3681 case SMB_FS_FULL_SIZE_INFORMATION:
3683 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3684 data_len = 32;
3685 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3686 &dfree, &dsize);
3687 if (df_ret == (uint64_t)-1) {
3688 return map_nt_error_from_unix(errno);
3690 block_size = lp_block_size(snum);
3691 if (bsize < block_size) {
3692 uint64_t factor = block_size/bsize;
3693 bsize = block_size;
3694 dsize /= factor;
3695 dfree /= factor;
3697 if (bsize > block_size) {
3698 uint64_t factor = bsize/block_size;
3699 bsize = block_size;
3700 dsize *= factor;
3701 dfree *= factor;
3703 sectors_per_unit = bsize/bytes_per_sector;
3704 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3705 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3706 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3707 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3708 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3709 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3710 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3711 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3712 *fixed_portion = 32;
3713 break;
3716 case SMB_QUERY_FS_DEVICE_INFO:
3717 case SMB_FS_DEVICE_INFORMATION:
3719 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3721 if (!CAN_WRITE(conn)) {
3722 characteristics |= FILE_READ_ONLY_DEVICE;
3724 data_len = 8;
3725 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3726 SIVAL(pdata,4,characteristics);
3727 *fixed_portion = 8;
3728 break;
3731 #ifdef HAVE_SYS_QUOTAS
3732 case SMB_FS_QUOTA_INFORMATION:
3734 * what we have to send --metze:
3736 * Unknown1: 24 NULL bytes
3737 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3738 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3739 * Quota Flags: 2 byte :
3740 * Unknown3: 6 NULL bytes
3742 * 48 bytes total
3744 * details for Quota Flags:
3746 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3747 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3748 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3749 * 0x0001 Enable Quotas: enable quota for this fs
3753 /* we need to fake up a fsp here,
3754 * because its not send in this call
3756 files_struct fsp;
3757 SMB_NTQUOTA_STRUCT quotas;
3759 ZERO_STRUCT(fsp);
3760 ZERO_STRUCT(quotas);
3762 fsp.conn = conn;
3763 fsp.fnum = FNUM_FIELD_INVALID;
3765 /* access check */
3766 if (get_current_uid(conn) != 0) {
3767 DEBUG(0,("get_user_quota: access_denied "
3768 "service [%s] user [%s]\n",
3769 lp_servicename(talloc_tos(), SNUM(conn)),
3770 conn->session_info->unix_info->unix_name));
3771 return NT_STATUS_ACCESS_DENIED;
3774 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3775 NULL, &quotas);
3776 if (!NT_STATUS_IS_OK(status)) {
3777 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3778 return status;
3781 data_len = 48;
3783 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3784 lp_servicename(talloc_tos(), SNUM(conn))));
3786 /* Unknown1 24 NULL bytes*/
3787 SBIG_UINT(pdata,0,(uint64_t)0);
3788 SBIG_UINT(pdata,8,(uint64_t)0);
3789 SBIG_UINT(pdata,16,(uint64_t)0);
3791 /* Default Soft Quota 8 bytes */
3792 SBIG_UINT(pdata,24,quotas.softlim);
3794 /* Default Hard Quota 8 bytes */
3795 SBIG_UINT(pdata,32,quotas.hardlim);
3797 /* Quota flag 2 bytes */
3798 SSVAL(pdata,40,quotas.qflags);
3800 /* Unknown3 6 NULL bytes */
3801 SSVAL(pdata,42,0);
3802 SIVAL(pdata,44,0);
3804 break;
3806 #endif /* HAVE_SYS_QUOTAS */
3807 case SMB_FS_OBJECTID_INFORMATION:
3809 unsigned char objid[16];
3810 struct smb_extended_info extended_info;
3811 memcpy(pdata,create_volume_objectid(conn, objid),16);
3812 samba_extended_info_version (&extended_info);
3813 SIVAL(pdata,16,extended_info.samba_magic);
3814 SIVAL(pdata,20,extended_info.samba_version);
3815 SIVAL(pdata,24,extended_info.samba_subversion);
3816 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3817 memcpy(pdata+36,extended_info.samba_version_string,28);
3818 data_len = 64;
3819 break;
3822 case SMB_FS_SECTOR_SIZE_INFORMATION:
3824 data_len = 28;
3826 * These values match a physical Windows Server 2012
3827 * share backed by NTFS atop spinning rust.
3829 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3830 /* logical_bytes_per_sector */
3831 SIVAL(pdata, 0, bytes_per_sector);
3832 /* phys_bytes_per_sector_atomic */
3833 SIVAL(pdata, 4, bytes_per_sector);
3834 /* phys_bytes_per_sector_perf */
3835 SIVAL(pdata, 8, bytes_per_sector);
3836 /* fs_effective_phys_bytes_per_sector_atomic */
3837 SIVAL(pdata, 12, bytes_per_sector);
3838 /* flags */
3839 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3840 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3841 /* byte_off_sector_align */
3842 SIVAL(pdata, 20, 0);
3843 /* byte_off_partition_align */
3844 SIVAL(pdata, 24, 0);
3845 *fixed_portion = 28;
3846 break;
3851 * Query the version and capabilities of the CIFS UNIX extensions
3852 * in use.
3855 case SMB_QUERY_CIFS_UNIX_INFO:
3857 bool large_write = lp_min_receive_file_size() &&
3858 !srv_is_signing_active(xconn);
3859 bool large_read = !srv_is_signing_active(xconn);
3860 int encrypt_caps = 0;
3862 if (!lp_unix_extensions()) {
3863 return NT_STATUS_INVALID_LEVEL;
3866 switch (conn->encrypt_level) {
3867 case SMB_SIGNING_OFF:
3868 encrypt_caps = 0;
3869 break;
3870 case SMB_SIGNING_DESIRED:
3871 case SMB_SIGNING_IF_REQUIRED:
3872 case SMB_SIGNING_DEFAULT:
3873 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3874 break;
3875 case SMB_SIGNING_REQUIRED:
3876 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3877 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3878 large_write = false;
3879 large_read = false;
3880 break;
3883 data_len = 12;
3884 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3885 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3887 /* We have POSIX ACLs, pathname, encryption,
3888 * large read/write, and locking capability. */
3890 SBIG_UINT(pdata,4,((uint64_t)(
3891 CIFS_UNIX_POSIX_ACLS_CAP|
3892 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3893 CIFS_UNIX_FCNTL_LOCKS_CAP|
3894 CIFS_UNIX_EXTATTR_CAP|
3895 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3896 encrypt_caps|
3897 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3898 (large_write ?
3899 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3900 break;
3903 case SMB_QUERY_POSIX_FS_INFO:
3905 int rc;
3906 vfs_statvfs_struct svfs;
3908 if (!lp_unix_extensions()) {
3909 return NT_STATUS_INVALID_LEVEL;
3912 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3914 if (!rc) {
3915 data_len = 56;
3916 SIVAL(pdata,0,svfs.OptimalTransferSize);
3917 SIVAL(pdata,4,svfs.BlockSize);
3918 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3919 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3920 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3921 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3922 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3923 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3924 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3925 #ifdef EOPNOTSUPP
3926 } else if (rc == EOPNOTSUPP) {
3927 return NT_STATUS_INVALID_LEVEL;
3928 #endif /* EOPNOTSUPP */
3929 } else {
3930 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3931 return NT_STATUS_DOS(ERRSRV, ERRerror);
3933 break;
3936 case SMB_QUERY_POSIX_WHOAMI:
3938 uint32_t flags = 0;
3939 uint32_t sid_bytes;
3940 int i;
3942 if (!lp_unix_extensions()) {
3943 return NT_STATUS_INVALID_LEVEL;
3946 if (max_data_bytes < 40) {
3947 return NT_STATUS_BUFFER_TOO_SMALL;
3950 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3951 flags |= SMB_WHOAMI_GUEST;
3954 /* NOTE: 8 bytes for UID/GID, irrespective of native
3955 * platform size. This matches
3956 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3958 data_len = 4 /* flags */
3959 + 4 /* flag mask */
3960 + 8 /* uid */
3961 + 8 /* gid */
3962 + 4 /* ngroups */
3963 + 4 /* num_sids */
3964 + 4 /* SID bytes */
3965 + 4 /* pad/reserved */
3966 + (conn->session_info->unix_token->ngroups * 8)
3967 /* groups list */
3968 + (conn->session_info->security_token->num_sids *
3969 SID_MAX_SIZE)
3970 /* SID list */;
3972 SIVAL(pdata, 0, flags);
3973 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3974 SBIG_UINT(pdata, 8,
3975 (uint64_t)conn->session_info->unix_token->uid);
3976 SBIG_UINT(pdata, 16,
3977 (uint64_t)conn->session_info->unix_token->gid);
3980 if (data_len >= max_data_bytes) {
3981 /* Potential overflow, skip the GIDs and SIDs. */
3983 SIVAL(pdata, 24, 0); /* num_groups */
3984 SIVAL(pdata, 28, 0); /* num_sids */
3985 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3986 SIVAL(pdata, 36, 0); /* reserved */
3988 data_len = 40;
3989 break;
3992 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3993 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3995 /* We walk the SID list twice, but this call is fairly
3996 * infrequent, and I don't expect that it's performance
3997 * sensitive -- jpeach
3999 for (i = 0, sid_bytes = 0;
4000 i < conn->session_info->security_token->num_sids; ++i) {
4001 sid_bytes += ndr_size_dom_sid(
4002 &conn->session_info->security_token->sids[i],
4006 /* SID list byte count */
4007 SIVAL(pdata, 32, sid_bytes);
4009 /* 4 bytes pad/reserved - must be zero */
4010 SIVAL(pdata, 36, 0);
4011 data_len = 40;
4013 /* GID list */
4014 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4015 SBIG_UINT(pdata, data_len,
4016 (uint64_t)conn->session_info->unix_token->groups[i]);
4017 data_len += 8;
4020 /* SID list */
4021 for (i = 0;
4022 i < conn->session_info->security_token->num_sids; ++i) {
4023 int sid_len = ndr_size_dom_sid(
4024 &conn->session_info->security_token->sids[i],
4027 sid_linearize((uint8_t *)(pdata + data_len),
4028 sid_len,
4029 &conn->session_info->security_token->sids[i]);
4030 data_len += sid_len;
4033 break;
4036 case SMB_MAC_QUERY_FS_INFO:
4038 * Thursby MAC extension... ONLY on NTFS filesystems
4039 * once we do streams then we don't need this
4041 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4042 data_len = 88;
4043 SIVAL(pdata,84,0x100); /* Don't support mac... */
4044 break;
4047 FALL_THROUGH;
4048 default:
4049 return NT_STATUS_INVALID_LEVEL;
4052 *ret_data_len = data_len;
4053 return status;
4056 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4057 struct smb_request *req,
4058 files_struct *fsp,
4059 const DATA_BLOB *qdata)
4061 NTSTATUS status;
4062 SMB_NTQUOTA_STRUCT quotas;
4064 ZERO_STRUCT(quotas);
4066 /* access check */
4067 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4068 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4069 lp_servicename(talloc_tos(), SNUM(conn)),
4070 conn->session_info->unix_info->unix_name));
4071 return NT_STATUS_ACCESS_DENIED;
4074 if (!check_fsp_ntquota_handle(conn, req,
4075 fsp)) {
4076 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4077 return NT_STATUS_INVALID_HANDLE;
4080 /* note: normally there're 48 bytes,
4081 * but we didn't use the last 6 bytes for now
4082 * --metze
4084 if (qdata->length < 42) {
4085 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4086 (unsigned int)qdata->length));
4087 return NT_STATUS_INVALID_PARAMETER;
4090 /* unknown_1 24 NULL bytes in pdata*/
4092 /* the soft quotas 8 bytes (uint64_t)*/
4093 quotas.softlim = BVAL(qdata->data,24);
4095 /* the hard quotas 8 bytes (uint64_t)*/
4096 quotas.hardlim = BVAL(qdata->data,32);
4098 /* quota_flags 2 bytes **/
4099 quotas.qflags = SVAL(qdata->data,40);
4101 /* unknown_2 6 NULL bytes follow*/
4103 /* now set the quotas */
4104 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4105 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4106 lp_servicename(talloc_tos(), SNUM(conn))));
4107 status = map_nt_error_from_unix(errno);
4108 } else {
4109 status = NT_STATUS_OK;
4111 return status;
4114 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4115 struct smb_request *req,
4116 TALLOC_CTX *mem_ctx,
4117 uint16_t info_level,
4118 files_struct *fsp,
4119 const DATA_BLOB *pdata)
4121 switch (info_level) {
4122 case SMB_FS_QUOTA_INFORMATION:
4124 return smb_set_fsquota(conn,
4125 req,
4126 fsp,
4127 pdata);
4130 default:
4131 break;
4133 return NT_STATUS_INVALID_LEVEL;
4136 /****************************************************************************
4137 Reply to a TRANS2_QFSINFO (query filesystem info).
4138 ****************************************************************************/
4140 static void call_trans2qfsinfo(connection_struct *conn,
4141 struct smb_request *req,
4142 char **pparams, int total_params,
4143 char **ppdata, int total_data,
4144 unsigned int max_data_bytes)
4146 char *params = *pparams;
4147 uint16_t info_level;
4148 int data_len = 0;
4149 size_t fixed_portion;
4150 NTSTATUS status;
4152 if (total_params < 2) {
4153 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4154 return;
4157 info_level = SVAL(params,0);
4159 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4160 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4161 DEBUG(0,("call_trans2qfsinfo: encryption required "
4162 "and info level 0x%x sent.\n",
4163 (unsigned int)info_level));
4164 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4165 return;
4169 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4171 status = smbd_do_qfsinfo(req->xconn, conn, req,
4172 info_level,
4173 req->flags2,
4174 max_data_bytes,
4175 &fixed_portion,
4176 NULL,
4177 ppdata, &data_len);
4178 if (!NT_STATUS_IS_OK(status)) {
4179 reply_nterror(req, status);
4180 return;
4183 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4184 max_data_bytes);
4186 DEBUG( 4, ( "%s info_level = %d\n",
4187 smb_fn_name(req->cmd), info_level) );
4189 return;
4192 /****************************************************************************
4193 Reply to a TRANS2_SETFSINFO (set filesystem info).
4194 ****************************************************************************/
4196 static void call_trans2setfsinfo(connection_struct *conn,
4197 struct smb_request *req,
4198 char **pparams, int total_params,
4199 char **ppdata, int total_data,
4200 unsigned int max_data_bytes)
4202 struct smbXsrv_connection *xconn = req->xconn;
4203 char *pdata = *ppdata;
4204 char *params = *pparams;
4205 uint16_t info_level;
4207 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4208 lp_servicename(talloc_tos(), SNUM(conn))));
4210 /* */
4211 if (total_params < 4) {
4212 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4213 total_params));
4214 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4215 return;
4218 info_level = SVAL(params,2);
4220 if (IS_IPC(conn)) {
4221 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4222 info_level != SMB_SET_CIFS_UNIX_INFO) {
4223 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4224 "info level (0x%x) on IPC$.\n",
4225 (unsigned int)info_level));
4226 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4227 return;
4231 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4232 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4233 DEBUG(0,("call_trans2setfsinfo: encryption required "
4234 "and info level 0x%x sent.\n",
4235 (unsigned int)info_level));
4236 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4237 return;
4241 switch(info_level) {
4242 case SMB_SET_CIFS_UNIX_INFO:
4243 if (!lp_unix_extensions()) {
4244 DEBUG(2,("call_trans2setfsinfo: "
4245 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4246 "unix extensions off\n"));
4247 reply_nterror(req,
4248 NT_STATUS_INVALID_LEVEL);
4249 return;
4252 /* There should be 12 bytes of capabilities set. */
4253 if (total_data < 12) {
4254 reply_nterror(
4255 req,
4256 NT_STATUS_INVALID_PARAMETER);
4257 return;
4259 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4260 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4261 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4262 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4263 /* Just print these values for now. */
4264 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4265 "major = %u, minor = %u cap_low = 0x%x, "
4266 "cap_high = 0x%xn",
4267 (unsigned int)xconn->
4268 smb1.unix_info.client_major,
4269 (unsigned int)xconn->
4270 smb1.unix_info.client_minor,
4271 (unsigned int)xconn->
4272 smb1.unix_info.client_cap_low,
4273 (unsigned int)xconn->
4274 smb1.unix_info.client_cap_high));
4276 /* Here is where we must switch to posix pathname processing... */
4277 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4278 lp_set_posix_pathnames();
4279 mangle_change_to_posix();
4282 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4283 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4284 /* Client that knows how to do posix locks,
4285 * but not posix open/mkdir operations. Set a
4286 * default type for read/write checks. */
4288 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4291 break;
4293 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4295 NTSTATUS status;
4296 size_t param_len = 0;
4297 size_t data_len = total_data;
4299 if (!lp_unix_extensions()) {
4300 reply_nterror(
4301 req,
4302 NT_STATUS_INVALID_LEVEL);
4303 return;
4306 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4307 reply_nterror(
4308 req,
4309 NT_STATUS_NOT_SUPPORTED);
4310 return;
4313 if (xconn->smb1.echo_handler.trusted_fde) {
4314 DEBUG( 2,("call_trans2setfsinfo: "
4315 "request transport encryption disabled"
4316 "with 'fork echo handler = yes'\n"));
4317 reply_nterror(
4318 req,
4319 NT_STATUS_NOT_SUPPORTED);
4320 return;
4323 DEBUG( 4,("call_trans2setfsinfo: "
4324 "request transport encryption.\n"));
4326 status = srv_request_encryption_setup(conn,
4327 (unsigned char **)ppdata,
4328 &data_len,
4329 (unsigned char **)pparams,
4330 &param_len);
4332 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4333 !NT_STATUS_IS_OK(status)) {
4334 reply_nterror(req, status);
4335 return;
4338 send_trans2_replies(conn, req,
4339 NT_STATUS_OK,
4340 *pparams,
4341 param_len,
4342 *ppdata,
4343 data_len,
4344 max_data_bytes);
4346 if (NT_STATUS_IS_OK(status)) {
4347 /* Server-side transport
4348 * encryption is now *on*. */
4349 status = srv_encryption_start(conn);
4350 if (!NT_STATUS_IS_OK(status)) {
4351 char *reason = talloc_asprintf(talloc_tos(),
4352 "Failure in setting "
4353 "up encrypted transport: %s",
4354 nt_errstr(status));
4355 exit_server_cleanly(reason);
4358 return;
4361 case SMB_FS_QUOTA_INFORMATION:
4363 NTSTATUS status;
4364 DATA_BLOB qdata = {
4365 .data = (uint8_t *)pdata,
4366 .length = total_data
4368 files_struct *fsp = NULL;
4369 fsp = file_fsp(req, SVAL(params,0));
4371 status = smb_set_fsquota(conn,
4372 req,
4373 fsp,
4374 &qdata);
4375 if (!NT_STATUS_IS_OK(status)) {
4376 reply_nterror(req, status);
4377 return;
4379 break;
4381 default:
4382 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4383 info_level));
4384 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4385 return;
4386 break;
4390 * sending this reply works fine,
4391 * but I'm not sure it's the same
4392 * like windows do...
4393 * --metze
4395 reply_outbuf(req, 10, 0);
4398 #if defined(HAVE_POSIX_ACLS)
4399 /****************************************************************************
4400 Utility function to count the number of entries in a POSIX acl.
4401 ****************************************************************************/
4403 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4405 unsigned int ace_count = 0;
4406 int entry_id = SMB_ACL_FIRST_ENTRY;
4407 SMB_ACL_ENTRY_T entry;
4409 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4410 /* get_next... */
4411 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4412 entry_id = SMB_ACL_NEXT_ENTRY;
4414 ace_count++;
4416 return ace_count;
4419 /****************************************************************************
4420 Utility function to marshall a POSIX acl into wire format.
4421 ****************************************************************************/
4423 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4425 int entry_id = SMB_ACL_FIRST_ENTRY;
4426 SMB_ACL_ENTRY_T entry;
4428 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4429 SMB_ACL_TAG_T tagtype;
4430 SMB_ACL_PERMSET_T permset;
4431 unsigned char perms = 0;
4432 unsigned int own_grp;
4434 /* get_next... */
4435 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4436 entry_id = SMB_ACL_NEXT_ENTRY;
4439 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4440 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4441 return False;
4444 if (sys_acl_get_permset(entry, &permset) == -1) {
4445 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4446 return False;
4449 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4450 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4451 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4453 SCVAL(pdata,1,perms);
4455 switch (tagtype) {
4456 case SMB_ACL_USER_OBJ:
4457 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4458 own_grp = (unsigned int)pst->st_ex_uid;
4459 SIVAL(pdata,2,own_grp);
4460 SIVAL(pdata,6,0);
4461 break;
4462 case SMB_ACL_USER:
4464 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4465 if (!puid) {
4466 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4467 return False;
4469 own_grp = (unsigned int)*puid;
4470 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4471 SIVAL(pdata,2,own_grp);
4472 SIVAL(pdata,6,0);
4473 break;
4475 case SMB_ACL_GROUP_OBJ:
4476 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4477 own_grp = (unsigned int)pst->st_ex_gid;
4478 SIVAL(pdata,2,own_grp);
4479 SIVAL(pdata,6,0);
4480 break;
4481 case SMB_ACL_GROUP:
4483 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4484 if (!pgid) {
4485 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4486 return False;
4488 own_grp = (unsigned int)*pgid;
4489 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4490 SIVAL(pdata,2,own_grp);
4491 SIVAL(pdata,6,0);
4492 break;
4494 case SMB_ACL_MASK:
4495 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4496 SIVAL(pdata,2,0xFFFFFFFF);
4497 SIVAL(pdata,6,0xFFFFFFFF);
4498 break;
4499 case SMB_ACL_OTHER:
4500 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4501 SIVAL(pdata,2,0xFFFFFFFF);
4502 SIVAL(pdata,6,0xFFFFFFFF);
4503 break;
4504 default:
4505 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4506 return False;
4508 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4511 return True;
4513 #endif
4515 /****************************************************************************
4516 Store the FILE_UNIX_BASIC info.
4517 ****************************************************************************/
4519 static char *store_file_unix_basic(connection_struct *conn,
4520 char *pdata,
4521 files_struct *fsp,
4522 const SMB_STRUCT_STAT *psbuf)
4524 uint64_t file_index = get_FileIndex(conn, psbuf);
4525 dev_t devno;
4527 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4528 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4530 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4531 pdata += 8;
4533 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4534 pdata += 8;
4536 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4537 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4538 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4539 pdata += 24;
4541 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4542 SIVAL(pdata,4,0);
4543 pdata += 8;
4545 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4546 SIVAL(pdata,4,0);
4547 pdata += 8;
4549 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4550 pdata += 4;
4552 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4553 devno = psbuf->st_ex_rdev;
4554 } else {
4555 devno = psbuf->st_ex_dev;
4558 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4559 SIVAL(pdata,4,0);
4560 pdata += 8;
4562 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4563 SIVAL(pdata,4,0);
4564 pdata += 8;
4566 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4567 pdata += 8;
4569 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4570 SIVAL(pdata,4,0);
4571 pdata += 8;
4573 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4574 SIVAL(pdata,4,0);
4575 pdata += 8;
4577 return pdata;
4580 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4581 * the chflags(2) (or equivalent) flags.
4583 * XXX: this really should be behind the VFS interface. To do this, we would
4584 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4585 * Each VFS module could then implement its own mapping as appropriate for the
4586 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4588 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4589 info2_flags_map[] =
4591 #ifdef UF_NODUMP
4592 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4593 #endif
4595 #ifdef UF_IMMUTABLE
4596 { UF_IMMUTABLE, EXT_IMMUTABLE },
4597 #endif
4599 #ifdef UF_APPEND
4600 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4601 #endif
4603 #ifdef UF_HIDDEN
4604 { UF_HIDDEN, EXT_HIDDEN },
4605 #endif
4607 /* Do not remove. We need to guarantee that this array has at least one
4608 * entry to build on HP-UX.
4610 { 0, 0 }
4614 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4615 uint32_t *smb_fflags, uint32_t *smb_fmask)
4617 int i;
4619 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4620 *smb_fmask |= info2_flags_map[i].smb_fflag;
4621 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4622 *smb_fflags |= info2_flags_map[i].smb_fflag;
4627 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4628 const uint32_t smb_fflags,
4629 const uint32_t smb_fmask,
4630 int *stat_fflags)
4632 uint32_t max_fmask = 0;
4633 int i;
4635 *stat_fflags = psbuf->st_ex_flags;
4637 /* For each flags requested in smb_fmask, check the state of the
4638 * corresponding flag in smb_fflags and set or clear the matching
4639 * stat flag.
4642 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4643 max_fmask |= info2_flags_map[i].smb_fflag;
4644 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4645 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4646 *stat_fflags |= info2_flags_map[i].stat_fflag;
4647 } else {
4648 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4653 /* If smb_fmask is asking to set any bits that are not supported by
4654 * our flag mappings, we should fail.
4656 if ((smb_fmask & max_fmask) != smb_fmask) {
4657 return False;
4660 return True;
4664 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4665 * of file flags and birth (create) time.
4667 static char *store_file_unix_basic_info2(connection_struct *conn,
4668 char *pdata,
4669 files_struct *fsp,
4670 const SMB_STRUCT_STAT *psbuf)
4672 uint32_t file_flags = 0;
4673 uint32_t flags_mask = 0;
4675 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4677 /* Create (birth) time 64 bit */
4678 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4679 pdata += 8;
4681 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4682 SIVAL(pdata, 0, file_flags); /* flags */
4683 SIVAL(pdata, 4, flags_mask); /* mask */
4684 pdata += 8;
4686 return pdata;
4689 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4690 const struct stream_struct *streams,
4691 char *data,
4692 unsigned int max_data_bytes,
4693 unsigned int *data_size)
4695 unsigned int i;
4696 unsigned int ofs = 0;
4698 if (max_data_bytes < 32) {
4699 return NT_STATUS_INFO_LENGTH_MISMATCH;
4702 for (i = 0; i < num_streams; i++) {
4703 unsigned int next_offset;
4704 size_t namelen;
4705 smb_ucs2_t *namebuf;
4707 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4708 streams[i].name, &namelen) ||
4709 namelen <= 2)
4711 return NT_STATUS_INVALID_PARAMETER;
4715 * name_buf is now null-terminated, we need to marshall as not
4716 * terminated
4719 namelen -= 2;
4722 * We cannot overflow ...
4724 if ((ofs + 24 + namelen) > max_data_bytes) {
4725 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4726 i));
4727 TALLOC_FREE(namebuf);
4728 return STATUS_BUFFER_OVERFLOW;
4731 SIVAL(data, ofs+4, namelen);
4732 SOFF_T(data, ofs+8, streams[i].size);
4733 SOFF_T(data, ofs+16, streams[i].alloc_size);
4734 memcpy(data+ofs+24, namebuf, namelen);
4735 TALLOC_FREE(namebuf);
4737 next_offset = ofs + 24 + namelen;
4739 if (i == num_streams-1) {
4740 SIVAL(data, ofs, 0);
4742 else {
4743 unsigned int align = ndr_align_size(next_offset, 8);
4745 if ((next_offset + align) > max_data_bytes) {
4746 DEBUG(10, ("refusing to overflow align "
4747 "reply at stream %u\n",
4748 i));
4749 TALLOC_FREE(namebuf);
4750 return STATUS_BUFFER_OVERFLOW;
4753 memset(data+next_offset, 0, align);
4754 next_offset += align;
4756 SIVAL(data, ofs, next_offset - ofs);
4757 ofs = next_offset;
4760 ofs = next_offset;
4763 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4765 *data_size = ofs;
4767 return NT_STATUS_OK;
4770 /****************************************************************************
4771 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4772 ****************************************************************************/
4774 static void call_trans2qpipeinfo(connection_struct *conn,
4775 struct smb_request *req,
4776 unsigned int tran_call,
4777 char **pparams, int total_params,
4778 char **ppdata, int total_data,
4779 unsigned int max_data_bytes)
4781 char *params = *pparams;
4782 char *pdata = *ppdata;
4783 unsigned int data_size = 0;
4784 unsigned int param_size = 2;
4785 uint16_t info_level;
4786 files_struct *fsp;
4788 if (!params) {
4789 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4790 return;
4793 if (total_params < 4) {
4794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4795 return;
4798 fsp = file_fsp(req, SVAL(params,0));
4799 if (!fsp_is_np(fsp)) {
4800 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4801 return;
4804 info_level = SVAL(params,2);
4806 *pparams = (char *)SMB_REALLOC(*pparams,2);
4807 if (*pparams == NULL) {
4808 reply_nterror(req, NT_STATUS_NO_MEMORY);
4809 return;
4811 params = *pparams;
4812 SSVAL(params,0,0);
4813 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4814 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4815 return;
4817 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4818 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4819 if (*ppdata == NULL ) {
4820 reply_nterror(req, NT_STATUS_NO_MEMORY);
4821 return;
4823 pdata = *ppdata;
4825 switch (info_level) {
4826 case SMB_FILE_STANDARD_INFORMATION:
4827 memset(pdata,0,24);
4828 SOFF_T(pdata,0,4096LL);
4829 SIVAL(pdata,16,1);
4830 SIVAL(pdata,20,1);
4831 data_size = 24;
4832 break;
4834 default:
4835 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4836 return;
4839 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4840 max_data_bytes);
4842 return;
4845 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4846 TALLOC_CTX *mem_ctx,
4847 uint16_t info_level,
4848 files_struct *fsp,
4849 struct smb_filename *smb_fname,
4850 bool delete_pending,
4851 struct timespec write_time_ts,
4852 struct ea_list *ea_list,
4853 int lock_data_count,
4854 char *lock_data,
4855 uint16_t flags2,
4856 unsigned int max_data_bytes,
4857 size_t *fixed_portion,
4858 char **ppdata,
4859 unsigned int *pdata_size)
4861 char *pdata = *ppdata;
4862 char *dstart, *dend;
4863 unsigned int data_size;
4864 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4865 time_t create_time, mtime, atime, c_time;
4866 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4867 char *p;
4868 char *base_name;
4869 char *dos_fname;
4870 int mode;
4871 int nlink;
4872 NTSTATUS status;
4873 uint64_t file_size = 0;
4874 uint64_t pos = 0;
4875 uint64_t allocation_size = 0;
4876 uint64_t file_index = 0;
4877 uint32_t access_mask = 0;
4878 size_t len = 0;
4880 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4881 return NT_STATUS_INVALID_LEVEL;
4884 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4885 smb_fname_str_dbg(smb_fname),
4886 fsp_fnum_dbg(fsp),
4887 info_level, max_data_bytes));
4889 mode = dos_mode(conn, smb_fname);
4890 nlink = psbuf->st_ex_nlink;
4892 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4893 nlink = 1;
4896 if ((nlink > 0) && delete_pending) {
4897 nlink -= 1;
4900 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4901 return NT_STATUS_INVALID_PARAMETER;
4904 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4905 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4906 if (*ppdata == NULL) {
4907 return NT_STATUS_NO_MEMORY;
4909 pdata = *ppdata;
4910 dstart = pdata;
4911 dend = dstart + data_size - 1;
4913 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4914 update_stat_ex_mtime(psbuf, write_time_ts);
4917 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4918 mtime_ts = psbuf->st_ex_mtime;
4919 atime_ts = psbuf->st_ex_atime;
4920 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4922 if (lp_dos_filetime_resolution(SNUM(conn))) {
4923 dos_filetime_timespec(&create_time_ts);
4924 dos_filetime_timespec(&mtime_ts);
4925 dos_filetime_timespec(&atime_ts);
4926 dos_filetime_timespec(&ctime_ts);
4929 create_time = convert_timespec_to_time_t(create_time_ts);
4930 mtime = convert_timespec_to_time_t(mtime_ts);
4931 atime = convert_timespec_to_time_t(atime_ts);
4932 c_time = convert_timespec_to_time_t(ctime_ts);
4934 p = strrchr_m(smb_fname->base_name,'/');
4935 if (!p)
4936 base_name = smb_fname->base_name;
4937 else
4938 base_name = p+1;
4940 /* NT expects the name to be in an exact form of the *full*
4941 filename. See the trans2 torture test */
4942 if (ISDOT(base_name)) {
4943 dos_fname = talloc_strdup(mem_ctx, "\\");
4944 if (!dos_fname) {
4945 return NT_STATUS_NO_MEMORY;
4947 } else {
4948 dos_fname = talloc_asprintf(mem_ctx,
4949 "\\%s",
4950 smb_fname->base_name);
4951 if (!dos_fname) {
4952 return NT_STATUS_NO_MEMORY;
4954 if (is_ntfs_stream_smb_fname(smb_fname)) {
4955 dos_fname = talloc_asprintf(dos_fname, "%s",
4956 smb_fname->stream_name);
4957 if (!dos_fname) {
4958 return NT_STATUS_NO_MEMORY;
4962 string_replace(dos_fname, '/', '\\');
4965 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4967 if (!fsp) {
4968 /* Do we have this path open ? */
4969 files_struct *fsp1;
4970 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4971 fsp1 = file_find_di_first(conn->sconn, fileid);
4972 if (fsp1 && fsp1->initial_allocation_size) {
4973 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4977 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4978 file_size = get_file_size_stat(psbuf);
4981 if (fsp) {
4982 pos = fsp->fh->position_information;
4985 if (fsp) {
4986 access_mask = fsp->access_mask;
4987 } else {
4988 /* GENERIC_EXECUTE mapping from Windows */
4989 access_mask = 0x12019F;
4992 /* This should be an index number - looks like
4993 dev/ino to me :-)
4995 I think this causes us to fail the IFSKIT
4996 BasicFileInformationTest. -tpot */
4997 file_index = get_FileIndex(conn, psbuf);
4999 *fixed_portion = 0;
5001 switch (info_level) {
5002 case SMB_INFO_STANDARD:
5003 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
5004 data_size = 22;
5005 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5006 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5007 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5008 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5009 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5010 SSVAL(pdata,l1_attrFile,mode);
5011 break;
5013 case SMB_INFO_QUERY_EA_SIZE:
5015 unsigned int ea_size =
5016 estimate_ea_size(conn, fsp,
5017 smb_fname);
5018 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5019 data_size = 26;
5020 srv_put_dos_date2(pdata,0,create_time);
5021 srv_put_dos_date2(pdata,4,atime);
5022 srv_put_dos_date2(pdata,8,mtime); /* write time */
5023 SIVAL(pdata,12,(uint32_t)file_size);
5024 SIVAL(pdata,16,(uint32_t)allocation_size);
5025 SSVAL(pdata,20,mode);
5026 SIVAL(pdata,22,ea_size);
5027 break;
5030 case SMB_INFO_IS_NAME_VALID:
5031 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5032 if (fsp) {
5033 /* os/2 needs this ? really ?*/
5034 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5036 /* This is only reached for qpathinfo */
5037 data_size = 0;
5038 break;
5040 case SMB_INFO_QUERY_EAS_FROM_LIST:
5042 size_t total_ea_len = 0;
5043 struct ea_list *ea_file_list = NULL;
5044 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5046 status =
5047 get_ea_list_from_file(mem_ctx, conn, fsp,
5048 smb_fname,
5049 &total_ea_len, &ea_file_list);
5050 if (!NT_STATUS_IS_OK(status)) {
5051 return status;
5054 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5056 if (!ea_list || (total_ea_len > data_size)) {
5057 data_size = 4;
5058 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5059 break;
5062 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5063 break;
5066 case SMB_INFO_QUERY_ALL_EAS:
5068 /* We have data_size bytes to put EA's into. */
5069 size_t total_ea_len = 0;
5070 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5072 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5073 smb_fname,
5074 &total_ea_len, &ea_list);
5075 if (!NT_STATUS_IS_OK(status)) {
5076 return status;
5079 if (!ea_list || (total_ea_len > data_size)) {
5080 data_size = 4;
5081 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5082 break;
5085 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5086 break;
5089 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5091 /* This is FileFullEaInformation - 0xF which maps to
5092 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5094 /* We have data_size bytes to put EA's into. */
5095 size_t total_ea_len = 0;
5096 struct ea_list *ea_file_list = NULL;
5098 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5100 /*TODO: add filtering and index handling */
5102 status =
5103 get_ea_list_from_file(mem_ctx, conn, fsp,
5104 smb_fname,
5105 &total_ea_len, &ea_file_list);
5106 if (!NT_STATUS_IS_OK(status)) {
5107 return status;
5109 if (!ea_file_list) {
5110 return NT_STATUS_NO_EAS_ON_FILE;
5113 status = fill_ea_chained_buffer(mem_ctx,
5114 pdata,
5115 data_size,
5116 &data_size,
5117 conn, ea_file_list);
5118 if (!NT_STATUS_IS_OK(status)) {
5119 return status;
5121 break;
5124 case SMB_FILE_BASIC_INFORMATION:
5125 case SMB_QUERY_FILE_BASIC_INFO:
5127 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5128 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5129 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5130 } else {
5131 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5132 data_size = 40;
5133 SIVAL(pdata,36,0);
5135 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5136 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5137 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5138 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5139 SIVAL(pdata,32,mode);
5141 DEBUG(5,("SMB_QFBI - "));
5142 DEBUG(5,("create: %s ", ctime(&create_time)));
5143 DEBUG(5,("access: %s ", ctime(&atime)));
5144 DEBUG(5,("write: %s ", ctime(&mtime)));
5145 DEBUG(5,("change: %s ", ctime(&c_time)));
5146 DEBUG(5,("mode: %x\n", mode));
5147 *fixed_portion = data_size;
5148 break;
5150 case SMB_FILE_STANDARD_INFORMATION:
5151 case SMB_QUERY_FILE_STANDARD_INFO:
5153 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5154 data_size = 24;
5155 SOFF_T(pdata,0,allocation_size);
5156 SOFF_T(pdata,8,file_size);
5157 SIVAL(pdata,16,nlink);
5158 SCVAL(pdata,20,delete_pending?1:0);
5159 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5160 SSVAL(pdata,22,0); /* Padding. */
5161 *fixed_portion = 24;
5162 break;
5164 case SMB_FILE_EA_INFORMATION:
5165 case SMB_QUERY_FILE_EA_INFO:
5167 unsigned int ea_size =
5168 estimate_ea_size(conn, fsp, smb_fname);
5169 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5170 data_size = 4;
5171 *fixed_portion = 4;
5172 SIVAL(pdata,0,ea_size);
5173 break;
5176 /* Get the 8.3 name - used if NT SMB was negotiated. */
5177 case SMB_QUERY_FILE_ALT_NAME_INFO:
5178 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5180 char mangled_name[13];
5181 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5182 if (!name_to_8_3(base_name,mangled_name,
5183 True,conn->params)) {
5184 return NT_STATUS_NO_MEMORY;
5186 status = srvstr_push(dstart, flags2,
5187 pdata+4, mangled_name,
5188 PTR_DIFF(dend, pdata+4),
5189 STR_UNICODE, &len);
5190 if (!NT_STATUS_IS_OK(status)) {
5191 return status;
5193 data_size = 4 + len;
5194 SIVAL(pdata,0,len);
5195 *fixed_portion = 8;
5196 break;
5199 case SMB_QUERY_FILE_NAME_INFO:
5202 this must be *exactly* right for ACLs on mapped drives to work
5204 status = srvstr_push(dstart, flags2,
5205 pdata+4, dos_fname,
5206 PTR_DIFF(dend, pdata+4),
5207 STR_UNICODE, &len);
5208 if (!NT_STATUS_IS_OK(status)) {
5209 return status;
5211 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5212 data_size = 4 + len;
5213 SIVAL(pdata,0,len);
5214 break;
5217 case SMB_FILE_ALLOCATION_INFORMATION:
5218 case SMB_QUERY_FILE_ALLOCATION_INFO:
5219 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5220 data_size = 8;
5221 SOFF_T(pdata,0,allocation_size);
5222 break;
5224 case SMB_FILE_END_OF_FILE_INFORMATION:
5225 case SMB_QUERY_FILE_END_OF_FILEINFO:
5226 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5227 data_size = 8;
5228 SOFF_T(pdata,0,file_size);
5229 break;
5231 case SMB_QUERY_FILE_ALL_INFO:
5232 case SMB_FILE_ALL_INFORMATION:
5234 unsigned int ea_size =
5235 estimate_ea_size(conn, fsp, smb_fname);
5236 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5237 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5238 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5239 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5240 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5241 SIVAL(pdata,32,mode);
5242 SIVAL(pdata,36,0); /* padding. */
5243 pdata += 40;
5244 SOFF_T(pdata,0,allocation_size);
5245 SOFF_T(pdata,8,file_size);
5246 SIVAL(pdata,16,nlink);
5247 SCVAL(pdata,20,delete_pending);
5248 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5249 SSVAL(pdata,22,0);
5250 pdata += 24;
5251 SIVAL(pdata,0,ea_size);
5252 pdata += 4; /* EA info */
5253 status = srvstr_push(dstart, flags2,
5254 pdata+4, dos_fname,
5255 PTR_DIFF(dend, pdata+4),
5256 STR_UNICODE, &len);
5257 if (!NT_STATUS_IS_OK(status)) {
5258 return status;
5260 SIVAL(pdata,0,len);
5261 pdata += 4 + len;
5262 data_size = PTR_DIFF(pdata,(*ppdata));
5263 *fixed_portion = 10;
5264 break;
5267 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5269 unsigned int ea_size =
5270 estimate_ea_size(conn, fsp, smb_fname);
5271 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5272 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5273 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5274 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5275 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5276 SIVAL(pdata, 0x20, mode);
5277 SIVAL(pdata, 0x24, 0); /* padding. */
5278 SBVAL(pdata, 0x28, allocation_size);
5279 SBVAL(pdata, 0x30, file_size);
5280 SIVAL(pdata, 0x38, nlink);
5281 SCVAL(pdata, 0x3C, delete_pending);
5282 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5283 SSVAL(pdata, 0x3E, 0); /* padding */
5284 SBVAL(pdata, 0x40, file_index);
5285 SIVAL(pdata, 0x48, ea_size);
5286 SIVAL(pdata, 0x4C, access_mask);
5287 SBVAL(pdata, 0x50, pos);
5288 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5289 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5291 pdata += 0x60;
5293 status = srvstr_push(dstart, flags2,
5294 pdata+4, dos_fname,
5295 PTR_DIFF(dend, pdata+4),
5296 STR_UNICODE, &len);
5297 if (!NT_STATUS_IS_OK(status)) {
5298 return status;
5300 SIVAL(pdata,0,len);
5301 pdata += 4 + len;
5302 data_size = PTR_DIFF(pdata,(*ppdata));
5303 *fixed_portion = 104;
5304 break;
5306 case SMB_FILE_INTERNAL_INFORMATION:
5308 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5309 SBVAL(pdata, 0, file_index);
5310 data_size = 8;
5311 *fixed_portion = 8;
5312 break;
5314 case SMB_FILE_ACCESS_INFORMATION:
5315 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5316 SIVAL(pdata, 0, access_mask);
5317 data_size = 4;
5318 *fixed_portion = 4;
5319 break;
5321 case SMB_FILE_NAME_INFORMATION:
5322 /* Pathname with leading '\'. */
5324 size_t byte_len;
5325 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5326 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5327 SIVAL(pdata,0,byte_len);
5328 data_size = 4 + byte_len;
5329 break;
5332 case SMB_FILE_DISPOSITION_INFORMATION:
5333 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5334 data_size = 1;
5335 SCVAL(pdata,0,delete_pending);
5336 *fixed_portion = 1;
5337 break;
5339 case SMB_FILE_POSITION_INFORMATION:
5340 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5341 data_size = 8;
5342 SOFF_T(pdata,0,pos);
5343 *fixed_portion = 8;
5344 break;
5346 case SMB_FILE_MODE_INFORMATION:
5347 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5348 SIVAL(pdata,0,mode);
5349 data_size = 4;
5350 *fixed_portion = 4;
5351 break;
5353 case SMB_FILE_ALIGNMENT_INFORMATION:
5354 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5355 SIVAL(pdata,0,0); /* No alignment needed. */
5356 data_size = 4;
5357 *fixed_portion = 4;
5358 break;
5361 * NT4 server just returns "invalid query" to this - if we try
5362 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5363 * want this. JRA.
5365 /* The first statement above is false - verified using Thursby
5366 * client against NT4 -- gcolley.
5368 case SMB_QUERY_FILE_STREAM_INFO:
5369 case SMB_FILE_STREAM_INFORMATION: {
5370 unsigned int num_streams = 0;
5371 struct stream_struct *streams = NULL;
5373 DEBUG(10,("smbd_do_qfilepathinfo: "
5374 "SMB_FILE_STREAM_INFORMATION\n"));
5376 if (is_ntfs_stream_smb_fname(smb_fname)) {
5377 return NT_STATUS_INVALID_PARAMETER;
5380 status = vfs_streaminfo(conn,
5381 fsp,
5382 smb_fname,
5383 talloc_tos(),
5384 &num_streams,
5385 &streams);
5387 if (!NT_STATUS_IS_OK(status)) {
5388 DEBUG(10, ("could not get stream info: %s\n",
5389 nt_errstr(status)));
5390 return status;
5393 status = marshall_stream_info(num_streams, streams,
5394 pdata, max_data_bytes,
5395 &data_size);
5397 if (!NT_STATUS_IS_OK(status)) {
5398 DEBUG(10, ("marshall_stream_info failed: %s\n",
5399 nt_errstr(status)));
5400 TALLOC_FREE(streams);
5401 return status;
5404 TALLOC_FREE(streams);
5406 *fixed_portion = 32;
5408 break;
5410 case SMB_QUERY_COMPRESSION_INFO:
5411 case SMB_FILE_COMPRESSION_INFORMATION:
5412 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5413 SOFF_T(pdata,0,file_size);
5414 SIVAL(pdata,8,0); /* ??? */
5415 SIVAL(pdata,12,0); /* ??? */
5416 data_size = 16;
5417 *fixed_portion = 16;
5418 break;
5420 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5421 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5422 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5423 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5424 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5425 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5426 SOFF_T(pdata,32,allocation_size);
5427 SOFF_T(pdata,40,file_size);
5428 SIVAL(pdata,48,mode);
5429 SIVAL(pdata,52,0); /* ??? */
5430 data_size = 56;
5431 *fixed_portion = 56;
5432 break;
5434 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5435 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5436 SIVAL(pdata,0,mode);
5437 SIVAL(pdata,4,0);
5438 data_size = 8;
5439 *fixed_portion = 8;
5440 break;
5443 * CIFS UNIX Extensions.
5446 case SMB_QUERY_FILE_UNIX_BASIC:
5448 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5449 data_size = PTR_DIFF(pdata,(*ppdata));
5451 DEBUG(4,("smbd_do_qfilepathinfo: "
5452 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5453 dump_data(4, (uint8_t *)(*ppdata), data_size);
5455 break;
5457 case SMB_QUERY_FILE_UNIX_INFO2:
5459 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5460 data_size = PTR_DIFF(pdata,(*ppdata));
5463 int i;
5464 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5466 for (i=0; i<100; i++)
5467 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5468 DEBUG(4,("\n"));
5471 break;
5473 case SMB_QUERY_FILE_UNIX_LINK:
5475 int link_len = 0;
5476 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5478 if (!buffer) {
5479 return NT_STATUS_NO_MEMORY;
5482 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5483 #ifdef S_ISLNK
5484 if(!S_ISLNK(psbuf->st_ex_mode)) {
5485 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5487 #else
5488 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5489 #endif
5490 link_len = SMB_VFS_READLINK(conn,
5491 smb_fname,
5492 buffer, PATH_MAX);
5493 if (link_len == -1) {
5494 return map_nt_error_from_unix(errno);
5496 buffer[link_len] = 0;
5497 status = srvstr_push(dstart, flags2,
5498 pdata, buffer,
5499 PTR_DIFF(dend, pdata),
5500 STR_TERMINATE, &len);
5501 if (!NT_STATUS_IS_OK(status)) {
5502 return status;
5504 pdata += len;
5505 data_size = PTR_DIFF(pdata,(*ppdata));
5507 break;
5510 #if defined(HAVE_POSIX_ACLS)
5511 case SMB_QUERY_POSIX_ACL:
5513 SMB_ACL_T file_acl = NULL;
5514 SMB_ACL_T def_acl = NULL;
5515 uint16_t num_file_acls = 0;
5516 uint16_t num_def_acls = 0;
5518 status = refuse_symlink(conn,
5519 fsp,
5520 smb_fname);
5521 if (!NT_STATUS_IS_OK(status)) {
5522 return status;
5525 if (fsp && fsp->fh->fd != -1) {
5526 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5527 talloc_tos());
5528 } else {
5529 file_acl =
5530 SMB_VFS_SYS_ACL_GET_FILE(conn,
5531 smb_fname,
5532 SMB_ACL_TYPE_ACCESS,
5533 talloc_tos());
5536 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5537 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5538 "not implemented on "
5539 "filesystem containing %s\n",
5540 smb_fname->base_name));
5541 return NT_STATUS_NOT_IMPLEMENTED;
5544 if (S_ISDIR(psbuf->st_ex_mode)) {
5545 if (fsp && fsp->is_directory) {
5546 def_acl =
5547 SMB_VFS_SYS_ACL_GET_FILE(
5548 conn,
5549 fsp->fsp_name,
5550 SMB_ACL_TYPE_DEFAULT,
5551 talloc_tos());
5552 } else {
5553 def_acl =
5554 SMB_VFS_SYS_ACL_GET_FILE(
5555 conn,
5556 smb_fname,
5557 SMB_ACL_TYPE_DEFAULT,
5558 talloc_tos());
5560 def_acl = free_empty_sys_acl(conn, def_acl);
5563 num_file_acls = count_acl_entries(conn, file_acl);
5564 num_def_acls = count_acl_entries(conn, def_acl);
5566 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5567 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5568 data_size,
5569 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5570 SMB_POSIX_ACL_HEADER_SIZE) ));
5571 if (file_acl) {
5572 TALLOC_FREE(file_acl);
5574 if (def_acl) {
5575 TALLOC_FREE(def_acl);
5577 return NT_STATUS_BUFFER_TOO_SMALL;
5580 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5581 SSVAL(pdata,2,num_file_acls);
5582 SSVAL(pdata,4,num_def_acls);
5583 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5584 if (file_acl) {
5585 TALLOC_FREE(file_acl);
5587 if (def_acl) {
5588 TALLOC_FREE(def_acl);
5590 return NT_STATUS_INTERNAL_ERROR;
5592 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5593 if (file_acl) {
5594 TALLOC_FREE(file_acl);
5596 if (def_acl) {
5597 TALLOC_FREE(def_acl);
5599 return NT_STATUS_INTERNAL_ERROR;
5602 if (file_acl) {
5603 TALLOC_FREE(file_acl);
5605 if (def_acl) {
5606 TALLOC_FREE(def_acl);
5608 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5609 break;
5611 #endif
5614 case SMB_QUERY_POSIX_LOCK:
5616 uint64_t count;
5617 uint64_t offset;
5618 uint64_t smblctx;
5619 enum brl_type lock_type;
5621 /* We need an open file with a real fd for this. */
5622 if (!fsp || fsp->fh->fd == -1) {
5623 return NT_STATUS_INVALID_LEVEL;
5626 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5627 return NT_STATUS_INVALID_PARAMETER;
5630 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5631 case POSIX_LOCK_TYPE_READ:
5632 lock_type = READ_LOCK;
5633 break;
5634 case POSIX_LOCK_TYPE_WRITE:
5635 lock_type = WRITE_LOCK;
5636 break;
5637 case POSIX_LOCK_TYPE_UNLOCK:
5638 default:
5639 /* There's no point in asking for an unlock... */
5640 return NT_STATUS_INVALID_PARAMETER;
5643 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5644 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5645 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5647 status = query_lock(fsp,
5648 &smblctx,
5649 &count,
5650 &offset,
5651 &lock_type,
5652 POSIX_LOCK);
5654 if (ERROR_WAS_LOCK_DENIED(status)) {
5655 /* Here we need to report who has it locked... */
5656 data_size = POSIX_LOCK_DATA_SIZE;
5658 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5659 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5660 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5661 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5662 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5664 } else if (NT_STATUS_IS_OK(status)) {
5665 /* For success we just return a copy of what we sent
5666 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5667 data_size = POSIX_LOCK_DATA_SIZE;
5668 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5669 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5670 } else {
5671 return status;
5673 break;
5676 default:
5677 return NT_STATUS_INVALID_LEVEL;
5680 *pdata_size = data_size;
5681 return NT_STATUS_OK;
5684 /****************************************************************************
5685 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5686 file name or file id).
5687 ****************************************************************************/
5689 static void call_trans2qfilepathinfo(connection_struct *conn,
5690 struct smb_request *req,
5691 unsigned int tran_call,
5692 char **pparams, int total_params,
5693 char **ppdata, int total_data,
5694 unsigned int max_data_bytes)
5696 char *params = *pparams;
5697 char *pdata = *ppdata;
5698 uint16_t info_level;
5699 unsigned int data_size = 0;
5700 unsigned int param_size = 2;
5701 struct smb_filename *smb_fname = NULL;
5702 bool delete_pending = False;
5703 struct timespec write_time_ts;
5704 files_struct *fsp = NULL;
5705 struct file_id fileid;
5706 struct ea_list *ea_list = NULL;
5707 int lock_data_count = 0;
5708 char *lock_data = NULL;
5709 size_t fixed_portion;
5710 NTSTATUS status = NT_STATUS_OK;
5712 if (!params) {
5713 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5714 return;
5717 ZERO_STRUCT(write_time_ts);
5719 if (tran_call == TRANSACT2_QFILEINFO) {
5720 if (total_params < 4) {
5721 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5722 return;
5725 if (IS_IPC(conn)) {
5726 call_trans2qpipeinfo(conn, req, tran_call,
5727 pparams, total_params,
5728 ppdata, total_data,
5729 max_data_bytes);
5730 return;
5733 fsp = file_fsp(req, SVAL(params,0));
5734 info_level = SVAL(params,2);
5736 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5738 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5739 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5740 return;
5743 /* Initial check for valid fsp ptr. */
5744 if (!check_fsp_open(conn, req, fsp)) {
5745 return;
5748 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5749 if (smb_fname == NULL) {
5750 reply_nterror(req, NT_STATUS_NO_MEMORY);
5751 return;
5754 if(fsp->fake_file_handle) {
5756 * This is actually for the QUOTA_FAKE_FILE --metze
5759 /* We know this name is ok, it's already passed the checks. */
5761 } else if(fsp->fh->fd == -1) {
5763 * This is actually a QFILEINFO on a directory
5764 * handle (returned from an NT SMB). NT5.0 seems
5765 * to do this call. JRA.
5768 if (INFO_LEVEL_IS_UNIX(info_level)) {
5769 /* Always do lstat for UNIX calls. */
5770 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5771 DEBUG(3,("call_trans2qfilepathinfo: "
5772 "SMB_VFS_LSTAT of %s failed "
5773 "(%s)\n",
5774 smb_fname_str_dbg(smb_fname),
5775 strerror(errno)));
5776 reply_nterror(req,
5777 map_nt_error_from_unix(errno));
5778 return;
5780 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5781 DEBUG(3,("call_trans2qfilepathinfo: "
5782 "SMB_VFS_STAT of %s failed (%s)\n",
5783 smb_fname_str_dbg(smb_fname),
5784 strerror(errno)));
5785 reply_nterror(req,
5786 map_nt_error_from_unix(errno));
5787 return;
5790 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5791 fileid = vfs_file_id_from_sbuf(
5792 conn, &smb_fname->st);
5793 get_file_infos(fileid, fsp->name_hash,
5794 &delete_pending,
5795 &write_time_ts);
5797 } else {
5799 * Original code - this is an open file.
5801 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5802 DEBUG(3, ("fstat of %s failed (%s)\n",
5803 fsp_fnum_dbg(fsp), strerror(errno)));
5804 reply_nterror(req,
5805 map_nt_error_from_unix(errno));
5806 return;
5808 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5809 fileid = vfs_file_id_from_sbuf(
5810 conn, &smb_fname->st);
5811 get_file_infos(fileid, fsp->name_hash,
5812 &delete_pending,
5813 &write_time_ts);
5817 } else {
5818 uint32_t name_hash;
5819 char *fname = NULL;
5820 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5822 /* qpathinfo */
5823 if (total_params < 7) {
5824 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5825 return;
5828 info_level = SVAL(params,0);
5830 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5832 if (INFO_LEVEL_IS_UNIX(info_level)) {
5833 if (!lp_unix_extensions()) {
5834 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5835 return;
5837 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5838 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5839 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5840 req->posix_pathnames) {
5841 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5845 if (req->posix_pathnames) {
5846 srvstr_get_path_posix(req,
5847 params,
5848 req->flags2,
5849 &fname,
5850 &params[6],
5851 total_params - 6,
5852 STR_TERMINATE,
5853 &status);
5854 } else {
5855 srvstr_get_path(req,
5856 params,
5857 req->flags2,
5858 &fname,
5859 &params[6],
5860 total_params - 6,
5861 STR_TERMINATE,
5862 &status);
5864 if (!NT_STATUS_IS_OK(status)) {
5865 reply_nterror(req, status);
5866 return;
5869 status = filename_convert(req,
5870 conn,
5871 fname,
5872 ucf_flags,
5873 NULL,
5874 NULL,
5875 &smb_fname);
5876 if (!NT_STATUS_IS_OK(status)) {
5877 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5878 reply_botherror(req,
5879 NT_STATUS_PATH_NOT_COVERED,
5880 ERRSRV, ERRbadpath);
5881 return;
5883 reply_nterror(req, status);
5884 return;
5887 /* If this is a stream, check if there is a delete_pending. */
5888 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5889 && is_ntfs_stream_smb_fname(smb_fname)) {
5890 struct smb_filename *smb_fname_base;
5892 /* Create an smb_filename with stream_name == NULL. */
5893 smb_fname_base = synthetic_smb_fname(
5894 talloc_tos(),
5895 smb_fname->base_name,
5896 NULL,
5897 NULL,
5898 smb_fname->flags);
5899 if (smb_fname_base == NULL) {
5900 reply_nterror(req, NT_STATUS_NO_MEMORY);
5901 return;
5904 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5905 /* Always do lstat for UNIX calls. */
5906 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5907 DEBUG(3,("call_trans2qfilepathinfo: "
5908 "SMB_VFS_LSTAT of %s failed "
5909 "(%s)\n",
5910 smb_fname_str_dbg(smb_fname_base),
5911 strerror(errno)));
5912 TALLOC_FREE(smb_fname_base);
5913 reply_nterror(req,
5914 map_nt_error_from_unix(errno));
5915 return;
5917 } else {
5918 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5919 DEBUG(3,("call_trans2qfilepathinfo: "
5920 "fileinfo of %s failed "
5921 "(%s)\n",
5922 smb_fname_str_dbg(smb_fname_base),
5923 strerror(errno)));
5924 TALLOC_FREE(smb_fname_base);
5925 reply_nterror(req,
5926 map_nt_error_from_unix(errno));
5927 return;
5931 status = file_name_hash(conn,
5932 smb_fname_str_dbg(smb_fname_base),
5933 &name_hash);
5934 if (!NT_STATUS_IS_OK(status)) {
5935 TALLOC_FREE(smb_fname_base);
5936 reply_nterror(req, status);
5937 return;
5940 fileid = vfs_file_id_from_sbuf(conn,
5941 &smb_fname_base->st);
5942 TALLOC_FREE(smb_fname_base);
5943 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5944 if (delete_pending) {
5945 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5946 return;
5950 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5951 /* Always do lstat for UNIX calls. */
5952 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5953 DEBUG(3,("call_trans2qfilepathinfo: "
5954 "SMB_VFS_LSTAT of %s failed (%s)\n",
5955 smb_fname_str_dbg(smb_fname),
5956 strerror(errno)));
5957 reply_nterror(req,
5958 map_nt_error_from_unix(errno));
5959 return;
5962 } else {
5963 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5964 DEBUG(3,("call_trans2qfilepathinfo: "
5965 "SMB_VFS_STAT of %s failed (%s)\n",
5966 smb_fname_str_dbg(smb_fname),
5967 strerror(errno)));
5968 reply_nterror(req,
5969 map_nt_error_from_unix(errno));
5970 return;
5974 status = file_name_hash(conn,
5975 smb_fname_str_dbg(smb_fname),
5976 &name_hash);
5977 if (!NT_STATUS_IS_OK(status)) {
5978 reply_nterror(req, status);
5979 return;
5982 if (lp_smbd_getinfo_ask_sharemode(SNUM(conn))) {
5983 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5984 get_file_infos(fileid, name_hash, &delete_pending,
5985 &write_time_ts);
5988 if (delete_pending) {
5989 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5990 return;
5994 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5995 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5996 fsp_fnum_dbg(fsp),
5997 info_level,tran_call,total_data));
5999 /* Pull out any data sent here before we realloc. */
6000 switch (info_level) {
6001 case SMB_INFO_QUERY_EAS_FROM_LIST:
6003 /* Pull any EA list from the data portion. */
6004 uint32_t ea_size;
6006 if (total_data < 4) {
6007 reply_nterror(
6008 req, NT_STATUS_INVALID_PARAMETER);
6009 return;
6011 ea_size = IVAL(pdata,0);
6013 if (total_data > 0 && ea_size != total_data) {
6014 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
6015 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
6016 reply_nterror(
6017 req, NT_STATUS_INVALID_PARAMETER);
6018 return;
6021 if (!lp_ea_support(SNUM(conn))) {
6022 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6023 return;
6026 /* Pull out the list of names. */
6027 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6028 if (!ea_list) {
6029 reply_nterror(
6030 req, NT_STATUS_INVALID_PARAMETER);
6031 return;
6033 break;
6036 case SMB_QUERY_POSIX_LOCK:
6038 if (fsp == NULL || fsp->fh->fd == -1) {
6039 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6040 return;
6043 if (total_data != POSIX_LOCK_DATA_SIZE) {
6044 reply_nterror(
6045 req, NT_STATUS_INVALID_PARAMETER);
6046 return;
6049 /* Copy the lock range data. */
6050 lock_data = (char *)talloc_memdup(
6051 req, pdata, total_data);
6052 if (!lock_data) {
6053 reply_nterror(req, NT_STATUS_NO_MEMORY);
6054 return;
6056 lock_data_count = total_data;
6058 default:
6059 break;
6062 *pparams = (char *)SMB_REALLOC(*pparams,2);
6063 if (*pparams == NULL) {
6064 reply_nterror(req, NT_STATUS_NO_MEMORY);
6065 return;
6067 params = *pparams;
6068 SSVAL(params,0,0);
6071 * draft-leach-cifs-v1-spec-02.txt
6072 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6073 * says:
6075 * The requested information is placed in the Data portion of the
6076 * transaction response. For the information levels greater than 0x100,
6077 * the transaction response has 1 parameter word which should be
6078 * ignored by the client.
6080 * However Windows only follows this rule for the IS_NAME_VALID call.
6082 switch (info_level) {
6083 case SMB_INFO_IS_NAME_VALID:
6084 param_size = 0;
6085 break;
6088 if ((info_level & 0xFF00) == 0xFF00) {
6090 * We use levels that start with 0xFF00
6091 * internally to represent SMB2 specific levels
6093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6094 return;
6097 status = smbd_do_qfilepathinfo(conn, req, info_level,
6098 fsp, smb_fname,
6099 delete_pending, write_time_ts,
6100 ea_list,
6101 lock_data_count, lock_data,
6102 req->flags2, max_data_bytes,
6103 &fixed_portion,
6104 ppdata, &data_size);
6105 if (!NT_STATUS_IS_OK(status)) {
6106 reply_nterror(req, status);
6107 return;
6109 if (fixed_portion > max_data_bytes) {
6110 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6111 return;
6114 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6115 max_data_bytes);
6117 return;
6120 /****************************************************************************
6121 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6122 code.
6123 ****************************************************************************/
6125 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6126 connection_struct *conn,
6127 struct smb_request *req,
6128 bool overwrite_if_exists,
6129 const struct smb_filename *smb_fname_old,
6130 struct smb_filename *smb_fname_new)
6132 NTSTATUS status = NT_STATUS_OK;
6133 bool ok;
6135 /* source must already exist. */
6136 if (!VALID_STAT(smb_fname_old->st)) {
6137 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6140 if (VALID_STAT(smb_fname_new->st)) {
6141 if (overwrite_if_exists) {
6142 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6143 return NT_STATUS_FILE_IS_A_DIRECTORY;
6145 status = unlink_internals(conn,
6146 req,
6147 FILE_ATTRIBUTE_NORMAL,
6148 smb_fname_new,
6149 false);
6150 if (!NT_STATUS_IS_OK(status)) {
6151 return status;
6153 } else {
6154 /* Disallow if newname already exists. */
6155 return NT_STATUS_OBJECT_NAME_COLLISION;
6159 /* No links from a directory. */
6160 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6161 return NT_STATUS_FILE_IS_A_DIRECTORY;
6164 /* Setting a hardlink to/from a stream isn't currently supported. */
6165 ok = is_ntfs_stream_smb_fname(smb_fname_old);
6166 if (ok) {
6167 DBG_DEBUG("Old name has streams\n");
6168 return NT_STATUS_INVALID_PARAMETER;
6170 ok = is_ntfs_stream_smb_fname(smb_fname_new);
6171 if (ok) {
6172 DBG_DEBUG("New name has streams\n");
6173 return NT_STATUS_INVALID_PARAMETER;
6176 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6177 smb_fname_old->base_name, smb_fname_new->base_name));
6179 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6180 status = map_nt_error_from_unix(errno);
6181 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6182 nt_errstr(status), smb_fname_old->base_name,
6183 smb_fname_new->base_name));
6185 return status;
6188 /****************************************************************************
6189 Deal with setting the time from any of the setfilepathinfo functions.
6190 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6191 calling this function.
6192 ****************************************************************************/
6194 NTSTATUS smb_set_file_time(connection_struct *conn,
6195 files_struct *fsp,
6196 const struct smb_filename *smb_fname,
6197 struct smb_file_time *ft,
6198 bool setting_write_time)
6200 struct smb_filename smb_fname_base;
6201 uint32_t action =
6202 FILE_NOTIFY_CHANGE_LAST_ACCESS
6203 |FILE_NOTIFY_CHANGE_LAST_WRITE
6204 |FILE_NOTIFY_CHANGE_CREATION;
6206 if (!VALID_STAT(smb_fname->st)) {
6207 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6210 /* get some defaults (no modifications) if any info is zero or -1. */
6211 if (null_timespec(ft->create_time)) {
6212 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6215 if (null_timespec(ft->atime)) {
6216 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6219 if (null_timespec(ft->mtime)) {
6220 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6223 if (!setting_write_time) {
6224 /* ft->mtime comes from change time, not write time. */
6225 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6228 /* Ensure the resolution is the correct for
6229 * what we can store on this filesystem. */
6231 round_timespec(conn->ts_res, &ft->create_time);
6232 round_timespec(conn->ts_res, &ft->ctime);
6233 round_timespec(conn->ts_res, &ft->atime);
6234 round_timespec(conn->ts_res, &ft->mtime);
6236 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6237 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6238 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6239 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6240 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6241 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6242 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6243 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6245 if (setting_write_time) {
6247 * This was a Windows setfileinfo on an open file.
6248 * NT does this a lot. We also need to
6249 * set the time here, as it can be read by
6250 * FindFirst/FindNext and with the patch for bug #2045
6251 * in smbd/fileio.c it ensures that this timestamp is
6252 * kept sticky even after a write. We save the request
6253 * away and will set it on file close and after a write. JRA.
6256 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6257 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6259 if (fsp != NULL) {
6260 if (fsp->base_fsp) {
6261 set_sticky_write_time_fsp(fsp->base_fsp,
6262 ft->mtime);
6263 } else {
6264 set_sticky_write_time_fsp(fsp, ft->mtime);
6266 } else {
6267 set_sticky_write_time_path(
6268 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6269 ft->mtime);
6273 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6275 /* Always call ntimes on the base, even if a stream was passed in. */
6276 smb_fname_base = *smb_fname;
6277 smb_fname_base.stream_name = NULL;
6279 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6280 return map_nt_error_from_unix(errno);
6283 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6284 smb_fname->base_name);
6285 return NT_STATUS_OK;
6288 /****************************************************************************
6289 Deal with setting the dosmode from any of the setfilepathinfo functions.
6290 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6291 done before calling this function.
6292 ****************************************************************************/
6294 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6295 const struct smb_filename *smb_fname,
6296 uint32_t dosmode)
6298 struct smb_filename *smb_fname_base;
6299 NTSTATUS status;
6301 if (!VALID_STAT(smb_fname->st)) {
6302 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6305 /* Always operate on the base_name, even if a stream was passed in. */
6306 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6307 smb_fname->base_name,
6308 NULL,
6309 &smb_fname->st,
6310 smb_fname->flags);
6311 if (smb_fname_base == NULL) {
6312 return NT_STATUS_NO_MEMORY;
6315 if (dosmode) {
6316 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6317 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6318 } else {
6319 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6323 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6325 /* check the mode isn't different, before changing it */
6326 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6327 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6328 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6329 (unsigned int)dosmode));
6331 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6332 false)) {
6333 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6334 "%s failed (%s)\n",
6335 smb_fname_str_dbg(smb_fname_base),
6336 strerror(errno)));
6337 status = map_nt_error_from_unix(errno);
6338 goto out;
6341 status = NT_STATUS_OK;
6342 out:
6343 TALLOC_FREE(smb_fname_base);
6344 return status;
6347 /****************************************************************************
6348 Deal with setting the size from any of the setfilepathinfo functions.
6349 ****************************************************************************/
6351 static NTSTATUS smb_set_file_size(connection_struct *conn,
6352 struct smb_request *req,
6353 files_struct *fsp,
6354 const struct smb_filename *smb_fname,
6355 const SMB_STRUCT_STAT *psbuf,
6356 off_t size,
6357 bool fail_after_createfile)
6359 NTSTATUS status = NT_STATUS_OK;
6360 struct smb_filename *smb_fname_tmp = NULL;
6361 files_struct *new_fsp = NULL;
6363 if (!VALID_STAT(*psbuf)) {
6364 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6367 DBG_INFO("size: %"PRIu64", file_size_stat=%"PRIu64"\n",
6368 (uint64_t)size,
6369 get_file_size_stat(psbuf));
6371 if (size == get_file_size_stat(psbuf)) {
6372 return NT_STATUS_OK;
6375 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6376 smb_fname_str_dbg(smb_fname), (double)size));
6378 if (fsp && fsp->fh->fd != -1) {
6379 /* Handle based call. */
6380 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6381 return NT_STATUS_ACCESS_DENIED;
6384 if (vfs_set_filelen(fsp, size) == -1) {
6385 return map_nt_error_from_unix(errno);
6387 trigger_write_time_update_immediate(fsp);
6388 return NT_STATUS_OK;
6391 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6392 if (smb_fname_tmp == NULL) {
6393 return NT_STATUS_NO_MEMORY;
6396 smb_fname_tmp->st = *psbuf;
6398 status = SMB_VFS_CREATE_FILE(
6399 conn, /* conn */
6400 req, /* req */
6401 0, /* root_dir_fid */
6402 smb_fname_tmp, /* fname */
6403 FILE_WRITE_DATA, /* access_mask */
6404 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6405 FILE_SHARE_DELETE),
6406 FILE_OPEN, /* create_disposition*/
6407 0, /* create_options */
6408 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6409 0, /* oplock_request */
6410 NULL, /* lease */
6411 0, /* allocation_size */
6412 0, /* private_flags */
6413 NULL, /* sd */
6414 NULL, /* ea_list */
6415 &new_fsp, /* result */
6416 NULL, /* pinfo */
6417 NULL, NULL); /* create context */
6419 TALLOC_FREE(smb_fname_tmp);
6421 if (!NT_STATUS_IS_OK(status)) {
6422 /* NB. We check for open_was_deferred in the caller. */
6423 return status;
6426 /* See RAW-SFILEINFO-END-OF-FILE */
6427 if (fail_after_createfile) {
6428 close_file(req, new_fsp,NORMAL_CLOSE);
6429 return NT_STATUS_INVALID_LEVEL;
6432 if (vfs_set_filelen(new_fsp, size) == -1) {
6433 status = map_nt_error_from_unix(errno);
6434 close_file(req, new_fsp,NORMAL_CLOSE);
6435 return status;
6438 trigger_write_time_update_immediate(new_fsp);
6439 close_file(req, new_fsp,NORMAL_CLOSE);
6440 return NT_STATUS_OK;
6443 /****************************************************************************
6444 Deal with SMB_INFO_SET_EA.
6445 ****************************************************************************/
6447 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6448 const char *pdata,
6449 int total_data,
6450 files_struct *fsp,
6451 const struct smb_filename *smb_fname)
6453 struct ea_list *ea_list = NULL;
6454 TALLOC_CTX *ctx = NULL;
6455 NTSTATUS status = NT_STATUS_OK;
6457 if (total_data < 10) {
6459 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6460 length. They seem to have no effect. Bug #3212. JRA */
6462 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6463 /* We're done. We only get EA info in this call. */
6464 return NT_STATUS_OK;
6467 return NT_STATUS_INVALID_PARAMETER;
6470 if (IVAL(pdata,0) > total_data) {
6471 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6472 IVAL(pdata,0), (unsigned int)total_data));
6473 return NT_STATUS_INVALID_PARAMETER;
6476 ctx = talloc_tos();
6477 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6478 if (!ea_list) {
6479 return NT_STATUS_INVALID_PARAMETER;
6482 status = set_ea(conn, fsp, smb_fname, ea_list);
6484 return status;
6487 /****************************************************************************
6488 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6489 ****************************************************************************/
6491 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6492 const char *pdata,
6493 int total_data,
6494 files_struct *fsp)
6496 struct ea_list *ea_list = NULL;
6497 NTSTATUS status;
6499 if (!fsp) {
6500 return NT_STATUS_INVALID_HANDLE;
6503 if (!lp_ea_support(SNUM(conn))) {
6504 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6505 "EA's not supported.\n",
6506 (unsigned int)total_data));
6507 return NT_STATUS_EAS_NOT_SUPPORTED;
6510 if (total_data < 10) {
6511 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6512 "too small.\n",
6513 (unsigned int)total_data));
6514 return NT_STATUS_INVALID_PARAMETER;
6517 ea_list = read_nttrans_ea_list(talloc_tos(),
6518 pdata,
6519 total_data);
6521 if (!ea_list) {
6522 return NT_STATUS_INVALID_PARAMETER;
6525 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6527 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6528 smb_fname_str_dbg(fsp->fsp_name),
6529 nt_errstr(status) ));
6531 return status;
6535 /****************************************************************************
6536 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6537 ****************************************************************************/
6539 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6540 const char *pdata,
6541 int total_data,
6542 files_struct *fsp,
6543 struct smb_filename *smb_fname)
6545 NTSTATUS status = NT_STATUS_OK;
6546 bool delete_on_close;
6547 uint32_t dosmode = 0;
6549 if (total_data < 1) {
6550 return NT_STATUS_INVALID_PARAMETER;
6553 if (fsp == NULL) {
6554 return NT_STATUS_INVALID_HANDLE;
6557 delete_on_close = (CVAL(pdata,0) ? True : False);
6558 dosmode = dos_mode(conn, smb_fname);
6560 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6561 "delete_on_close = %u\n",
6562 smb_fname_str_dbg(smb_fname),
6563 (unsigned int)dosmode,
6564 (unsigned int)delete_on_close ));
6566 if (delete_on_close) {
6567 status = can_set_delete_on_close(fsp, dosmode);
6568 if (!NT_STATUS_IS_OK(status)) {
6569 return status;
6573 /* The set is across all open files on this dev/inode pair. */
6574 if (!set_delete_on_close(fsp, delete_on_close,
6575 conn->session_info->security_token,
6576 conn->session_info->unix_token)) {
6577 return NT_STATUS_ACCESS_DENIED;
6579 return NT_STATUS_OK;
6582 /****************************************************************************
6583 Deal with SMB_FILE_POSITION_INFORMATION.
6584 ****************************************************************************/
6586 static NTSTATUS smb_file_position_information(connection_struct *conn,
6587 const char *pdata,
6588 int total_data,
6589 files_struct *fsp)
6591 uint64_t position_information;
6593 if (total_data < 8) {
6594 return NT_STATUS_INVALID_PARAMETER;
6597 if (fsp == NULL) {
6598 /* Ignore on pathname based set. */
6599 return NT_STATUS_OK;
6602 position_information = (uint64_t)IVAL(pdata,0);
6603 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6605 DEBUG(10,("smb_file_position_information: Set file position "
6606 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6607 (double)position_information));
6608 fsp->fh->position_information = position_information;
6609 return NT_STATUS_OK;
6612 /****************************************************************************
6613 Deal with SMB_FILE_MODE_INFORMATION.
6614 ****************************************************************************/
6616 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6617 const char *pdata,
6618 int total_data)
6620 uint32_t mode;
6622 if (total_data < 4) {
6623 return NT_STATUS_INVALID_PARAMETER;
6625 mode = IVAL(pdata,0);
6626 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6627 return NT_STATUS_INVALID_PARAMETER;
6629 return NT_STATUS_OK;
6632 /****************************************************************************
6633 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6634 ****************************************************************************/
6636 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6637 struct smb_request *req,
6638 const char *pdata,
6639 int total_data,
6640 const struct smb_filename *new_smb_fname)
6642 char *link_target = NULL;
6643 TALLOC_CTX *ctx = talloc_tos();
6645 /* Set a symbolic link. */
6646 /* Don't allow this if follow links is false. */
6648 if (total_data == 0) {
6649 return NT_STATUS_INVALID_PARAMETER;
6652 if (!lp_follow_symlinks(SNUM(conn))) {
6653 return NT_STATUS_ACCESS_DENIED;
6656 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6657 total_data, STR_TERMINATE);
6659 if (!link_target) {
6660 return NT_STATUS_INVALID_PARAMETER;
6663 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6664 new_smb_fname->base_name, link_target ));
6666 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6667 return map_nt_error_from_unix(errno);
6670 return NT_STATUS_OK;
6673 /****************************************************************************
6674 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6675 ****************************************************************************/
6677 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6678 struct smb_request *req,
6679 const char *pdata, int total_data,
6680 struct smb_filename *smb_fname_new)
6682 char *oldname = NULL;
6683 struct smb_filename *smb_fname_old = NULL;
6684 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6685 TALLOC_CTX *ctx = talloc_tos();
6686 NTSTATUS status = NT_STATUS_OK;
6688 /* Set a hard link. */
6689 if (total_data == 0) {
6690 return NT_STATUS_INVALID_PARAMETER;
6693 if (req->posix_pathnames) {
6694 srvstr_get_path_posix(ctx,
6695 pdata,
6696 req->flags2,
6697 &oldname,
6698 pdata,
6699 total_data,
6700 STR_TERMINATE,
6701 &status);
6702 } else {
6703 srvstr_get_path(ctx,
6704 pdata,
6705 req->flags2,
6706 &oldname,
6707 pdata,
6708 total_data,
6709 STR_TERMINATE,
6710 &status);
6712 if (!NT_STATUS_IS_OK(status)) {
6713 return status;
6716 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6717 smb_fname_str_dbg(smb_fname_new), oldname));
6719 status = filename_convert(ctx,
6720 conn,
6721 oldname,
6722 ucf_flags,
6723 NULL,
6724 NULL,
6725 &smb_fname_old);
6726 if (!NT_STATUS_IS_OK(status)) {
6727 return status;
6730 return hardlink_internals(ctx, conn, req, false,
6731 smb_fname_old, smb_fname_new);
6734 /****************************************************************************
6735 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6736 ****************************************************************************/
6738 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6739 struct smb_request *req,
6740 const char *pdata,
6741 int total_data,
6742 files_struct *fsp,
6743 struct smb_filename *smb_fname_src)
6745 bool overwrite;
6746 uint32_t len;
6747 char *newname = NULL;
6748 struct smb_filename *smb_fname_dst = NULL;
6749 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6750 ucf_flags_from_smb_request(req);
6751 NTSTATUS status = NT_STATUS_OK;
6752 TALLOC_CTX *ctx = talloc_tos();
6754 if (!fsp) {
6755 return NT_STATUS_INVALID_HANDLE;
6758 if (total_data < 20) {
6759 return NT_STATUS_INVALID_PARAMETER;
6762 overwrite = (CVAL(pdata,0) ? True : False);
6763 len = IVAL(pdata,16);
6765 if (len > (total_data - 20) || (len == 0)) {
6766 return NT_STATUS_INVALID_PARAMETER;
6769 if (req->posix_pathnames) {
6770 srvstr_get_path_posix(ctx,
6771 pdata,
6772 req->flags2,
6773 &newname,
6774 &pdata[20],
6775 len,
6776 STR_TERMINATE,
6777 &status);
6778 } else {
6779 srvstr_get_path(ctx,
6780 pdata,
6781 req->flags2,
6782 &newname,
6783 &pdata[20],
6784 len,
6785 STR_TERMINATE,
6786 &status);
6788 if (!NT_STATUS_IS_OK(status)) {
6789 return status;
6792 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6793 newname));
6795 status = filename_convert(ctx,
6796 conn,
6797 newname,
6798 ucf_flags,
6799 NULL,
6800 NULL,
6801 &smb_fname_dst);
6802 if (!NT_STATUS_IS_OK(status)) {
6803 return status;
6806 if (fsp->base_fsp) {
6807 /* newname must be a stream name. */
6808 if (newname[0] != ':') {
6809 return NT_STATUS_NOT_SUPPORTED;
6812 /* Create an smb_fname to call rename_internals_fsp() with. */
6813 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6814 fsp->base_fsp->fsp_name->base_name,
6815 newname,
6816 NULL,
6817 fsp->base_fsp->fsp_name->flags);
6818 if (smb_fname_dst == NULL) {
6819 status = NT_STATUS_NO_MEMORY;
6820 goto out;
6824 * Set the original last component, since
6825 * rename_internals_fsp() requires it.
6827 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6828 newname);
6829 if (smb_fname_dst->original_lcomp == NULL) {
6830 status = NT_STATUS_NO_MEMORY;
6831 goto out;
6836 DEBUG(10,("smb2_file_rename_information: "
6837 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6838 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6839 smb_fname_str_dbg(smb_fname_dst)));
6840 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6841 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6842 overwrite);
6844 out:
6845 TALLOC_FREE(smb_fname_dst);
6846 return status;
6849 static NTSTATUS smb_file_link_information(connection_struct *conn,
6850 struct smb_request *req,
6851 const char *pdata,
6852 int total_data,
6853 files_struct *fsp,
6854 struct smb_filename *smb_fname_src)
6856 bool overwrite;
6857 uint32_t len;
6858 char *newname = NULL;
6859 struct smb_filename *smb_fname_dst = NULL;
6860 NTSTATUS status = NT_STATUS_OK;
6861 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6862 ucf_flags_from_smb_request(req);
6863 TALLOC_CTX *ctx = talloc_tos();
6865 if (!fsp) {
6866 return NT_STATUS_INVALID_HANDLE;
6869 if (total_data < 20) {
6870 return NT_STATUS_INVALID_PARAMETER;
6873 overwrite = (CVAL(pdata,0) ? true : false);
6874 len = IVAL(pdata,16);
6876 if (len > (total_data - 20) || (len == 0)) {
6877 return NT_STATUS_INVALID_PARAMETER;
6880 if (smb_fname_src->flags & SMB_FILENAME_POSIX_PATH) {
6881 srvstr_get_path_posix(ctx,
6882 pdata,
6883 req->flags2,
6884 &newname,
6885 &pdata[20],
6886 len,
6887 STR_TERMINATE,
6888 &status);
6889 ucf_flags |= UCF_POSIX_PATHNAMES;
6890 } else {
6891 srvstr_get_path(ctx,
6892 pdata,
6893 req->flags2,
6894 &newname,
6895 &pdata[20],
6896 len,
6897 STR_TERMINATE,
6898 &status);
6900 if (!NT_STATUS_IS_OK(status)) {
6901 return status;
6904 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6905 newname));
6907 status = filename_convert(ctx,
6908 conn,
6909 newname,
6910 ucf_flags,
6911 NULL,
6912 NULL,
6913 &smb_fname_dst);
6914 if (!NT_STATUS_IS_OK(status)) {
6915 return status;
6918 if (fsp->base_fsp) {
6919 /* No stream names. */
6920 return NT_STATUS_NOT_SUPPORTED;
6923 DEBUG(10,("smb_file_link_information: "
6924 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6925 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6926 smb_fname_str_dbg(smb_fname_dst)));
6927 status = hardlink_internals(ctx,
6928 conn,
6929 req,
6930 overwrite,
6931 fsp->fsp_name,
6932 smb_fname_dst);
6934 TALLOC_FREE(smb_fname_dst);
6935 return status;
6938 /****************************************************************************
6939 Deal with SMB_FILE_RENAME_INFORMATION.
6940 ****************************************************************************/
6942 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6943 struct smb_request *req,
6944 const char *pdata,
6945 int total_data,
6946 files_struct *fsp,
6947 struct smb_filename *smb_fname_src)
6949 bool overwrite;
6950 uint32_t root_fid;
6951 uint32_t len;
6952 char *newname = NULL;
6953 struct smb_filename *smb_fname_dst = NULL;
6954 bool dest_has_wcard = False;
6955 NTSTATUS status = NT_STATUS_OK;
6956 char *p;
6957 TALLOC_CTX *ctx = talloc_tos();
6959 if (total_data < 13) {
6960 return NT_STATUS_INVALID_PARAMETER;
6963 overwrite = (CVAL(pdata,0) ? True : False);
6964 root_fid = IVAL(pdata,4);
6965 len = IVAL(pdata,8);
6967 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6968 return NT_STATUS_INVALID_PARAMETER;
6971 if (req->posix_pathnames) {
6972 srvstr_get_path_wcard_posix(ctx,
6973 pdata,
6974 req->flags2,
6975 &newname,
6976 &pdata[12],
6977 len,
6979 &status,
6980 &dest_has_wcard);
6981 } else {
6982 srvstr_get_path_wcard(ctx,
6983 pdata,
6984 req->flags2,
6985 &newname,
6986 &pdata[12],
6987 len,
6989 &status,
6990 &dest_has_wcard);
6992 if (!NT_STATUS_IS_OK(status)) {
6993 return status;
6996 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6997 newname));
6999 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
7000 status = resolve_dfspath_wcard(ctx, conn,
7001 newname,
7002 UCF_COND_ALLOW_WCARD_LCOMP,
7003 !conn->sconn->using_smb2,
7004 &newname,
7005 &dest_has_wcard);
7006 if (!NT_STATUS_IS_OK(status)) {
7007 return status;
7011 /* Check the new name has no '/' characters. */
7012 if (strchr_m(newname, '/')) {
7013 return NT_STATUS_NOT_SUPPORTED;
7016 if (fsp && fsp->base_fsp) {
7017 /* newname must be a stream name. */
7018 if (newname[0] != ':') {
7019 return NT_STATUS_NOT_SUPPORTED;
7022 /* Create an smb_fname to call rename_internals_fsp() with. */
7023 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
7024 fsp->base_fsp->fsp_name->base_name,
7025 newname,
7026 NULL,
7027 fsp->base_fsp->fsp_name->flags);
7028 if (smb_fname_dst == NULL) {
7029 status = NT_STATUS_NO_MEMORY;
7030 goto out;
7034 * Set the original last component, since
7035 * rename_internals_fsp() requires it.
7037 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7038 newname);
7039 if (smb_fname_dst->original_lcomp == NULL) {
7040 status = NT_STATUS_NO_MEMORY;
7041 goto out;
7044 } else {
7046 * Build up an smb_fname_dst based on the filename passed in.
7047 * We basically just strip off the last component, and put on
7048 * the newname instead.
7050 char *base_name = NULL;
7051 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7052 ucf_flags_from_smb_request(req);
7054 if (dest_has_wcard) {
7055 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7058 /* newname must *not* be a stream name. */
7059 if (newname[0] == ':') {
7060 return NT_STATUS_NOT_SUPPORTED;
7064 * Strip off the last component (filename) of the path passed
7065 * in.
7067 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7068 if (!base_name) {
7069 return NT_STATUS_NO_MEMORY;
7071 p = strrchr_m(base_name, '/');
7072 if (p) {
7073 p[1] = '\0';
7074 } else {
7075 base_name = talloc_strdup(ctx, "");
7076 if (!base_name) {
7077 return NT_STATUS_NO_MEMORY;
7080 /* Append the new name. */
7081 base_name = talloc_asprintf_append(base_name,
7082 "%s",
7083 newname);
7084 if (!base_name) {
7085 return NT_STATUS_NO_MEMORY;
7088 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7089 ucf_flags);
7091 /* If an error we expect this to be
7092 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7094 if (!NT_STATUS_IS_OK(status)) {
7095 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7096 status)) {
7097 goto out;
7099 /* Create an smb_fname to call rename_internals_fsp() */
7100 smb_fname_dst = synthetic_smb_fname(ctx,
7101 base_name,
7102 NULL,
7103 NULL,
7104 smb_fname_src->flags);
7105 if (smb_fname_dst == NULL) {
7106 status = NT_STATUS_NO_MEMORY;
7107 goto out;
7112 if (fsp) {
7113 DEBUG(10,("smb_file_rename_information: "
7114 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7115 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7116 smb_fname_str_dbg(smb_fname_dst)));
7117 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7118 overwrite);
7119 } else {
7120 DEBUG(10,("smb_file_rename_information: "
7121 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7122 smb_fname_str_dbg(smb_fname_src),
7123 smb_fname_str_dbg(smb_fname_dst)));
7124 status = rename_internals(ctx, conn, req, smb_fname_src,
7125 smb_fname_dst, 0, overwrite, false,
7126 dest_has_wcard,
7127 FILE_WRITE_ATTRIBUTES);
7129 out:
7130 TALLOC_FREE(smb_fname_dst);
7131 return status;
7134 /****************************************************************************
7135 Deal with SMB_SET_POSIX_ACL.
7136 ****************************************************************************/
7138 #if defined(HAVE_POSIX_ACLS)
7139 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7140 const char *pdata,
7141 int total_data,
7142 files_struct *fsp,
7143 const struct smb_filename *smb_fname)
7145 uint16_t posix_acl_version;
7146 uint16_t num_file_acls;
7147 uint16_t num_def_acls;
7148 bool valid_file_acls = True;
7149 bool valid_def_acls = True;
7150 NTSTATUS status;
7152 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7153 return NT_STATUS_INVALID_PARAMETER;
7155 posix_acl_version = SVAL(pdata,0);
7156 num_file_acls = SVAL(pdata,2);
7157 num_def_acls = SVAL(pdata,4);
7159 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7160 valid_file_acls = False;
7161 num_file_acls = 0;
7164 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7165 valid_def_acls = False;
7166 num_def_acls = 0;
7169 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7170 return NT_STATUS_INVALID_PARAMETER;
7173 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7174 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7175 return NT_STATUS_INVALID_PARAMETER;
7178 status = refuse_symlink(conn, fsp, smb_fname);
7179 if (!NT_STATUS_IS_OK(status)) {
7180 return status;
7183 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7184 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7185 (unsigned int)num_file_acls,
7186 (unsigned int)num_def_acls));
7188 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7189 smb_fname, num_file_acls,
7190 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7191 return map_nt_error_from_unix(errno);
7194 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7195 smb_fname, num_def_acls,
7196 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7197 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7198 return map_nt_error_from_unix(errno);
7200 return NT_STATUS_OK;
7202 #endif
7204 /****************************************************************************
7205 Deal with SMB_SET_POSIX_LOCK.
7206 ****************************************************************************/
7208 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7209 struct smb_request *req,
7210 const char *pdata,
7211 int total_data,
7212 files_struct *fsp)
7214 uint64_t count;
7215 uint64_t offset;
7216 uint64_t smblctx;
7217 bool blocking_lock = False;
7218 enum brl_type lock_type;
7220 NTSTATUS status = NT_STATUS_OK;
7222 if (fsp == NULL || fsp->fh->fd == -1) {
7223 return NT_STATUS_INVALID_HANDLE;
7226 if (total_data != POSIX_LOCK_DATA_SIZE) {
7227 return NT_STATUS_INVALID_PARAMETER;
7230 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7231 case POSIX_LOCK_TYPE_READ:
7232 lock_type = READ_LOCK;
7233 break;
7234 case POSIX_LOCK_TYPE_WRITE:
7235 /* Return the right POSIX-mappable error code for files opened read-only. */
7236 if (!fsp->can_write) {
7237 return NT_STATUS_INVALID_HANDLE;
7239 lock_type = WRITE_LOCK;
7240 break;
7241 case POSIX_LOCK_TYPE_UNLOCK:
7242 lock_type = UNLOCK_LOCK;
7243 break;
7244 default:
7245 return NT_STATUS_INVALID_PARAMETER;
7248 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7249 blocking_lock = False;
7250 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7251 blocking_lock = True;
7252 } else {
7253 return NT_STATUS_INVALID_PARAMETER;
7256 if (!lp_blocking_locks(SNUM(conn))) {
7257 blocking_lock = False;
7260 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7261 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7262 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7263 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7264 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7266 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7267 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7268 fsp_str_dbg(fsp),
7269 (unsigned int)lock_type,
7270 (unsigned long long)smblctx,
7271 (double)count,
7272 (double)offset ));
7274 if (lock_type == UNLOCK_LOCK) {
7275 status = do_unlock(req->sconn->msg_ctx,
7276 fsp,
7277 smblctx,
7278 count,
7279 offset,
7280 POSIX_LOCK);
7281 } else {
7282 uint64_t block_smblctx;
7284 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7285 fsp,
7286 smblctx,
7287 count,
7288 offset,
7289 lock_type,
7290 POSIX_LOCK,
7291 blocking_lock,
7292 &status,
7293 &block_smblctx);
7295 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7297 * A blocking lock was requested. Package up
7298 * this smb into a queued request and push it
7299 * onto the blocking lock queue.
7301 if(push_blocking_lock_request(br_lck,
7302 req,
7303 fsp,
7304 -1, /* infinite timeout. */
7306 smblctx,
7307 lock_type,
7308 POSIX_LOCK,
7309 offset,
7310 count,
7311 block_smblctx)) {
7312 TALLOC_FREE(br_lck);
7313 return status;
7316 TALLOC_FREE(br_lck);
7319 return status;
7322 /****************************************************************************
7323 Deal with SMB_SET_FILE_BASIC_INFO.
7324 ****************************************************************************/
7326 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7327 const char *pdata,
7328 int total_data,
7329 files_struct *fsp,
7330 const struct smb_filename *smb_fname)
7332 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7333 struct smb_file_time ft;
7334 uint32_t dosmode = 0;
7335 NTSTATUS status = NT_STATUS_OK;
7337 ZERO_STRUCT(ft);
7339 if (total_data < 36) {
7340 return NT_STATUS_INVALID_PARAMETER;
7343 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7344 if (!NT_STATUS_IS_OK(status)) {
7345 return status;
7348 /* Set the attributes */
7349 dosmode = IVAL(pdata,32);
7350 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7351 if (!NT_STATUS_IS_OK(status)) {
7352 return status;
7355 /* create time */
7356 ft.create_time = interpret_long_date(pdata);
7358 /* access time */
7359 ft.atime = interpret_long_date(pdata+8);
7361 /* write time. */
7362 ft.mtime = interpret_long_date(pdata+16);
7364 /* change time. */
7365 ft.ctime = interpret_long_date(pdata+24);
7367 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7368 smb_fname_str_dbg(smb_fname)));
7370 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7371 true);
7374 /****************************************************************************
7375 Deal with SMB_INFO_STANDARD.
7376 ****************************************************************************/
7378 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7379 const char *pdata,
7380 int total_data,
7381 files_struct *fsp,
7382 const struct smb_filename *smb_fname)
7384 NTSTATUS status;
7385 struct smb_file_time ft;
7387 ZERO_STRUCT(ft);
7389 if (total_data < 12) {
7390 return NT_STATUS_INVALID_PARAMETER;
7393 /* create time */
7394 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7395 /* access time */
7396 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7397 /* write time */
7398 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7400 DEBUG(10,("smb_set_info_standard: file %s\n",
7401 smb_fname_str_dbg(smb_fname)));
7403 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7404 if (!NT_STATUS_IS_OK(status)) {
7405 return status;
7408 return smb_set_file_time(conn,
7409 fsp,
7410 smb_fname,
7411 &ft,
7412 true);
7415 /****************************************************************************
7416 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7417 ****************************************************************************/
7419 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7420 struct smb_request *req,
7421 const char *pdata,
7422 int total_data,
7423 files_struct *fsp,
7424 struct smb_filename *smb_fname)
7426 uint64_t allocation_size = 0;
7427 NTSTATUS status = NT_STATUS_OK;
7428 files_struct *new_fsp = NULL;
7430 if (!VALID_STAT(smb_fname->st)) {
7431 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7434 if (total_data < 8) {
7435 return NT_STATUS_INVALID_PARAMETER;
7438 allocation_size = (uint64_t)IVAL(pdata,0);
7439 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7440 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7441 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7442 (double)allocation_size));
7444 if (allocation_size) {
7445 allocation_size = smb_roundup(conn, allocation_size);
7448 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7449 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7450 (double)allocation_size));
7452 if (fsp && fsp->fh->fd != -1) {
7453 /* Open file handle. */
7454 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7455 return NT_STATUS_ACCESS_DENIED;
7458 /* Only change if needed. */
7459 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7460 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7461 return map_nt_error_from_unix(errno);
7464 /* But always update the time. */
7466 * This is equivalent to a write. Ensure it's seen immediately
7467 * if there are no pending writes.
7469 trigger_write_time_update_immediate(fsp);
7470 return NT_STATUS_OK;
7473 /* Pathname or stat or directory file. */
7474 status = SMB_VFS_CREATE_FILE(
7475 conn, /* conn */
7476 req, /* req */
7477 0, /* root_dir_fid */
7478 smb_fname, /* fname */
7479 FILE_WRITE_DATA, /* access_mask */
7480 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7481 FILE_SHARE_DELETE),
7482 FILE_OPEN, /* create_disposition*/
7483 0, /* create_options */
7484 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7485 0, /* oplock_request */
7486 NULL, /* lease */
7487 0, /* allocation_size */
7488 0, /* private_flags */
7489 NULL, /* sd */
7490 NULL, /* ea_list */
7491 &new_fsp, /* result */
7492 NULL, /* pinfo */
7493 NULL, NULL); /* create context */
7495 if (!NT_STATUS_IS_OK(status)) {
7496 /* NB. We check for open_was_deferred in the caller. */
7497 return status;
7500 /* Only change if needed. */
7501 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7502 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7503 status = map_nt_error_from_unix(errno);
7504 close_file(req, new_fsp, NORMAL_CLOSE);
7505 return status;
7509 /* Changing the allocation size should set the last mod time. */
7511 * This is equivalent to a write. Ensure it's seen immediately
7512 * if there are no pending writes.
7514 trigger_write_time_update_immediate(new_fsp);
7515 close_file(req, new_fsp, NORMAL_CLOSE);
7516 return NT_STATUS_OK;
7519 /****************************************************************************
7520 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7521 ****************************************************************************/
7523 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7524 struct smb_request *req,
7525 const char *pdata,
7526 int total_data,
7527 files_struct *fsp,
7528 const struct smb_filename *smb_fname,
7529 bool fail_after_createfile)
7531 off_t size;
7533 if (total_data < 8) {
7534 return NT_STATUS_INVALID_PARAMETER;
7537 size = IVAL(pdata,0);
7538 size |= (((off_t)IVAL(pdata,4)) << 32);
7539 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7540 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7541 (double)size));
7543 return smb_set_file_size(conn, req,
7544 fsp,
7545 smb_fname,
7546 &smb_fname->st,
7547 size,
7548 fail_after_createfile);
7551 /****************************************************************************
7552 Allow a UNIX info mknod.
7553 ****************************************************************************/
7555 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7556 const char *pdata,
7557 int total_data,
7558 const struct smb_filename *smb_fname)
7560 uint32_t file_type = IVAL(pdata,56);
7561 #if defined(HAVE_MAKEDEV)
7562 uint32_t dev_major = IVAL(pdata,60);
7563 uint32_t dev_minor = IVAL(pdata,68);
7564 #endif
7565 SMB_DEV_T dev = (SMB_DEV_T)0;
7566 uint32_t raw_unixmode = IVAL(pdata,84);
7567 NTSTATUS status;
7568 mode_t unixmode;
7570 if (total_data < 100) {
7571 return NT_STATUS_INVALID_PARAMETER;
7574 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7575 PERM_NEW_FILE, &unixmode);
7576 if (!NT_STATUS_IS_OK(status)) {
7577 return status;
7580 #if defined(HAVE_MAKEDEV)
7581 dev = makedev(dev_major, dev_minor);
7582 #endif
7584 switch (file_type) {
7585 #if defined(S_IFIFO)
7586 case UNIX_TYPE_FIFO:
7587 unixmode |= S_IFIFO;
7588 break;
7589 #endif
7590 #if defined(S_IFSOCK)
7591 case UNIX_TYPE_SOCKET:
7592 unixmode |= S_IFSOCK;
7593 break;
7594 #endif
7595 #if defined(S_IFCHR)
7596 case UNIX_TYPE_CHARDEV:
7597 unixmode |= S_IFCHR;
7598 break;
7599 #endif
7600 #if defined(S_IFBLK)
7601 case UNIX_TYPE_BLKDEV:
7602 unixmode |= S_IFBLK;
7603 break;
7604 #endif
7605 default:
7606 return NT_STATUS_INVALID_PARAMETER;
7609 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7610 "%.0f mode 0%o for file %s\n", (double)dev,
7611 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7613 /* Ok - do the mknod. */
7614 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7615 return map_nt_error_from_unix(errno);
7618 /* If any of the other "set" calls fail we
7619 * don't want to end up with a half-constructed mknod.
7622 if (lp_inherit_permissions(SNUM(conn))) {
7623 char *parent;
7624 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7625 &parent, NULL)) {
7626 return NT_STATUS_NO_MEMORY;
7628 inherit_access_posix_acl(conn, parent, smb_fname,
7629 unixmode);
7630 TALLOC_FREE(parent);
7633 return NT_STATUS_OK;
7636 /****************************************************************************
7637 Deal with SMB_SET_FILE_UNIX_BASIC.
7638 ****************************************************************************/
7640 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7641 struct smb_request *req,
7642 const char *pdata,
7643 int total_data,
7644 files_struct *fsp,
7645 const struct smb_filename *smb_fname)
7647 struct smb_file_time ft;
7648 uint32_t raw_unixmode;
7649 mode_t unixmode;
7650 off_t size = 0;
7651 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7652 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7653 NTSTATUS status = NT_STATUS_OK;
7654 bool delete_on_fail = False;
7655 enum perm_type ptype;
7656 files_struct *all_fsps = NULL;
7657 bool modify_mtime = true;
7658 struct file_id id;
7659 struct smb_filename *smb_fname_tmp = NULL;
7660 SMB_STRUCT_STAT sbuf;
7662 ZERO_STRUCT(ft);
7664 if (total_data < 100) {
7665 return NT_STATUS_INVALID_PARAMETER;
7668 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7669 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7670 size=IVAL(pdata,0); /* first 8 Bytes are size */
7671 size |= (((off_t)IVAL(pdata,4)) << 32);
7674 ft.atime = interpret_long_date(pdata+24); /* access_time */
7675 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7676 set_owner = (uid_t)IVAL(pdata,40);
7677 set_grp = (gid_t)IVAL(pdata,48);
7678 raw_unixmode = IVAL(pdata,84);
7680 if (VALID_STAT(smb_fname->st)) {
7681 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7682 ptype = PERM_EXISTING_DIR;
7683 } else {
7684 ptype = PERM_EXISTING_FILE;
7686 } else {
7687 ptype = PERM_NEW_FILE;
7690 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7691 ptype, &unixmode);
7692 if (!NT_STATUS_IS_OK(status)) {
7693 return status;
7696 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7697 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7698 smb_fname_str_dbg(smb_fname), (double)size,
7699 (unsigned int)set_owner, (unsigned int)set_grp,
7700 (int)raw_unixmode));
7702 sbuf = smb_fname->st;
7704 if (!VALID_STAT(sbuf)) {
7706 * The only valid use of this is to create character and block
7707 * devices, and named pipes. This is deprecated (IMHO) and
7708 * a new info level should be used for mknod. JRA.
7711 status = smb_unix_mknod(conn,
7712 pdata,
7713 total_data,
7714 smb_fname);
7715 if (!NT_STATUS_IS_OK(status)) {
7716 return status;
7719 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7720 if (smb_fname_tmp == NULL) {
7721 return NT_STATUS_NO_MEMORY;
7724 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7725 status = map_nt_error_from_unix(errno);
7726 TALLOC_FREE(smb_fname_tmp);
7727 SMB_VFS_UNLINK(conn, smb_fname);
7728 return status;
7731 sbuf = smb_fname_tmp->st;
7732 smb_fname = smb_fname_tmp;
7734 /* Ensure we don't try and change anything else. */
7735 raw_unixmode = SMB_MODE_NO_CHANGE;
7736 size = get_file_size_stat(&sbuf);
7737 ft.atime = sbuf.st_ex_atime;
7738 ft.mtime = sbuf.st_ex_mtime;
7740 * We continue here as we might want to change the
7741 * owner uid/gid.
7743 delete_on_fail = True;
7746 #if 1
7747 /* Horrible backwards compatibility hack as an old server bug
7748 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7749 * */
7751 if (!size) {
7752 size = get_file_size_stat(&sbuf);
7754 #endif
7757 * Deal with the UNIX specific mode set.
7760 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7761 int ret;
7763 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7764 "setting mode 0%o for file %s\n",
7765 (unsigned int)unixmode,
7766 smb_fname_str_dbg(smb_fname)));
7767 if (fsp && fsp->fh->fd != -1) {
7768 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7769 } else {
7770 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7772 if (ret != 0) {
7773 return map_nt_error_from_unix(errno);
7778 * Deal with the UNIX specific uid set.
7781 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7782 (sbuf.st_ex_uid != set_owner)) {
7783 int ret;
7785 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7786 "changing owner %u for path %s\n",
7787 (unsigned int)set_owner,
7788 smb_fname_str_dbg(smb_fname)));
7790 if (fsp && fsp->fh->fd != -1) {
7791 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7792 } else {
7794 * UNIX extensions calls must always operate
7795 * on symlinks.
7797 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7798 set_owner, (gid_t)-1);
7801 if (ret != 0) {
7802 status = map_nt_error_from_unix(errno);
7803 if (delete_on_fail) {
7804 SMB_VFS_UNLINK(conn, smb_fname);
7806 return status;
7811 * Deal with the UNIX specific gid set.
7814 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7815 (sbuf.st_ex_gid != set_grp)) {
7816 int ret;
7818 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7819 "changing group %u for file %s\n",
7820 (unsigned int)set_grp,
7821 smb_fname_str_dbg(smb_fname)));
7822 if (fsp && fsp->fh->fd != -1) {
7823 ret = SMB_VFS_FCHOWN(fsp, (uid_t)-1, set_grp);
7824 } else {
7826 * UNIX extensions calls must always operate
7827 * on symlinks.
7829 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7830 set_grp);
7832 if (ret != 0) {
7833 status = map_nt_error_from_unix(errno);
7834 if (delete_on_fail) {
7835 SMB_VFS_UNLINK(conn, smb_fname);
7837 return status;
7841 /* Deal with any size changes. */
7843 status = smb_set_file_size(conn, req,
7844 fsp,
7845 smb_fname,
7846 &sbuf,
7847 size,
7848 false);
7849 if (!NT_STATUS_IS_OK(status)) {
7850 return status;
7853 /* Deal with any time changes. */
7854 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7855 /* No change, don't cancel anything. */
7856 return status;
7859 id = vfs_file_id_from_sbuf(conn, &sbuf);
7860 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7861 all_fsps = file_find_di_next(all_fsps)) {
7863 * We're setting the time explicitly for UNIX.
7864 * Cancel any pending changes over all handles.
7866 all_fsps->update_write_time_on_close = false;
7867 TALLOC_FREE(all_fsps->update_write_time_event);
7871 * Override the "setting_write_time"
7872 * parameter here as it almost does what
7873 * we need. Just remember if we modified
7874 * mtime and send the notify ourselves.
7876 if (null_timespec(ft.mtime)) {
7877 modify_mtime = false;
7880 status = smb_set_file_time(conn,
7881 fsp,
7882 smb_fname,
7883 &ft,
7884 false);
7885 if (modify_mtime) {
7886 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7887 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7889 return status;
7892 /****************************************************************************
7893 Deal with SMB_SET_FILE_UNIX_INFO2.
7894 ****************************************************************************/
7896 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7897 struct smb_request *req,
7898 const char *pdata,
7899 int total_data,
7900 files_struct *fsp,
7901 const struct smb_filename *smb_fname)
7903 NTSTATUS status;
7904 uint32_t smb_fflags;
7905 uint32_t smb_fmask;
7907 if (total_data < 116) {
7908 return NT_STATUS_INVALID_PARAMETER;
7911 /* Start by setting all the fields that are common between UNIX_BASIC
7912 * and UNIX_INFO2.
7914 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7915 fsp, smb_fname);
7916 if (!NT_STATUS_IS_OK(status)) {
7917 return status;
7920 smb_fflags = IVAL(pdata, 108);
7921 smb_fmask = IVAL(pdata, 112);
7923 /* NB: We should only attempt to alter the file flags if the client
7924 * sends a non-zero mask.
7926 if (smb_fmask != 0) {
7927 int stat_fflags = 0;
7929 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7930 smb_fmask, &stat_fflags)) {
7931 /* Client asked to alter a flag we don't understand. */
7932 return NT_STATUS_INVALID_PARAMETER;
7935 if (fsp && fsp->fh->fd != -1) {
7936 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7937 return NT_STATUS_NOT_SUPPORTED;
7938 } else {
7939 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7940 stat_fflags) != 0) {
7941 return map_nt_error_from_unix(errno);
7946 /* XXX: need to add support for changing the create_time here. You
7947 * can do this for paths on Darwin with setattrlist(2). The right way
7948 * to hook this up is probably by extending the VFS utimes interface.
7951 return NT_STATUS_OK;
7954 /****************************************************************************
7955 Create a directory with POSIX semantics.
7956 ****************************************************************************/
7958 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7959 struct smb_request *req,
7960 char **ppdata,
7961 int total_data,
7962 struct smb_filename *smb_fname,
7963 int *pdata_return_size)
7965 NTSTATUS status = NT_STATUS_OK;
7966 uint32_t raw_unixmode = 0;
7967 uint32_t mod_unixmode = 0;
7968 mode_t unixmode = (mode_t)0;
7969 files_struct *fsp = NULL;
7970 uint16_t info_level_return = 0;
7971 int info;
7972 char *pdata = *ppdata;
7974 if (total_data < 18) {
7975 return NT_STATUS_INVALID_PARAMETER;
7978 raw_unixmode = IVAL(pdata,8);
7979 /* Next 4 bytes are not yet defined. */
7981 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7982 PERM_NEW_DIR, &unixmode);
7983 if (!NT_STATUS_IS_OK(status)) {
7984 return status;
7987 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7989 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7990 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7992 status = SMB_VFS_CREATE_FILE(
7993 conn, /* conn */
7994 req, /* req */
7995 0, /* root_dir_fid */
7996 smb_fname, /* fname */
7997 FILE_READ_ATTRIBUTES, /* access_mask */
7998 FILE_SHARE_NONE, /* share_access */
7999 FILE_CREATE, /* create_disposition*/
8000 FILE_DIRECTORY_FILE, /* create_options */
8001 mod_unixmode, /* file_attributes */
8002 0, /* oplock_request */
8003 NULL, /* lease */
8004 0, /* allocation_size */
8005 0, /* private_flags */
8006 NULL, /* sd */
8007 NULL, /* ea_list */
8008 &fsp, /* result */
8009 &info, /* pinfo */
8010 NULL, NULL); /* create context */
8012 if (NT_STATUS_IS_OK(status)) {
8013 close_file(req, fsp, NORMAL_CLOSE);
8016 info_level_return = SVAL(pdata,16);
8018 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8019 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8020 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8021 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8022 } else {
8023 *pdata_return_size = 12;
8026 /* Realloc the data size */
8027 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8028 if (*ppdata == NULL) {
8029 *pdata_return_size = 0;
8030 return NT_STATUS_NO_MEMORY;
8032 pdata = *ppdata;
8034 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8035 SSVAL(pdata,2,0); /* No fnum. */
8036 SIVAL(pdata,4,info); /* Was directory created. */
8038 switch (info_level_return) {
8039 case SMB_QUERY_FILE_UNIX_BASIC:
8040 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8041 SSVAL(pdata,10,0); /* Padding. */
8042 store_file_unix_basic(conn, pdata + 12, fsp,
8043 &smb_fname->st);
8044 break;
8045 case SMB_QUERY_FILE_UNIX_INFO2:
8046 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8047 SSVAL(pdata,10,0); /* Padding. */
8048 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8049 &smb_fname->st);
8050 break;
8051 default:
8052 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8053 SSVAL(pdata,10,0); /* Padding. */
8054 break;
8057 return status;
8060 /****************************************************************************
8061 Open/Create a file with POSIX semantics.
8062 ****************************************************************************/
8064 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8065 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8067 static NTSTATUS smb_posix_open(connection_struct *conn,
8068 struct smb_request *req,
8069 char **ppdata,
8070 int total_data,
8071 struct smb_filename *smb_fname,
8072 int *pdata_return_size)
8074 bool extended_oplock_granted = False;
8075 char *pdata = *ppdata;
8076 uint32_t flags = 0;
8077 uint32_t wire_open_mode = 0;
8078 uint32_t raw_unixmode = 0;
8079 uint32_t mod_unixmode = 0;
8080 uint32_t create_disp = 0;
8081 uint32_t access_mask = 0;
8082 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8083 NTSTATUS status = NT_STATUS_OK;
8084 mode_t unixmode = (mode_t)0;
8085 files_struct *fsp = NULL;
8086 int oplock_request = 0;
8087 int info = 0;
8088 uint16_t info_level_return = 0;
8090 if (total_data < 18) {
8091 return NT_STATUS_INVALID_PARAMETER;
8094 flags = IVAL(pdata,0);
8095 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8096 if (oplock_request) {
8097 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8100 wire_open_mode = IVAL(pdata,4);
8102 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8103 return smb_posix_mkdir(conn, req,
8104 ppdata,
8105 total_data,
8106 smb_fname,
8107 pdata_return_size);
8110 switch (wire_open_mode & SMB_ACCMODE) {
8111 case SMB_O_RDONLY:
8112 access_mask = SMB_O_RDONLY_MAPPING;
8113 break;
8114 case SMB_O_WRONLY:
8115 access_mask = SMB_O_WRONLY_MAPPING;
8116 break;
8117 case SMB_O_RDWR:
8118 access_mask = (SMB_O_RDONLY_MAPPING|
8119 SMB_O_WRONLY_MAPPING);
8120 break;
8121 default:
8122 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8123 (unsigned int)wire_open_mode ));
8124 return NT_STATUS_INVALID_PARAMETER;
8127 wire_open_mode &= ~SMB_ACCMODE;
8129 /* First take care of O_CREAT|O_EXCL interactions. */
8130 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8131 case (SMB_O_CREAT | SMB_O_EXCL):
8132 /* File exists fail. File not exist create. */
8133 create_disp = FILE_CREATE;
8134 break;
8135 case SMB_O_CREAT:
8136 /* File exists open. File not exist create. */
8137 create_disp = FILE_OPEN_IF;
8138 break;
8139 case SMB_O_EXCL:
8140 /* O_EXCL on its own without O_CREAT is undefined.
8141 We deliberately ignore it as some versions of
8142 Linux CIFSFS can send a bare O_EXCL on the
8143 wire which other filesystems in the kernel
8144 ignore. See bug 9519 for details. */
8146 /* Fallthrough. */
8148 case 0:
8149 /* File exists open. File not exist fail. */
8150 create_disp = FILE_OPEN;
8151 break;
8152 default:
8153 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8154 (unsigned int)wire_open_mode ));
8155 return NT_STATUS_INVALID_PARAMETER;
8158 /* Next factor in the effects of O_TRUNC. */
8159 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8161 if (wire_open_mode & SMB_O_TRUNC) {
8162 switch (create_disp) {
8163 case FILE_CREATE:
8164 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8165 /* Leave create_disp alone as
8166 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8168 /* File exists fail. File not exist create. */
8169 break;
8170 case FILE_OPEN_IF:
8171 /* SMB_O_CREAT | SMB_O_TRUNC */
8172 /* File exists overwrite. File not exist create. */
8173 create_disp = FILE_OVERWRITE_IF;
8174 break;
8175 case FILE_OPEN:
8176 /* SMB_O_TRUNC */
8177 /* File exists overwrite. File not exist fail. */
8178 create_disp = FILE_OVERWRITE;
8179 break;
8180 default:
8181 /* Cannot get here. */
8182 smb_panic("smb_posix_open: logic error");
8183 return NT_STATUS_INVALID_PARAMETER;
8187 raw_unixmode = IVAL(pdata,8);
8188 /* Next 4 bytes are not yet defined. */
8190 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8191 (VALID_STAT(smb_fname->st) ?
8192 PERM_EXISTING_FILE : PERM_NEW_FILE),
8193 &unixmode);
8195 if (!NT_STATUS_IS_OK(status)) {
8196 return status;
8199 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8201 if (wire_open_mode & SMB_O_SYNC) {
8202 create_options |= FILE_WRITE_THROUGH;
8204 if (wire_open_mode & SMB_O_APPEND) {
8205 access_mask |= FILE_APPEND_DATA;
8207 if (wire_open_mode & SMB_O_DIRECT) {
8208 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8211 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8212 VALID_STAT_OF_DIR(smb_fname->st)) {
8213 if (access_mask != SMB_O_RDONLY_MAPPING) {
8214 return NT_STATUS_FILE_IS_A_DIRECTORY;
8216 create_options &= ~FILE_NON_DIRECTORY_FILE;
8217 create_options |= FILE_DIRECTORY_FILE;
8220 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8221 smb_fname_str_dbg(smb_fname),
8222 (unsigned int)wire_open_mode,
8223 (unsigned int)unixmode ));
8225 status = SMB_VFS_CREATE_FILE(
8226 conn, /* conn */
8227 req, /* req */
8228 0, /* root_dir_fid */
8229 smb_fname, /* fname */
8230 access_mask, /* access_mask */
8231 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8232 FILE_SHARE_DELETE),
8233 create_disp, /* create_disposition*/
8234 create_options, /* create_options */
8235 mod_unixmode, /* file_attributes */
8236 oplock_request, /* oplock_request */
8237 NULL, /* lease */
8238 0, /* allocation_size */
8239 0, /* private_flags */
8240 NULL, /* sd */
8241 NULL, /* ea_list */
8242 &fsp, /* result */
8243 &info, /* pinfo */
8244 NULL, NULL); /* create context */
8246 if (!NT_STATUS_IS_OK(status)) {
8247 return status;
8250 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8251 extended_oplock_granted = True;
8254 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8255 extended_oplock_granted = True;
8258 info_level_return = SVAL(pdata,16);
8260 /* Allocate the correct return size. */
8262 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8263 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8264 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8265 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8266 } else {
8267 *pdata_return_size = 12;
8270 /* Realloc the data size */
8271 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8272 if (*ppdata == NULL) {
8273 close_file(req, fsp, ERROR_CLOSE);
8274 *pdata_return_size = 0;
8275 return NT_STATUS_NO_MEMORY;
8277 pdata = *ppdata;
8279 if (extended_oplock_granted) {
8280 if (flags & REQUEST_BATCH_OPLOCK) {
8281 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8282 } else {
8283 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8285 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8286 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8287 } else {
8288 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8291 SSVAL(pdata,2,fsp->fnum);
8292 SIVAL(pdata,4,info); /* Was file created etc. */
8294 switch (info_level_return) {
8295 case SMB_QUERY_FILE_UNIX_BASIC:
8296 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8297 SSVAL(pdata,10,0); /* padding. */
8298 store_file_unix_basic(conn, pdata + 12, fsp,
8299 &smb_fname->st);
8300 break;
8301 case SMB_QUERY_FILE_UNIX_INFO2:
8302 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8303 SSVAL(pdata,10,0); /* padding. */
8304 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8305 &smb_fname->st);
8306 break;
8307 default:
8308 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8309 SSVAL(pdata,10,0); /* padding. */
8310 break;
8312 return NT_STATUS_OK;
8315 /****************************************************************************
8316 Delete a file with POSIX semantics.
8317 ****************************************************************************/
8319 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8320 struct smb_request *req,
8321 const char *pdata,
8322 int total_data,
8323 struct smb_filename *smb_fname)
8325 struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
8326 NTSTATUS status = NT_STATUS_OK;
8327 files_struct *fsp = NULL;
8328 uint16_t flags = 0;
8329 char del = 1;
8330 int info = 0;
8331 int create_options = 0;
8332 struct share_mode_lock *lck = NULL;
8333 bool other_nonposix_opens;
8335 if (total_data < 2) {
8336 return NT_STATUS_INVALID_PARAMETER;
8339 flags = SVAL(pdata,0);
8341 if (!VALID_STAT(smb_fname->st)) {
8342 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8345 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8346 !VALID_STAT_OF_DIR(smb_fname->st)) {
8347 return NT_STATUS_NOT_A_DIRECTORY;
8350 DEBUG(10,("smb_posix_unlink: %s %s\n",
8351 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8352 smb_fname_str_dbg(smb_fname)));
8354 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8355 create_options |= FILE_DIRECTORY_FILE;
8358 status = SMB_VFS_CREATE_FILE(
8359 conn, /* conn */
8360 req, /* req */
8361 0, /* root_dir_fid */
8362 smb_fname, /* fname */
8363 DELETE_ACCESS, /* access_mask */
8364 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8365 FILE_SHARE_DELETE),
8366 FILE_OPEN, /* create_disposition*/
8367 create_options, /* create_options */
8368 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8369 0, /* oplock_request */
8370 NULL, /* lease */
8371 0, /* allocation_size */
8372 0, /* private_flags */
8373 NULL, /* sd */
8374 NULL, /* ea_list */
8375 &fsp, /* result */
8376 &info, /* pinfo */
8377 NULL, NULL); /* create context */
8379 if (!NT_STATUS_IS_OK(status)) {
8380 return status;
8384 * Don't lie to client. If we can't really delete due to
8385 * non-POSIX opens return SHARING_VIOLATION.
8388 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8389 if (lck == NULL) {
8390 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8391 "lock for file %s\n", fsp_str_dbg(fsp)));
8392 close_file(req, fsp, NORMAL_CLOSE);
8393 return NT_STATUS_INVALID_PARAMETER;
8396 other_nonposix_opens = has_other_nonposix_opens(lck, fsp, self);
8397 if (other_nonposix_opens) {
8398 /* Fail with sharing violation. */
8399 TALLOC_FREE(lck);
8400 close_file(req, fsp, NORMAL_CLOSE);
8401 return NT_STATUS_SHARING_VIOLATION;
8405 * Set the delete on close.
8407 status = smb_set_file_disposition_info(conn,
8408 &del,
8410 fsp,
8411 smb_fname);
8413 TALLOC_FREE(lck);
8415 if (!NT_STATUS_IS_OK(status)) {
8416 close_file(req, fsp, NORMAL_CLOSE);
8417 return status;
8419 return close_file(req, fsp, NORMAL_CLOSE);
8422 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8423 struct smb_request *req,
8424 TALLOC_CTX *mem_ctx,
8425 uint16_t info_level,
8426 files_struct *fsp,
8427 struct smb_filename *smb_fname,
8428 char **ppdata, int total_data,
8429 int *ret_data_size)
8431 char *pdata = *ppdata;
8432 NTSTATUS status = NT_STATUS_OK;
8433 int data_return_size = 0;
8435 *ret_data_size = 0;
8437 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8438 return NT_STATUS_INVALID_LEVEL;
8441 if (!CAN_WRITE(conn)) {
8442 /* Allow POSIX opens. The open path will deny
8443 * any non-readonly opens. */
8444 if (info_level != SMB_POSIX_PATH_OPEN) {
8445 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8449 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8450 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8451 fsp_fnum_dbg(fsp),
8452 info_level, total_data));
8454 switch (info_level) {
8456 case SMB_INFO_STANDARD:
8458 status = smb_set_info_standard(conn,
8459 pdata,
8460 total_data,
8461 fsp,
8462 smb_fname);
8463 break;
8466 case SMB_INFO_SET_EA:
8468 status = smb_info_set_ea(conn,
8469 pdata,
8470 total_data,
8471 fsp,
8472 smb_fname);
8473 break;
8476 case SMB_SET_FILE_BASIC_INFO:
8477 case SMB_FILE_BASIC_INFORMATION:
8479 status = smb_set_file_basic_info(conn,
8480 pdata,
8481 total_data,
8482 fsp,
8483 smb_fname);
8484 break;
8487 case SMB_FILE_ALLOCATION_INFORMATION:
8488 case SMB_SET_FILE_ALLOCATION_INFO:
8490 status = smb_set_file_allocation_info(conn, req,
8491 pdata,
8492 total_data,
8493 fsp,
8494 smb_fname);
8495 break;
8498 case SMB_FILE_END_OF_FILE_INFORMATION:
8499 case SMB_SET_FILE_END_OF_FILE_INFO:
8502 * XP/Win7 both fail after the createfile with
8503 * SMB_SET_FILE_END_OF_FILE_INFO but not
8504 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8505 * The level is known here, so pass it down
8506 * appropriately.
8508 bool should_fail =
8509 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8511 status = smb_set_file_end_of_file_info(conn, req,
8512 pdata,
8513 total_data,
8514 fsp,
8515 smb_fname,
8516 should_fail);
8517 break;
8520 case SMB_FILE_DISPOSITION_INFORMATION:
8521 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8523 #if 0
8524 /* JRA - We used to just ignore this on a path ?
8525 * Shouldn't this be invalid level on a pathname
8526 * based call ?
8528 if (tran_call != TRANSACT2_SETFILEINFO) {
8529 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8531 #endif
8532 status = smb_set_file_disposition_info(conn,
8533 pdata,
8534 total_data,
8535 fsp,
8536 smb_fname);
8537 break;
8540 case SMB_FILE_POSITION_INFORMATION:
8542 status = smb_file_position_information(conn,
8543 pdata,
8544 total_data,
8545 fsp);
8546 break;
8549 case SMB_FILE_FULL_EA_INFORMATION:
8551 status = smb_set_file_full_ea_info(conn,
8552 pdata,
8553 total_data,
8554 fsp);
8555 break;
8558 /* From tridge Samba4 :
8559 * MODE_INFORMATION in setfileinfo (I have no
8560 * idea what "mode information" on a file is - it takes a value of 0,
8561 * 2, 4 or 6. What could it be?).
8564 case SMB_FILE_MODE_INFORMATION:
8566 status = smb_file_mode_information(conn,
8567 pdata,
8568 total_data);
8569 break;
8572 /* [MS-SMB2] 3.3.5.21.1 states we MUST fail with STATUS_NOT_SUPPORTED. */
8573 case SMB_FILE_VALID_DATA_LENGTH_INFORMATION:
8574 case SMB_FILE_SHORT_NAME_INFORMATION:
8575 return NT_STATUS_NOT_SUPPORTED;
8578 * CIFS UNIX extensions.
8581 case SMB_SET_FILE_UNIX_BASIC:
8583 status = smb_set_file_unix_basic(conn, req,
8584 pdata,
8585 total_data,
8586 fsp,
8587 smb_fname);
8588 break;
8591 case SMB_SET_FILE_UNIX_INFO2:
8593 status = smb_set_file_unix_info2(conn, req,
8594 pdata,
8595 total_data,
8596 fsp,
8597 smb_fname);
8598 break;
8601 case SMB_SET_FILE_UNIX_LINK:
8603 if (fsp) {
8604 /* We must have a pathname for this. */
8605 return NT_STATUS_INVALID_LEVEL;
8607 status = smb_set_file_unix_link(conn, req, pdata,
8608 total_data, smb_fname);
8609 break;
8612 case SMB_SET_FILE_UNIX_HLINK:
8614 if (fsp) {
8615 /* We must have a pathname for this. */
8616 return NT_STATUS_INVALID_LEVEL;
8618 status = smb_set_file_unix_hlink(conn, req,
8619 pdata, total_data,
8620 smb_fname);
8621 break;
8624 case SMB_FILE_RENAME_INFORMATION:
8626 status = smb_file_rename_information(conn, req,
8627 pdata, total_data,
8628 fsp, smb_fname);
8629 break;
8632 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8634 /* SMB2 rename information. */
8635 status = smb2_file_rename_information(conn, req,
8636 pdata, total_data,
8637 fsp, smb_fname);
8638 break;
8641 case SMB_FILE_LINK_INFORMATION:
8643 status = smb_file_link_information(conn, req,
8644 pdata, total_data,
8645 fsp, smb_fname);
8646 break;
8649 #if defined(HAVE_POSIX_ACLS)
8650 case SMB_SET_POSIX_ACL:
8652 status = smb_set_posix_acl(conn,
8653 pdata,
8654 total_data,
8655 fsp,
8656 smb_fname);
8657 break;
8659 #endif
8661 case SMB_SET_POSIX_LOCK:
8663 if (!fsp) {
8664 return NT_STATUS_INVALID_LEVEL;
8666 status = smb_set_posix_lock(conn, req,
8667 pdata, total_data, fsp);
8668 break;
8671 case SMB_POSIX_PATH_OPEN:
8673 if (fsp) {
8674 /* We must have a pathname for this. */
8675 return NT_STATUS_INVALID_LEVEL;
8678 status = smb_posix_open(conn, req,
8679 ppdata,
8680 total_data,
8681 smb_fname,
8682 &data_return_size);
8683 break;
8686 case SMB_POSIX_PATH_UNLINK:
8688 if (fsp) {
8689 /* We must have a pathname for this. */
8690 return NT_STATUS_INVALID_LEVEL;
8693 status = smb_posix_unlink(conn, req,
8694 pdata,
8695 total_data,
8696 smb_fname);
8697 break;
8700 default:
8701 return NT_STATUS_INVALID_LEVEL;
8704 if (!NT_STATUS_IS_OK(status)) {
8705 return status;
8708 *ret_data_size = data_return_size;
8709 return NT_STATUS_OK;
8712 /****************************************************************************
8713 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8714 ****************************************************************************/
8716 static void call_trans2setfilepathinfo(connection_struct *conn,
8717 struct smb_request *req,
8718 unsigned int tran_call,
8719 char **pparams, int total_params,
8720 char **ppdata, int total_data,
8721 unsigned int max_data_bytes)
8723 char *params = *pparams;
8724 char *pdata = *ppdata;
8725 uint16_t info_level;
8726 struct smb_filename *smb_fname = NULL;
8727 files_struct *fsp = NULL;
8728 NTSTATUS status = NT_STATUS_OK;
8729 int data_return_size = 0;
8731 if (!params) {
8732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8733 return;
8736 if (tran_call == TRANSACT2_SETFILEINFO) {
8737 if (total_params < 4) {
8738 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8739 return;
8742 fsp = file_fsp(req, SVAL(params,0));
8743 /* Basic check for non-null fsp. */
8744 if (!check_fsp_open(conn, req, fsp)) {
8745 return;
8747 info_level = SVAL(params,2);
8749 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8750 if (smb_fname == NULL) {
8751 reply_nterror(req, NT_STATUS_NO_MEMORY);
8752 return;
8755 if(fsp->fh->fd == -1) {
8757 * This is actually a SETFILEINFO on a directory
8758 * handle (returned from an NT SMB). NT5.0 seems
8759 * to do this call. JRA.
8761 if (INFO_LEVEL_IS_UNIX(info_level)) {
8762 /* Always do lstat for UNIX calls. */
8763 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8764 DEBUG(3,("call_trans2setfilepathinfo: "
8765 "SMB_VFS_LSTAT of %s failed "
8766 "(%s)\n",
8767 smb_fname_str_dbg(smb_fname),
8768 strerror(errno)));
8769 reply_nterror(req, map_nt_error_from_unix(errno));
8770 return;
8772 } else {
8773 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8774 DEBUG(3,("call_trans2setfilepathinfo: "
8775 "fileinfo of %s failed (%s)\n",
8776 smb_fname_str_dbg(smb_fname),
8777 strerror(errno)));
8778 reply_nterror(req, map_nt_error_from_unix(errno));
8779 return;
8782 } else if (fsp->print_file) {
8784 * Doing a DELETE_ON_CLOSE should cancel a print job.
8786 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8787 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8789 DEBUG(3,("call_trans2setfilepathinfo: "
8790 "Cancelling print job (%s)\n",
8791 fsp_str_dbg(fsp)));
8793 SSVAL(params,0,0);
8794 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8795 *ppdata, 0,
8796 max_data_bytes);
8797 return;
8798 } else {
8799 reply_nterror(req,
8800 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8801 return;
8803 } else {
8805 * Original code - this is an open file.
8807 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8808 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8809 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8810 strerror(errno)));
8811 reply_nterror(req, map_nt_error_from_unix(errno));
8812 return;
8815 } else {
8816 char *fname = NULL;
8817 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8819 /* set path info */
8820 if (total_params < 7) {
8821 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8822 return;
8825 info_level = SVAL(params,0);
8826 if (req->posix_pathnames) {
8827 srvstr_get_path_posix(req,
8828 params,
8829 req->flags2,
8830 &fname,
8831 &params[6],
8832 total_params - 6,
8833 STR_TERMINATE,
8834 &status);
8835 } else {
8836 srvstr_get_path(req,
8837 params,
8838 req->flags2,
8839 &fname,
8840 &params[6],
8841 total_params - 6,
8842 STR_TERMINATE,
8843 &status);
8845 if (!NT_STATUS_IS_OK(status)) {
8846 reply_nterror(req, status);
8847 return;
8850 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8851 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8852 info_level == SMB_FILE_RENAME_INFORMATION ||
8853 info_level == SMB_POSIX_PATH_OPEN ||
8854 info_level == SMB_POSIX_PATH_UNLINK) {
8855 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8858 status = filename_convert(req, conn,
8859 fname,
8860 ucf_flags,
8861 NULL,
8862 NULL,
8863 &smb_fname);
8864 if (!NT_STATUS_IS_OK(status)) {
8865 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8866 reply_botherror(req,
8867 NT_STATUS_PATH_NOT_COVERED,
8868 ERRSRV, ERRbadpath);
8869 return;
8871 reply_nterror(req, status);
8872 return;
8875 if (INFO_LEVEL_IS_UNIX(info_level)) {
8877 * For CIFS UNIX extensions the target name may not exist.
8880 /* Always do lstat for UNIX calls. */
8881 SMB_VFS_LSTAT(conn, smb_fname);
8883 } else if (!VALID_STAT(smb_fname->st) &&
8884 SMB_VFS_STAT(conn, smb_fname)) {
8885 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8886 "%s failed (%s)\n",
8887 smb_fname_str_dbg(smb_fname),
8888 strerror(errno)));
8889 reply_nterror(req, map_nt_error_from_unix(errno));
8890 return;
8894 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8895 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8896 fsp_fnum_dbg(fsp),
8897 info_level,total_data));
8899 /* Realloc the parameter size */
8900 *pparams = (char *)SMB_REALLOC(*pparams,2);
8901 if (*pparams == NULL) {
8902 reply_nterror(req, NT_STATUS_NO_MEMORY);
8903 return;
8905 params = *pparams;
8907 SSVAL(params,0,0);
8909 status = smbd_do_setfilepathinfo(conn, req, req,
8910 info_level,
8911 fsp,
8912 smb_fname,
8913 ppdata, total_data,
8914 &data_return_size);
8915 if (!NT_STATUS_IS_OK(status)) {
8916 if (open_was_deferred(req->xconn, req->mid)) {
8917 /* We have re-scheduled this call. */
8918 return;
8920 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8921 /* We have re-scheduled this call. */
8922 return;
8924 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8925 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8926 ERRSRV, ERRbadpath);
8927 return;
8929 if (info_level == SMB_POSIX_PATH_OPEN) {
8930 reply_openerror(req, status);
8931 return;
8935 * Invalid EA name needs to return 2 param bytes,
8936 * not a zero-length error packet.
8938 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8939 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8940 max_data_bytes);
8941 } else {
8942 reply_nterror(req, status);
8944 return;
8947 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8948 max_data_bytes);
8950 return;
8953 /****************************************************************************
8954 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8955 ****************************************************************************/
8957 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8958 char **pparams, int total_params,
8959 char **ppdata, int total_data,
8960 unsigned int max_data_bytes)
8962 struct smb_filename *smb_dname = NULL;
8963 char *params = *pparams;
8964 char *pdata = *ppdata;
8965 char *directory = NULL;
8966 NTSTATUS status = NT_STATUS_OK;
8967 struct ea_list *ea_list = NULL;
8968 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8969 TALLOC_CTX *ctx = talloc_tos();
8971 if (!CAN_WRITE(conn)) {
8972 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8973 return;
8976 if (total_params < 5) {
8977 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8978 return;
8981 if (req->posix_pathnames) {
8982 srvstr_get_path_posix(ctx,
8983 params,
8984 req->flags2,
8985 &directory,
8986 &params[4],
8987 total_params - 4,
8988 STR_TERMINATE,
8989 &status);
8990 } else {
8991 srvstr_get_path(ctx,
8992 params,
8993 req->flags2,
8994 &directory,
8995 &params[4],
8996 total_params - 4,
8997 STR_TERMINATE,
8998 &status);
9000 if (!NT_STATUS_IS_OK(status)) {
9001 reply_nterror(req, status);
9002 return;
9005 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
9007 status = filename_convert(ctx,
9008 conn,
9009 directory,
9010 ucf_flags,
9011 NULL,
9012 NULL,
9013 &smb_dname);
9015 if (!NT_STATUS_IS_OK(status)) {
9016 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
9017 reply_botherror(req,
9018 NT_STATUS_PATH_NOT_COVERED,
9019 ERRSRV, ERRbadpath);
9020 return;
9022 reply_nterror(req, status);
9023 return;
9027 * OS/2 workplace shell seems to send SET_EA requests of "null"
9028 * length (4 bytes containing IVAL 4).
9029 * They seem to have no effect. Bug #3212. JRA.
9032 if (total_data && (total_data != 4)) {
9033 /* Any data in this call is an EA list. */
9034 if (total_data < 10) {
9035 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9036 goto out;
9039 if (IVAL(pdata,0) > total_data) {
9040 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9041 IVAL(pdata,0), (unsigned int)total_data));
9042 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9043 goto out;
9046 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9047 total_data - 4);
9048 if (!ea_list) {
9049 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9050 goto out;
9053 if (!lp_ea_support(SNUM(conn))) {
9054 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9055 goto out;
9058 /* If total_data == 4 Windows doesn't care what values
9059 * are placed in that field, it just ignores them.
9060 * The System i QNTC IBM SMB client puts bad values here,
9061 * so ignore them. */
9063 status = create_directory(conn, req, smb_dname);
9065 if (!NT_STATUS_IS_OK(status)) {
9066 reply_nterror(req, status);
9067 goto out;
9070 /* Try and set any given EA. */
9071 if (ea_list) {
9072 status = set_ea(conn, NULL, smb_dname, ea_list);
9073 if (!NT_STATUS_IS_OK(status)) {
9074 reply_nterror(req, status);
9075 goto out;
9079 /* Realloc the parameter and data sizes */
9080 *pparams = (char *)SMB_REALLOC(*pparams,2);
9081 if(*pparams == NULL) {
9082 reply_nterror(req, NT_STATUS_NO_MEMORY);
9083 goto out;
9085 params = *pparams;
9087 SSVAL(params,0,0);
9089 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9091 out:
9092 TALLOC_FREE(smb_dname);
9093 return;
9096 /****************************************************************************
9097 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9098 We don't actually do this - we just send a null response.
9099 ****************************************************************************/
9101 static void call_trans2findnotifyfirst(connection_struct *conn,
9102 struct smb_request *req,
9103 char **pparams, int total_params,
9104 char **ppdata, int total_data,
9105 unsigned int max_data_bytes)
9107 char *params = *pparams;
9108 uint16_t info_level;
9110 if (total_params < 6) {
9111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9112 return;
9115 info_level = SVAL(params,4);
9116 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9118 switch (info_level) {
9119 case 1:
9120 case 2:
9121 break;
9122 default:
9123 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9124 return;
9127 /* Realloc the parameter and data sizes */
9128 *pparams = (char *)SMB_REALLOC(*pparams,6);
9129 if (*pparams == NULL) {
9130 reply_nterror(req, NT_STATUS_NO_MEMORY);
9131 return;
9133 params = *pparams;
9135 SSVAL(params,0,fnf_handle);
9136 SSVAL(params,2,0); /* No changes */
9137 SSVAL(params,4,0); /* No EA errors */
9139 fnf_handle++;
9141 if(fnf_handle == 0)
9142 fnf_handle = 257;
9144 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9146 return;
9149 /****************************************************************************
9150 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9151 changes). Currently this does nothing.
9152 ****************************************************************************/
9154 static void call_trans2findnotifynext(connection_struct *conn,
9155 struct smb_request *req,
9156 char **pparams, int total_params,
9157 char **ppdata, int total_data,
9158 unsigned int max_data_bytes)
9160 char *params = *pparams;
9162 DEBUG(3,("call_trans2findnotifynext\n"));
9164 /* Realloc the parameter and data sizes */
9165 *pparams = (char *)SMB_REALLOC(*pparams,4);
9166 if (*pparams == NULL) {
9167 reply_nterror(req, NT_STATUS_NO_MEMORY);
9168 return;
9170 params = *pparams;
9172 SSVAL(params,0,0); /* No changes */
9173 SSVAL(params,2,0); /* No EA errors */
9175 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9177 return;
9180 /****************************************************************************
9181 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9182 ****************************************************************************/
9184 static void call_trans2getdfsreferral(connection_struct *conn,
9185 struct smb_request *req,
9186 char **pparams, int total_params,
9187 char **ppdata, int total_data,
9188 unsigned int max_data_bytes)
9190 char *params = *pparams;
9191 char *pathname = NULL;
9192 int reply_size = 0;
9193 int max_referral_level;
9194 NTSTATUS status = NT_STATUS_OK;
9195 TALLOC_CTX *ctx = talloc_tos();
9197 DEBUG(10,("call_trans2getdfsreferral\n"));
9199 if (total_params < 3) {
9200 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9201 return;
9204 max_referral_level = SVAL(params,0);
9206 if(!lp_host_msdfs()) {
9207 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9208 return;
9211 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9212 total_params - 2, STR_TERMINATE);
9213 if (!pathname) {
9214 reply_nterror(req, NT_STATUS_NOT_FOUND);
9215 return;
9217 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9218 ppdata,&status)) < 0) {
9219 reply_nterror(req, status);
9220 return;
9223 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9224 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9225 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9227 return;
9230 #define LMCAT_SPL 0x53
9231 #define LMFUNC_GETJOBID 0x60
9233 /****************************************************************************
9234 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9235 ****************************************************************************/
9237 static void call_trans2ioctl(connection_struct *conn,
9238 struct smb_request *req,
9239 char **pparams, int total_params,
9240 char **ppdata, int total_data,
9241 unsigned int max_data_bytes)
9243 char *pdata = *ppdata;
9244 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9245 NTSTATUS status;
9246 size_t len = 0;
9248 /* check for an invalid fid before proceeding */
9250 if (!fsp) {
9251 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9252 return;
9255 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9256 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9257 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9258 if (*ppdata == NULL) {
9259 reply_nterror(req, NT_STATUS_NO_MEMORY);
9260 return;
9262 pdata = *ppdata;
9264 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9265 CAN ACCEPT THIS IN UNICODE. JRA. */
9267 /* Job number */
9268 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9270 status = srvstr_push(pdata, req->flags2, pdata + 2,
9271 lp_netbios_name(), 15,
9272 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9273 if (!NT_STATUS_IS_OK(status)) {
9274 reply_nterror(req, status);
9275 return;
9277 status = srvstr_push(pdata, req->flags2, pdata+18,
9278 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9279 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9280 if (!NT_STATUS_IS_OK(status)) {
9281 reply_nterror(req, status);
9282 return;
9284 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9285 max_data_bytes);
9286 return;
9289 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9290 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9293 /****************************************************************************
9294 Reply to a SMBfindclose (stop trans2 directory search).
9295 ****************************************************************************/
9297 void reply_findclose(struct smb_request *req)
9299 int dptr_num;
9300 struct smbd_server_connection *sconn = req->sconn;
9302 START_PROFILE(SMBfindclose);
9304 if (req->wct < 1) {
9305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9306 END_PROFILE(SMBfindclose);
9307 return;
9310 dptr_num = SVALS(req->vwv+0, 0);
9312 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9314 dptr_close(sconn, &dptr_num);
9316 reply_outbuf(req, 0, 0);
9318 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9320 END_PROFILE(SMBfindclose);
9321 return;
9324 /****************************************************************************
9325 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9326 ****************************************************************************/
9328 void reply_findnclose(struct smb_request *req)
9330 int dptr_num;
9332 START_PROFILE(SMBfindnclose);
9334 if (req->wct < 1) {
9335 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9336 END_PROFILE(SMBfindnclose);
9337 return;
9340 dptr_num = SVAL(req->vwv+0, 0);
9342 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9344 /* We never give out valid handles for a
9345 findnotifyfirst - so any dptr_num is ok here.
9346 Just ignore it. */
9348 reply_outbuf(req, 0, 0);
9350 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9352 END_PROFILE(SMBfindnclose);
9353 return;
9356 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9357 struct trans_state *state)
9359 if (get_Protocol() >= PROTOCOL_NT1) {
9360 req->flags2 |= 0x40; /* IS_LONG_NAME */
9361 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9364 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9365 if (state->call != TRANSACT2_QFSINFO &&
9366 state->call != TRANSACT2_SETFSINFO) {
9367 DEBUG(0,("handle_trans2: encryption required "
9368 "with call 0x%x\n",
9369 (unsigned int)state->call));
9370 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9371 return;
9375 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9377 /* Now we must call the relevant TRANS2 function */
9378 switch(state->call) {
9379 case TRANSACT2_OPEN:
9381 START_PROFILE(Trans2_open);
9382 call_trans2open(conn, req,
9383 &state->param, state->total_param,
9384 &state->data, state->total_data,
9385 state->max_data_return);
9386 END_PROFILE(Trans2_open);
9387 break;
9390 case TRANSACT2_FINDFIRST:
9392 START_PROFILE(Trans2_findfirst);
9393 call_trans2findfirst(conn, req,
9394 &state->param, state->total_param,
9395 &state->data, state->total_data,
9396 state->max_data_return);
9397 END_PROFILE(Trans2_findfirst);
9398 break;
9401 case TRANSACT2_FINDNEXT:
9403 START_PROFILE(Trans2_findnext);
9404 call_trans2findnext(conn, req,
9405 &state->param, state->total_param,
9406 &state->data, state->total_data,
9407 state->max_data_return);
9408 END_PROFILE(Trans2_findnext);
9409 break;
9412 case TRANSACT2_QFSINFO:
9414 START_PROFILE(Trans2_qfsinfo);
9415 call_trans2qfsinfo(conn, req,
9416 &state->param, state->total_param,
9417 &state->data, state->total_data,
9418 state->max_data_return);
9419 END_PROFILE(Trans2_qfsinfo);
9420 break;
9423 case TRANSACT2_SETFSINFO:
9425 START_PROFILE(Trans2_setfsinfo);
9426 call_trans2setfsinfo(conn, req,
9427 &state->param, state->total_param,
9428 &state->data, state->total_data,
9429 state->max_data_return);
9430 END_PROFILE(Trans2_setfsinfo);
9431 break;
9434 case TRANSACT2_QPATHINFO:
9435 case TRANSACT2_QFILEINFO:
9437 START_PROFILE(Trans2_qpathinfo);
9438 call_trans2qfilepathinfo(conn, req, state->call,
9439 &state->param, state->total_param,
9440 &state->data, state->total_data,
9441 state->max_data_return);
9442 END_PROFILE(Trans2_qpathinfo);
9443 break;
9446 case TRANSACT2_SETPATHINFO:
9447 case TRANSACT2_SETFILEINFO:
9449 START_PROFILE(Trans2_setpathinfo);
9450 call_trans2setfilepathinfo(conn, req, state->call,
9451 &state->param, state->total_param,
9452 &state->data, state->total_data,
9453 state->max_data_return);
9454 END_PROFILE(Trans2_setpathinfo);
9455 break;
9458 case TRANSACT2_FINDNOTIFYFIRST:
9460 START_PROFILE(Trans2_findnotifyfirst);
9461 call_trans2findnotifyfirst(conn, req,
9462 &state->param, state->total_param,
9463 &state->data, state->total_data,
9464 state->max_data_return);
9465 END_PROFILE(Trans2_findnotifyfirst);
9466 break;
9469 case TRANSACT2_FINDNOTIFYNEXT:
9471 START_PROFILE(Trans2_findnotifynext);
9472 call_trans2findnotifynext(conn, req,
9473 &state->param, state->total_param,
9474 &state->data, state->total_data,
9475 state->max_data_return);
9476 END_PROFILE(Trans2_findnotifynext);
9477 break;
9480 case TRANSACT2_MKDIR:
9482 START_PROFILE(Trans2_mkdir);
9483 call_trans2mkdir(conn, req,
9484 &state->param, state->total_param,
9485 &state->data, state->total_data,
9486 state->max_data_return);
9487 END_PROFILE(Trans2_mkdir);
9488 break;
9491 case TRANSACT2_GET_DFS_REFERRAL:
9493 START_PROFILE(Trans2_get_dfs_referral);
9494 call_trans2getdfsreferral(conn, req,
9495 &state->param, state->total_param,
9496 &state->data, state->total_data,
9497 state->max_data_return);
9498 END_PROFILE(Trans2_get_dfs_referral);
9499 break;
9502 case TRANSACT2_IOCTL:
9504 START_PROFILE(Trans2_ioctl);
9505 call_trans2ioctl(conn, req,
9506 &state->param, state->total_param,
9507 &state->data, state->total_data,
9508 state->max_data_return);
9509 END_PROFILE(Trans2_ioctl);
9510 break;
9513 default:
9514 /* Error in request */
9515 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9516 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9520 /****************************************************************************
9521 Reply to a SMBtrans2.
9522 ****************************************************************************/
9524 void reply_trans2(struct smb_request *req)
9526 connection_struct *conn = req->conn;
9527 unsigned int dsoff;
9528 unsigned int dscnt;
9529 unsigned int psoff;
9530 unsigned int pscnt;
9531 unsigned int tran_call;
9532 struct trans_state *state;
9533 NTSTATUS result;
9535 START_PROFILE(SMBtrans2);
9537 if (req->wct < 14) {
9538 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9539 END_PROFILE(SMBtrans2);
9540 return;
9543 dsoff = SVAL(req->vwv+12, 0);
9544 dscnt = SVAL(req->vwv+11, 0);
9545 psoff = SVAL(req->vwv+10, 0);
9546 pscnt = SVAL(req->vwv+9, 0);
9547 tran_call = SVAL(req->vwv+14, 0);
9549 result = allow_new_trans(conn->pending_trans, req->mid);
9550 if (!NT_STATUS_IS_OK(result)) {
9551 DEBUG(2, ("Got invalid trans2 request: %s\n",
9552 nt_errstr(result)));
9553 reply_nterror(req, result);
9554 END_PROFILE(SMBtrans2);
9555 return;
9558 if (IS_IPC(conn)) {
9559 switch (tran_call) {
9560 /* List the allowed trans2 calls on IPC$ */
9561 case TRANSACT2_OPEN:
9562 case TRANSACT2_GET_DFS_REFERRAL:
9563 case TRANSACT2_QFILEINFO:
9564 case TRANSACT2_QFSINFO:
9565 case TRANSACT2_SETFSINFO:
9566 break;
9567 default:
9568 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9569 END_PROFILE(SMBtrans2);
9570 return;
9574 if ((state = talloc(conn, struct trans_state)) == NULL) {
9575 DEBUG(0, ("talloc failed\n"));
9576 reply_nterror(req, NT_STATUS_NO_MEMORY);
9577 END_PROFILE(SMBtrans2);
9578 return;
9581 state->cmd = SMBtrans2;
9583 state->mid = req->mid;
9584 state->vuid = req->vuid;
9585 state->setup_count = SVAL(req->vwv+13, 0);
9586 state->setup = NULL;
9587 state->total_param = SVAL(req->vwv+0, 0);
9588 state->param = NULL;
9589 state->total_data = SVAL(req->vwv+1, 0);
9590 state->data = NULL;
9591 state->max_param_return = SVAL(req->vwv+2, 0);
9592 state->max_data_return = SVAL(req->vwv+3, 0);
9593 state->max_setup_return = SVAL(req->vwv+4, 0);
9594 state->close_on_completion = BITSETW(req->vwv+5, 0);
9595 state->one_way = BITSETW(req->vwv+5, 1);
9597 state->call = tran_call;
9599 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9600 is so as a sanity check */
9601 if (state->setup_count != 1) {
9603 * Need to have rc=0 for ioctl to get job id for OS/2.
9604 * Network printing will fail if function is not successful.
9605 * Similar function in reply.c will be used if protocol
9606 * is LANMAN1.0 instead of LM1.2X002.
9607 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9608 * outbuf doesn't have to be set(only job id is used).
9610 if ( (state->setup_count == 4)
9611 && (tran_call == TRANSACT2_IOCTL)
9612 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9613 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9614 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9615 } else {
9616 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9617 DEBUG(2,("Transaction is %d\n",tran_call));
9618 TALLOC_FREE(state);
9619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9620 END_PROFILE(SMBtrans2);
9621 return;
9625 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9626 goto bad_param;
9628 if (state->total_data) {
9630 if (trans_oob(state->total_data, 0, dscnt)
9631 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9632 goto bad_param;
9635 /* Can't use talloc here, the core routines do realloc on the
9636 * params and data. */
9637 state->data = (char *)SMB_MALLOC(state->total_data);
9638 if (state->data == NULL) {
9639 DEBUG(0,("reply_trans2: data malloc fail for %u "
9640 "bytes !\n", (unsigned int)state->total_data));
9641 TALLOC_FREE(state);
9642 reply_nterror(req, NT_STATUS_NO_MEMORY);
9643 END_PROFILE(SMBtrans2);
9644 return;
9647 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9650 if (state->total_param) {
9652 if (trans_oob(state->total_param, 0, pscnt)
9653 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9654 goto bad_param;
9657 /* Can't use talloc here, the core routines do realloc on the
9658 * params and data. */
9659 state->param = (char *)SMB_MALLOC(state->total_param);
9660 if (state->param == NULL) {
9661 DEBUG(0,("reply_trans: param malloc fail for %u "
9662 "bytes !\n", (unsigned int)state->total_param));
9663 SAFE_FREE(state->data);
9664 TALLOC_FREE(state);
9665 reply_nterror(req, NT_STATUS_NO_MEMORY);
9666 END_PROFILE(SMBtrans2);
9667 return;
9670 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9673 state->received_data = dscnt;
9674 state->received_param = pscnt;
9676 if ((state->received_param == state->total_param) &&
9677 (state->received_data == state->total_data)) {
9679 handle_trans2(conn, req, state);
9681 SAFE_FREE(state->data);
9682 SAFE_FREE(state->param);
9683 TALLOC_FREE(state);
9684 END_PROFILE(SMBtrans2);
9685 return;
9688 DLIST_ADD(conn->pending_trans, state);
9690 /* We need to send an interim response then receive the rest
9691 of the parameter/data bytes */
9692 reply_outbuf(req, 0, 0);
9693 show_msg((char *)req->outbuf);
9694 END_PROFILE(SMBtrans2);
9695 return;
9697 bad_param:
9699 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9700 SAFE_FREE(state->data);
9701 SAFE_FREE(state->param);
9702 TALLOC_FREE(state);
9703 END_PROFILE(SMBtrans2);
9704 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9708 /****************************************************************************
9709 Reply to a SMBtranss2
9710 ****************************************************************************/
9712 void reply_transs2(struct smb_request *req)
9714 connection_struct *conn = req->conn;
9715 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9716 struct trans_state *state;
9718 START_PROFILE(SMBtranss2);
9720 show_msg((const char *)req->inbuf);
9722 /* Windows clients expect all replies to
9723 a transact secondary (SMBtranss2 0x33)
9724 to have a command code of transact
9725 (SMBtrans2 0x32). See bug #8989
9726 and also [MS-CIFS] section 2.2.4.47.2
9727 for details.
9729 req->cmd = SMBtrans2;
9731 if (req->wct < 8) {
9732 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9733 END_PROFILE(SMBtranss2);
9734 return;
9737 for (state = conn->pending_trans; state != NULL;
9738 state = state->next) {
9739 if (state->mid == req->mid) {
9740 break;
9744 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9745 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9746 END_PROFILE(SMBtranss2);
9747 return;
9750 /* Revise state->total_param and state->total_data in case they have
9751 changed downwards */
9753 if (SVAL(req->vwv+0, 0) < state->total_param)
9754 state->total_param = SVAL(req->vwv+0, 0);
9755 if (SVAL(req->vwv+1, 0) < state->total_data)
9756 state->total_data = SVAL(req->vwv+1, 0);
9758 pcnt = SVAL(req->vwv+2, 0);
9759 poff = SVAL(req->vwv+3, 0);
9760 pdisp = SVAL(req->vwv+4, 0);
9762 dcnt = SVAL(req->vwv+5, 0);
9763 doff = SVAL(req->vwv+6, 0);
9764 ddisp = SVAL(req->vwv+7, 0);
9766 state->received_param += pcnt;
9767 state->received_data += dcnt;
9769 if ((state->received_data > state->total_data) ||
9770 (state->received_param > state->total_param))
9771 goto bad_param;
9773 if (pcnt) {
9774 if (trans_oob(state->total_param, pdisp, pcnt)
9775 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9776 goto bad_param;
9778 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9781 if (dcnt) {
9782 if (trans_oob(state->total_data, ddisp, dcnt)
9783 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9784 goto bad_param;
9786 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9789 if ((state->received_param < state->total_param) ||
9790 (state->received_data < state->total_data)) {
9791 END_PROFILE(SMBtranss2);
9792 return;
9795 handle_trans2(conn, req, state);
9797 DLIST_REMOVE(conn->pending_trans, state);
9798 SAFE_FREE(state->data);
9799 SAFE_FREE(state->param);
9800 TALLOC_FREE(state);
9802 END_PROFILE(SMBtranss2);
9803 return;
9805 bad_param:
9807 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9808 DLIST_REMOVE(conn->pending_trans, state);
9809 SAFE_FREE(state->data);
9810 SAFE_FREE(state->param);
9811 TALLOC_FREE(state);
9812 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9813 END_PROFILE(SMBtranss2);
9814 return;