winbindd: queryuser - only get group name if needed
[Samba.git] / source3 / smbd / trans2.c
blobde6073a973fdbc35197caf5831199727b83f49f2
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 "../librpc/gen_ndr/open_files.h"
36 #include "libcli/security/security.h"
37 #include "trans2.h"
38 #include "auth.h"
39 #include "smbprofile.h"
40 #include "rpc_server/srv_pipe_hnd.h"
41 #include "printing.h"
42 #include "lib/util_ea.h"
43 #include "lib/readdir_attr.h"
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 &smb_fname);
1300 if (!NT_STATUS_IS_OK(status)) {
1301 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1302 reply_botherror(req,
1303 NT_STATUS_PATH_NOT_COVERED,
1304 ERRSRV, ERRbadpath);
1305 goto out;
1307 reply_nterror(req, status);
1308 goto out;
1311 if (open_ofun == 0) {
1312 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1313 goto out;
1316 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1317 open_ofun,
1318 &access_mask, &share_mode,
1319 &create_disposition,
1320 &create_options,
1321 &private_flags)) {
1322 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1323 goto out;
1326 /* Any data in this call is an EA list. */
1327 if (total_data && (total_data != 4)) {
1328 if (total_data < 10) {
1329 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1330 goto out;
1333 if (IVAL(pdata,0) > total_data) {
1334 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1335 IVAL(pdata,0), (unsigned int)total_data));
1336 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1337 goto out;
1340 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1341 total_data - 4);
1342 if (!ea_list) {
1343 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1344 goto out;
1347 if (!lp_ea_support(SNUM(conn))) {
1348 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1349 goto out;
1352 if (!req->posix_pathnames &&
1353 ea_list_has_invalid_name(ea_list)) {
1354 int param_len = 30;
1355 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1356 if(*pparams == NULL ) {
1357 reply_nterror(req, NT_STATUS_NO_MEMORY);
1358 goto out;
1360 params = *pparams;
1361 memset(params, '\0', param_len);
1362 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1363 params, param_len, NULL, 0, max_data_bytes);
1364 goto out;
1368 status = SMB_VFS_CREATE_FILE(
1369 conn, /* conn */
1370 req, /* req */
1371 0, /* root_dir_fid */
1372 smb_fname, /* fname */
1373 access_mask, /* access_mask */
1374 share_mode, /* share_access */
1375 create_disposition, /* create_disposition*/
1376 create_options, /* create_options */
1377 open_attr, /* file_attributes */
1378 oplock_request, /* oplock_request */
1379 NULL, /* lease */
1380 open_size, /* allocation_size */
1381 private_flags,
1382 NULL, /* sd */
1383 ea_list, /* ea_list */
1384 &fsp, /* result */
1385 &smb_action, /* psbuf */
1386 NULL, NULL); /* create context */
1388 if (!NT_STATUS_IS_OK(status)) {
1389 if (open_was_deferred(req->xconn, req->mid)) {
1390 /* We have re-scheduled this call. */
1391 goto out;
1393 reply_openerror(req, status);
1394 goto out;
1397 size = get_file_size_stat(&smb_fname->st);
1398 fattr = dos_mode(conn, smb_fname);
1399 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1400 inode = smb_fname->st.st_ex_ino;
1401 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1402 close_file(req, fsp, ERROR_CLOSE);
1403 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1404 goto out;
1407 /* Realloc the size of parameters and data we will return */
1408 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1409 if(*pparams == NULL ) {
1410 reply_nterror(req, NT_STATUS_NO_MEMORY);
1411 goto out;
1413 params = *pparams;
1415 SSVAL(params,0,fsp->fnum);
1416 SSVAL(params,2,fattr);
1417 srv_put_dos_date2(params,4, mtime);
1418 SIVAL(params,8, (uint32_t)size);
1419 SSVAL(params,12,deny_mode);
1420 SSVAL(params,14,0); /* open_type - file or directory. */
1421 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1423 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1424 smb_action |= EXTENDED_OPLOCK_GRANTED;
1427 SSVAL(params,18,smb_action);
1430 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1432 SIVAL(params,20,inode);
1433 SSVAL(params,24,0); /* Padding. */
1434 if (flags & 8) {
1435 uint32_t ea_size = estimate_ea_size(conn, fsp,
1436 smb_fname);
1437 SIVAL(params, 26, ea_size);
1438 } else {
1439 SIVAL(params, 26, 0);
1442 /* Send the required number of replies */
1443 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1444 out:
1445 TALLOC_FREE(smb_fname);
1448 /*********************************************************
1449 Routine to check if a given string matches exactly.
1450 as a special case a mask of "." does NOT match. That
1451 is required for correct wildcard semantics
1452 Case can be significant or not.
1453 **********************************************************/
1455 static bool exact_match(bool has_wild,
1456 bool case_sensitive,
1457 const char *str,
1458 const char *mask)
1460 if (mask[0] == '.' && mask[1] == 0) {
1461 return false;
1464 if (has_wild) {
1465 return false;
1468 if (case_sensitive) {
1469 return strcmp(str,mask)==0;
1470 } else {
1471 return strcasecmp_m(str,mask) == 0;
1475 /****************************************************************************
1476 Return the filetype for UNIX extensions.
1477 ****************************************************************************/
1479 static uint32_t unix_filetype(mode_t mode)
1481 if(S_ISREG(mode))
1482 return UNIX_TYPE_FILE;
1483 else if(S_ISDIR(mode))
1484 return UNIX_TYPE_DIR;
1485 #ifdef S_ISLNK
1486 else if(S_ISLNK(mode))
1487 return UNIX_TYPE_SYMLINK;
1488 #endif
1489 #ifdef S_ISCHR
1490 else if(S_ISCHR(mode))
1491 return UNIX_TYPE_CHARDEV;
1492 #endif
1493 #ifdef S_ISBLK
1494 else if(S_ISBLK(mode))
1495 return UNIX_TYPE_BLKDEV;
1496 #endif
1497 #ifdef S_ISFIFO
1498 else if(S_ISFIFO(mode))
1499 return UNIX_TYPE_FIFO;
1500 #endif
1501 #ifdef S_ISSOCK
1502 else if(S_ISSOCK(mode))
1503 return UNIX_TYPE_SOCKET;
1504 #endif
1506 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1507 return UNIX_TYPE_UNKNOWN;
1510 /****************************************************************************
1511 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1512 ****************************************************************************/
1514 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1516 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1517 const SMB_STRUCT_STAT *psbuf,
1518 uint32_t perms,
1519 enum perm_type ptype,
1520 mode_t *ret_perms)
1522 mode_t ret = 0;
1524 if (perms == SMB_MODE_NO_CHANGE) {
1525 if (!VALID_STAT(*psbuf)) {
1526 return NT_STATUS_INVALID_PARAMETER;
1527 } else {
1528 *ret_perms = psbuf->st_ex_mode;
1529 return NT_STATUS_OK;
1533 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1534 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1535 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1536 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1537 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1538 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1539 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1540 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1541 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1542 #ifdef S_ISVTX
1543 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1544 #endif
1545 #ifdef S_ISGID
1546 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1547 #endif
1548 #ifdef S_ISUID
1549 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1550 #endif
1552 if (ptype == PERM_NEW_FILE) {
1554 * "create mask"/"force create mode" are
1555 * only applied to new files, not existing ones.
1557 ret &= lp_create_mask(SNUM(conn));
1558 /* Add in force bits */
1559 ret |= lp_force_create_mode(SNUM(conn));
1560 } else if (ptype == PERM_NEW_DIR) {
1562 * "directory mask"/"force directory mode" are
1563 * only applied to new directories, not existing ones.
1565 ret &= lp_directory_mask(SNUM(conn));
1566 /* Add in force bits */
1567 ret |= lp_force_directory_mode(SNUM(conn));
1570 *ret_perms = ret;
1571 return NT_STATUS_OK;
1574 /****************************************************************************
1575 Needed to show the msdfs symlinks as directories. Modifies psbuf
1576 to be a directory if it's a msdfs link.
1577 ****************************************************************************/
1579 static bool check_msdfs_link(connection_struct *conn,
1580 struct smb_filename *smb_fname)
1582 int saved_errno = errno;
1583 if(lp_host_msdfs() &&
1584 lp_msdfs_root(SNUM(conn)) &&
1585 is_msdfs_link(conn, smb_fname)) {
1587 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1588 "as a directory\n",
1589 smb_fname->base_name));
1590 smb_fname->st.st_ex_mode =
1591 (smb_fname->st.st_ex_mode & 0xFFF) | S_IFDIR;
1592 errno = saved_errno;
1593 return true;
1595 errno = saved_errno;
1596 return false;
1600 /****************************************************************************
1601 Get a level dependent lanman2 dir entry.
1602 ****************************************************************************/
1604 struct smbd_dirptr_lanman2_state {
1605 connection_struct *conn;
1606 uint32_t info_level;
1607 bool check_mangled_names;
1608 bool has_wild;
1609 bool got_exact_match;
1612 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1613 void *private_data,
1614 const char *dname,
1615 const char *mask,
1616 char **_fname)
1618 struct smbd_dirptr_lanman2_state *state =
1619 (struct smbd_dirptr_lanman2_state *)private_data;
1620 bool ok;
1621 char mangled_name[13]; /* mangled 8.3 name. */
1622 bool got_match;
1623 const char *fname;
1625 /* Mangle fname if it's an illegal name. */
1626 if (mangle_must_mangle(dname, state->conn->params)) {
1628 * Slow path - ensure we can push the original name as UCS2. If
1629 * not, then just don't return this name.
1631 NTSTATUS status;
1632 size_t ret_len = 0;
1633 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1634 uint8_t *tmp = talloc_array(talloc_tos(),
1635 uint8_t,
1636 len);
1638 status = srvstr_push(NULL,
1639 FLAGS2_UNICODE_STRINGS,
1640 tmp,
1641 dname,
1642 len,
1643 STR_TERMINATE,
1644 &ret_len);
1646 TALLOC_FREE(tmp);
1648 if (!NT_STATUS_IS_OK(status)) {
1649 return false;
1652 ok = name_to_8_3(dname, mangled_name,
1653 true, state->conn->params);
1654 if (!ok) {
1655 return false;
1657 fname = mangled_name;
1658 } else {
1659 fname = dname;
1662 got_match = exact_match(state->has_wild,
1663 state->conn->case_sensitive,
1664 fname, mask);
1665 state->got_exact_match = got_match;
1666 if (!got_match) {
1667 got_match = mask_match(fname, mask,
1668 state->conn->case_sensitive);
1671 if(!got_match && state->check_mangled_names &&
1672 !mangle_is_8_3(fname, false, state->conn->params)) {
1674 * It turns out that NT matches wildcards against
1675 * both long *and* short names. This may explain some
1676 * of the wildcard wierdness from old DOS clients
1677 * that some people have been seeing.... JRA.
1679 /* Force the mangling into 8.3. */
1680 ok = name_to_8_3(fname, mangled_name,
1681 false, state->conn->params);
1682 if (!ok) {
1683 return false;
1686 got_match = exact_match(state->has_wild,
1687 state->conn->case_sensitive,
1688 mangled_name, mask);
1689 state->got_exact_match = got_match;
1690 if (!got_match) {
1691 got_match = mask_match(mangled_name, mask,
1692 state->conn->case_sensitive);
1696 if (!got_match) {
1697 return false;
1700 *_fname = talloc_strdup(ctx, fname);
1701 if (*_fname == NULL) {
1702 return false;
1705 return true;
1708 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1709 void *private_data,
1710 struct smb_filename *smb_fname,
1711 uint32_t *_mode)
1713 struct smbd_dirptr_lanman2_state *state =
1714 (struct smbd_dirptr_lanman2_state *)private_data;
1715 bool ms_dfs_link = false;
1716 uint32_t mode = 0;
1718 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1719 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1720 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1721 "Couldn't lstat [%s] (%s)\n",
1722 smb_fname_str_dbg(smb_fname),
1723 strerror(errno)));
1724 return false;
1726 } else if (!VALID_STAT(smb_fname->st) &&
1727 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1728 /* Needed to show the msdfs symlinks as
1729 * directories */
1731 ms_dfs_link = check_msdfs_link(state->conn,
1732 smb_fname);
1733 if (!ms_dfs_link) {
1734 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1735 "Couldn't stat [%s] (%s)\n",
1736 smb_fname_str_dbg(smb_fname),
1737 strerror(errno)));
1738 return false;
1742 if (ms_dfs_link) {
1743 mode = dos_mode_msdfs(state->conn, smb_fname);
1744 } else {
1745 mode = dos_mode(state->conn, smb_fname);
1748 *_mode = mode;
1749 return true;
1752 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1753 connection_struct *conn,
1754 uint16_t flags2,
1755 uint32_t info_level,
1756 struct ea_list *name_list,
1757 bool check_mangled_names,
1758 bool requires_resume_key,
1759 uint32_t mode,
1760 const char *fname,
1761 const struct smb_filename *smb_fname,
1762 int space_remaining,
1763 uint8_t align,
1764 bool do_pad,
1765 char *base_data,
1766 char **ppdata,
1767 char *end_data,
1768 uint64_t *last_entry_off)
1770 char *p, *q, *pdata = *ppdata;
1771 uint32_t reskey=0;
1772 uint64_t file_size = 0;
1773 uint64_t allocation_size = 0;
1774 uint64_t file_index = 0;
1775 size_t len = 0;
1776 struct timespec mdate_ts = {0};
1777 struct timespec adate_ts = {0};
1778 struct timespec cdate_ts = {0};
1779 struct timespec create_date_ts = {0};
1780 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1781 char *nameptr;
1782 char *last_entry_ptr;
1783 bool was_8_3;
1784 int off;
1785 int pad = 0;
1786 NTSTATUS status;
1787 struct readdir_attr_data *readdir_attr_data = NULL;
1789 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1790 file_size = get_file_size_stat(&smb_fname->st);
1792 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1794 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1795 if (!NT_STATUS_IS_OK(status)) {
1796 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1797 return status;
1801 file_index = get_FileIndex(conn, &smb_fname->st);
1803 mdate_ts = smb_fname->st.st_ex_mtime;
1804 adate_ts = smb_fname->st.st_ex_atime;
1805 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1806 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1808 if (lp_dos_filetime_resolution(SNUM(conn))) {
1809 dos_filetime_timespec(&create_date_ts);
1810 dos_filetime_timespec(&mdate_ts);
1811 dos_filetime_timespec(&adate_ts);
1812 dos_filetime_timespec(&cdate_ts);
1815 create_date = convert_timespec_to_time_t(create_date_ts);
1816 mdate = convert_timespec_to_time_t(mdate_ts);
1817 adate = convert_timespec_to_time_t(adate_ts);
1819 /* align the record */
1820 SMB_ASSERT(align >= 1);
1822 off = (int)PTR_DIFF(pdata, base_data);
1823 pad = (off + (align-1)) & ~(align-1);
1824 pad -= off;
1826 if (pad && pad > space_remaining) {
1827 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1828 "for padding (wanted %u, had %d)\n",
1829 (unsigned int)pad,
1830 space_remaining ));
1831 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1834 off += pad;
1835 /* initialize padding to 0 */
1836 if (pad) {
1837 memset(pdata, 0, pad);
1839 space_remaining -= pad;
1841 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1842 space_remaining ));
1844 pdata += pad;
1845 p = pdata;
1846 last_entry_ptr = p;
1848 pad = 0;
1849 off = 0;
1851 switch (info_level) {
1852 case SMB_FIND_INFO_STANDARD:
1853 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1854 if(requires_resume_key) {
1855 SIVAL(p,0,reskey);
1856 p += 4;
1858 srv_put_dos_date2(p,0,create_date);
1859 srv_put_dos_date2(p,4,adate);
1860 srv_put_dos_date2(p,8,mdate);
1861 SIVAL(p,12,(uint32_t)file_size);
1862 SIVAL(p,16,(uint32_t)allocation_size);
1863 SSVAL(p,20,mode);
1864 p += 23;
1865 nameptr = p;
1866 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1867 p += ucs2_align(base_data, p, 0);
1869 status = srvstr_push(base_data, flags2, p,
1870 fname, PTR_DIFF(end_data, p),
1871 STR_TERMINATE, &len);
1872 if (!NT_STATUS_IS_OK(status)) {
1873 return status;
1875 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1876 if (len > 2) {
1877 SCVAL(nameptr, -1, len - 2);
1878 } else {
1879 SCVAL(nameptr, -1, 0);
1881 } else {
1882 if (len > 1) {
1883 SCVAL(nameptr, -1, len - 1);
1884 } else {
1885 SCVAL(nameptr, -1, 0);
1888 p += len;
1889 break;
1891 case SMB_FIND_EA_SIZE:
1892 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1893 if (requires_resume_key) {
1894 SIVAL(p,0,reskey);
1895 p += 4;
1897 srv_put_dos_date2(p,0,create_date);
1898 srv_put_dos_date2(p,4,adate);
1899 srv_put_dos_date2(p,8,mdate);
1900 SIVAL(p,12,(uint32_t)file_size);
1901 SIVAL(p,16,(uint32_t)allocation_size);
1902 SSVAL(p,20,mode);
1904 unsigned int ea_size = estimate_ea_size(conn, NULL,
1905 smb_fname);
1906 SIVAL(p,22,ea_size); /* Extended attributes */
1908 p += 27;
1909 nameptr = p - 1;
1910 status = srvstr_push(base_data, flags2,
1911 p, fname, PTR_DIFF(end_data, p),
1912 STR_TERMINATE | STR_NOALIGN, &len);
1913 if (!NT_STATUS_IS_OK(status)) {
1914 return status;
1916 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1917 if (len > 2) {
1918 len -= 2;
1919 } else {
1920 len = 0;
1922 } else {
1923 if (len > 1) {
1924 len -= 1;
1925 } else {
1926 len = 0;
1929 SCVAL(nameptr,0,len);
1930 p += len;
1931 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1932 break;
1934 case SMB_FIND_EA_LIST:
1936 struct ea_list *file_list = NULL;
1937 size_t ea_len = 0;
1939 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1940 if (!name_list) {
1941 return NT_STATUS_INVALID_PARAMETER;
1943 if (requires_resume_key) {
1944 SIVAL(p,0,reskey);
1945 p += 4;
1947 srv_put_dos_date2(p,0,create_date);
1948 srv_put_dos_date2(p,4,adate);
1949 srv_put_dos_date2(p,8,mdate);
1950 SIVAL(p,12,(uint32_t)file_size);
1951 SIVAL(p,16,(uint32_t)allocation_size);
1952 SSVAL(p,20,mode);
1953 p += 22; /* p now points to the EA area. */
1955 status = get_ea_list_from_file(ctx, conn, NULL,
1956 smb_fname,
1957 &ea_len, &file_list);
1958 if (!NT_STATUS_IS_OK(status)) {
1959 file_list = NULL;
1961 name_list = ea_list_union(name_list, file_list, &ea_len);
1963 /* We need to determine if this entry will fit in the space available. */
1964 /* Max string size is 255 bytes. */
1965 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1966 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1967 "(wanted %u, had %d)\n",
1968 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1969 space_remaining ));
1970 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1973 /* Push the ea_data followed by the name. */
1974 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1975 nameptr = p;
1976 status = srvstr_push(base_data, flags2,
1977 p + 1, fname, PTR_DIFF(end_data, p+1),
1978 STR_TERMINATE | STR_NOALIGN, &len);
1979 if (!NT_STATUS_IS_OK(status)) {
1980 return status;
1982 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1983 if (len > 2) {
1984 len -= 2;
1985 } else {
1986 len = 0;
1988 } else {
1989 if (len > 1) {
1990 len -= 1;
1991 } else {
1992 len = 0;
1995 SCVAL(nameptr,0,len);
1996 p += len + 1;
1997 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1998 break;
2001 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2002 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
2003 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2004 p += 4;
2005 SIVAL(p,0,reskey); p += 4;
2006 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2007 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2008 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2009 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2010 SOFF_T(p,0,file_size); p += 8;
2011 SOFF_T(p,0,allocation_size); p += 8;
2012 SIVAL(p,0,mode); p += 4;
2013 q = p; p += 4; /* q is placeholder for name length. */
2014 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2015 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2016 } else {
2017 unsigned int ea_size = estimate_ea_size(conn, NULL,
2018 smb_fname);
2019 SIVAL(p,0,ea_size); /* Extended attributes */
2021 p += 4;
2022 /* Clear the short name buffer. This is
2023 * IMPORTANT as not doing so will trigger
2024 * a Win2k client bug. JRA.
2026 if (!was_8_3 && check_mangled_names) {
2027 char mangled_name[13]; /* mangled 8.3 name. */
2028 if (!name_to_8_3(fname,mangled_name,True,
2029 conn->params)) {
2030 /* Error - mangle failed ! */
2031 memset(mangled_name,'\0',12);
2033 mangled_name[12] = 0;
2034 status = srvstr_push(base_data, flags2,
2035 p+2, mangled_name, 24,
2036 STR_UPPER|STR_UNICODE, &len);
2037 if (!NT_STATUS_IS_OK(status)) {
2038 return status;
2040 if (len < 24) {
2041 memset(p + 2 + len,'\0',24 - len);
2043 SSVAL(p, 0, len);
2044 } else {
2045 memset(p,'\0',26);
2047 p += 2 + 24;
2048 status = srvstr_push(base_data, flags2, p,
2049 fname, PTR_DIFF(end_data, p),
2050 STR_TERMINATE_ASCII, &len);
2051 if (!NT_STATUS_IS_OK(status)) {
2052 return status;
2054 SIVAL(q,0,len);
2055 p += len;
2057 len = PTR_DIFF(p, pdata);
2058 pad = (len + (align-1)) & ~(align-1);
2060 * offset to the next entry, the caller
2061 * will overwrite it for the last entry
2062 * that's why we always include the padding
2064 SIVAL(pdata,0,pad);
2066 * set padding to zero
2068 if (do_pad) {
2069 memset(p, 0, pad - len);
2070 p = pdata + pad;
2071 } else {
2072 p = pdata + len;
2074 break;
2076 case SMB_FIND_FILE_DIRECTORY_INFO:
2077 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2078 p += 4;
2079 SIVAL(p,0,reskey); p += 4;
2080 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2081 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2082 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2083 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2084 SOFF_T(p,0,file_size); p += 8;
2085 SOFF_T(p,0,allocation_size); p += 8;
2086 SIVAL(p,0,mode); p += 4;
2087 status = srvstr_push(base_data, flags2,
2088 p + 4, fname, PTR_DIFF(end_data, p+4),
2089 STR_TERMINATE_ASCII, &len);
2090 if (!NT_STATUS_IS_OK(status)) {
2091 return status;
2093 SIVAL(p,0,len);
2094 p += 4 + len;
2096 len = PTR_DIFF(p, pdata);
2097 pad = (len + (align-1)) & ~(align-1);
2099 * offset to the next entry, the caller
2100 * will overwrite it for the last entry
2101 * that's why we always include the padding
2103 SIVAL(pdata,0,pad);
2105 * set padding to zero
2107 if (do_pad) {
2108 memset(p, 0, pad - len);
2109 p = pdata + pad;
2110 } else {
2111 p = pdata + len;
2113 break;
2115 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2116 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2117 p += 4;
2118 SIVAL(p,0,reskey); p += 4;
2119 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2120 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2121 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2122 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2123 SOFF_T(p,0,file_size); p += 8;
2124 SOFF_T(p,0,allocation_size); p += 8;
2125 SIVAL(p,0,mode); p += 4;
2126 q = p; p += 4; /* q is placeholder for name length. */
2128 unsigned int ea_size = estimate_ea_size(conn, NULL,
2129 smb_fname);
2130 SIVAL(p,0,ea_size); /* Extended attributes */
2131 p +=4;
2133 status = srvstr_push(base_data, flags2, p,
2134 fname, PTR_DIFF(end_data, p),
2135 STR_TERMINATE_ASCII, &len);
2136 if (!NT_STATUS_IS_OK(status)) {
2137 return status;
2139 SIVAL(q, 0, len);
2140 p += len;
2142 len = PTR_DIFF(p, pdata);
2143 pad = (len + (align-1)) & ~(align-1);
2145 * offset to the next entry, the caller
2146 * will overwrite it for the last entry
2147 * that's why we always include the padding
2149 SIVAL(pdata,0,pad);
2151 * set padding to zero
2153 if (do_pad) {
2154 memset(p, 0, pad - len);
2155 p = pdata + pad;
2156 } else {
2157 p = pdata + len;
2159 break;
2161 case SMB_FIND_FILE_NAMES_INFO:
2162 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2163 p += 4;
2164 SIVAL(p,0,reskey); p += 4;
2165 p += 4;
2166 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2167 acl on a dir (tridge) */
2168 status = srvstr_push(base_data, flags2, p,
2169 fname, PTR_DIFF(end_data, p),
2170 STR_TERMINATE_ASCII, &len);
2171 if (!NT_STATUS_IS_OK(status)) {
2172 return status;
2174 SIVAL(p, -4, len);
2175 p += len;
2177 len = PTR_DIFF(p, pdata);
2178 pad = (len + (align-1)) & ~(align-1);
2180 * offset to the next entry, the caller
2181 * will overwrite it for the last entry
2182 * that's why we always include the padding
2184 SIVAL(pdata,0,pad);
2186 * set padding to zero
2188 if (do_pad) {
2189 memset(p, 0, pad - len);
2190 p = pdata + pad;
2191 } else {
2192 p = pdata + len;
2194 break;
2196 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2197 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2198 p += 4;
2199 SIVAL(p,0,reskey); p += 4;
2200 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2201 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2202 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2203 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2204 SOFF_T(p,0,file_size); p += 8;
2205 SOFF_T(p,0,allocation_size); p += 8;
2206 SIVAL(p,0,mode); p += 4;
2207 q = p; p += 4; /* q is placeholder for name length. */
2208 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2209 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2210 } else {
2211 unsigned int ea_size = estimate_ea_size(conn, NULL,
2212 smb_fname);
2213 SIVAL(p,0,ea_size); /* Extended attributes */
2215 p += 4;
2216 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2217 SBVAL(p,0,file_index); p += 8;
2218 status = srvstr_push(base_data, flags2, p,
2219 fname, PTR_DIFF(end_data, p),
2220 STR_TERMINATE_ASCII, &len);
2221 if (!NT_STATUS_IS_OK(status)) {
2222 return status;
2224 SIVAL(q, 0, len);
2225 p += len;
2227 len = PTR_DIFF(p, pdata);
2228 pad = (len + (align-1)) & ~(align-1);
2230 * offset to the next entry, the caller
2231 * will overwrite it for the last entry
2232 * that's why we always include the padding
2234 SIVAL(pdata,0,pad);
2236 * set padding to zero
2238 if (do_pad) {
2239 memset(p, 0, pad - len);
2240 p = pdata + pad;
2241 } else {
2242 p = pdata + len;
2244 break;
2246 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2247 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2248 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2249 p += 4;
2250 SIVAL(p,0,reskey); p += 4;
2251 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2252 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2253 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2254 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2255 SOFF_T(p,0,file_size); p += 8;
2256 SOFF_T(p,0,allocation_size); p += 8;
2257 SIVAL(p,0,mode); p += 4;
2258 q = p; p += 4; /* q is placeholder for name length */
2259 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2260 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2261 } else if (readdir_attr_data &&
2262 readdir_attr_data->type == RDATTR_AAPL) {
2264 * OS X specific SMB2 extension negotiated via
2265 * AAPL create context: return max_access in
2266 * ea_size field.
2268 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2269 } else {
2270 unsigned int ea_size = estimate_ea_size(conn, NULL,
2271 smb_fname);
2272 SIVAL(p,0,ea_size); /* Extended attributes */
2274 p += 4;
2276 if (readdir_attr_data &&
2277 readdir_attr_data->type == RDATTR_AAPL) {
2279 * OS X specific SMB2 extension negotiated via
2280 * AAPL create context: return resource fork
2281 * length and compressed FinderInfo in
2282 * shortname field.
2284 * According to documentation short_name_len
2285 * should be 0, but on the wire behaviour
2286 * shows its set to 24 by clients.
2288 SSVAL(p, 0, 24);
2290 /* Resourefork length */
2291 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2293 /* Compressed FinderInfo */
2294 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2295 } else if (!was_8_3 && check_mangled_names) {
2296 char mangled_name[13]; /* mangled 8.3 name. */
2297 if (!name_to_8_3(fname,mangled_name,True,
2298 conn->params)) {
2299 /* Error - mangle failed ! */
2300 memset(mangled_name,'\0',12);
2302 mangled_name[12] = 0;
2303 status = srvstr_push(base_data, flags2,
2304 p+2, mangled_name, 24,
2305 STR_UPPER|STR_UNICODE, &len);
2306 if (!NT_STATUS_IS_OK(status)) {
2307 return status;
2309 SSVAL(p, 0, len);
2310 if (len < 24) {
2311 memset(p + 2 + len,'\0',24 - len);
2313 SSVAL(p, 0, len);
2314 } else {
2315 /* Clear the short name buffer. This is
2316 * IMPORTANT as not doing so will trigger
2317 * a Win2k client bug. JRA.
2319 memset(p,'\0',26);
2321 p += 26;
2323 /* Reserved ? */
2324 if (readdir_attr_data &&
2325 readdir_attr_data->type == RDATTR_AAPL) {
2327 * OS X specific SMB2 extension negotiated via
2328 * AAPL create context: return UNIX mode in
2329 * reserved field.
2331 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2332 SSVAL(p, 0, aapl_mode);
2333 } else {
2334 SSVAL(p, 0, 0);
2336 p += 2;
2338 SBVAL(p,0,file_index); p += 8;
2339 status = srvstr_push(base_data, flags2, p,
2340 fname, PTR_DIFF(end_data, p),
2341 STR_TERMINATE_ASCII, &len);
2342 if (!NT_STATUS_IS_OK(status)) {
2343 return status;
2345 SIVAL(q,0,len);
2346 p += len;
2348 len = PTR_DIFF(p, pdata);
2349 pad = (len + (align-1)) & ~(align-1);
2351 * offset to the next entry, the caller
2352 * will overwrite it for the last entry
2353 * that's why we always include the padding
2355 SIVAL(pdata,0,pad);
2357 * set padding to zero
2359 if (do_pad) {
2360 memset(p, 0, pad - len);
2361 p = pdata + pad;
2362 } else {
2363 p = pdata + len;
2365 break;
2367 /* CIFS UNIX Extension. */
2369 case SMB_FIND_FILE_UNIX:
2370 case SMB_FIND_FILE_UNIX_INFO2:
2371 p+= 4;
2372 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2374 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2376 if (info_level == SMB_FIND_FILE_UNIX) {
2377 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2378 p = store_file_unix_basic(conn, p,
2379 NULL, &smb_fname->st);
2380 status = srvstr_push(base_data, flags2, p,
2381 fname, PTR_DIFF(end_data, p),
2382 STR_TERMINATE, &len);
2383 if (!NT_STATUS_IS_OK(status)) {
2384 return status;
2386 } else {
2387 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2388 p = store_file_unix_basic_info2(conn, p,
2389 NULL, &smb_fname->st);
2390 nameptr = p;
2391 p += 4;
2392 status = srvstr_push(base_data, flags2, p, fname,
2393 PTR_DIFF(end_data, p), 0, &len);
2394 if (!NT_STATUS_IS_OK(status)) {
2395 return status;
2397 SIVAL(nameptr, 0, len);
2400 p += len;
2402 len = PTR_DIFF(p, pdata);
2403 pad = (len + (align-1)) & ~(align-1);
2405 * offset to the next entry, the caller
2406 * will overwrite it for the last entry
2407 * that's why we always include the padding
2409 SIVAL(pdata,0,pad);
2411 * set padding to zero
2413 if (do_pad) {
2414 memset(p, 0, pad - len);
2415 p = pdata + pad;
2416 } else {
2417 p = pdata + len;
2419 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2421 break;
2423 default:
2424 return NT_STATUS_INVALID_LEVEL;
2427 if (PTR_DIFF(p,pdata) > space_remaining) {
2428 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2429 "(wanted %u, had %d)\n",
2430 (unsigned int)PTR_DIFF(p,pdata),
2431 space_remaining ));
2432 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2435 /* Setup the last entry pointer, as an offset from base_data */
2436 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2437 /* Advance the data pointer to the next slot */
2438 *ppdata = p;
2440 return NT_STATUS_OK;
2443 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2444 connection_struct *conn,
2445 struct dptr_struct *dirptr,
2446 uint16_t flags2,
2447 const char *path_mask,
2448 uint32_t dirtype,
2449 int info_level,
2450 int requires_resume_key,
2451 bool dont_descend,
2452 bool ask_sharemode,
2453 uint8_t align,
2454 bool do_pad,
2455 char **ppdata,
2456 char *base_data,
2457 char *end_data,
2458 int space_remaining,
2459 bool *got_exact_match,
2460 int *_last_entry_off,
2461 struct ea_list *name_list,
2462 struct file_id *file_id)
2464 const char *p;
2465 const char *mask = NULL;
2466 long prev_dirpos = 0;
2467 uint32_t mode = 0;
2468 char *fname = NULL;
2469 struct smb_filename *smb_fname = NULL;
2470 struct smbd_dirptr_lanman2_state state;
2471 bool ok;
2472 uint64_t last_entry_off = 0;
2473 NTSTATUS status;
2474 enum mangled_names_options mangled_names;
2475 bool marshall_with_83_names;
2477 mangled_names = lp_mangled_names(conn->params);
2479 ZERO_STRUCT(state);
2480 state.conn = conn;
2481 state.info_level = info_level;
2482 if (mangled_names != MANGLED_NAMES_NO) {
2483 state.check_mangled_names = true;
2485 state.has_wild = dptr_has_wild(dirptr);
2486 state.got_exact_match = false;
2488 *got_exact_match = false;
2490 p = strrchr_m(path_mask,'/');
2491 if(p != NULL) {
2492 if(p[1] == '\0') {
2493 mask = "*.*";
2494 } else {
2495 mask = p+1;
2497 } else {
2498 mask = path_mask;
2501 ok = smbd_dirptr_get_entry(ctx,
2502 dirptr,
2503 mask,
2504 dirtype,
2505 dont_descend,
2506 ask_sharemode,
2507 smbd_dirptr_lanman2_match_fn,
2508 smbd_dirptr_lanman2_mode_fn,
2509 &state,
2510 &fname,
2511 &smb_fname,
2512 &mode,
2513 &prev_dirpos);
2514 if (!ok) {
2515 return NT_STATUS_END_OF_FILE;
2518 *got_exact_match = state.got_exact_match;
2520 marshall_with_83_names = (mangled_names == MANGLED_NAMES_YES);
2522 status = smbd_marshall_dir_entry(ctx,
2523 conn,
2524 flags2,
2525 info_level,
2526 name_list,
2527 marshall_with_83_names,
2528 requires_resume_key,
2529 mode,
2530 fname,
2531 smb_fname,
2532 space_remaining,
2533 align,
2534 do_pad,
2535 base_data,
2536 ppdata,
2537 end_data,
2538 &last_entry_off);
2539 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2540 DEBUG(1,("Conversion error: illegal character: %s\n",
2541 smb_fname_str_dbg(smb_fname)));
2544 if (file_id != NULL) {
2545 *file_id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
2548 TALLOC_FREE(fname);
2549 TALLOC_FREE(smb_fname);
2550 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2551 dptr_SeekDir(dirptr, prev_dirpos);
2552 return status;
2554 if (!NT_STATUS_IS_OK(status)) {
2555 return status;
2558 *_last_entry_off = last_entry_off;
2559 return NT_STATUS_OK;
2562 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2563 connection_struct *conn,
2564 struct dptr_struct *dirptr,
2565 uint16_t flags2,
2566 const char *path_mask,
2567 uint32_t dirtype,
2568 int info_level,
2569 bool requires_resume_key,
2570 bool dont_descend,
2571 bool ask_sharemode,
2572 char **ppdata,
2573 char *base_data,
2574 char *end_data,
2575 int space_remaining,
2576 bool *got_exact_match,
2577 int *last_entry_off,
2578 struct ea_list *name_list)
2580 uint8_t align = 4;
2581 const bool do_pad = true;
2583 if (info_level >= 1 && info_level <= 3) {
2584 /* No alignment on earlier info levels. */
2585 align = 1;
2588 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2589 path_mask, dirtype, info_level,
2590 requires_resume_key, dont_descend, ask_sharemode,
2591 align, do_pad,
2592 ppdata, base_data, end_data,
2593 space_remaining,
2594 got_exact_match,
2595 last_entry_off, name_list, NULL);
2598 /****************************************************************************
2599 Reply to a TRANS2_FINDFIRST.
2600 ****************************************************************************/
2602 static void call_trans2findfirst(connection_struct *conn,
2603 struct smb_request *req,
2604 char **pparams, int total_params,
2605 char **ppdata, int total_data,
2606 unsigned int max_data_bytes)
2608 /* We must be careful here that we don't return more than the
2609 allowed number of data bytes. If this means returning fewer than
2610 maxentries then so be it. We assume that the redirector has
2611 enough room for the fixed number of parameter bytes it has
2612 requested. */
2613 struct smb_filename *smb_dname = NULL;
2614 char *params = *pparams;
2615 char *pdata = *ppdata;
2616 char *data_end;
2617 uint32_t dirtype;
2618 int maxentries;
2619 uint16_t findfirst_flags;
2620 bool close_after_first;
2621 bool close_if_end;
2622 bool requires_resume_key;
2623 int info_level;
2624 char *directory = NULL;
2625 char *mask = NULL;
2626 char *p;
2627 int last_entry_off=0;
2628 int dptr_num = -1;
2629 int numentries = 0;
2630 int i;
2631 bool finished = False;
2632 bool dont_descend = False;
2633 bool out_of_space = False;
2634 int space_remaining;
2635 bool mask_contains_wcard = False;
2636 struct ea_list *ea_list = NULL;
2637 NTSTATUS ntstatus = NT_STATUS_OK;
2638 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2639 struct dptr_struct *dirptr = NULL;
2640 struct smbd_server_connection *sconn = req->sconn;
2641 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2642 ucf_flags_from_smb_request(req);
2643 bool backup_priv = false;
2644 bool as_root = false;
2646 if (total_params < 13) {
2647 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2648 goto out;
2651 dirtype = SVAL(params,0);
2652 maxentries = SVAL(params,2);
2653 findfirst_flags = SVAL(params,4);
2654 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2655 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2656 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2657 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2658 security_token_has_privilege(get_current_nttok(conn),
2659 SEC_PRIV_BACKUP));
2661 info_level = SVAL(params,6);
2663 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2664 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2665 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2666 (int)backup_priv,
2667 info_level, max_data_bytes));
2669 if (!maxentries) {
2670 /* W2K3 seems to treat zero as 1. */
2671 maxentries = 1;
2674 switch (info_level) {
2675 case SMB_FIND_INFO_STANDARD:
2676 case SMB_FIND_EA_SIZE:
2677 case SMB_FIND_EA_LIST:
2678 case SMB_FIND_FILE_DIRECTORY_INFO:
2679 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2680 case SMB_FIND_FILE_NAMES_INFO:
2681 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2682 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2683 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2684 break;
2685 case SMB_FIND_FILE_UNIX:
2686 case SMB_FIND_FILE_UNIX_INFO2:
2687 /* Always use filesystem for UNIX mtime query. */
2688 ask_sharemode = false;
2689 if (!lp_unix_extensions()) {
2690 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2691 goto out;
2693 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2694 break;
2695 default:
2696 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2697 goto out;
2700 if (req->posix_pathnames) {
2701 srvstr_get_path_wcard_posix(talloc_tos(),
2702 params,
2703 req->flags2,
2704 &directory,
2705 params+12,
2706 total_params - 12,
2707 STR_TERMINATE,
2708 &ntstatus,
2709 &mask_contains_wcard);
2710 } else {
2711 srvstr_get_path_wcard(talloc_tos(),
2712 params,
2713 req->flags2,
2714 &directory,
2715 params+12,
2716 total_params - 12,
2717 STR_TERMINATE,
2718 &ntstatus,
2719 &mask_contains_wcard);
2721 if (!NT_STATUS_IS_OK(ntstatus)) {
2722 reply_nterror(req, ntstatus);
2723 goto out;
2726 if (backup_priv) {
2727 become_root();
2728 as_root = true;
2729 ntstatus = filename_convert_with_privilege(talloc_tos(),
2730 conn,
2731 req,
2732 directory,
2733 ucf_flags,
2734 &mask_contains_wcard,
2735 &smb_dname);
2736 } else {
2737 ntstatus = filename_convert(talloc_tos(), conn,
2738 directory,
2739 ucf_flags,
2740 &mask_contains_wcard,
2741 &smb_dname);
2744 if (!NT_STATUS_IS_OK(ntstatus)) {
2745 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2746 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2747 ERRSRV, ERRbadpath);
2748 goto out;
2750 reply_nterror(req, ntstatus);
2751 goto out;
2754 mask = smb_dname->original_lcomp;
2756 directory = smb_dname->base_name;
2758 p = strrchr_m(directory,'/');
2759 if(p == NULL) {
2760 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2761 if((directory[0] == '.') && (directory[1] == '\0')) {
2762 mask = talloc_strdup(talloc_tos(),"*");
2763 if (!mask) {
2764 reply_nterror(req, NT_STATUS_NO_MEMORY);
2765 goto out;
2767 mask_contains_wcard = True;
2769 } else {
2770 *p = 0;
2773 if (p == NULL || p == directory) {
2774 /* Ensure we don't have a directory name of "". */
2775 directory = talloc_strdup(talloc_tos(), ".");
2776 if (!directory) {
2777 reply_nterror(req, NT_STATUS_NO_MEMORY);
2778 goto out;
2780 /* Ensure smb_dname->base_name matches. */
2781 smb_dname->base_name = directory;
2784 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2786 if (info_level == SMB_FIND_EA_LIST) {
2787 uint32_t ea_size;
2789 if (total_data < 4) {
2790 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2791 goto out;
2794 ea_size = IVAL(pdata,0);
2795 if (ea_size != total_data) {
2796 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2797 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2798 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2799 goto out;
2802 if (!lp_ea_support(SNUM(conn))) {
2803 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2804 goto out;
2807 /* Pull out the list of names. */
2808 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2809 if (!ea_list) {
2810 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2811 goto out;
2815 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2816 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2817 goto out;
2820 *ppdata = (char *)SMB_REALLOC(
2821 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2822 if(*ppdata == NULL ) {
2823 reply_nterror(req, NT_STATUS_NO_MEMORY);
2824 goto out;
2826 pdata = *ppdata;
2827 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2829 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2830 * error.
2832 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2833 /* Realloc the params space */
2834 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2835 if (*pparams == NULL) {
2836 reply_nterror(req, NT_STATUS_NO_MEMORY);
2837 goto out;
2839 params = *pparams;
2841 /* Save the wildcard match and attribs we are using on this directory -
2842 needed as lanman2 assumes these are being saved between calls */
2844 ntstatus = dptr_create(conn,
2845 req,
2846 NULL, /* fsp */
2847 smb_dname,
2848 False,
2849 True,
2850 req->smbpid,
2851 mask,
2852 mask_contains_wcard,
2853 dirtype,
2854 &dirptr);
2856 if (!NT_STATUS_IS_OK(ntstatus)) {
2857 reply_nterror(req, ntstatus);
2858 goto out;
2861 if (backup_priv) {
2862 /* Remember this in case we have
2863 to do a findnext. */
2864 dptr_set_priv(dirptr);
2867 dptr_num = dptr_dnum(dirptr);
2868 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2870 /* Initialize per TRANS2_FIND_FIRST operation data */
2871 dptr_init_search_op(dirptr);
2873 /* We don't need to check for VOL here as this is returned by
2874 a different TRANS2 call. */
2876 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2877 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2878 if (in_list(directory,
2879 lp_dont_descend(talloc_tos(), SNUM(conn)),
2880 conn->case_sensitive)) {
2881 dont_descend = True;
2884 p = pdata;
2885 space_remaining = max_data_bytes;
2886 out_of_space = False;
2888 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2889 bool got_exact_match = False;
2891 /* this is a heuristic to avoid seeking the dirptr except when
2892 absolutely necessary. It allows for a filename of about 40 chars */
2893 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2894 out_of_space = True;
2895 finished = False;
2896 } else {
2897 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2898 conn,
2899 dirptr,
2900 req->flags2,
2901 mask,dirtype,info_level,
2902 requires_resume_key,dont_descend,
2903 ask_sharemode,
2904 &p,pdata,data_end,
2905 space_remaining,
2906 &got_exact_match,
2907 &last_entry_off, ea_list);
2908 if (NT_STATUS_EQUAL(ntstatus,
2909 NT_STATUS_ILLEGAL_CHARACTER)) {
2911 * Bad character conversion on name. Ignore this
2912 * entry.
2914 continue;
2916 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2917 out_of_space = true;
2918 } else {
2919 finished = !NT_STATUS_IS_OK(ntstatus);
2923 if (!finished && !out_of_space)
2924 numentries++;
2927 * As an optimisation if we know we aren't looking
2928 * for a wildcard name (ie. the name matches the wildcard exactly)
2929 * then we can finish on any (first) match.
2930 * This speeds up large directory searches. JRA.
2933 if(got_exact_match)
2934 finished = True;
2936 /* Ensure space_remaining never goes -ve. */
2937 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2938 space_remaining = 0;
2939 out_of_space = true;
2940 } else {
2941 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2945 /* Check if we can close the dirptr */
2946 if(close_after_first || (finished && close_if_end)) {
2947 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2948 dptr_close(sconn, &dptr_num);
2952 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2953 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2954 * the protocol level is less than NT1. Tested with smbclient. JRA.
2955 * This should fix the OS/2 client bug #2335.
2958 if(numentries == 0) {
2959 dptr_close(sconn, &dptr_num);
2960 if (get_Protocol() < PROTOCOL_NT1) {
2961 reply_force_doserror(req, ERRDOS, ERRnofiles);
2962 goto out;
2963 } else {
2964 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2965 ERRDOS, ERRbadfile);
2966 goto out;
2970 /* At this point pdata points to numentries directory entries. */
2972 /* Set up the return parameter block */
2973 SSVAL(params,0,dptr_num);
2974 SSVAL(params,2,numentries);
2975 SSVAL(params,4,finished);
2976 SSVAL(params,6,0); /* Never an EA error */
2977 SSVAL(params,8,last_entry_off);
2979 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2980 max_data_bytes);
2982 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2983 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2984 if (!directory) {
2985 reply_nterror(req, NT_STATUS_NO_MEMORY);
2989 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2990 smb_fn_name(req->cmd),
2991 mask, directory, dirtype, numentries ) );
2994 * Force a name mangle here to ensure that the
2995 * mask as an 8.3 name is top of the mangled cache.
2996 * The reasons for this are subtle. Don't remove
2997 * this code unless you know what you are doing
2998 * (see PR#13758). JRA.
3001 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
3002 char mangled_name[13];
3003 name_to_8_3(mask, mangled_name, True, conn->params);
3005 out:
3007 if (as_root) {
3008 unbecome_root();
3011 TALLOC_FREE(smb_dname);
3012 return;
3015 /****************************************************************************
3016 Reply to a TRANS2_FINDNEXT.
3017 ****************************************************************************/
3019 static void call_trans2findnext(connection_struct *conn,
3020 struct smb_request *req,
3021 char **pparams, int total_params,
3022 char **ppdata, int total_data,
3023 unsigned int max_data_bytes)
3025 /* We must be careful here that we don't return more than the
3026 allowed number of data bytes. If this means returning fewer than
3027 maxentries then so be it. We assume that the redirector has
3028 enough room for the fixed number of parameter bytes it has
3029 requested. */
3030 char *params = *pparams;
3031 char *pdata = *ppdata;
3032 char *data_end;
3033 int dptr_num;
3034 int maxentries;
3035 uint16_t info_level;
3036 uint32_t resume_key;
3037 uint16_t findnext_flags;
3038 bool close_after_request;
3039 bool close_if_end;
3040 bool requires_resume_key;
3041 bool continue_bit;
3042 bool mask_contains_wcard = False;
3043 char *resume_name = NULL;
3044 const char *mask = NULL;
3045 const char *directory = NULL;
3046 char *p = NULL;
3047 uint16_t dirtype;
3048 int numentries = 0;
3049 int i, last_entry_off=0;
3050 bool finished = False;
3051 bool dont_descend = False;
3052 bool out_of_space = False;
3053 int space_remaining;
3054 struct ea_list *ea_list = NULL;
3055 NTSTATUS ntstatus = NT_STATUS_OK;
3056 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3057 TALLOC_CTX *ctx = talloc_tos();
3058 struct dptr_struct *dirptr;
3059 struct smbd_server_connection *sconn = req->sconn;
3060 bool backup_priv = false;
3061 bool as_root = false;
3063 if (total_params < 13) {
3064 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3065 return;
3068 dptr_num = SVAL(params,0);
3069 maxentries = SVAL(params,2);
3070 info_level = SVAL(params,4);
3071 resume_key = IVAL(params,6);
3072 findnext_flags = SVAL(params,10);
3073 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3074 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3075 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3076 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3078 if (!continue_bit) {
3079 /* We only need resume_name if continue_bit is zero. */
3080 if (req->posix_pathnames) {
3081 srvstr_get_path_wcard_posix(ctx,
3082 params,
3083 req->flags2,
3084 &resume_name,
3085 params+12,
3086 total_params - 12,
3087 STR_TERMINATE,
3088 &ntstatus,
3089 &mask_contains_wcard);
3090 } else {
3091 srvstr_get_path_wcard(ctx,
3092 params,
3093 req->flags2,
3094 &resume_name,
3095 params+12,
3096 total_params - 12,
3097 STR_TERMINATE,
3098 &ntstatus,
3099 &mask_contains_wcard);
3101 if (!NT_STATUS_IS_OK(ntstatus)) {
3102 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3103 complain (it thinks we're asking for the directory above the shared
3104 path or an invalid name). Catch this as the resume name is only compared, never used in
3105 a file access. JRA. */
3106 srvstr_pull_talloc(ctx, params, req->flags2,
3107 &resume_name, params+12,
3108 total_params - 12,
3109 STR_TERMINATE);
3111 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3112 reply_nterror(req, ntstatus);
3113 return;
3118 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3119 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3120 resume_key = %d resume name = %s continue=%d level = %d\n",
3121 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3122 requires_resume_key, resume_key,
3123 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3125 if (!maxentries) {
3126 /* W2K3 seems to treat zero as 1. */
3127 maxentries = 1;
3130 switch (info_level) {
3131 case SMB_FIND_INFO_STANDARD:
3132 case SMB_FIND_EA_SIZE:
3133 case SMB_FIND_EA_LIST:
3134 case SMB_FIND_FILE_DIRECTORY_INFO:
3135 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3136 case SMB_FIND_FILE_NAMES_INFO:
3137 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3138 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3139 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3140 break;
3141 case SMB_FIND_FILE_UNIX:
3142 case SMB_FIND_FILE_UNIX_INFO2:
3143 /* Always use filesystem for UNIX mtime query. */
3144 ask_sharemode = false;
3145 if (!lp_unix_extensions()) {
3146 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3147 return;
3149 break;
3150 default:
3151 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3152 return;
3155 if (info_level == SMB_FIND_EA_LIST) {
3156 uint32_t ea_size;
3158 if (total_data < 4) {
3159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3160 return;
3163 ea_size = IVAL(pdata,0);
3164 if (ea_size != total_data) {
3165 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3166 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3167 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3168 return;
3171 if (!lp_ea_support(SNUM(conn))) {
3172 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3173 return;
3176 /* Pull out the list of names. */
3177 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3178 if (!ea_list) {
3179 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3180 return;
3184 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3185 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3186 return;
3189 *ppdata = (char *)SMB_REALLOC(
3190 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3191 if(*ppdata == NULL) {
3192 reply_nterror(req, NT_STATUS_NO_MEMORY);
3193 return;
3196 pdata = *ppdata;
3197 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3200 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3201 * error.
3203 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3204 /* Realloc the params space */
3205 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3206 if(*pparams == NULL ) {
3207 reply_nterror(req, NT_STATUS_NO_MEMORY);
3208 return;
3211 params = *pparams;
3213 /* Check that the dptr is valid */
3214 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3215 reply_nterror(req, STATUS_NO_MORE_FILES);
3216 return;
3219 directory = dptr_path(sconn, dptr_num);
3221 /* Get the wildcard mask from the dptr */
3222 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3223 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3224 reply_nterror(req, STATUS_NO_MORE_FILES);
3225 return;
3228 /* Get the attr mask from the dptr */
3229 dirtype = dptr_attr(sconn, dptr_num);
3231 backup_priv = dptr_get_priv(dirptr);
3233 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3234 "backup_priv = %d\n",
3235 dptr_num, mask, dirtype,
3236 (long)dirptr,
3237 dptr_TellDir(dirptr),
3238 (int)backup_priv));
3240 /* Initialize per TRANS2_FIND_NEXT operation data */
3241 dptr_init_search_op(dirptr);
3243 /* We don't need to check for VOL here as this is returned by
3244 a different TRANS2 call. */
3246 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3247 directory,lp_dont_descend(ctx, SNUM(conn))));
3248 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3249 dont_descend = True;
3251 p = pdata;
3252 space_remaining = max_data_bytes;
3253 out_of_space = False;
3255 if (backup_priv) {
3256 become_root();
3257 as_root = true;
3261 * Seek to the correct position. We no longer use the resume key but
3262 * depend on the last file name instead.
3265 if(!continue_bit && resume_name && *resume_name) {
3266 SMB_STRUCT_STAT st;
3268 long current_pos = 0;
3270 * Remember, name_to_8_3 is called by
3271 * get_lanman2_dir_entry(), so the resume name
3272 * could be mangled. Ensure we check the unmangled name.
3275 if (mangle_is_mangled(resume_name, conn->params)) {
3276 char *new_resume_name = NULL;
3277 mangle_lookup_name_from_8_3(ctx,
3278 resume_name,
3279 &new_resume_name,
3280 conn->params);
3281 if (new_resume_name) {
3282 resume_name = new_resume_name;
3287 * Fix for NT redirector problem triggered by resume key indexes
3288 * changing between directory scans. We now return a resume key of 0
3289 * and instead look for the filename to continue from (also given
3290 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3291 * findfirst/findnext (as is usual) then the directory pointer
3292 * should already be at the correct place.
3295 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3296 } /* end if resume_name && !continue_bit */
3298 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3299 bool got_exact_match = False;
3301 /* this is a heuristic to avoid seeking the dirptr except when
3302 absolutely necessary. It allows for a filename of about 40 chars */
3303 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3304 out_of_space = True;
3305 finished = False;
3306 } else {
3307 ntstatus = get_lanman2_dir_entry(ctx,
3308 conn,
3309 dirptr,
3310 req->flags2,
3311 mask,dirtype,info_level,
3312 requires_resume_key,dont_descend,
3313 ask_sharemode,
3314 &p,pdata,data_end,
3315 space_remaining,
3316 &got_exact_match,
3317 &last_entry_off, ea_list);
3318 if (NT_STATUS_EQUAL(ntstatus,
3319 NT_STATUS_ILLEGAL_CHARACTER)) {
3321 * Bad character conversion on name. Ignore this
3322 * entry.
3324 continue;
3326 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3327 out_of_space = true;
3328 } else {
3329 finished = !NT_STATUS_IS_OK(ntstatus);
3333 if (!finished && !out_of_space)
3334 numentries++;
3337 * As an optimisation if we know we aren't looking
3338 * for a wildcard name (ie. the name matches the wildcard exactly)
3339 * then we can finish on any (first) match.
3340 * This speeds up large directory searches. JRA.
3343 if(got_exact_match)
3344 finished = True;
3346 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3349 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3350 smb_fn_name(req->cmd),
3351 mask, directory, dirtype, numentries ) );
3353 /* Check if we can close the dirptr */
3354 if(close_after_request || (finished && close_if_end)) {
3355 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3356 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3359 if (as_root) {
3360 unbecome_root();
3363 /* Set up the return parameter block */
3364 SSVAL(params,0,numentries);
3365 SSVAL(params,2,finished);
3366 SSVAL(params,4,0); /* Never an EA error */
3367 SSVAL(params,6,last_entry_off);
3369 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3370 max_data_bytes);
3372 return;
3375 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3377 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3378 return objid;
3381 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3383 SMB_ASSERT(extended_info != NULL);
3385 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3386 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3387 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3388 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3389 #ifdef SAMBA_VERSION_REVISION
3390 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3391 #endif
3392 extended_info->samba_subversion = 0;
3393 #ifdef SAMBA_VERSION_RC_RELEASE
3394 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3395 #else
3396 #ifdef SAMBA_VERSION_PRE_RELEASE
3397 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3398 #endif
3399 #endif
3400 #ifdef SAMBA_VERSION_VENDOR_PATCH
3401 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3402 #endif
3403 extended_info->samba_gitcommitdate = 0;
3404 #ifdef SAMBA_VERSION_COMMIT_TIME
3405 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3406 #endif
3408 memset(extended_info->samba_version_string, 0,
3409 sizeof(extended_info->samba_version_string));
3411 snprintf (extended_info->samba_version_string,
3412 sizeof(extended_info->samba_version_string),
3413 "%s", samba_version_string());
3416 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3417 connection_struct *conn,
3418 TALLOC_CTX *mem_ctx,
3419 uint16_t info_level,
3420 uint16_t flags2,
3421 unsigned int max_data_bytes,
3422 size_t *fixed_portion,
3423 struct smb_filename *fname,
3424 char **ppdata,
3425 int *ret_data_len)
3427 char *pdata, *end_data;
3428 int data_len = 0;
3429 size_t len = 0;
3430 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3431 int snum = SNUM(conn);
3432 const char *fstype = lp_fstype(SNUM(conn));
3433 const char *filename = NULL;
3434 const uint64_t bytes_per_sector = 512;
3435 uint32_t additional_flags = 0;
3436 struct smb_filename smb_fname;
3437 SMB_STRUCT_STAT st;
3438 NTSTATUS status = NT_STATUS_OK;
3439 uint64_t df_ret;
3441 if (fname == NULL || fname->base_name == NULL) {
3442 filename = ".";
3443 } else {
3444 filename = fname->base_name;
3447 if (IS_IPC(conn)) {
3448 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3449 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3450 "info level (0x%x) on IPC$.\n",
3451 (unsigned int)info_level));
3452 return NT_STATUS_ACCESS_DENIED;
3456 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3458 ZERO_STRUCT(smb_fname);
3459 smb_fname.base_name = discard_const_p(char, filename);
3461 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3462 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3463 return map_nt_error_from_unix(errno);
3466 st = smb_fname.st;
3468 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3469 return NT_STATUS_INVALID_PARAMETER;
3472 *ppdata = (char *)SMB_REALLOC(
3473 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3474 if (*ppdata == NULL) {
3475 return NT_STATUS_NO_MEMORY;
3478 pdata = *ppdata;
3479 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3480 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3482 *fixed_portion = 0;
3484 switch (info_level) {
3485 case SMB_INFO_ALLOCATION:
3487 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3488 data_len = 18;
3489 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3490 &dfree, &dsize);
3491 if (df_ret == (uint64_t)-1) {
3492 return map_nt_error_from_unix(errno);
3495 block_size = lp_block_size(snum);
3496 if (bsize < block_size) {
3497 uint64_t factor = block_size/bsize;
3498 bsize = block_size;
3499 dsize /= factor;
3500 dfree /= factor;
3502 if (bsize > block_size) {
3503 uint64_t factor = bsize/block_size;
3504 bsize = block_size;
3505 dsize *= factor;
3506 dfree *= factor;
3508 sectors_per_unit = bsize/bytes_per_sector;
3510 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3511 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3512 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3515 * For large drives, return max values and not modulo.
3517 dsize = MIN(dsize, UINT32_MAX);
3518 dfree = MIN(dfree, UINT32_MAX);
3520 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3521 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3522 SIVAL(pdata,l1_cUnit,dsize);
3523 SIVAL(pdata,l1_cUnitAvail,dfree);
3524 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3525 break;
3528 case SMB_INFO_VOLUME:
3529 /* Return volume name */
3531 * Add volume serial number - hash of a combination of
3532 * the called hostname and the service name.
3534 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3536 * Win2k3 and previous mess this up by sending a name length
3537 * one byte short. I believe only older clients (OS/2 Win9x) use
3538 * this call so try fixing this by adding a terminating null to
3539 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3541 status = srvstr_push(
3542 pdata, flags2,
3543 pdata+l2_vol_szVolLabel, vname,
3544 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3545 STR_NOALIGN|STR_TERMINATE, &len);
3546 if (!NT_STATUS_IS_OK(status)) {
3547 return status;
3549 SCVAL(pdata,l2_vol_cch,len);
3550 data_len = l2_vol_szVolLabel + len;
3551 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3552 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3553 (unsigned)len, vname));
3554 break;
3556 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3557 case SMB_FS_ATTRIBUTE_INFORMATION:
3559 additional_flags = 0;
3560 #if defined(HAVE_SYS_QUOTAS)
3561 additional_flags |= FILE_VOLUME_QUOTAS;
3562 #endif
3564 if(lp_nt_acl_support(SNUM(conn))) {
3565 additional_flags |= FILE_PERSISTENT_ACLS;
3568 /* Capabilities are filled in at connection time through STATVFS call */
3569 additional_flags |= conn->fs_capabilities;
3570 additional_flags |= lp_parm_int(conn->params->service,
3571 "share", "fake_fscaps",
3574 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3575 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3576 additional_flags); /* FS ATTRIBUTES */
3578 SIVAL(pdata,4,255); /* Max filename component length */
3579 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3580 and will think we can't do long filenames */
3581 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3582 PTR_DIFF(end_data, pdata+12),
3583 STR_UNICODE, &len);
3584 if (!NT_STATUS_IS_OK(status)) {
3585 return status;
3587 SIVAL(pdata,8,len);
3588 data_len = 12 + len;
3589 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3590 /* the client only requested a portion of the
3591 file system name */
3592 data_len = max_data_bytes;
3593 status = STATUS_BUFFER_OVERFLOW;
3595 *fixed_portion = 16;
3596 break;
3598 case SMB_QUERY_FS_LABEL_INFO:
3599 case SMB_FS_LABEL_INFORMATION:
3600 status = srvstr_push(pdata, flags2, pdata+4, vname,
3601 PTR_DIFF(end_data, pdata+4), 0, &len);
3602 if (!NT_STATUS_IS_OK(status)) {
3603 return status;
3605 data_len = 4 + len;
3606 SIVAL(pdata,0,len);
3607 break;
3609 case SMB_QUERY_FS_VOLUME_INFO:
3610 case SMB_FS_VOLUME_INFORMATION:
3613 * Add volume serial number - hash of a combination of
3614 * the called hostname and the service name.
3616 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3617 (str_checksum(get_local_machine_name())<<16));
3619 /* Max label len is 32 characters. */
3620 status = srvstr_push(pdata, flags2, pdata+18, vname,
3621 PTR_DIFF(end_data, pdata+18),
3622 STR_UNICODE, &len);
3623 if (!NT_STATUS_IS_OK(status)) {
3624 return status;
3626 SIVAL(pdata,12,len);
3627 data_len = 18+len;
3629 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3630 (int)strlen(vname),vname,
3631 lp_servicename(talloc_tos(), snum)));
3632 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3633 /* the client only requested a portion of the
3634 volume label */
3635 data_len = max_data_bytes;
3636 status = STATUS_BUFFER_OVERFLOW;
3638 *fixed_portion = 24;
3639 break;
3641 case SMB_QUERY_FS_SIZE_INFO:
3642 case SMB_FS_SIZE_INFORMATION:
3644 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3645 data_len = 24;
3646 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3647 &dfree, &dsize);
3648 if (df_ret == (uint64_t)-1) {
3649 return map_nt_error_from_unix(errno);
3651 block_size = lp_block_size(snum);
3652 if (bsize < block_size) {
3653 uint64_t factor = block_size/bsize;
3654 bsize = block_size;
3655 dsize /= factor;
3656 dfree /= factor;
3658 if (bsize > block_size) {
3659 uint64_t factor = bsize/block_size;
3660 bsize = block_size;
3661 dsize *= factor;
3662 dfree *= factor;
3664 sectors_per_unit = bsize/bytes_per_sector;
3665 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3666 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3667 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3668 SBIG_UINT(pdata,0,dsize);
3669 SBIG_UINT(pdata,8,dfree);
3670 SIVAL(pdata,16,sectors_per_unit);
3671 SIVAL(pdata,20,bytes_per_sector);
3672 *fixed_portion = 24;
3673 break;
3676 case SMB_FS_FULL_SIZE_INFORMATION:
3678 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3679 data_len = 32;
3680 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3681 &dfree, &dsize);
3682 if (df_ret == (uint64_t)-1) {
3683 return map_nt_error_from_unix(errno);
3685 block_size = lp_block_size(snum);
3686 if (bsize < block_size) {
3687 uint64_t factor = block_size/bsize;
3688 bsize = block_size;
3689 dsize /= factor;
3690 dfree /= factor;
3692 if (bsize > block_size) {
3693 uint64_t factor = bsize/block_size;
3694 bsize = block_size;
3695 dsize *= factor;
3696 dfree *= factor;
3698 sectors_per_unit = bsize/bytes_per_sector;
3699 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3700 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3701 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3702 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3703 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3704 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3705 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3706 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3707 *fixed_portion = 32;
3708 break;
3711 case SMB_QUERY_FS_DEVICE_INFO:
3712 case SMB_FS_DEVICE_INFORMATION:
3714 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3716 if (!CAN_WRITE(conn)) {
3717 characteristics |= FILE_READ_ONLY_DEVICE;
3719 data_len = 8;
3720 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3721 SIVAL(pdata,4,characteristics);
3722 *fixed_portion = 8;
3723 break;
3726 #ifdef HAVE_SYS_QUOTAS
3727 case SMB_FS_QUOTA_INFORMATION:
3729 * what we have to send --metze:
3731 * Unknown1: 24 NULL bytes
3732 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3733 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3734 * Quota Flags: 2 byte :
3735 * Unknown3: 6 NULL bytes
3737 * 48 bytes total
3739 * details for Quota Flags:
3741 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3742 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3743 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3744 * 0x0001 Enable Quotas: enable quota for this fs
3748 /* we need to fake up a fsp here,
3749 * because its not send in this call
3751 files_struct fsp;
3752 SMB_NTQUOTA_STRUCT quotas;
3754 ZERO_STRUCT(fsp);
3755 ZERO_STRUCT(quotas);
3757 fsp.conn = conn;
3758 fsp.fnum = FNUM_FIELD_INVALID;
3760 /* access check */
3761 if (get_current_uid(conn) != 0) {
3762 DEBUG(0,("get_user_quota: access_denied "
3763 "service [%s] user [%s]\n",
3764 lp_servicename(talloc_tos(), SNUM(conn)),
3765 conn->session_info->unix_info->unix_name));
3766 return NT_STATUS_ACCESS_DENIED;
3769 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3770 NULL, &quotas);
3771 if (!NT_STATUS_IS_OK(status)) {
3772 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3773 return status;
3776 data_len = 48;
3778 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3779 lp_servicename(talloc_tos(), SNUM(conn))));
3781 /* Unknown1 24 NULL bytes*/
3782 SBIG_UINT(pdata,0,(uint64_t)0);
3783 SBIG_UINT(pdata,8,(uint64_t)0);
3784 SBIG_UINT(pdata,16,(uint64_t)0);
3786 /* Default Soft Quota 8 bytes */
3787 SBIG_UINT(pdata,24,quotas.softlim);
3789 /* Default Hard Quota 8 bytes */
3790 SBIG_UINT(pdata,32,quotas.hardlim);
3792 /* Quota flag 2 bytes */
3793 SSVAL(pdata,40,quotas.qflags);
3795 /* Unknown3 6 NULL bytes */
3796 SSVAL(pdata,42,0);
3797 SIVAL(pdata,44,0);
3799 break;
3801 #endif /* HAVE_SYS_QUOTAS */
3802 case SMB_FS_OBJECTID_INFORMATION:
3804 unsigned char objid[16];
3805 struct smb_extended_info extended_info;
3806 memcpy(pdata,create_volume_objectid(conn, objid),16);
3807 samba_extended_info_version (&extended_info);
3808 SIVAL(pdata,16,extended_info.samba_magic);
3809 SIVAL(pdata,20,extended_info.samba_version);
3810 SIVAL(pdata,24,extended_info.samba_subversion);
3811 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3812 memcpy(pdata+36,extended_info.samba_version_string,28);
3813 data_len = 64;
3814 break;
3817 case SMB_FS_SECTOR_SIZE_INFORMATION:
3819 data_len = 28;
3821 * These values match a physical Windows Server 2012
3822 * share backed by NTFS atop spinning rust.
3824 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3825 /* logical_bytes_per_sector */
3826 SIVAL(pdata, 0, bytes_per_sector);
3827 /* phys_bytes_per_sector_atomic */
3828 SIVAL(pdata, 4, bytes_per_sector);
3829 /* phys_bytes_per_sector_perf */
3830 SIVAL(pdata, 8, bytes_per_sector);
3831 /* fs_effective_phys_bytes_per_sector_atomic */
3832 SIVAL(pdata, 12, bytes_per_sector);
3833 /* flags */
3834 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3835 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3836 /* byte_off_sector_align */
3837 SIVAL(pdata, 20, 0);
3838 /* byte_off_partition_align */
3839 SIVAL(pdata, 24, 0);
3840 *fixed_portion = 28;
3841 break;
3846 * Query the version and capabilities of the CIFS UNIX extensions
3847 * in use.
3850 case SMB_QUERY_CIFS_UNIX_INFO:
3852 bool large_write = lp_min_receive_file_size() &&
3853 !srv_is_signing_active(xconn);
3854 bool large_read = !srv_is_signing_active(xconn);
3855 int encrypt_caps = 0;
3857 if (!lp_unix_extensions()) {
3858 return NT_STATUS_INVALID_LEVEL;
3861 switch (conn->encrypt_level) {
3862 case SMB_SIGNING_OFF:
3863 encrypt_caps = 0;
3864 break;
3865 case SMB_SIGNING_DESIRED:
3866 case SMB_SIGNING_IF_REQUIRED:
3867 case SMB_SIGNING_DEFAULT:
3868 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3869 break;
3870 case SMB_SIGNING_REQUIRED:
3871 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3872 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3873 large_write = false;
3874 large_read = false;
3875 break;
3878 data_len = 12;
3879 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3880 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3882 /* We have POSIX ACLs, pathname, encryption,
3883 * large read/write, and locking capability. */
3885 SBIG_UINT(pdata,4,((uint64_t)(
3886 CIFS_UNIX_POSIX_ACLS_CAP|
3887 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3888 CIFS_UNIX_FCNTL_LOCKS_CAP|
3889 CIFS_UNIX_EXTATTR_CAP|
3890 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3891 encrypt_caps|
3892 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3893 (large_write ?
3894 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3895 break;
3898 case SMB_QUERY_POSIX_FS_INFO:
3900 int rc;
3901 vfs_statvfs_struct svfs;
3903 if (!lp_unix_extensions()) {
3904 return NT_STATUS_INVALID_LEVEL;
3907 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3909 if (!rc) {
3910 data_len = 56;
3911 SIVAL(pdata,0,svfs.OptimalTransferSize);
3912 SIVAL(pdata,4,svfs.BlockSize);
3913 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3914 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3915 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3916 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3917 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3918 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3919 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3920 #ifdef EOPNOTSUPP
3921 } else if (rc == EOPNOTSUPP) {
3922 return NT_STATUS_INVALID_LEVEL;
3923 #endif /* EOPNOTSUPP */
3924 } else {
3925 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3926 return NT_STATUS_DOS(ERRSRV, ERRerror);
3928 break;
3931 case SMB_QUERY_POSIX_WHOAMI:
3933 uint32_t flags = 0;
3934 uint32_t sid_bytes;
3935 int i;
3937 if (!lp_unix_extensions()) {
3938 return NT_STATUS_INVALID_LEVEL;
3941 if (max_data_bytes < 40) {
3942 return NT_STATUS_BUFFER_TOO_SMALL;
3945 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3946 flags |= SMB_WHOAMI_GUEST;
3949 /* NOTE: 8 bytes for UID/GID, irrespective of native
3950 * platform size. This matches
3951 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3953 data_len = 4 /* flags */
3954 + 4 /* flag mask */
3955 + 8 /* uid */
3956 + 8 /* gid */
3957 + 4 /* ngroups */
3958 + 4 /* num_sids */
3959 + 4 /* SID bytes */
3960 + 4 /* pad/reserved */
3961 + (conn->session_info->unix_token->ngroups * 8)
3962 /* groups list */
3963 + (conn->session_info->security_token->num_sids *
3964 SID_MAX_SIZE)
3965 /* SID list */;
3967 SIVAL(pdata, 0, flags);
3968 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3969 SBIG_UINT(pdata, 8,
3970 (uint64_t)conn->session_info->unix_token->uid);
3971 SBIG_UINT(pdata, 16,
3972 (uint64_t)conn->session_info->unix_token->gid);
3975 if (data_len >= max_data_bytes) {
3976 /* Potential overflow, skip the GIDs and SIDs. */
3978 SIVAL(pdata, 24, 0); /* num_groups */
3979 SIVAL(pdata, 28, 0); /* num_sids */
3980 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3981 SIVAL(pdata, 36, 0); /* reserved */
3983 data_len = 40;
3984 break;
3987 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3988 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3990 /* We walk the SID list twice, but this call is fairly
3991 * infrequent, and I don't expect that it's performance
3992 * sensitive -- jpeach
3994 for (i = 0, sid_bytes = 0;
3995 i < conn->session_info->security_token->num_sids; ++i) {
3996 sid_bytes += ndr_size_dom_sid(
3997 &conn->session_info->security_token->sids[i],
4001 /* SID list byte count */
4002 SIVAL(pdata, 32, sid_bytes);
4004 /* 4 bytes pad/reserved - must be zero */
4005 SIVAL(pdata, 36, 0);
4006 data_len = 40;
4008 /* GID list */
4009 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4010 SBIG_UINT(pdata, data_len,
4011 (uint64_t)conn->session_info->unix_token->groups[i]);
4012 data_len += 8;
4015 /* SID list */
4016 for (i = 0;
4017 i < conn->session_info->security_token->num_sids; ++i) {
4018 int sid_len = ndr_size_dom_sid(
4019 &conn->session_info->security_token->sids[i],
4022 sid_linearize((uint8_t *)(pdata + data_len),
4023 sid_len,
4024 &conn->session_info->security_token->sids[i]);
4025 data_len += sid_len;
4028 break;
4031 case SMB_MAC_QUERY_FS_INFO:
4033 * Thursby MAC extension... ONLY on NTFS filesystems
4034 * once we do streams then we don't need this
4036 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4037 data_len = 88;
4038 SIVAL(pdata,84,0x100); /* Don't support mac... */
4039 break;
4041 /* drop through */
4042 default:
4043 return NT_STATUS_INVALID_LEVEL;
4046 *ret_data_len = data_len;
4047 return status;
4050 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4051 struct smb_request *req,
4052 files_struct *fsp,
4053 const DATA_BLOB *qdata)
4055 NTSTATUS status;
4056 SMB_NTQUOTA_STRUCT quotas;
4058 ZERO_STRUCT(quotas);
4060 /* access check */
4061 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4062 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4063 lp_servicename(talloc_tos(), SNUM(conn)),
4064 conn->session_info->unix_info->unix_name));
4065 return NT_STATUS_ACCESS_DENIED;
4068 if (!check_fsp_ntquota_handle(conn, req,
4069 fsp)) {
4070 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4071 return NT_STATUS_INVALID_HANDLE;
4074 /* note: normally there're 48 bytes,
4075 * but we didn't use the last 6 bytes for now
4076 * --metze
4078 if (qdata->length < 42) {
4079 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4080 (unsigned int)qdata->length));
4081 return NT_STATUS_INVALID_PARAMETER;
4084 /* unknown_1 24 NULL bytes in pdata*/
4086 /* the soft quotas 8 bytes (uint64_t)*/
4087 quotas.softlim = BVAL(qdata->data,24);
4089 /* the hard quotas 8 bytes (uint64_t)*/
4090 quotas.hardlim = BVAL(qdata->data,32);
4092 /* quota_flags 2 bytes **/
4093 quotas.qflags = SVAL(qdata->data,40);
4095 /* unknown_2 6 NULL bytes follow*/
4097 /* now set the quotas */
4098 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4099 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4100 lp_servicename(talloc_tos(), SNUM(conn))));
4101 status = map_nt_error_from_unix(errno);
4102 } else {
4103 status = NT_STATUS_OK;
4105 return status;
4108 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4109 struct smb_request *req,
4110 TALLOC_CTX *mem_ctx,
4111 uint16_t info_level,
4112 files_struct *fsp,
4113 const DATA_BLOB *pdata)
4115 switch (info_level) {
4116 case SMB_FS_QUOTA_INFORMATION:
4118 return smb_set_fsquota(conn,
4119 req,
4120 fsp,
4121 pdata);
4124 default:
4125 break;
4127 return NT_STATUS_INVALID_LEVEL;
4130 /****************************************************************************
4131 Reply to a TRANS2_QFSINFO (query filesystem info).
4132 ****************************************************************************/
4134 static void call_trans2qfsinfo(connection_struct *conn,
4135 struct smb_request *req,
4136 char **pparams, int total_params,
4137 char **ppdata, int total_data,
4138 unsigned int max_data_bytes)
4140 char *params = *pparams;
4141 uint16_t info_level;
4142 int data_len = 0;
4143 size_t fixed_portion;
4144 NTSTATUS status;
4146 if (total_params < 2) {
4147 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4148 return;
4151 info_level = SVAL(params,0);
4153 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4154 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4155 DEBUG(0,("call_trans2qfsinfo: encryption required "
4156 "and info level 0x%x sent.\n",
4157 (unsigned int)info_level));
4158 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4159 return;
4163 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4165 status = smbd_do_qfsinfo(req->xconn, conn, req,
4166 info_level,
4167 req->flags2,
4168 max_data_bytes,
4169 &fixed_portion,
4170 NULL,
4171 ppdata, &data_len);
4172 if (!NT_STATUS_IS_OK(status)) {
4173 reply_nterror(req, status);
4174 return;
4177 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4178 max_data_bytes);
4180 DEBUG( 4, ( "%s info_level = %d\n",
4181 smb_fn_name(req->cmd), info_level) );
4183 return;
4186 /****************************************************************************
4187 Reply to a TRANS2_SETFSINFO (set filesystem info).
4188 ****************************************************************************/
4190 static void call_trans2setfsinfo(connection_struct *conn,
4191 struct smb_request *req,
4192 char **pparams, int total_params,
4193 char **ppdata, int total_data,
4194 unsigned int max_data_bytes)
4196 struct smbXsrv_connection *xconn = req->xconn;
4197 char *pdata = *ppdata;
4198 char *params = *pparams;
4199 uint16_t info_level;
4201 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4202 lp_servicename(talloc_tos(), SNUM(conn))));
4204 /* */
4205 if (total_params < 4) {
4206 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4207 total_params));
4208 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4209 return;
4212 info_level = SVAL(params,2);
4214 if (IS_IPC(conn)) {
4215 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4216 info_level != SMB_SET_CIFS_UNIX_INFO) {
4217 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4218 "info level (0x%x) on IPC$.\n",
4219 (unsigned int)info_level));
4220 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4221 return;
4225 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4226 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4227 DEBUG(0,("call_trans2setfsinfo: encryption required "
4228 "and info level 0x%x sent.\n",
4229 (unsigned int)info_level));
4230 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4231 return;
4235 switch(info_level) {
4236 case SMB_SET_CIFS_UNIX_INFO:
4237 if (!lp_unix_extensions()) {
4238 DEBUG(2,("call_trans2setfsinfo: "
4239 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4240 "unix extensions off\n"));
4241 reply_nterror(req,
4242 NT_STATUS_INVALID_LEVEL);
4243 return;
4246 /* There should be 12 bytes of capabilities set. */
4247 if (total_data < 12) {
4248 reply_nterror(
4249 req,
4250 NT_STATUS_INVALID_PARAMETER);
4251 return;
4253 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4254 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4255 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4256 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4257 /* Just print these values for now. */
4258 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4259 "major = %u, minor = %u cap_low = 0x%x, "
4260 "cap_high = 0x%xn",
4261 (unsigned int)xconn->
4262 smb1.unix_info.client_major,
4263 (unsigned int)xconn->
4264 smb1.unix_info.client_minor,
4265 (unsigned int)xconn->
4266 smb1.unix_info.client_cap_low,
4267 (unsigned int)xconn->
4268 smb1.unix_info.client_cap_high));
4270 /* Here is where we must switch to posix pathname processing... */
4271 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4272 lp_set_posix_pathnames();
4273 mangle_change_to_posix();
4276 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4277 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4278 /* Client that knows how to do posix locks,
4279 * but not posix open/mkdir operations. Set a
4280 * default type for read/write checks. */
4282 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4285 break;
4287 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4289 NTSTATUS status;
4290 size_t param_len = 0;
4291 size_t data_len = total_data;
4293 if (!lp_unix_extensions()) {
4294 reply_nterror(
4295 req,
4296 NT_STATUS_INVALID_LEVEL);
4297 return;
4300 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4301 reply_nterror(
4302 req,
4303 NT_STATUS_NOT_SUPPORTED);
4304 return;
4307 if (xconn->smb1.echo_handler.trusted_fde) {
4308 DEBUG( 2,("call_trans2setfsinfo: "
4309 "request transport encryption disabled"
4310 "with 'fork echo handler = yes'\n"));
4311 reply_nterror(
4312 req,
4313 NT_STATUS_NOT_SUPPORTED);
4314 return;
4317 DEBUG( 4,("call_trans2setfsinfo: "
4318 "request transport encryption.\n"));
4320 status = srv_request_encryption_setup(conn,
4321 (unsigned char **)ppdata,
4322 &data_len,
4323 (unsigned char **)pparams,
4324 &param_len);
4326 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4327 !NT_STATUS_IS_OK(status)) {
4328 reply_nterror(req, status);
4329 return;
4332 send_trans2_replies(conn, req,
4333 NT_STATUS_OK,
4334 *pparams,
4335 param_len,
4336 *ppdata,
4337 data_len,
4338 max_data_bytes);
4340 if (NT_STATUS_IS_OK(status)) {
4341 /* Server-side transport
4342 * encryption is now *on*. */
4343 status = srv_encryption_start(conn);
4344 if (!NT_STATUS_IS_OK(status)) {
4345 char *reason = talloc_asprintf(talloc_tos(),
4346 "Failure in setting "
4347 "up encrypted transport: %s",
4348 nt_errstr(status));
4349 exit_server_cleanly(reason);
4352 return;
4355 case SMB_FS_QUOTA_INFORMATION:
4357 NTSTATUS status;
4358 DATA_BLOB qdata = {
4359 .data = (uint8_t *)pdata,
4360 .length = total_data
4362 files_struct *fsp = NULL;
4363 fsp = file_fsp(req, SVAL(params,0));
4365 status = smb_set_fsquota(conn,
4366 req,
4367 fsp,
4368 &qdata);
4369 if (!NT_STATUS_IS_OK(status)) {
4370 reply_nterror(req, status);
4371 return;
4373 break;
4375 default:
4376 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4377 info_level));
4378 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4379 return;
4380 break;
4384 * sending this reply works fine,
4385 * but I'm not sure it's the same
4386 * like windows do...
4387 * --metze
4389 reply_outbuf(req, 10, 0);
4392 #if defined(HAVE_POSIX_ACLS)
4393 /****************************************************************************
4394 Utility function to count the number of entries in a POSIX acl.
4395 ****************************************************************************/
4397 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4399 unsigned int ace_count = 0;
4400 int entry_id = SMB_ACL_FIRST_ENTRY;
4401 SMB_ACL_ENTRY_T entry;
4403 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4404 /* get_next... */
4405 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4406 entry_id = SMB_ACL_NEXT_ENTRY;
4408 ace_count++;
4410 return ace_count;
4413 /****************************************************************************
4414 Utility function to marshall a POSIX acl into wire format.
4415 ****************************************************************************/
4417 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4419 int entry_id = SMB_ACL_FIRST_ENTRY;
4420 SMB_ACL_ENTRY_T entry;
4422 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4423 SMB_ACL_TAG_T tagtype;
4424 SMB_ACL_PERMSET_T permset;
4425 unsigned char perms = 0;
4426 unsigned int own_grp;
4428 /* get_next... */
4429 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4430 entry_id = SMB_ACL_NEXT_ENTRY;
4433 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4434 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4435 return False;
4438 if (sys_acl_get_permset(entry, &permset) == -1) {
4439 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4440 return False;
4443 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4444 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4445 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4447 SCVAL(pdata,1,perms);
4449 switch (tagtype) {
4450 case SMB_ACL_USER_OBJ:
4451 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4452 own_grp = (unsigned int)pst->st_ex_uid;
4453 SIVAL(pdata,2,own_grp);
4454 SIVAL(pdata,6,0);
4455 break;
4456 case SMB_ACL_USER:
4458 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4459 if (!puid) {
4460 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4461 return False;
4463 own_grp = (unsigned int)*puid;
4464 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4465 SIVAL(pdata,2,own_grp);
4466 SIVAL(pdata,6,0);
4467 break;
4469 case SMB_ACL_GROUP_OBJ:
4470 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4471 own_grp = (unsigned int)pst->st_ex_gid;
4472 SIVAL(pdata,2,own_grp);
4473 SIVAL(pdata,6,0);
4474 break;
4475 case SMB_ACL_GROUP:
4477 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4478 if (!pgid) {
4479 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4480 return False;
4482 own_grp = (unsigned int)*pgid;
4483 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4484 SIVAL(pdata,2,own_grp);
4485 SIVAL(pdata,6,0);
4486 break;
4488 case SMB_ACL_MASK:
4489 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4490 SIVAL(pdata,2,0xFFFFFFFF);
4491 SIVAL(pdata,6,0xFFFFFFFF);
4492 break;
4493 case SMB_ACL_OTHER:
4494 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4495 SIVAL(pdata,2,0xFFFFFFFF);
4496 SIVAL(pdata,6,0xFFFFFFFF);
4497 break;
4498 default:
4499 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4500 return False;
4502 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4505 return True;
4507 #endif
4509 /****************************************************************************
4510 Store the FILE_UNIX_BASIC info.
4511 ****************************************************************************/
4513 static char *store_file_unix_basic(connection_struct *conn,
4514 char *pdata,
4515 files_struct *fsp,
4516 const SMB_STRUCT_STAT *psbuf)
4518 uint64_t file_index = get_FileIndex(conn, psbuf);
4519 dev_t devno;
4521 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4522 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4524 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4525 pdata += 8;
4527 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4528 pdata += 8;
4530 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4531 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4532 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4533 pdata += 24;
4535 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4536 SIVAL(pdata,4,0);
4537 pdata += 8;
4539 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4540 SIVAL(pdata,4,0);
4541 pdata += 8;
4543 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4544 pdata += 4;
4546 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4547 devno = psbuf->st_ex_rdev;
4548 } else {
4549 devno = psbuf->st_ex_dev;
4552 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4553 SIVAL(pdata,4,0);
4554 pdata += 8;
4556 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4557 SIVAL(pdata,4,0);
4558 pdata += 8;
4560 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4561 pdata += 8;
4563 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4564 SIVAL(pdata,4,0);
4565 pdata += 8;
4567 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4568 SIVAL(pdata,4,0);
4569 pdata += 8;
4571 return pdata;
4574 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4575 * the chflags(2) (or equivalent) flags.
4577 * XXX: this really should be behind the VFS interface. To do this, we would
4578 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4579 * Each VFS module could then implement its own mapping as appropriate for the
4580 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4582 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4583 info2_flags_map[] =
4585 #ifdef UF_NODUMP
4586 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4587 #endif
4589 #ifdef UF_IMMUTABLE
4590 { UF_IMMUTABLE, EXT_IMMUTABLE },
4591 #endif
4593 #ifdef UF_APPEND
4594 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4595 #endif
4597 #ifdef UF_HIDDEN
4598 { UF_HIDDEN, EXT_HIDDEN },
4599 #endif
4601 /* Do not remove. We need to guarantee that this array has at least one
4602 * entry to build on HP-UX.
4604 { 0, 0 }
4608 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4609 uint32_t *smb_fflags, uint32_t *smb_fmask)
4611 int i;
4613 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4614 *smb_fmask |= info2_flags_map[i].smb_fflag;
4615 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4616 *smb_fflags |= info2_flags_map[i].smb_fflag;
4621 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4622 const uint32_t smb_fflags,
4623 const uint32_t smb_fmask,
4624 int *stat_fflags)
4626 uint32_t max_fmask = 0;
4627 int i;
4629 *stat_fflags = psbuf->st_ex_flags;
4631 /* For each flags requested in smb_fmask, check the state of the
4632 * corresponding flag in smb_fflags and set or clear the matching
4633 * stat flag.
4636 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4637 max_fmask |= info2_flags_map[i].smb_fflag;
4638 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4639 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4640 *stat_fflags |= info2_flags_map[i].stat_fflag;
4641 } else {
4642 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4647 /* If smb_fmask is asking to set any bits that are not supported by
4648 * our flag mappings, we should fail.
4650 if ((smb_fmask & max_fmask) != smb_fmask) {
4651 return False;
4654 return True;
4658 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4659 * of file flags and birth (create) time.
4661 static char *store_file_unix_basic_info2(connection_struct *conn,
4662 char *pdata,
4663 files_struct *fsp,
4664 const SMB_STRUCT_STAT *psbuf)
4666 uint32_t file_flags = 0;
4667 uint32_t flags_mask = 0;
4669 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4671 /* Create (birth) time 64 bit */
4672 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4673 pdata += 8;
4675 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4676 SIVAL(pdata, 0, file_flags); /* flags */
4677 SIVAL(pdata, 4, flags_mask); /* mask */
4678 pdata += 8;
4680 return pdata;
4683 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4684 const struct stream_struct *streams,
4685 char *data,
4686 unsigned int max_data_bytes,
4687 unsigned int *data_size)
4689 unsigned int i;
4690 unsigned int ofs = 0;
4692 if (max_data_bytes < 32) {
4693 return NT_STATUS_INFO_LENGTH_MISMATCH;
4696 for (i = 0; i < num_streams; i++) {
4697 unsigned int next_offset;
4698 size_t namelen;
4699 smb_ucs2_t *namebuf;
4701 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4702 streams[i].name, &namelen) ||
4703 namelen <= 2)
4705 return NT_STATUS_INVALID_PARAMETER;
4709 * name_buf is now null-terminated, we need to marshall as not
4710 * terminated
4713 namelen -= 2;
4716 * We cannot overflow ...
4718 if ((ofs + 24 + namelen) > max_data_bytes) {
4719 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4720 i));
4721 TALLOC_FREE(namebuf);
4722 return STATUS_BUFFER_OVERFLOW;
4725 SIVAL(data, ofs+4, namelen);
4726 SOFF_T(data, ofs+8, streams[i].size);
4727 SOFF_T(data, ofs+16, streams[i].alloc_size);
4728 memcpy(data+ofs+24, namebuf, namelen);
4729 TALLOC_FREE(namebuf);
4731 next_offset = ofs + 24 + namelen;
4733 if (i == num_streams-1) {
4734 SIVAL(data, ofs, 0);
4736 else {
4737 unsigned int align = ndr_align_size(next_offset, 8);
4739 if ((next_offset + align) > max_data_bytes) {
4740 DEBUG(10, ("refusing to overflow align "
4741 "reply at stream %u\n",
4742 i));
4743 TALLOC_FREE(namebuf);
4744 return STATUS_BUFFER_OVERFLOW;
4747 memset(data+next_offset, 0, align);
4748 next_offset += align;
4750 SIVAL(data, ofs, next_offset - ofs);
4751 ofs = next_offset;
4754 ofs = next_offset;
4757 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4759 *data_size = ofs;
4761 return NT_STATUS_OK;
4764 /****************************************************************************
4765 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4766 ****************************************************************************/
4768 static void call_trans2qpipeinfo(connection_struct *conn,
4769 struct smb_request *req,
4770 unsigned int tran_call,
4771 char **pparams, int total_params,
4772 char **ppdata, int total_data,
4773 unsigned int max_data_bytes)
4775 char *params = *pparams;
4776 char *pdata = *ppdata;
4777 unsigned int data_size = 0;
4778 unsigned int param_size = 2;
4779 uint16_t info_level;
4780 files_struct *fsp;
4782 if (!params) {
4783 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4784 return;
4787 if (total_params < 4) {
4788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4789 return;
4792 fsp = file_fsp(req, SVAL(params,0));
4793 if (!fsp_is_np(fsp)) {
4794 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4795 return;
4798 info_level = SVAL(params,2);
4800 *pparams = (char *)SMB_REALLOC(*pparams,2);
4801 if (*pparams == NULL) {
4802 reply_nterror(req, NT_STATUS_NO_MEMORY);
4803 return;
4805 params = *pparams;
4806 SSVAL(params,0,0);
4807 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4809 return;
4811 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4812 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4813 if (*ppdata == NULL ) {
4814 reply_nterror(req, NT_STATUS_NO_MEMORY);
4815 return;
4817 pdata = *ppdata;
4819 switch (info_level) {
4820 case SMB_FILE_STANDARD_INFORMATION:
4821 memset(pdata,0,24);
4822 SOFF_T(pdata,0,4096LL);
4823 SIVAL(pdata,16,1);
4824 SIVAL(pdata,20,1);
4825 data_size = 24;
4826 break;
4828 default:
4829 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4830 return;
4833 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4834 max_data_bytes);
4836 return;
4839 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4840 TALLOC_CTX *mem_ctx,
4841 uint16_t info_level,
4842 files_struct *fsp,
4843 struct smb_filename *smb_fname,
4844 bool delete_pending,
4845 struct timespec write_time_ts,
4846 struct ea_list *ea_list,
4847 int lock_data_count,
4848 char *lock_data,
4849 uint16_t flags2,
4850 unsigned int max_data_bytes,
4851 size_t *fixed_portion,
4852 char **ppdata,
4853 unsigned int *pdata_size)
4855 char *pdata = *ppdata;
4856 char *dstart, *dend;
4857 unsigned int data_size;
4858 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4859 time_t create_time, mtime, atime, c_time;
4860 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4861 char *p;
4862 char *base_name;
4863 char *dos_fname;
4864 int mode;
4865 int nlink;
4866 NTSTATUS status;
4867 uint64_t file_size = 0;
4868 uint64_t pos = 0;
4869 uint64_t allocation_size = 0;
4870 uint64_t file_index = 0;
4871 uint32_t access_mask = 0;
4872 size_t len = 0;
4874 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4875 return NT_STATUS_INVALID_LEVEL;
4878 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4879 smb_fname_str_dbg(smb_fname),
4880 fsp_fnum_dbg(fsp),
4881 info_level, max_data_bytes));
4883 mode = dos_mode(conn, smb_fname);
4884 nlink = psbuf->st_ex_nlink;
4886 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4887 nlink = 1;
4890 if ((nlink > 0) && delete_pending) {
4891 nlink -= 1;
4894 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4895 return NT_STATUS_INVALID_PARAMETER;
4898 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4899 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4900 if (*ppdata == NULL) {
4901 return NT_STATUS_NO_MEMORY;
4903 pdata = *ppdata;
4904 dstart = pdata;
4905 dend = dstart + data_size - 1;
4907 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4908 update_stat_ex_mtime(psbuf, write_time_ts);
4911 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4912 mtime_ts = psbuf->st_ex_mtime;
4913 atime_ts = psbuf->st_ex_atime;
4914 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4916 if (lp_dos_filetime_resolution(SNUM(conn))) {
4917 dos_filetime_timespec(&create_time_ts);
4918 dos_filetime_timespec(&mtime_ts);
4919 dos_filetime_timespec(&atime_ts);
4920 dos_filetime_timespec(&ctime_ts);
4923 create_time = convert_timespec_to_time_t(create_time_ts);
4924 mtime = convert_timespec_to_time_t(mtime_ts);
4925 atime = convert_timespec_to_time_t(atime_ts);
4926 c_time = convert_timespec_to_time_t(ctime_ts);
4928 p = strrchr_m(smb_fname->base_name,'/');
4929 if (!p)
4930 base_name = smb_fname->base_name;
4931 else
4932 base_name = p+1;
4934 /* NT expects the name to be in an exact form of the *full*
4935 filename. See the trans2 torture test */
4936 if (ISDOT(base_name)) {
4937 dos_fname = talloc_strdup(mem_ctx, "\\");
4938 if (!dos_fname) {
4939 return NT_STATUS_NO_MEMORY;
4941 } else {
4942 dos_fname = talloc_asprintf(mem_ctx,
4943 "\\%s",
4944 smb_fname->base_name);
4945 if (!dos_fname) {
4946 return NT_STATUS_NO_MEMORY;
4948 if (is_ntfs_stream_smb_fname(smb_fname)) {
4949 dos_fname = talloc_asprintf(dos_fname, "%s",
4950 smb_fname->stream_name);
4951 if (!dos_fname) {
4952 return NT_STATUS_NO_MEMORY;
4956 string_replace(dos_fname, '/', '\\');
4959 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4961 if (!fsp) {
4962 /* Do we have this path open ? */
4963 files_struct *fsp1;
4964 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4965 fsp1 = file_find_di_first(conn->sconn, fileid);
4966 if (fsp1 && fsp1->initial_allocation_size) {
4967 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4971 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4972 file_size = get_file_size_stat(psbuf);
4975 if (fsp) {
4976 pos = fsp->fh->position_information;
4979 if (fsp) {
4980 access_mask = fsp->access_mask;
4981 } else {
4982 /* GENERIC_EXECUTE mapping from Windows */
4983 access_mask = 0x12019F;
4986 /* This should be an index number - looks like
4987 dev/ino to me :-)
4989 I think this causes us to fail the IFSKIT
4990 BasicFileInformationTest. -tpot */
4991 file_index = get_FileIndex(conn, psbuf);
4993 *fixed_portion = 0;
4995 switch (info_level) {
4996 case SMB_INFO_STANDARD:
4997 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4998 data_size = 22;
4999 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
5000 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
5001 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
5002 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
5003 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
5004 SSVAL(pdata,l1_attrFile,mode);
5005 break;
5007 case SMB_INFO_QUERY_EA_SIZE:
5009 unsigned int ea_size =
5010 estimate_ea_size(conn, fsp,
5011 smb_fname);
5012 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5013 data_size = 26;
5014 srv_put_dos_date2(pdata,0,create_time);
5015 srv_put_dos_date2(pdata,4,atime);
5016 srv_put_dos_date2(pdata,8,mtime); /* write time */
5017 SIVAL(pdata,12,(uint32_t)file_size);
5018 SIVAL(pdata,16,(uint32_t)allocation_size);
5019 SSVAL(pdata,20,mode);
5020 SIVAL(pdata,22,ea_size);
5021 break;
5024 case SMB_INFO_IS_NAME_VALID:
5025 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5026 if (fsp) {
5027 /* os/2 needs this ? really ?*/
5028 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5030 /* This is only reached for qpathinfo */
5031 data_size = 0;
5032 break;
5034 case SMB_INFO_QUERY_EAS_FROM_LIST:
5036 size_t total_ea_len = 0;
5037 struct ea_list *ea_file_list = NULL;
5038 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5040 status =
5041 get_ea_list_from_file(mem_ctx, conn, fsp,
5042 smb_fname,
5043 &total_ea_len, &ea_file_list);
5044 if (!NT_STATUS_IS_OK(status)) {
5045 return status;
5048 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5050 if (!ea_list || (total_ea_len > data_size)) {
5051 data_size = 4;
5052 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5053 break;
5056 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5057 break;
5060 case SMB_INFO_QUERY_ALL_EAS:
5062 /* We have data_size bytes to put EA's into. */
5063 size_t total_ea_len = 0;
5064 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5066 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5067 smb_fname,
5068 &total_ea_len, &ea_list);
5069 if (!NT_STATUS_IS_OK(status)) {
5070 return status;
5073 if (!ea_list || (total_ea_len > data_size)) {
5074 data_size = 4;
5075 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5076 break;
5079 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5080 break;
5083 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5085 /* This is FileFullEaInformation - 0xF which maps to
5086 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5088 /* We have data_size bytes to put EA's into. */
5089 size_t total_ea_len = 0;
5090 struct ea_list *ea_file_list = NULL;
5092 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5094 /*TODO: add filtering and index handling */
5096 status =
5097 get_ea_list_from_file(mem_ctx, conn, fsp,
5098 smb_fname,
5099 &total_ea_len, &ea_file_list);
5100 if (!NT_STATUS_IS_OK(status)) {
5101 return status;
5103 if (!ea_file_list) {
5104 return NT_STATUS_NO_EAS_ON_FILE;
5107 status = fill_ea_chained_buffer(mem_ctx,
5108 pdata,
5109 data_size,
5110 &data_size,
5111 conn, ea_file_list);
5112 if (!NT_STATUS_IS_OK(status)) {
5113 return status;
5115 break;
5118 case SMB_FILE_BASIC_INFORMATION:
5119 case SMB_QUERY_FILE_BASIC_INFO:
5121 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5122 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5123 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5124 } else {
5125 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5126 data_size = 40;
5127 SIVAL(pdata,36,0);
5129 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5130 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5131 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5132 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5133 SIVAL(pdata,32,mode);
5135 DEBUG(5,("SMB_QFBI - "));
5136 DEBUG(5,("create: %s ", ctime(&create_time)));
5137 DEBUG(5,("access: %s ", ctime(&atime)));
5138 DEBUG(5,("write: %s ", ctime(&mtime)));
5139 DEBUG(5,("change: %s ", ctime(&c_time)));
5140 DEBUG(5,("mode: %x\n", mode));
5141 *fixed_portion = data_size;
5142 break;
5144 case SMB_FILE_STANDARD_INFORMATION:
5145 case SMB_QUERY_FILE_STANDARD_INFO:
5147 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5148 data_size = 24;
5149 SOFF_T(pdata,0,allocation_size);
5150 SOFF_T(pdata,8,file_size);
5151 SIVAL(pdata,16,nlink);
5152 SCVAL(pdata,20,delete_pending?1:0);
5153 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5154 SSVAL(pdata,22,0); /* Padding. */
5155 *fixed_portion = 24;
5156 break;
5158 case SMB_FILE_EA_INFORMATION:
5159 case SMB_QUERY_FILE_EA_INFO:
5161 unsigned int ea_size =
5162 estimate_ea_size(conn, fsp, smb_fname);
5163 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5164 data_size = 4;
5165 *fixed_portion = 4;
5166 SIVAL(pdata,0,ea_size);
5167 break;
5170 /* Get the 8.3 name - used if NT SMB was negotiated. */
5171 case SMB_QUERY_FILE_ALT_NAME_INFO:
5172 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5174 char mangled_name[13];
5175 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5176 if (!name_to_8_3(base_name,mangled_name,
5177 True,conn->params)) {
5178 return NT_STATUS_NO_MEMORY;
5180 status = srvstr_push(dstart, flags2,
5181 pdata+4, mangled_name,
5182 PTR_DIFF(dend, pdata+4),
5183 STR_UNICODE, &len);
5184 if (!NT_STATUS_IS_OK(status)) {
5185 return status;
5187 data_size = 4 + len;
5188 SIVAL(pdata,0,len);
5189 *fixed_portion = 8;
5190 break;
5193 case SMB_QUERY_FILE_NAME_INFO:
5196 this must be *exactly* right for ACLs on mapped drives to work
5198 status = srvstr_push(dstart, flags2,
5199 pdata+4, dos_fname,
5200 PTR_DIFF(dend, pdata+4),
5201 STR_UNICODE, &len);
5202 if (!NT_STATUS_IS_OK(status)) {
5203 return status;
5205 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5206 data_size = 4 + len;
5207 SIVAL(pdata,0,len);
5208 break;
5211 case SMB_FILE_ALLOCATION_INFORMATION:
5212 case SMB_QUERY_FILE_ALLOCATION_INFO:
5213 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5214 data_size = 8;
5215 SOFF_T(pdata,0,allocation_size);
5216 break;
5218 case SMB_FILE_END_OF_FILE_INFORMATION:
5219 case SMB_QUERY_FILE_END_OF_FILEINFO:
5220 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5221 data_size = 8;
5222 SOFF_T(pdata,0,file_size);
5223 break;
5225 case SMB_QUERY_FILE_ALL_INFO:
5226 case SMB_FILE_ALL_INFORMATION:
5228 unsigned int ea_size =
5229 estimate_ea_size(conn, fsp, smb_fname);
5230 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5231 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5232 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5233 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5234 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5235 SIVAL(pdata,32,mode);
5236 SIVAL(pdata,36,0); /* padding. */
5237 pdata += 40;
5238 SOFF_T(pdata,0,allocation_size);
5239 SOFF_T(pdata,8,file_size);
5240 SIVAL(pdata,16,nlink);
5241 SCVAL(pdata,20,delete_pending);
5242 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5243 SSVAL(pdata,22,0);
5244 pdata += 24;
5245 SIVAL(pdata,0,ea_size);
5246 pdata += 4; /* EA info */
5247 status = srvstr_push(dstart, flags2,
5248 pdata+4, dos_fname,
5249 PTR_DIFF(dend, pdata+4),
5250 STR_UNICODE, &len);
5251 if (!NT_STATUS_IS_OK(status)) {
5252 return status;
5254 SIVAL(pdata,0,len);
5255 pdata += 4 + len;
5256 data_size = PTR_DIFF(pdata,(*ppdata));
5257 *fixed_portion = 10;
5258 break;
5261 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5263 unsigned int ea_size =
5264 estimate_ea_size(conn, fsp, smb_fname);
5265 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5266 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5267 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5268 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5269 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5270 SIVAL(pdata, 0x20, mode);
5271 SIVAL(pdata, 0x24, 0); /* padding. */
5272 SBVAL(pdata, 0x28, allocation_size);
5273 SBVAL(pdata, 0x30, file_size);
5274 SIVAL(pdata, 0x38, nlink);
5275 SCVAL(pdata, 0x3C, delete_pending);
5276 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5277 SSVAL(pdata, 0x3E, 0); /* padding */
5278 SBVAL(pdata, 0x40, file_index);
5279 SIVAL(pdata, 0x48, ea_size);
5280 SIVAL(pdata, 0x4C, access_mask);
5281 SBVAL(pdata, 0x50, pos);
5282 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5283 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5285 pdata += 0x60;
5287 status = srvstr_push(dstart, flags2,
5288 pdata+4, dos_fname,
5289 PTR_DIFF(dend, pdata+4),
5290 STR_UNICODE, &len);
5291 if (!NT_STATUS_IS_OK(status)) {
5292 return status;
5294 SIVAL(pdata,0,len);
5295 pdata += 4 + len;
5296 data_size = PTR_DIFF(pdata,(*ppdata));
5297 *fixed_portion = 104;
5298 break;
5300 case SMB_FILE_INTERNAL_INFORMATION:
5302 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5303 SBVAL(pdata, 0, file_index);
5304 data_size = 8;
5305 *fixed_portion = 8;
5306 break;
5308 case SMB_FILE_ACCESS_INFORMATION:
5309 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5310 SIVAL(pdata, 0, access_mask);
5311 data_size = 4;
5312 *fixed_portion = 4;
5313 break;
5315 case SMB_FILE_NAME_INFORMATION:
5316 /* Pathname with leading '\'. */
5318 size_t byte_len;
5319 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5320 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5321 SIVAL(pdata,0,byte_len);
5322 data_size = 4 + byte_len;
5323 break;
5326 case SMB_FILE_DISPOSITION_INFORMATION:
5327 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5328 data_size = 1;
5329 SCVAL(pdata,0,delete_pending);
5330 *fixed_portion = 1;
5331 break;
5333 case SMB_FILE_POSITION_INFORMATION:
5334 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5335 data_size = 8;
5336 SOFF_T(pdata,0,pos);
5337 *fixed_portion = 8;
5338 break;
5340 case SMB_FILE_MODE_INFORMATION:
5341 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5342 SIVAL(pdata,0,mode);
5343 data_size = 4;
5344 *fixed_portion = 4;
5345 break;
5347 case SMB_FILE_ALIGNMENT_INFORMATION:
5348 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5349 SIVAL(pdata,0,0); /* No alignment needed. */
5350 data_size = 4;
5351 *fixed_portion = 4;
5352 break;
5355 * NT4 server just returns "invalid query" to this - if we try
5356 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5357 * want this. JRA.
5359 /* The first statement above is false - verified using Thursby
5360 * client against NT4 -- gcolley.
5362 case SMB_QUERY_FILE_STREAM_INFO:
5363 case SMB_FILE_STREAM_INFORMATION: {
5364 unsigned int num_streams = 0;
5365 struct stream_struct *streams = NULL;
5367 DEBUG(10,("smbd_do_qfilepathinfo: "
5368 "SMB_FILE_STREAM_INFORMATION\n"));
5370 if (is_ntfs_stream_smb_fname(smb_fname)) {
5371 return NT_STATUS_INVALID_PARAMETER;
5374 status = vfs_streaminfo(conn,
5375 fsp,
5376 smb_fname,
5377 talloc_tos(),
5378 &num_streams,
5379 &streams);
5381 if (!NT_STATUS_IS_OK(status)) {
5382 DEBUG(10, ("could not get stream info: %s\n",
5383 nt_errstr(status)));
5384 return status;
5387 status = marshall_stream_info(num_streams, streams,
5388 pdata, max_data_bytes,
5389 &data_size);
5391 if (!NT_STATUS_IS_OK(status)) {
5392 DEBUG(10, ("marshall_stream_info failed: %s\n",
5393 nt_errstr(status)));
5394 TALLOC_FREE(streams);
5395 return status;
5398 TALLOC_FREE(streams);
5400 *fixed_portion = 32;
5402 break;
5404 case SMB_QUERY_COMPRESSION_INFO:
5405 case SMB_FILE_COMPRESSION_INFORMATION:
5406 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5407 SOFF_T(pdata,0,file_size);
5408 SIVAL(pdata,8,0); /* ??? */
5409 SIVAL(pdata,12,0); /* ??? */
5410 data_size = 16;
5411 *fixed_portion = 16;
5412 break;
5414 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5415 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5416 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5417 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5418 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5419 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5420 SOFF_T(pdata,32,allocation_size);
5421 SOFF_T(pdata,40,file_size);
5422 SIVAL(pdata,48,mode);
5423 SIVAL(pdata,52,0); /* ??? */
5424 data_size = 56;
5425 *fixed_portion = 56;
5426 break;
5428 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5429 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5430 SIVAL(pdata,0,mode);
5431 SIVAL(pdata,4,0);
5432 data_size = 8;
5433 *fixed_portion = 8;
5434 break;
5437 * CIFS UNIX Extensions.
5440 case SMB_QUERY_FILE_UNIX_BASIC:
5442 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5443 data_size = PTR_DIFF(pdata,(*ppdata));
5445 DEBUG(4,("smbd_do_qfilepathinfo: "
5446 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5447 dump_data(4, (uint8_t *)(*ppdata), data_size);
5449 break;
5451 case SMB_QUERY_FILE_UNIX_INFO2:
5453 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5454 data_size = PTR_DIFF(pdata,(*ppdata));
5457 int i;
5458 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5460 for (i=0; i<100; i++)
5461 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5462 DEBUG(4,("\n"));
5465 break;
5467 case SMB_QUERY_FILE_UNIX_LINK:
5469 int link_len = 0;
5470 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5472 if (!buffer) {
5473 return NT_STATUS_NO_MEMORY;
5476 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5477 #ifdef S_ISLNK
5478 if(!S_ISLNK(psbuf->st_ex_mode)) {
5479 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5481 #else
5482 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5483 #endif
5484 link_len = SMB_VFS_READLINK(conn,
5485 smb_fname,
5486 buffer, PATH_MAX);
5487 if (link_len == -1) {
5488 return map_nt_error_from_unix(errno);
5490 buffer[link_len] = 0;
5491 status = srvstr_push(dstart, flags2,
5492 pdata, buffer,
5493 PTR_DIFF(dend, pdata),
5494 STR_TERMINATE, &len);
5495 if (!NT_STATUS_IS_OK(status)) {
5496 return status;
5498 pdata += len;
5499 data_size = PTR_DIFF(pdata,(*ppdata));
5501 break;
5504 #if defined(HAVE_POSIX_ACLS)
5505 case SMB_QUERY_POSIX_ACL:
5507 SMB_ACL_T file_acl = NULL;
5508 SMB_ACL_T def_acl = NULL;
5509 uint16_t num_file_acls = 0;
5510 uint16_t num_def_acls = 0;
5512 status = refuse_symlink(conn,
5513 fsp,
5514 smb_fname);
5515 if (!NT_STATUS_IS_OK(status)) {
5516 return status;
5519 if (fsp && fsp->fh->fd != -1) {
5520 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5521 talloc_tos());
5522 } else {
5523 file_acl =
5524 SMB_VFS_SYS_ACL_GET_FILE(conn,
5525 smb_fname,
5526 SMB_ACL_TYPE_ACCESS,
5527 talloc_tos());
5530 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5531 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5532 "not implemented on "
5533 "filesystem containing %s\n",
5534 smb_fname->base_name));
5535 return NT_STATUS_NOT_IMPLEMENTED;
5538 if (S_ISDIR(psbuf->st_ex_mode)) {
5539 if (fsp && fsp->is_directory) {
5540 def_acl =
5541 SMB_VFS_SYS_ACL_GET_FILE(
5542 conn,
5543 fsp->fsp_name,
5544 SMB_ACL_TYPE_DEFAULT,
5545 talloc_tos());
5546 } else {
5547 def_acl =
5548 SMB_VFS_SYS_ACL_GET_FILE(
5549 conn,
5550 smb_fname,
5551 SMB_ACL_TYPE_DEFAULT,
5552 talloc_tos());
5554 def_acl = free_empty_sys_acl(conn, def_acl);
5557 num_file_acls = count_acl_entries(conn, file_acl);
5558 num_def_acls = count_acl_entries(conn, def_acl);
5560 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5561 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5562 data_size,
5563 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5564 SMB_POSIX_ACL_HEADER_SIZE) ));
5565 if (file_acl) {
5566 TALLOC_FREE(file_acl);
5568 if (def_acl) {
5569 TALLOC_FREE(def_acl);
5571 return NT_STATUS_BUFFER_TOO_SMALL;
5574 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5575 SSVAL(pdata,2,num_file_acls);
5576 SSVAL(pdata,4,num_def_acls);
5577 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5578 if (file_acl) {
5579 TALLOC_FREE(file_acl);
5581 if (def_acl) {
5582 TALLOC_FREE(def_acl);
5584 return NT_STATUS_INTERNAL_ERROR;
5586 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5587 if (file_acl) {
5588 TALLOC_FREE(file_acl);
5590 if (def_acl) {
5591 TALLOC_FREE(def_acl);
5593 return NT_STATUS_INTERNAL_ERROR;
5596 if (file_acl) {
5597 TALLOC_FREE(file_acl);
5599 if (def_acl) {
5600 TALLOC_FREE(def_acl);
5602 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5603 break;
5605 #endif
5608 case SMB_QUERY_POSIX_LOCK:
5610 uint64_t count;
5611 uint64_t offset;
5612 uint64_t smblctx;
5613 enum brl_type lock_type;
5615 /* We need an open file with a real fd for this. */
5616 if (!fsp || fsp->fh->fd == -1) {
5617 return NT_STATUS_INVALID_LEVEL;
5620 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5621 return NT_STATUS_INVALID_PARAMETER;
5624 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5625 case POSIX_LOCK_TYPE_READ:
5626 lock_type = READ_LOCK;
5627 break;
5628 case POSIX_LOCK_TYPE_WRITE:
5629 lock_type = WRITE_LOCK;
5630 break;
5631 case POSIX_LOCK_TYPE_UNLOCK:
5632 default:
5633 /* There's no point in asking for an unlock... */
5634 return NT_STATUS_INVALID_PARAMETER;
5637 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5638 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5639 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5641 status = query_lock(fsp,
5642 &smblctx,
5643 &count,
5644 &offset,
5645 &lock_type,
5646 POSIX_LOCK);
5648 if (ERROR_WAS_LOCK_DENIED(status)) {
5649 /* Here we need to report who has it locked... */
5650 data_size = POSIX_LOCK_DATA_SIZE;
5652 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5653 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5654 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5655 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5656 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5658 } else if (NT_STATUS_IS_OK(status)) {
5659 /* For success we just return a copy of what we sent
5660 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5661 data_size = POSIX_LOCK_DATA_SIZE;
5662 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5663 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5664 } else {
5665 return status;
5667 break;
5670 default:
5671 return NT_STATUS_INVALID_LEVEL;
5674 *pdata_size = data_size;
5675 return NT_STATUS_OK;
5678 /****************************************************************************
5679 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5680 file name or file id).
5681 ****************************************************************************/
5683 static void call_trans2qfilepathinfo(connection_struct *conn,
5684 struct smb_request *req,
5685 unsigned int tran_call,
5686 char **pparams, int total_params,
5687 char **ppdata, int total_data,
5688 unsigned int max_data_bytes)
5690 char *params = *pparams;
5691 char *pdata = *ppdata;
5692 uint16_t info_level;
5693 unsigned int data_size = 0;
5694 unsigned int param_size = 2;
5695 struct smb_filename *smb_fname = NULL;
5696 bool delete_pending = False;
5697 struct timespec write_time_ts;
5698 files_struct *fsp = NULL;
5699 struct file_id fileid;
5700 struct ea_list *ea_list = NULL;
5701 int lock_data_count = 0;
5702 char *lock_data = NULL;
5703 size_t fixed_portion;
5704 NTSTATUS status = NT_STATUS_OK;
5706 if (!params) {
5707 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5708 return;
5711 ZERO_STRUCT(write_time_ts);
5713 if (tran_call == TRANSACT2_QFILEINFO) {
5714 if (total_params < 4) {
5715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5716 return;
5719 if (IS_IPC(conn)) {
5720 call_trans2qpipeinfo(conn, req, tran_call,
5721 pparams, total_params,
5722 ppdata, total_data,
5723 max_data_bytes);
5724 return;
5727 fsp = file_fsp(req, SVAL(params,0));
5728 info_level = SVAL(params,2);
5730 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5732 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5733 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5734 return;
5737 /* Initial check for valid fsp ptr. */
5738 if (!check_fsp_open(conn, req, fsp)) {
5739 return;
5742 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5743 if (smb_fname == NULL) {
5744 reply_nterror(req, NT_STATUS_NO_MEMORY);
5745 return;
5748 if(fsp->fake_file_handle) {
5750 * This is actually for the QUOTA_FAKE_FILE --metze
5753 /* We know this name is ok, it's already passed the checks. */
5755 } else if(fsp->fh->fd == -1) {
5757 * This is actually a QFILEINFO on a directory
5758 * handle (returned from an NT SMB). NT5.0 seems
5759 * to do this call. JRA.
5762 if (INFO_LEVEL_IS_UNIX(info_level)) {
5763 /* Always do lstat for UNIX calls. */
5764 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5765 DEBUG(3,("call_trans2qfilepathinfo: "
5766 "SMB_VFS_LSTAT of %s failed "
5767 "(%s)\n",
5768 smb_fname_str_dbg(smb_fname),
5769 strerror(errno)));
5770 reply_nterror(req,
5771 map_nt_error_from_unix(errno));
5772 return;
5774 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5775 DEBUG(3,("call_trans2qfilepathinfo: "
5776 "SMB_VFS_STAT of %s failed (%s)\n",
5777 smb_fname_str_dbg(smb_fname),
5778 strerror(errno)));
5779 reply_nterror(req,
5780 map_nt_error_from_unix(errno));
5781 return;
5784 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5785 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5786 } else {
5788 * Original code - this is an open file.
5790 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5791 DEBUG(3, ("fstat of %s failed (%s)\n",
5792 fsp_fnum_dbg(fsp), strerror(errno)));
5793 reply_nterror(req,
5794 map_nt_error_from_unix(errno));
5795 return;
5797 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5798 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5801 } else {
5802 uint32_t name_hash;
5803 char *fname = NULL;
5804 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5806 /* qpathinfo */
5807 if (total_params < 7) {
5808 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5809 return;
5812 info_level = SVAL(params,0);
5814 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5816 if (INFO_LEVEL_IS_UNIX(info_level)) {
5817 if (!lp_unix_extensions()) {
5818 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5819 return;
5821 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5822 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5823 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5824 req->posix_pathnames) {
5825 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5829 if (req->posix_pathnames) {
5830 srvstr_get_path_posix(req,
5831 params,
5832 req->flags2,
5833 &fname,
5834 &params[6],
5835 total_params - 6,
5836 STR_TERMINATE,
5837 &status);
5838 } else {
5839 srvstr_get_path(req,
5840 params,
5841 req->flags2,
5842 &fname,
5843 &params[6],
5844 total_params - 6,
5845 STR_TERMINATE,
5846 &status);
5848 if (!NT_STATUS_IS_OK(status)) {
5849 reply_nterror(req, status);
5850 return;
5853 status = filename_convert(req,
5854 conn,
5855 fname,
5856 ucf_flags,
5857 NULL,
5858 &smb_fname);
5859 if (!NT_STATUS_IS_OK(status)) {
5860 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5861 reply_botherror(req,
5862 NT_STATUS_PATH_NOT_COVERED,
5863 ERRSRV, ERRbadpath);
5864 return;
5866 reply_nterror(req, status);
5867 return;
5870 /* If this is a stream, check if there is a delete_pending. */
5871 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5872 && is_ntfs_stream_smb_fname(smb_fname)) {
5873 struct smb_filename *smb_fname_base;
5875 /* Create an smb_filename with stream_name == NULL. */
5876 smb_fname_base = synthetic_smb_fname(
5877 talloc_tos(),
5878 smb_fname->base_name,
5879 NULL,
5880 NULL,
5881 smb_fname->flags);
5882 if (smb_fname_base == NULL) {
5883 reply_nterror(req, NT_STATUS_NO_MEMORY);
5884 return;
5887 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5888 /* Always do lstat for UNIX calls. */
5889 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5890 DEBUG(3,("call_trans2qfilepathinfo: "
5891 "SMB_VFS_LSTAT of %s failed "
5892 "(%s)\n",
5893 smb_fname_str_dbg(smb_fname_base),
5894 strerror(errno)));
5895 TALLOC_FREE(smb_fname_base);
5896 reply_nterror(req,
5897 map_nt_error_from_unix(errno));
5898 return;
5900 } else {
5901 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5902 DEBUG(3,("call_trans2qfilepathinfo: "
5903 "fileinfo of %s failed "
5904 "(%s)\n",
5905 smb_fname_str_dbg(smb_fname_base),
5906 strerror(errno)));
5907 TALLOC_FREE(smb_fname_base);
5908 reply_nterror(req,
5909 map_nt_error_from_unix(errno));
5910 return;
5914 status = file_name_hash(conn,
5915 smb_fname_str_dbg(smb_fname_base),
5916 &name_hash);
5917 if (!NT_STATUS_IS_OK(status)) {
5918 TALLOC_FREE(smb_fname_base);
5919 reply_nterror(req, status);
5920 return;
5923 fileid = vfs_file_id_from_sbuf(conn,
5924 &smb_fname_base->st);
5925 TALLOC_FREE(smb_fname_base);
5926 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5927 if (delete_pending) {
5928 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5929 return;
5933 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5934 /* Always do lstat for UNIX calls. */
5935 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5936 DEBUG(3,("call_trans2qfilepathinfo: "
5937 "SMB_VFS_LSTAT of %s failed (%s)\n",
5938 smb_fname_str_dbg(smb_fname),
5939 strerror(errno)));
5940 reply_nterror(req,
5941 map_nt_error_from_unix(errno));
5942 return;
5945 } else {
5946 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5947 DEBUG(3,("call_trans2qfilepathinfo: "
5948 "SMB_VFS_STAT of %s failed (%s)\n",
5949 smb_fname_str_dbg(smb_fname),
5950 strerror(errno)));
5951 reply_nterror(req,
5952 map_nt_error_from_unix(errno));
5953 return;
5957 status = file_name_hash(conn,
5958 smb_fname_str_dbg(smb_fname),
5959 &name_hash);
5960 if (!NT_STATUS_IS_OK(status)) {
5961 reply_nterror(req, status);
5962 return;
5965 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5966 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5967 if (delete_pending) {
5968 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5969 return;
5973 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5974 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5975 fsp_fnum_dbg(fsp),
5976 info_level,tran_call,total_data));
5978 /* Pull out any data sent here before we realloc. */
5979 switch (info_level) {
5980 case SMB_INFO_QUERY_EAS_FROM_LIST:
5982 /* Pull any EA list from the data portion. */
5983 uint32_t ea_size;
5985 if (total_data < 4) {
5986 reply_nterror(
5987 req, NT_STATUS_INVALID_PARAMETER);
5988 return;
5990 ea_size = IVAL(pdata,0);
5992 if (total_data > 0 && ea_size != total_data) {
5993 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5994 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5995 reply_nterror(
5996 req, NT_STATUS_INVALID_PARAMETER);
5997 return;
6000 if (!lp_ea_support(SNUM(conn))) {
6001 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
6002 return;
6005 /* Pull out the list of names. */
6006 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6007 if (!ea_list) {
6008 reply_nterror(
6009 req, NT_STATUS_INVALID_PARAMETER);
6010 return;
6012 break;
6015 case SMB_QUERY_POSIX_LOCK:
6017 if (fsp == NULL || fsp->fh->fd == -1) {
6018 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6019 return;
6022 if (total_data != POSIX_LOCK_DATA_SIZE) {
6023 reply_nterror(
6024 req, NT_STATUS_INVALID_PARAMETER);
6025 return;
6028 /* Copy the lock range data. */
6029 lock_data = (char *)talloc_memdup(
6030 req, pdata, total_data);
6031 if (!lock_data) {
6032 reply_nterror(req, NT_STATUS_NO_MEMORY);
6033 return;
6035 lock_data_count = total_data;
6037 default:
6038 break;
6041 *pparams = (char *)SMB_REALLOC(*pparams,2);
6042 if (*pparams == NULL) {
6043 reply_nterror(req, NT_STATUS_NO_MEMORY);
6044 return;
6046 params = *pparams;
6047 SSVAL(params,0,0);
6050 * draft-leach-cifs-v1-spec-02.txt
6051 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6052 * says:
6054 * The requested information is placed in the Data portion of the
6055 * transaction response. For the information levels greater than 0x100,
6056 * the transaction response has 1 parameter word which should be
6057 * ignored by the client.
6059 * However Windows only follows this rule for the IS_NAME_VALID call.
6061 switch (info_level) {
6062 case SMB_INFO_IS_NAME_VALID:
6063 param_size = 0;
6064 break;
6067 if ((info_level & 0xFF00) == 0xFF00) {
6069 * We use levels that start with 0xFF00
6070 * internally to represent SMB2 specific levels
6072 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6073 return;
6076 status = smbd_do_qfilepathinfo(conn, req, info_level,
6077 fsp, smb_fname,
6078 delete_pending, write_time_ts,
6079 ea_list,
6080 lock_data_count, lock_data,
6081 req->flags2, max_data_bytes,
6082 &fixed_portion,
6083 ppdata, &data_size);
6084 if (!NT_STATUS_IS_OK(status)) {
6085 reply_nterror(req, status);
6086 return;
6088 if (fixed_portion > max_data_bytes) {
6089 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6090 return;
6093 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6094 max_data_bytes);
6096 return;
6099 /****************************************************************************
6100 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6101 code.
6102 ****************************************************************************/
6104 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6105 connection_struct *conn,
6106 struct smb_request *req,
6107 bool overwrite_if_exists,
6108 const struct smb_filename *smb_fname_old,
6109 struct smb_filename *smb_fname_new)
6111 NTSTATUS status = NT_STATUS_OK;
6113 /* source must already exist. */
6114 if (!VALID_STAT(smb_fname_old->st)) {
6115 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6118 if (VALID_STAT(smb_fname_new->st)) {
6119 if (overwrite_if_exists) {
6120 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6121 return NT_STATUS_FILE_IS_A_DIRECTORY;
6123 status = unlink_internals(conn,
6124 req,
6125 FILE_ATTRIBUTE_NORMAL,
6126 smb_fname_new,
6127 false);
6128 if (!NT_STATUS_IS_OK(status)) {
6129 return status;
6131 } else {
6132 /* Disallow if newname already exists. */
6133 return NT_STATUS_OBJECT_NAME_COLLISION;
6137 /* No links from a directory. */
6138 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6139 return NT_STATUS_FILE_IS_A_DIRECTORY;
6142 /* Setting a hardlink to/from a stream isn't currently supported. */
6143 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6144 is_ntfs_stream_smb_fname(smb_fname_new)) {
6145 return NT_STATUS_INVALID_PARAMETER;
6148 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6149 smb_fname_old->base_name, smb_fname_new->base_name));
6151 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6152 status = map_nt_error_from_unix(errno);
6153 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6154 nt_errstr(status), smb_fname_old->base_name,
6155 smb_fname_new->base_name));
6157 return status;
6160 /****************************************************************************
6161 Deal with setting the time from any of the setfilepathinfo functions.
6162 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6163 calling this function.
6164 ****************************************************************************/
6166 NTSTATUS smb_set_file_time(connection_struct *conn,
6167 files_struct *fsp,
6168 const struct smb_filename *smb_fname,
6169 struct smb_file_time *ft,
6170 bool setting_write_time)
6172 struct smb_filename smb_fname_base;
6173 uint32_t action =
6174 FILE_NOTIFY_CHANGE_LAST_ACCESS
6175 |FILE_NOTIFY_CHANGE_LAST_WRITE
6176 |FILE_NOTIFY_CHANGE_CREATION;
6178 if (!VALID_STAT(smb_fname->st)) {
6179 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6182 /* get some defaults (no modifications) if any info is zero or -1. */
6183 if (null_timespec(ft->create_time)) {
6184 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6187 if (null_timespec(ft->atime)) {
6188 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6191 if (null_timespec(ft->mtime)) {
6192 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6195 if (!setting_write_time) {
6196 /* ft->mtime comes from change time, not write time. */
6197 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6200 /* Ensure the resolution is the correct for
6201 * what we can store on this filesystem. */
6203 round_timespec(conn->ts_res, &ft->create_time);
6204 round_timespec(conn->ts_res, &ft->ctime);
6205 round_timespec(conn->ts_res, &ft->atime);
6206 round_timespec(conn->ts_res, &ft->mtime);
6208 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6209 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6210 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6211 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6212 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6213 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6214 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6215 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6217 if (setting_write_time) {
6219 * This was a Windows setfileinfo on an open file.
6220 * NT does this a lot. We also need to
6221 * set the time here, as it can be read by
6222 * FindFirst/FindNext and with the patch for bug #2045
6223 * in smbd/fileio.c it ensures that this timestamp is
6224 * kept sticky even after a write. We save the request
6225 * away and will set it on file close and after a write. JRA.
6228 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6229 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6231 if (fsp != NULL) {
6232 if (fsp->base_fsp) {
6233 set_sticky_write_time_fsp(fsp->base_fsp,
6234 ft->mtime);
6235 } else {
6236 set_sticky_write_time_fsp(fsp, ft->mtime);
6238 } else {
6239 set_sticky_write_time_path(
6240 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6241 ft->mtime);
6245 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6247 /* Always call ntimes on the base, even if a stream was passed in. */
6248 smb_fname_base = *smb_fname;
6249 smb_fname_base.stream_name = NULL;
6251 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6252 return map_nt_error_from_unix(errno);
6255 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6256 smb_fname->base_name);
6257 return NT_STATUS_OK;
6260 /****************************************************************************
6261 Deal with setting the dosmode from any of the setfilepathinfo functions.
6262 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6263 done before calling this function.
6264 ****************************************************************************/
6266 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6267 const struct smb_filename *smb_fname,
6268 uint32_t dosmode)
6270 struct smb_filename *smb_fname_base;
6271 NTSTATUS status;
6273 if (!VALID_STAT(smb_fname->st)) {
6274 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6277 /* Always operate on the base_name, even if a stream was passed in. */
6278 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6279 smb_fname->base_name,
6280 NULL,
6281 &smb_fname->st,
6282 smb_fname->flags);
6283 if (smb_fname_base == NULL) {
6284 return NT_STATUS_NO_MEMORY;
6287 if (dosmode) {
6288 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6289 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6290 } else {
6291 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6295 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6297 /* check the mode isn't different, before changing it */
6298 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6299 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6300 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6301 (unsigned int)dosmode));
6303 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6304 false)) {
6305 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6306 "%s failed (%s)\n",
6307 smb_fname_str_dbg(smb_fname_base),
6308 strerror(errno)));
6309 status = map_nt_error_from_unix(errno);
6310 goto out;
6313 status = NT_STATUS_OK;
6314 out:
6315 TALLOC_FREE(smb_fname_base);
6316 return status;
6319 /****************************************************************************
6320 Deal with setting the size from any of the setfilepathinfo functions.
6321 ****************************************************************************/
6323 static NTSTATUS smb_set_file_size(connection_struct *conn,
6324 struct smb_request *req,
6325 files_struct *fsp,
6326 const struct smb_filename *smb_fname,
6327 const SMB_STRUCT_STAT *psbuf,
6328 off_t size,
6329 bool fail_after_createfile)
6331 NTSTATUS status = NT_STATUS_OK;
6332 struct smb_filename *smb_fname_tmp = NULL;
6333 files_struct *new_fsp = NULL;
6335 if (!VALID_STAT(*psbuf)) {
6336 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6339 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6341 if (size == get_file_size_stat(psbuf)) {
6342 return NT_STATUS_OK;
6345 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6346 smb_fname_str_dbg(smb_fname), (double)size));
6348 if (fsp && fsp->fh->fd != -1) {
6349 /* Handle based call. */
6350 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6351 return NT_STATUS_ACCESS_DENIED;
6354 if (vfs_set_filelen(fsp, size) == -1) {
6355 return map_nt_error_from_unix(errno);
6357 trigger_write_time_update_immediate(fsp);
6358 return NT_STATUS_OK;
6361 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6362 if (smb_fname_tmp == NULL) {
6363 return NT_STATUS_NO_MEMORY;
6366 smb_fname_tmp->st = *psbuf;
6368 status = SMB_VFS_CREATE_FILE(
6369 conn, /* conn */
6370 req, /* req */
6371 0, /* root_dir_fid */
6372 smb_fname_tmp, /* fname */
6373 FILE_WRITE_DATA, /* access_mask */
6374 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6375 FILE_SHARE_DELETE),
6376 FILE_OPEN, /* create_disposition*/
6377 0, /* create_options */
6378 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6379 0, /* oplock_request */
6380 NULL, /* lease */
6381 0, /* allocation_size */
6382 0, /* private_flags */
6383 NULL, /* sd */
6384 NULL, /* ea_list */
6385 &new_fsp, /* result */
6386 NULL, /* pinfo */
6387 NULL, NULL); /* create context */
6389 TALLOC_FREE(smb_fname_tmp);
6391 if (!NT_STATUS_IS_OK(status)) {
6392 /* NB. We check for open_was_deferred in the caller. */
6393 return status;
6396 /* See RAW-SFILEINFO-END-OF-FILE */
6397 if (fail_after_createfile) {
6398 close_file(req, new_fsp,NORMAL_CLOSE);
6399 return NT_STATUS_INVALID_LEVEL;
6402 if (vfs_set_filelen(new_fsp, size) == -1) {
6403 status = map_nt_error_from_unix(errno);
6404 close_file(req, new_fsp,NORMAL_CLOSE);
6405 return status;
6408 trigger_write_time_update_immediate(new_fsp);
6409 close_file(req, new_fsp,NORMAL_CLOSE);
6410 return NT_STATUS_OK;
6413 /****************************************************************************
6414 Deal with SMB_INFO_SET_EA.
6415 ****************************************************************************/
6417 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6418 const char *pdata,
6419 int total_data,
6420 files_struct *fsp,
6421 const struct smb_filename *smb_fname)
6423 struct ea_list *ea_list = NULL;
6424 TALLOC_CTX *ctx = NULL;
6425 NTSTATUS status = NT_STATUS_OK;
6427 if (total_data < 10) {
6429 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6430 length. They seem to have no effect. Bug #3212. JRA */
6432 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6433 /* We're done. We only get EA info in this call. */
6434 return NT_STATUS_OK;
6437 return NT_STATUS_INVALID_PARAMETER;
6440 if (IVAL(pdata,0) > total_data) {
6441 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6442 IVAL(pdata,0), (unsigned int)total_data));
6443 return NT_STATUS_INVALID_PARAMETER;
6446 ctx = talloc_tos();
6447 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6448 if (!ea_list) {
6449 return NT_STATUS_INVALID_PARAMETER;
6452 status = set_ea(conn, fsp, smb_fname, ea_list);
6454 return status;
6457 /****************************************************************************
6458 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6459 ****************************************************************************/
6461 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6462 const char *pdata,
6463 int total_data,
6464 files_struct *fsp)
6466 struct ea_list *ea_list = NULL;
6467 NTSTATUS status;
6469 if (!fsp) {
6470 return NT_STATUS_INVALID_HANDLE;
6473 if (!lp_ea_support(SNUM(conn))) {
6474 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6475 "EA's not supported.\n",
6476 (unsigned int)total_data));
6477 return NT_STATUS_EAS_NOT_SUPPORTED;
6480 if (total_data < 10) {
6481 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6482 "too small.\n",
6483 (unsigned int)total_data));
6484 return NT_STATUS_INVALID_PARAMETER;
6487 ea_list = read_nttrans_ea_list(talloc_tos(),
6488 pdata,
6489 total_data);
6491 if (!ea_list) {
6492 return NT_STATUS_INVALID_PARAMETER;
6495 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6497 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6498 smb_fname_str_dbg(fsp->fsp_name),
6499 nt_errstr(status) ));
6501 return status;
6505 /****************************************************************************
6506 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6507 ****************************************************************************/
6509 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6510 const char *pdata,
6511 int total_data,
6512 files_struct *fsp,
6513 struct smb_filename *smb_fname)
6515 NTSTATUS status = NT_STATUS_OK;
6516 bool delete_on_close;
6517 uint32_t dosmode = 0;
6519 if (total_data < 1) {
6520 return NT_STATUS_INVALID_PARAMETER;
6523 if (fsp == NULL) {
6524 return NT_STATUS_INVALID_HANDLE;
6527 delete_on_close = (CVAL(pdata,0) ? True : False);
6528 dosmode = dos_mode(conn, smb_fname);
6530 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6531 "delete_on_close = %u\n",
6532 smb_fname_str_dbg(smb_fname),
6533 (unsigned int)dosmode,
6534 (unsigned int)delete_on_close ));
6536 if (delete_on_close) {
6537 status = can_set_delete_on_close(fsp, dosmode);
6538 if (!NT_STATUS_IS_OK(status)) {
6539 return status;
6543 /* The set is across all open files on this dev/inode pair. */
6544 if (!set_delete_on_close(fsp, delete_on_close,
6545 conn->session_info->security_token,
6546 conn->session_info->unix_token)) {
6547 return NT_STATUS_ACCESS_DENIED;
6549 return NT_STATUS_OK;
6552 /****************************************************************************
6553 Deal with SMB_FILE_POSITION_INFORMATION.
6554 ****************************************************************************/
6556 static NTSTATUS smb_file_position_information(connection_struct *conn,
6557 const char *pdata,
6558 int total_data,
6559 files_struct *fsp)
6561 uint64_t position_information;
6563 if (total_data < 8) {
6564 return NT_STATUS_INVALID_PARAMETER;
6567 if (fsp == NULL) {
6568 /* Ignore on pathname based set. */
6569 return NT_STATUS_OK;
6572 position_information = (uint64_t)IVAL(pdata,0);
6573 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6575 DEBUG(10,("smb_file_position_information: Set file position "
6576 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6577 (double)position_information));
6578 fsp->fh->position_information = position_information;
6579 return NT_STATUS_OK;
6582 /****************************************************************************
6583 Deal with SMB_FILE_MODE_INFORMATION.
6584 ****************************************************************************/
6586 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6587 const char *pdata,
6588 int total_data)
6590 uint32_t mode;
6592 if (total_data < 4) {
6593 return NT_STATUS_INVALID_PARAMETER;
6595 mode = IVAL(pdata,0);
6596 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6597 return NT_STATUS_INVALID_PARAMETER;
6599 return NT_STATUS_OK;
6602 /****************************************************************************
6603 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6604 ****************************************************************************/
6606 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6607 struct smb_request *req,
6608 const char *pdata,
6609 int total_data,
6610 const struct smb_filename *new_smb_fname)
6612 char *link_target = NULL;
6613 TALLOC_CTX *ctx = talloc_tos();
6615 /* Set a symbolic link. */
6616 /* Don't allow this if follow links is false. */
6618 if (total_data == 0) {
6619 return NT_STATUS_INVALID_PARAMETER;
6622 if (!lp_follow_symlinks(SNUM(conn))) {
6623 return NT_STATUS_ACCESS_DENIED;
6626 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6627 total_data, STR_TERMINATE);
6629 if (!link_target) {
6630 return NT_STATUS_INVALID_PARAMETER;
6633 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6634 new_smb_fname->base_name, link_target ));
6636 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6637 return map_nt_error_from_unix(errno);
6640 return NT_STATUS_OK;
6643 /****************************************************************************
6644 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6645 ****************************************************************************/
6647 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6648 struct smb_request *req,
6649 const char *pdata, int total_data,
6650 struct smb_filename *smb_fname_new)
6652 char *oldname = NULL;
6653 struct smb_filename *smb_fname_old = NULL;
6654 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6655 TALLOC_CTX *ctx = talloc_tos();
6656 NTSTATUS status = NT_STATUS_OK;
6658 /* Set a hard link. */
6659 if (total_data == 0) {
6660 return NT_STATUS_INVALID_PARAMETER;
6663 if (req->posix_pathnames) {
6664 srvstr_get_path_posix(ctx,
6665 pdata,
6666 req->flags2,
6667 &oldname,
6668 pdata,
6669 total_data,
6670 STR_TERMINATE,
6671 &status);
6672 } else {
6673 srvstr_get_path(ctx,
6674 pdata,
6675 req->flags2,
6676 &oldname,
6677 pdata,
6678 total_data,
6679 STR_TERMINATE,
6680 &status);
6682 if (!NT_STATUS_IS_OK(status)) {
6683 return status;
6686 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6687 smb_fname_str_dbg(smb_fname_new), oldname));
6689 status = filename_convert(ctx,
6690 conn,
6691 oldname,
6692 ucf_flags,
6693 NULL,
6694 &smb_fname_old);
6695 if (!NT_STATUS_IS_OK(status)) {
6696 return status;
6699 return hardlink_internals(ctx, conn, req, false,
6700 smb_fname_old, smb_fname_new);
6703 /****************************************************************************
6704 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6705 ****************************************************************************/
6707 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6708 struct smb_request *req,
6709 const char *pdata,
6710 int total_data,
6711 files_struct *fsp,
6712 struct smb_filename *smb_fname_src)
6714 bool overwrite;
6715 uint32_t len;
6716 char *newname = NULL;
6717 struct smb_filename *smb_fname_dst = NULL;
6718 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6719 ucf_flags_from_smb_request(req);
6720 NTSTATUS status = NT_STATUS_OK;
6721 TALLOC_CTX *ctx = talloc_tos();
6723 if (!fsp) {
6724 return NT_STATUS_INVALID_HANDLE;
6727 if (total_data < 20) {
6728 return NT_STATUS_INVALID_PARAMETER;
6731 overwrite = (CVAL(pdata,0) ? True : False);
6732 len = IVAL(pdata,16);
6734 if (len > (total_data - 20) || (len == 0)) {
6735 return NT_STATUS_INVALID_PARAMETER;
6738 if (req->posix_pathnames) {
6739 srvstr_get_path_posix(ctx,
6740 pdata,
6741 req->flags2,
6742 &newname,
6743 &pdata[20],
6744 len,
6745 STR_TERMINATE,
6746 &status);
6747 } else {
6748 srvstr_get_path(ctx,
6749 pdata,
6750 req->flags2,
6751 &newname,
6752 &pdata[20],
6753 len,
6754 STR_TERMINATE,
6755 &status);
6757 if (!NT_STATUS_IS_OK(status)) {
6758 return status;
6761 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6762 newname));
6764 status = filename_convert(ctx,
6765 conn,
6766 newname,
6767 ucf_flags,
6768 NULL,
6769 &smb_fname_dst);
6770 if (!NT_STATUS_IS_OK(status)) {
6771 return status;
6774 if (fsp->base_fsp) {
6775 /* newname must be a stream name. */
6776 if (newname[0] != ':') {
6777 return NT_STATUS_NOT_SUPPORTED;
6780 /* Create an smb_fname to call rename_internals_fsp() with. */
6781 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6782 fsp->base_fsp->fsp_name->base_name,
6783 newname,
6784 NULL,
6785 fsp->base_fsp->fsp_name->flags);
6786 if (smb_fname_dst == NULL) {
6787 status = NT_STATUS_NO_MEMORY;
6788 goto out;
6792 * Set the original last component, since
6793 * rename_internals_fsp() requires it.
6795 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6796 newname);
6797 if (smb_fname_dst->original_lcomp == NULL) {
6798 status = NT_STATUS_NO_MEMORY;
6799 goto out;
6804 DEBUG(10,("smb2_file_rename_information: "
6805 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6806 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6807 smb_fname_str_dbg(smb_fname_dst)));
6808 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6809 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6810 overwrite);
6812 out:
6813 TALLOC_FREE(smb_fname_dst);
6814 return status;
6817 static NTSTATUS smb_file_link_information(connection_struct *conn,
6818 struct smb_request *req,
6819 const char *pdata,
6820 int total_data,
6821 files_struct *fsp,
6822 struct smb_filename *smb_fname_src)
6824 bool overwrite;
6825 uint32_t len;
6826 char *newname = NULL;
6827 struct smb_filename *smb_fname_dst = NULL;
6828 NTSTATUS status = NT_STATUS_OK;
6829 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6830 ucf_flags_from_smb_request(req);
6831 TALLOC_CTX *ctx = talloc_tos();
6833 if (!fsp) {
6834 return NT_STATUS_INVALID_HANDLE;
6837 if (total_data < 20) {
6838 return NT_STATUS_INVALID_PARAMETER;
6841 overwrite = (CVAL(pdata,0) ? true : false);
6842 len = IVAL(pdata,16);
6844 if (len > (total_data - 20) || (len == 0)) {
6845 return NT_STATUS_INVALID_PARAMETER;
6848 if (req->posix_pathnames) {
6849 srvstr_get_path_posix(ctx,
6850 pdata,
6851 req->flags2,
6852 &newname,
6853 &pdata[20],
6854 len,
6855 STR_TERMINATE,
6856 &status);
6857 } else {
6858 srvstr_get_path(ctx,
6859 pdata,
6860 req->flags2,
6861 &newname,
6862 &pdata[20],
6863 len,
6864 STR_TERMINATE,
6865 &status);
6867 if (!NT_STATUS_IS_OK(status)) {
6868 return status;
6871 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6872 newname));
6874 status = filename_convert(ctx,
6875 conn,
6876 newname,
6877 ucf_flags,
6878 NULL,
6879 &smb_fname_dst);
6880 if (!NT_STATUS_IS_OK(status)) {
6881 return status;
6884 if (fsp->base_fsp) {
6885 /* No stream names. */
6886 return NT_STATUS_NOT_SUPPORTED;
6889 DEBUG(10,("smb_file_link_information: "
6890 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6891 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6892 smb_fname_str_dbg(smb_fname_dst)));
6893 status = hardlink_internals(ctx,
6894 conn,
6895 req,
6896 overwrite,
6897 fsp->fsp_name,
6898 smb_fname_dst);
6900 TALLOC_FREE(smb_fname_dst);
6901 return status;
6904 /****************************************************************************
6905 Deal with SMB_FILE_RENAME_INFORMATION.
6906 ****************************************************************************/
6908 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6909 struct smb_request *req,
6910 const char *pdata,
6911 int total_data,
6912 files_struct *fsp,
6913 struct smb_filename *smb_fname_src)
6915 bool overwrite;
6916 uint32_t root_fid;
6917 uint32_t len;
6918 char *newname = NULL;
6919 struct smb_filename *smb_fname_dst = NULL;
6920 bool dest_has_wcard = False;
6921 NTSTATUS status = NT_STATUS_OK;
6922 char *p;
6923 TALLOC_CTX *ctx = talloc_tos();
6925 if (total_data < 13) {
6926 return NT_STATUS_INVALID_PARAMETER;
6929 overwrite = (CVAL(pdata,0) ? True : False);
6930 root_fid = IVAL(pdata,4);
6931 len = IVAL(pdata,8);
6933 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6934 return NT_STATUS_INVALID_PARAMETER;
6937 if (req->posix_pathnames) {
6938 srvstr_get_path_wcard_posix(ctx,
6939 pdata,
6940 req->flags2,
6941 &newname,
6942 &pdata[12],
6943 len,
6945 &status,
6946 &dest_has_wcard);
6947 } else {
6948 srvstr_get_path_wcard(ctx,
6949 pdata,
6950 req->flags2,
6951 &newname,
6952 &pdata[12],
6953 len,
6955 &status,
6956 &dest_has_wcard);
6958 if (!NT_STATUS_IS_OK(status)) {
6959 return status;
6962 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6963 newname));
6965 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6966 status = resolve_dfspath_wcard(ctx, conn,
6967 newname,
6968 UCF_COND_ALLOW_WCARD_LCOMP,
6969 !conn->sconn->using_smb2,
6970 &newname,
6971 &dest_has_wcard);
6972 if (!NT_STATUS_IS_OK(status)) {
6973 return status;
6977 /* Check the new name has no '/' characters. */
6978 if (strchr_m(newname, '/')) {
6979 return NT_STATUS_NOT_SUPPORTED;
6982 if (fsp && fsp->base_fsp) {
6983 /* newname must be a stream name. */
6984 if (newname[0] != ':') {
6985 return NT_STATUS_NOT_SUPPORTED;
6988 /* Create an smb_fname to call rename_internals_fsp() with. */
6989 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6990 fsp->base_fsp->fsp_name->base_name,
6991 newname,
6992 NULL,
6993 fsp->base_fsp->fsp_name->flags);
6994 if (smb_fname_dst == NULL) {
6995 status = NT_STATUS_NO_MEMORY;
6996 goto out;
7000 * Set the original last component, since
7001 * rename_internals_fsp() requires it.
7003 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
7004 newname);
7005 if (smb_fname_dst->original_lcomp == NULL) {
7006 status = NT_STATUS_NO_MEMORY;
7007 goto out;
7010 } else {
7012 * Build up an smb_fname_dst based on the filename passed in.
7013 * We basically just strip off the last component, and put on
7014 * the newname instead.
7016 char *base_name = NULL;
7017 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7018 ucf_flags_from_smb_request(req);
7020 if (dest_has_wcard) {
7021 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7024 /* newname must *not* be a stream name. */
7025 if (newname[0] == ':') {
7026 return NT_STATUS_NOT_SUPPORTED;
7030 * Strip off the last component (filename) of the path passed
7031 * in.
7033 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7034 if (!base_name) {
7035 return NT_STATUS_NO_MEMORY;
7037 p = strrchr_m(base_name, '/');
7038 if (p) {
7039 p[1] = '\0';
7040 } else {
7041 base_name = talloc_strdup(ctx, "");
7042 if (!base_name) {
7043 return NT_STATUS_NO_MEMORY;
7046 /* Append the new name. */
7047 base_name = talloc_asprintf_append(base_name,
7048 "%s",
7049 newname);
7050 if (!base_name) {
7051 return NT_STATUS_NO_MEMORY;
7054 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7055 ucf_flags);
7057 /* If an error we expect this to be
7058 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7060 if (!NT_STATUS_IS_OK(status)) {
7061 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7062 status)) {
7063 goto out;
7065 /* Create an smb_fname to call rename_internals_fsp() */
7066 smb_fname_dst = synthetic_smb_fname(ctx,
7067 base_name,
7068 NULL,
7069 NULL,
7070 smb_fname_src->flags);
7071 if (smb_fname_dst == NULL) {
7072 status = NT_STATUS_NO_MEMORY;
7073 goto out;
7078 if (fsp) {
7079 DEBUG(10,("smb_file_rename_information: "
7080 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7081 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7082 smb_fname_str_dbg(smb_fname_dst)));
7083 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7084 overwrite);
7085 } else {
7086 DEBUG(10,("smb_file_rename_information: "
7087 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7088 smb_fname_str_dbg(smb_fname_src),
7089 smb_fname_str_dbg(smb_fname_dst)));
7090 status = rename_internals(ctx, conn, req, smb_fname_src,
7091 smb_fname_dst, 0, overwrite, false,
7092 dest_has_wcard,
7093 FILE_WRITE_ATTRIBUTES);
7095 out:
7096 TALLOC_FREE(smb_fname_dst);
7097 return status;
7100 /****************************************************************************
7101 Deal with SMB_SET_POSIX_ACL.
7102 ****************************************************************************/
7104 #if defined(HAVE_POSIX_ACLS)
7105 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7106 const char *pdata,
7107 int total_data,
7108 files_struct *fsp,
7109 const struct smb_filename *smb_fname)
7111 uint16_t posix_acl_version;
7112 uint16_t num_file_acls;
7113 uint16_t num_def_acls;
7114 bool valid_file_acls = True;
7115 bool valid_def_acls = True;
7116 NTSTATUS status;
7118 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7119 return NT_STATUS_INVALID_PARAMETER;
7121 posix_acl_version = SVAL(pdata,0);
7122 num_file_acls = SVAL(pdata,2);
7123 num_def_acls = SVAL(pdata,4);
7125 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7126 valid_file_acls = False;
7127 num_file_acls = 0;
7130 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7131 valid_def_acls = False;
7132 num_def_acls = 0;
7135 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7136 return NT_STATUS_INVALID_PARAMETER;
7139 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7140 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7141 return NT_STATUS_INVALID_PARAMETER;
7144 status = refuse_symlink(conn, fsp, smb_fname);
7145 if (!NT_STATUS_IS_OK(status)) {
7146 return status;
7149 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7150 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7151 (unsigned int)num_file_acls,
7152 (unsigned int)num_def_acls));
7154 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7155 smb_fname, num_file_acls,
7156 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7157 return map_nt_error_from_unix(errno);
7160 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7161 smb_fname, num_def_acls,
7162 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7163 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7164 return map_nt_error_from_unix(errno);
7166 return NT_STATUS_OK;
7168 #endif
7170 /****************************************************************************
7171 Deal with SMB_SET_POSIX_LOCK.
7172 ****************************************************************************/
7174 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7175 struct smb_request *req,
7176 const char *pdata,
7177 int total_data,
7178 files_struct *fsp)
7180 uint64_t count;
7181 uint64_t offset;
7182 uint64_t smblctx;
7183 bool blocking_lock = False;
7184 enum brl_type lock_type;
7186 NTSTATUS status = NT_STATUS_OK;
7188 if (fsp == NULL || fsp->fh->fd == -1) {
7189 return NT_STATUS_INVALID_HANDLE;
7192 if (total_data != POSIX_LOCK_DATA_SIZE) {
7193 return NT_STATUS_INVALID_PARAMETER;
7196 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7197 case POSIX_LOCK_TYPE_READ:
7198 lock_type = READ_LOCK;
7199 break;
7200 case POSIX_LOCK_TYPE_WRITE:
7201 /* Return the right POSIX-mappable error code for files opened read-only. */
7202 if (!fsp->can_write) {
7203 return NT_STATUS_INVALID_HANDLE;
7205 lock_type = WRITE_LOCK;
7206 break;
7207 case POSIX_LOCK_TYPE_UNLOCK:
7208 lock_type = UNLOCK_LOCK;
7209 break;
7210 default:
7211 return NT_STATUS_INVALID_PARAMETER;
7214 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7215 blocking_lock = False;
7216 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7217 blocking_lock = True;
7218 } else {
7219 return NT_STATUS_INVALID_PARAMETER;
7222 if (!lp_blocking_locks(SNUM(conn))) {
7223 blocking_lock = False;
7226 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7227 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7228 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7229 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7230 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7232 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7233 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7234 fsp_str_dbg(fsp),
7235 (unsigned int)lock_type,
7236 (unsigned long long)smblctx,
7237 (double)count,
7238 (double)offset ));
7240 if (lock_type == UNLOCK_LOCK) {
7241 status = do_unlock(req->sconn->msg_ctx,
7242 fsp,
7243 smblctx,
7244 count,
7245 offset,
7246 POSIX_LOCK);
7247 } else {
7248 uint64_t block_smblctx;
7250 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7251 fsp,
7252 smblctx,
7253 count,
7254 offset,
7255 lock_type,
7256 POSIX_LOCK,
7257 blocking_lock,
7258 &status,
7259 &block_smblctx);
7261 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7263 * A blocking lock was requested. Package up
7264 * this smb into a queued request and push it
7265 * onto the blocking lock queue.
7267 if(push_blocking_lock_request(br_lck,
7268 req,
7269 fsp,
7270 -1, /* infinite timeout. */
7272 smblctx,
7273 lock_type,
7274 POSIX_LOCK,
7275 offset,
7276 count,
7277 block_smblctx)) {
7278 TALLOC_FREE(br_lck);
7279 return status;
7282 TALLOC_FREE(br_lck);
7285 return status;
7288 /****************************************************************************
7289 Deal with SMB_SET_FILE_BASIC_INFO.
7290 ****************************************************************************/
7292 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7293 const char *pdata,
7294 int total_data,
7295 files_struct *fsp,
7296 const struct smb_filename *smb_fname)
7298 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7299 struct smb_file_time ft;
7300 uint32_t dosmode = 0;
7301 NTSTATUS status = NT_STATUS_OK;
7303 ZERO_STRUCT(ft);
7305 if (total_data < 36) {
7306 return NT_STATUS_INVALID_PARAMETER;
7309 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7310 if (!NT_STATUS_IS_OK(status)) {
7311 return status;
7314 /* Set the attributes */
7315 dosmode = IVAL(pdata,32);
7316 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7317 if (!NT_STATUS_IS_OK(status)) {
7318 return status;
7321 /* create time */
7322 ft.create_time = interpret_long_date(pdata);
7324 /* access time */
7325 ft.atime = interpret_long_date(pdata+8);
7327 /* write time. */
7328 ft.mtime = interpret_long_date(pdata+16);
7330 /* change time. */
7331 ft.ctime = interpret_long_date(pdata+24);
7333 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7334 smb_fname_str_dbg(smb_fname)));
7336 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7337 true);
7340 /****************************************************************************
7341 Deal with SMB_INFO_STANDARD.
7342 ****************************************************************************/
7344 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7345 const char *pdata,
7346 int total_data,
7347 files_struct *fsp,
7348 const struct smb_filename *smb_fname)
7350 NTSTATUS status;
7351 struct smb_file_time ft;
7353 ZERO_STRUCT(ft);
7355 if (total_data < 12) {
7356 return NT_STATUS_INVALID_PARAMETER;
7359 /* create time */
7360 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7361 /* access time */
7362 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7363 /* write time */
7364 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7366 DEBUG(10,("smb_set_info_standard: file %s\n",
7367 smb_fname_str_dbg(smb_fname)));
7369 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7370 if (!NT_STATUS_IS_OK(status)) {
7371 return status;
7374 return smb_set_file_time(conn,
7375 fsp,
7376 smb_fname,
7377 &ft,
7378 true);
7381 /****************************************************************************
7382 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7383 ****************************************************************************/
7385 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7386 struct smb_request *req,
7387 const char *pdata,
7388 int total_data,
7389 files_struct *fsp,
7390 struct smb_filename *smb_fname)
7392 uint64_t allocation_size = 0;
7393 NTSTATUS status = NT_STATUS_OK;
7394 files_struct *new_fsp = NULL;
7396 if (!VALID_STAT(smb_fname->st)) {
7397 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7400 if (total_data < 8) {
7401 return NT_STATUS_INVALID_PARAMETER;
7404 allocation_size = (uint64_t)IVAL(pdata,0);
7405 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7406 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7407 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7408 (double)allocation_size));
7410 if (allocation_size) {
7411 allocation_size = smb_roundup(conn, allocation_size);
7414 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7415 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7416 (double)allocation_size));
7418 if (fsp && fsp->fh->fd != -1) {
7419 /* Open file handle. */
7420 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7421 return NT_STATUS_ACCESS_DENIED;
7424 /* Only change if needed. */
7425 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7426 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7427 return map_nt_error_from_unix(errno);
7430 /* But always update the time. */
7432 * This is equivalent to a write. Ensure it's seen immediately
7433 * if there are no pending writes.
7435 trigger_write_time_update_immediate(fsp);
7436 return NT_STATUS_OK;
7439 /* Pathname or stat or directory file. */
7440 status = SMB_VFS_CREATE_FILE(
7441 conn, /* conn */
7442 req, /* req */
7443 0, /* root_dir_fid */
7444 smb_fname, /* fname */
7445 FILE_WRITE_DATA, /* access_mask */
7446 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7447 FILE_SHARE_DELETE),
7448 FILE_OPEN, /* create_disposition*/
7449 0, /* create_options */
7450 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7451 0, /* oplock_request */
7452 NULL, /* lease */
7453 0, /* allocation_size */
7454 0, /* private_flags */
7455 NULL, /* sd */
7456 NULL, /* ea_list */
7457 &new_fsp, /* result */
7458 NULL, /* pinfo */
7459 NULL, NULL); /* create context */
7461 if (!NT_STATUS_IS_OK(status)) {
7462 /* NB. We check for open_was_deferred in the caller. */
7463 return status;
7466 /* Only change if needed. */
7467 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7468 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7469 status = map_nt_error_from_unix(errno);
7470 close_file(req, new_fsp, NORMAL_CLOSE);
7471 return status;
7475 /* Changing the allocation size should set the last mod time. */
7477 * This is equivalent to a write. Ensure it's seen immediately
7478 * if there are no pending writes.
7480 trigger_write_time_update_immediate(new_fsp);
7481 close_file(req, new_fsp, NORMAL_CLOSE);
7482 return NT_STATUS_OK;
7485 /****************************************************************************
7486 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7487 ****************************************************************************/
7489 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7490 struct smb_request *req,
7491 const char *pdata,
7492 int total_data,
7493 files_struct *fsp,
7494 const struct smb_filename *smb_fname,
7495 bool fail_after_createfile)
7497 off_t size;
7499 if (total_data < 8) {
7500 return NT_STATUS_INVALID_PARAMETER;
7503 size = IVAL(pdata,0);
7504 size |= (((off_t)IVAL(pdata,4)) << 32);
7505 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7506 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7507 (double)size));
7509 return smb_set_file_size(conn, req,
7510 fsp,
7511 smb_fname,
7512 &smb_fname->st,
7513 size,
7514 fail_after_createfile);
7517 /****************************************************************************
7518 Allow a UNIX info mknod.
7519 ****************************************************************************/
7521 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7522 const char *pdata,
7523 int total_data,
7524 const struct smb_filename *smb_fname)
7526 uint32_t file_type = IVAL(pdata,56);
7527 #if defined(HAVE_MAKEDEV)
7528 uint32_t dev_major = IVAL(pdata,60);
7529 uint32_t dev_minor = IVAL(pdata,68);
7530 #endif
7531 SMB_DEV_T dev = (SMB_DEV_T)0;
7532 uint32_t raw_unixmode = IVAL(pdata,84);
7533 NTSTATUS status;
7534 mode_t unixmode;
7536 if (total_data < 100) {
7537 return NT_STATUS_INVALID_PARAMETER;
7540 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7541 PERM_NEW_FILE, &unixmode);
7542 if (!NT_STATUS_IS_OK(status)) {
7543 return status;
7546 #if defined(HAVE_MAKEDEV)
7547 dev = makedev(dev_major, dev_minor);
7548 #endif
7550 switch (file_type) {
7551 #if defined(S_IFIFO)
7552 case UNIX_TYPE_FIFO:
7553 unixmode |= S_IFIFO;
7554 break;
7555 #endif
7556 #if defined(S_IFSOCK)
7557 case UNIX_TYPE_SOCKET:
7558 unixmode |= S_IFSOCK;
7559 break;
7560 #endif
7561 #if defined(S_IFCHR)
7562 case UNIX_TYPE_CHARDEV:
7563 unixmode |= S_IFCHR;
7564 break;
7565 #endif
7566 #if defined(S_IFBLK)
7567 case UNIX_TYPE_BLKDEV:
7568 unixmode |= S_IFBLK;
7569 break;
7570 #endif
7571 default:
7572 return NT_STATUS_INVALID_PARAMETER;
7575 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7576 "%.0f mode 0%o for file %s\n", (double)dev,
7577 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7579 /* Ok - do the mknod. */
7580 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7581 return map_nt_error_from_unix(errno);
7584 /* If any of the other "set" calls fail we
7585 * don't want to end up with a half-constructed mknod.
7588 if (lp_inherit_permissions(SNUM(conn))) {
7589 char *parent;
7590 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7591 &parent, NULL)) {
7592 return NT_STATUS_NO_MEMORY;
7594 inherit_access_posix_acl(conn, parent, smb_fname,
7595 unixmode);
7596 TALLOC_FREE(parent);
7599 return NT_STATUS_OK;
7602 /****************************************************************************
7603 Deal with SMB_SET_FILE_UNIX_BASIC.
7604 ****************************************************************************/
7606 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7607 struct smb_request *req,
7608 const char *pdata,
7609 int total_data,
7610 files_struct *fsp,
7611 const struct smb_filename *smb_fname)
7613 struct smb_file_time ft;
7614 uint32_t raw_unixmode;
7615 mode_t unixmode;
7616 off_t size = 0;
7617 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7618 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7619 NTSTATUS status = NT_STATUS_OK;
7620 bool delete_on_fail = False;
7621 enum perm_type ptype;
7622 files_struct *all_fsps = NULL;
7623 bool modify_mtime = true;
7624 struct file_id id;
7625 struct smb_filename *smb_fname_tmp = NULL;
7626 SMB_STRUCT_STAT sbuf;
7628 ZERO_STRUCT(ft);
7630 if (total_data < 100) {
7631 return NT_STATUS_INVALID_PARAMETER;
7634 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7635 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7636 size=IVAL(pdata,0); /* first 8 Bytes are size */
7637 size |= (((off_t)IVAL(pdata,4)) << 32);
7640 ft.atime = interpret_long_date(pdata+24); /* access_time */
7641 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7642 set_owner = (uid_t)IVAL(pdata,40);
7643 set_grp = (gid_t)IVAL(pdata,48);
7644 raw_unixmode = IVAL(pdata,84);
7646 if (VALID_STAT(smb_fname->st)) {
7647 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7648 ptype = PERM_EXISTING_DIR;
7649 } else {
7650 ptype = PERM_EXISTING_FILE;
7652 } else {
7653 ptype = PERM_NEW_FILE;
7656 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7657 ptype, &unixmode);
7658 if (!NT_STATUS_IS_OK(status)) {
7659 return status;
7662 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7663 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7664 smb_fname_str_dbg(smb_fname), (double)size,
7665 (unsigned int)set_owner, (unsigned int)set_grp,
7666 (int)raw_unixmode));
7668 sbuf = smb_fname->st;
7670 if (!VALID_STAT(sbuf)) {
7672 * The only valid use of this is to create character and block
7673 * devices, and named pipes. This is deprecated (IMHO) and
7674 * a new info level should be used for mknod. JRA.
7677 status = smb_unix_mknod(conn,
7678 pdata,
7679 total_data,
7680 smb_fname);
7681 if (!NT_STATUS_IS_OK(status)) {
7682 return status;
7685 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7686 if (smb_fname_tmp == NULL) {
7687 return NT_STATUS_NO_MEMORY;
7690 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7691 status = map_nt_error_from_unix(errno);
7692 TALLOC_FREE(smb_fname_tmp);
7693 SMB_VFS_UNLINK(conn, smb_fname);
7694 return status;
7697 sbuf = smb_fname_tmp->st;
7698 smb_fname = smb_fname_tmp;
7700 /* Ensure we don't try and change anything else. */
7701 raw_unixmode = SMB_MODE_NO_CHANGE;
7702 size = get_file_size_stat(&sbuf);
7703 ft.atime = sbuf.st_ex_atime;
7704 ft.mtime = sbuf.st_ex_mtime;
7706 * We continue here as we might want to change the
7707 * owner uid/gid.
7709 delete_on_fail = True;
7712 #if 1
7713 /* Horrible backwards compatibility hack as an old server bug
7714 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7715 * */
7717 if (!size) {
7718 size = get_file_size_stat(&sbuf);
7720 #endif
7723 * Deal with the UNIX specific mode set.
7726 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7727 int ret;
7729 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7730 "setting mode 0%o for file %s\n",
7731 (unsigned int)unixmode,
7732 smb_fname_str_dbg(smb_fname)));
7733 if (fsp && fsp->fh->fd != -1) {
7734 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7735 } else {
7736 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7738 if (ret != 0) {
7739 return map_nt_error_from_unix(errno);
7744 * Deal with the UNIX specific uid set.
7747 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7748 (sbuf.st_ex_uid != set_owner)) {
7749 int ret;
7751 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7752 "changing owner %u for path %s\n",
7753 (unsigned int)set_owner,
7754 smb_fname_str_dbg(smb_fname)));
7756 if (fsp && fsp->fh->fd != -1) {
7757 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7758 } else {
7760 * UNIX extensions calls must always operate
7761 * on symlinks.
7763 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7764 set_owner, (gid_t)-1);
7767 if (ret != 0) {
7768 status = map_nt_error_from_unix(errno);
7769 if (delete_on_fail) {
7770 SMB_VFS_UNLINK(conn, smb_fname);
7772 return status;
7777 * Deal with the UNIX specific gid set.
7780 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7781 (sbuf.st_ex_gid != set_grp)) {
7782 int ret;
7784 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7785 "changing group %u for file %s\n",
7786 (unsigned int)set_owner,
7787 smb_fname_str_dbg(smb_fname)));
7788 if (fsp && fsp->fh->fd != -1) {
7789 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7790 } else {
7792 * UNIX extensions calls must always operate
7793 * on symlinks.
7795 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7796 set_grp);
7798 if (ret != 0) {
7799 status = map_nt_error_from_unix(errno);
7800 if (delete_on_fail) {
7801 SMB_VFS_UNLINK(conn, smb_fname);
7803 return status;
7807 /* Deal with any size changes. */
7809 status = smb_set_file_size(conn, req,
7810 fsp,
7811 smb_fname,
7812 &sbuf,
7813 size,
7814 false);
7815 if (!NT_STATUS_IS_OK(status)) {
7816 return status;
7819 /* Deal with any time changes. */
7820 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7821 /* No change, don't cancel anything. */
7822 return status;
7825 id = vfs_file_id_from_sbuf(conn, &sbuf);
7826 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7827 all_fsps = file_find_di_next(all_fsps)) {
7829 * We're setting the time explicitly for UNIX.
7830 * Cancel any pending changes over all handles.
7832 all_fsps->update_write_time_on_close = false;
7833 TALLOC_FREE(all_fsps->update_write_time_event);
7837 * Override the "setting_write_time"
7838 * parameter here as it almost does what
7839 * we need. Just remember if we modified
7840 * mtime and send the notify ourselves.
7842 if (null_timespec(ft.mtime)) {
7843 modify_mtime = false;
7846 status = smb_set_file_time(conn,
7847 fsp,
7848 smb_fname,
7849 &ft,
7850 false);
7851 if (modify_mtime) {
7852 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7853 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7855 return status;
7858 /****************************************************************************
7859 Deal with SMB_SET_FILE_UNIX_INFO2.
7860 ****************************************************************************/
7862 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7863 struct smb_request *req,
7864 const char *pdata,
7865 int total_data,
7866 files_struct *fsp,
7867 const struct smb_filename *smb_fname)
7869 NTSTATUS status;
7870 uint32_t smb_fflags;
7871 uint32_t smb_fmask;
7873 if (total_data < 116) {
7874 return NT_STATUS_INVALID_PARAMETER;
7877 /* Start by setting all the fields that are common between UNIX_BASIC
7878 * and UNIX_INFO2.
7880 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7881 fsp, smb_fname);
7882 if (!NT_STATUS_IS_OK(status)) {
7883 return status;
7886 smb_fflags = IVAL(pdata, 108);
7887 smb_fmask = IVAL(pdata, 112);
7889 /* NB: We should only attempt to alter the file flags if the client
7890 * sends a non-zero mask.
7892 if (smb_fmask != 0) {
7893 int stat_fflags = 0;
7895 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7896 smb_fmask, &stat_fflags)) {
7897 /* Client asked to alter a flag we don't understand. */
7898 return NT_STATUS_INVALID_PARAMETER;
7901 if (fsp && fsp->fh->fd != -1) {
7902 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7903 return NT_STATUS_NOT_SUPPORTED;
7904 } else {
7905 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7906 stat_fflags) != 0) {
7907 return map_nt_error_from_unix(errno);
7912 /* XXX: need to add support for changing the create_time here. You
7913 * can do this for paths on Darwin with setattrlist(2). The right way
7914 * to hook this up is probably by extending the VFS utimes interface.
7917 return NT_STATUS_OK;
7920 /****************************************************************************
7921 Create a directory with POSIX semantics.
7922 ****************************************************************************/
7924 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7925 struct smb_request *req,
7926 char **ppdata,
7927 int total_data,
7928 struct smb_filename *smb_fname,
7929 int *pdata_return_size)
7931 NTSTATUS status = NT_STATUS_OK;
7932 uint32_t raw_unixmode = 0;
7933 uint32_t mod_unixmode = 0;
7934 mode_t unixmode = (mode_t)0;
7935 files_struct *fsp = NULL;
7936 uint16_t info_level_return = 0;
7937 int info;
7938 char *pdata = *ppdata;
7940 if (total_data < 18) {
7941 return NT_STATUS_INVALID_PARAMETER;
7944 raw_unixmode = IVAL(pdata,8);
7945 /* Next 4 bytes are not yet defined. */
7947 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7948 PERM_NEW_DIR, &unixmode);
7949 if (!NT_STATUS_IS_OK(status)) {
7950 return status;
7953 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7955 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7956 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7958 status = SMB_VFS_CREATE_FILE(
7959 conn, /* conn */
7960 req, /* req */
7961 0, /* root_dir_fid */
7962 smb_fname, /* fname */
7963 FILE_READ_ATTRIBUTES, /* access_mask */
7964 FILE_SHARE_NONE, /* share_access */
7965 FILE_CREATE, /* create_disposition*/
7966 FILE_DIRECTORY_FILE, /* create_options */
7967 mod_unixmode, /* file_attributes */
7968 0, /* oplock_request */
7969 NULL, /* lease */
7970 0, /* allocation_size */
7971 0, /* private_flags */
7972 NULL, /* sd */
7973 NULL, /* ea_list */
7974 &fsp, /* result */
7975 &info, /* pinfo */
7976 NULL, NULL); /* create context */
7978 if (NT_STATUS_IS_OK(status)) {
7979 close_file(req, fsp, NORMAL_CLOSE);
7982 info_level_return = SVAL(pdata,16);
7984 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7985 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7986 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7987 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7988 } else {
7989 *pdata_return_size = 12;
7992 /* Realloc the data size */
7993 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7994 if (*ppdata == NULL) {
7995 *pdata_return_size = 0;
7996 return NT_STATUS_NO_MEMORY;
7998 pdata = *ppdata;
8000 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8001 SSVAL(pdata,2,0); /* No fnum. */
8002 SIVAL(pdata,4,info); /* Was directory created. */
8004 switch (info_level_return) {
8005 case SMB_QUERY_FILE_UNIX_BASIC:
8006 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8007 SSVAL(pdata,10,0); /* Padding. */
8008 store_file_unix_basic(conn, pdata + 12, fsp,
8009 &smb_fname->st);
8010 break;
8011 case SMB_QUERY_FILE_UNIX_INFO2:
8012 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8013 SSVAL(pdata,10,0); /* Padding. */
8014 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8015 &smb_fname->st);
8016 break;
8017 default:
8018 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8019 SSVAL(pdata,10,0); /* Padding. */
8020 break;
8023 return status;
8026 /****************************************************************************
8027 Open/Create a file with POSIX semantics.
8028 ****************************************************************************/
8030 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8031 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8033 static NTSTATUS smb_posix_open(connection_struct *conn,
8034 struct smb_request *req,
8035 char **ppdata,
8036 int total_data,
8037 struct smb_filename *smb_fname,
8038 int *pdata_return_size)
8040 bool extended_oplock_granted = False;
8041 char *pdata = *ppdata;
8042 uint32_t flags = 0;
8043 uint32_t wire_open_mode = 0;
8044 uint32_t raw_unixmode = 0;
8045 uint32_t mod_unixmode = 0;
8046 uint32_t create_disp = 0;
8047 uint32_t access_mask = 0;
8048 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8049 NTSTATUS status = NT_STATUS_OK;
8050 mode_t unixmode = (mode_t)0;
8051 files_struct *fsp = NULL;
8052 int oplock_request = 0;
8053 int info = 0;
8054 uint16_t info_level_return = 0;
8056 if (total_data < 18) {
8057 return NT_STATUS_INVALID_PARAMETER;
8060 flags = IVAL(pdata,0);
8061 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8062 if (oplock_request) {
8063 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8066 wire_open_mode = IVAL(pdata,4);
8068 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8069 return smb_posix_mkdir(conn, req,
8070 ppdata,
8071 total_data,
8072 smb_fname,
8073 pdata_return_size);
8076 switch (wire_open_mode & SMB_ACCMODE) {
8077 case SMB_O_RDONLY:
8078 access_mask = SMB_O_RDONLY_MAPPING;
8079 break;
8080 case SMB_O_WRONLY:
8081 access_mask = SMB_O_WRONLY_MAPPING;
8082 break;
8083 case SMB_O_RDWR:
8084 access_mask = (SMB_O_RDONLY_MAPPING|
8085 SMB_O_WRONLY_MAPPING);
8086 break;
8087 default:
8088 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8089 (unsigned int)wire_open_mode ));
8090 return NT_STATUS_INVALID_PARAMETER;
8093 wire_open_mode &= ~SMB_ACCMODE;
8095 /* First take care of O_CREAT|O_EXCL interactions. */
8096 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8097 case (SMB_O_CREAT | SMB_O_EXCL):
8098 /* File exists fail. File not exist create. */
8099 create_disp = FILE_CREATE;
8100 break;
8101 case SMB_O_CREAT:
8102 /* File exists open. File not exist create. */
8103 create_disp = FILE_OPEN_IF;
8104 break;
8105 case SMB_O_EXCL:
8106 /* O_EXCL on its own without O_CREAT is undefined.
8107 We deliberately ignore it as some versions of
8108 Linux CIFSFS can send a bare O_EXCL on the
8109 wire which other filesystems in the kernel
8110 ignore. See bug 9519 for details. */
8112 /* Fallthrough. */
8114 case 0:
8115 /* File exists open. File not exist fail. */
8116 create_disp = FILE_OPEN;
8117 break;
8118 default:
8119 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8120 (unsigned int)wire_open_mode ));
8121 return NT_STATUS_INVALID_PARAMETER;
8124 /* Next factor in the effects of O_TRUNC. */
8125 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8127 if (wire_open_mode & SMB_O_TRUNC) {
8128 switch (create_disp) {
8129 case FILE_CREATE:
8130 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8131 /* Leave create_disp alone as
8132 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8134 /* File exists fail. File not exist create. */
8135 break;
8136 case FILE_OPEN_IF:
8137 /* SMB_O_CREAT | SMB_O_TRUNC */
8138 /* File exists overwrite. File not exist create. */
8139 create_disp = FILE_OVERWRITE_IF;
8140 break;
8141 case FILE_OPEN:
8142 /* SMB_O_TRUNC */
8143 /* File exists overwrite. File not exist fail. */
8144 create_disp = FILE_OVERWRITE;
8145 break;
8146 default:
8147 /* Cannot get here. */
8148 smb_panic("smb_posix_open: logic error");
8149 return NT_STATUS_INVALID_PARAMETER;
8153 raw_unixmode = IVAL(pdata,8);
8154 /* Next 4 bytes are not yet defined. */
8156 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8157 (VALID_STAT(smb_fname->st) ?
8158 PERM_EXISTING_FILE : PERM_NEW_FILE),
8159 &unixmode);
8161 if (!NT_STATUS_IS_OK(status)) {
8162 return status;
8165 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8167 if (wire_open_mode & SMB_O_SYNC) {
8168 create_options |= FILE_WRITE_THROUGH;
8170 if (wire_open_mode & SMB_O_APPEND) {
8171 access_mask |= FILE_APPEND_DATA;
8173 if (wire_open_mode & SMB_O_DIRECT) {
8174 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8177 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8178 VALID_STAT_OF_DIR(smb_fname->st)) {
8179 if (access_mask != SMB_O_RDONLY_MAPPING) {
8180 return NT_STATUS_FILE_IS_A_DIRECTORY;
8182 create_options &= ~FILE_NON_DIRECTORY_FILE;
8183 create_options |= FILE_DIRECTORY_FILE;
8186 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8187 smb_fname_str_dbg(smb_fname),
8188 (unsigned int)wire_open_mode,
8189 (unsigned int)unixmode ));
8191 status = SMB_VFS_CREATE_FILE(
8192 conn, /* conn */
8193 req, /* req */
8194 0, /* root_dir_fid */
8195 smb_fname, /* fname */
8196 access_mask, /* access_mask */
8197 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8198 FILE_SHARE_DELETE),
8199 create_disp, /* create_disposition*/
8200 create_options, /* create_options */
8201 mod_unixmode, /* file_attributes */
8202 oplock_request, /* oplock_request */
8203 NULL, /* lease */
8204 0, /* allocation_size */
8205 0, /* private_flags */
8206 NULL, /* sd */
8207 NULL, /* ea_list */
8208 &fsp, /* result */
8209 &info, /* pinfo */
8210 NULL, NULL); /* create context */
8212 if (!NT_STATUS_IS_OK(status)) {
8213 return status;
8216 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8217 extended_oplock_granted = True;
8220 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8221 extended_oplock_granted = True;
8224 info_level_return = SVAL(pdata,16);
8226 /* Allocate the correct return size. */
8228 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8229 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8230 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8231 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8232 } else {
8233 *pdata_return_size = 12;
8236 /* Realloc the data size */
8237 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8238 if (*ppdata == NULL) {
8239 close_file(req, fsp, ERROR_CLOSE);
8240 *pdata_return_size = 0;
8241 return NT_STATUS_NO_MEMORY;
8243 pdata = *ppdata;
8245 if (extended_oplock_granted) {
8246 if (flags & REQUEST_BATCH_OPLOCK) {
8247 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8248 } else {
8249 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8251 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8252 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8253 } else {
8254 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8257 SSVAL(pdata,2,fsp->fnum);
8258 SIVAL(pdata,4,info); /* Was file created etc. */
8260 switch (info_level_return) {
8261 case SMB_QUERY_FILE_UNIX_BASIC:
8262 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8263 SSVAL(pdata,10,0); /* padding. */
8264 store_file_unix_basic(conn, pdata + 12, fsp,
8265 &smb_fname->st);
8266 break;
8267 case SMB_QUERY_FILE_UNIX_INFO2:
8268 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8269 SSVAL(pdata,10,0); /* padding. */
8270 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8271 &smb_fname->st);
8272 break;
8273 default:
8274 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8275 SSVAL(pdata,10,0); /* padding. */
8276 break;
8278 return NT_STATUS_OK;
8281 /****************************************************************************
8282 Delete a file with POSIX semantics.
8283 ****************************************************************************/
8285 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8286 struct smb_request *req,
8287 const char *pdata,
8288 int total_data,
8289 struct smb_filename *smb_fname)
8291 NTSTATUS status = NT_STATUS_OK;
8292 files_struct *fsp = NULL;
8293 uint16_t flags = 0;
8294 char del = 1;
8295 int info = 0;
8296 int create_options = 0;
8297 int i;
8298 struct share_mode_lock *lck = NULL;
8300 if (total_data < 2) {
8301 return NT_STATUS_INVALID_PARAMETER;
8304 flags = SVAL(pdata,0);
8306 if (!VALID_STAT(smb_fname->st)) {
8307 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8310 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8311 !VALID_STAT_OF_DIR(smb_fname->st)) {
8312 return NT_STATUS_NOT_A_DIRECTORY;
8315 DEBUG(10,("smb_posix_unlink: %s %s\n",
8316 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8317 smb_fname_str_dbg(smb_fname)));
8319 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8320 create_options |= FILE_DIRECTORY_FILE;
8323 status = SMB_VFS_CREATE_FILE(
8324 conn, /* conn */
8325 req, /* req */
8326 0, /* root_dir_fid */
8327 smb_fname, /* fname */
8328 DELETE_ACCESS, /* access_mask */
8329 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8330 FILE_SHARE_DELETE),
8331 FILE_OPEN, /* create_disposition*/
8332 create_options, /* create_options */
8333 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8334 0, /* oplock_request */
8335 NULL, /* lease */
8336 0, /* allocation_size */
8337 0, /* private_flags */
8338 NULL, /* sd */
8339 NULL, /* ea_list */
8340 &fsp, /* result */
8341 &info, /* pinfo */
8342 NULL, NULL); /* create context */
8344 if (!NT_STATUS_IS_OK(status)) {
8345 return status;
8349 * Don't lie to client. If we can't really delete due to
8350 * non-POSIX opens return SHARING_VIOLATION.
8353 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8354 if (lck == NULL) {
8355 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8356 "lock for file %s\n", fsp_str_dbg(fsp)));
8357 close_file(req, fsp, NORMAL_CLOSE);
8358 return NT_STATUS_INVALID_PARAMETER;
8362 * See if others still have the file open. If this is the case, then
8363 * don't delete. If all opens are POSIX delete we can set the delete
8364 * on close disposition.
8366 for (i=0; i<lck->data->num_share_modes; i++) {
8367 struct share_mode_entry *e = &lck->data->share_modes[i];
8368 if (is_valid_share_mode_entry(e)) {
8369 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8370 continue;
8372 if (share_mode_stale_pid(lck->data, i)) {
8373 continue;
8375 /* Fail with sharing violation. */
8376 TALLOC_FREE(lck);
8377 close_file(req, fsp, NORMAL_CLOSE);
8378 return NT_STATUS_SHARING_VIOLATION;
8383 * Set the delete on close.
8385 status = smb_set_file_disposition_info(conn,
8386 &del,
8388 fsp,
8389 smb_fname);
8391 TALLOC_FREE(lck);
8393 if (!NT_STATUS_IS_OK(status)) {
8394 close_file(req, fsp, NORMAL_CLOSE);
8395 return status;
8397 return close_file(req, fsp, NORMAL_CLOSE);
8400 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8401 struct smb_request *req,
8402 TALLOC_CTX *mem_ctx,
8403 uint16_t info_level,
8404 files_struct *fsp,
8405 struct smb_filename *smb_fname,
8406 char **ppdata, int total_data,
8407 int *ret_data_size)
8409 char *pdata = *ppdata;
8410 NTSTATUS status = NT_STATUS_OK;
8411 int data_return_size = 0;
8413 *ret_data_size = 0;
8415 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8416 return NT_STATUS_INVALID_LEVEL;
8419 if (!CAN_WRITE(conn)) {
8420 /* Allow POSIX opens. The open path will deny
8421 * any non-readonly opens. */
8422 if (info_level != SMB_POSIX_PATH_OPEN) {
8423 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8427 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8428 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8429 fsp_fnum_dbg(fsp),
8430 info_level, total_data));
8432 switch (info_level) {
8434 case SMB_INFO_STANDARD:
8436 status = smb_set_info_standard(conn,
8437 pdata,
8438 total_data,
8439 fsp,
8440 smb_fname);
8441 break;
8444 case SMB_INFO_SET_EA:
8446 status = smb_info_set_ea(conn,
8447 pdata,
8448 total_data,
8449 fsp,
8450 smb_fname);
8451 break;
8454 case SMB_SET_FILE_BASIC_INFO:
8455 case SMB_FILE_BASIC_INFORMATION:
8457 status = smb_set_file_basic_info(conn,
8458 pdata,
8459 total_data,
8460 fsp,
8461 smb_fname);
8462 break;
8465 case SMB_FILE_ALLOCATION_INFORMATION:
8466 case SMB_SET_FILE_ALLOCATION_INFO:
8468 status = smb_set_file_allocation_info(conn, req,
8469 pdata,
8470 total_data,
8471 fsp,
8472 smb_fname);
8473 break;
8476 case SMB_FILE_END_OF_FILE_INFORMATION:
8477 case SMB_SET_FILE_END_OF_FILE_INFO:
8480 * XP/Win7 both fail after the createfile with
8481 * SMB_SET_FILE_END_OF_FILE_INFO but not
8482 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8483 * The level is known here, so pass it down
8484 * appropriately.
8486 bool should_fail =
8487 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8489 status = smb_set_file_end_of_file_info(conn, req,
8490 pdata,
8491 total_data,
8492 fsp,
8493 smb_fname,
8494 should_fail);
8495 break;
8498 case SMB_FILE_DISPOSITION_INFORMATION:
8499 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8501 #if 0
8502 /* JRA - We used to just ignore this on a path ?
8503 * Shouldn't this be invalid level on a pathname
8504 * based call ?
8506 if (tran_call != TRANSACT2_SETFILEINFO) {
8507 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8509 #endif
8510 status = smb_set_file_disposition_info(conn,
8511 pdata,
8512 total_data,
8513 fsp,
8514 smb_fname);
8515 break;
8518 case SMB_FILE_POSITION_INFORMATION:
8520 status = smb_file_position_information(conn,
8521 pdata,
8522 total_data,
8523 fsp);
8524 break;
8527 case SMB_FILE_FULL_EA_INFORMATION:
8529 status = smb_set_file_full_ea_info(conn,
8530 pdata,
8531 total_data,
8532 fsp);
8533 break;
8536 /* From tridge Samba4 :
8537 * MODE_INFORMATION in setfileinfo (I have no
8538 * idea what "mode information" on a file is - it takes a value of 0,
8539 * 2, 4 or 6. What could it be?).
8542 case SMB_FILE_MODE_INFORMATION:
8544 status = smb_file_mode_information(conn,
8545 pdata,
8546 total_data);
8547 break;
8551 * CIFS UNIX extensions.
8554 case SMB_SET_FILE_UNIX_BASIC:
8556 status = smb_set_file_unix_basic(conn, req,
8557 pdata,
8558 total_data,
8559 fsp,
8560 smb_fname);
8561 break;
8564 case SMB_SET_FILE_UNIX_INFO2:
8566 status = smb_set_file_unix_info2(conn, req,
8567 pdata,
8568 total_data,
8569 fsp,
8570 smb_fname);
8571 break;
8574 case SMB_SET_FILE_UNIX_LINK:
8576 if (fsp) {
8577 /* We must have a pathname for this. */
8578 return NT_STATUS_INVALID_LEVEL;
8580 status = smb_set_file_unix_link(conn, req, pdata,
8581 total_data, smb_fname);
8582 break;
8585 case SMB_SET_FILE_UNIX_HLINK:
8587 if (fsp) {
8588 /* We must have a pathname for this. */
8589 return NT_STATUS_INVALID_LEVEL;
8591 status = smb_set_file_unix_hlink(conn, req,
8592 pdata, total_data,
8593 smb_fname);
8594 break;
8597 case SMB_FILE_RENAME_INFORMATION:
8599 status = smb_file_rename_information(conn, req,
8600 pdata, total_data,
8601 fsp, smb_fname);
8602 break;
8605 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8607 /* SMB2 rename information. */
8608 status = smb2_file_rename_information(conn, req,
8609 pdata, total_data,
8610 fsp, smb_fname);
8611 break;
8614 case SMB_FILE_LINK_INFORMATION:
8616 status = smb_file_link_information(conn, req,
8617 pdata, total_data,
8618 fsp, smb_fname);
8619 break;
8622 #if defined(HAVE_POSIX_ACLS)
8623 case SMB_SET_POSIX_ACL:
8625 status = smb_set_posix_acl(conn,
8626 pdata,
8627 total_data,
8628 fsp,
8629 smb_fname);
8630 break;
8632 #endif
8634 case SMB_SET_POSIX_LOCK:
8636 if (!fsp) {
8637 return NT_STATUS_INVALID_LEVEL;
8639 status = smb_set_posix_lock(conn, req,
8640 pdata, total_data, fsp);
8641 break;
8644 case SMB_POSIX_PATH_OPEN:
8646 if (fsp) {
8647 /* We must have a pathname for this. */
8648 return NT_STATUS_INVALID_LEVEL;
8651 status = smb_posix_open(conn, req,
8652 ppdata,
8653 total_data,
8654 smb_fname,
8655 &data_return_size);
8656 break;
8659 case SMB_POSIX_PATH_UNLINK:
8661 if (fsp) {
8662 /* We must have a pathname for this. */
8663 return NT_STATUS_INVALID_LEVEL;
8666 status = smb_posix_unlink(conn, req,
8667 pdata,
8668 total_data,
8669 smb_fname);
8670 break;
8673 default:
8674 return NT_STATUS_INVALID_LEVEL;
8677 if (!NT_STATUS_IS_OK(status)) {
8678 return status;
8681 *ret_data_size = data_return_size;
8682 return NT_STATUS_OK;
8685 /****************************************************************************
8686 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8687 ****************************************************************************/
8689 static void call_trans2setfilepathinfo(connection_struct *conn,
8690 struct smb_request *req,
8691 unsigned int tran_call,
8692 char **pparams, int total_params,
8693 char **ppdata, int total_data,
8694 unsigned int max_data_bytes)
8696 char *params = *pparams;
8697 char *pdata = *ppdata;
8698 uint16_t info_level;
8699 struct smb_filename *smb_fname = NULL;
8700 files_struct *fsp = NULL;
8701 NTSTATUS status = NT_STATUS_OK;
8702 int data_return_size = 0;
8704 if (!params) {
8705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8706 return;
8709 if (tran_call == TRANSACT2_SETFILEINFO) {
8710 if (total_params < 4) {
8711 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8712 return;
8715 fsp = file_fsp(req, SVAL(params,0));
8716 /* Basic check for non-null fsp. */
8717 if (!check_fsp_open(conn, req, fsp)) {
8718 return;
8720 info_level = SVAL(params,2);
8722 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8723 if (smb_fname == NULL) {
8724 reply_nterror(req, NT_STATUS_NO_MEMORY);
8725 return;
8728 if(fsp->fh->fd == -1) {
8730 * This is actually a SETFILEINFO on a directory
8731 * handle (returned from an NT SMB). NT5.0 seems
8732 * to do this call. JRA.
8734 if (INFO_LEVEL_IS_UNIX(info_level)) {
8735 /* Always do lstat for UNIX calls. */
8736 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8737 DEBUG(3,("call_trans2setfilepathinfo: "
8738 "SMB_VFS_LSTAT of %s failed "
8739 "(%s)\n",
8740 smb_fname_str_dbg(smb_fname),
8741 strerror(errno)));
8742 reply_nterror(req, map_nt_error_from_unix(errno));
8743 return;
8745 } else {
8746 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8747 DEBUG(3,("call_trans2setfilepathinfo: "
8748 "fileinfo of %s failed (%s)\n",
8749 smb_fname_str_dbg(smb_fname),
8750 strerror(errno)));
8751 reply_nterror(req, map_nt_error_from_unix(errno));
8752 return;
8755 } else if (fsp->print_file) {
8757 * Doing a DELETE_ON_CLOSE should cancel a print job.
8759 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8760 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8762 DEBUG(3,("call_trans2setfilepathinfo: "
8763 "Cancelling print job (%s)\n",
8764 fsp_str_dbg(fsp)));
8766 SSVAL(params,0,0);
8767 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8768 *ppdata, 0,
8769 max_data_bytes);
8770 return;
8771 } else {
8772 reply_nterror(req,
8773 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8774 return;
8776 } else {
8778 * Original code - this is an open file.
8780 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8781 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8782 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8783 strerror(errno)));
8784 reply_nterror(req, map_nt_error_from_unix(errno));
8785 return;
8788 } else {
8789 char *fname = NULL;
8790 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8792 /* set path info */
8793 if (total_params < 7) {
8794 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8795 return;
8798 info_level = SVAL(params,0);
8799 if (req->posix_pathnames) {
8800 srvstr_get_path_posix(req,
8801 params,
8802 req->flags2,
8803 &fname,
8804 &params[6],
8805 total_params - 6,
8806 STR_TERMINATE,
8807 &status);
8808 } else {
8809 srvstr_get_path(req,
8810 params,
8811 req->flags2,
8812 &fname,
8813 &params[6],
8814 total_params - 6,
8815 STR_TERMINATE,
8816 &status);
8818 if (!NT_STATUS_IS_OK(status)) {
8819 reply_nterror(req, status);
8820 return;
8823 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8824 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8825 info_level == SMB_FILE_RENAME_INFORMATION ||
8826 info_level == SMB_POSIX_PATH_UNLINK) {
8827 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8830 status = filename_convert(req, conn,
8831 fname,
8832 ucf_flags,
8833 NULL,
8834 &smb_fname);
8835 if (!NT_STATUS_IS_OK(status)) {
8836 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8837 reply_botherror(req,
8838 NT_STATUS_PATH_NOT_COVERED,
8839 ERRSRV, ERRbadpath);
8840 return;
8842 reply_nterror(req, status);
8843 return;
8846 if (INFO_LEVEL_IS_UNIX(info_level)) {
8848 * For CIFS UNIX extensions the target name may not exist.
8851 /* Always do lstat for UNIX calls. */
8852 SMB_VFS_LSTAT(conn, smb_fname);
8854 } else if (!VALID_STAT(smb_fname->st) &&
8855 SMB_VFS_STAT(conn, smb_fname)) {
8856 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8857 "%s failed (%s)\n",
8858 smb_fname_str_dbg(smb_fname),
8859 strerror(errno)));
8860 reply_nterror(req, map_nt_error_from_unix(errno));
8861 return;
8865 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8866 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8867 fsp_fnum_dbg(fsp),
8868 info_level,total_data));
8870 /* Realloc the parameter size */
8871 *pparams = (char *)SMB_REALLOC(*pparams,2);
8872 if (*pparams == NULL) {
8873 reply_nterror(req, NT_STATUS_NO_MEMORY);
8874 return;
8876 params = *pparams;
8878 SSVAL(params,0,0);
8880 status = smbd_do_setfilepathinfo(conn, req, req,
8881 info_level,
8882 fsp,
8883 smb_fname,
8884 ppdata, total_data,
8885 &data_return_size);
8886 if (!NT_STATUS_IS_OK(status)) {
8887 if (open_was_deferred(req->xconn, req->mid)) {
8888 /* We have re-scheduled this call. */
8889 return;
8891 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8892 /* We have re-scheduled this call. */
8893 return;
8895 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8896 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8897 ERRSRV, ERRbadpath);
8898 return;
8900 if (info_level == SMB_POSIX_PATH_OPEN) {
8901 reply_openerror(req, status);
8902 return;
8906 * Invalid EA name needs to return 2 param bytes,
8907 * not a zero-length error packet.
8909 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8910 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8911 max_data_bytes);
8912 } else {
8913 reply_nterror(req, status);
8915 return;
8918 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8919 max_data_bytes);
8921 return;
8924 /****************************************************************************
8925 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8926 ****************************************************************************/
8928 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8929 char **pparams, int total_params,
8930 char **ppdata, int total_data,
8931 unsigned int max_data_bytes)
8933 struct smb_filename *smb_dname = NULL;
8934 char *params = *pparams;
8935 char *pdata = *ppdata;
8936 char *directory = NULL;
8937 NTSTATUS status = NT_STATUS_OK;
8938 struct ea_list *ea_list = NULL;
8939 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8940 TALLOC_CTX *ctx = talloc_tos();
8942 if (!CAN_WRITE(conn)) {
8943 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8944 return;
8947 if (total_params < 5) {
8948 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8949 return;
8952 if (req->posix_pathnames) {
8953 srvstr_get_path_posix(ctx,
8954 params,
8955 req->flags2,
8956 &directory,
8957 &params[4],
8958 total_params - 4,
8959 STR_TERMINATE,
8960 &status);
8961 } else {
8962 srvstr_get_path(ctx,
8963 params,
8964 req->flags2,
8965 &directory,
8966 &params[4],
8967 total_params - 4,
8968 STR_TERMINATE,
8969 &status);
8971 if (!NT_STATUS_IS_OK(status)) {
8972 reply_nterror(req, status);
8973 return;
8976 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8978 status = filename_convert(ctx,
8979 conn,
8980 directory,
8981 ucf_flags,
8982 NULL,
8983 &smb_dname);
8985 if (!NT_STATUS_IS_OK(status)) {
8986 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8987 reply_botherror(req,
8988 NT_STATUS_PATH_NOT_COVERED,
8989 ERRSRV, ERRbadpath);
8990 return;
8992 reply_nterror(req, status);
8993 return;
8997 * OS/2 workplace shell seems to send SET_EA requests of "null"
8998 * length (4 bytes containing IVAL 4).
8999 * They seem to have no effect. Bug #3212. JRA.
9002 if (total_data && (total_data != 4)) {
9003 /* Any data in this call is an EA list. */
9004 if (total_data < 10) {
9005 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9006 goto out;
9009 if (IVAL(pdata,0) > total_data) {
9010 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9011 IVAL(pdata,0), (unsigned int)total_data));
9012 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9013 goto out;
9016 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9017 total_data - 4);
9018 if (!ea_list) {
9019 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9020 goto out;
9023 if (!lp_ea_support(SNUM(conn))) {
9024 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9025 goto out;
9028 /* If total_data == 4 Windows doesn't care what values
9029 * are placed in that field, it just ignores them.
9030 * The System i QNTC IBM SMB client puts bad values here,
9031 * so ignore them. */
9033 status = create_directory(conn, req, smb_dname);
9035 if (!NT_STATUS_IS_OK(status)) {
9036 reply_nterror(req, status);
9037 goto out;
9040 /* Try and set any given EA. */
9041 if (ea_list) {
9042 status = set_ea(conn, NULL, smb_dname, ea_list);
9043 if (!NT_STATUS_IS_OK(status)) {
9044 reply_nterror(req, status);
9045 goto out;
9049 /* Realloc the parameter and data sizes */
9050 *pparams = (char *)SMB_REALLOC(*pparams,2);
9051 if(*pparams == NULL) {
9052 reply_nterror(req, NT_STATUS_NO_MEMORY);
9053 goto out;
9055 params = *pparams;
9057 SSVAL(params,0,0);
9059 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9061 out:
9062 TALLOC_FREE(smb_dname);
9063 return;
9066 /****************************************************************************
9067 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9068 We don't actually do this - we just send a null response.
9069 ****************************************************************************/
9071 static void call_trans2findnotifyfirst(connection_struct *conn,
9072 struct smb_request *req,
9073 char **pparams, int total_params,
9074 char **ppdata, int total_data,
9075 unsigned int max_data_bytes)
9077 char *params = *pparams;
9078 uint16_t info_level;
9080 if (total_params < 6) {
9081 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9082 return;
9085 info_level = SVAL(params,4);
9086 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9088 switch (info_level) {
9089 case 1:
9090 case 2:
9091 break;
9092 default:
9093 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9094 return;
9097 /* Realloc the parameter and data sizes */
9098 *pparams = (char *)SMB_REALLOC(*pparams,6);
9099 if (*pparams == NULL) {
9100 reply_nterror(req, NT_STATUS_NO_MEMORY);
9101 return;
9103 params = *pparams;
9105 SSVAL(params,0,fnf_handle);
9106 SSVAL(params,2,0); /* No changes */
9107 SSVAL(params,4,0); /* No EA errors */
9109 fnf_handle++;
9111 if(fnf_handle == 0)
9112 fnf_handle = 257;
9114 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9116 return;
9119 /****************************************************************************
9120 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9121 changes). Currently this does nothing.
9122 ****************************************************************************/
9124 static void call_trans2findnotifynext(connection_struct *conn,
9125 struct smb_request *req,
9126 char **pparams, int total_params,
9127 char **ppdata, int total_data,
9128 unsigned int max_data_bytes)
9130 char *params = *pparams;
9132 DEBUG(3,("call_trans2findnotifynext\n"));
9134 /* Realloc the parameter and data sizes */
9135 *pparams = (char *)SMB_REALLOC(*pparams,4);
9136 if (*pparams == NULL) {
9137 reply_nterror(req, NT_STATUS_NO_MEMORY);
9138 return;
9140 params = *pparams;
9142 SSVAL(params,0,0); /* No changes */
9143 SSVAL(params,2,0); /* No EA errors */
9145 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9147 return;
9150 /****************************************************************************
9151 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9152 ****************************************************************************/
9154 static void call_trans2getdfsreferral(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;
9161 char *pathname = NULL;
9162 int reply_size = 0;
9163 int max_referral_level;
9164 NTSTATUS status = NT_STATUS_OK;
9165 TALLOC_CTX *ctx = talloc_tos();
9167 DEBUG(10,("call_trans2getdfsreferral\n"));
9169 if (total_params < 3) {
9170 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9171 return;
9174 max_referral_level = SVAL(params,0);
9176 if(!lp_host_msdfs()) {
9177 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9178 return;
9181 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9182 total_params - 2, STR_TERMINATE);
9183 if (!pathname) {
9184 reply_nterror(req, NT_STATUS_NOT_FOUND);
9185 return;
9187 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9188 ppdata,&status)) < 0) {
9189 reply_nterror(req, status);
9190 return;
9193 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9194 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9195 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9197 return;
9200 #define LMCAT_SPL 0x53
9201 #define LMFUNC_GETJOBID 0x60
9203 /****************************************************************************
9204 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9205 ****************************************************************************/
9207 static void call_trans2ioctl(connection_struct *conn,
9208 struct smb_request *req,
9209 char **pparams, int total_params,
9210 char **ppdata, int total_data,
9211 unsigned int max_data_bytes)
9213 char *pdata = *ppdata;
9214 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9215 NTSTATUS status;
9216 size_t len = 0;
9218 /* check for an invalid fid before proceeding */
9220 if (!fsp) {
9221 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9222 return;
9225 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9226 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9227 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9228 if (*ppdata == NULL) {
9229 reply_nterror(req, NT_STATUS_NO_MEMORY);
9230 return;
9232 pdata = *ppdata;
9234 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9235 CAN ACCEPT THIS IN UNICODE. JRA. */
9237 /* Job number */
9238 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9240 status = srvstr_push(pdata, req->flags2, pdata + 2,
9241 lp_netbios_name(), 15,
9242 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9243 if (!NT_STATUS_IS_OK(status)) {
9244 reply_nterror(req, status);
9245 return;
9247 status = srvstr_push(pdata, req->flags2, pdata+18,
9248 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9249 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9250 if (!NT_STATUS_IS_OK(status)) {
9251 reply_nterror(req, status);
9252 return;
9254 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9255 max_data_bytes);
9256 return;
9259 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9260 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9263 /****************************************************************************
9264 Reply to a SMBfindclose (stop trans2 directory search).
9265 ****************************************************************************/
9267 void reply_findclose(struct smb_request *req)
9269 int dptr_num;
9270 struct smbd_server_connection *sconn = req->sconn;
9272 START_PROFILE(SMBfindclose);
9274 if (req->wct < 1) {
9275 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9276 END_PROFILE(SMBfindclose);
9277 return;
9280 dptr_num = SVALS(req->vwv+0, 0);
9282 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9284 dptr_close(sconn, &dptr_num);
9286 reply_outbuf(req, 0, 0);
9288 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9290 END_PROFILE(SMBfindclose);
9291 return;
9294 /****************************************************************************
9295 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9296 ****************************************************************************/
9298 void reply_findnclose(struct smb_request *req)
9300 int dptr_num;
9302 START_PROFILE(SMBfindnclose);
9304 if (req->wct < 1) {
9305 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9306 END_PROFILE(SMBfindnclose);
9307 return;
9310 dptr_num = SVAL(req->vwv+0, 0);
9312 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9314 /* We never give out valid handles for a
9315 findnotifyfirst - so any dptr_num is ok here.
9316 Just ignore it. */
9318 reply_outbuf(req, 0, 0);
9320 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9322 END_PROFILE(SMBfindnclose);
9323 return;
9326 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9327 struct trans_state *state)
9329 if (get_Protocol() >= PROTOCOL_NT1) {
9330 req->flags2 |= 0x40; /* IS_LONG_NAME */
9331 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9334 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9335 if (state->call != TRANSACT2_QFSINFO &&
9336 state->call != TRANSACT2_SETFSINFO) {
9337 DEBUG(0,("handle_trans2: encryption required "
9338 "with call 0x%x\n",
9339 (unsigned int)state->call));
9340 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9341 return;
9345 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9347 /* Now we must call the relevant TRANS2 function */
9348 switch(state->call) {
9349 case TRANSACT2_OPEN:
9351 START_PROFILE(Trans2_open);
9352 call_trans2open(conn, req,
9353 &state->param, state->total_param,
9354 &state->data, state->total_data,
9355 state->max_data_return);
9356 END_PROFILE(Trans2_open);
9357 break;
9360 case TRANSACT2_FINDFIRST:
9362 START_PROFILE(Trans2_findfirst);
9363 call_trans2findfirst(conn, req,
9364 &state->param, state->total_param,
9365 &state->data, state->total_data,
9366 state->max_data_return);
9367 END_PROFILE(Trans2_findfirst);
9368 break;
9371 case TRANSACT2_FINDNEXT:
9373 START_PROFILE(Trans2_findnext);
9374 call_trans2findnext(conn, req,
9375 &state->param, state->total_param,
9376 &state->data, state->total_data,
9377 state->max_data_return);
9378 END_PROFILE(Trans2_findnext);
9379 break;
9382 case TRANSACT2_QFSINFO:
9384 START_PROFILE(Trans2_qfsinfo);
9385 call_trans2qfsinfo(conn, req,
9386 &state->param, state->total_param,
9387 &state->data, state->total_data,
9388 state->max_data_return);
9389 END_PROFILE(Trans2_qfsinfo);
9390 break;
9393 case TRANSACT2_SETFSINFO:
9395 START_PROFILE(Trans2_setfsinfo);
9396 call_trans2setfsinfo(conn, req,
9397 &state->param, state->total_param,
9398 &state->data, state->total_data,
9399 state->max_data_return);
9400 END_PROFILE(Trans2_setfsinfo);
9401 break;
9404 case TRANSACT2_QPATHINFO:
9405 case TRANSACT2_QFILEINFO:
9407 START_PROFILE(Trans2_qpathinfo);
9408 call_trans2qfilepathinfo(conn, req, state->call,
9409 &state->param, state->total_param,
9410 &state->data, state->total_data,
9411 state->max_data_return);
9412 END_PROFILE(Trans2_qpathinfo);
9413 break;
9416 case TRANSACT2_SETPATHINFO:
9417 case TRANSACT2_SETFILEINFO:
9419 START_PROFILE(Trans2_setpathinfo);
9420 call_trans2setfilepathinfo(conn, req, state->call,
9421 &state->param, state->total_param,
9422 &state->data, state->total_data,
9423 state->max_data_return);
9424 END_PROFILE(Trans2_setpathinfo);
9425 break;
9428 case TRANSACT2_FINDNOTIFYFIRST:
9430 START_PROFILE(Trans2_findnotifyfirst);
9431 call_trans2findnotifyfirst(conn, req,
9432 &state->param, state->total_param,
9433 &state->data, state->total_data,
9434 state->max_data_return);
9435 END_PROFILE(Trans2_findnotifyfirst);
9436 break;
9439 case TRANSACT2_FINDNOTIFYNEXT:
9441 START_PROFILE(Trans2_findnotifynext);
9442 call_trans2findnotifynext(conn, req,
9443 &state->param, state->total_param,
9444 &state->data, state->total_data,
9445 state->max_data_return);
9446 END_PROFILE(Trans2_findnotifynext);
9447 break;
9450 case TRANSACT2_MKDIR:
9452 START_PROFILE(Trans2_mkdir);
9453 call_trans2mkdir(conn, req,
9454 &state->param, state->total_param,
9455 &state->data, state->total_data,
9456 state->max_data_return);
9457 END_PROFILE(Trans2_mkdir);
9458 break;
9461 case TRANSACT2_GET_DFS_REFERRAL:
9463 START_PROFILE(Trans2_get_dfs_referral);
9464 call_trans2getdfsreferral(conn, req,
9465 &state->param, state->total_param,
9466 &state->data, state->total_data,
9467 state->max_data_return);
9468 END_PROFILE(Trans2_get_dfs_referral);
9469 break;
9472 case TRANSACT2_IOCTL:
9474 START_PROFILE(Trans2_ioctl);
9475 call_trans2ioctl(conn, req,
9476 &state->param, state->total_param,
9477 &state->data, state->total_data,
9478 state->max_data_return);
9479 END_PROFILE(Trans2_ioctl);
9480 break;
9483 default:
9484 /* Error in request */
9485 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9486 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9490 /****************************************************************************
9491 Reply to a SMBtrans2.
9492 ****************************************************************************/
9494 void reply_trans2(struct smb_request *req)
9496 connection_struct *conn = req->conn;
9497 unsigned int dsoff;
9498 unsigned int dscnt;
9499 unsigned int psoff;
9500 unsigned int pscnt;
9501 unsigned int tran_call;
9502 struct trans_state *state;
9503 NTSTATUS result;
9505 START_PROFILE(SMBtrans2);
9507 if (req->wct < 14) {
9508 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9509 END_PROFILE(SMBtrans2);
9510 return;
9513 dsoff = SVAL(req->vwv+12, 0);
9514 dscnt = SVAL(req->vwv+11, 0);
9515 psoff = SVAL(req->vwv+10, 0);
9516 pscnt = SVAL(req->vwv+9, 0);
9517 tran_call = SVAL(req->vwv+14, 0);
9519 result = allow_new_trans(conn->pending_trans, req->mid);
9520 if (!NT_STATUS_IS_OK(result)) {
9521 DEBUG(2, ("Got invalid trans2 request: %s\n",
9522 nt_errstr(result)));
9523 reply_nterror(req, result);
9524 END_PROFILE(SMBtrans2);
9525 return;
9528 if (IS_IPC(conn)) {
9529 switch (tran_call) {
9530 /* List the allowed trans2 calls on IPC$ */
9531 case TRANSACT2_OPEN:
9532 case TRANSACT2_GET_DFS_REFERRAL:
9533 case TRANSACT2_QFILEINFO:
9534 case TRANSACT2_QFSINFO:
9535 case TRANSACT2_SETFSINFO:
9536 break;
9537 default:
9538 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9539 END_PROFILE(SMBtrans2);
9540 return;
9544 if ((state = talloc(conn, struct trans_state)) == NULL) {
9545 DEBUG(0, ("talloc failed\n"));
9546 reply_nterror(req, NT_STATUS_NO_MEMORY);
9547 END_PROFILE(SMBtrans2);
9548 return;
9551 state->cmd = SMBtrans2;
9553 state->mid = req->mid;
9554 state->vuid = req->vuid;
9555 state->setup_count = SVAL(req->vwv+13, 0);
9556 state->setup = NULL;
9557 state->total_param = SVAL(req->vwv+0, 0);
9558 state->param = NULL;
9559 state->total_data = SVAL(req->vwv+1, 0);
9560 state->data = NULL;
9561 state->max_param_return = SVAL(req->vwv+2, 0);
9562 state->max_data_return = SVAL(req->vwv+3, 0);
9563 state->max_setup_return = SVAL(req->vwv+4, 0);
9564 state->close_on_completion = BITSETW(req->vwv+5, 0);
9565 state->one_way = BITSETW(req->vwv+5, 1);
9567 state->call = tran_call;
9569 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9570 is so as a sanity check */
9571 if (state->setup_count != 1) {
9573 * Need to have rc=0 for ioctl to get job id for OS/2.
9574 * Network printing will fail if function is not successful.
9575 * Similar function in reply.c will be used if protocol
9576 * is LANMAN1.0 instead of LM1.2X002.
9577 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9578 * outbuf doesn't have to be set(only job id is used).
9580 if ( (state->setup_count == 4)
9581 && (tran_call == TRANSACT2_IOCTL)
9582 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9583 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9584 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9585 } else {
9586 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9587 DEBUG(2,("Transaction is %d\n",tran_call));
9588 TALLOC_FREE(state);
9589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9590 END_PROFILE(SMBtrans2);
9591 return;
9595 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9596 goto bad_param;
9598 if (state->total_data) {
9600 if (trans_oob(state->total_data, 0, dscnt)
9601 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9602 goto bad_param;
9605 /* Can't use talloc here, the core routines do realloc on the
9606 * params and data. */
9607 state->data = (char *)SMB_MALLOC(state->total_data);
9608 if (state->data == NULL) {
9609 DEBUG(0,("reply_trans2: data malloc fail for %u "
9610 "bytes !\n", (unsigned int)state->total_data));
9611 TALLOC_FREE(state);
9612 reply_nterror(req, NT_STATUS_NO_MEMORY);
9613 END_PROFILE(SMBtrans2);
9614 return;
9617 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9620 if (state->total_param) {
9622 if (trans_oob(state->total_param, 0, pscnt)
9623 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9624 goto bad_param;
9627 /* Can't use talloc here, the core routines do realloc on the
9628 * params and data. */
9629 state->param = (char *)SMB_MALLOC(state->total_param);
9630 if (state->param == NULL) {
9631 DEBUG(0,("reply_trans: param malloc fail for %u "
9632 "bytes !\n", (unsigned int)state->total_param));
9633 SAFE_FREE(state->data);
9634 TALLOC_FREE(state);
9635 reply_nterror(req, NT_STATUS_NO_MEMORY);
9636 END_PROFILE(SMBtrans2);
9637 return;
9640 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9643 state->received_data = dscnt;
9644 state->received_param = pscnt;
9646 if ((state->received_param == state->total_param) &&
9647 (state->received_data == state->total_data)) {
9649 handle_trans2(conn, req, state);
9651 SAFE_FREE(state->data);
9652 SAFE_FREE(state->param);
9653 TALLOC_FREE(state);
9654 END_PROFILE(SMBtrans2);
9655 return;
9658 DLIST_ADD(conn->pending_trans, state);
9660 /* We need to send an interim response then receive the rest
9661 of the parameter/data bytes */
9662 reply_outbuf(req, 0, 0);
9663 show_msg((char *)req->outbuf);
9664 END_PROFILE(SMBtrans2);
9665 return;
9667 bad_param:
9669 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9670 SAFE_FREE(state->data);
9671 SAFE_FREE(state->param);
9672 TALLOC_FREE(state);
9673 END_PROFILE(SMBtrans2);
9674 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9678 /****************************************************************************
9679 Reply to a SMBtranss2
9680 ****************************************************************************/
9682 void reply_transs2(struct smb_request *req)
9684 connection_struct *conn = req->conn;
9685 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9686 struct trans_state *state;
9688 START_PROFILE(SMBtranss2);
9690 show_msg((const char *)req->inbuf);
9692 /* Windows clients expect all replies to
9693 a transact secondary (SMBtranss2 0x33)
9694 to have a command code of transact
9695 (SMBtrans2 0x32). See bug #8989
9696 and also [MS-CIFS] section 2.2.4.47.2
9697 for details.
9699 req->cmd = SMBtrans2;
9701 if (req->wct < 8) {
9702 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9703 END_PROFILE(SMBtranss2);
9704 return;
9707 for (state = conn->pending_trans; state != NULL;
9708 state = state->next) {
9709 if (state->mid == req->mid) {
9710 break;
9714 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9715 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9716 END_PROFILE(SMBtranss2);
9717 return;
9720 /* Revise state->total_param and state->total_data in case they have
9721 changed downwards */
9723 if (SVAL(req->vwv+0, 0) < state->total_param)
9724 state->total_param = SVAL(req->vwv+0, 0);
9725 if (SVAL(req->vwv+1, 0) < state->total_data)
9726 state->total_data = SVAL(req->vwv+1, 0);
9728 pcnt = SVAL(req->vwv+2, 0);
9729 poff = SVAL(req->vwv+3, 0);
9730 pdisp = SVAL(req->vwv+4, 0);
9732 dcnt = SVAL(req->vwv+5, 0);
9733 doff = SVAL(req->vwv+6, 0);
9734 ddisp = SVAL(req->vwv+7, 0);
9736 state->received_param += pcnt;
9737 state->received_data += dcnt;
9739 if ((state->received_data > state->total_data) ||
9740 (state->received_param > state->total_param))
9741 goto bad_param;
9743 if (pcnt) {
9744 if (trans_oob(state->total_param, pdisp, pcnt)
9745 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9746 goto bad_param;
9748 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9751 if (dcnt) {
9752 if (trans_oob(state->total_data, ddisp, dcnt)
9753 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9754 goto bad_param;
9756 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9759 if ((state->received_param < state->total_param) ||
9760 (state->received_data < state->total_data)) {
9761 END_PROFILE(SMBtranss2);
9762 return;
9765 handle_trans2(conn, req, state);
9767 DLIST_REMOVE(conn->pending_trans, state);
9768 SAFE_FREE(state->data);
9769 SAFE_FREE(state->param);
9770 TALLOC_FREE(state);
9772 END_PROFILE(SMBtranss2);
9773 return;
9775 bad_param:
9777 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9778 DLIST_REMOVE(conn->pending_trans, state);
9779 SAFE_FREE(state->data);
9780 SAFE_FREE(state->param);
9781 TALLOC_FREE(state);
9782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9783 END_PROFILE(SMBtranss2);
9784 return;