libnet: Add NULL checks to py_net_finddc
[Samba.git] / source3 / smbd / trans2.c
blobdbad71be3b759ef8109f9f5da21f60d5e942e36d
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 /* We don't need to check for VOL here as this is returned by
2871 a different TRANS2 call. */
2873 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2874 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2875 if (in_list(directory,
2876 lp_dont_descend(talloc_tos(), SNUM(conn)),
2877 conn->case_sensitive)) {
2878 dont_descend = True;
2881 p = pdata;
2882 space_remaining = max_data_bytes;
2883 out_of_space = False;
2885 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2886 bool got_exact_match = False;
2888 /* this is a heuristic to avoid seeking the dirptr except when
2889 absolutely necessary. It allows for a filename of about 40 chars */
2890 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2891 out_of_space = True;
2892 finished = False;
2893 } else {
2894 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2895 conn,
2896 dirptr,
2897 req->flags2,
2898 mask,dirtype,info_level,
2899 requires_resume_key,dont_descend,
2900 ask_sharemode,
2901 &p,pdata,data_end,
2902 space_remaining,
2903 &got_exact_match,
2904 &last_entry_off, ea_list);
2905 if (NT_STATUS_EQUAL(ntstatus,
2906 NT_STATUS_ILLEGAL_CHARACTER)) {
2908 * Bad character conversion on name. Ignore this
2909 * entry.
2911 continue;
2913 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2914 out_of_space = true;
2915 } else {
2916 finished = !NT_STATUS_IS_OK(ntstatus);
2920 if (!finished && !out_of_space)
2921 numentries++;
2924 * As an optimisation if we know we aren't looking
2925 * for a wildcard name (ie. the name matches the wildcard exactly)
2926 * then we can finish on any (first) match.
2927 * This speeds up large directory searches. JRA.
2930 if(got_exact_match)
2931 finished = True;
2933 /* Ensure space_remaining never goes -ve. */
2934 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2935 space_remaining = 0;
2936 out_of_space = true;
2937 } else {
2938 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2942 /* Check if we can close the dirptr */
2943 if(close_after_first || (finished && close_if_end)) {
2944 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2945 dptr_close(sconn, &dptr_num);
2949 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2950 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2951 * the protocol level is less than NT1. Tested with smbclient. JRA.
2952 * This should fix the OS/2 client bug #2335.
2955 if(numentries == 0) {
2956 dptr_close(sconn, &dptr_num);
2957 if (get_Protocol() < PROTOCOL_NT1) {
2958 reply_force_doserror(req, ERRDOS, ERRnofiles);
2959 goto out;
2960 } else {
2961 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2962 ERRDOS, ERRbadfile);
2963 goto out;
2967 /* At this point pdata points to numentries directory entries. */
2969 /* Set up the return parameter block */
2970 SSVAL(params,0,dptr_num);
2971 SSVAL(params,2,numentries);
2972 SSVAL(params,4,finished);
2973 SSVAL(params,6,0); /* Never an EA error */
2974 SSVAL(params,8,last_entry_off);
2976 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2977 max_data_bytes);
2979 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2980 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2981 if (!directory) {
2982 reply_nterror(req, NT_STATUS_NO_MEMORY);
2986 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2987 smb_fn_name(req->cmd),
2988 mask, directory, dirtype, numentries ) );
2991 * Force a name mangle here to ensure that the
2992 * mask as an 8.3 name is top of the mangled cache.
2993 * The reasons for this are subtle. Don't remove
2994 * this code unless you know what you are doing
2995 * (see PR#13758). JRA.
2998 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2999 char mangled_name[13];
3000 name_to_8_3(mask, mangled_name, True, conn->params);
3002 out:
3004 if (as_root) {
3005 unbecome_root();
3008 TALLOC_FREE(smb_dname);
3009 return;
3012 /****************************************************************************
3013 Reply to a TRANS2_FINDNEXT.
3014 ****************************************************************************/
3016 static void call_trans2findnext(connection_struct *conn,
3017 struct smb_request *req,
3018 char **pparams, int total_params,
3019 char **ppdata, int total_data,
3020 unsigned int max_data_bytes)
3022 /* We must be careful here that we don't return more than the
3023 allowed number of data bytes. If this means returning fewer than
3024 maxentries then so be it. We assume that the redirector has
3025 enough room for the fixed number of parameter bytes it has
3026 requested. */
3027 char *params = *pparams;
3028 char *pdata = *ppdata;
3029 char *data_end;
3030 int dptr_num;
3031 int maxentries;
3032 uint16_t info_level;
3033 uint32_t resume_key;
3034 uint16_t findnext_flags;
3035 bool close_after_request;
3036 bool close_if_end;
3037 bool requires_resume_key;
3038 bool continue_bit;
3039 bool mask_contains_wcard = False;
3040 char *resume_name = NULL;
3041 const char *mask = NULL;
3042 const char *directory = NULL;
3043 char *p = NULL;
3044 uint16_t dirtype;
3045 int numentries = 0;
3046 int i, last_entry_off=0;
3047 bool finished = False;
3048 bool dont_descend = False;
3049 bool out_of_space = False;
3050 int space_remaining;
3051 struct ea_list *ea_list = NULL;
3052 NTSTATUS ntstatus = NT_STATUS_OK;
3053 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3054 TALLOC_CTX *ctx = talloc_tos();
3055 struct dptr_struct *dirptr;
3056 struct smbd_server_connection *sconn = req->sconn;
3057 bool backup_priv = false;
3058 bool as_root = false;
3060 if (total_params < 13) {
3061 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3062 return;
3065 dptr_num = SVAL(params,0);
3066 maxentries = SVAL(params,2);
3067 info_level = SVAL(params,4);
3068 resume_key = IVAL(params,6);
3069 findnext_flags = SVAL(params,10);
3070 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3071 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3072 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3073 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3075 if (!continue_bit) {
3076 /* We only need resume_name if continue_bit is zero. */
3077 if (req->posix_pathnames) {
3078 srvstr_get_path_wcard_posix(ctx,
3079 params,
3080 req->flags2,
3081 &resume_name,
3082 params+12,
3083 total_params - 12,
3084 STR_TERMINATE,
3085 &ntstatus,
3086 &mask_contains_wcard);
3087 } else {
3088 srvstr_get_path_wcard(ctx,
3089 params,
3090 req->flags2,
3091 &resume_name,
3092 params+12,
3093 total_params - 12,
3094 STR_TERMINATE,
3095 &ntstatus,
3096 &mask_contains_wcard);
3098 if (!NT_STATUS_IS_OK(ntstatus)) {
3099 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3100 complain (it thinks we're asking for the directory above the shared
3101 path or an invalid name). Catch this as the resume name is only compared, never used in
3102 a file access. JRA. */
3103 srvstr_pull_talloc(ctx, params, req->flags2,
3104 &resume_name, params+12,
3105 total_params - 12,
3106 STR_TERMINATE);
3108 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3109 reply_nterror(req, ntstatus);
3110 return;
3115 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3116 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3117 resume_key = %d resume name = %s continue=%d level = %d\n",
3118 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3119 requires_resume_key, resume_key,
3120 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3122 if (!maxentries) {
3123 /* W2K3 seems to treat zero as 1. */
3124 maxentries = 1;
3127 switch (info_level) {
3128 case SMB_FIND_INFO_STANDARD:
3129 case SMB_FIND_EA_SIZE:
3130 case SMB_FIND_EA_LIST:
3131 case SMB_FIND_FILE_DIRECTORY_INFO:
3132 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3133 case SMB_FIND_FILE_NAMES_INFO:
3134 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3135 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3136 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3137 break;
3138 case SMB_FIND_FILE_UNIX:
3139 case SMB_FIND_FILE_UNIX_INFO2:
3140 /* Always use filesystem for UNIX mtime query. */
3141 ask_sharemode = false;
3142 if (!lp_unix_extensions()) {
3143 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3144 return;
3146 break;
3147 default:
3148 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3149 return;
3152 if (info_level == SMB_FIND_EA_LIST) {
3153 uint32_t ea_size;
3155 if (total_data < 4) {
3156 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3157 return;
3160 ea_size = IVAL(pdata,0);
3161 if (ea_size != total_data) {
3162 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3163 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3165 return;
3168 if (!lp_ea_support(SNUM(conn))) {
3169 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3170 return;
3173 /* Pull out the list of names. */
3174 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3175 if (!ea_list) {
3176 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3177 return;
3181 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3182 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3183 return;
3186 *ppdata = (char *)SMB_REALLOC(
3187 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3188 if(*ppdata == NULL) {
3189 reply_nterror(req, NT_STATUS_NO_MEMORY);
3190 return;
3193 pdata = *ppdata;
3194 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3197 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3198 * error.
3200 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3201 /* Realloc the params space */
3202 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3203 if(*pparams == NULL ) {
3204 reply_nterror(req, NT_STATUS_NO_MEMORY);
3205 return;
3208 params = *pparams;
3210 /* Check that the dptr is valid */
3211 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3212 reply_nterror(req, STATUS_NO_MORE_FILES);
3213 return;
3216 directory = dptr_path(sconn, dptr_num);
3218 /* Get the wildcard mask from the dptr */
3219 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3220 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3221 reply_nterror(req, STATUS_NO_MORE_FILES);
3222 return;
3225 /* Get the attr mask from the dptr */
3226 dirtype = dptr_attr(sconn, dptr_num);
3228 backup_priv = dptr_get_priv(dirptr);
3230 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3231 "backup_priv = %d\n",
3232 dptr_num, mask, dirtype,
3233 (long)dirptr,
3234 dptr_TellDir(dirptr),
3235 (int)backup_priv));
3237 /* We don't need to check for VOL here as this is returned by
3238 a different TRANS2 call. */
3240 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3241 directory,lp_dont_descend(ctx, SNUM(conn))));
3242 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3243 dont_descend = True;
3245 p = pdata;
3246 space_remaining = max_data_bytes;
3247 out_of_space = False;
3249 if (backup_priv) {
3250 become_root();
3251 as_root = true;
3255 * Seek to the correct position. We no longer use the resume key but
3256 * depend on the last file name instead.
3259 if(!continue_bit && resume_name && *resume_name) {
3260 SMB_STRUCT_STAT st;
3262 long current_pos = 0;
3264 * Remember, name_to_8_3 is called by
3265 * get_lanman2_dir_entry(), so the resume name
3266 * could be mangled. Ensure we check the unmangled name.
3269 if (mangle_is_mangled(resume_name, conn->params)) {
3270 char *new_resume_name = NULL;
3271 mangle_lookup_name_from_8_3(ctx,
3272 resume_name,
3273 &new_resume_name,
3274 conn->params);
3275 if (new_resume_name) {
3276 resume_name = new_resume_name;
3281 * Fix for NT redirector problem triggered by resume key indexes
3282 * changing between directory scans. We now return a resume key of 0
3283 * and instead look for the filename to continue from (also given
3284 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3285 * findfirst/findnext (as is usual) then the directory pointer
3286 * should already be at the correct place.
3289 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3290 } /* end if resume_name && !continue_bit */
3292 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3293 bool got_exact_match = False;
3295 /* this is a heuristic to avoid seeking the dirptr except when
3296 absolutely necessary. It allows for a filename of about 40 chars */
3297 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3298 out_of_space = True;
3299 finished = False;
3300 } else {
3301 ntstatus = get_lanman2_dir_entry(ctx,
3302 conn,
3303 dirptr,
3304 req->flags2,
3305 mask,dirtype,info_level,
3306 requires_resume_key,dont_descend,
3307 ask_sharemode,
3308 &p,pdata,data_end,
3309 space_remaining,
3310 &got_exact_match,
3311 &last_entry_off, ea_list);
3312 if (NT_STATUS_EQUAL(ntstatus,
3313 NT_STATUS_ILLEGAL_CHARACTER)) {
3315 * Bad character conversion on name. Ignore this
3316 * entry.
3318 continue;
3320 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3321 out_of_space = true;
3322 } else {
3323 finished = !NT_STATUS_IS_OK(ntstatus);
3327 if (!finished && !out_of_space)
3328 numentries++;
3331 * As an optimisation if we know we aren't looking
3332 * for a wildcard name (ie. the name matches the wildcard exactly)
3333 * then we can finish on any (first) match.
3334 * This speeds up large directory searches. JRA.
3337 if(got_exact_match)
3338 finished = True;
3340 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3343 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3344 smb_fn_name(req->cmd),
3345 mask, directory, dirtype, numentries ) );
3347 /* Check if we can close the dirptr */
3348 if(close_after_request || (finished && close_if_end)) {
3349 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3350 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3353 if (as_root) {
3354 unbecome_root();
3357 /* Set up the return parameter block */
3358 SSVAL(params,0,numentries);
3359 SSVAL(params,2,finished);
3360 SSVAL(params,4,0); /* Never an EA error */
3361 SSVAL(params,6,last_entry_off);
3363 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3364 max_data_bytes);
3366 return;
3369 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3371 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3372 return objid;
3375 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3377 SMB_ASSERT(extended_info != NULL);
3379 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3380 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3381 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3382 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3383 #ifdef SAMBA_VERSION_REVISION
3384 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3385 #endif
3386 extended_info->samba_subversion = 0;
3387 #ifdef SAMBA_VERSION_RC_RELEASE
3388 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3389 #else
3390 #ifdef SAMBA_VERSION_PRE_RELEASE
3391 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3392 #endif
3393 #endif
3394 #ifdef SAMBA_VERSION_VENDOR_PATCH
3395 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3396 #endif
3397 extended_info->samba_gitcommitdate = 0;
3398 #ifdef SAMBA_VERSION_COMMIT_TIME
3399 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3400 #endif
3402 memset(extended_info->samba_version_string, 0,
3403 sizeof(extended_info->samba_version_string));
3405 snprintf (extended_info->samba_version_string,
3406 sizeof(extended_info->samba_version_string),
3407 "%s", samba_version_string());
3410 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3411 connection_struct *conn,
3412 TALLOC_CTX *mem_ctx,
3413 uint16_t info_level,
3414 uint16_t flags2,
3415 unsigned int max_data_bytes,
3416 size_t *fixed_portion,
3417 struct smb_filename *fname,
3418 char **ppdata,
3419 int *ret_data_len)
3421 char *pdata, *end_data;
3422 int data_len = 0;
3423 size_t len = 0;
3424 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3425 int snum = SNUM(conn);
3426 const char *fstype = lp_fstype(SNUM(conn));
3427 const char *filename = NULL;
3428 const uint64_t bytes_per_sector = 512;
3429 uint32_t additional_flags = 0;
3430 struct smb_filename smb_fname;
3431 SMB_STRUCT_STAT st;
3432 NTSTATUS status = NT_STATUS_OK;
3433 uint64_t df_ret;
3435 if (fname == NULL || fname->base_name == NULL) {
3436 filename = ".";
3437 } else {
3438 filename = fname->base_name;
3441 if (IS_IPC(conn)) {
3442 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3443 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3444 "info level (0x%x) on IPC$.\n",
3445 (unsigned int)info_level));
3446 return NT_STATUS_ACCESS_DENIED;
3450 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3452 ZERO_STRUCT(smb_fname);
3453 smb_fname.base_name = discard_const_p(char, filename);
3455 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3456 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3457 return map_nt_error_from_unix(errno);
3460 st = smb_fname.st;
3462 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3463 return NT_STATUS_INVALID_PARAMETER;
3466 *ppdata = (char *)SMB_REALLOC(
3467 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3468 if (*ppdata == NULL) {
3469 return NT_STATUS_NO_MEMORY;
3472 pdata = *ppdata;
3473 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3474 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3476 *fixed_portion = 0;
3478 switch (info_level) {
3479 case SMB_INFO_ALLOCATION:
3481 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3482 data_len = 18;
3483 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3484 &dfree, &dsize);
3485 if (df_ret == (uint64_t)-1) {
3486 return map_nt_error_from_unix(errno);
3489 block_size = lp_block_size(snum);
3490 if (bsize < block_size) {
3491 uint64_t factor = block_size/bsize;
3492 bsize = block_size;
3493 dsize /= factor;
3494 dfree /= factor;
3496 if (bsize > block_size) {
3497 uint64_t factor = bsize/block_size;
3498 bsize = block_size;
3499 dsize *= factor;
3500 dfree *= factor;
3502 sectors_per_unit = bsize/bytes_per_sector;
3504 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3505 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3506 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3509 * For large drives, return max values and not modulo.
3511 dsize = MIN(dsize, UINT32_MAX);
3512 dfree = MIN(dfree, UINT32_MAX);
3514 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3515 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3516 SIVAL(pdata,l1_cUnit,dsize);
3517 SIVAL(pdata,l1_cUnitAvail,dfree);
3518 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3519 break;
3522 case SMB_INFO_VOLUME:
3523 /* Return volume name */
3525 * Add volume serial number - hash of a combination of
3526 * the called hostname and the service name.
3528 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3530 * Win2k3 and previous mess this up by sending a name length
3531 * one byte short. I believe only older clients (OS/2 Win9x) use
3532 * this call so try fixing this by adding a terminating null to
3533 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3535 status = srvstr_push(
3536 pdata, flags2,
3537 pdata+l2_vol_szVolLabel, vname,
3538 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3539 STR_NOALIGN|STR_TERMINATE, &len);
3540 if (!NT_STATUS_IS_OK(status)) {
3541 return status;
3543 SCVAL(pdata,l2_vol_cch,len);
3544 data_len = l2_vol_szVolLabel + len;
3545 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3546 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3547 (unsigned)len, vname));
3548 break;
3550 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3551 case SMB_FS_ATTRIBUTE_INFORMATION:
3553 additional_flags = 0;
3554 #if defined(HAVE_SYS_QUOTAS)
3555 additional_flags |= FILE_VOLUME_QUOTAS;
3556 #endif
3558 if(lp_nt_acl_support(SNUM(conn))) {
3559 additional_flags |= FILE_PERSISTENT_ACLS;
3562 /* Capabilities are filled in at connection time through STATVFS call */
3563 additional_flags |= conn->fs_capabilities;
3564 additional_flags |= lp_parm_int(conn->params->service,
3565 "share", "fake_fscaps",
3568 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3569 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3570 additional_flags); /* FS ATTRIBUTES */
3572 SIVAL(pdata,4,255); /* Max filename component length */
3573 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3574 and will think we can't do long filenames */
3575 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3576 PTR_DIFF(end_data, pdata+12),
3577 STR_UNICODE, &len);
3578 if (!NT_STATUS_IS_OK(status)) {
3579 return status;
3581 SIVAL(pdata,8,len);
3582 data_len = 12 + len;
3583 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3584 /* the client only requested a portion of the
3585 file system name */
3586 data_len = max_data_bytes;
3587 status = STATUS_BUFFER_OVERFLOW;
3589 *fixed_portion = 16;
3590 break;
3592 case SMB_QUERY_FS_LABEL_INFO:
3593 case SMB_FS_LABEL_INFORMATION:
3594 status = srvstr_push(pdata, flags2, pdata+4, vname,
3595 PTR_DIFF(end_data, pdata+4), 0, &len);
3596 if (!NT_STATUS_IS_OK(status)) {
3597 return status;
3599 data_len = 4 + len;
3600 SIVAL(pdata,0,len);
3601 break;
3603 case SMB_QUERY_FS_VOLUME_INFO:
3604 case SMB_FS_VOLUME_INFORMATION:
3607 * Add volume serial number - hash of a combination of
3608 * the called hostname and the service name.
3610 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3611 (str_checksum(get_local_machine_name())<<16));
3613 /* Max label len is 32 characters. */
3614 status = srvstr_push(pdata, flags2, pdata+18, vname,
3615 PTR_DIFF(end_data, pdata+18),
3616 STR_UNICODE, &len);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 return status;
3620 SIVAL(pdata,12,len);
3621 data_len = 18+len;
3623 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3624 (int)strlen(vname),vname,
3625 lp_servicename(talloc_tos(), snum)));
3626 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3627 /* the client only requested a portion of the
3628 volume label */
3629 data_len = max_data_bytes;
3630 status = STATUS_BUFFER_OVERFLOW;
3632 *fixed_portion = 24;
3633 break;
3635 case SMB_QUERY_FS_SIZE_INFO:
3636 case SMB_FS_SIZE_INFORMATION:
3638 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3639 data_len = 24;
3640 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3641 &dfree, &dsize);
3642 if (df_ret == (uint64_t)-1) {
3643 return map_nt_error_from_unix(errno);
3645 block_size = lp_block_size(snum);
3646 if (bsize < block_size) {
3647 uint64_t factor = block_size/bsize;
3648 bsize = block_size;
3649 dsize /= factor;
3650 dfree /= factor;
3652 if (bsize > block_size) {
3653 uint64_t factor = bsize/block_size;
3654 bsize = block_size;
3655 dsize *= factor;
3656 dfree *= factor;
3658 sectors_per_unit = bsize/bytes_per_sector;
3659 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3660 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3661 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3662 SBIG_UINT(pdata,0,dsize);
3663 SBIG_UINT(pdata,8,dfree);
3664 SIVAL(pdata,16,sectors_per_unit);
3665 SIVAL(pdata,20,bytes_per_sector);
3666 *fixed_portion = 24;
3667 break;
3670 case SMB_FS_FULL_SIZE_INFORMATION:
3672 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3673 data_len = 32;
3674 df_ret = get_dfree_info(conn, &smb_fname, &bsize,
3675 &dfree, &dsize);
3676 if (df_ret == (uint64_t)-1) {
3677 return map_nt_error_from_unix(errno);
3679 block_size = lp_block_size(snum);
3680 if (bsize < block_size) {
3681 uint64_t factor = block_size/bsize;
3682 bsize = block_size;
3683 dsize /= factor;
3684 dfree /= factor;
3686 if (bsize > block_size) {
3687 uint64_t factor = bsize/block_size;
3688 bsize = block_size;
3689 dsize *= factor;
3690 dfree *= factor;
3692 sectors_per_unit = bsize/bytes_per_sector;
3693 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3694 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3695 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3696 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3697 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3698 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3699 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3700 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3701 *fixed_portion = 32;
3702 break;
3705 case SMB_QUERY_FS_DEVICE_INFO:
3706 case SMB_FS_DEVICE_INFORMATION:
3708 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3710 if (!CAN_WRITE(conn)) {
3711 characteristics |= FILE_READ_ONLY_DEVICE;
3713 data_len = 8;
3714 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3715 SIVAL(pdata,4,characteristics);
3716 *fixed_portion = 8;
3717 break;
3720 #ifdef HAVE_SYS_QUOTAS
3721 case SMB_FS_QUOTA_INFORMATION:
3723 * what we have to send --metze:
3725 * Unknown1: 24 NULL bytes
3726 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3727 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3728 * Quota Flags: 2 byte :
3729 * Unknown3: 6 NULL bytes
3731 * 48 bytes total
3733 * details for Quota Flags:
3735 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3736 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3737 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3738 * 0x0001 Enable Quotas: enable quota for this fs
3742 /* we need to fake up a fsp here,
3743 * because its not send in this call
3745 files_struct fsp;
3746 SMB_NTQUOTA_STRUCT quotas;
3748 ZERO_STRUCT(fsp);
3749 ZERO_STRUCT(quotas);
3751 fsp.conn = conn;
3752 fsp.fnum = FNUM_FIELD_INVALID;
3754 /* access check */
3755 if (get_current_uid(conn) != 0) {
3756 DEBUG(0,("get_user_quota: access_denied "
3757 "service [%s] user [%s]\n",
3758 lp_servicename(talloc_tos(), SNUM(conn)),
3759 conn->session_info->unix_info->unix_name));
3760 return NT_STATUS_ACCESS_DENIED;
3763 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3764 NULL, &quotas);
3765 if (!NT_STATUS_IS_OK(status)) {
3766 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3767 return status;
3770 data_len = 48;
3772 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3773 lp_servicename(talloc_tos(), SNUM(conn))));
3775 /* Unknown1 24 NULL bytes*/
3776 SBIG_UINT(pdata,0,(uint64_t)0);
3777 SBIG_UINT(pdata,8,(uint64_t)0);
3778 SBIG_UINT(pdata,16,(uint64_t)0);
3780 /* Default Soft Quota 8 bytes */
3781 SBIG_UINT(pdata,24,quotas.softlim);
3783 /* Default Hard Quota 8 bytes */
3784 SBIG_UINT(pdata,32,quotas.hardlim);
3786 /* Quota flag 2 bytes */
3787 SSVAL(pdata,40,quotas.qflags);
3789 /* Unknown3 6 NULL bytes */
3790 SSVAL(pdata,42,0);
3791 SIVAL(pdata,44,0);
3793 break;
3795 #endif /* HAVE_SYS_QUOTAS */
3796 case SMB_FS_OBJECTID_INFORMATION:
3798 unsigned char objid[16];
3799 struct smb_extended_info extended_info;
3800 memcpy(pdata,create_volume_objectid(conn, objid),16);
3801 samba_extended_info_version (&extended_info);
3802 SIVAL(pdata,16,extended_info.samba_magic);
3803 SIVAL(pdata,20,extended_info.samba_version);
3804 SIVAL(pdata,24,extended_info.samba_subversion);
3805 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3806 memcpy(pdata+36,extended_info.samba_version_string,28);
3807 data_len = 64;
3808 break;
3811 case SMB_FS_SECTOR_SIZE_INFORMATION:
3813 data_len = 28;
3815 * These values match a physical Windows Server 2012
3816 * share backed by NTFS atop spinning rust.
3818 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3819 /* logical_bytes_per_sector */
3820 SIVAL(pdata, 0, bytes_per_sector);
3821 /* phys_bytes_per_sector_atomic */
3822 SIVAL(pdata, 4, bytes_per_sector);
3823 /* phys_bytes_per_sector_perf */
3824 SIVAL(pdata, 8, bytes_per_sector);
3825 /* fs_effective_phys_bytes_per_sector_atomic */
3826 SIVAL(pdata, 12, bytes_per_sector);
3827 /* flags */
3828 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3829 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3830 /* byte_off_sector_align */
3831 SIVAL(pdata, 20, 0);
3832 /* byte_off_partition_align */
3833 SIVAL(pdata, 24, 0);
3834 *fixed_portion = 28;
3835 break;
3840 * Query the version and capabilities of the CIFS UNIX extensions
3841 * in use.
3844 case SMB_QUERY_CIFS_UNIX_INFO:
3846 bool large_write = lp_min_receive_file_size() &&
3847 !srv_is_signing_active(xconn);
3848 bool large_read = !srv_is_signing_active(xconn);
3849 int encrypt_caps = 0;
3851 if (!lp_unix_extensions()) {
3852 return NT_STATUS_INVALID_LEVEL;
3855 switch (conn->encrypt_level) {
3856 case SMB_SIGNING_OFF:
3857 encrypt_caps = 0;
3858 break;
3859 case SMB_SIGNING_DESIRED:
3860 case SMB_SIGNING_IF_REQUIRED:
3861 case SMB_SIGNING_DEFAULT:
3862 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3863 break;
3864 case SMB_SIGNING_REQUIRED:
3865 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3866 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3867 large_write = false;
3868 large_read = false;
3869 break;
3872 data_len = 12;
3873 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3874 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3876 /* We have POSIX ACLs, pathname, encryption,
3877 * large read/write, and locking capability. */
3879 SBIG_UINT(pdata,4,((uint64_t)(
3880 CIFS_UNIX_POSIX_ACLS_CAP|
3881 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3882 CIFS_UNIX_FCNTL_LOCKS_CAP|
3883 CIFS_UNIX_EXTATTR_CAP|
3884 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3885 encrypt_caps|
3886 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3887 (large_write ?
3888 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3889 break;
3892 case SMB_QUERY_POSIX_FS_INFO:
3894 int rc;
3895 vfs_statvfs_struct svfs;
3897 if (!lp_unix_extensions()) {
3898 return NT_STATUS_INVALID_LEVEL;
3901 rc = SMB_VFS_STATVFS(conn, &smb_fname, &svfs);
3903 if (!rc) {
3904 data_len = 56;
3905 SIVAL(pdata,0,svfs.OptimalTransferSize);
3906 SIVAL(pdata,4,svfs.BlockSize);
3907 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3908 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3909 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3910 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3911 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3912 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3913 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3914 #ifdef EOPNOTSUPP
3915 } else if (rc == EOPNOTSUPP) {
3916 return NT_STATUS_INVALID_LEVEL;
3917 #endif /* EOPNOTSUPP */
3918 } else {
3919 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3920 return NT_STATUS_DOS(ERRSRV, ERRerror);
3922 break;
3925 case SMB_QUERY_POSIX_WHOAMI:
3927 uint32_t flags = 0;
3928 uint32_t sid_bytes;
3929 int i;
3931 if (!lp_unix_extensions()) {
3932 return NT_STATUS_INVALID_LEVEL;
3935 if (max_data_bytes < 40) {
3936 return NT_STATUS_BUFFER_TOO_SMALL;
3939 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3940 flags |= SMB_WHOAMI_GUEST;
3943 /* NOTE: 8 bytes for UID/GID, irrespective of native
3944 * platform size. This matches
3945 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3947 data_len = 4 /* flags */
3948 + 4 /* flag mask */
3949 + 8 /* uid */
3950 + 8 /* gid */
3951 + 4 /* ngroups */
3952 + 4 /* num_sids */
3953 + 4 /* SID bytes */
3954 + 4 /* pad/reserved */
3955 + (conn->session_info->unix_token->ngroups * 8)
3956 /* groups list */
3957 + (conn->session_info->security_token->num_sids *
3958 SID_MAX_SIZE)
3959 /* SID list */;
3961 SIVAL(pdata, 0, flags);
3962 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3963 SBIG_UINT(pdata, 8,
3964 (uint64_t)conn->session_info->unix_token->uid);
3965 SBIG_UINT(pdata, 16,
3966 (uint64_t)conn->session_info->unix_token->gid);
3969 if (data_len >= max_data_bytes) {
3970 /* Potential overflow, skip the GIDs and SIDs. */
3972 SIVAL(pdata, 24, 0); /* num_groups */
3973 SIVAL(pdata, 28, 0); /* num_sids */
3974 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3975 SIVAL(pdata, 36, 0); /* reserved */
3977 data_len = 40;
3978 break;
3981 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3982 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3984 /* We walk the SID list twice, but this call is fairly
3985 * infrequent, and I don't expect that it's performance
3986 * sensitive -- jpeach
3988 for (i = 0, sid_bytes = 0;
3989 i < conn->session_info->security_token->num_sids; ++i) {
3990 sid_bytes += ndr_size_dom_sid(
3991 &conn->session_info->security_token->sids[i],
3995 /* SID list byte count */
3996 SIVAL(pdata, 32, sid_bytes);
3998 /* 4 bytes pad/reserved - must be zero */
3999 SIVAL(pdata, 36, 0);
4000 data_len = 40;
4002 /* GID list */
4003 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
4004 SBIG_UINT(pdata, data_len,
4005 (uint64_t)conn->session_info->unix_token->groups[i]);
4006 data_len += 8;
4009 /* SID list */
4010 for (i = 0;
4011 i < conn->session_info->security_token->num_sids; ++i) {
4012 int sid_len = ndr_size_dom_sid(
4013 &conn->session_info->security_token->sids[i],
4016 sid_linearize((uint8_t *)(pdata + data_len),
4017 sid_len,
4018 &conn->session_info->security_token->sids[i]);
4019 data_len += sid_len;
4022 break;
4025 case SMB_MAC_QUERY_FS_INFO:
4027 * Thursby MAC extension... ONLY on NTFS filesystems
4028 * once we do streams then we don't need this
4030 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
4031 data_len = 88;
4032 SIVAL(pdata,84,0x100); /* Don't support mac... */
4033 break;
4035 /* drop through */
4036 default:
4037 return NT_STATUS_INVALID_LEVEL;
4040 *ret_data_len = data_len;
4041 return status;
4044 static NTSTATUS smb_set_fsquota(connection_struct *conn,
4045 struct smb_request *req,
4046 files_struct *fsp,
4047 const DATA_BLOB *qdata)
4049 NTSTATUS status;
4050 SMB_NTQUOTA_STRUCT quotas;
4052 ZERO_STRUCT(quotas);
4054 /* access check */
4055 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4056 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4057 lp_servicename(talloc_tos(), SNUM(conn)),
4058 conn->session_info->unix_info->unix_name));
4059 return NT_STATUS_ACCESS_DENIED;
4062 if (!check_fsp_ntquota_handle(conn, req,
4063 fsp)) {
4064 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4065 return NT_STATUS_INVALID_HANDLE;
4068 /* note: normally there're 48 bytes,
4069 * but we didn't use the last 6 bytes for now
4070 * --metze
4072 if (qdata->length < 42) {
4073 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4074 (unsigned int)qdata->length));
4075 return NT_STATUS_INVALID_PARAMETER;
4078 /* unknown_1 24 NULL bytes in pdata*/
4080 /* the soft quotas 8 bytes (uint64_t)*/
4081 quotas.softlim = BVAL(qdata->data,24);
4083 /* the hard quotas 8 bytes (uint64_t)*/
4084 quotas.hardlim = BVAL(qdata->data,32);
4086 /* quota_flags 2 bytes **/
4087 quotas.qflags = SVAL(qdata->data,40);
4089 /* unknown_2 6 NULL bytes follow*/
4091 /* now set the quotas */
4092 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4093 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4094 lp_servicename(talloc_tos(), SNUM(conn))));
4095 status = map_nt_error_from_unix(errno);
4096 } else {
4097 status = NT_STATUS_OK;
4099 return status;
4102 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4103 struct smb_request *req,
4104 TALLOC_CTX *mem_ctx,
4105 uint16_t info_level,
4106 files_struct *fsp,
4107 const DATA_BLOB *pdata)
4109 switch (info_level) {
4110 case SMB_FS_QUOTA_INFORMATION:
4112 return smb_set_fsquota(conn,
4113 req,
4114 fsp,
4115 pdata);
4118 default:
4119 break;
4121 return NT_STATUS_INVALID_LEVEL;
4124 /****************************************************************************
4125 Reply to a TRANS2_QFSINFO (query filesystem info).
4126 ****************************************************************************/
4128 static void call_trans2qfsinfo(connection_struct *conn,
4129 struct smb_request *req,
4130 char **pparams, int total_params,
4131 char **ppdata, int total_data,
4132 unsigned int max_data_bytes)
4134 char *params = *pparams;
4135 uint16_t info_level;
4136 int data_len = 0;
4137 size_t fixed_portion;
4138 NTSTATUS status;
4140 if (total_params < 2) {
4141 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4142 return;
4145 info_level = SVAL(params,0);
4147 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4148 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4149 DEBUG(0,("call_trans2qfsinfo: encryption required "
4150 "and info level 0x%x sent.\n",
4151 (unsigned int)info_level));
4152 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4153 return;
4157 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4159 status = smbd_do_qfsinfo(req->xconn, conn, req,
4160 info_level,
4161 req->flags2,
4162 max_data_bytes,
4163 &fixed_portion,
4164 NULL,
4165 ppdata, &data_len);
4166 if (!NT_STATUS_IS_OK(status)) {
4167 reply_nterror(req, status);
4168 return;
4171 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4172 max_data_bytes);
4174 DEBUG( 4, ( "%s info_level = %d\n",
4175 smb_fn_name(req->cmd), info_level) );
4177 return;
4180 /****************************************************************************
4181 Reply to a TRANS2_SETFSINFO (set filesystem info).
4182 ****************************************************************************/
4184 static void call_trans2setfsinfo(connection_struct *conn,
4185 struct smb_request *req,
4186 char **pparams, int total_params,
4187 char **ppdata, int total_data,
4188 unsigned int max_data_bytes)
4190 struct smbXsrv_connection *xconn = req->xconn;
4191 char *pdata = *ppdata;
4192 char *params = *pparams;
4193 uint16_t info_level;
4195 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4196 lp_servicename(talloc_tos(), SNUM(conn))));
4198 /* */
4199 if (total_params < 4) {
4200 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4201 total_params));
4202 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4203 return;
4206 info_level = SVAL(params,2);
4208 if (IS_IPC(conn)) {
4209 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4210 info_level != SMB_SET_CIFS_UNIX_INFO) {
4211 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4212 "info level (0x%x) on IPC$.\n",
4213 (unsigned int)info_level));
4214 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4215 return;
4219 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4220 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4221 DEBUG(0,("call_trans2setfsinfo: encryption required "
4222 "and info level 0x%x sent.\n",
4223 (unsigned int)info_level));
4224 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4225 return;
4229 switch(info_level) {
4230 case SMB_SET_CIFS_UNIX_INFO:
4231 if (!lp_unix_extensions()) {
4232 DEBUG(2,("call_trans2setfsinfo: "
4233 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4234 "unix extensions off\n"));
4235 reply_nterror(req,
4236 NT_STATUS_INVALID_LEVEL);
4237 return;
4240 /* There should be 12 bytes of capabilities set. */
4241 if (total_data < 12) {
4242 reply_nterror(
4243 req,
4244 NT_STATUS_INVALID_PARAMETER);
4245 return;
4247 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4248 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4249 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4250 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4251 /* Just print these values for now. */
4252 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4253 "major = %u, minor = %u cap_low = 0x%x, "
4254 "cap_high = 0x%xn",
4255 (unsigned int)xconn->
4256 smb1.unix_info.client_major,
4257 (unsigned int)xconn->
4258 smb1.unix_info.client_minor,
4259 (unsigned int)xconn->
4260 smb1.unix_info.client_cap_low,
4261 (unsigned int)xconn->
4262 smb1.unix_info.client_cap_high));
4264 /* Here is where we must switch to posix pathname processing... */
4265 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4266 lp_set_posix_pathnames();
4267 mangle_change_to_posix();
4270 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4271 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4272 /* Client that knows how to do posix locks,
4273 * but not posix open/mkdir operations. Set a
4274 * default type for read/write checks. */
4276 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4279 break;
4281 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4283 NTSTATUS status;
4284 size_t param_len = 0;
4285 size_t data_len = total_data;
4287 if (!lp_unix_extensions()) {
4288 reply_nterror(
4289 req,
4290 NT_STATUS_INVALID_LEVEL);
4291 return;
4294 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4295 reply_nterror(
4296 req,
4297 NT_STATUS_NOT_SUPPORTED);
4298 return;
4301 if (xconn->smb1.echo_handler.trusted_fde) {
4302 DEBUG( 2,("call_trans2setfsinfo: "
4303 "request transport encryption disabled"
4304 "with 'fork echo handler = yes'\n"));
4305 reply_nterror(
4306 req,
4307 NT_STATUS_NOT_SUPPORTED);
4308 return;
4311 DEBUG( 4,("call_trans2setfsinfo: "
4312 "request transport encryption.\n"));
4314 status = srv_request_encryption_setup(conn,
4315 (unsigned char **)ppdata,
4316 &data_len,
4317 (unsigned char **)pparams,
4318 &param_len);
4320 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4321 !NT_STATUS_IS_OK(status)) {
4322 reply_nterror(req, status);
4323 return;
4326 send_trans2_replies(conn, req,
4327 NT_STATUS_OK,
4328 *pparams,
4329 param_len,
4330 *ppdata,
4331 data_len,
4332 max_data_bytes);
4334 if (NT_STATUS_IS_OK(status)) {
4335 /* Server-side transport
4336 * encryption is now *on*. */
4337 status = srv_encryption_start(conn);
4338 if (!NT_STATUS_IS_OK(status)) {
4339 char *reason = talloc_asprintf(talloc_tos(),
4340 "Failure in setting "
4341 "up encrypted transport: %s",
4342 nt_errstr(status));
4343 exit_server_cleanly(reason);
4346 return;
4349 case SMB_FS_QUOTA_INFORMATION:
4351 NTSTATUS status;
4352 DATA_BLOB qdata = {
4353 .data = (uint8_t *)pdata,
4354 .length = total_data
4356 files_struct *fsp = NULL;
4357 fsp = file_fsp(req, SVAL(params,0));
4359 status = smb_set_fsquota(conn,
4360 req,
4361 fsp,
4362 &qdata);
4363 if (!NT_STATUS_IS_OK(status)) {
4364 reply_nterror(req, status);
4365 return;
4367 break;
4369 default:
4370 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4371 info_level));
4372 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4373 return;
4374 break;
4378 * sending this reply works fine,
4379 * but I'm not sure it's the same
4380 * like windows do...
4381 * --metze
4383 reply_outbuf(req, 10, 0);
4386 #if defined(HAVE_POSIX_ACLS)
4387 /****************************************************************************
4388 Utility function to count the number of entries in a POSIX acl.
4389 ****************************************************************************/
4391 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4393 unsigned int ace_count = 0;
4394 int entry_id = SMB_ACL_FIRST_ENTRY;
4395 SMB_ACL_ENTRY_T entry;
4397 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4398 /* get_next... */
4399 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4400 entry_id = SMB_ACL_NEXT_ENTRY;
4402 ace_count++;
4404 return ace_count;
4407 /****************************************************************************
4408 Utility function to marshall a POSIX acl into wire format.
4409 ****************************************************************************/
4411 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4413 int entry_id = SMB_ACL_FIRST_ENTRY;
4414 SMB_ACL_ENTRY_T entry;
4416 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4417 SMB_ACL_TAG_T tagtype;
4418 SMB_ACL_PERMSET_T permset;
4419 unsigned char perms = 0;
4420 unsigned int own_grp;
4422 /* get_next... */
4423 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4424 entry_id = SMB_ACL_NEXT_ENTRY;
4427 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4428 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4429 return False;
4432 if (sys_acl_get_permset(entry, &permset) == -1) {
4433 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4434 return False;
4437 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4438 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4439 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4441 SCVAL(pdata,1,perms);
4443 switch (tagtype) {
4444 case SMB_ACL_USER_OBJ:
4445 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4446 own_grp = (unsigned int)pst->st_ex_uid;
4447 SIVAL(pdata,2,own_grp);
4448 SIVAL(pdata,6,0);
4449 break;
4450 case SMB_ACL_USER:
4452 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4453 if (!puid) {
4454 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4455 return False;
4457 own_grp = (unsigned int)*puid;
4458 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4459 SIVAL(pdata,2,own_grp);
4460 SIVAL(pdata,6,0);
4461 break;
4463 case SMB_ACL_GROUP_OBJ:
4464 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4465 own_grp = (unsigned int)pst->st_ex_gid;
4466 SIVAL(pdata,2,own_grp);
4467 SIVAL(pdata,6,0);
4468 break;
4469 case SMB_ACL_GROUP:
4471 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4472 if (!pgid) {
4473 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4474 return False;
4476 own_grp = (unsigned int)*pgid;
4477 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4478 SIVAL(pdata,2,own_grp);
4479 SIVAL(pdata,6,0);
4480 break;
4482 case SMB_ACL_MASK:
4483 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4484 SIVAL(pdata,2,0xFFFFFFFF);
4485 SIVAL(pdata,6,0xFFFFFFFF);
4486 break;
4487 case SMB_ACL_OTHER:
4488 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4489 SIVAL(pdata,2,0xFFFFFFFF);
4490 SIVAL(pdata,6,0xFFFFFFFF);
4491 break;
4492 default:
4493 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4494 return False;
4496 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4499 return True;
4501 #endif
4503 /****************************************************************************
4504 Store the FILE_UNIX_BASIC info.
4505 ****************************************************************************/
4507 static char *store_file_unix_basic(connection_struct *conn,
4508 char *pdata,
4509 files_struct *fsp,
4510 const SMB_STRUCT_STAT *psbuf)
4512 uint64_t file_index = get_FileIndex(conn, psbuf);
4513 dev_t devno;
4515 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4516 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4518 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4519 pdata += 8;
4521 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4522 pdata += 8;
4524 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4525 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4526 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4527 pdata += 24;
4529 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4530 SIVAL(pdata,4,0);
4531 pdata += 8;
4533 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4534 SIVAL(pdata,4,0);
4535 pdata += 8;
4537 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4538 pdata += 4;
4540 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4541 devno = psbuf->st_ex_rdev;
4542 } else {
4543 devno = psbuf->st_ex_dev;
4546 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4547 SIVAL(pdata,4,0);
4548 pdata += 8;
4550 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4551 SIVAL(pdata,4,0);
4552 pdata += 8;
4554 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4555 pdata += 8;
4557 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4558 SIVAL(pdata,4,0);
4559 pdata += 8;
4561 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4562 SIVAL(pdata,4,0);
4563 pdata += 8;
4565 return pdata;
4568 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4569 * the chflags(2) (or equivalent) flags.
4571 * XXX: this really should be behind the VFS interface. To do this, we would
4572 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4573 * Each VFS module could then implement its own mapping as appropriate for the
4574 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4576 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4577 info2_flags_map[] =
4579 #ifdef UF_NODUMP
4580 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4581 #endif
4583 #ifdef UF_IMMUTABLE
4584 { UF_IMMUTABLE, EXT_IMMUTABLE },
4585 #endif
4587 #ifdef UF_APPEND
4588 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4589 #endif
4591 #ifdef UF_HIDDEN
4592 { UF_HIDDEN, EXT_HIDDEN },
4593 #endif
4595 /* Do not remove. We need to guarantee that this array has at least one
4596 * entry to build on HP-UX.
4598 { 0, 0 }
4602 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4603 uint32_t *smb_fflags, uint32_t *smb_fmask)
4605 int i;
4607 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4608 *smb_fmask |= info2_flags_map[i].smb_fflag;
4609 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4610 *smb_fflags |= info2_flags_map[i].smb_fflag;
4615 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4616 const uint32_t smb_fflags,
4617 const uint32_t smb_fmask,
4618 int *stat_fflags)
4620 uint32_t max_fmask = 0;
4621 int i;
4623 *stat_fflags = psbuf->st_ex_flags;
4625 /* For each flags requested in smb_fmask, check the state of the
4626 * corresponding flag in smb_fflags and set or clear the matching
4627 * stat flag.
4630 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4631 max_fmask |= info2_flags_map[i].smb_fflag;
4632 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4633 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4634 *stat_fflags |= info2_flags_map[i].stat_fflag;
4635 } else {
4636 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4641 /* If smb_fmask is asking to set any bits that are not supported by
4642 * our flag mappings, we should fail.
4644 if ((smb_fmask & max_fmask) != smb_fmask) {
4645 return False;
4648 return True;
4652 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4653 * of file flags and birth (create) time.
4655 static char *store_file_unix_basic_info2(connection_struct *conn,
4656 char *pdata,
4657 files_struct *fsp,
4658 const SMB_STRUCT_STAT *psbuf)
4660 uint32_t file_flags = 0;
4661 uint32_t flags_mask = 0;
4663 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4665 /* Create (birth) time 64 bit */
4666 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4667 pdata += 8;
4669 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4670 SIVAL(pdata, 0, file_flags); /* flags */
4671 SIVAL(pdata, 4, flags_mask); /* mask */
4672 pdata += 8;
4674 return pdata;
4677 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4678 const struct stream_struct *streams,
4679 char *data,
4680 unsigned int max_data_bytes,
4681 unsigned int *data_size)
4683 unsigned int i;
4684 unsigned int ofs = 0;
4686 if (max_data_bytes < 32) {
4687 return NT_STATUS_INFO_LENGTH_MISMATCH;
4690 for (i = 0; i < num_streams; i++) {
4691 unsigned int next_offset;
4692 size_t namelen;
4693 smb_ucs2_t *namebuf;
4695 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4696 streams[i].name, &namelen) ||
4697 namelen <= 2)
4699 return NT_STATUS_INVALID_PARAMETER;
4703 * name_buf is now null-terminated, we need to marshall as not
4704 * terminated
4707 namelen -= 2;
4710 * We cannot overflow ...
4712 if ((ofs + 24 + namelen) > max_data_bytes) {
4713 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4714 i));
4715 TALLOC_FREE(namebuf);
4716 return STATUS_BUFFER_OVERFLOW;
4719 SIVAL(data, ofs+4, namelen);
4720 SOFF_T(data, ofs+8, streams[i].size);
4721 SOFF_T(data, ofs+16, streams[i].alloc_size);
4722 memcpy(data+ofs+24, namebuf, namelen);
4723 TALLOC_FREE(namebuf);
4725 next_offset = ofs + 24 + namelen;
4727 if (i == num_streams-1) {
4728 SIVAL(data, ofs, 0);
4730 else {
4731 unsigned int align = ndr_align_size(next_offset, 8);
4733 if ((next_offset + align) > max_data_bytes) {
4734 DEBUG(10, ("refusing to overflow align "
4735 "reply at stream %u\n",
4736 i));
4737 TALLOC_FREE(namebuf);
4738 return STATUS_BUFFER_OVERFLOW;
4741 memset(data+next_offset, 0, align);
4742 next_offset += align;
4744 SIVAL(data, ofs, next_offset - ofs);
4745 ofs = next_offset;
4748 ofs = next_offset;
4751 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4753 *data_size = ofs;
4755 return NT_STATUS_OK;
4758 /****************************************************************************
4759 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4760 ****************************************************************************/
4762 static void call_trans2qpipeinfo(connection_struct *conn,
4763 struct smb_request *req,
4764 unsigned int tran_call,
4765 char **pparams, int total_params,
4766 char **ppdata, int total_data,
4767 unsigned int max_data_bytes)
4769 char *params = *pparams;
4770 char *pdata = *ppdata;
4771 unsigned int data_size = 0;
4772 unsigned int param_size = 2;
4773 uint16_t info_level;
4774 files_struct *fsp;
4776 if (!params) {
4777 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4778 return;
4781 if (total_params < 4) {
4782 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4783 return;
4786 fsp = file_fsp(req, SVAL(params,0));
4787 if (!fsp_is_np(fsp)) {
4788 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4789 return;
4792 info_level = SVAL(params,2);
4794 *pparams = (char *)SMB_REALLOC(*pparams,2);
4795 if (*pparams == NULL) {
4796 reply_nterror(req, NT_STATUS_NO_MEMORY);
4797 return;
4799 params = *pparams;
4800 SSVAL(params,0,0);
4801 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4803 return;
4805 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4806 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4807 if (*ppdata == NULL ) {
4808 reply_nterror(req, NT_STATUS_NO_MEMORY);
4809 return;
4811 pdata = *ppdata;
4813 switch (info_level) {
4814 case SMB_FILE_STANDARD_INFORMATION:
4815 memset(pdata,0,24);
4816 SOFF_T(pdata,0,4096LL);
4817 SIVAL(pdata,16,1);
4818 SIVAL(pdata,20,1);
4819 data_size = 24;
4820 break;
4822 default:
4823 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4824 return;
4827 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4828 max_data_bytes);
4830 return;
4833 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4834 TALLOC_CTX *mem_ctx,
4835 uint16_t info_level,
4836 files_struct *fsp,
4837 struct smb_filename *smb_fname,
4838 bool delete_pending,
4839 struct timespec write_time_ts,
4840 struct ea_list *ea_list,
4841 int lock_data_count,
4842 char *lock_data,
4843 uint16_t flags2,
4844 unsigned int max_data_bytes,
4845 size_t *fixed_portion,
4846 char **ppdata,
4847 unsigned int *pdata_size)
4849 char *pdata = *ppdata;
4850 char *dstart, *dend;
4851 unsigned int data_size;
4852 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4853 time_t create_time, mtime, atime, c_time;
4854 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4855 char *p;
4856 char *base_name;
4857 char *dos_fname;
4858 int mode;
4859 int nlink;
4860 NTSTATUS status;
4861 uint64_t file_size = 0;
4862 uint64_t pos = 0;
4863 uint64_t allocation_size = 0;
4864 uint64_t file_index = 0;
4865 uint32_t access_mask = 0;
4866 size_t len = 0;
4868 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4869 return NT_STATUS_INVALID_LEVEL;
4872 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4873 smb_fname_str_dbg(smb_fname),
4874 fsp_fnum_dbg(fsp),
4875 info_level, max_data_bytes));
4877 mode = dos_mode(conn, smb_fname);
4878 nlink = psbuf->st_ex_nlink;
4880 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4881 nlink = 1;
4884 if ((nlink > 0) && delete_pending) {
4885 nlink -= 1;
4888 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4889 return NT_STATUS_INVALID_PARAMETER;
4892 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4893 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4894 if (*ppdata == NULL) {
4895 return NT_STATUS_NO_MEMORY;
4897 pdata = *ppdata;
4898 dstart = pdata;
4899 dend = dstart + data_size - 1;
4901 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4902 update_stat_ex_mtime(psbuf, write_time_ts);
4905 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4906 mtime_ts = psbuf->st_ex_mtime;
4907 atime_ts = psbuf->st_ex_atime;
4908 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4910 if (lp_dos_filetime_resolution(SNUM(conn))) {
4911 dos_filetime_timespec(&create_time_ts);
4912 dos_filetime_timespec(&mtime_ts);
4913 dos_filetime_timespec(&atime_ts);
4914 dos_filetime_timespec(&ctime_ts);
4917 create_time = convert_timespec_to_time_t(create_time_ts);
4918 mtime = convert_timespec_to_time_t(mtime_ts);
4919 atime = convert_timespec_to_time_t(atime_ts);
4920 c_time = convert_timespec_to_time_t(ctime_ts);
4922 p = strrchr_m(smb_fname->base_name,'/');
4923 if (!p)
4924 base_name = smb_fname->base_name;
4925 else
4926 base_name = p+1;
4928 /* NT expects the name to be in an exact form of the *full*
4929 filename. See the trans2 torture test */
4930 if (ISDOT(base_name)) {
4931 dos_fname = talloc_strdup(mem_ctx, "\\");
4932 if (!dos_fname) {
4933 return NT_STATUS_NO_MEMORY;
4935 } else {
4936 dos_fname = talloc_asprintf(mem_ctx,
4937 "\\%s",
4938 smb_fname->base_name);
4939 if (!dos_fname) {
4940 return NT_STATUS_NO_MEMORY;
4942 if (is_ntfs_stream_smb_fname(smb_fname)) {
4943 dos_fname = talloc_asprintf(dos_fname, "%s",
4944 smb_fname->stream_name);
4945 if (!dos_fname) {
4946 return NT_STATUS_NO_MEMORY;
4950 string_replace(dos_fname, '/', '\\');
4953 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4955 if (!fsp) {
4956 /* Do we have this path open ? */
4957 files_struct *fsp1;
4958 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4959 fsp1 = file_find_di_first(conn->sconn, fileid);
4960 if (fsp1 && fsp1->initial_allocation_size) {
4961 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4965 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4966 file_size = get_file_size_stat(psbuf);
4969 if (fsp) {
4970 pos = fsp->fh->position_information;
4973 if (fsp) {
4974 access_mask = fsp->access_mask;
4975 } else {
4976 /* GENERIC_EXECUTE mapping from Windows */
4977 access_mask = 0x12019F;
4980 /* This should be an index number - looks like
4981 dev/ino to me :-)
4983 I think this causes us to fail the IFSKIT
4984 BasicFileInformationTest. -tpot */
4985 file_index = get_FileIndex(conn, psbuf);
4987 *fixed_portion = 0;
4989 switch (info_level) {
4990 case SMB_INFO_STANDARD:
4991 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4992 data_size = 22;
4993 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4994 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4995 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4996 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4997 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4998 SSVAL(pdata,l1_attrFile,mode);
4999 break;
5001 case SMB_INFO_QUERY_EA_SIZE:
5003 unsigned int ea_size =
5004 estimate_ea_size(conn, fsp,
5005 smb_fname);
5006 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
5007 data_size = 26;
5008 srv_put_dos_date2(pdata,0,create_time);
5009 srv_put_dos_date2(pdata,4,atime);
5010 srv_put_dos_date2(pdata,8,mtime); /* write time */
5011 SIVAL(pdata,12,(uint32_t)file_size);
5012 SIVAL(pdata,16,(uint32_t)allocation_size);
5013 SSVAL(pdata,20,mode);
5014 SIVAL(pdata,22,ea_size);
5015 break;
5018 case SMB_INFO_IS_NAME_VALID:
5019 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
5020 if (fsp) {
5021 /* os/2 needs this ? really ?*/
5022 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
5024 /* This is only reached for qpathinfo */
5025 data_size = 0;
5026 break;
5028 case SMB_INFO_QUERY_EAS_FROM_LIST:
5030 size_t total_ea_len = 0;
5031 struct ea_list *ea_file_list = NULL;
5032 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
5034 status =
5035 get_ea_list_from_file(mem_ctx, conn, fsp,
5036 smb_fname,
5037 &total_ea_len, &ea_file_list);
5038 if (!NT_STATUS_IS_OK(status)) {
5039 return status;
5042 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
5044 if (!ea_list || (total_ea_len > data_size)) {
5045 data_size = 4;
5046 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5047 break;
5050 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5051 break;
5054 case SMB_INFO_QUERY_ALL_EAS:
5056 /* We have data_size bytes to put EA's into. */
5057 size_t total_ea_len = 0;
5058 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5060 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5061 smb_fname,
5062 &total_ea_len, &ea_list);
5063 if (!NT_STATUS_IS_OK(status)) {
5064 return status;
5067 if (!ea_list || (total_ea_len > data_size)) {
5068 data_size = 4;
5069 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5070 break;
5073 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5074 break;
5077 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5079 /* This is FileFullEaInformation - 0xF which maps to
5080 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5082 /* We have data_size bytes to put EA's into. */
5083 size_t total_ea_len = 0;
5084 struct ea_list *ea_file_list = NULL;
5086 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5088 /*TODO: add filtering and index handling */
5090 status =
5091 get_ea_list_from_file(mem_ctx, conn, fsp,
5092 smb_fname,
5093 &total_ea_len, &ea_file_list);
5094 if (!NT_STATUS_IS_OK(status)) {
5095 return status;
5097 if (!ea_file_list) {
5098 return NT_STATUS_NO_EAS_ON_FILE;
5101 status = fill_ea_chained_buffer(mem_ctx,
5102 pdata,
5103 data_size,
5104 &data_size,
5105 conn, ea_file_list);
5106 if (!NT_STATUS_IS_OK(status)) {
5107 return status;
5109 break;
5112 case SMB_FILE_BASIC_INFORMATION:
5113 case SMB_QUERY_FILE_BASIC_INFO:
5115 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5116 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5117 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5118 } else {
5119 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5120 data_size = 40;
5121 SIVAL(pdata,36,0);
5123 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5124 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5125 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5126 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5127 SIVAL(pdata,32,mode);
5129 DEBUG(5,("SMB_QFBI - "));
5130 DEBUG(5,("create: %s ", ctime(&create_time)));
5131 DEBUG(5,("access: %s ", ctime(&atime)));
5132 DEBUG(5,("write: %s ", ctime(&mtime)));
5133 DEBUG(5,("change: %s ", ctime(&c_time)));
5134 DEBUG(5,("mode: %x\n", mode));
5135 *fixed_portion = data_size;
5136 break;
5138 case SMB_FILE_STANDARD_INFORMATION:
5139 case SMB_QUERY_FILE_STANDARD_INFO:
5141 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5142 data_size = 24;
5143 SOFF_T(pdata,0,allocation_size);
5144 SOFF_T(pdata,8,file_size);
5145 SIVAL(pdata,16,nlink);
5146 SCVAL(pdata,20,delete_pending?1:0);
5147 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5148 SSVAL(pdata,22,0); /* Padding. */
5149 *fixed_portion = 24;
5150 break;
5152 case SMB_FILE_EA_INFORMATION:
5153 case SMB_QUERY_FILE_EA_INFO:
5155 unsigned int ea_size =
5156 estimate_ea_size(conn, fsp, smb_fname);
5157 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5158 data_size = 4;
5159 *fixed_portion = 4;
5160 SIVAL(pdata,0,ea_size);
5161 break;
5164 /* Get the 8.3 name - used if NT SMB was negotiated. */
5165 case SMB_QUERY_FILE_ALT_NAME_INFO:
5166 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5168 char mangled_name[13];
5169 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5170 if (!name_to_8_3(base_name,mangled_name,
5171 True,conn->params)) {
5172 return NT_STATUS_NO_MEMORY;
5174 status = srvstr_push(dstart, flags2,
5175 pdata+4, mangled_name,
5176 PTR_DIFF(dend, pdata+4),
5177 STR_UNICODE, &len);
5178 if (!NT_STATUS_IS_OK(status)) {
5179 return status;
5181 data_size = 4 + len;
5182 SIVAL(pdata,0,len);
5183 *fixed_portion = 8;
5184 break;
5187 case SMB_QUERY_FILE_NAME_INFO:
5190 this must be *exactly* right for ACLs on mapped drives to work
5192 status = srvstr_push(dstart, flags2,
5193 pdata+4, dos_fname,
5194 PTR_DIFF(dend, pdata+4),
5195 STR_UNICODE, &len);
5196 if (!NT_STATUS_IS_OK(status)) {
5197 return status;
5199 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5200 data_size = 4 + len;
5201 SIVAL(pdata,0,len);
5202 break;
5205 case SMB_FILE_ALLOCATION_INFORMATION:
5206 case SMB_QUERY_FILE_ALLOCATION_INFO:
5207 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5208 data_size = 8;
5209 SOFF_T(pdata,0,allocation_size);
5210 break;
5212 case SMB_FILE_END_OF_FILE_INFORMATION:
5213 case SMB_QUERY_FILE_END_OF_FILEINFO:
5214 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5215 data_size = 8;
5216 SOFF_T(pdata,0,file_size);
5217 break;
5219 case SMB_QUERY_FILE_ALL_INFO:
5220 case SMB_FILE_ALL_INFORMATION:
5222 unsigned int ea_size =
5223 estimate_ea_size(conn, fsp, smb_fname);
5224 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5225 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5226 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5227 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5228 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5229 SIVAL(pdata,32,mode);
5230 SIVAL(pdata,36,0); /* padding. */
5231 pdata += 40;
5232 SOFF_T(pdata,0,allocation_size);
5233 SOFF_T(pdata,8,file_size);
5234 SIVAL(pdata,16,nlink);
5235 SCVAL(pdata,20,delete_pending);
5236 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5237 SSVAL(pdata,22,0);
5238 pdata += 24;
5239 SIVAL(pdata,0,ea_size);
5240 pdata += 4; /* EA info */
5241 status = srvstr_push(dstart, flags2,
5242 pdata+4, dos_fname,
5243 PTR_DIFF(dend, pdata+4),
5244 STR_UNICODE, &len);
5245 if (!NT_STATUS_IS_OK(status)) {
5246 return status;
5248 SIVAL(pdata,0,len);
5249 pdata += 4 + len;
5250 data_size = PTR_DIFF(pdata,(*ppdata));
5251 *fixed_portion = 10;
5252 break;
5255 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5257 unsigned int ea_size =
5258 estimate_ea_size(conn, fsp, smb_fname);
5259 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5260 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5261 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5262 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5263 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5264 SIVAL(pdata, 0x20, mode);
5265 SIVAL(pdata, 0x24, 0); /* padding. */
5266 SBVAL(pdata, 0x28, allocation_size);
5267 SBVAL(pdata, 0x30, file_size);
5268 SIVAL(pdata, 0x38, nlink);
5269 SCVAL(pdata, 0x3C, delete_pending);
5270 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5271 SSVAL(pdata, 0x3E, 0); /* padding */
5272 SBVAL(pdata, 0x40, file_index);
5273 SIVAL(pdata, 0x48, ea_size);
5274 SIVAL(pdata, 0x4C, access_mask);
5275 SBVAL(pdata, 0x50, pos);
5276 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5277 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5279 pdata += 0x60;
5281 status = srvstr_push(dstart, flags2,
5282 pdata+4, dos_fname,
5283 PTR_DIFF(dend, pdata+4),
5284 STR_UNICODE, &len);
5285 if (!NT_STATUS_IS_OK(status)) {
5286 return status;
5288 SIVAL(pdata,0,len);
5289 pdata += 4 + len;
5290 data_size = PTR_DIFF(pdata,(*ppdata));
5291 *fixed_portion = 104;
5292 break;
5294 case SMB_FILE_INTERNAL_INFORMATION:
5296 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5297 SBVAL(pdata, 0, file_index);
5298 data_size = 8;
5299 *fixed_portion = 8;
5300 break;
5302 case SMB_FILE_ACCESS_INFORMATION:
5303 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5304 SIVAL(pdata, 0, access_mask);
5305 data_size = 4;
5306 *fixed_portion = 4;
5307 break;
5309 case SMB_FILE_NAME_INFORMATION:
5310 /* Pathname with leading '\'. */
5312 size_t byte_len;
5313 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5314 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5315 SIVAL(pdata,0,byte_len);
5316 data_size = 4 + byte_len;
5317 break;
5320 case SMB_FILE_DISPOSITION_INFORMATION:
5321 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5322 data_size = 1;
5323 SCVAL(pdata,0,delete_pending);
5324 *fixed_portion = 1;
5325 break;
5327 case SMB_FILE_POSITION_INFORMATION:
5328 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5329 data_size = 8;
5330 SOFF_T(pdata,0,pos);
5331 *fixed_portion = 8;
5332 break;
5334 case SMB_FILE_MODE_INFORMATION:
5335 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5336 SIVAL(pdata,0,mode);
5337 data_size = 4;
5338 *fixed_portion = 4;
5339 break;
5341 case SMB_FILE_ALIGNMENT_INFORMATION:
5342 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5343 SIVAL(pdata,0,0); /* No alignment needed. */
5344 data_size = 4;
5345 *fixed_portion = 4;
5346 break;
5349 * NT4 server just returns "invalid query" to this - if we try
5350 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5351 * want this. JRA.
5353 /* The first statement above is false - verified using Thursby
5354 * client against NT4 -- gcolley.
5356 case SMB_QUERY_FILE_STREAM_INFO:
5357 case SMB_FILE_STREAM_INFORMATION: {
5358 unsigned int num_streams = 0;
5359 struct stream_struct *streams = NULL;
5361 DEBUG(10,("smbd_do_qfilepathinfo: "
5362 "SMB_FILE_STREAM_INFORMATION\n"));
5364 if (is_ntfs_stream_smb_fname(smb_fname)) {
5365 return NT_STATUS_INVALID_PARAMETER;
5368 status = vfs_streaminfo(conn,
5369 fsp,
5370 smb_fname,
5371 talloc_tos(),
5372 &num_streams,
5373 &streams);
5375 if (!NT_STATUS_IS_OK(status)) {
5376 DEBUG(10, ("could not get stream info: %s\n",
5377 nt_errstr(status)));
5378 return status;
5381 status = marshall_stream_info(num_streams, streams,
5382 pdata, max_data_bytes,
5383 &data_size);
5385 if (!NT_STATUS_IS_OK(status)) {
5386 DEBUG(10, ("marshall_stream_info failed: %s\n",
5387 nt_errstr(status)));
5388 TALLOC_FREE(streams);
5389 return status;
5392 TALLOC_FREE(streams);
5394 *fixed_portion = 32;
5396 break;
5398 case SMB_QUERY_COMPRESSION_INFO:
5399 case SMB_FILE_COMPRESSION_INFORMATION:
5400 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5401 SOFF_T(pdata,0,file_size);
5402 SIVAL(pdata,8,0); /* ??? */
5403 SIVAL(pdata,12,0); /* ??? */
5404 data_size = 16;
5405 *fixed_portion = 16;
5406 break;
5408 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5409 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5410 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5411 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5412 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5413 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5414 SOFF_T(pdata,32,allocation_size);
5415 SOFF_T(pdata,40,file_size);
5416 SIVAL(pdata,48,mode);
5417 SIVAL(pdata,52,0); /* ??? */
5418 data_size = 56;
5419 *fixed_portion = 56;
5420 break;
5422 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5423 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5424 SIVAL(pdata,0,mode);
5425 SIVAL(pdata,4,0);
5426 data_size = 8;
5427 *fixed_portion = 8;
5428 break;
5431 * CIFS UNIX Extensions.
5434 case SMB_QUERY_FILE_UNIX_BASIC:
5436 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5437 data_size = PTR_DIFF(pdata,(*ppdata));
5439 DEBUG(4,("smbd_do_qfilepathinfo: "
5440 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5441 dump_data(4, (uint8_t *)(*ppdata), data_size);
5443 break;
5445 case SMB_QUERY_FILE_UNIX_INFO2:
5447 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5448 data_size = PTR_DIFF(pdata,(*ppdata));
5451 int i;
5452 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5454 for (i=0; i<100; i++)
5455 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5456 DEBUG(4,("\n"));
5459 break;
5461 case SMB_QUERY_FILE_UNIX_LINK:
5463 int link_len = 0;
5464 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5466 if (!buffer) {
5467 return NT_STATUS_NO_MEMORY;
5470 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5471 #ifdef S_ISLNK
5472 if(!S_ISLNK(psbuf->st_ex_mode)) {
5473 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5475 #else
5476 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5477 #endif
5478 link_len = SMB_VFS_READLINK(conn,
5479 smb_fname,
5480 buffer, PATH_MAX);
5481 if (link_len == -1) {
5482 return map_nt_error_from_unix(errno);
5484 buffer[link_len] = 0;
5485 status = srvstr_push(dstart, flags2,
5486 pdata, buffer,
5487 PTR_DIFF(dend, pdata),
5488 STR_TERMINATE, &len);
5489 if (!NT_STATUS_IS_OK(status)) {
5490 return status;
5492 pdata += len;
5493 data_size = PTR_DIFF(pdata,(*ppdata));
5495 break;
5498 #if defined(HAVE_POSIX_ACLS)
5499 case SMB_QUERY_POSIX_ACL:
5501 SMB_ACL_T file_acl = NULL;
5502 SMB_ACL_T def_acl = NULL;
5503 uint16_t num_file_acls = 0;
5504 uint16_t num_def_acls = 0;
5506 status = refuse_symlink(conn,
5507 fsp,
5508 smb_fname);
5509 if (!NT_STATUS_IS_OK(status)) {
5510 return status;
5513 if (fsp && fsp->fh->fd != -1) {
5514 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5515 talloc_tos());
5516 } else {
5517 file_acl =
5518 SMB_VFS_SYS_ACL_GET_FILE(conn,
5519 smb_fname,
5520 SMB_ACL_TYPE_ACCESS,
5521 talloc_tos());
5524 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5525 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5526 "not implemented on "
5527 "filesystem containing %s\n",
5528 smb_fname->base_name));
5529 return NT_STATUS_NOT_IMPLEMENTED;
5532 if (S_ISDIR(psbuf->st_ex_mode)) {
5533 if (fsp && fsp->is_directory) {
5534 def_acl =
5535 SMB_VFS_SYS_ACL_GET_FILE(
5536 conn,
5537 fsp->fsp_name,
5538 SMB_ACL_TYPE_DEFAULT,
5539 talloc_tos());
5540 } else {
5541 def_acl =
5542 SMB_VFS_SYS_ACL_GET_FILE(
5543 conn,
5544 smb_fname,
5545 SMB_ACL_TYPE_DEFAULT,
5546 talloc_tos());
5548 def_acl = free_empty_sys_acl(conn, def_acl);
5551 num_file_acls = count_acl_entries(conn, file_acl);
5552 num_def_acls = count_acl_entries(conn, def_acl);
5554 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5555 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5556 data_size,
5557 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5558 SMB_POSIX_ACL_HEADER_SIZE) ));
5559 if (file_acl) {
5560 TALLOC_FREE(file_acl);
5562 if (def_acl) {
5563 TALLOC_FREE(def_acl);
5565 return NT_STATUS_BUFFER_TOO_SMALL;
5568 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5569 SSVAL(pdata,2,num_file_acls);
5570 SSVAL(pdata,4,num_def_acls);
5571 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5572 if (file_acl) {
5573 TALLOC_FREE(file_acl);
5575 if (def_acl) {
5576 TALLOC_FREE(def_acl);
5578 return NT_STATUS_INTERNAL_ERROR;
5580 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5581 if (file_acl) {
5582 TALLOC_FREE(file_acl);
5584 if (def_acl) {
5585 TALLOC_FREE(def_acl);
5587 return NT_STATUS_INTERNAL_ERROR;
5590 if (file_acl) {
5591 TALLOC_FREE(file_acl);
5593 if (def_acl) {
5594 TALLOC_FREE(def_acl);
5596 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5597 break;
5599 #endif
5602 case SMB_QUERY_POSIX_LOCK:
5604 uint64_t count;
5605 uint64_t offset;
5606 uint64_t smblctx;
5607 enum brl_type lock_type;
5609 /* We need an open file with a real fd for this. */
5610 if (!fsp || fsp->fh->fd == -1) {
5611 return NT_STATUS_INVALID_LEVEL;
5614 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5615 return NT_STATUS_INVALID_PARAMETER;
5618 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5619 case POSIX_LOCK_TYPE_READ:
5620 lock_type = READ_LOCK;
5621 break;
5622 case POSIX_LOCK_TYPE_WRITE:
5623 lock_type = WRITE_LOCK;
5624 break;
5625 case POSIX_LOCK_TYPE_UNLOCK:
5626 default:
5627 /* There's no point in asking for an unlock... */
5628 return NT_STATUS_INVALID_PARAMETER;
5631 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5632 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5633 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5635 status = query_lock(fsp,
5636 &smblctx,
5637 &count,
5638 &offset,
5639 &lock_type,
5640 POSIX_LOCK);
5642 if (ERROR_WAS_LOCK_DENIED(status)) {
5643 /* Here we need to report who has it locked... */
5644 data_size = POSIX_LOCK_DATA_SIZE;
5646 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5647 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5648 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5649 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5650 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5652 } else if (NT_STATUS_IS_OK(status)) {
5653 /* For success we just return a copy of what we sent
5654 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5655 data_size = POSIX_LOCK_DATA_SIZE;
5656 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5657 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5658 } else {
5659 return status;
5661 break;
5664 default:
5665 return NT_STATUS_INVALID_LEVEL;
5668 *pdata_size = data_size;
5669 return NT_STATUS_OK;
5672 /****************************************************************************
5673 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5674 file name or file id).
5675 ****************************************************************************/
5677 static void call_trans2qfilepathinfo(connection_struct *conn,
5678 struct smb_request *req,
5679 unsigned int tran_call,
5680 char **pparams, int total_params,
5681 char **ppdata, int total_data,
5682 unsigned int max_data_bytes)
5684 char *params = *pparams;
5685 char *pdata = *ppdata;
5686 uint16_t info_level;
5687 unsigned int data_size = 0;
5688 unsigned int param_size = 2;
5689 struct smb_filename *smb_fname = NULL;
5690 bool delete_pending = False;
5691 struct timespec write_time_ts;
5692 files_struct *fsp = NULL;
5693 struct file_id fileid;
5694 struct ea_list *ea_list = NULL;
5695 int lock_data_count = 0;
5696 char *lock_data = NULL;
5697 size_t fixed_portion;
5698 NTSTATUS status = NT_STATUS_OK;
5700 if (!params) {
5701 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5702 return;
5705 ZERO_STRUCT(write_time_ts);
5707 if (tran_call == TRANSACT2_QFILEINFO) {
5708 if (total_params < 4) {
5709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5710 return;
5713 if (IS_IPC(conn)) {
5714 call_trans2qpipeinfo(conn, req, tran_call,
5715 pparams, total_params,
5716 ppdata, total_data,
5717 max_data_bytes);
5718 return;
5721 fsp = file_fsp(req, SVAL(params,0));
5722 info_level = SVAL(params,2);
5724 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5726 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5727 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5728 return;
5731 /* Initial check for valid fsp ptr. */
5732 if (!check_fsp_open(conn, req, fsp)) {
5733 return;
5736 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5737 if (smb_fname == NULL) {
5738 reply_nterror(req, NT_STATUS_NO_MEMORY);
5739 return;
5742 if(fsp->fake_file_handle) {
5744 * This is actually for the QUOTA_FAKE_FILE --metze
5747 /* We know this name is ok, it's already passed the checks. */
5749 } else if(fsp->fh->fd == -1) {
5751 * This is actually a QFILEINFO on a directory
5752 * handle (returned from an NT SMB). NT5.0 seems
5753 * to do this call. JRA.
5756 if (INFO_LEVEL_IS_UNIX(info_level)) {
5757 /* Always do lstat for UNIX calls. */
5758 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5759 DEBUG(3,("call_trans2qfilepathinfo: "
5760 "SMB_VFS_LSTAT of %s failed "
5761 "(%s)\n",
5762 smb_fname_str_dbg(smb_fname),
5763 strerror(errno)));
5764 reply_nterror(req,
5765 map_nt_error_from_unix(errno));
5766 return;
5768 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5769 DEBUG(3,("call_trans2qfilepathinfo: "
5770 "SMB_VFS_STAT of %s failed (%s)\n",
5771 smb_fname_str_dbg(smb_fname),
5772 strerror(errno)));
5773 reply_nterror(req,
5774 map_nt_error_from_unix(errno));
5775 return;
5778 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5779 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5780 } else {
5782 * Original code - this is an open file.
5784 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5785 DEBUG(3, ("fstat of %s failed (%s)\n",
5786 fsp_fnum_dbg(fsp), strerror(errno)));
5787 reply_nterror(req,
5788 map_nt_error_from_unix(errno));
5789 return;
5791 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5792 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5795 } else {
5796 uint32_t name_hash;
5797 char *fname = NULL;
5798 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
5800 /* qpathinfo */
5801 if (total_params < 7) {
5802 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5803 return;
5806 info_level = SVAL(params,0);
5808 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5810 if (INFO_LEVEL_IS_UNIX(info_level)) {
5811 if (!lp_unix_extensions()) {
5812 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5813 return;
5815 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5816 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5817 info_level == SMB_QUERY_FILE_UNIX_LINK ||
5818 req->posix_pathnames) {
5819 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5823 if (req->posix_pathnames) {
5824 srvstr_get_path_posix(req,
5825 params,
5826 req->flags2,
5827 &fname,
5828 &params[6],
5829 total_params - 6,
5830 STR_TERMINATE,
5831 &status);
5832 } else {
5833 srvstr_get_path(req,
5834 params,
5835 req->flags2,
5836 &fname,
5837 &params[6],
5838 total_params - 6,
5839 STR_TERMINATE,
5840 &status);
5842 if (!NT_STATUS_IS_OK(status)) {
5843 reply_nterror(req, status);
5844 return;
5847 status = filename_convert(req,
5848 conn,
5849 fname,
5850 ucf_flags,
5851 NULL,
5852 &smb_fname);
5853 if (!NT_STATUS_IS_OK(status)) {
5854 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5855 reply_botherror(req,
5856 NT_STATUS_PATH_NOT_COVERED,
5857 ERRSRV, ERRbadpath);
5858 return;
5860 reply_nterror(req, status);
5861 return;
5864 /* If this is a stream, check if there is a delete_pending. */
5865 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5866 && is_ntfs_stream_smb_fname(smb_fname)) {
5867 struct smb_filename *smb_fname_base;
5869 /* Create an smb_filename with stream_name == NULL. */
5870 smb_fname_base = synthetic_smb_fname(
5871 talloc_tos(),
5872 smb_fname->base_name,
5873 NULL,
5874 NULL,
5875 smb_fname->flags);
5876 if (smb_fname_base == NULL) {
5877 reply_nterror(req, NT_STATUS_NO_MEMORY);
5878 return;
5881 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5882 /* Always do lstat for UNIX calls. */
5883 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5884 DEBUG(3,("call_trans2qfilepathinfo: "
5885 "SMB_VFS_LSTAT of %s failed "
5886 "(%s)\n",
5887 smb_fname_str_dbg(smb_fname_base),
5888 strerror(errno)));
5889 TALLOC_FREE(smb_fname_base);
5890 reply_nterror(req,
5891 map_nt_error_from_unix(errno));
5892 return;
5894 } else {
5895 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5896 DEBUG(3,("call_trans2qfilepathinfo: "
5897 "fileinfo of %s failed "
5898 "(%s)\n",
5899 smb_fname_str_dbg(smb_fname_base),
5900 strerror(errno)));
5901 TALLOC_FREE(smb_fname_base);
5902 reply_nterror(req,
5903 map_nt_error_from_unix(errno));
5904 return;
5908 status = file_name_hash(conn,
5909 smb_fname_str_dbg(smb_fname_base),
5910 &name_hash);
5911 if (!NT_STATUS_IS_OK(status)) {
5912 TALLOC_FREE(smb_fname_base);
5913 reply_nterror(req, status);
5914 return;
5917 fileid = vfs_file_id_from_sbuf(conn,
5918 &smb_fname_base->st);
5919 TALLOC_FREE(smb_fname_base);
5920 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5921 if (delete_pending) {
5922 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5923 return;
5927 if (INFO_LEVEL_IS_UNIX(info_level) || req->posix_pathnames) {
5928 /* Always do lstat for UNIX calls. */
5929 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5930 DEBUG(3,("call_trans2qfilepathinfo: "
5931 "SMB_VFS_LSTAT of %s failed (%s)\n",
5932 smb_fname_str_dbg(smb_fname),
5933 strerror(errno)));
5934 reply_nterror(req,
5935 map_nt_error_from_unix(errno));
5936 return;
5939 } else {
5940 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5941 DEBUG(3,("call_trans2qfilepathinfo: "
5942 "SMB_VFS_STAT of %s failed (%s)\n",
5943 smb_fname_str_dbg(smb_fname),
5944 strerror(errno)));
5945 reply_nterror(req,
5946 map_nt_error_from_unix(errno));
5947 return;
5951 status = file_name_hash(conn,
5952 smb_fname_str_dbg(smb_fname),
5953 &name_hash);
5954 if (!NT_STATUS_IS_OK(status)) {
5955 reply_nterror(req, status);
5956 return;
5959 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5960 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5961 if (delete_pending) {
5962 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5963 return;
5967 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5968 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5969 fsp_fnum_dbg(fsp),
5970 info_level,tran_call,total_data));
5972 /* Pull out any data sent here before we realloc. */
5973 switch (info_level) {
5974 case SMB_INFO_QUERY_EAS_FROM_LIST:
5976 /* Pull any EA list from the data portion. */
5977 uint32_t ea_size;
5979 if (total_data < 4) {
5980 reply_nterror(
5981 req, NT_STATUS_INVALID_PARAMETER);
5982 return;
5984 ea_size = IVAL(pdata,0);
5986 if (total_data > 0 && ea_size != total_data) {
5987 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5988 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5989 reply_nterror(
5990 req, NT_STATUS_INVALID_PARAMETER);
5991 return;
5994 if (!lp_ea_support(SNUM(conn))) {
5995 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5996 return;
5999 /* Pull out the list of names. */
6000 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
6001 if (!ea_list) {
6002 reply_nterror(
6003 req, NT_STATUS_INVALID_PARAMETER);
6004 return;
6006 break;
6009 case SMB_QUERY_POSIX_LOCK:
6011 if (fsp == NULL || fsp->fh->fd == -1) {
6012 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
6013 return;
6016 if (total_data != POSIX_LOCK_DATA_SIZE) {
6017 reply_nterror(
6018 req, NT_STATUS_INVALID_PARAMETER);
6019 return;
6022 /* Copy the lock range data. */
6023 lock_data = (char *)talloc_memdup(
6024 req, pdata, total_data);
6025 if (!lock_data) {
6026 reply_nterror(req, NT_STATUS_NO_MEMORY);
6027 return;
6029 lock_data_count = total_data;
6031 default:
6032 break;
6035 *pparams = (char *)SMB_REALLOC(*pparams,2);
6036 if (*pparams == NULL) {
6037 reply_nterror(req, NT_STATUS_NO_MEMORY);
6038 return;
6040 params = *pparams;
6041 SSVAL(params,0,0);
6044 * draft-leach-cifs-v1-spec-02.txt
6045 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
6046 * says:
6048 * The requested information is placed in the Data portion of the
6049 * transaction response. For the information levels greater than 0x100,
6050 * the transaction response has 1 parameter word which should be
6051 * ignored by the client.
6053 * However Windows only follows this rule for the IS_NAME_VALID call.
6055 switch (info_level) {
6056 case SMB_INFO_IS_NAME_VALID:
6057 param_size = 0;
6058 break;
6061 if ((info_level & 0xFF00) == 0xFF00) {
6063 * We use levels that start with 0xFF00
6064 * internally to represent SMB2 specific levels
6066 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6067 return;
6070 status = smbd_do_qfilepathinfo(conn, req, info_level,
6071 fsp, smb_fname,
6072 delete_pending, write_time_ts,
6073 ea_list,
6074 lock_data_count, lock_data,
6075 req->flags2, max_data_bytes,
6076 &fixed_portion,
6077 ppdata, &data_size);
6078 if (!NT_STATUS_IS_OK(status)) {
6079 reply_nterror(req, status);
6080 return;
6082 if (fixed_portion > max_data_bytes) {
6083 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6084 return;
6087 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6088 max_data_bytes);
6090 return;
6093 /****************************************************************************
6094 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6095 code.
6096 ****************************************************************************/
6098 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6099 connection_struct *conn,
6100 struct smb_request *req,
6101 bool overwrite_if_exists,
6102 const struct smb_filename *smb_fname_old,
6103 struct smb_filename *smb_fname_new)
6105 NTSTATUS status = NT_STATUS_OK;
6107 /* source must already exist. */
6108 if (!VALID_STAT(smb_fname_old->st)) {
6109 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6112 if (VALID_STAT(smb_fname_new->st)) {
6113 if (overwrite_if_exists) {
6114 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6115 return NT_STATUS_FILE_IS_A_DIRECTORY;
6117 status = unlink_internals(conn,
6118 req,
6119 FILE_ATTRIBUTE_NORMAL,
6120 smb_fname_new,
6121 false);
6122 if (!NT_STATUS_IS_OK(status)) {
6123 return status;
6125 } else {
6126 /* Disallow if newname already exists. */
6127 return NT_STATUS_OBJECT_NAME_COLLISION;
6131 /* No links from a directory. */
6132 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6133 return NT_STATUS_FILE_IS_A_DIRECTORY;
6136 /* Setting a hardlink to/from a stream isn't currently supported. */
6137 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6138 is_ntfs_stream_smb_fname(smb_fname_new)) {
6139 return NT_STATUS_INVALID_PARAMETER;
6142 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6143 smb_fname_old->base_name, smb_fname_new->base_name));
6145 if (SMB_VFS_LINK(conn, smb_fname_old, smb_fname_new) != 0) {
6146 status = map_nt_error_from_unix(errno);
6147 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6148 nt_errstr(status), smb_fname_old->base_name,
6149 smb_fname_new->base_name));
6151 return status;
6154 /****************************************************************************
6155 Deal with setting the time from any of the setfilepathinfo functions.
6156 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6157 calling this function.
6158 ****************************************************************************/
6160 NTSTATUS smb_set_file_time(connection_struct *conn,
6161 files_struct *fsp,
6162 const struct smb_filename *smb_fname,
6163 struct smb_file_time *ft,
6164 bool setting_write_time)
6166 struct smb_filename smb_fname_base;
6167 uint32_t action =
6168 FILE_NOTIFY_CHANGE_LAST_ACCESS
6169 |FILE_NOTIFY_CHANGE_LAST_WRITE
6170 |FILE_NOTIFY_CHANGE_CREATION;
6172 if (!VALID_STAT(smb_fname->st)) {
6173 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6176 /* get some defaults (no modifications) if any info is zero or -1. */
6177 if (null_timespec(ft->create_time)) {
6178 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6181 if (null_timespec(ft->atime)) {
6182 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6185 if (null_timespec(ft->mtime)) {
6186 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6189 if (!setting_write_time) {
6190 /* ft->mtime comes from change time, not write time. */
6191 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6194 /* Ensure the resolution is the correct for
6195 * what we can store on this filesystem. */
6197 round_timespec(conn->ts_res, &ft->create_time);
6198 round_timespec(conn->ts_res, &ft->ctime);
6199 round_timespec(conn->ts_res, &ft->atime);
6200 round_timespec(conn->ts_res, &ft->mtime);
6202 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6203 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6204 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6205 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6206 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6207 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6208 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6209 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6211 if (setting_write_time) {
6213 * This was a Windows setfileinfo on an open file.
6214 * NT does this a lot. We also need to
6215 * set the time here, as it can be read by
6216 * FindFirst/FindNext and with the patch for bug #2045
6217 * in smbd/fileio.c it ensures that this timestamp is
6218 * kept sticky even after a write. We save the request
6219 * away and will set it on file close and after a write. JRA.
6222 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6223 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6225 if (fsp != NULL) {
6226 if (fsp->base_fsp) {
6227 set_sticky_write_time_fsp(fsp->base_fsp,
6228 ft->mtime);
6229 } else {
6230 set_sticky_write_time_fsp(fsp, ft->mtime);
6232 } else {
6233 set_sticky_write_time_path(
6234 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6235 ft->mtime);
6239 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6241 /* Always call ntimes on the base, even if a stream was passed in. */
6242 smb_fname_base = *smb_fname;
6243 smb_fname_base.stream_name = NULL;
6245 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6246 return map_nt_error_from_unix(errno);
6249 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6250 smb_fname->base_name);
6251 return NT_STATUS_OK;
6254 /****************************************************************************
6255 Deal with setting the dosmode from any of the setfilepathinfo functions.
6256 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6257 done before calling this function.
6258 ****************************************************************************/
6260 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6261 const struct smb_filename *smb_fname,
6262 uint32_t dosmode)
6264 struct smb_filename *smb_fname_base;
6265 NTSTATUS status;
6267 if (!VALID_STAT(smb_fname->st)) {
6268 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6271 /* Always operate on the base_name, even if a stream was passed in. */
6272 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6273 smb_fname->base_name,
6274 NULL,
6275 &smb_fname->st,
6276 smb_fname->flags);
6277 if (smb_fname_base == NULL) {
6278 return NT_STATUS_NO_MEMORY;
6281 if (dosmode) {
6282 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6283 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6284 } else {
6285 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6289 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6291 /* check the mode isn't different, before changing it */
6292 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6293 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6294 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6295 (unsigned int)dosmode));
6297 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6298 false)) {
6299 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6300 "%s failed (%s)\n",
6301 smb_fname_str_dbg(smb_fname_base),
6302 strerror(errno)));
6303 status = map_nt_error_from_unix(errno);
6304 goto out;
6307 status = NT_STATUS_OK;
6308 out:
6309 TALLOC_FREE(smb_fname_base);
6310 return status;
6313 /****************************************************************************
6314 Deal with setting the size from any of the setfilepathinfo functions.
6315 ****************************************************************************/
6317 static NTSTATUS smb_set_file_size(connection_struct *conn,
6318 struct smb_request *req,
6319 files_struct *fsp,
6320 const struct smb_filename *smb_fname,
6321 const SMB_STRUCT_STAT *psbuf,
6322 off_t size,
6323 bool fail_after_createfile)
6325 NTSTATUS status = NT_STATUS_OK;
6326 struct smb_filename *smb_fname_tmp = NULL;
6327 files_struct *new_fsp = NULL;
6329 if (!VALID_STAT(*psbuf)) {
6330 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6333 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6335 if (size == get_file_size_stat(psbuf)) {
6336 return NT_STATUS_OK;
6339 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6340 smb_fname_str_dbg(smb_fname), (double)size));
6342 if (fsp && fsp->fh->fd != -1) {
6343 /* Handle based call. */
6344 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6345 return NT_STATUS_ACCESS_DENIED;
6348 if (vfs_set_filelen(fsp, size) == -1) {
6349 return map_nt_error_from_unix(errno);
6351 trigger_write_time_update_immediate(fsp);
6352 return NT_STATUS_OK;
6355 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6356 if (smb_fname_tmp == NULL) {
6357 return NT_STATUS_NO_MEMORY;
6360 smb_fname_tmp->st = *psbuf;
6362 status = SMB_VFS_CREATE_FILE(
6363 conn, /* conn */
6364 req, /* req */
6365 0, /* root_dir_fid */
6366 smb_fname_tmp, /* fname */
6367 FILE_WRITE_DATA, /* access_mask */
6368 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6369 FILE_SHARE_DELETE),
6370 FILE_OPEN, /* create_disposition*/
6371 0, /* create_options */
6372 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6373 0, /* oplock_request */
6374 NULL, /* lease */
6375 0, /* allocation_size */
6376 0, /* private_flags */
6377 NULL, /* sd */
6378 NULL, /* ea_list */
6379 &new_fsp, /* result */
6380 NULL, /* pinfo */
6381 NULL, NULL); /* create context */
6383 TALLOC_FREE(smb_fname_tmp);
6385 if (!NT_STATUS_IS_OK(status)) {
6386 /* NB. We check for open_was_deferred in the caller. */
6387 return status;
6390 /* See RAW-SFILEINFO-END-OF-FILE */
6391 if (fail_after_createfile) {
6392 close_file(req, new_fsp,NORMAL_CLOSE);
6393 return NT_STATUS_INVALID_LEVEL;
6396 if (vfs_set_filelen(new_fsp, size) == -1) {
6397 status = map_nt_error_from_unix(errno);
6398 close_file(req, new_fsp,NORMAL_CLOSE);
6399 return status;
6402 trigger_write_time_update_immediate(new_fsp);
6403 close_file(req, new_fsp,NORMAL_CLOSE);
6404 return NT_STATUS_OK;
6407 /****************************************************************************
6408 Deal with SMB_INFO_SET_EA.
6409 ****************************************************************************/
6411 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6412 const char *pdata,
6413 int total_data,
6414 files_struct *fsp,
6415 const struct smb_filename *smb_fname)
6417 struct ea_list *ea_list = NULL;
6418 TALLOC_CTX *ctx = NULL;
6419 NTSTATUS status = NT_STATUS_OK;
6421 if (total_data < 10) {
6423 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6424 length. They seem to have no effect. Bug #3212. JRA */
6426 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6427 /* We're done. We only get EA info in this call. */
6428 return NT_STATUS_OK;
6431 return NT_STATUS_INVALID_PARAMETER;
6434 if (IVAL(pdata,0) > total_data) {
6435 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6436 IVAL(pdata,0), (unsigned int)total_data));
6437 return NT_STATUS_INVALID_PARAMETER;
6440 ctx = talloc_tos();
6441 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6442 if (!ea_list) {
6443 return NT_STATUS_INVALID_PARAMETER;
6446 status = set_ea(conn, fsp, smb_fname, ea_list);
6448 return status;
6451 /****************************************************************************
6452 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6453 ****************************************************************************/
6455 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6456 const char *pdata,
6457 int total_data,
6458 files_struct *fsp)
6460 struct ea_list *ea_list = NULL;
6461 NTSTATUS status;
6463 if (!fsp) {
6464 return NT_STATUS_INVALID_HANDLE;
6467 if (!lp_ea_support(SNUM(conn))) {
6468 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6469 "EA's not supported.\n",
6470 (unsigned int)total_data));
6471 return NT_STATUS_EAS_NOT_SUPPORTED;
6474 if (total_data < 10) {
6475 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6476 "too small.\n",
6477 (unsigned int)total_data));
6478 return NT_STATUS_INVALID_PARAMETER;
6481 ea_list = read_nttrans_ea_list(talloc_tos(),
6482 pdata,
6483 total_data);
6485 if (!ea_list) {
6486 return NT_STATUS_INVALID_PARAMETER;
6489 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6491 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6492 smb_fname_str_dbg(fsp->fsp_name),
6493 nt_errstr(status) ));
6495 return status;
6499 /****************************************************************************
6500 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6501 ****************************************************************************/
6503 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6504 const char *pdata,
6505 int total_data,
6506 files_struct *fsp,
6507 struct smb_filename *smb_fname)
6509 NTSTATUS status = NT_STATUS_OK;
6510 bool delete_on_close;
6511 uint32_t dosmode = 0;
6513 if (total_data < 1) {
6514 return NT_STATUS_INVALID_PARAMETER;
6517 if (fsp == NULL) {
6518 return NT_STATUS_INVALID_HANDLE;
6521 delete_on_close = (CVAL(pdata,0) ? True : False);
6522 dosmode = dos_mode(conn, smb_fname);
6524 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6525 "delete_on_close = %u\n",
6526 smb_fname_str_dbg(smb_fname),
6527 (unsigned int)dosmode,
6528 (unsigned int)delete_on_close ));
6530 if (delete_on_close) {
6531 status = can_set_delete_on_close(fsp, dosmode);
6532 if (!NT_STATUS_IS_OK(status)) {
6533 return status;
6537 /* The set is across all open files on this dev/inode pair. */
6538 if (!set_delete_on_close(fsp, delete_on_close,
6539 conn->session_info->security_token,
6540 conn->session_info->unix_token)) {
6541 return NT_STATUS_ACCESS_DENIED;
6543 return NT_STATUS_OK;
6546 /****************************************************************************
6547 Deal with SMB_FILE_POSITION_INFORMATION.
6548 ****************************************************************************/
6550 static NTSTATUS smb_file_position_information(connection_struct *conn,
6551 const char *pdata,
6552 int total_data,
6553 files_struct *fsp)
6555 uint64_t position_information;
6557 if (total_data < 8) {
6558 return NT_STATUS_INVALID_PARAMETER;
6561 if (fsp == NULL) {
6562 /* Ignore on pathname based set. */
6563 return NT_STATUS_OK;
6566 position_information = (uint64_t)IVAL(pdata,0);
6567 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6569 DEBUG(10,("smb_file_position_information: Set file position "
6570 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6571 (double)position_information));
6572 fsp->fh->position_information = position_information;
6573 return NT_STATUS_OK;
6576 /****************************************************************************
6577 Deal with SMB_FILE_MODE_INFORMATION.
6578 ****************************************************************************/
6580 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6581 const char *pdata,
6582 int total_data)
6584 uint32_t mode;
6586 if (total_data < 4) {
6587 return NT_STATUS_INVALID_PARAMETER;
6589 mode = IVAL(pdata,0);
6590 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6591 return NT_STATUS_INVALID_PARAMETER;
6593 return NT_STATUS_OK;
6596 /****************************************************************************
6597 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6598 ****************************************************************************/
6600 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6601 struct smb_request *req,
6602 const char *pdata,
6603 int total_data,
6604 const struct smb_filename *new_smb_fname)
6606 char *link_target = NULL;
6607 TALLOC_CTX *ctx = talloc_tos();
6609 /* Set a symbolic link. */
6610 /* Don't allow this if follow links is false. */
6612 if (total_data == 0) {
6613 return NT_STATUS_INVALID_PARAMETER;
6616 if (!lp_follow_symlinks(SNUM(conn))) {
6617 return NT_STATUS_ACCESS_DENIED;
6620 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6621 total_data, STR_TERMINATE);
6623 if (!link_target) {
6624 return NT_STATUS_INVALID_PARAMETER;
6627 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6628 new_smb_fname->base_name, link_target ));
6630 if (SMB_VFS_SYMLINK(conn,link_target,new_smb_fname) != 0) {
6631 return map_nt_error_from_unix(errno);
6634 return NT_STATUS_OK;
6637 /****************************************************************************
6638 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6639 ****************************************************************************/
6641 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6642 struct smb_request *req,
6643 const char *pdata, int total_data,
6644 struct smb_filename *smb_fname_new)
6646 char *oldname = NULL;
6647 struct smb_filename *smb_fname_old = NULL;
6648 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
6649 TALLOC_CTX *ctx = talloc_tos();
6650 NTSTATUS status = NT_STATUS_OK;
6652 /* Set a hard link. */
6653 if (total_data == 0) {
6654 return NT_STATUS_INVALID_PARAMETER;
6657 if (req->posix_pathnames) {
6658 srvstr_get_path_posix(ctx,
6659 pdata,
6660 req->flags2,
6661 &oldname,
6662 pdata,
6663 total_data,
6664 STR_TERMINATE,
6665 &status);
6666 } else {
6667 srvstr_get_path(ctx,
6668 pdata,
6669 req->flags2,
6670 &oldname,
6671 pdata,
6672 total_data,
6673 STR_TERMINATE,
6674 &status);
6676 if (!NT_STATUS_IS_OK(status)) {
6677 return status;
6680 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6681 smb_fname_str_dbg(smb_fname_new), oldname));
6683 status = filename_convert(ctx,
6684 conn,
6685 oldname,
6686 ucf_flags,
6687 NULL,
6688 &smb_fname_old);
6689 if (!NT_STATUS_IS_OK(status)) {
6690 return status;
6693 return hardlink_internals(ctx, conn, req, false,
6694 smb_fname_old, smb_fname_new);
6697 /****************************************************************************
6698 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6699 ****************************************************************************/
6701 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6702 struct smb_request *req,
6703 const char *pdata,
6704 int total_data,
6705 files_struct *fsp,
6706 struct smb_filename *smb_fname_src)
6708 bool overwrite;
6709 uint32_t len;
6710 char *newname = NULL;
6711 struct smb_filename *smb_fname_dst = NULL;
6712 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6713 ucf_flags_from_smb_request(req);
6714 NTSTATUS status = NT_STATUS_OK;
6715 TALLOC_CTX *ctx = talloc_tos();
6717 if (!fsp) {
6718 return NT_STATUS_INVALID_HANDLE;
6721 if (total_data < 20) {
6722 return NT_STATUS_INVALID_PARAMETER;
6725 overwrite = (CVAL(pdata,0) ? True : False);
6726 len = IVAL(pdata,16);
6728 if (len > (total_data - 20) || (len == 0)) {
6729 return NT_STATUS_INVALID_PARAMETER;
6732 if (req->posix_pathnames) {
6733 srvstr_get_path_posix(ctx,
6734 pdata,
6735 req->flags2,
6736 &newname,
6737 &pdata[20],
6738 len,
6739 STR_TERMINATE,
6740 &status);
6741 } else {
6742 srvstr_get_path(ctx,
6743 pdata,
6744 req->flags2,
6745 &newname,
6746 &pdata[20],
6747 len,
6748 STR_TERMINATE,
6749 &status);
6751 if (!NT_STATUS_IS_OK(status)) {
6752 return status;
6755 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6756 newname));
6758 status = filename_convert(ctx,
6759 conn,
6760 newname,
6761 ucf_flags,
6762 NULL,
6763 &smb_fname_dst);
6764 if (!NT_STATUS_IS_OK(status)) {
6765 return status;
6768 if (fsp->base_fsp) {
6769 /* newname must be a stream name. */
6770 if (newname[0] != ':') {
6771 return NT_STATUS_NOT_SUPPORTED;
6774 /* Create an smb_fname to call rename_internals_fsp() with. */
6775 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6776 fsp->base_fsp->fsp_name->base_name,
6777 newname,
6778 NULL,
6779 fsp->base_fsp->fsp_name->flags);
6780 if (smb_fname_dst == NULL) {
6781 status = NT_STATUS_NO_MEMORY;
6782 goto out;
6786 * Set the original last component, since
6787 * rename_internals_fsp() requires it.
6789 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6790 newname);
6791 if (smb_fname_dst->original_lcomp == NULL) {
6792 status = NT_STATUS_NO_MEMORY;
6793 goto out;
6798 DEBUG(10,("smb2_file_rename_information: "
6799 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6800 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6801 smb_fname_str_dbg(smb_fname_dst)));
6802 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6803 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6804 overwrite);
6806 out:
6807 TALLOC_FREE(smb_fname_dst);
6808 return status;
6811 static NTSTATUS smb_file_link_information(connection_struct *conn,
6812 struct smb_request *req,
6813 const char *pdata,
6814 int total_data,
6815 files_struct *fsp,
6816 struct smb_filename *smb_fname_src)
6818 bool overwrite;
6819 uint32_t len;
6820 char *newname = NULL;
6821 struct smb_filename *smb_fname_dst = NULL;
6822 NTSTATUS status = NT_STATUS_OK;
6823 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6824 ucf_flags_from_smb_request(req);
6825 TALLOC_CTX *ctx = talloc_tos();
6827 if (!fsp) {
6828 return NT_STATUS_INVALID_HANDLE;
6831 if (total_data < 20) {
6832 return NT_STATUS_INVALID_PARAMETER;
6835 overwrite = (CVAL(pdata,0) ? true : false);
6836 len = IVAL(pdata,16);
6838 if (len > (total_data - 20) || (len == 0)) {
6839 return NT_STATUS_INVALID_PARAMETER;
6842 if (req->posix_pathnames) {
6843 srvstr_get_path_posix(ctx,
6844 pdata,
6845 req->flags2,
6846 &newname,
6847 &pdata[20],
6848 len,
6849 STR_TERMINATE,
6850 &status);
6851 } else {
6852 srvstr_get_path(ctx,
6853 pdata,
6854 req->flags2,
6855 &newname,
6856 &pdata[20],
6857 len,
6858 STR_TERMINATE,
6859 &status);
6861 if (!NT_STATUS_IS_OK(status)) {
6862 return status;
6865 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6866 newname));
6868 status = filename_convert(ctx,
6869 conn,
6870 newname,
6871 ucf_flags,
6872 NULL,
6873 &smb_fname_dst);
6874 if (!NT_STATUS_IS_OK(status)) {
6875 return status;
6878 if (fsp->base_fsp) {
6879 /* No stream names. */
6880 return NT_STATUS_NOT_SUPPORTED;
6883 DEBUG(10,("smb_file_link_information: "
6884 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6885 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6886 smb_fname_str_dbg(smb_fname_dst)));
6887 status = hardlink_internals(ctx,
6888 conn,
6889 req,
6890 overwrite,
6891 fsp->fsp_name,
6892 smb_fname_dst);
6894 TALLOC_FREE(smb_fname_dst);
6895 return status;
6898 /****************************************************************************
6899 Deal with SMB_FILE_RENAME_INFORMATION.
6900 ****************************************************************************/
6902 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6903 struct smb_request *req,
6904 const char *pdata,
6905 int total_data,
6906 files_struct *fsp,
6907 struct smb_filename *smb_fname_src)
6909 bool overwrite;
6910 uint32_t root_fid;
6911 uint32_t len;
6912 char *newname = NULL;
6913 struct smb_filename *smb_fname_dst = NULL;
6914 bool dest_has_wcard = False;
6915 NTSTATUS status = NT_STATUS_OK;
6916 char *p;
6917 TALLOC_CTX *ctx = talloc_tos();
6919 if (total_data < 13) {
6920 return NT_STATUS_INVALID_PARAMETER;
6923 overwrite = (CVAL(pdata,0) ? True : False);
6924 root_fid = IVAL(pdata,4);
6925 len = IVAL(pdata,8);
6927 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6928 return NT_STATUS_INVALID_PARAMETER;
6931 if (req->posix_pathnames) {
6932 srvstr_get_path_wcard_posix(ctx,
6933 pdata,
6934 req->flags2,
6935 &newname,
6936 &pdata[12],
6937 len,
6939 &status,
6940 &dest_has_wcard);
6941 } else {
6942 srvstr_get_path_wcard(ctx,
6943 pdata,
6944 req->flags2,
6945 &newname,
6946 &pdata[12],
6947 len,
6949 &status,
6950 &dest_has_wcard);
6952 if (!NT_STATUS_IS_OK(status)) {
6953 return status;
6956 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6957 newname));
6959 if (req->flags2 & FLAGS2_DFS_PATHNAMES) {
6960 status = resolve_dfspath_wcard(ctx, conn,
6961 newname,
6962 UCF_COND_ALLOW_WCARD_LCOMP,
6963 !conn->sconn->using_smb2,
6964 &newname,
6965 &dest_has_wcard);
6966 if (!NT_STATUS_IS_OK(status)) {
6967 return status;
6971 /* Check the new name has no '/' characters. */
6972 if (strchr_m(newname, '/')) {
6973 return NT_STATUS_NOT_SUPPORTED;
6976 if (fsp && fsp->base_fsp) {
6977 /* newname must be a stream name. */
6978 if (newname[0] != ':') {
6979 return NT_STATUS_NOT_SUPPORTED;
6982 /* Create an smb_fname to call rename_internals_fsp() with. */
6983 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6984 fsp->base_fsp->fsp_name->base_name,
6985 newname,
6986 NULL,
6987 fsp->base_fsp->fsp_name->flags);
6988 if (smb_fname_dst == NULL) {
6989 status = NT_STATUS_NO_MEMORY;
6990 goto out;
6994 * Set the original last component, since
6995 * rename_internals_fsp() requires it.
6997 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6998 newname);
6999 if (smb_fname_dst->original_lcomp == NULL) {
7000 status = NT_STATUS_NO_MEMORY;
7001 goto out;
7004 } else {
7006 * Build up an smb_fname_dst based on the filename passed in.
7007 * We basically just strip off the last component, and put on
7008 * the newname instead.
7010 char *base_name = NULL;
7011 uint32_t ucf_flags = UCF_SAVE_LCOMP |
7012 ucf_flags_from_smb_request(req);
7014 if (dest_has_wcard) {
7015 ucf_flags |= UCF_ALWAYS_ALLOW_WCARD_LCOMP;
7018 /* newname must *not* be a stream name. */
7019 if (newname[0] == ':') {
7020 return NT_STATUS_NOT_SUPPORTED;
7024 * Strip off the last component (filename) of the path passed
7025 * in.
7027 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
7028 if (!base_name) {
7029 return NT_STATUS_NO_MEMORY;
7031 p = strrchr_m(base_name, '/');
7032 if (p) {
7033 p[1] = '\0';
7034 } else {
7035 base_name = talloc_strdup(ctx, "");
7036 if (!base_name) {
7037 return NT_STATUS_NO_MEMORY;
7040 /* Append the new name. */
7041 base_name = talloc_asprintf_append(base_name,
7042 "%s",
7043 newname);
7044 if (!base_name) {
7045 return NT_STATUS_NO_MEMORY;
7048 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7049 ucf_flags);
7051 /* If an error we expect this to be
7052 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7054 if (!NT_STATUS_IS_OK(status)) {
7055 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7056 status)) {
7057 goto out;
7059 /* Create an smb_fname to call rename_internals_fsp() */
7060 smb_fname_dst = synthetic_smb_fname(ctx,
7061 base_name,
7062 NULL,
7063 NULL,
7064 smb_fname_src->flags);
7065 if (smb_fname_dst == NULL) {
7066 status = NT_STATUS_NO_MEMORY;
7067 goto out;
7072 if (fsp) {
7073 DEBUG(10,("smb_file_rename_information: "
7074 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7075 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7076 smb_fname_str_dbg(smb_fname_dst)));
7077 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7078 overwrite);
7079 } else {
7080 DEBUG(10,("smb_file_rename_information: "
7081 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7082 smb_fname_str_dbg(smb_fname_src),
7083 smb_fname_str_dbg(smb_fname_dst)));
7084 status = rename_internals(ctx, conn, req, smb_fname_src,
7085 smb_fname_dst, 0, overwrite, false,
7086 dest_has_wcard,
7087 FILE_WRITE_ATTRIBUTES);
7089 out:
7090 TALLOC_FREE(smb_fname_dst);
7091 return status;
7094 /****************************************************************************
7095 Deal with SMB_SET_POSIX_ACL.
7096 ****************************************************************************/
7098 #if defined(HAVE_POSIX_ACLS)
7099 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7100 const char *pdata,
7101 int total_data,
7102 files_struct *fsp,
7103 const struct smb_filename *smb_fname)
7105 uint16_t posix_acl_version;
7106 uint16_t num_file_acls;
7107 uint16_t num_def_acls;
7108 bool valid_file_acls = True;
7109 bool valid_def_acls = True;
7110 NTSTATUS status;
7112 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7113 return NT_STATUS_INVALID_PARAMETER;
7115 posix_acl_version = SVAL(pdata,0);
7116 num_file_acls = SVAL(pdata,2);
7117 num_def_acls = SVAL(pdata,4);
7119 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7120 valid_file_acls = False;
7121 num_file_acls = 0;
7124 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7125 valid_def_acls = False;
7126 num_def_acls = 0;
7129 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7130 return NT_STATUS_INVALID_PARAMETER;
7133 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7134 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7135 return NT_STATUS_INVALID_PARAMETER;
7138 status = refuse_symlink(conn, fsp, smb_fname);
7139 if (!NT_STATUS_IS_OK(status)) {
7140 return status;
7143 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7144 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7145 (unsigned int)num_file_acls,
7146 (unsigned int)num_def_acls));
7148 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7149 smb_fname, num_file_acls,
7150 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7151 return map_nt_error_from_unix(errno);
7154 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7155 smb_fname, num_def_acls,
7156 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7157 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7158 return map_nt_error_from_unix(errno);
7160 return NT_STATUS_OK;
7162 #endif
7164 /****************************************************************************
7165 Deal with SMB_SET_POSIX_LOCK.
7166 ****************************************************************************/
7168 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7169 struct smb_request *req,
7170 const char *pdata,
7171 int total_data,
7172 files_struct *fsp)
7174 uint64_t count;
7175 uint64_t offset;
7176 uint64_t smblctx;
7177 bool blocking_lock = False;
7178 enum brl_type lock_type;
7180 NTSTATUS status = NT_STATUS_OK;
7182 if (fsp == NULL || fsp->fh->fd == -1) {
7183 return NT_STATUS_INVALID_HANDLE;
7186 if (total_data != POSIX_LOCK_DATA_SIZE) {
7187 return NT_STATUS_INVALID_PARAMETER;
7190 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7191 case POSIX_LOCK_TYPE_READ:
7192 lock_type = READ_LOCK;
7193 break;
7194 case POSIX_LOCK_TYPE_WRITE:
7195 /* Return the right POSIX-mappable error code for files opened read-only. */
7196 if (!fsp->can_write) {
7197 return NT_STATUS_INVALID_HANDLE;
7199 lock_type = WRITE_LOCK;
7200 break;
7201 case POSIX_LOCK_TYPE_UNLOCK:
7202 lock_type = UNLOCK_LOCK;
7203 break;
7204 default:
7205 return NT_STATUS_INVALID_PARAMETER;
7208 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7209 blocking_lock = False;
7210 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7211 blocking_lock = True;
7212 } else {
7213 return NT_STATUS_INVALID_PARAMETER;
7216 if (!lp_blocking_locks(SNUM(conn))) {
7217 blocking_lock = False;
7220 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7221 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7222 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7223 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7224 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7226 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7227 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7228 fsp_str_dbg(fsp),
7229 (unsigned int)lock_type,
7230 (unsigned long long)smblctx,
7231 (double)count,
7232 (double)offset ));
7234 if (lock_type == UNLOCK_LOCK) {
7235 status = do_unlock(req->sconn->msg_ctx,
7236 fsp,
7237 smblctx,
7238 count,
7239 offset,
7240 POSIX_LOCK);
7241 } else {
7242 uint64_t block_smblctx;
7244 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7245 fsp,
7246 smblctx,
7247 count,
7248 offset,
7249 lock_type,
7250 POSIX_LOCK,
7251 blocking_lock,
7252 &status,
7253 &block_smblctx);
7255 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7257 * A blocking lock was requested. Package up
7258 * this smb into a queued request and push it
7259 * onto the blocking lock queue.
7261 if(push_blocking_lock_request(br_lck,
7262 req,
7263 fsp,
7264 -1, /* infinite timeout. */
7266 smblctx,
7267 lock_type,
7268 POSIX_LOCK,
7269 offset,
7270 count,
7271 block_smblctx)) {
7272 TALLOC_FREE(br_lck);
7273 return status;
7276 TALLOC_FREE(br_lck);
7279 return status;
7282 /****************************************************************************
7283 Deal with SMB_SET_FILE_BASIC_INFO.
7284 ****************************************************************************/
7286 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7287 const char *pdata,
7288 int total_data,
7289 files_struct *fsp,
7290 const struct smb_filename *smb_fname)
7292 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7293 struct smb_file_time ft;
7294 uint32_t dosmode = 0;
7295 NTSTATUS status = NT_STATUS_OK;
7297 ZERO_STRUCT(ft);
7299 if (total_data < 36) {
7300 return NT_STATUS_INVALID_PARAMETER;
7303 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7304 if (!NT_STATUS_IS_OK(status)) {
7305 return status;
7308 /* Set the attributes */
7309 dosmode = IVAL(pdata,32);
7310 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7311 if (!NT_STATUS_IS_OK(status)) {
7312 return status;
7315 /* create time */
7316 ft.create_time = interpret_long_date(pdata);
7318 /* access time */
7319 ft.atime = interpret_long_date(pdata+8);
7321 /* write time. */
7322 ft.mtime = interpret_long_date(pdata+16);
7324 /* change time. */
7325 ft.ctime = interpret_long_date(pdata+24);
7327 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7328 smb_fname_str_dbg(smb_fname)));
7330 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7331 true);
7334 /****************************************************************************
7335 Deal with SMB_INFO_STANDARD.
7336 ****************************************************************************/
7338 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7339 const char *pdata,
7340 int total_data,
7341 files_struct *fsp,
7342 const struct smb_filename *smb_fname)
7344 NTSTATUS status;
7345 struct smb_file_time ft;
7347 ZERO_STRUCT(ft);
7349 if (total_data < 12) {
7350 return NT_STATUS_INVALID_PARAMETER;
7353 /* create time */
7354 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7355 /* access time */
7356 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7357 /* write time */
7358 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7360 DEBUG(10,("smb_set_info_standard: file %s\n",
7361 smb_fname_str_dbg(smb_fname)));
7363 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7364 if (!NT_STATUS_IS_OK(status)) {
7365 return status;
7368 return smb_set_file_time(conn,
7369 fsp,
7370 smb_fname,
7371 &ft,
7372 true);
7375 /****************************************************************************
7376 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7377 ****************************************************************************/
7379 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7380 struct smb_request *req,
7381 const char *pdata,
7382 int total_data,
7383 files_struct *fsp,
7384 struct smb_filename *smb_fname)
7386 uint64_t allocation_size = 0;
7387 NTSTATUS status = NT_STATUS_OK;
7388 files_struct *new_fsp = NULL;
7390 if (!VALID_STAT(smb_fname->st)) {
7391 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7394 if (total_data < 8) {
7395 return NT_STATUS_INVALID_PARAMETER;
7398 allocation_size = (uint64_t)IVAL(pdata,0);
7399 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7400 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7401 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7402 (double)allocation_size));
7404 if (allocation_size) {
7405 allocation_size = smb_roundup(conn, allocation_size);
7408 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7409 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7410 (double)allocation_size));
7412 if (fsp && fsp->fh->fd != -1) {
7413 /* Open file handle. */
7414 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7415 return NT_STATUS_ACCESS_DENIED;
7418 /* Only change if needed. */
7419 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7420 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7421 return map_nt_error_from_unix(errno);
7424 /* But always update the time. */
7426 * This is equivalent to a write. Ensure it's seen immediately
7427 * if there are no pending writes.
7429 trigger_write_time_update_immediate(fsp);
7430 return NT_STATUS_OK;
7433 /* Pathname or stat or directory file. */
7434 status = SMB_VFS_CREATE_FILE(
7435 conn, /* conn */
7436 req, /* req */
7437 0, /* root_dir_fid */
7438 smb_fname, /* fname */
7439 FILE_WRITE_DATA, /* access_mask */
7440 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7441 FILE_SHARE_DELETE),
7442 FILE_OPEN, /* create_disposition*/
7443 0, /* create_options */
7444 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7445 0, /* oplock_request */
7446 NULL, /* lease */
7447 0, /* allocation_size */
7448 0, /* private_flags */
7449 NULL, /* sd */
7450 NULL, /* ea_list */
7451 &new_fsp, /* result */
7452 NULL, /* pinfo */
7453 NULL, NULL); /* create context */
7455 if (!NT_STATUS_IS_OK(status)) {
7456 /* NB. We check for open_was_deferred in the caller. */
7457 return status;
7460 /* Only change if needed. */
7461 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7462 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7463 status = map_nt_error_from_unix(errno);
7464 close_file(req, new_fsp, NORMAL_CLOSE);
7465 return status;
7469 /* Changing the allocation size should set the last mod time. */
7471 * This is equivalent to a write. Ensure it's seen immediately
7472 * if there are no pending writes.
7474 trigger_write_time_update_immediate(new_fsp);
7475 close_file(req, new_fsp, NORMAL_CLOSE);
7476 return NT_STATUS_OK;
7479 /****************************************************************************
7480 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7481 ****************************************************************************/
7483 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7484 struct smb_request *req,
7485 const char *pdata,
7486 int total_data,
7487 files_struct *fsp,
7488 const struct smb_filename *smb_fname,
7489 bool fail_after_createfile)
7491 off_t size;
7493 if (total_data < 8) {
7494 return NT_STATUS_INVALID_PARAMETER;
7497 size = IVAL(pdata,0);
7498 size |= (((off_t)IVAL(pdata,4)) << 32);
7499 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7500 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7501 (double)size));
7503 return smb_set_file_size(conn, req,
7504 fsp,
7505 smb_fname,
7506 &smb_fname->st,
7507 size,
7508 fail_after_createfile);
7511 /****************************************************************************
7512 Allow a UNIX info mknod.
7513 ****************************************************************************/
7515 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7516 const char *pdata,
7517 int total_data,
7518 const struct smb_filename *smb_fname)
7520 uint32_t file_type = IVAL(pdata,56);
7521 #if defined(HAVE_MAKEDEV)
7522 uint32_t dev_major = IVAL(pdata,60);
7523 uint32_t dev_minor = IVAL(pdata,68);
7524 #endif
7525 SMB_DEV_T dev = (SMB_DEV_T)0;
7526 uint32_t raw_unixmode = IVAL(pdata,84);
7527 NTSTATUS status;
7528 mode_t unixmode;
7530 if (total_data < 100) {
7531 return NT_STATUS_INVALID_PARAMETER;
7534 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7535 PERM_NEW_FILE, &unixmode);
7536 if (!NT_STATUS_IS_OK(status)) {
7537 return status;
7540 #if defined(HAVE_MAKEDEV)
7541 dev = makedev(dev_major, dev_minor);
7542 #endif
7544 switch (file_type) {
7545 #if defined(S_IFIFO)
7546 case UNIX_TYPE_FIFO:
7547 unixmode |= S_IFIFO;
7548 break;
7549 #endif
7550 #if defined(S_IFSOCK)
7551 case UNIX_TYPE_SOCKET:
7552 unixmode |= S_IFSOCK;
7553 break;
7554 #endif
7555 #if defined(S_IFCHR)
7556 case UNIX_TYPE_CHARDEV:
7557 unixmode |= S_IFCHR;
7558 break;
7559 #endif
7560 #if defined(S_IFBLK)
7561 case UNIX_TYPE_BLKDEV:
7562 unixmode |= S_IFBLK;
7563 break;
7564 #endif
7565 default:
7566 return NT_STATUS_INVALID_PARAMETER;
7569 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7570 "%.0f mode 0%o for file %s\n", (double)dev,
7571 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7573 /* Ok - do the mknod. */
7574 if (SMB_VFS_MKNOD(conn, smb_fname, unixmode, dev) != 0) {
7575 return map_nt_error_from_unix(errno);
7578 /* If any of the other "set" calls fail we
7579 * don't want to end up with a half-constructed mknod.
7582 if (lp_inherit_permissions(SNUM(conn))) {
7583 char *parent;
7584 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7585 &parent, NULL)) {
7586 return NT_STATUS_NO_MEMORY;
7588 inherit_access_posix_acl(conn, parent, smb_fname,
7589 unixmode);
7590 TALLOC_FREE(parent);
7593 return NT_STATUS_OK;
7596 /****************************************************************************
7597 Deal with SMB_SET_FILE_UNIX_BASIC.
7598 ****************************************************************************/
7600 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7601 struct smb_request *req,
7602 const char *pdata,
7603 int total_data,
7604 files_struct *fsp,
7605 const struct smb_filename *smb_fname)
7607 struct smb_file_time ft;
7608 uint32_t raw_unixmode;
7609 mode_t unixmode;
7610 off_t size = 0;
7611 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7612 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7613 NTSTATUS status = NT_STATUS_OK;
7614 bool delete_on_fail = False;
7615 enum perm_type ptype;
7616 files_struct *all_fsps = NULL;
7617 bool modify_mtime = true;
7618 struct file_id id;
7619 struct smb_filename *smb_fname_tmp = NULL;
7620 SMB_STRUCT_STAT sbuf;
7622 ZERO_STRUCT(ft);
7624 if (total_data < 100) {
7625 return NT_STATUS_INVALID_PARAMETER;
7628 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7629 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7630 size=IVAL(pdata,0); /* first 8 Bytes are size */
7631 size |= (((off_t)IVAL(pdata,4)) << 32);
7634 ft.atime = interpret_long_date(pdata+24); /* access_time */
7635 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7636 set_owner = (uid_t)IVAL(pdata,40);
7637 set_grp = (gid_t)IVAL(pdata,48);
7638 raw_unixmode = IVAL(pdata,84);
7640 if (VALID_STAT(smb_fname->st)) {
7641 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7642 ptype = PERM_EXISTING_DIR;
7643 } else {
7644 ptype = PERM_EXISTING_FILE;
7646 } else {
7647 ptype = PERM_NEW_FILE;
7650 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7651 ptype, &unixmode);
7652 if (!NT_STATUS_IS_OK(status)) {
7653 return status;
7656 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7657 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7658 smb_fname_str_dbg(smb_fname), (double)size,
7659 (unsigned int)set_owner, (unsigned int)set_grp,
7660 (int)raw_unixmode));
7662 sbuf = smb_fname->st;
7664 if (!VALID_STAT(sbuf)) {
7666 * The only valid use of this is to create character and block
7667 * devices, and named pipes. This is deprecated (IMHO) and
7668 * a new info level should be used for mknod. JRA.
7671 status = smb_unix_mknod(conn,
7672 pdata,
7673 total_data,
7674 smb_fname);
7675 if (!NT_STATUS_IS_OK(status)) {
7676 return status;
7679 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7680 if (smb_fname_tmp == NULL) {
7681 return NT_STATUS_NO_MEMORY;
7684 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7685 status = map_nt_error_from_unix(errno);
7686 TALLOC_FREE(smb_fname_tmp);
7687 SMB_VFS_UNLINK(conn, smb_fname);
7688 return status;
7691 sbuf = smb_fname_tmp->st;
7692 smb_fname = smb_fname_tmp;
7694 /* Ensure we don't try and change anything else. */
7695 raw_unixmode = SMB_MODE_NO_CHANGE;
7696 size = get_file_size_stat(&sbuf);
7697 ft.atime = sbuf.st_ex_atime;
7698 ft.mtime = sbuf.st_ex_mtime;
7700 * We continue here as we might want to change the
7701 * owner uid/gid.
7703 delete_on_fail = True;
7706 #if 1
7707 /* Horrible backwards compatibility hack as an old server bug
7708 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7709 * */
7711 if (!size) {
7712 size = get_file_size_stat(&sbuf);
7714 #endif
7717 * Deal with the UNIX specific mode set.
7720 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7721 int ret;
7723 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7724 "setting mode 0%o for file %s\n",
7725 (unsigned int)unixmode,
7726 smb_fname_str_dbg(smb_fname)));
7727 if (fsp && fsp->fh->fd != -1) {
7728 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7729 } else {
7730 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7732 if (ret != 0) {
7733 return map_nt_error_from_unix(errno);
7738 * Deal with the UNIX specific uid set.
7741 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7742 (sbuf.st_ex_uid != set_owner)) {
7743 int ret;
7745 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7746 "changing owner %u for path %s\n",
7747 (unsigned int)set_owner,
7748 smb_fname_str_dbg(smb_fname)));
7750 if (fsp && fsp->fh->fd != -1) {
7751 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7752 } else {
7754 * UNIX extensions calls must always operate
7755 * on symlinks.
7757 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7758 set_owner, (gid_t)-1);
7761 if (ret != 0) {
7762 status = map_nt_error_from_unix(errno);
7763 if (delete_on_fail) {
7764 SMB_VFS_UNLINK(conn, smb_fname);
7766 return status;
7771 * Deal with the UNIX specific gid set.
7774 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7775 (sbuf.st_ex_gid != set_grp)) {
7776 int ret;
7778 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7779 "changing group %u for file %s\n",
7780 (unsigned int)set_owner,
7781 smb_fname_str_dbg(smb_fname)));
7782 if (fsp && fsp->fh->fd != -1) {
7783 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7784 } else {
7786 * UNIX extensions calls must always operate
7787 * on symlinks.
7789 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7790 set_grp);
7792 if (ret != 0) {
7793 status = map_nt_error_from_unix(errno);
7794 if (delete_on_fail) {
7795 SMB_VFS_UNLINK(conn, smb_fname);
7797 return status;
7801 /* Deal with any size changes. */
7803 status = smb_set_file_size(conn, req,
7804 fsp,
7805 smb_fname,
7806 &sbuf,
7807 size,
7808 false);
7809 if (!NT_STATUS_IS_OK(status)) {
7810 return status;
7813 /* Deal with any time changes. */
7814 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7815 /* No change, don't cancel anything. */
7816 return status;
7819 id = vfs_file_id_from_sbuf(conn, &sbuf);
7820 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7821 all_fsps = file_find_di_next(all_fsps)) {
7823 * We're setting the time explicitly for UNIX.
7824 * Cancel any pending changes over all handles.
7826 all_fsps->update_write_time_on_close = false;
7827 TALLOC_FREE(all_fsps->update_write_time_event);
7831 * Override the "setting_write_time"
7832 * parameter here as it almost does what
7833 * we need. Just remember if we modified
7834 * mtime and send the notify ourselves.
7836 if (null_timespec(ft.mtime)) {
7837 modify_mtime = false;
7840 status = smb_set_file_time(conn,
7841 fsp,
7842 smb_fname,
7843 &ft,
7844 false);
7845 if (modify_mtime) {
7846 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7847 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7849 return status;
7852 /****************************************************************************
7853 Deal with SMB_SET_FILE_UNIX_INFO2.
7854 ****************************************************************************/
7856 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7857 struct smb_request *req,
7858 const char *pdata,
7859 int total_data,
7860 files_struct *fsp,
7861 const struct smb_filename *smb_fname)
7863 NTSTATUS status;
7864 uint32_t smb_fflags;
7865 uint32_t smb_fmask;
7867 if (total_data < 116) {
7868 return NT_STATUS_INVALID_PARAMETER;
7871 /* Start by setting all the fields that are common between UNIX_BASIC
7872 * and UNIX_INFO2.
7874 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7875 fsp, smb_fname);
7876 if (!NT_STATUS_IS_OK(status)) {
7877 return status;
7880 smb_fflags = IVAL(pdata, 108);
7881 smb_fmask = IVAL(pdata, 112);
7883 /* NB: We should only attempt to alter the file flags if the client
7884 * sends a non-zero mask.
7886 if (smb_fmask != 0) {
7887 int stat_fflags = 0;
7889 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7890 smb_fmask, &stat_fflags)) {
7891 /* Client asked to alter a flag we don't understand. */
7892 return NT_STATUS_INVALID_PARAMETER;
7895 if (fsp && fsp->fh->fd != -1) {
7896 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7897 return NT_STATUS_NOT_SUPPORTED;
7898 } else {
7899 if (SMB_VFS_CHFLAGS(conn, smb_fname,
7900 stat_fflags) != 0) {
7901 return map_nt_error_from_unix(errno);
7906 /* XXX: need to add support for changing the create_time here. You
7907 * can do this for paths on Darwin with setattrlist(2). The right way
7908 * to hook this up is probably by extending the VFS utimes interface.
7911 return NT_STATUS_OK;
7914 /****************************************************************************
7915 Create a directory with POSIX semantics.
7916 ****************************************************************************/
7918 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7919 struct smb_request *req,
7920 char **ppdata,
7921 int total_data,
7922 struct smb_filename *smb_fname,
7923 int *pdata_return_size)
7925 NTSTATUS status = NT_STATUS_OK;
7926 uint32_t raw_unixmode = 0;
7927 uint32_t mod_unixmode = 0;
7928 mode_t unixmode = (mode_t)0;
7929 files_struct *fsp = NULL;
7930 uint16_t info_level_return = 0;
7931 int info;
7932 char *pdata = *ppdata;
7934 if (total_data < 18) {
7935 return NT_STATUS_INVALID_PARAMETER;
7938 raw_unixmode = IVAL(pdata,8);
7939 /* Next 4 bytes are not yet defined. */
7941 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7942 PERM_NEW_DIR, &unixmode);
7943 if (!NT_STATUS_IS_OK(status)) {
7944 return status;
7947 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7949 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7950 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7952 status = SMB_VFS_CREATE_FILE(
7953 conn, /* conn */
7954 req, /* req */
7955 0, /* root_dir_fid */
7956 smb_fname, /* fname */
7957 FILE_READ_ATTRIBUTES, /* access_mask */
7958 FILE_SHARE_NONE, /* share_access */
7959 FILE_CREATE, /* create_disposition*/
7960 FILE_DIRECTORY_FILE, /* create_options */
7961 mod_unixmode, /* file_attributes */
7962 0, /* oplock_request */
7963 NULL, /* lease */
7964 0, /* allocation_size */
7965 0, /* private_flags */
7966 NULL, /* sd */
7967 NULL, /* ea_list */
7968 &fsp, /* result */
7969 &info, /* pinfo */
7970 NULL, NULL); /* create context */
7972 if (NT_STATUS_IS_OK(status)) {
7973 close_file(req, fsp, NORMAL_CLOSE);
7976 info_level_return = SVAL(pdata,16);
7978 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7979 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7980 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7981 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7982 } else {
7983 *pdata_return_size = 12;
7986 /* Realloc the data size */
7987 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7988 if (*ppdata == NULL) {
7989 *pdata_return_size = 0;
7990 return NT_STATUS_NO_MEMORY;
7992 pdata = *ppdata;
7994 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7995 SSVAL(pdata,2,0); /* No fnum. */
7996 SIVAL(pdata,4,info); /* Was directory created. */
7998 switch (info_level_return) {
7999 case SMB_QUERY_FILE_UNIX_BASIC:
8000 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8001 SSVAL(pdata,10,0); /* Padding. */
8002 store_file_unix_basic(conn, pdata + 12, fsp,
8003 &smb_fname->st);
8004 break;
8005 case SMB_QUERY_FILE_UNIX_INFO2:
8006 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8007 SSVAL(pdata,10,0); /* Padding. */
8008 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8009 &smb_fname->st);
8010 break;
8011 default:
8012 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8013 SSVAL(pdata,10,0); /* Padding. */
8014 break;
8017 return status;
8020 /****************************************************************************
8021 Open/Create a file with POSIX semantics.
8022 ****************************************************************************/
8024 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
8025 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
8027 static NTSTATUS smb_posix_open(connection_struct *conn,
8028 struct smb_request *req,
8029 char **ppdata,
8030 int total_data,
8031 struct smb_filename *smb_fname,
8032 int *pdata_return_size)
8034 bool extended_oplock_granted = False;
8035 char *pdata = *ppdata;
8036 uint32_t flags = 0;
8037 uint32_t wire_open_mode = 0;
8038 uint32_t raw_unixmode = 0;
8039 uint32_t mod_unixmode = 0;
8040 uint32_t create_disp = 0;
8041 uint32_t access_mask = 0;
8042 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
8043 NTSTATUS status = NT_STATUS_OK;
8044 mode_t unixmode = (mode_t)0;
8045 files_struct *fsp = NULL;
8046 int oplock_request = 0;
8047 int info = 0;
8048 uint16_t info_level_return = 0;
8050 if (total_data < 18) {
8051 return NT_STATUS_INVALID_PARAMETER;
8054 flags = IVAL(pdata,0);
8055 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8056 if (oplock_request) {
8057 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8060 wire_open_mode = IVAL(pdata,4);
8062 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8063 return smb_posix_mkdir(conn, req,
8064 ppdata,
8065 total_data,
8066 smb_fname,
8067 pdata_return_size);
8070 switch (wire_open_mode & SMB_ACCMODE) {
8071 case SMB_O_RDONLY:
8072 access_mask = SMB_O_RDONLY_MAPPING;
8073 break;
8074 case SMB_O_WRONLY:
8075 access_mask = SMB_O_WRONLY_MAPPING;
8076 break;
8077 case SMB_O_RDWR:
8078 access_mask = (SMB_O_RDONLY_MAPPING|
8079 SMB_O_WRONLY_MAPPING);
8080 break;
8081 default:
8082 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8083 (unsigned int)wire_open_mode ));
8084 return NT_STATUS_INVALID_PARAMETER;
8087 wire_open_mode &= ~SMB_ACCMODE;
8089 /* First take care of O_CREAT|O_EXCL interactions. */
8090 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8091 case (SMB_O_CREAT | SMB_O_EXCL):
8092 /* File exists fail. File not exist create. */
8093 create_disp = FILE_CREATE;
8094 break;
8095 case SMB_O_CREAT:
8096 /* File exists open. File not exist create. */
8097 create_disp = FILE_OPEN_IF;
8098 break;
8099 case SMB_O_EXCL:
8100 /* O_EXCL on its own without O_CREAT is undefined.
8101 We deliberately ignore it as some versions of
8102 Linux CIFSFS can send a bare O_EXCL on the
8103 wire which other filesystems in the kernel
8104 ignore. See bug 9519 for details. */
8106 /* Fallthrough. */
8108 case 0:
8109 /* File exists open. File not exist fail. */
8110 create_disp = FILE_OPEN;
8111 break;
8112 default:
8113 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8114 (unsigned int)wire_open_mode ));
8115 return NT_STATUS_INVALID_PARAMETER;
8118 /* Next factor in the effects of O_TRUNC. */
8119 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8121 if (wire_open_mode & SMB_O_TRUNC) {
8122 switch (create_disp) {
8123 case FILE_CREATE:
8124 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8125 /* Leave create_disp alone as
8126 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8128 /* File exists fail. File not exist create. */
8129 break;
8130 case FILE_OPEN_IF:
8131 /* SMB_O_CREAT | SMB_O_TRUNC */
8132 /* File exists overwrite. File not exist create. */
8133 create_disp = FILE_OVERWRITE_IF;
8134 break;
8135 case FILE_OPEN:
8136 /* SMB_O_TRUNC */
8137 /* File exists overwrite. File not exist fail. */
8138 create_disp = FILE_OVERWRITE;
8139 break;
8140 default:
8141 /* Cannot get here. */
8142 smb_panic("smb_posix_open: logic error");
8143 return NT_STATUS_INVALID_PARAMETER;
8147 raw_unixmode = IVAL(pdata,8);
8148 /* Next 4 bytes are not yet defined. */
8150 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8151 (VALID_STAT(smb_fname->st) ?
8152 PERM_EXISTING_FILE : PERM_NEW_FILE),
8153 &unixmode);
8155 if (!NT_STATUS_IS_OK(status)) {
8156 return status;
8159 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8161 if (wire_open_mode & SMB_O_SYNC) {
8162 create_options |= FILE_WRITE_THROUGH;
8164 if (wire_open_mode & SMB_O_APPEND) {
8165 access_mask |= FILE_APPEND_DATA;
8167 if (wire_open_mode & SMB_O_DIRECT) {
8168 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8171 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8172 VALID_STAT_OF_DIR(smb_fname->st)) {
8173 if (access_mask != SMB_O_RDONLY_MAPPING) {
8174 return NT_STATUS_FILE_IS_A_DIRECTORY;
8176 create_options &= ~FILE_NON_DIRECTORY_FILE;
8177 create_options |= FILE_DIRECTORY_FILE;
8180 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8181 smb_fname_str_dbg(smb_fname),
8182 (unsigned int)wire_open_mode,
8183 (unsigned int)unixmode ));
8185 status = SMB_VFS_CREATE_FILE(
8186 conn, /* conn */
8187 req, /* req */
8188 0, /* root_dir_fid */
8189 smb_fname, /* fname */
8190 access_mask, /* access_mask */
8191 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8192 FILE_SHARE_DELETE),
8193 create_disp, /* create_disposition*/
8194 create_options, /* create_options */
8195 mod_unixmode, /* file_attributes */
8196 oplock_request, /* oplock_request */
8197 NULL, /* lease */
8198 0, /* allocation_size */
8199 0, /* private_flags */
8200 NULL, /* sd */
8201 NULL, /* ea_list */
8202 &fsp, /* result */
8203 &info, /* pinfo */
8204 NULL, NULL); /* create context */
8206 if (!NT_STATUS_IS_OK(status)) {
8207 return status;
8210 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8211 extended_oplock_granted = True;
8214 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8215 extended_oplock_granted = True;
8218 info_level_return = SVAL(pdata,16);
8220 /* Allocate the correct return size. */
8222 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8223 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8224 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8225 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8226 } else {
8227 *pdata_return_size = 12;
8230 /* Realloc the data size */
8231 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8232 if (*ppdata == NULL) {
8233 close_file(req, fsp, ERROR_CLOSE);
8234 *pdata_return_size = 0;
8235 return NT_STATUS_NO_MEMORY;
8237 pdata = *ppdata;
8239 if (extended_oplock_granted) {
8240 if (flags & REQUEST_BATCH_OPLOCK) {
8241 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8242 } else {
8243 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8245 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8246 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8247 } else {
8248 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8251 SSVAL(pdata,2,fsp->fnum);
8252 SIVAL(pdata,4,info); /* Was file created etc. */
8254 switch (info_level_return) {
8255 case SMB_QUERY_FILE_UNIX_BASIC:
8256 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8257 SSVAL(pdata,10,0); /* padding. */
8258 store_file_unix_basic(conn, pdata + 12, fsp,
8259 &smb_fname->st);
8260 break;
8261 case SMB_QUERY_FILE_UNIX_INFO2:
8262 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8263 SSVAL(pdata,10,0); /* padding. */
8264 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8265 &smb_fname->st);
8266 break;
8267 default:
8268 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8269 SSVAL(pdata,10,0); /* padding. */
8270 break;
8272 return NT_STATUS_OK;
8275 /****************************************************************************
8276 Delete a file with POSIX semantics.
8277 ****************************************************************************/
8279 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8280 struct smb_request *req,
8281 const char *pdata,
8282 int total_data,
8283 struct smb_filename *smb_fname)
8285 NTSTATUS status = NT_STATUS_OK;
8286 files_struct *fsp = NULL;
8287 uint16_t flags = 0;
8288 char del = 1;
8289 int info = 0;
8290 int create_options = 0;
8291 int i;
8292 struct share_mode_lock *lck = NULL;
8294 if (total_data < 2) {
8295 return NT_STATUS_INVALID_PARAMETER;
8298 flags = SVAL(pdata,0);
8300 if (!VALID_STAT(smb_fname->st)) {
8301 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8304 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8305 !VALID_STAT_OF_DIR(smb_fname->st)) {
8306 return NT_STATUS_NOT_A_DIRECTORY;
8309 DEBUG(10,("smb_posix_unlink: %s %s\n",
8310 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8311 smb_fname_str_dbg(smb_fname)));
8313 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8314 create_options |= FILE_DIRECTORY_FILE;
8317 status = SMB_VFS_CREATE_FILE(
8318 conn, /* conn */
8319 req, /* req */
8320 0, /* root_dir_fid */
8321 smb_fname, /* fname */
8322 DELETE_ACCESS, /* access_mask */
8323 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8324 FILE_SHARE_DELETE),
8325 FILE_OPEN, /* create_disposition*/
8326 create_options, /* create_options */
8327 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8328 0, /* oplock_request */
8329 NULL, /* lease */
8330 0, /* allocation_size */
8331 0, /* private_flags */
8332 NULL, /* sd */
8333 NULL, /* ea_list */
8334 &fsp, /* result */
8335 &info, /* pinfo */
8336 NULL, NULL); /* create context */
8338 if (!NT_STATUS_IS_OK(status)) {
8339 return status;
8343 * Don't lie to client. If we can't really delete due to
8344 * non-POSIX opens return SHARING_VIOLATION.
8347 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8348 if (lck == NULL) {
8349 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8350 "lock for file %s\n", fsp_str_dbg(fsp)));
8351 close_file(req, fsp, NORMAL_CLOSE);
8352 return NT_STATUS_INVALID_PARAMETER;
8356 * See if others still have the file open. If this is the case, then
8357 * don't delete. If all opens are POSIX delete we can set the delete
8358 * on close disposition.
8360 for (i=0; i<lck->data->num_share_modes; i++) {
8361 struct share_mode_entry *e = &lck->data->share_modes[i];
8362 if (is_valid_share_mode_entry(e)) {
8363 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8364 continue;
8366 if (share_mode_stale_pid(lck->data, i)) {
8367 continue;
8369 /* Fail with sharing violation. */
8370 TALLOC_FREE(lck);
8371 close_file(req, fsp, NORMAL_CLOSE);
8372 return NT_STATUS_SHARING_VIOLATION;
8377 * Set the delete on close.
8379 status = smb_set_file_disposition_info(conn,
8380 &del,
8382 fsp,
8383 smb_fname);
8385 TALLOC_FREE(lck);
8387 if (!NT_STATUS_IS_OK(status)) {
8388 close_file(req, fsp, NORMAL_CLOSE);
8389 return status;
8391 return close_file(req, fsp, NORMAL_CLOSE);
8394 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8395 struct smb_request *req,
8396 TALLOC_CTX *mem_ctx,
8397 uint16_t info_level,
8398 files_struct *fsp,
8399 struct smb_filename *smb_fname,
8400 char **ppdata, int total_data,
8401 int *ret_data_size)
8403 char *pdata = *ppdata;
8404 NTSTATUS status = NT_STATUS_OK;
8405 int data_return_size = 0;
8407 *ret_data_size = 0;
8409 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8410 return NT_STATUS_INVALID_LEVEL;
8413 if (!CAN_WRITE(conn)) {
8414 /* Allow POSIX opens. The open path will deny
8415 * any non-readonly opens. */
8416 if (info_level != SMB_POSIX_PATH_OPEN) {
8417 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8421 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8422 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8423 fsp_fnum_dbg(fsp),
8424 info_level, total_data));
8426 switch (info_level) {
8428 case SMB_INFO_STANDARD:
8430 status = smb_set_info_standard(conn,
8431 pdata,
8432 total_data,
8433 fsp,
8434 smb_fname);
8435 break;
8438 case SMB_INFO_SET_EA:
8440 status = smb_info_set_ea(conn,
8441 pdata,
8442 total_data,
8443 fsp,
8444 smb_fname);
8445 break;
8448 case SMB_SET_FILE_BASIC_INFO:
8449 case SMB_FILE_BASIC_INFORMATION:
8451 status = smb_set_file_basic_info(conn,
8452 pdata,
8453 total_data,
8454 fsp,
8455 smb_fname);
8456 break;
8459 case SMB_FILE_ALLOCATION_INFORMATION:
8460 case SMB_SET_FILE_ALLOCATION_INFO:
8462 status = smb_set_file_allocation_info(conn, req,
8463 pdata,
8464 total_data,
8465 fsp,
8466 smb_fname);
8467 break;
8470 case SMB_FILE_END_OF_FILE_INFORMATION:
8471 case SMB_SET_FILE_END_OF_FILE_INFO:
8474 * XP/Win7 both fail after the createfile with
8475 * SMB_SET_FILE_END_OF_FILE_INFO but not
8476 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8477 * The level is known here, so pass it down
8478 * appropriately.
8480 bool should_fail =
8481 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8483 status = smb_set_file_end_of_file_info(conn, req,
8484 pdata,
8485 total_data,
8486 fsp,
8487 smb_fname,
8488 should_fail);
8489 break;
8492 case SMB_FILE_DISPOSITION_INFORMATION:
8493 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8495 #if 0
8496 /* JRA - We used to just ignore this on a path ?
8497 * Shouldn't this be invalid level on a pathname
8498 * based call ?
8500 if (tran_call != TRANSACT2_SETFILEINFO) {
8501 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8503 #endif
8504 status = smb_set_file_disposition_info(conn,
8505 pdata,
8506 total_data,
8507 fsp,
8508 smb_fname);
8509 break;
8512 case SMB_FILE_POSITION_INFORMATION:
8514 status = smb_file_position_information(conn,
8515 pdata,
8516 total_data,
8517 fsp);
8518 break;
8521 case SMB_FILE_FULL_EA_INFORMATION:
8523 status = smb_set_file_full_ea_info(conn,
8524 pdata,
8525 total_data,
8526 fsp);
8527 break;
8530 /* From tridge Samba4 :
8531 * MODE_INFORMATION in setfileinfo (I have no
8532 * idea what "mode information" on a file is - it takes a value of 0,
8533 * 2, 4 or 6. What could it be?).
8536 case SMB_FILE_MODE_INFORMATION:
8538 status = smb_file_mode_information(conn,
8539 pdata,
8540 total_data);
8541 break;
8545 * CIFS UNIX extensions.
8548 case SMB_SET_FILE_UNIX_BASIC:
8550 status = smb_set_file_unix_basic(conn, req,
8551 pdata,
8552 total_data,
8553 fsp,
8554 smb_fname);
8555 break;
8558 case SMB_SET_FILE_UNIX_INFO2:
8560 status = smb_set_file_unix_info2(conn, req,
8561 pdata,
8562 total_data,
8563 fsp,
8564 smb_fname);
8565 break;
8568 case SMB_SET_FILE_UNIX_LINK:
8570 if (fsp) {
8571 /* We must have a pathname for this. */
8572 return NT_STATUS_INVALID_LEVEL;
8574 status = smb_set_file_unix_link(conn, req, pdata,
8575 total_data, smb_fname);
8576 break;
8579 case SMB_SET_FILE_UNIX_HLINK:
8581 if (fsp) {
8582 /* We must have a pathname for this. */
8583 return NT_STATUS_INVALID_LEVEL;
8585 status = smb_set_file_unix_hlink(conn, req,
8586 pdata, total_data,
8587 smb_fname);
8588 break;
8591 case SMB_FILE_RENAME_INFORMATION:
8593 status = smb_file_rename_information(conn, req,
8594 pdata, total_data,
8595 fsp, smb_fname);
8596 break;
8599 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8601 /* SMB2 rename information. */
8602 status = smb2_file_rename_information(conn, req,
8603 pdata, total_data,
8604 fsp, smb_fname);
8605 break;
8608 case SMB_FILE_LINK_INFORMATION:
8610 status = smb_file_link_information(conn, req,
8611 pdata, total_data,
8612 fsp, smb_fname);
8613 break;
8616 #if defined(HAVE_POSIX_ACLS)
8617 case SMB_SET_POSIX_ACL:
8619 status = smb_set_posix_acl(conn,
8620 pdata,
8621 total_data,
8622 fsp,
8623 smb_fname);
8624 break;
8626 #endif
8628 case SMB_SET_POSIX_LOCK:
8630 if (!fsp) {
8631 return NT_STATUS_INVALID_LEVEL;
8633 status = smb_set_posix_lock(conn, req,
8634 pdata, total_data, fsp);
8635 break;
8638 case SMB_POSIX_PATH_OPEN:
8640 if (fsp) {
8641 /* We must have a pathname for this. */
8642 return NT_STATUS_INVALID_LEVEL;
8645 status = smb_posix_open(conn, req,
8646 ppdata,
8647 total_data,
8648 smb_fname,
8649 &data_return_size);
8650 break;
8653 case SMB_POSIX_PATH_UNLINK:
8655 if (fsp) {
8656 /* We must have a pathname for this. */
8657 return NT_STATUS_INVALID_LEVEL;
8660 status = smb_posix_unlink(conn, req,
8661 pdata,
8662 total_data,
8663 smb_fname);
8664 break;
8667 default:
8668 return NT_STATUS_INVALID_LEVEL;
8671 if (!NT_STATUS_IS_OK(status)) {
8672 return status;
8675 *ret_data_size = data_return_size;
8676 return NT_STATUS_OK;
8679 /****************************************************************************
8680 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8681 ****************************************************************************/
8683 static void call_trans2setfilepathinfo(connection_struct *conn,
8684 struct smb_request *req,
8685 unsigned int tran_call,
8686 char **pparams, int total_params,
8687 char **ppdata, int total_data,
8688 unsigned int max_data_bytes)
8690 char *params = *pparams;
8691 char *pdata = *ppdata;
8692 uint16_t info_level;
8693 struct smb_filename *smb_fname = NULL;
8694 files_struct *fsp = NULL;
8695 NTSTATUS status = NT_STATUS_OK;
8696 int data_return_size = 0;
8698 if (!params) {
8699 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8700 return;
8703 if (tran_call == TRANSACT2_SETFILEINFO) {
8704 if (total_params < 4) {
8705 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8706 return;
8709 fsp = file_fsp(req, SVAL(params,0));
8710 /* Basic check for non-null fsp. */
8711 if (!check_fsp_open(conn, req, fsp)) {
8712 return;
8714 info_level = SVAL(params,2);
8716 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8717 if (smb_fname == NULL) {
8718 reply_nterror(req, NT_STATUS_NO_MEMORY);
8719 return;
8722 if(fsp->fh->fd == -1) {
8724 * This is actually a SETFILEINFO on a directory
8725 * handle (returned from an NT SMB). NT5.0 seems
8726 * to do this call. JRA.
8728 if (INFO_LEVEL_IS_UNIX(info_level)) {
8729 /* Always do lstat for UNIX calls. */
8730 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8731 DEBUG(3,("call_trans2setfilepathinfo: "
8732 "SMB_VFS_LSTAT of %s failed "
8733 "(%s)\n",
8734 smb_fname_str_dbg(smb_fname),
8735 strerror(errno)));
8736 reply_nterror(req, map_nt_error_from_unix(errno));
8737 return;
8739 } else {
8740 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8741 DEBUG(3,("call_trans2setfilepathinfo: "
8742 "fileinfo of %s failed (%s)\n",
8743 smb_fname_str_dbg(smb_fname),
8744 strerror(errno)));
8745 reply_nterror(req, map_nt_error_from_unix(errno));
8746 return;
8749 } else if (fsp->print_file) {
8751 * Doing a DELETE_ON_CLOSE should cancel a print job.
8753 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8754 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8756 DEBUG(3,("call_trans2setfilepathinfo: "
8757 "Cancelling print job (%s)\n",
8758 fsp_str_dbg(fsp)));
8760 SSVAL(params,0,0);
8761 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8762 *ppdata, 0,
8763 max_data_bytes);
8764 return;
8765 } else {
8766 reply_nterror(req,
8767 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8768 return;
8770 } else {
8772 * Original code - this is an open file.
8774 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8775 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8776 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8777 strerror(errno)));
8778 reply_nterror(req, map_nt_error_from_unix(errno));
8779 return;
8782 } else {
8783 char *fname = NULL;
8784 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8786 /* set path info */
8787 if (total_params < 7) {
8788 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8789 return;
8792 info_level = SVAL(params,0);
8793 if (req->posix_pathnames) {
8794 srvstr_get_path_posix(req,
8795 params,
8796 req->flags2,
8797 &fname,
8798 &params[6],
8799 total_params - 6,
8800 STR_TERMINATE,
8801 &status);
8802 } else {
8803 srvstr_get_path(req,
8804 params,
8805 req->flags2,
8806 &fname,
8807 &params[6],
8808 total_params - 6,
8809 STR_TERMINATE,
8810 &status);
8812 if (!NT_STATUS_IS_OK(status)) {
8813 reply_nterror(req, status);
8814 return;
8817 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8818 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8819 info_level == SMB_FILE_RENAME_INFORMATION ||
8820 info_level == SMB_POSIX_PATH_UNLINK) {
8821 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8824 status = filename_convert(req, conn,
8825 fname,
8826 ucf_flags,
8827 NULL,
8828 &smb_fname);
8829 if (!NT_STATUS_IS_OK(status)) {
8830 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8831 reply_botherror(req,
8832 NT_STATUS_PATH_NOT_COVERED,
8833 ERRSRV, ERRbadpath);
8834 return;
8836 reply_nterror(req, status);
8837 return;
8840 if (INFO_LEVEL_IS_UNIX(info_level)) {
8842 * For CIFS UNIX extensions the target name may not exist.
8845 /* Always do lstat for UNIX calls. */
8846 SMB_VFS_LSTAT(conn, smb_fname);
8848 } else if (!VALID_STAT(smb_fname->st) &&
8849 SMB_VFS_STAT(conn, smb_fname)) {
8850 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8851 "%s failed (%s)\n",
8852 smb_fname_str_dbg(smb_fname),
8853 strerror(errno)));
8854 reply_nterror(req, map_nt_error_from_unix(errno));
8855 return;
8859 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8860 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8861 fsp_fnum_dbg(fsp),
8862 info_level,total_data));
8864 /* Realloc the parameter size */
8865 *pparams = (char *)SMB_REALLOC(*pparams,2);
8866 if (*pparams == NULL) {
8867 reply_nterror(req, NT_STATUS_NO_MEMORY);
8868 return;
8870 params = *pparams;
8872 SSVAL(params,0,0);
8874 status = smbd_do_setfilepathinfo(conn, req, req,
8875 info_level,
8876 fsp,
8877 smb_fname,
8878 ppdata, total_data,
8879 &data_return_size);
8880 if (!NT_STATUS_IS_OK(status)) {
8881 if (open_was_deferred(req->xconn, req->mid)) {
8882 /* We have re-scheduled this call. */
8883 return;
8885 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8886 /* We have re-scheduled this call. */
8887 return;
8889 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8890 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8891 ERRSRV, ERRbadpath);
8892 return;
8894 if (info_level == SMB_POSIX_PATH_OPEN) {
8895 reply_openerror(req, status);
8896 return;
8900 * Invalid EA name needs to return 2 param bytes,
8901 * not a zero-length error packet.
8903 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8904 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8905 max_data_bytes);
8906 } else {
8907 reply_nterror(req, status);
8909 return;
8912 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8913 max_data_bytes);
8915 return;
8918 /****************************************************************************
8919 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8920 ****************************************************************************/
8922 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8923 char **pparams, int total_params,
8924 char **ppdata, int total_data,
8925 unsigned int max_data_bytes)
8927 struct smb_filename *smb_dname = NULL;
8928 char *params = *pparams;
8929 char *pdata = *ppdata;
8930 char *directory = NULL;
8931 NTSTATUS status = NT_STATUS_OK;
8932 struct ea_list *ea_list = NULL;
8933 uint32_t ucf_flags = ucf_flags_from_smb_request(req);
8934 TALLOC_CTX *ctx = talloc_tos();
8936 if (!CAN_WRITE(conn)) {
8937 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8938 return;
8941 if (total_params < 5) {
8942 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8943 return;
8946 if (req->posix_pathnames) {
8947 srvstr_get_path_posix(ctx,
8948 params,
8949 req->flags2,
8950 &directory,
8951 &params[4],
8952 total_params - 4,
8953 STR_TERMINATE,
8954 &status);
8955 } else {
8956 srvstr_get_path(ctx,
8957 params,
8958 req->flags2,
8959 &directory,
8960 &params[4],
8961 total_params - 4,
8962 STR_TERMINATE,
8963 &status);
8965 if (!NT_STATUS_IS_OK(status)) {
8966 reply_nterror(req, status);
8967 return;
8970 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8972 status = filename_convert(ctx,
8973 conn,
8974 directory,
8975 ucf_flags,
8976 NULL,
8977 &smb_dname);
8979 if (!NT_STATUS_IS_OK(status)) {
8980 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8981 reply_botherror(req,
8982 NT_STATUS_PATH_NOT_COVERED,
8983 ERRSRV, ERRbadpath);
8984 return;
8986 reply_nterror(req, status);
8987 return;
8991 * OS/2 workplace shell seems to send SET_EA requests of "null"
8992 * length (4 bytes containing IVAL 4).
8993 * They seem to have no effect. Bug #3212. JRA.
8996 if (total_data && (total_data != 4)) {
8997 /* Any data in this call is an EA list. */
8998 if (total_data < 10) {
8999 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9000 goto out;
9003 if (IVAL(pdata,0) > total_data) {
9004 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
9005 IVAL(pdata,0), (unsigned int)total_data));
9006 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9007 goto out;
9010 ea_list = read_ea_list(talloc_tos(), pdata + 4,
9011 total_data - 4);
9012 if (!ea_list) {
9013 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9014 goto out;
9017 if (!lp_ea_support(SNUM(conn))) {
9018 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
9019 goto out;
9022 /* If total_data == 4 Windows doesn't care what values
9023 * are placed in that field, it just ignores them.
9024 * The System i QNTC IBM SMB client puts bad values here,
9025 * so ignore them. */
9027 status = create_directory(conn, req, smb_dname);
9029 if (!NT_STATUS_IS_OK(status)) {
9030 reply_nterror(req, status);
9031 goto out;
9034 /* Try and set any given EA. */
9035 if (ea_list) {
9036 status = set_ea(conn, NULL, smb_dname, ea_list);
9037 if (!NT_STATUS_IS_OK(status)) {
9038 reply_nterror(req, status);
9039 goto out;
9043 /* Realloc the parameter and data sizes */
9044 *pparams = (char *)SMB_REALLOC(*pparams,2);
9045 if(*pparams == NULL) {
9046 reply_nterror(req, NT_STATUS_NO_MEMORY);
9047 goto out;
9049 params = *pparams;
9051 SSVAL(params,0,0);
9053 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9055 out:
9056 TALLOC_FREE(smb_dname);
9057 return;
9060 /****************************************************************************
9061 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9062 We don't actually do this - we just send a null response.
9063 ****************************************************************************/
9065 static void call_trans2findnotifyfirst(connection_struct *conn,
9066 struct smb_request *req,
9067 char **pparams, int total_params,
9068 char **ppdata, int total_data,
9069 unsigned int max_data_bytes)
9071 char *params = *pparams;
9072 uint16_t info_level;
9074 if (total_params < 6) {
9075 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9076 return;
9079 info_level = SVAL(params,4);
9080 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9082 switch (info_level) {
9083 case 1:
9084 case 2:
9085 break;
9086 default:
9087 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9088 return;
9091 /* Realloc the parameter and data sizes */
9092 *pparams = (char *)SMB_REALLOC(*pparams,6);
9093 if (*pparams == NULL) {
9094 reply_nterror(req, NT_STATUS_NO_MEMORY);
9095 return;
9097 params = *pparams;
9099 SSVAL(params,0,fnf_handle);
9100 SSVAL(params,2,0); /* No changes */
9101 SSVAL(params,4,0); /* No EA errors */
9103 fnf_handle++;
9105 if(fnf_handle == 0)
9106 fnf_handle = 257;
9108 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9110 return;
9113 /****************************************************************************
9114 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9115 changes). Currently this does nothing.
9116 ****************************************************************************/
9118 static void call_trans2findnotifynext(connection_struct *conn,
9119 struct smb_request *req,
9120 char **pparams, int total_params,
9121 char **ppdata, int total_data,
9122 unsigned int max_data_bytes)
9124 char *params = *pparams;
9126 DEBUG(3,("call_trans2findnotifynext\n"));
9128 /* Realloc the parameter and data sizes */
9129 *pparams = (char *)SMB_REALLOC(*pparams,4);
9130 if (*pparams == NULL) {
9131 reply_nterror(req, NT_STATUS_NO_MEMORY);
9132 return;
9134 params = *pparams;
9136 SSVAL(params,0,0); /* No changes */
9137 SSVAL(params,2,0); /* No EA errors */
9139 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9141 return;
9144 /****************************************************************************
9145 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9146 ****************************************************************************/
9148 static void call_trans2getdfsreferral(connection_struct *conn,
9149 struct smb_request *req,
9150 char **pparams, int total_params,
9151 char **ppdata, int total_data,
9152 unsigned int max_data_bytes)
9154 char *params = *pparams;
9155 char *pathname = NULL;
9156 int reply_size = 0;
9157 int max_referral_level;
9158 NTSTATUS status = NT_STATUS_OK;
9159 TALLOC_CTX *ctx = talloc_tos();
9161 DEBUG(10,("call_trans2getdfsreferral\n"));
9163 if (total_params < 3) {
9164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9165 return;
9168 max_referral_level = SVAL(params,0);
9170 if(!lp_host_msdfs()) {
9171 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9172 return;
9175 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9176 total_params - 2, STR_TERMINATE);
9177 if (!pathname) {
9178 reply_nterror(req, NT_STATUS_NOT_FOUND);
9179 return;
9181 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9182 ppdata,&status)) < 0) {
9183 reply_nterror(req, status);
9184 return;
9187 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9188 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9189 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9191 return;
9194 #define LMCAT_SPL 0x53
9195 #define LMFUNC_GETJOBID 0x60
9197 /****************************************************************************
9198 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9199 ****************************************************************************/
9201 static void call_trans2ioctl(connection_struct *conn,
9202 struct smb_request *req,
9203 char **pparams, int total_params,
9204 char **ppdata, int total_data,
9205 unsigned int max_data_bytes)
9207 char *pdata = *ppdata;
9208 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9209 NTSTATUS status;
9210 size_t len = 0;
9212 /* check for an invalid fid before proceeding */
9214 if (!fsp) {
9215 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9216 return;
9219 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9220 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9221 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9222 if (*ppdata == NULL) {
9223 reply_nterror(req, NT_STATUS_NO_MEMORY);
9224 return;
9226 pdata = *ppdata;
9228 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9229 CAN ACCEPT THIS IN UNICODE. JRA. */
9231 /* Job number */
9232 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9234 status = srvstr_push(pdata, req->flags2, pdata + 2,
9235 lp_netbios_name(), 15,
9236 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9237 if (!NT_STATUS_IS_OK(status)) {
9238 reply_nterror(req, status);
9239 return;
9241 status = srvstr_push(pdata, req->flags2, pdata+18,
9242 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9243 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9244 if (!NT_STATUS_IS_OK(status)) {
9245 reply_nterror(req, status);
9246 return;
9248 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9249 max_data_bytes);
9250 return;
9253 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9254 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9257 /****************************************************************************
9258 Reply to a SMBfindclose (stop trans2 directory search).
9259 ****************************************************************************/
9261 void reply_findclose(struct smb_request *req)
9263 int dptr_num;
9264 struct smbd_server_connection *sconn = req->sconn;
9266 START_PROFILE(SMBfindclose);
9268 if (req->wct < 1) {
9269 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9270 END_PROFILE(SMBfindclose);
9271 return;
9274 dptr_num = SVALS(req->vwv+0, 0);
9276 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9278 dptr_close(sconn, &dptr_num);
9280 reply_outbuf(req, 0, 0);
9282 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9284 END_PROFILE(SMBfindclose);
9285 return;
9288 /****************************************************************************
9289 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9290 ****************************************************************************/
9292 void reply_findnclose(struct smb_request *req)
9294 int dptr_num;
9296 START_PROFILE(SMBfindnclose);
9298 if (req->wct < 1) {
9299 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9300 END_PROFILE(SMBfindnclose);
9301 return;
9304 dptr_num = SVAL(req->vwv+0, 0);
9306 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9308 /* We never give out valid handles for a
9309 findnotifyfirst - so any dptr_num is ok here.
9310 Just ignore it. */
9312 reply_outbuf(req, 0, 0);
9314 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9316 END_PROFILE(SMBfindnclose);
9317 return;
9320 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9321 struct trans_state *state)
9323 if (get_Protocol() >= PROTOCOL_NT1) {
9324 req->flags2 |= 0x40; /* IS_LONG_NAME */
9325 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9328 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9329 if (state->call != TRANSACT2_QFSINFO &&
9330 state->call != TRANSACT2_SETFSINFO) {
9331 DEBUG(0,("handle_trans2: encryption required "
9332 "with call 0x%x\n",
9333 (unsigned int)state->call));
9334 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9335 return;
9339 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9341 /* Now we must call the relevant TRANS2 function */
9342 switch(state->call) {
9343 case TRANSACT2_OPEN:
9345 START_PROFILE(Trans2_open);
9346 call_trans2open(conn, req,
9347 &state->param, state->total_param,
9348 &state->data, state->total_data,
9349 state->max_data_return);
9350 END_PROFILE(Trans2_open);
9351 break;
9354 case TRANSACT2_FINDFIRST:
9356 START_PROFILE(Trans2_findfirst);
9357 call_trans2findfirst(conn, req,
9358 &state->param, state->total_param,
9359 &state->data, state->total_data,
9360 state->max_data_return);
9361 END_PROFILE(Trans2_findfirst);
9362 break;
9365 case TRANSACT2_FINDNEXT:
9367 START_PROFILE(Trans2_findnext);
9368 call_trans2findnext(conn, req,
9369 &state->param, state->total_param,
9370 &state->data, state->total_data,
9371 state->max_data_return);
9372 END_PROFILE(Trans2_findnext);
9373 break;
9376 case TRANSACT2_QFSINFO:
9378 START_PROFILE(Trans2_qfsinfo);
9379 call_trans2qfsinfo(conn, req,
9380 &state->param, state->total_param,
9381 &state->data, state->total_data,
9382 state->max_data_return);
9383 END_PROFILE(Trans2_qfsinfo);
9384 break;
9387 case TRANSACT2_SETFSINFO:
9389 START_PROFILE(Trans2_setfsinfo);
9390 call_trans2setfsinfo(conn, req,
9391 &state->param, state->total_param,
9392 &state->data, state->total_data,
9393 state->max_data_return);
9394 END_PROFILE(Trans2_setfsinfo);
9395 break;
9398 case TRANSACT2_QPATHINFO:
9399 case TRANSACT2_QFILEINFO:
9401 START_PROFILE(Trans2_qpathinfo);
9402 call_trans2qfilepathinfo(conn, req, state->call,
9403 &state->param, state->total_param,
9404 &state->data, state->total_data,
9405 state->max_data_return);
9406 END_PROFILE(Trans2_qpathinfo);
9407 break;
9410 case TRANSACT2_SETPATHINFO:
9411 case TRANSACT2_SETFILEINFO:
9413 START_PROFILE(Trans2_setpathinfo);
9414 call_trans2setfilepathinfo(conn, req, state->call,
9415 &state->param, state->total_param,
9416 &state->data, state->total_data,
9417 state->max_data_return);
9418 END_PROFILE(Trans2_setpathinfo);
9419 break;
9422 case TRANSACT2_FINDNOTIFYFIRST:
9424 START_PROFILE(Trans2_findnotifyfirst);
9425 call_trans2findnotifyfirst(conn, req,
9426 &state->param, state->total_param,
9427 &state->data, state->total_data,
9428 state->max_data_return);
9429 END_PROFILE(Trans2_findnotifyfirst);
9430 break;
9433 case TRANSACT2_FINDNOTIFYNEXT:
9435 START_PROFILE(Trans2_findnotifynext);
9436 call_trans2findnotifynext(conn, req,
9437 &state->param, state->total_param,
9438 &state->data, state->total_data,
9439 state->max_data_return);
9440 END_PROFILE(Trans2_findnotifynext);
9441 break;
9444 case TRANSACT2_MKDIR:
9446 START_PROFILE(Trans2_mkdir);
9447 call_trans2mkdir(conn, req,
9448 &state->param, state->total_param,
9449 &state->data, state->total_data,
9450 state->max_data_return);
9451 END_PROFILE(Trans2_mkdir);
9452 break;
9455 case TRANSACT2_GET_DFS_REFERRAL:
9457 START_PROFILE(Trans2_get_dfs_referral);
9458 call_trans2getdfsreferral(conn, req,
9459 &state->param, state->total_param,
9460 &state->data, state->total_data,
9461 state->max_data_return);
9462 END_PROFILE(Trans2_get_dfs_referral);
9463 break;
9466 case TRANSACT2_IOCTL:
9468 START_PROFILE(Trans2_ioctl);
9469 call_trans2ioctl(conn, req,
9470 &state->param, state->total_param,
9471 &state->data, state->total_data,
9472 state->max_data_return);
9473 END_PROFILE(Trans2_ioctl);
9474 break;
9477 default:
9478 /* Error in request */
9479 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9480 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9484 /****************************************************************************
9485 Reply to a SMBtrans2.
9486 ****************************************************************************/
9488 void reply_trans2(struct smb_request *req)
9490 connection_struct *conn = req->conn;
9491 unsigned int dsoff;
9492 unsigned int dscnt;
9493 unsigned int psoff;
9494 unsigned int pscnt;
9495 unsigned int tran_call;
9496 struct trans_state *state;
9497 NTSTATUS result;
9499 START_PROFILE(SMBtrans2);
9501 if (req->wct < 14) {
9502 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9503 END_PROFILE(SMBtrans2);
9504 return;
9507 dsoff = SVAL(req->vwv+12, 0);
9508 dscnt = SVAL(req->vwv+11, 0);
9509 psoff = SVAL(req->vwv+10, 0);
9510 pscnt = SVAL(req->vwv+9, 0);
9511 tran_call = SVAL(req->vwv+14, 0);
9513 result = allow_new_trans(conn->pending_trans, req->mid);
9514 if (!NT_STATUS_IS_OK(result)) {
9515 DEBUG(2, ("Got invalid trans2 request: %s\n",
9516 nt_errstr(result)));
9517 reply_nterror(req, result);
9518 END_PROFILE(SMBtrans2);
9519 return;
9522 if (IS_IPC(conn)) {
9523 switch (tran_call) {
9524 /* List the allowed trans2 calls on IPC$ */
9525 case TRANSACT2_OPEN:
9526 case TRANSACT2_GET_DFS_REFERRAL:
9527 case TRANSACT2_QFILEINFO:
9528 case TRANSACT2_QFSINFO:
9529 case TRANSACT2_SETFSINFO:
9530 break;
9531 default:
9532 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9533 END_PROFILE(SMBtrans2);
9534 return;
9538 if ((state = talloc(conn, struct trans_state)) == NULL) {
9539 DEBUG(0, ("talloc failed\n"));
9540 reply_nterror(req, NT_STATUS_NO_MEMORY);
9541 END_PROFILE(SMBtrans2);
9542 return;
9545 state->cmd = SMBtrans2;
9547 state->mid = req->mid;
9548 state->vuid = req->vuid;
9549 state->setup_count = SVAL(req->vwv+13, 0);
9550 state->setup = NULL;
9551 state->total_param = SVAL(req->vwv+0, 0);
9552 state->param = NULL;
9553 state->total_data = SVAL(req->vwv+1, 0);
9554 state->data = NULL;
9555 state->max_param_return = SVAL(req->vwv+2, 0);
9556 state->max_data_return = SVAL(req->vwv+3, 0);
9557 state->max_setup_return = SVAL(req->vwv+4, 0);
9558 state->close_on_completion = BITSETW(req->vwv+5, 0);
9559 state->one_way = BITSETW(req->vwv+5, 1);
9561 state->call = tran_call;
9563 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9564 is so as a sanity check */
9565 if (state->setup_count != 1) {
9567 * Need to have rc=0 for ioctl to get job id for OS/2.
9568 * Network printing will fail if function is not successful.
9569 * Similar function in reply.c will be used if protocol
9570 * is LANMAN1.0 instead of LM1.2X002.
9571 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9572 * outbuf doesn't have to be set(only job id is used).
9574 if ( (state->setup_count == 4)
9575 && (tran_call == TRANSACT2_IOCTL)
9576 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9577 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9578 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9579 } else {
9580 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9581 DEBUG(2,("Transaction is %d\n",tran_call));
9582 TALLOC_FREE(state);
9583 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9584 END_PROFILE(SMBtrans2);
9585 return;
9589 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9590 goto bad_param;
9592 if (state->total_data) {
9594 if (trans_oob(state->total_data, 0, dscnt)
9595 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9596 goto bad_param;
9599 /* Can't use talloc here, the core routines do realloc on the
9600 * params and data. */
9601 state->data = (char *)SMB_MALLOC(state->total_data);
9602 if (state->data == NULL) {
9603 DEBUG(0,("reply_trans2: data malloc fail for %u "
9604 "bytes !\n", (unsigned int)state->total_data));
9605 TALLOC_FREE(state);
9606 reply_nterror(req, NT_STATUS_NO_MEMORY);
9607 END_PROFILE(SMBtrans2);
9608 return;
9611 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9614 if (state->total_param) {
9616 if (trans_oob(state->total_param, 0, pscnt)
9617 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9618 goto bad_param;
9621 /* Can't use talloc here, the core routines do realloc on the
9622 * params and data. */
9623 state->param = (char *)SMB_MALLOC(state->total_param);
9624 if (state->param == NULL) {
9625 DEBUG(0,("reply_trans: param malloc fail for %u "
9626 "bytes !\n", (unsigned int)state->total_param));
9627 SAFE_FREE(state->data);
9628 TALLOC_FREE(state);
9629 reply_nterror(req, NT_STATUS_NO_MEMORY);
9630 END_PROFILE(SMBtrans2);
9631 return;
9634 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9637 state->received_data = dscnt;
9638 state->received_param = pscnt;
9640 if ((state->received_param == state->total_param) &&
9641 (state->received_data == state->total_data)) {
9643 handle_trans2(conn, req, state);
9645 SAFE_FREE(state->data);
9646 SAFE_FREE(state->param);
9647 TALLOC_FREE(state);
9648 END_PROFILE(SMBtrans2);
9649 return;
9652 DLIST_ADD(conn->pending_trans, state);
9654 /* We need to send an interim response then receive the rest
9655 of the parameter/data bytes */
9656 reply_outbuf(req, 0, 0);
9657 show_msg((char *)req->outbuf);
9658 END_PROFILE(SMBtrans2);
9659 return;
9661 bad_param:
9663 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9664 SAFE_FREE(state->data);
9665 SAFE_FREE(state->param);
9666 TALLOC_FREE(state);
9667 END_PROFILE(SMBtrans2);
9668 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9672 /****************************************************************************
9673 Reply to a SMBtranss2
9674 ****************************************************************************/
9676 void reply_transs2(struct smb_request *req)
9678 connection_struct *conn = req->conn;
9679 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9680 struct trans_state *state;
9682 START_PROFILE(SMBtranss2);
9684 show_msg((const char *)req->inbuf);
9686 /* Windows clients expect all replies to
9687 a transact secondary (SMBtranss2 0x33)
9688 to have a command code of transact
9689 (SMBtrans2 0x32). See bug #8989
9690 and also [MS-CIFS] section 2.2.4.47.2
9691 for details.
9693 req->cmd = SMBtrans2;
9695 if (req->wct < 8) {
9696 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9697 END_PROFILE(SMBtranss2);
9698 return;
9701 for (state = conn->pending_trans; state != NULL;
9702 state = state->next) {
9703 if (state->mid == req->mid) {
9704 break;
9708 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9709 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9710 END_PROFILE(SMBtranss2);
9711 return;
9714 /* Revise state->total_param and state->total_data in case they have
9715 changed downwards */
9717 if (SVAL(req->vwv+0, 0) < state->total_param)
9718 state->total_param = SVAL(req->vwv+0, 0);
9719 if (SVAL(req->vwv+1, 0) < state->total_data)
9720 state->total_data = SVAL(req->vwv+1, 0);
9722 pcnt = SVAL(req->vwv+2, 0);
9723 poff = SVAL(req->vwv+3, 0);
9724 pdisp = SVAL(req->vwv+4, 0);
9726 dcnt = SVAL(req->vwv+5, 0);
9727 doff = SVAL(req->vwv+6, 0);
9728 ddisp = SVAL(req->vwv+7, 0);
9730 state->received_param += pcnt;
9731 state->received_data += dcnt;
9733 if ((state->received_data > state->total_data) ||
9734 (state->received_param > state->total_param))
9735 goto bad_param;
9737 if (pcnt) {
9738 if (trans_oob(state->total_param, pdisp, pcnt)
9739 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9740 goto bad_param;
9742 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9745 if (dcnt) {
9746 if (trans_oob(state->total_data, ddisp, dcnt)
9747 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9748 goto bad_param;
9750 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9753 if ((state->received_param < state->total_param) ||
9754 (state->received_data < state->total_data)) {
9755 END_PROFILE(SMBtranss2);
9756 return;
9759 handle_trans2(conn, req, state);
9761 DLIST_REMOVE(conn->pending_trans, state);
9762 SAFE_FREE(state->data);
9763 SAFE_FREE(state->param);
9764 TALLOC_FREE(state);
9766 END_PROFILE(SMBtranss2);
9767 return;
9769 bad_param:
9771 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9772 DLIST_REMOVE(conn->pending_trans, state);
9773 SAFE_FREE(state->data);
9774 SAFE_FREE(state->param);
9775 TALLOC_FREE(state);
9776 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9777 END_PROFILE(SMBtranss2);
9778 return;