s4:dsdb/common: prepare dsdb_user_obj_set_defaults() for tombstone reanimation
[Samba.git] / source3 / smbd / trans2.c
blob9c0660b367488a61ec031d9387d37236d2baf4be
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 pathname 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 int ret = vfs_stat_smb_basename(conn,
72 smb_fname,
73 &sbuf);
74 if (ret == -1) {
75 return map_nt_error_from_unix(errno);
77 pst = &sbuf;
79 if (S_ISLNK(pst->st_ex_mode)) {
80 return NT_STATUS_ACCESS_DENIED;
82 return NT_STATUS_OK;
85 NTSTATUS check_access_fsp(const struct files_struct *fsp,
86 uint32_t access_mask)
88 if (!(fsp->access_mask & access_mask)) {
89 return NT_STATUS_ACCESS_DENIED;
91 return NT_STATUS_OK;
94 /********************************************************************
95 The canonical "check access" based on object handle or path function.
96 ********************************************************************/
98 NTSTATUS check_access(connection_struct *conn,
99 files_struct *fsp,
100 const struct smb_filename *smb_fname,
101 uint32_t access_mask)
103 NTSTATUS status;
105 if (fsp) {
106 status = check_access_fsp(fsp, access_mask);
107 } else {
108 status = smbd_check_access_rights(conn, smb_fname,
109 false, access_mask);
112 return status;
115 /********************************************************************
116 Roundup a value to the nearest allocation roundup size boundary.
117 Only do this for Windows clients.
118 ********************************************************************/
120 uint64_t smb_roundup(connection_struct *conn, uint64_t val)
122 uint64_t rval = lp_allocation_roundup_size(SNUM(conn));
124 /* Only roundup for Windows clients. */
125 enum remote_arch_types ra_type = get_remote_arch();
126 if (rval && (ra_type != RA_SAMBA) && (ra_type != RA_CIFSFS)) {
127 val = SMB_ROUNDUP(val,rval);
129 return val;
132 /********************************************************************
133 Create a 64 bit FileIndex. If the file is on the same device as
134 the root of the share, just return the 64-bit inode. If it isn't,
135 mangle as we used to do.
136 ********************************************************************/
138 uint64_t get_FileIndex(connection_struct *conn, const SMB_STRUCT_STAT *psbuf)
140 uint64_t file_index;
141 if (conn->base_share_dev == psbuf->st_ex_dev) {
142 return (uint64_t)psbuf->st_ex_ino;
144 file_index = ((psbuf->st_ex_ino) & UINT32_MAX); /* FileIndexLow */
145 file_index |= ((uint64_t)((psbuf->st_ex_dev) & UINT32_MAX)) << 32; /* FileIndexHigh */
146 return file_index;
149 /****************************************************************************
150 Utility functions for dealing with extended attributes.
151 ****************************************************************************/
153 /****************************************************************************
154 Refuse to allow clients to overwrite our private xattrs.
155 ****************************************************************************/
157 bool samba_private_attr_name(const char *unix_ea_name)
159 static const char * const prohibited_ea_names[] = {
160 SAMBA_POSIX_INHERITANCE_EA_NAME,
161 SAMBA_XATTR_DOS_ATTRIB,
162 SAMBA_XATTR_MARKER,
163 XATTR_NTACL_NAME,
164 NULL
167 int i;
169 for (i = 0; prohibited_ea_names[i]; i++) {
170 if (strequal( prohibited_ea_names[i], unix_ea_name))
171 return true;
173 if (strncasecmp_m(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX,
174 strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) {
175 return true;
177 return false;
180 /****************************************************************************
181 Get one EA value. Fill in a struct ea_struct.
182 ****************************************************************************/
184 NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn,
185 files_struct *fsp, const char *fname,
186 const char *ea_name, struct ea_struct *pea)
188 /* Get the value of this xattr. Max size is 64k. */
189 size_t attr_size = 256;
190 char *val = NULL;
191 ssize_t sizeret;
193 again:
195 val = talloc_realloc(mem_ctx, val, char, attr_size);
196 if (!val) {
197 return NT_STATUS_NO_MEMORY;
200 if (fsp && fsp->fh->fd != -1) {
201 sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
202 } else {
203 sizeret = SMB_VFS_GETXATTR(conn, fname, ea_name, val, attr_size);
206 if (sizeret == -1 && errno == ERANGE && attr_size != 65536) {
207 attr_size = 65536;
208 goto again;
211 if (sizeret == -1) {
212 return map_nt_error_from_unix(errno);
215 DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret));
216 dump_data(10, (uint8_t *)val, sizeret);
218 pea->flags = 0;
219 if (strnequal(ea_name, "user.", 5)) {
220 pea->name = talloc_strdup(mem_ctx, &ea_name[5]);
221 } else {
222 pea->name = talloc_strdup(mem_ctx, ea_name);
224 if (pea->name == NULL) {
225 TALLOC_FREE(val);
226 return NT_STATUS_NO_MEMORY;
228 pea->value.data = (unsigned char *)val;
229 pea->value.length = (size_t)sizeret;
230 return NT_STATUS_OK;
233 NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx,
234 connection_struct *conn,
235 files_struct *fsp,
236 const struct smb_filename *smb_fname,
237 char ***pnames,
238 size_t *pnum_names)
240 /* Get a list of all xattrs. Max namesize is 64k. */
241 size_t ea_namelist_size = 1024;
242 char *ea_namelist = NULL;
244 char *p;
245 char **names, **tmp;
246 size_t num_names;
247 ssize_t sizeret = -1;
248 NTSTATUS status;
250 if (pnames) {
251 *pnames = NULL;
253 *pnum_names = 0;
255 if (!lp_ea_support(SNUM(conn))) {
256 return NT_STATUS_OK;
259 status = refuse_symlink(conn, fsp, smb_fname);
260 if (!NT_STATUS_IS_OK(status)) {
262 * Just return no EA's on a symlink.
264 return NT_STATUS_OK;
268 * TALLOC the result early to get the talloc hierarchy right.
271 names = talloc_array(mem_ctx, char *, 1);
272 if (names == NULL) {
273 DEBUG(0, ("talloc failed\n"));
274 return NT_STATUS_NO_MEMORY;
277 while (ea_namelist_size <= 65536) {
279 ea_namelist = talloc_realloc(
280 names, ea_namelist, char, ea_namelist_size);
281 if (ea_namelist == NULL) {
282 DEBUG(0, ("talloc failed\n"));
283 TALLOC_FREE(names);
284 return NT_STATUS_NO_MEMORY;
287 if (fsp && fsp->fh->fd != -1) {
288 sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist,
289 ea_namelist_size);
290 } else {
291 sizeret = SMB_VFS_LISTXATTR(conn,
292 smb_fname->base_name,
293 ea_namelist,
294 ea_namelist_size);
297 if ((sizeret == -1) && (errno == ERANGE)) {
298 ea_namelist_size *= 2;
300 else {
301 break;
305 if (sizeret == -1) {
306 TALLOC_FREE(names);
307 return map_nt_error_from_unix(errno);
310 DEBUG(10, ("%s: ea_namelist size = %u\n",
311 __func__, (unsigned int)sizeret));
313 if (sizeret == 0) {
314 TALLOC_FREE(names);
315 return NT_STATUS_OK;
319 * Ensure the result is 0-terminated
322 if (ea_namelist[sizeret-1] != '\0') {
323 TALLOC_FREE(names);
324 return NT_STATUS_INTERNAL_ERROR;
328 * count the names
330 num_names = 0;
332 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
333 num_names += 1;
336 tmp = talloc_realloc(mem_ctx, names, char *, num_names);
337 if (tmp == NULL) {
338 DEBUG(0, ("talloc failed\n"));
339 TALLOC_FREE(names);
340 return NT_STATUS_NO_MEMORY;
343 names = tmp;
344 num_names = 0;
346 for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) {
347 names[num_names++] = p;
350 if (pnames) {
351 *pnames = names;
352 } else {
353 TALLOC_FREE(names);
355 *pnum_names = num_names;
356 return NT_STATUS_OK;
359 /****************************************************************************
360 Return a linked list of the total EA's. Plus the total size
361 ****************************************************************************/
363 static NTSTATUS get_ea_list_from_file_path(TALLOC_CTX *mem_ctx,
364 connection_struct *conn,
365 files_struct *fsp,
366 const struct smb_filename *smb_fname,
367 size_t *pea_total_len,
368 struct ea_list **ea_list)
370 /* Get a list of all xattrs. Max namesize is 64k. */
371 size_t i, num_names;
372 char **names;
373 struct ea_list *ea_list_head = NULL;
374 bool posix_pathnames = false;
375 NTSTATUS status;
377 *pea_total_len = 0;
378 *ea_list = NULL;
380 if (fsp) {
381 posix_pathnames =
382 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
383 } else {
384 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
387 status = get_ea_names_from_file(talloc_tos(),
388 conn,
389 fsp,
390 smb_fname,
391 &names,
392 &num_names);
394 if (!NT_STATUS_IS_OK(status)) {
395 return status;
398 if (num_names == 0) {
399 *ea_list = NULL;
400 return NT_STATUS_OK;
403 for (i=0; i<num_names; i++) {
404 struct ea_list *listp;
405 fstring dos_ea_name;
407 if (strnequal(names[i], "system.", 7)
408 || samba_private_attr_name(names[i]))
409 continue;
412 * Filter out any underlying POSIX EA names
413 * that a Windows client can't handle.
415 if (!posix_pathnames &&
416 is_invalid_windows_ea_name(names[i])) {
417 continue;
420 listp = talloc(mem_ctx, struct ea_list);
421 if (listp == NULL) {
422 return NT_STATUS_NO_MEMORY;
425 status = get_ea_value(listp,
426 conn,
427 fsp,
428 smb_fname->base_name,
429 names[i],
430 &listp->ea);
432 if (!NT_STATUS_IS_OK(status)) {
433 TALLOC_FREE(listp);
434 return status;
437 if (listp->ea.value.length == 0) {
439 * We can never return a zero length EA.
440 * Windows reports the EA's as corrupted.
442 TALLOC_FREE(listp);
443 continue;
446 push_ascii_fstring(dos_ea_name, listp->ea.name);
448 *pea_total_len +=
449 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
451 DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len "
452 "= %u\n", (unsigned int)*pea_total_len, dos_ea_name,
453 (unsigned int)listp->ea.value.length));
455 DLIST_ADD_END(ea_list_head, listp);
459 /* Add on 4 for total length. */
460 if (*pea_total_len) {
461 *pea_total_len += 4;
464 DEBUG(10, ("get_ea_list_from_file: total_len = %u\n",
465 (unsigned int)*pea_total_len));
467 *ea_list = ea_list_head;
468 return NT_STATUS_OK;
471 static NTSTATUS get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp,
472 const struct smb_filename *smb_fname, size_t *pea_total_len, struct ea_list **ea_list)
474 *pea_total_len = 0;
475 *ea_list = NULL;
477 if (!lp_ea_support(SNUM(conn))) {
478 return NT_STATUS_OK;
481 if (is_ntfs_stream_smb_fname(smb_fname)) {
482 return NT_STATUS_INVALID_PARAMETER;
485 return get_ea_list_from_file_path(mem_ctx,
486 conn,
487 fsp,
488 smb_fname,
489 pea_total_len,
490 ea_list);
493 /****************************************************************************
494 Fill a qfilepathinfo buffer with EA's. Returns the length of the buffer
495 that was filled.
496 ****************************************************************************/
498 static unsigned int fill_ea_buffer(TALLOC_CTX *mem_ctx, char *pdata, unsigned int total_data_size,
499 connection_struct *conn, struct ea_list *ea_list)
501 unsigned int ret_data_size = 4;
502 char *p = pdata;
504 SMB_ASSERT(total_data_size >= 4);
506 if (!lp_ea_support(SNUM(conn))) {
507 SIVAL(pdata,4,0);
508 return 4;
511 for (p = pdata + 4; ea_list; ea_list = ea_list->next) {
512 size_t dos_namelen;
513 fstring dos_ea_name;
514 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
515 dos_namelen = strlen(dos_ea_name);
516 if (dos_namelen > 255 || dos_namelen == 0) {
517 break;
519 if (ea_list->ea.value.length > 65535) {
520 break;
522 if (4 + dos_namelen + 1 + ea_list->ea.value.length > total_data_size) {
523 break;
526 /* We know we have room. */
527 SCVAL(p,0,ea_list->ea.flags);
528 SCVAL(p,1,dos_namelen);
529 SSVAL(p,2,ea_list->ea.value.length);
530 strlcpy(p+4, dos_ea_name, dos_namelen+1);
531 memcpy( p + 4 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
533 total_data_size -= 4 + dos_namelen + 1 + ea_list->ea.value.length;
534 p += 4 + dos_namelen + 1 + ea_list->ea.value.length;
537 ret_data_size = PTR_DIFF(p, pdata);
538 DEBUG(10,("fill_ea_buffer: data_size = %u\n", ret_data_size ));
539 SIVAL(pdata,0,ret_data_size);
540 return ret_data_size;
543 static NTSTATUS fill_ea_chained_buffer(TALLOC_CTX *mem_ctx,
544 char *pdata,
545 unsigned int total_data_size,
546 unsigned int *ret_data_size,
547 connection_struct *conn,
548 struct ea_list *ea_list)
550 uint8_t *p = (uint8_t *)pdata;
551 uint8_t *last_start = NULL;
552 bool do_store_data = (pdata != NULL);
554 *ret_data_size = 0;
556 if (!lp_ea_support(SNUM(conn))) {
557 return NT_STATUS_NO_EAS_ON_FILE;
560 for (; ea_list; ea_list = ea_list->next) {
561 size_t dos_namelen;
562 fstring dos_ea_name;
563 size_t this_size;
564 size_t pad = 0;
566 if (last_start != NULL && do_store_data) {
567 SIVAL(last_start, 0, PTR_DIFF(p, last_start));
569 last_start = p;
571 push_ascii_fstring(dos_ea_name, ea_list->ea.name);
572 dos_namelen = strlen(dos_ea_name);
573 if (dos_namelen > 255 || dos_namelen == 0) {
574 return NT_STATUS_INTERNAL_ERROR;
576 if (ea_list->ea.value.length > 65535) {
577 return NT_STATUS_INTERNAL_ERROR;
580 this_size = 0x08 + dos_namelen + 1 + ea_list->ea.value.length;
582 if (ea_list->next) {
583 pad = (4 - (this_size % 4)) % 4;
584 this_size += pad;
587 if (do_store_data) {
588 if (this_size > total_data_size) {
589 return NT_STATUS_INFO_LENGTH_MISMATCH;
592 /* We know we have room. */
593 SIVAL(p, 0x00, 0); /* next offset */
594 SCVAL(p, 0x04, ea_list->ea.flags);
595 SCVAL(p, 0x05, dos_namelen);
596 SSVAL(p, 0x06, ea_list->ea.value.length);
597 strlcpy((char *)(p+0x08), dos_ea_name, dos_namelen+1);
598 memcpy(p + 0x08 + dos_namelen + 1, ea_list->ea.value.data, ea_list->ea.value.length);
599 if (pad) {
600 memset(p + 0x08 + dos_namelen + 1 + ea_list->ea.value.length,
601 '\0',
602 pad);
604 total_data_size -= this_size;
607 p += this_size;
610 *ret_data_size = PTR_DIFF(p, pdata);
611 DEBUG(10,("fill_ea_chained_buffer: data_size = %u\n", *ret_data_size));
612 return NT_STATUS_OK;
615 static unsigned int estimate_ea_size(connection_struct *conn, files_struct *fsp, const struct smb_filename *smb_fname)
617 size_t total_ea_len = 0;
618 TALLOC_CTX *mem_ctx;
619 struct ea_list *ea_list = NULL;
621 if (!lp_ea_support(SNUM(conn))) {
622 return 0;
624 mem_ctx = talloc_stackframe();
626 /* If this is a stream fsp, then we need to instead find the
627 * estimated ea len from the main file, not the stream
628 * (streams cannot have EAs), but the estimate isn't just 0 in
629 * this case! */
630 if (is_ntfs_stream_smb_fname(smb_fname)) {
631 fsp = NULL;
633 (void)get_ea_list_from_file_path(mem_ctx,
634 conn,
635 fsp,
636 smb_fname,
637 &total_ea_len,
638 &ea_list);
639 if(conn->sconn->using_smb2) {
640 NTSTATUS status;
641 unsigned int ret_data_size;
643 * We're going to be using fill_ea_chained_buffer() to
644 * marshall EA's - this size is significantly larger
645 * than the SMB1 buffer. Re-calculate the size without
646 * marshalling.
648 status = fill_ea_chained_buffer(mem_ctx,
649 NULL,
651 &ret_data_size,
652 conn,
653 ea_list);
654 if (!NT_STATUS_IS_OK(status)) {
655 ret_data_size = 0;
657 total_ea_len = ret_data_size;
659 TALLOC_FREE(mem_ctx);
660 return total_ea_len;
663 /****************************************************************************
664 Ensure the EA name is case insensitive by matching any existing EA name.
665 ****************************************************************************/
667 static void canonicalize_ea_name(connection_struct *conn,
668 files_struct *fsp,
669 const struct smb_filename *smb_fname,
670 fstring unix_ea_name)
672 size_t total_ea_len;
673 TALLOC_CTX *mem_ctx = talloc_tos();
674 struct ea_list *ea_list;
675 NTSTATUS status = get_ea_list_from_file_path(mem_ctx,
676 conn,
677 fsp,
678 smb_fname,
679 &total_ea_len,
680 &ea_list);
681 if (!NT_STATUS_IS_OK(status)) {
682 return;
685 for (; ea_list; ea_list = ea_list->next) {
686 if (strequal(&unix_ea_name[5], ea_list->ea.name)) {
687 DEBUG(10,("canonicalize_ea_name: %s -> %s\n",
688 &unix_ea_name[5], ea_list->ea.name));
689 strlcpy(&unix_ea_name[5], ea_list->ea.name, sizeof(fstring)-5);
690 break;
695 /****************************************************************************
696 Set or delete an extended attribute.
697 ****************************************************************************/
699 NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
700 const struct smb_filename *smb_fname, struct ea_list *ea_list)
702 NTSTATUS status;
703 bool posix_pathnames = false;
705 if (!lp_ea_support(SNUM(conn))) {
706 return NT_STATUS_EAS_NOT_SUPPORTED;
709 if (fsp) {
710 posix_pathnames =
711 (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
712 } else {
713 posix_pathnames = (smb_fname->flags & SMB_FILENAME_POSIX_PATH);
716 status = refuse_symlink(conn, fsp, smb_fname);
717 if (!NT_STATUS_IS_OK(status)) {
718 return status;
721 status = check_access(conn, fsp, smb_fname, FILE_WRITE_EA);
722 if (!NT_STATUS_IS_OK(status)) {
723 return status;
726 /* Setting EAs on streams isn't supported. */
727 if (is_ntfs_stream_smb_fname(smb_fname)) {
728 return NT_STATUS_INVALID_PARAMETER;
732 * Filter out invalid Windows EA names - before
733 * we set *any* of them.
736 if (!posix_pathnames && ea_list_has_invalid_name(ea_list)) {
737 return STATUS_INVALID_EA_NAME;
740 for (;ea_list; ea_list = ea_list->next) {
741 int ret;
742 fstring unix_ea_name;
744 fstrcpy(unix_ea_name, "user."); /* All EA's must start with user. */
745 fstrcat(unix_ea_name, ea_list->ea.name);
747 canonicalize_ea_name(conn,
748 fsp,
749 smb_fname,
750 unix_ea_name);
752 DEBUG(10,("set_ea: ea_name %s ealen = %u\n", unix_ea_name, (unsigned int)ea_list->ea.value.length));
754 if (samba_private_attr_name(unix_ea_name)) {
755 DEBUG(10,("set_ea: ea name %s is a private Samba name.\n", unix_ea_name));
756 return NT_STATUS_ACCESS_DENIED;
759 if (ea_list->ea.value.length == 0) {
760 /* Remove the attribute. */
761 if (fsp && (fsp->fh->fd != -1)) {
762 DEBUG(10,("set_ea: deleting ea name %s on "
763 "file %s by file descriptor.\n",
764 unix_ea_name, fsp_str_dbg(fsp)));
765 ret = SMB_VFS_FREMOVEXATTR(fsp, unix_ea_name);
766 } else {
767 DEBUG(10,("set_ea: deleting ea name %s on file %s.\n",
768 unix_ea_name, smb_fname->base_name));
769 ret = SMB_VFS_REMOVEXATTR(conn,
770 smb_fname->base_name,
771 unix_ea_name);
773 #ifdef ENOATTR
774 /* Removing a non existent attribute always succeeds. */
775 if (ret == -1 && errno == ENOATTR) {
776 DEBUG(10,("set_ea: deleting ea name %s didn't exist - succeeding by default.\n",
777 unix_ea_name));
778 ret = 0;
780 #endif
781 } else {
782 if (fsp && (fsp->fh->fd != -1)) {
783 DEBUG(10,("set_ea: setting ea name %s on file "
784 "%s by file descriptor.\n",
785 unix_ea_name, fsp_str_dbg(fsp)));
786 ret = SMB_VFS_FSETXATTR(fsp, unix_ea_name,
787 ea_list->ea.value.data, ea_list->ea.value.length, 0);
788 } else {
789 DEBUG(10,("set_ea: setting ea name %s on file %s.\n",
790 unix_ea_name, smb_fname->base_name));
791 ret = SMB_VFS_SETXATTR(conn,
792 smb_fname->base_name,
793 unix_ea_name,
794 ea_list->ea.value.data,
795 ea_list->ea.value.length,
800 if (ret == -1) {
801 #ifdef ENOTSUP
802 if (errno == ENOTSUP) {
803 return NT_STATUS_EAS_NOT_SUPPORTED;
805 #endif
806 return map_nt_error_from_unix(errno);
810 return NT_STATUS_OK;
812 /****************************************************************************
813 Read a list of EA names from an incoming data buffer. Create an ea_list with them.
814 ****************************************************************************/
816 static struct ea_list *read_ea_name_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
818 struct ea_list *ea_list_head = NULL;
819 size_t converted_size, offset = 0;
821 while (offset + 2 < data_size) {
822 struct ea_list *eal = talloc_zero(ctx, struct ea_list);
823 unsigned int namelen = CVAL(pdata,offset);
825 offset++; /* Go past the namelen byte. */
827 /* integer wrap paranioa. */
828 if ((offset + namelen < offset) || (offset + namelen < namelen) ||
829 (offset > data_size) || (namelen > data_size) ||
830 (offset + namelen >= data_size)) {
831 break;
833 /* Ensure the name is null terminated. */
834 if (pdata[offset + namelen] != '\0') {
835 return NULL;
837 if (!pull_ascii_talloc(ctx, &eal->ea.name, &pdata[offset],
838 &converted_size)) {
839 DEBUG(0,("read_ea_name_list: pull_ascii_talloc "
840 "failed: %s", strerror(errno)));
842 if (!eal->ea.name) {
843 return NULL;
846 offset += (namelen + 1); /* Go past the name + terminating zero. */
847 DLIST_ADD_END(ea_list_head, eal);
848 DEBUG(10,("read_ea_name_list: read ea name %s\n", eal->ea.name));
851 return ea_list_head;
854 /****************************************************************************
855 Read a list of EA names and data from an incoming data buffer. Create an ea_list with them.
856 ****************************************************************************/
858 static struct ea_list *read_ea_list(TALLOC_CTX *ctx, const char *pdata, size_t data_size)
860 struct ea_list *ea_list_head = NULL;
861 size_t offset = 0;
862 size_t bytes_used = 0;
864 while (offset < data_size) {
865 struct ea_list *eal = read_ea_list_entry(ctx, pdata + offset, data_size - offset, &bytes_used);
867 if (!eal) {
868 return NULL;
871 DLIST_ADD_END(ea_list_head, eal);
872 offset += bytes_used;
875 return ea_list_head;
878 /****************************************************************************
879 Count the total EA size needed.
880 ****************************************************************************/
882 static size_t ea_list_size(struct ea_list *ealist)
884 fstring dos_ea_name;
885 struct ea_list *listp;
886 size_t ret = 0;
888 for (listp = ealist; listp; listp = listp->next) {
889 push_ascii_fstring(dos_ea_name, listp->ea.name);
890 ret += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length;
892 /* Add on 4 for total length. */
893 if (ret) {
894 ret += 4;
897 return ret;
900 /****************************************************************************
901 Return a union of EA's from a file list and a list of names.
902 The TALLOC context for the two lists *MUST* be identical as we steal
903 memory from one list to add to another. JRA.
904 ****************************************************************************/
906 static struct ea_list *ea_list_union(struct ea_list *name_list, struct ea_list *file_list, size_t *total_ea_len)
908 struct ea_list *nlistp, *flistp;
910 for (nlistp = name_list; nlistp; nlistp = nlistp->next) {
911 for (flistp = file_list; flistp; flistp = flistp->next) {
912 if (strequal(nlistp->ea.name, flistp->ea.name)) {
913 break;
917 if (flistp) {
918 /* Copy the data from this entry. */
919 nlistp->ea.flags = flistp->ea.flags;
920 nlistp->ea.value = flistp->ea.value;
921 } else {
922 /* Null entry. */
923 nlistp->ea.flags = 0;
924 ZERO_STRUCT(nlistp->ea.value);
928 *total_ea_len = ea_list_size(name_list);
929 return name_list;
932 /****************************************************************************
933 Send the required number of replies back.
934 We assume all fields other than the data fields are
935 set correctly for the type of call.
936 HACK ! Always assumes smb_setup field is zero.
937 ****************************************************************************/
939 void send_trans2_replies(connection_struct *conn,
940 struct smb_request *req,
941 NTSTATUS status,
942 const char *params,
943 int paramsize,
944 const char *pdata,
945 int datasize,
946 int max_data_bytes)
948 /* As we are using a protocol > LANMAN1 then the max_send
949 variable must have been set in the sessetupX call.
950 This takes precedence over the max_xmit field in the
951 global struct. These different max_xmit variables should
952 be merged as this is now too confusing */
954 int data_to_send = datasize;
955 int params_to_send = paramsize;
956 int useable_space;
957 const char *pp = params;
958 const char *pd = pdata;
959 int params_sent_thistime, data_sent_thistime, total_sent_thistime;
960 int alignment_offset = 1; /* JRA. This used to be 3. Set to 1 to make netmon parse ok. */
961 int data_alignment_offset = 0;
962 bool overflow = False;
963 struct smbXsrv_connection *xconn = req->xconn;
964 int max_send = xconn->smb1.sessions.max_send;
966 /* Modify the data_to_send and datasize and set the error if
967 we're trying to send more than max_data_bytes. We still send
968 the part of the packet(s) that fit. Strange, but needed
969 for OS/2. */
971 if (max_data_bytes > 0 && datasize > max_data_bytes) {
972 DEBUG(5,("send_trans2_replies: max_data_bytes %d exceeded by data %d\n",
973 max_data_bytes, datasize ));
974 datasize = data_to_send = max_data_bytes;
975 overflow = True;
978 /* If there genuinely are no parameters or data to send just send the empty packet */
980 if(params_to_send == 0 && data_to_send == 0) {
981 reply_outbuf(req, 10, 0);
982 if (NT_STATUS_V(status)) {
983 uint8_t eclass;
984 uint32_t ecode;
985 ntstatus_to_dos(status, &eclass, &ecode);
986 error_packet_set((char *)req->outbuf,
987 eclass, ecode, status,
988 __LINE__,__FILE__);
990 show_msg((char *)req->outbuf);
991 if (!srv_send_smb(xconn,
992 (char *)req->outbuf,
993 true, req->seqnum+1,
994 IS_CONN_ENCRYPTED(conn),
995 &req->pcd)) {
996 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
998 TALLOC_FREE(req->outbuf);
999 return;
1002 /* When sending params and data ensure that both are nicely aligned */
1003 /* Only do this alignment when there is also data to send - else
1004 can cause NT redirector problems. */
1006 if (((params_to_send % 4) != 0) && (data_to_send != 0))
1007 data_alignment_offset = 4 - (params_to_send % 4);
1009 /* Space is bufsize minus Netbios over TCP header minus SMB header */
1010 /* The alignment_offset is to align the param bytes on an even byte
1011 boundary. NT 4.0 Beta needs this to work correctly. */
1013 useable_space = max_send - (smb_size
1014 + 2 * 10 /* wct */
1015 + alignment_offset
1016 + data_alignment_offset);
1018 if (useable_space < 0) {
1019 DEBUG(0, ("send_trans2_replies failed sanity useable_space "
1020 "= %d!!!", useable_space));
1021 exit_server_cleanly("send_trans2_replies: Not enough space");
1024 while (params_to_send || data_to_send) {
1025 /* Calculate whether we will totally or partially fill this packet */
1027 total_sent_thistime = params_to_send + data_to_send;
1029 /* We can never send more than useable_space */
1031 * Note that 'useable_space' does not include the alignment offsets,
1032 * but we must include the alignment offsets in the calculation of
1033 * the length of the data we send over the wire, as the alignment offsets
1034 * are sent here. Fix from Marc_Jacobsen@hp.com.
1037 total_sent_thistime = MIN(total_sent_thistime, useable_space);
1039 reply_outbuf(req, 10, total_sent_thistime + alignment_offset
1040 + data_alignment_offset);
1042 /* Set total params and data to be sent */
1043 SSVAL(req->outbuf,smb_tprcnt,paramsize);
1044 SSVAL(req->outbuf,smb_tdrcnt,datasize);
1046 /* Calculate how many parameters and data we can fit into
1047 * this packet. Parameters get precedence
1050 params_sent_thistime = MIN(params_to_send,useable_space);
1051 data_sent_thistime = useable_space - params_sent_thistime;
1052 data_sent_thistime = MIN(data_sent_thistime,data_to_send);
1054 SSVAL(req->outbuf,smb_prcnt, params_sent_thistime);
1056 /* smb_proff is the offset from the start of the SMB header to the
1057 parameter bytes, however the first 4 bytes of outbuf are
1058 the Netbios over TCP header. Thus use smb_base() to subtract
1059 them from the calculation */
1061 SSVAL(req->outbuf,smb_proff,
1062 ((smb_buf(req->outbuf)+alignment_offset)
1063 - smb_base(req->outbuf)));
1065 if(params_sent_thistime == 0)
1066 SSVAL(req->outbuf,smb_prdisp,0);
1067 else
1068 /* Absolute displacement of param bytes sent in this packet */
1069 SSVAL(req->outbuf,smb_prdisp,pp - params);
1071 SSVAL(req->outbuf,smb_drcnt, data_sent_thistime);
1072 if(data_sent_thistime == 0) {
1073 SSVAL(req->outbuf,smb_droff,0);
1074 SSVAL(req->outbuf,smb_drdisp, 0);
1075 } else {
1076 /* The offset of the data bytes is the offset of the
1077 parameter bytes plus the number of parameters being sent this time */
1078 SSVAL(req->outbuf, smb_droff,
1079 ((smb_buf(req->outbuf)+alignment_offset)
1080 - smb_base(req->outbuf))
1081 + params_sent_thistime + data_alignment_offset);
1082 SSVAL(req->outbuf,smb_drdisp, pd - pdata);
1085 /* Initialize the padding for alignment */
1087 if (alignment_offset != 0) {
1088 memset(smb_buf(req->outbuf), 0, alignment_offset);
1091 /* Copy the param bytes into the packet */
1093 if(params_sent_thistime) {
1094 memcpy((smb_buf(req->outbuf)+alignment_offset), pp,
1095 params_sent_thistime);
1098 /* Copy in the data bytes */
1099 if(data_sent_thistime) {
1100 if (data_alignment_offset != 0) {
1101 memset((smb_buf(req->outbuf)+alignment_offset+
1102 params_sent_thistime), 0,
1103 data_alignment_offset);
1105 memcpy(smb_buf(req->outbuf)+alignment_offset
1106 +params_sent_thistime+data_alignment_offset,
1107 pd,data_sent_thistime);
1110 DEBUG(9,("t2_rep: params_sent_thistime = %d, data_sent_thistime = %d, useable_space = %d\n",
1111 params_sent_thistime, data_sent_thistime, useable_space));
1112 DEBUG(9,("t2_rep: params_to_send = %d, data_to_send = %d, paramsize = %d, datasize = %d\n",
1113 params_to_send, data_to_send, paramsize, datasize));
1115 if (overflow) {
1116 error_packet_set((char *)req->outbuf,
1117 ERRDOS,ERRbufferoverflow,
1118 STATUS_BUFFER_OVERFLOW,
1119 __LINE__,__FILE__);
1120 } else if (NT_STATUS_V(status)) {
1121 uint8_t eclass;
1122 uint32_t ecode;
1123 ntstatus_to_dos(status, &eclass, &ecode);
1124 error_packet_set((char *)req->outbuf,
1125 eclass, ecode, status,
1126 __LINE__,__FILE__);
1129 /* Send the packet */
1130 show_msg((char *)req->outbuf);
1131 if (!srv_send_smb(xconn,
1132 (char *)req->outbuf,
1133 true, req->seqnum+1,
1134 IS_CONN_ENCRYPTED(conn),
1135 &req->pcd))
1136 exit_server_cleanly("send_trans2_replies: srv_send_smb failed.");
1138 TALLOC_FREE(req->outbuf);
1140 pp += params_sent_thistime;
1141 pd += data_sent_thistime;
1143 params_to_send -= params_sent_thistime;
1144 data_to_send -= data_sent_thistime;
1146 /* Sanity check */
1147 if(params_to_send < 0 || data_to_send < 0) {
1148 DEBUG(0,("send_trans2_replies failed sanity check pts = %d, dts = %d\n!!!",
1149 params_to_send, data_to_send));
1150 return;
1154 return;
1157 /****************************************************************************
1158 Reply to a TRANSACT2_OPEN.
1159 ****************************************************************************/
1161 static void call_trans2open(connection_struct *conn,
1162 struct smb_request *req,
1163 char **pparams, int total_params,
1164 char **ppdata, int total_data,
1165 unsigned int max_data_bytes)
1167 struct smb_filename *smb_fname = NULL;
1168 char *params = *pparams;
1169 char *pdata = *ppdata;
1170 int deny_mode;
1171 int32_t open_attr;
1172 bool oplock_request;
1173 #if 0
1174 bool return_additional_info;
1175 int16 open_sattr;
1176 time_t open_time;
1177 #endif
1178 int open_ofun;
1179 uint32_t open_size;
1180 char *pname;
1181 char *fname = NULL;
1182 off_t size=0;
1183 int fattr=0,mtime=0;
1184 SMB_INO_T inode = 0;
1185 int smb_action = 0;
1186 files_struct *fsp;
1187 struct ea_list *ea_list = NULL;
1188 uint16_t flags = 0;
1189 NTSTATUS status;
1190 uint32_t access_mask;
1191 uint32_t share_mode;
1192 uint32_t create_disposition;
1193 uint32_t create_options = 0;
1194 uint32_t private_flags = 0;
1195 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
1196 TALLOC_CTX *ctx = talloc_tos();
1199 * Ensure we have enough parameters to perform the operation.
1202 if (total_params < 29) {
1203 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1204 goto out;
1207 flags = SVAL(params, 0);
1208 deny_mode = SVAL(params, 2);
1209 open_attr = SVAL(params,6);
1210 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
1211 if (oplock_request) {
1212 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
1215 #if 0
1216 return_additional_info = BITSETW(params,0);
1217 open_sattr = SVAL(params, 4);
1218 open_time = make_unix_date3(params+8);
1219 #endif
1220 open_ofun = SVAL(params,12);
1221 open_size = IVAL(params,14);
1222 pname = &params[28];
1224 if (IS_IPC(conn)) {
1225 reply_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
1226 goto out;
1229 if (req->posix_pathnames) {
1230 srvstr_get_path_posix(ctx,
1231 params,
1232 req->flags2,
1233 &fname,
1234 pname,
1235 total_params - 28,
1236 STR_TERMINATE,
1237 &status);
1238 } else {
1239 srvstr_get_path(ctx,
1240 params,
1241 req->flags2,
1242 &fname,
1243 pname,
1244 total_params - 28,
1245 STR_TERMINATE,
1246 &status);
1248 if (!NT_STATUS_IS_OK(status)) {
1249 reply_nterror(req, status);
1250 goto out;
1253 DEBUG(3,("call_trans2open %s deny_mode=0x%x attr=%d ofun=0x%x size=%d\n",
1254 fname, (unsigned int)deny_mode, (unsigned int)open_attr,
1255 (unsigned int)open_ofun, open_size));
1257 status = filename_convert(ctx,
1258 conn,
1259 req->flags2 & FLAGS2_DFS_PATHNAMES,
1260 fname,
1261 ucf_flags,
1262 NULL,
1263 &smb_fname);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
1266 reply_botherror(req,
1267 NT_STATUS_PATH_NOT_COVERED,
1268 ERRSRV, ERRbadpath);
1269 goto out;
1271 reply_nterror(req, status);
1272 goto out;
1275 if (open_ofun == 0) {
1276 reply_nterror(req, NT_STATUS_OBJECT_NAME_COLLISION);
1277 goto out;
1280 if (!map_open_params_to_ntcreate(smb_fname->base_name, deny_mode,
1281 open_ofun,
1282 &access_mask, &share_mode,
1283 &create_disposition,
1284 &create_options,
1285 &private_flags)) {
1286 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1287 goto out;
1290 /* Any data in this call is an EA list. */
1291 if (total_data && (total_data != 4)) {
1292 if (total_data < 10) {
1293 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1294 goto out;
1297 if (IVAL(pdata,0) > total_data) {
1298 DEBUG(10,("call_trans2open: bad total data size (%u) > %u\n",
1299 IVAL(pdata,0), (unsigned int)total_data));
1300 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1301 goto out;
1304 ea_list = read_ea_list(talloc_tos(), pdata + 4,
1305 total_data - 4);
1306 if (!ea_list) {
1307 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
1308 goto out;
1311 if (!lp_ea_support(SNUM(conn))) {
1312 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
1313 goto out;
1316 if (!req->posix_pathnames &&
1317 ea_list_has_invalid_name(ea_list)) {
1318 int param_len = 30;
1319 *pparams = (char *)SMB_REALLOC(*pparams, param_len);
1320 if(*pparams == NULL ) {
1321 reply_nterror(req, NT_STATUS_NO_MEMORY);
1322 goto out;
1324 params = *pparams;
1325 memset(params, '\0', param_len);
1326 send_trans2_replies(conn, req, STATUS_INVALID_EA_NAME,
1327 params, param_len, NULL, 0, max_data_bytes);
1328 goto out;
1332 status = SMB_VFS_CREATE_FILE(
1333 conn, /* conn */
1334 req, /* req */
1335 0, /* root_dir_fid */
1336 smb_fname, /* fname */
1337 access_mask, /* access_mask */
1338 share_mode, /* share_access */
1339 create_disposition, /* create_disposition*/
1340 create_options, /* create_options */
1341 open_attr, /* file_attributes */
1342 oplock_request, /* oplock_request */
1343 NULL, /* lease */
1344 open_size, /* allocation_size */
1345 private_flags,
1346 NULL, /* sd */
1347 ea_list, /* ea_list */
1348 &fsp, /* result */
1349 &smb_action, /* psbuf */
1350 NULL, NULL); /* create context */
1352 if (!NT_STATUS_IS_OK(status)) {
1353 if (open_was_deferred(req->xconn, req->mid)) {
1354 /* We have re-scheduled this call. */
1355 goto out;
1357 reply_openerror(req, status);
1358 goto out;
1361 size = get_file_size_stat(&smb_fname->st);
1362 fattr = dos_mode(conn, smb_fname);
1363 mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
1364 inode = smb_fname->st.st_ex_ino;
1365 if (fattr & FILE_ATTRIBUTE_DIRECTORY) {
1366 close_file(req, fsp, ERROR_CLOSE);
1367 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
1368 goto out;
1371 /* Realloc the size of parameters and data we will return */
1372 *pparams = (char *)SMB_REALLOC(*pparams, 30);
1373 if(*pparams == NULL ) {
1374 reply_nterror(req, NT_STATUS_NO_MEMORY);
1375 goto out;
1377 params = *pparams;
1379 SSVAL(params,0,fsp->fnum);
1380 SSVAL(params,2,fattr);
1381 srv_put_dos_date2(params,4, mtime);
1382 SIVAL(params,8, (uint32_t)size);
1383 SSVAL(params,12,deny_mode);
1384 SSVAL(params,14,0); /* open_type - file or directory. */
1385 SSVAL(params,16,0); /* open_state - only valid for IPC device. */
1387 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
1388 smb_action |= EXTENDED_OPLOCK_GRANTED;
1391 SSVAL(params,18,smb_action);
1394 * WARNING - this may need to be changed if SMB_INO_T <> 4 bytes.
1396 SIVAL(params,20,inode);
1397 SSVAL(params,24,0); /* Padding. */
1398 if (flags & 8) {
1399 uint32_t ea_size = estimate_ea_size(conn, fsp,
1400 smb_fname);
1401 SIVAL(params, 26, ea_size);
1402 } else {
1403 SIVAL(params, 26, 0);
1406 /* Send the required number of replies */
1407 send_trans2_replies(conn, req, NT_STATUS_OK, params, 30, *ppdata, 0, max_data_bytes);
1408 out:
1409 TALLOC_FREE(smb_fname);
1412 /*********************************************************
1413 Routine to check if a given string matches exactly.
1414 as a special case a mask of "." does NOT match. That
1415 is required for correct wildcard semantics
1416 Case can be significant or not.
1417 **********************************************************/
1419 static bool exact_match(bool has_wild,
1420 bool case_sensitive,
1421 const char *str,
1422 const char *mask)
1424 if (mask[0] == '.' && mask[1] == 0) {
1425 return false;
1428 if (has_wild) {
1429 return false;
1432 if (case_sensitive) {
1433 return strcmp(str,mask)==0;
1434 } else {
1435 return strcasecmp_m(str,mask) == 0;
1439 /****************************************************************************
1440 Return the filetype for UNIX extensions.
1441 ****************************************************************************/
1443 static uint32_t unix_filetype(mode_t mode)
1445 if(S_ISREG(mode))
1446 return UNIX_TYPE_FILE;
1447 else if(S_ISDIR(mode))
1448 return UNIX_TYPE_DIR;
1449 #ifdef S_ISLNK
1450 else if(S_ISLNK(mode))
1451 return UNIX_TYPE_SYMLINK;
1452 #endif
1453 #ifdef S_ISCHR
1454 else if(S_ISCHR(mode))
1455 return UNIX_TYPE_CHARDEV;
1456 #endif
1457 #ifdef S_ISBLK
1458 else if(S_ISBLK(mode))
1459 return UNIX_TYPE_BLKDEV;
1460 #endif
1461 #ifdef S_ISFIFO
1462 else if(S_ISFIFO(mode))
1463 return UNIX_TYPE_FIFO;
1464 #endif
1465 #ifdef S_ISSOCK
1466 else if(S_ISSOCK(mode))
1467 return UNIX_TYPE_SOCKET;
1468 #endif
1470 DEBUG(0,("unix_filetype: unknown filetype %u\n", (unsigned)mode));
1471 return UNIX_TYPE_UNKNOWN;
1474 /****************************************************************************
1475 Map wire perms onto standard UNIX permissions. Obey share restrictions.
1476 ****************************************************************************/
1478 enum perm_type { PERM_NEW_FILE, PERM_NEW_DIR, PERM_EXISTING_FILE, PERM_EXISTING_DIR};
1480 static NTSTATUS unix_perms_from_wire( connection_struct *conn,
1481 const SMB_STRUCT_STAT *psbuf,
1482 uint32_t perms,
1483 enum perm_type ptype,
1484 mode_t *ret_perms)
1486 mode_t ret = 0;
1488 if (perms == SMB_MODE_NO_CHANGE) {
1489 if (!VALID_STAT(*psbuf)) {
1490 return NT_STATUS_INVALID_PARAMETER;
1491 } else {
1492 *ret_perms = psbuf->st_ex_mode;
1493 return NT_STATUS_OK;
1497 ret |= ((perms & UNIX_X_OTH ) ? S_IXOTH : 0);
1498 ret |= ((perms & UNIX_W_OTH ) ? S_IWOTH : 0);
1499 ret |= ((perms & UNIX_R_OTH ) ? S_IROTH : 0);
1500 ret |= ((perms & UNIX_X_GRP ) ? S_IXGRP : 0);
1501 ret |= ((perms & UNIX_W_GRP ) ? S_IWGRP : 0);
1502 ret |= ((perms & UNIX_R_GRP ) ? S_IRGRP : 0);
1503 ret |= ((perms & UNIX_X_USR ) ? S_IXUSR : 0);
1504 ret |= ((perms & UNIX_W_USR ) ? S_IWUSR : 0);
1505 ret |= ((perms & UNIX_R_USR ) ? S_IRUSR : 0);
1506 #ifdef S_ISVTX
1507 ret |= ((perms & UNIX_STICKY ) ? S_ISVTX : 0);
1508 #endif
1509 #ifdef S_ISGID
1510 ret |= ((perms & UNIX_SET_GID ) ? S_ISGID : 0);
1511 #endif
1512 #ifdef S_ISUID
1513 ret |= ((perms & UNIX_SET_UID ) ? S_ISUID : 0);
1514 #endif
1516 if (ptype == PERM_NEW_FILE) {
1518 * "create mask"/"force create mode" are
1519 * only applied to new files, not existing ones.
1521 ret &= lp_create_mask(SNUM(conn));
1522 /* Add in force bits */
1523 ret |= lp_force_create_mode(SNUM(conn));
1524 } else if (ptype == PERM_NEW_DIR) {
1526 * "directory mask"/"force directory mode" are
1527 * only applied to new directories, not existing ones.
1529 ret &= lp_directory_mask(SNUM(conn));
1530 /* Add in force bits */
1531 ret |= lp_force_directory_mode(SNUM(conn));
1534 *ret_perms = ret;
1535 return NT_STATUS_OK;
1538 /****************************************************************************
1539 Needed to show the msdfs symlinks as directories. Modifies psbuf
1540 to be a directory if it's a msdfs link.
1541 ****************************************************************************/
1543 static bool check_msdfs_link(connection_struct *conn,
1544 const char *pathname,
1545 SMB_STRUCT_STAT *psbuf)
1547 int saved_errno = errno;
1548 if(lp_host_msdfs() &&
1549 lp_msdfs_root(SNUM(conn)) &&
1550 is_msdfs_link(conn, pathname, psbuf)) {
1552 DEBUG(5,("check_msdfs_link: Masquerading msdfs link %s "
1553 "as a directory\n",
1554 pathname));
1555 psbuf->st_ex_mode = (psbuf->st_ex_mode & 0xFFF) | S_IFDIR;
1556 errno = saved_errno;
1557 return true;
1559 errno = saved_errno;
1560 return false;
1564 /****************************************************************************
1565 Get a level dependent lanman2 dir entry.
1566 ****************************************************************************/
1568 struct smbd_dirptr_lanman2_state {
1569 connection_struct *conn;
1570 uint32_t info_level;
1571 bool check_mangled_names;
1572 bool has_wild;
1573 bool got_exact_match;
1576 static bool smbd_dirptr_lanman2_match_fn(TALLOC_CTX *ctx,
1577 void *private_data,
1578 const char *dname,
1579 const char *mask,
1580 char **_fname)
1582 struct smbd_dirptr_lanman2_state *state =
1583 (struct smbd_dirptr_lanman2_state *)private_data;
1584 bool ok;
1585 char mangled_name[13]; /* mangled 8.3 name. */
1586 bool got_match;
1587 const char *fname;
1589 /* Mangle fname if it's an illegal name. */
1590 if (mangle_must_mangle(dname, state->conn->params)) {
1592 * Slow path - ensure we can push the original name as UCS2. If
1593 * not, then just don't return this name.
1595 NTSTATUS status;
1596 size_t ret_len = 0;
1597 size_t len = (strlen(dname) + 2) * 4; /* Allow enough space. */
1598 uint8_t *tmp = talloc_array(talloc_tos(),
1599 uint8_t,
1600 len);
1602 status = srvstr_push(NULL,
1603 FLAGS2_UNICODE_STRINGS,
1604 tmp,
1605 dname,
1606 len,
1607 STR_TERMINATE,
1608 &ret_len);
1610 TALLOC_FREE(tmp);
1612 if (!NT_STATUS_IS_OK(status)) {
1613 return false;
1616 ok = name_to_8_3(dname, mangled_name,
1617 true, state->conn->params);
1618 if (!ok) {
1619 return false;
1621 fname = mangled_name;
1622 } else {
1623 fname = dname;
1626 got_match = exact_match(state->has_wild,
1627 state->conn->case_sensitive,
1628 fname, mask);
1629 state->got_exact_match = got_match;
1630 if (!got_match) {
1631 got_match = mask_match(fname, mask,
1632 state->conn->case_sensitive);
1635 if(!got_match && state->check_mangled_names &&
1636 !mangle_is_8_3(fname, false, state->conn->params)) {
1638 * It turns out that NT matches wildcards against
1639 * both long *and* short names. This may explain some
1640 * of the wildcard wierdness from old DOS clients
1641 * that some people have been seeing.... JRA.
1643 /* Force the mangling into 8.3. */
1644 ok = name_to_8_3(fname, mangled_name,
1645 false, state->conn->params);
1646 if (!ok) {
1647 return false;
1650 got_match = exact_match(state->has_wild,
1651 state->conn->case_sensitive,
1652 mangled_name, mask);
1653 state->got_exact_match = got_match;
1654 if (!got_match) {
1655 got_match = mask_match(mangled_name, mask,
1656 state->conn->case_sensitive);
1660 if (!got_match) {
1661 return false;
1664 *_fname = talloc_strdup(ctx, fname);
1665 if (*_fname == NULL) {
1666 return false;
1669 return true;
1672 static bool smbd_dirptr_lanman2_mode_fn(TALLOC_CTX *ctx,
1673 void *private_data,
1674 struct smb_filename *smb_fname,
1675 uint32_t *_mode)
1677 struct smbd_dirptr_lanman2_state *state =
1678 (struct smbd_dirptr_lanman2_state *)private_data;
1679 bool ms_dfs_link = false;
1680 uint32_t mode = 0;
1682 if (INFO_LEVEL_IS_UNIX(state->info_level)) {
1683 if (SMB_VFS_LSTAT(state->conn, smb_fname) != 0) {
1684 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1685 "Couldn't lstat [%s] (%s)\n",
1686 smb_fname_str_dbg(smb_fname),
1687 strerror(errno)));
1688 return false;
1690 } else if (!VALID_STAT(smb_fname->st) &&
1691 SMB_VFS_STAT(state->conn, smb_fname) != 0) {
1692 /* Needed to show the msdfs symlinks as
1693 * directories */
1695 ms_dfs_link = check_msdfs_link(state->conn,
1696 smb_fname->base_name,
1697 &smb_fname->st);
1698 if (!ms_dfs_link) {
1699 DEBUG(5,("smbd_dirptr_lanman2_mode_fn: "
1700 "Couldn't stat [%s] (%s)\n",
1701 smb_fname_str_dbg(smb_fname),
1702 strerror(errno)));
1703 return false;
1707 if (ms_dfs_link) {
1708 mode = dos_mode_msdfs(state->conn, smb_fname);
1709 } else {
1710 mode = dos_mode(state->conn, smb_fname);
1713 *_mode = mode;
1714 return true;
1717 static NTSTATUS smbd_marshall_dir_entry(TALLOC_CTX *ctx,
1718 connection_struct *conn,
1719 uint16_t flags2,
1720 uint32_t info_level,
1721 struct ea_list *name_list,
1722 bool check_mangled_names,
1723 bool requires_resume_key,
1724 uint32_t mode,
1725 const char *fname,
1726 const struct smb_filename *smb_fname,
1727 int space_remaining,
1728 uint8_t align,
1729 bool do_pad,
1730 char *base_data,
1731 char **ppdata,
1732 char *end_data,
1733 uint64_t *last_entry_off)
1735 char *p, *q, *pdata = *ppdata;
1736 uint32_t reskey=0;
1737 uint64_t file_size = 0;
1738 uint64_t allocation_size = 0;
1739 uint64_t file_index = 0;
1740 size_t len = 0;
1741 struct timespec mdate_ts = {0};
1742 struct timespec adate_ts = {0};
1743 struct timespec cdate_ts = {0};
1744 struct timespec create_date_ts = {0};
1745 time_t mdate = (time_t)0, adate = (time_t)0, create_date = (time_t)0;
1746 char *nameptr;
1747 char *last_entry_ptr;
1748 bool was_8_3;
1749 int off;
1750 int pad = 0;
1751 NTSTATUS status;
1752 struct readdir_attr_data *readdir_attr_data = NULL;
1754 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
1755 file_size = get_file_size_stat(&smb_fname->st);
1757 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, NULL, &smb_fname->st);
1759 status = SMB_VFS_READDIR_ATTR(conn, smb_fname, ctx, &readdir_attr_data);
1760 if (!NT_STATUS_IS_OK(status)) {
1761 if (!NT_STATUS_EQUAL(NT_STATUS_NOT_SUPPORTED, status)) {
1762 return status;
1766 file_index = get_FileIndex(conn, &smb_fname->st);
1768 mdate_ts = smb_fname->st.st_ex_mtime;
1769 adate_ts = smb_fname->st.st_ex_atime;
1770 create_date_ts = get_create_timespec(conn, NULL, smb_fname);
1771 cdate_ts = get_change_timespec(conn, NULL, smb_fname);
1773 if (lp_dos_filetime_resolution(SNUM(conn))) {
1774 dos_filetime_timespec(&create_date_ts);
1775 dos_filetime_timespec(&mdate_ts);
1776 dos_filetime_timespec(&adate_ts);
1777 dos_filetime_timespec(&cdate_ts);
1780 create_date = convert_timespec_to_time_t(create_date_ts);
1781 mdate = convert_timespec_to_time_t(mdate_ts);
1782 adate = convert_timespec_to_time_t(adate_ts);
1784 /* align the record */
1785 SMB_ASSERT(align >= 1);
1787 off = (int)PTR_DIFF(pdata, base_data);
1788 pad = (off + (align-1)) & ~(align-1);
1789 pad -= off;
1791 if (pad && pad > space_remaining) {
1792 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1793 "for padding (wanted %u, had %d)\n",
1794 (unsigned int)pad,
1795 space_remaining ));
1796 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1799 off += pad;
1800 /* initialize padding to 0 */
1801 if (pad) {
1802 memset(pdata, 0, pad);
1804 space_remaining -= pad;
1806 DEBUG(10,("smbd_marshall_dir_entry: space_remaining = %d\n",
1807 space_remaining ));
1809 pdata += pad;
1810 p = pdata;
1811 last_entry_ptr = p;
1813 pad = 0;
1814 off = 0;
1816 switch (info_level) {
1817 case SMB_FIND_INFO_STANDARD:
1818 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_INFO_STANDARD\n"));
1819 if(requires_resume_key) {
1820 SIVAL(p,0,reskey);
1821 p += 4;
1823 srv_put_dos_date2(p,0,create_date);
1824 srv_put_dos_date2(p,4,adate);
1825 srv_put_dos_date2(p,8,mdate);
1826 SIVAL(p,12,(uint32_t)file_size);
1827 SIVAL(p,16,(uint32_t)allocation_size);
1828 SSVAL(p,20,mode);
1829 p += 23;
1830 nameptr = p;
1831 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1832 p += ucs2_align(base_data, p, 0);
1834 status = srvstr_push(base_data, flags2, p,
1835 fname, PTR_DIFF(end_data, p),
1836 STR_TERMINATE, &len);
1837 if (!NT_STATUS_IS_OK(status)) {
1838 return status;
1840 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1841 if (len > 2) {
1842 SCVAL(nameptr, -1, len - 2);
1843 } else {
1844 SCVAL(nameptr, -1, 0);
1846 } else {
1847 if (len > 1) {
1848 SCVAL(nameptr, -1, len - 1);
1849 } else {
1850 SCVAL(nameptr, -1, 0);
1853 p += len;
1854 break;
1856 case SMB_FIND_EA_SIZE:
1857 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_SIZE\n"));
1858 if (requires_resume_key) {
1859 SIVAL(p,0,reskey);
1860 p += 4;
1862 srv_put_dos_date2(p,0,create_date);
1863 srv_put_dos_date2(p,4,adate);
1864 srv_put_dos_date2(p,8,mdate);
1865 SIVAL(p,12,(uint32_t)file_size);
1866 SIVAL(p,16,(uint32_t)allocation_size);
1867 SSVAL(p,20,mode);
1869 unsigned int ea_size = estimate_ea_size(conn, NULL,
1870 smb_fname);
1871 SIVAL(p,22,ea_size); /* Extended attributes */
1873 p += 27;
1874 nameptr = p - 1;
1875 status = srvstr_push(base_data, flags2,
1876 p, fname, PTR_DIFF(end_data, p),
1877 STR_TERMINATE | STR_NOALIGN, &len);
1878 if (!NT_STATUS_IS_OK(status)) {
1879 return status;
1881 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1882 if (len > 2) {
1883 len -= 2;
1884 } else {
1885 len = 0;
1887 } else {
1888 if (len > 1) {
1889 len -= 1;
1890 } else {
1891 len = 0;
1894 SCVAL(nameptr,0,len);
1895 p += len;
1896 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1897 break;
1899 case SMB_FIND_EA_LIST:
1901 struct ea_list *file_list = NULL;
1902 size_t ea_len = 0;
1904 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_EA_LIST\n"));
1905 if (!name_list) {
1906 return NT_STATUS_INVALID_PARAMETER;
1908 if (requires_resume_key) {
1909 SIVAL(p,0,reskey);
1910 p += 4;
1912 srv_put_dos_date2(p,0,create_date);
1913 srv_put_dos_date2(p,4,adate);
1914 srv_put_dos_date2(p,8,mdate);
1915 SIVAL(p,12,(uint32_t)file_size);
1916 SIVAL(p,16,(uint32_t)allocation_size);
1917 SSVAL(p,20,mode);
1918 p += 22; /* p now points to the EA area. */
1920 status = get_ea_list_from_file(ctx, conn, NULL,
1921 smb_fname,
1922 &ea_len, &file_list);
1923 if (!NT_STATUS_IS_OK(status)) {
1924 file_list = NULL;
1926 name_list = ea_list_union(name_list, file_list, &ea_len);
1928 /* We need to determine if this entry will fit in the space available. */
1929 /* Max string size is 255 bytes. */
1930 if (PTR_DIFF(p + 255 + ea_len,pdata) > space_remaining) {
1931 DEBUG(9,("smbd_marshall_dir_entry: out of space "
1932 "(wanted %u, had %d)\n",
1933 (unsigned int)PTR_DIFF(p + 255 + ea_len,pdata),
1934 space_remaining ));
1935 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
1938 /* Push the ea_data followed by the name. */
1939 p += fill_ea_buffer(ctx, p, space_remaining, conn, name_list);
1940 nameptr = p;
1941 status = srvstr_push(base_data, flags2,
1942 p + 1, fname, PTR_DIFF(end_data, p+1),
1943 STR_TERMINATE | STR_NOALIGN, &len);
1944 if (!NT_STATUS_IS_OK(status)) {
1945 return status;
1947 if (flags2 & FLAGS2_UNICODE_STRINGS) {
1948 if (len > 2) {
1949 len -= 2;
1950 } else {
1951 len = 0;
1953 } else {
1954 if (len > 1) {
1955 len -= 1;
1956 } else {
1957 len = 0;
1960 SCVAL(nameptr,0,len);
1961 p += len + 1;
1962 SCVAL(p,0,0); p += 1; /* Extra zero byte ? - why.. */
1963 break;
1966 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
1967 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_BOTH_DIRECTORY_INFO\n"));
1968 was_8_3 = mangle_is_8_3(fname, True, conn->params);
1969 p += 4;
1970 SIVAL(p,0,reskey); p += 4;
1971 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
1972 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
1973 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
1974 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
1975 SOFF_T(p,0,file_size); p += 8;
1976 SOFF_T(p,0,allocation_size); p += 8;
1977 SIVAL(p,0,mode); p += 4;
1978 q = p; p += 4; /* q is placeholder for name length. */
1979 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
1980 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
1981 } else {
1982 unsigned int ea_size = estimate_ea_size(conn, NULL,
1983 smb_fname);
1984 SIVAL(p,0,ea_size); /* Extended attributes */
1986 p += 4;
1987 /* Clear the short name buffer. This is
1988 * IMPORTANT as not doing so will trigger
1989 * a Win2k client bug. JRA.
1991 if (!was_8_3 && check_mangled_names) {
1992 char mangled_name[13]; /* mangled 8.3 name. */
1993 if (!name_to_8_3(fname,mangled_name,True,
1994 conn->params)) {
1995 /* Error - mangle failed ! */
1996 memset(mangled_name,'\0',12);
1998 mangled_name[12] = 0;
1999 status = srvstr_push(base_data, flags2,
2000 p+2, mangled_name, 24,
2001 STR_UPPER|STR_UNICODE, &len);
2002 if (!NT_STATUS_IS_OK(status)) {
2003 return status;
2005 if (len < 24) {
2006 memset(p + 2 + len,'\0',24 - len);
2008 SSVAL(p, 0, len);
2009 } else {
2010 memset(p,'\0',26);
2012 p += 2 + 24;
2013 status = srvstr_push(base_data, flags2, p,
2014 fname, PTR_DIFF(end_data, p),
2015 STR_TERMINATE_ASCII, &len);
2016 if (!NT_STATUS_IS_OK(status)) {
2017 return status;
2019 SIVAL(q,0,len);
2020 p += len;
2022 len = PTR_DIFF(p, pdata);
2023 pad = (len + (align-1)) & ~(align-1);
2025 * offset to the next entry, the caller
2026 * will overwrite it for the last entry
2027 * that's why we always include the padding
2029 SIVAL(pdata,0,pad);
2031 * set padding to zero
2033 if (do_pad) {
2034 memset(p, 0, pad - len);
2035 p = pdata + pad;
2036 } else {
2037 p = pdata + len;
2039 break;
2041 case SMB_FIND_FILE_DIRECTORY_INFO:
2042 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_DIRECTORY_INFO\n"));
2043 p += 4;
2044 SIVAL(p,0,reskey); p += 4;
2045 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2046 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2047 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2048 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2049 SOFF_T(p,0,file_size); p += 8;
2050 SOFF_T(p,0,allocation_size); p += 8;
2051 SIVAL(p,0,mode); p += 4;
2052 status = srvstr_push(base_data, flags2,
2053 p + 4, fname, PTR_DIFF(end_data, p+4),
2054 STR_TERMINATE_ASCII, &len);
2055 if (!NT_STATUS_IS_OK(status)) {
2056 return status;
2058 SIVAL(p,0,len);
2059 p += 4 + len;
2061 len = PTR_DIFF(p, pdata);
2062 pad = (len + (align-1)) & ~(align-1);
2064 * offset to the next entry, the caller
2065 * will overwrite it for the last entry
2066 * that's why we always include the padding
2068 SIVAL(pdata,0,pad);
2070 * set padding to zero
2072 if (do_pad) {
2073 memset(p, 0, pad - len);
2074 p = pdata + pad;
2075 } else {
2076 p = pdata + len;
2078 break;
2080 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2081 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_FULL_DIRECTORY_INFO\n"));
2082 p += 4;
2083 SIVAL(p,0,reskey); p += 4;
2084 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2085 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2086 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2087 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2088 SOFF_T(p,0,file_size); p += 8;
2089 SOFF_T(p,0,allocation_size); p += 8;
2090 SIVAL(p,0,mode); p += 4;
2091 q = p; p += 4; /* q is placeholder for name length. */
2093 unsigned int ea_size = estimate_ea_size(conn, NULL,
2094 smb_fname);
2095 SIVAL(p,0,ea_size); /* Extended attributes */
2096 p +=4;
2098 status = srvstr_push(base_data, flags2, p,
2099 fname, PTR_DIFF(end_data, p),
2100 STR_TERMINATE_ASCII, &len);
2101 if (!NT_STATUS_IS_OK(status)) {
2102 return status;
2104 SIVAL(q, 0, len);
2105 p += len;
2107 len = PTR_DIFF(p, pdata);
2108 pad = (len + (align-1)) & ~(align-1);
2110 * offset to the next entry, the caller
2111 * will overwrite it for the last entry
2112 * that's why we always include the padding
2114 SIVAL(pdata,0,pad);
2116 * set padding to zero
2118 if (do_pad) {
2119 memset(p, 0, pad - len);
2120 p = pdata + pad;
2121 } else {
2122 p = pdata + len;
2124 break;
2126 case SMB_FIND_FILE_NAMES_INFO:
2127 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_NAMES_INFO\n"));
2128 p += 4;
2129 SIVAL(p,0,reskey); p += 4;
2130 p += 4;
2131 /* this must *not* be null terminated or w2k gets in a loop trying to set an
2132 acl on a dir (tridge) */
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(p, -4, 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_ID_FULL_DIRECTORY_INFO:
2162 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_FULL_DIRECTORY_INFO\n"));
2163 p += 4;
2164 SIVAL(p,0,reskey); p += 4;
2165 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2166 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2167 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2168 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2169 SOFF_T(p,0,file_size); p += 8;
2170 SOFF_T(p,0,allocation_size); p += 8;
2171 SIVAL(p,0,mode); p += 4;
2172 q = p; p += 4; /* q is placeholder for name length. */
2173 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2174 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2175 } else {
2176 unsigned int ea_size = estimate_ea_size(conn, NULL,
2177 smb_fname);
2178 SIVAL(p,0,ea_size); /* Extended attributes */
2180 p += 4;
2181 SIVAL(p,0,0); p += 4; /* Unknown - reserved ? */
2182 SBVAL(p,0,file_index); p += 8;
2183 status = srvstr_push(base_data, flags2, p,
2184 fname, PTR_DIFF(end_data, p),
2185 STR_TERMINATE_ASCII, &len);
2186 if (!NT_STATUS_IS_OK(status)) {
2187 return status;
2189 SIVAL(q, 0, len);
2190 p += len;
2192 len = PTR_DIFF(p, pdata);
2193 pad = (len + (align-1)) & ~(align-1);
2195 * offset to the next entry, the caller
2196 * will overwrite it for the last entry
2197 * that's why we always include the padding
2199 SIVAL(pdata,0,pad);
2201 * set padding to zero
2203 if (do_pad) {
2204 memset(p, 0, pad - len);
2205 p = pdata + pad;
2206 } else {
2207 p = pdata + len;
2209 break;
2211 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2212 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_ID_BOTH_DIRECTORY_INFO\n"));
2213 was_8_3 = mangle_is_8_3(fname, True, conn->params);
2214 p += 4;
2215 SIVAL(p,0,reskey); p += 4;
2216 put_long_date_timespec(conn->ts_res,p,create_date_ts); p += 8;
2217 put_long_date_timespec(conn->ts_res,p,adate_ts); p += 8;
2218 put_long_date_timespec(conn->ts_res,p,mdate_ts); p += 8;
2219 put_long_date_timespec(conn->ts_res,p,cdate_ts); p += 8;
2220 SOFF_T(p,0,file_size); p += 8;
2221 SOFF_T(p,0,allocation_size); p += 8;
2222 SIVAL(p,0,mode); p += 4;
2223 q = p; p += 4; /* q is placeholder for name length */
2224 if (mode & FILE_ATTRIBUTE_REPARSE_POINT) {
2225 SIVAL(p, 0, IO_REPARSE_TAG_DFS);
2226 } else if (readdir_attr_data &&
2227 readdir_attr_data->type == RDATTR_AAPL) {
2229 * OS X specific SMB2 extension negotiated via
2230 * AAPL create context: return max_access in
2231 * ea_size field.
2233 SIVAL(p, 0, readdir_attr_data->attr_data.aapl.max_access);
2234 } else {
2235 unsigned int ea_size = estimate_ea_size(conn, NULL,
2236 smb_fname);
2237 SIVAL(p,0,ea_size); /* Extended attributes */
2239 p += 4;
2241 if (readdir_attr_data &&
2242 readdir_attr_data->type == RDATTR_AAPL) {
2244 * OS X specific SMB2 extension negotiated via
2245 * AAPL create context: return resource fork
2246 * length and compressed FinderInfo in
2247 * shortname field.
2249 * According to documentation short_name_len
2250 * should be 0, but on the wire behaviour
2251 * shows its set to 24 by clients.
2253 SSVAL(p, 0, 24);
2255 /* Resourefork length */
2256 SBVAL(p, 2, readdir_attr_data->attr_data.aapl.rfork_size);
2258 /* Compressed FinderInfo */
2259 memcpy(p + 10, &readdir_attr_data->attr_data.aapl.finder_info, 16);
2260 } else if (!was_8_3 && check_mangled_names) {
2261 char mangled_name[13]; /* mangled 8.3 name. */
2262 if (!name_to_8_3(fname,mangled_name,True,
2263 conn->params)) {
2264 /* Error - mangle failed ! */
2265 memset(mangled_name,'\0',12);
2267 mangled_name[12] = 0;
2268 status = srvstr_push(base_data, flags2,
2269 p+2, mangled_name, 24,
2270 STR_UPPER|STR_UNICODE, &len);
2271 if (!NT_STATUS_IS_OK(status)) {
2272 return status;
2274 SSVAL(p, 0, len);
2275 if (len < 24) {
2276 memset(p + 2 + len,'\0',24 - len);
2278 SSVAL(p, 0, len);
2279 } else {
2280 /* Clear the short name buffer. This is
2281 * IMPORTANT as not doing so will trigger
2282 * a Win2k client bug. JRA.
2284 memset(p,'\0',26);
2286 p += 26;
2288 /* Reserved ? */
2289 if (readdir_attr_data &&
2290 readdir_attr_data->type == RDATTR_AAPL) {
2292 * OS X specific SMB2 extension negotiated via
2293 * AAPL create context: return UNIX mode in
2294 * reserved field.
2296 uint16_t aapl_mode = (uint16_t)readdir_attr_data->attr_data.aapl.unix_mode;
2297 SSVAL(p, 0, aapl_mode);
2298 } else {
2299 SSVAL(p, 0, 0);
2301 p += 2;
2303 SBVAL(p,0,file_index); p += 8;
2304 status = srvstr_push(base_data, flags2, p,
2305 fname, PTR_DIFF(end_data, p),
2306 STR_TERMINATE_ASCII, &len);
2307 if (!NT_STATUS_IS_OK(status)) {
2308 return status;
2310 SIVAL(q,0,len);
2311 p += len;
2313 len = PTR_DIFF(p, pdata);
2314 pad = (len + (align-1)) & ~(align-1);
2316 * offset to the next entry, the caller
2317 * will overwrite it for the last entry
2318 * that's why we always include the padding
2320 SIVAL(pdata,0,pad);
2322 * set padding to zero
2324 if (do_pad) {
2325 memset(p, 0, pad - len);
2326 p = pdata + pad;
2327 } else {
2328 p = pdata + len;
2330 break;
2332 /* CIFS UNIX Extension. */
2334 case SMB_FIND_FILE_UNIX:
2335 case SMB_FIND_FILE_UNIX_INFO2:
2336 p+= 4;
2337 SIVAL(p,0,reskey); p+= 4; /* Used for continuing search. */
2339 /* Begin of SMB_QUERY_FILE_UNIX_BASIC */
2341 if (info_level == SMB_FIND_FILE_UNIX) {
2342 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX\n"));
2343 p = store_file_unix_basic(conn, p,
2344 NULL, &smb_fname->st);
2345 status = srvstr_push(base_data, flags2, p,
2346 fname, PTR_DIFF(end_data, p),
2347 STR_TERMINATE, &len);
2348 if (!NT_STATUS_IS_OK(status)) {
2349 return status;
2351 } else {
2352 DEBUG(10,("smbd_marshall_dir_entry: SMB_FIND_FILE_UNIX_INFO2\n"));
2353 p = store_file_unix_basic_info2(conn, p,
2354 NULL, &smb_fname->st);
2355 nameptr = p;
2356 p += 4;
2357 status = srvstr_push(base_data, flags2, p, fname,
2358 PTR_DIFF(end_data, p), 0, &len);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 return status;
2362 SIVAL(nameptr, 0, len);
2365 p += len;
2367 len = PTR_DIFF(p, pdata);
2368 pad = (len + (align-1)) & ~(align-1);
2370 * offset to the next entry, the caller
2371 * will overwrite it for the last entry
2372 * that's why we always include the padding
2374 SIVAL(pdata,0,pad);
2376 * set padding to zero
2378 if (do_pad) {
2379 memset(p, 0, pad - len);
2380 p = pdata + pad;
2381 } else {
2382 p = pdata + len;
2384 /* End of SMB_QUERY_FILE_UNIX_BASIC */
2386 break;
2388 default:
2389 return NT_STATUS_INVALID_LEVEL;
2392 if (PTR_DIFF(p,pdata) > space_remaining) {
2393 DEBUG(9,("smbd_marshall_dir_entry: out of space "
2394 "(wanted %u, had %d)\n",
2395 (unsigned int)PTR_DIFF(p,pdata),
2396 space_remaining ));
2397 return STATUS_MORE_ENTRIES; /* Not finished - just out of space */
2400 /* Setup the last entry pointer, as an offset from base_data */
2401 *last_entry_off = PTR_DIFF(last_entry_ptr,base_data);
2402 /* Advance the data pointer to the next slot */
2403 *ppdata = p;
2405 return NT_STATUS_OK;
2408 NTSTATUS smbd_dirptr_lanman2_entry(TALLOC_CTX *ctx,
2409 connection_struct *conn,
2410 struct dptr_struct *dirptr,
2411 uint16_t flags2,
2412 const char *path_mask,
2413 uint32_t dirtype,
2414 int info_level,
2415 int requires_resume_key,
2416 bool dont_descend,
2417 bool ask_sharemode,
2418 uint8_t align,
2419 bool do_pad,
2420 char **ppdata,
2421 char *base_data,
2422 char *end_data,
2423 int space_remaining,
2424 bool *got_exact_match,
2425 int *_last_entry_off,
2426 struct ea_list *name_list)
2428 const char *p;
2429 const char *mask = NULL;
2430 long prev_dirpos = 0;
2431 uint32_t mode = 0;
2432 char *fname = NULL;
2433 struct smb_filename *smb_fname = NULL;
2434 struct smbd_dirptr_lanman2_state state;
2435 bool ok;
2436 uint64_t last_entry_off = 0;
2437 NTSTATUS status;
2439 ZERO_STRUCT(state);
2440 state.conn = conn;
2441 state.info_level = info_level;
2442 state.check_mangled_names = lp_mangled_names(conn->params);
2443 state.has_wild = dptr_has_wild(dirptr);
2444 state.got_exact_match = false;
2446 *got_exact_match = false;
2448 p = strrchr_m(path_mask,'/');
2449 if(p != NULL) {
2450 if(p[1] == '\0') {
2451 mask = "*.*";
2452 } else {
2453 mask = p+1;
2455 } else {
2456 mask = path_mask;
2459 ok = smbd_dirptr_get_entry(ctx,
2460 dirptr,
2461 mask,
2462 dirtype,
2463 dont_descend,
2464 ask_sharemode,
2465 smbd_dirptr_lanman2_match_fn,
2466 smbd_dirptr_lanman2_mode_fn,
2467 &state,
2468 &fname,
2469 &smb_fname,
2470 &mode,
2471 &prev_dirpos);
2472 if (!ok) {
2473 return NT_STATUS_END_OF_FILE;
2476 *got_exact_match = state.got_exact_match;
2478 status = smbd_marshall_dir_entry(ctx,
2479 conn,
2480 flags2,
2481 info_level,
2482 name_list,
2483 state.check_mangled_names,
2484 requires_resume_key,
2485 mode,
2486 fname,
2487 smb_fname,
2488 space_remaining,
2489 align,
2490 do_pad,
2491 base_data,
2492 ppdata,
2493 end_data,
2494 &last_entry_off);
2495 if (NT_STATUS_EQUAL(status, NT_STATUS_ILLEGAL_CHARACTER)) {
2496 DEBUG(1,("Conversion error: illegal character: %s\n",
2497 smb_fname_str_dbg(smb_fname)));
2499 TALLOC_FREE(fname);
2500 TALLOC_FREE(smb_fname);
2501 if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
2502 dptr_SeekDir(dirptr, prev_dirpos);
2503 return status;
2505 if (!NT_STATUS_IS_OK(status)) {
2506 return status;
2509 *_last_entry_off = last_entry_off;
2510 return NT_STATUS_OK;
2513 static NTSTATUS get_lanman2_dir_entry(TALLOC_CTX *ctx,
2514 connection_struct *conn,
2515 struct dptr_struct *dirptr,
2516 uint16_t flags2,
2517 const char *path_mask,
2518 uint32_t dirtype,
2519 int info_level,
2520 bool requires_resume_key,
2521 bool dont_descend,
2522 bool ask_sharemode,
2523 char **ppdata,
2524 char *base_data,
2525 char *end_data,
2526 int space_remaining,
2527 bool *got_exact_match,
2528 int *last_entry_off,
2529 struct ea_list *name_list)
2531 uint8_t align = 4;
2532 const bool do_pad = true;
2534 if (info_level >= 1 && info_level <= 3) {
2535 /* No alignment on earlier info levels. */
2536 align = 1;
2539 return smbd_dirptr_lanman2_entry(ctx, conn, dirptr, flags2,
2540 path_mask, dirtype, info_level,
2541 requires_resume_key, dont_descend, ask_sharemode,
2542 align, do_pad,
2543 ppdata, base_data, end_data,
2544 space_remaining,
2545 got_exact_match,
2546 last_entry_off, name_list);
2549 /****************************************************************************
2550 Reply to a TRANS2_FINDFIRST.
2551 ****************************************************************************/
2553 static void call_trans2findfirst(connection_struct *conn,
2554 struct smb_request *req,
2555 char **pparams, int total_params,
2556 char **ppdata, int total_data,
2557 unsigned int max_data_bytes)
2559 /* We must be careful here that we don't return more than the
2560 allowed number of data bytes. If this means returning fewer than
2561 maxentries then so be it. We assume that the redirector has
2562 enough room for the fixed number of parameter bytes it has
2563 requested. */
2564 struct smb_filename *smb_dname = NULL;
2565 char *params = *pparams;
2566 char *pdata = *ppdata;
2567 char *data_end;
2568 uint32_t dirtype;
2569 int maxentries;
2570 uint16_t findfirst_flags;
2571 bool close_after_first;
2572 bool close_if_end;
2573 bool requires_resume_key;
2574 int info_level;
2575 char *directory = NULL;
2576 char *mask = NULL;
2577 char *p;
2578 int last_entry_off=0;
2579 int dptr_num = -1;
2580 int numentries = 0;
2581 int i;
2582 bool finished = False;
2583 bool dont_descend = False;
2584 bool out_of_space = False;
2585 int space_remaining;
2586 bool mask_contains_wcard = False;
2587 struct ea_list *ea_list = NULL;
2588 NTSTATUS ntstatus = NT_STATUS_OK;
2589 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
2590 struct dptr_struct *dirptr = NULL;
2591 struct smbd_server_connection *sconn = req->sconn;
2592 uint32_t ucf_flags = UCF_SAVE_LCOMP | UCF_ALWAYS_ALLOW_WCARD_LCOMP |
2593 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
2594 bool backup_priv = false;
2595 bool as_root = false;
2597 if (total_params < 13) {
2598 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2599 goto out;
2602 dirtype = SVAL(params,0);
2603 maxentries = SVAL(params,2);
2604 findfirst_flags = SVAL(params,4);
2605 close_after_first = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE);
2606 close_if_end = (findfirst_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
2607 requires_resume_key = (findfirst_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
2608 backup_priv = ((findfirst_flags & FLAG_TRANS2_FIND_BACKUP_INTENT) &&
2609 security_token_has_privilege(get_current_nttok(conn),
2610 SEC_PRIV_BACKUP));
2612 info_level = SVAL(params,6);
2614 DEBUG(3,("call_trans2findfirst: dirtype = %x, maxentries = %d, close_after_first=%d, \
2615 close_if_end = %d requires_resume_key = %d backup_priv = %d level = 0x%x, max_data_bytes = %d\n",
2616 (unsigned int)dirtype, maxentries, close_after_first, close_if_end, requires_resume_key,
2617 (int)backup_priv,
2618 info_level, max_data_bytes));
2620 if (!maxentries) {
2621 /* W2K3 seems to treat zero as 1. */
2622 maxentries = 1;
2625 switch (info_level) {
2626 case SMB_FIND_INFO_STANDARD:
2627 case SMB_FIND_EA_SIZE:
2628 case SMB_FIND_EA_LIST:
2629 case SMB_FIND_FILE_DIRECTORY_INFO:
2630 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
2631 case SMB_FIND_FILE_NAMES_INFO:
2632 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
2633 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
2634 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
2635 break;
2636 case SMB_FIND_FILE_UNIX:
2637 case SMB_FIND_FILE_UNIX_INFO2:
2638 /* Always use filesystem for UNIX mtime query. */
2639 ask_sharemode = false;
2640 if (!lp_unix_extensions()) {
2641 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2642 goto out;
2644 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
2645 break;
2646 default:
2647 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
2648 goto out;
2651 if (req->posix_pathnames) {
2652 srvstr_get_path_wcard_posix(talloc_tos(),
2653 params,
2654 req->flags2,
2655 &directory,
2656 params+12,
2657 total_params - 12,
2658 STR_TERMINATE,
2659 &ntstatus,
2660 &mask_contains_wcard);
2661 } else {
2662 srvstr_get_path_wcard(talloc_tos(),
2663 params,
2664 req->flags2,
2665 &directory,
2666 params+12,
2667 total_params - 12,
2668 STR_TERMINATE,
2669 &ntstatus,
2670 &mask_contains_wcard);
2672 if (!NT_STATUS_IS_OK(ntstatus)) {
2673 reply_nterror(req, ntstatus);
2674 goto out;
2677 if (backup_priv) {
2678 become_root();
2679 as_root = true;
2680 ntstatus = filename_convert_with_privilege(talloc_tos(),
2681 conn,
2682 req,
2683 directory,
2684 ucf_flags,
2685 &mask_contains_wcard,
2686 &smb_dname);
2687 } else {
2688 ntstatus = filename_convert(talloc_tos(), conn,
2689 req->flags2 & FLAGS2_DFS_PATHNAMES,
2690 directory,
2691 ucf_flags,
2692 &mask_contains_wcard,
2693 &smb_dname);
2696 if (!NT_STATUS_IS_OK(ntstatus)) {
2697 if (NT_STATUS_EQUAL(ntstatus,NT_STATUS_PATH_NOT_COVERED)) {
2698 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
2699 ERRSRV, ERRbadpath);
2700 goto out;
2702 reply_nterror(req, ntstatus);
2703 goto out;
2706 mask = smb_dname->original_lcomp;
2708 directory = smb_dname->base_name;
2710 p = strrchr_m(directory,'/');
2711 if(p == NULL) {
2712 /* Windows and OS/2 systems treat search on the root '\' as if it were '\*' */
2713 if((directory[0] == '.') && (directory[1] == '\0')) {
2714 mask = talloc_strdup(talloc_tos(),"*");
2715 if (!mask) {
2716 reply_nterror(req, NT_STATUS_NO_MEMORY);
2717 goto out;
2719 mask_contains_wcard = True;
2721 } else {
2722 *p = 0;
2725 if (p == NULL || p == directory) {
2726 /* Ensure we don't have a directory name of "". */
2727 directory = talloc_strdup(talloc_tos(), ".");
2728 if (!directory) {
2729 reply_nterror(req, NT_STATUS_NO_MEMORY);
2730 goto out;
2732 /* Ensure smb_dname->base_name matches. */
2733 smb_dname->base_name = directory;
2736 DEBUG(5,("dir=%s, mask = %s\n",directory, mask));
2738 if (info_level == SMB_FIND_EA_LIST) {
2739 uint32_t ea_size;
2741 if (total_data < 4) {
2742 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2743 goto out;
2746 ea_size = IVAL(pdata,0);
2747 if (ea_size != total_data) {
2748 DEBUG(4,("call_trans2findfirst: Rejecting EA request with incorrect \
2749 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
2750 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2751 goto out;
2754 if (!lp_ea_support(SNUM(conn))) {
2755 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
2756 goto out;
2759 /* Pull out the list of names. */
2760 ea_list = read_ea_name_list(talloc_tos(), pdata + 4, ea_size - 4);
2761 if (!ea_list) {
2762 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2763 goto out;
2767 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
2768 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
2769 goto out;
2772 *ppdata = (char *)SMB_REALLOC(
2773 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
2774 if(*ppdata == NULL ) {
2775 reply_nterror(req, NT_STATUS_NO_MEMORY);
2776 goto out;
2778 pdata = *ppdata;
2779 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
2781 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
2782 * error.
2784 memset(pdata + total_data, 0, ((max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data));
2785 /* Realloc the params space */
2786 *pparams = (char *)SMB_REALLOC(*pparams, 10);
2787 if (*pparams == NULL) {
2788 reply_nterror(req, NT_STATUS_NO_MEMORY);
2789 goto out;
2791 params = *pparams;
2793 /* Save the wildcard match and attribs we are using on this directory -
2794 needed as lanman2 assumes these are being saved between calls */
2796 ntstatus = dptr_create(conn,
2797 req,
2798 NULL, /* fsp */
2799 smb_dname,
2800 False,
2801 True,
2802 req->smbpid,
2803 mask,
2804 mask_contains_wcard,
2805 dirtype,
2806 &dirptr);
2808 if (!NT_STATUS_IS_OK(ntstatus)) {
2809 reply_nterror(req, ntstatus);
2810 goto out;
2813 if (backup_priv) {
2814 /* Remember this in case we have
2815 to do a findnext. */
2816 dptr_set_priv(dirptr);
2819 dptr_num = dptr_dnum(dirptr);
2820 DEBUG(4,("dptr_num is %d, wcard = %s, attr = %d\n", dptr_num, mask, dirtype));
2822 /* Initialize per TRANS2_FIND_FIRST operation data */
2823 dptr_init_search_op(dirptr);
2825 /* We don't need to check for VOL here as this is returned by
2826 a different TRANS2 call. */
2828 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
2829 directory,lp_dont_descend(talloc_tos(), SNUM(conn))));
2830 if (in_list(directory,
2831 lp_dont_descend(talloc_tos(), SNUM(conn)),
2832 conn->case_sensitive)) {
2833 dont_descend = True;
2836 p = pdata;
2837 space_remaining = max_data_bytes;
2838 out_of_space = False;
2840 for (i=0;(i<maxentries) && !finished && !out_of_space;i++) {
2841 bool got_exact_match = False;
2843 /* this is a heuristic to avoid seeking the dirptr except when
2844 absolutely necessary. It allows for a filename of about 40 chars */
2845 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
2846 out_of_space = True;
2847 finished = False;
2848 } else {
2849 ntstatus = get_lanman2_dir_entry(talloc_tos(),
2850 conn,
2851 dirptr,
2852 req->flags2,
2853 mask,dirtype,info_level,
2854 requires_resume_key,dont_descend,
2855 ask_sharemode,
2856 &p,pdata,data_end,
2857 space_remaining,
2858 &got_exact_match,
2859 &last_entry_off, ea_list);
2860 if (NT_STATUS_EQUAL(ntstatus,
2861 NT_STATUS_ILLEGAL_CHARACTER)) {
2863 * Bad character conversion on name. Ignore this
2864 * entry.
2866 continue;
2868 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
2869 out_of_space = true;
2870 } else {
2871 finished = !NT_STATUS_IS_OK(ntstatus);
2875 if (!finished && !out_of_space)
2876 numentries++;
2879 * As an optimisation if we know we aren't looking
2880 * for a wildcard name (ie. the name matches the wildcard exactly)
2881 * then we can finish on any (first) match.
2882 * This speeds up large directory searches. JRA.
2885 if(got_exact_match)
2886 finished = True;
2888 /* Ensure space_remaining never goes -ve. */
2889 if (PTR_DIFF(p,pdata) > max_data_bytes) {
2890 space_remaining = 0;
2891 out_of_space = true;
2892 } else {
2893 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
2897 /* Check if we can close the dirptr */
2898 if(close_after_first || (finished && close_if_end)) {
2899 DEBUG(5,("call_trans2findfirst - (2) closing dptr_num %d\n", dptr_num));
2900 dptr_close(sconn, &dptr_num);
2904 * If there are no matching entries we must return ERRDOS/ERRbadfile -
2905 * from observation of NT. NB. This changes to ERRDOS,ERRnofiles if
2906 * the protocol level is less than NT1. Tested with smbclient. JRA.
2907 * This should fix the OS/2 client bug #2335.
2910 if(numentries == 0) {
2911 dptr_close(sconn, &dptr_num);
2912 if (get_Protocol() < PROTOCOL_NT1) {
2913 reply_force_doserror(req, ERRDOS, ERRnofiles);
2914 goto out;
2915 } else {
2916 reply_botherror(req, NT_STATUS_NO_SUCH_FILE,
2917 ERRDOS, ERRbadfile);
2918 goto out;
2922 /* At this point pdata points to numentries directory entries. */
2924 /* Set up the return parameter block */
2925 SSVAL(params,0,dptr_num);
2926 SSVAL(params,2,numentries);
2927 SSVAL(params,4,finished);
2928 SSVAL(params,6,0); /* Never an EA error */
2929 SSVAL(params,8,last_entry_off);
2931 send_trans2_replies(conn, req, NT_STATUS_OK, params, 10, pdata, PTR_DIFF(p,pdata),
2932 max_data_bytes);
2934 if ((! *directory) && dptr_path(sconn, dptr_num)) {
2935 directory = talloc_strdup(talloc_tos(),dptr_path(sconn, dptr_num));
2936 if (!directory) {
2937 reply_nterror(req, NT_STATUS_NO_MEMORY);
2941 DEBUG( 4, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
2942 smb_fn_name(req->cmd),
2943 mask, directory, dirtype, numentries ) );
2946 * Force a name mangle here to ensure that the
2947 * mask as an 8.3 name is top of the mangled cache.
2948 * The reasons for this are subtle. Don't remove
2949 * this code unless you know what you are doing
2950 * (see PR#13758). JRA.
2953 if(!mangle_is_8_3_wildcards( mask, False, conn->params)) {
2954 char mangled_name[13];
2955 name_to_8_3(mask, mangled_name, True, conn->params);
2957 out:
2959 if (as_root) {
2960 unbecome_root();
2963 TALLOC_FREE(smb_dname);
2964 return;
2967 /****************************************************************************
2968 Reply to a TRANS2_FINDNEXT.
2969 ****************************************************************************/
2971 static void call_trans2findnext(connection_struct *conn,
2972 struct smb_request *req,
2973 char **pparams, int total_params,
2974 char **ppdata, int total_data,
2975 unsigned int max_data_bytes)
2977 /* We must be careful here that we don't return more than the
2978 allowed number of data bytes. If this means returning fewer than
2979 maxentries then so be it. We assume that the redirector has
2980 enough room for the fixed number of parameter bytes it has
2981 requested. */
2982 char *params = *pparams;
2983 char *pdata = *ppdata;
2984 char *data_end;
2985 int dptr_num;
2986 int maxentries;
2987 uint16_t info_level;
2988 uint32_t resume_key;
2989 uint16_t findnext_flags;
2990 bool close_after_request;
2991 bool close_if_end;
2992 bool requires_resume_key;
2993 bool continue_bit;
2994 bool mask_contains_wcard = False;
2995 char *resume_name = NULL;
2996 const char *mask = NULL;
2997 const char *directory = NULL;
2998 char *p = NULL;
2999 uint16_t dirtype;
3000 int numentries = 0;
3001 int i, last_entry_off=0;
3002 bool finished = False;
3003 bool dont_descend = False;
3004 bool out_of_space = False;
3005 int space_remaining;
3006 struct ea_list *ea_list = NULL;
3007 NTSTATUS ntstatus = NT_STATUS_OK;
3008 bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
3009 TALLOC_CTX *ctx = talloc_tos();
3010 struct dptr_struct *dirptr;
3011 struct smbd_server_connection *sconn = req->sconn;
3012 bool backup_priv = false;
3013 bool as_root = false;
3015 if (total_params < 13) {
3016 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3017 return;
3020 dptr_num = SVAL(params,0);
3021 maxentries = SVAL(params,2);
3022 info_level = SVAL(params,4);
3023 resume_key = IVAL(params,6);
3024 findnext_flags = SVAL(params,10);
3025 close_after_request = (findnext_flags & FLAG_TRANS2_FIND_CLOSE);
3026 close_if_end = (findnext_flags & FLAG_TRANS2_FIND_CLOSE_IF_END);
3027 requires_resume_key = (findnext_flags & FLAG_TRANS2_FIND_REQUIRE_RESUME);
3028 continue_bit = (findnext_flags & FLAG_TRANS2_FIND_CONTINUE);
3030 if (!continue_bit) {
3031 /* We only need resume_name if continue_bit is zero. */
3032 if (req->posix_pathnames) {
3033 srvstr_get_path_wcard_posix(ctx,
3034 params,
3035 req->flags2,
3036 &resume_name,
3037 params+12,
3038 total_params - 12,
3039 STR_TERMINATE,
3040 &ntstatus,
3041 &mask_contains_wcard);
3042 } else {
3043 srvstr_get_path_wcard(ctx,
3044 params,
3045 req->flags2,
3046 &resume_name,
3047 params+12,
3048 total_params - 12,
3049 STR_TERMINATE,
3050 &ntstatus,
3051 &mask_contains_wcard);
3053 if (!NT_STATUS_IS_OK(ntstatus)) {
3054 /* Win9x or OS/2 can send a resume name of ".." or ".". This will cause the parser to
3055 complain (it thinks we're asking for the directory above the shared
3056 path or an invalid name). Catch this as the resume name is only compared, never used in
3057 a file access. JRA. */
3058 srvstr_pull_talloc(ctx, params, req->flags2,
3059 &resume_name, params+12,
3060 total_params - 12,
3061 STR_TERMINATE);
3063 if (!resume_name || !(ISDOT(resume_name) || ISDOTDOT(resume_name))) {
3064 reply_nterror(req, ntstatus);
3065 return;
3070 DEBUG(3,("call_trans2findnext: dirhandle = %d, max_data_bytes = %d, maxentries = %d, \
3071 close_after_request=%d, close_if_end = %d requires_resume_key = %d \
3072 resume_key = %d resume name = %s continue=%d level = %d\n",
3073 dptr_num, max_data_bytes, maxentries, close_after_request, close_if_end,
3074 requires_resume_key, resume_key,
3075 resume_name ? resume_name : "(NULL)", continue_bit, info_level));
3077 if (!maxentries) {
3078 /* W2K3 seems to treat zero as 1. */
3079 maxentries = 1;
3082 switch (info_level) {
3083 case SMB_FIND_INFO_STANDARD:
3084 case SMB_FIND_EA_SIZE:
3085 case SMB_FIND_EA_LIST:
3086 case SMB_FIND_FILE_DIRECTORY_INFO:
3087 case SMB_FIND_FILE_FULL_DIRECTORY_INFO:
3088 case SMB_FIND_FILE_NAMES_INFO:
3089 case SMB_FIND_FILE_BOTH_DIRECTORY_INFO:
3090 case SMB_FIND_ID_FULL_DIRECTORY_INFO:
3091 case SMB_FIND_ID_BOTH_DIRECTORY_INFO:
3092 break;
3093 case SMB_FIND_FILE_UNIX:
3094 case SMB_FIND_FILE_UNIX_INFO2:
3095 /* Always use filesystem for UNIX mtime query. */
3096 ask_sharemode = false;
3097 if (!lp_unix_extensions()) {
3098 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3099 return;
3101 break;
3102 default:
3103 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
3104 return;
3107 if (info_level == SMB_FIND_EA_LIST) {
3108 uint32_t ea_size;
3110 if (total_data < 4) {
3111 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3112 return;
3115 ea_size = IVAL(pdata,0);
3116 if (ea_size != total_data) {
3117 DEBUG(4,("call_trans2findnext: Rejecting EA request with incorrect \
3118 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
3119 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3120 return;
3123 if (!lp_ea_support(SNUM(conn))) {
3124 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
3125 return;
3128 /* Pull out the list of names. */
3129 ea_list = read_ea_name_list(ctx, pdata + 4, ea_size - 4);
3130 if (!ea_list) {
3131 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3132 return;
3136 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3137 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
3138 return;
3141 *ppdata = (char *)SMB_REALLOC(
3142 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3143 if(*ppdata == NULL) {
3144 reply_nterror(req, NT_STATUS_NO_MEMORY);
3145 return;
3148 pdata = *ppdata;
3149 data_end = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3152 * squash valgrind "writev(vector[...]) points to uninitialised byte(s)"
3153 * error.
3155 memset(pdata + total_data, 0, (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN) - total_data);
3156 /* Realloc the params space */
3157 *pparams = (char *)SMB_REALLOC(*pparams, 6*SIZEOFWORD);
3158 if(*pparams == NULL ) {
3159 reply_nterror(req, NT_STATUS_NO_MEMORY);
3160 return;
3163 params = *pparams;
3165 /* Check that the dptr is valid */
3166 if(!(dirptr = dptr_fetch_lanman2(sconn, dptr_num))) {
3167 reply_nterror(req, STATUS_NO_MORE_FILES);
3168 return;
3171 directory = dptr_path(sconn, dptr_num);
3173 /* Get the wildcard mask from the dptr */
3174 if((mask = dptr_wcard(sconn, dptr_num))== NULL) {
3175 DEBUG(2,("dptr_num %d has no wildcard\n", dptr_num));
3176 reply_nterror(req, STATUS_NO_MORE_FILES);
3177 return;
3180 /* Get the attr mask from the dptr */
3181 dirtype = dptr_attr(sconn, dptr_num);
3183 backup_priv = dptr_get_priv(dirptr);
3185 DEBUG(3,("dptr_num is %d, mask = %s, attr = %x, dirptr=(0x%lX,%ld) "
3186 "backup_priv = %d\n",
3187 dptr_num, mask, dirtype,
3188 (long)dirptr,
3189 dptr_TellDir(dirptr),
3190 (int)backup_priv));
3192 /* Initialize per TRANS2_FIND_NEXT operation data */
3193 dptr_init_search_op(dirptr);
3195 /* We don't need to check for VOL here as this is returned by
3196 a different TRANS2 call. */
3198 DEBUG(8,("dirpath=<%s> dontdescend=<%s>\n",
3199 directory,lp_dont_descend(ctx, SNUM(conn))));
3200 if (in_list(directory,lp_dont_descend(ctx, SNUM(conn)),conn->case_sensitive))
3201 dont_descend = True;
3203 p = pdata;
3204 space_remaining = max_data_bytes;
3205 out_of_space = False;
3207 if (backup_priv) {
3208 become_root();
3209 as_root = true;
3213 * Seek to the correct position. We no longer use the resume key but
3214 * depend on the last file name instead.
3217 if(!continue_bit && resume_name && *resume_name) {
3218 SMB_STRUCT_STAT st;
3220 long current_pos = 0;
3222 * Remember, name_to_8_3 is called by
3223 * get_lanman2_dir_entry(), so the resume name
3224 * could be mangled. Ensure we check the unmangled name.
3227 if (mangle_is_mangled(resume_name, conn->params)) {
3228 char *new_resume_name = NULL;
3229 mangle_lookup_name_from_8_3(ctx,
3230 resume_name,
3231 &new_resume_name,
3232 conn->params);
3233 if (new_resume_name) {
3234 resume_name = new_resume_name;
3239 * Fix for NT redirector problem triggered by resume key indexes
3240 * changing between directory scans. We now return a resume key of 0
3241 * and instead look for the filename to continue from (also given
3242 * to us by NT/95/smbfs/smbclient). If no other scans have been done between the
3243 * findfirst/findnext (as is usual) then the directory pointer
3244 * should already be at the correct place.
3247 finished = !dptr_SearchDir(dirptr, resume_name, &current_pos, &st);
3248 } /* end if resume_name && !continue_bit */
3250 for (i=0;(i<(int)maxentries) && !finished && !out_of_space ;i++) {
3251 bool got_exact_match = False;
3253 /* this is a heuristic to avoid seeking the dirptr except when
3254 absolutely necessary. It allows for a filename of about 40 chars */
3255 if (space_remaining < DIRLEN_GUESS && numentries > 0) {
3256 out_of_space = True;
3257 finished = False;
3258 } else {
3259 ntstatus = get_lanman2_dir_entry(ctx,
3260 conn,
3261 dirptr,
3262 req->flags2,
3263 mask,dirtype,info_level,
3264 requires_resume_key,dont_descend,
3265 ask_sharemode,
3266 &p,pdata,data_end,
3267 space_remaining,
3268 &got_exact_match,
3269 &last_entry_off, ea_list);
3270 if (NT_STATUS_EQUAL(ntstatus,
3271 NT_STATUS_ILLEGAL_CHARACTER)) {
3273 * Bad character conversion on name. Ignore this
3274 * entry.
3276 continue;
3278 if (NT_STATUS_EQUAL(ntstatus, STATUS_MORE_ENTRIES)) {
3279 out_of_space = true;
3280 } else {
3281 finished = !NT_STATUS_IS_OK(ntstatus);
3285 if (!finished && !out_of_space)
3286 numentries++;
3289 * As an optimisation if we know we aren't looking
3290 * for a wildcard name (ie. the name matches the wildcard exactly)
3291 * then we can finish on any (first) match.
3292 * This speeds up large directory searches. JRA.
3295 if(got_exact_match)
3296 finished = True;
3298 space_remaining = max_data_bytes - PTR_DIFF(p,pdata);
3301 DEBUG( 3, ( "%s mask=%s directory=%s dirtype=%d numentries=%d\n",
3302 smb_fn_name(req->cmd),
3303 mask, directory, dirtype, numentries ) );
3305 /* Check if we can close the dirptr */
3306 if(close_after_request || (finished && close_if_end)) {
3307 DEBUG(5,("call_trans2findnext: closing dptr_num = %d\n", dptr_num));
3308 dptr_close(sconn, &dptr_num); /* This frees up the saved mask */
3311 if (as_root) {
3312 unbecome_root();
3315 /* Set up the return parameter block */
3316 SSVAL(params,0,numentries);
3317 SSVAL(params,2,finished);
3318 SSVAL(params,4,0); /* Never an EA error */
3319 SSVAL(params,6,last_entry_off);
3321 send_trans2_replies(conn, req, NT_STATUS_OK, params, 8, pdata, PTR_DIFF(p,pdata),
3322 max_data_bytes);
3324 return;
3327 unsigned char *create_volume_objectid(connection_struct *conn, unsigned char objid[16])
3329 E_md4hash(lp_servicename(talloc_tos(), SNUM(conn)),objid);
3330 return objid;
3333 static void samba_extended_info_version(struct smb_extended_info *extended_info)
3335 SMB_ASSERT(extended_info != NULL);
3337 extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC;
3338 extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24)
3339 | ((SAMBA_VERSION_MINOR & 0xff) << 16)
3340 | ((SAMBA_VERSION_RELEASE & 0xff) << 8);
3341 #ifdef SAMBA_VERSION_REVISION
3342 extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff;
3343 #endif
3344 extended_info->samba_subversion = 0;
3345 #ifdef SAMBA_VERSION_RC_RELEASE
3346 extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24;
3347 #else
3348 #ifdef SAMBA_VERSION_PRE_RELEASE
3349 extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16;
3350 #endif
3351 #endif
3352 #ifdef SAMBA_VERSION_VENDOR_PATCH
3353 extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff);
3354 #endif
3355 extended_info->samba_gitcommitdate = 0;
3356 #ifdef SAMBA_VERSION_COMMIT_TIME
3357 unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_COMMIT_TIME);
3358 #endif
3360 memset(extended_info->samba_version_string, 0,
3361 sizeof(extended_info->samba_version_string));
3363 snprintf (extended_info->samba_version_string,
3364 sizeof(extended_info->samba_version_string),
3365 "%s", samba_version_string());
3368 NTSTATUS smbd_do_qfsinfo(struct smbXsrv_connection *xconn,
3369 connection_struct *conn,
3370 TALLOC_CTX *mem_ctx,
3371 uint16_t info_level,
3372 uint16_t flags2,
3373 unsigned int max_data_bytes,
3374 size_t *fixed_portion,
3375 struct smb_filename *fname,
3376 char **ppdata,
3377 int *ret_data_len)
3379 char *pdata, *end_data;
3380 int data_len = 0;
3381 size_t len = 0;
3382 const char *vname = volume_label(talloc_tos(), SNUM(conn));
3383 int snum = SNUM(conn);
3384 const char *fstype = lp_fstype(SNUM(conn));
3385 const char *filename = NULL;
3386 const uint64_t bytes_per_sector = 512;
3387 uint32_t additional_flags = 0;
3388 struct smb_filename smb_fname;
3389 SMB_STRUCT_STAT st;
3390 NTSTATUS status = NT_STATUS_OK;
3391 uint64_t df_ret;
3393 if (fname == NULL || fname->base_name == NULL) {
3394 filename = ".";
3395 } else {
3396 filename = fname->base_name;
3399 if (IS_IPC(conn)) {
3400 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
3401 DEBUG(0,("smbd_do_qfsinfo: not an allowed "
3402 "info level (0x%x) on IPC$.\n",
3403 (unsigned int)info_level));
3404 return NT_STATUS_ACCESS_DENIED;
3408 DEBUG(3,("smbd_do_qfsinfo: level = %d\n", info_level));
3410 ZERO_STRUCT(smb_fname);
3411 smb_fname.base_name = discard_const_p(char, filename);
3413 if(SMB_VFS_STAT(conn, &smb_fname) != 0) {
3414 DEBUG(2,("stat of . failed (%s)\n", strerror(errno)));
3415 return map_nt_error_from_unix(errno);
3418 st = smb_fname.st;
3420 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
3421 return NT_STATUS_INVALID_PARAMETER;
3424 *ppdata = (char *)SMB_REALLOC(
3425 *ppdata, max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3426 if (*ppdata == NULL) {
3427 return NT_STATUS_NO_MEMORY;
3430 pdata = *ppdata;
3431 memset((char *)pdata,'\0',max_data_bytes + DIR_ENTRY_SAFETY_MARGIN);
3432 end_data = pdata + max_data_bytes + DIR_ENTRY_SAFETY_MARGIN - 1;
3434 *fixed_portion = 0;
3436 switch (info_level) {
3437 case SMB_INFO_ALLOCATION:
3439 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3440 data_len = 18;
3441 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3442 &dsize);
3443 if (df_ret == (uint64_t)-1) {
3444 return map_nt_error_from_unix(errno);
3447 block_size = lp_block_size(snum);
3448 if (bsize < block_size) {
3449 uint64_t factor = block_size/bsize;
3450 bsize = block_size;
3451 dsize /= factor;
3452 dfree /= factor;
3454 if (bsize > block_size) {
3455 uint64_t factor = bsize/block_size;
3456 bsize = block_size;
3457 dsize *= factor;
3458 dfree *= factor;
3460 sectors_per_unit = bsize/bytes_per_sector;
3462 DEBUG(5,("smbd_do_qfsinfo : SMB_INFO_ALLOCATION id=%x, bsize=%u, cSectorUnit=%u, \
3463 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)st.st_ex_dev, (unsigned int)bsize, (unsigned int)sectors_per_unit,
3464 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3466 SIVAL(pdata,l1_idFileSystem,st.st_ex_dev);
3467 SIVAL(pdata,l1_cSectorUnit,sectors_per_unit);
3468 SIVAL(pdata,l1_cUnit,dsize);
3469 SIVAL(pdata,l1_cUnitAvail,dfree);
3470 SSVAL(pdata,l1_cbSector,bytes_per_sector);
3471 break;
3474 case SMB_INFO_VOLUME:
3475 /* Return volume name */
3477 * Add volume serial number - hash of a combination of
3478 * the called hostname and the service name.
3480 SIVAL(pdata,0,str_checksum(lp_servicename(talloc_tos(), snum)) ^ (str_checksum(get_local_machine_name())<<16) );
3482 * Win2k3 and previous mess this up by sending a name length
3483 * one byte short. I believe only older clients (OS/2 Win9x) use
3484 * this call so try fixing this by adding a terminating null to
3485 * the pushed string. The change here was adding the STR_TERMINATE. JRA.
3487 status = srvstr_push(
3488 pdata, flags2,
3489 pdata+l2_vol_szVolLabel, vname,
3490 PTR_DIFF(end_data, pdata+l2_vol_szVolLabel),
3491 STR_NOALIGN|STR_TERMINATE, &len);
3492 if (!NT_STATUS_IS_OK(status)) {
3493 return status;
3495 SCVAL(pdata,l2_vol_cch,len);
3496 data_len = l2_vol_szVolLabel + len;
3497 DEBUG(5,("smbd_do_qfsinfo : time = %x, namelen = %u, name = %s\n",
3498 (unsigned)convert_timespec_to_time_t(st.st_ex_ctime),
3499 (unsigned)len, vname));
3500 break;
3502 case SMB_QUERY_FS_ATTRIBUTE_INFO:
3503 case SMB_FS_ATTRIBUTE_INFORMATION:
3505 additional_flags = 0;
3506 #if defined(HAVE_SYS_QUOTAS)
3507 additional_flags |= FILE_VOLUME_QUOTAS;
3508 #endif
3510 if(lp_nt_acl_support(SNUM(conn))) {
3511 additional_flags |= FILE_PERSISTENT_ACLS;
3514 /* Capabilities are filled in at connection time through STATVFS call */
3515 additional_flags |= conn->fs_capabilities;
3516 additional_flags |= lp_parm_int(conn->params->service,
3517 "share", "fake_fscaps",
3520 SIVAL(pdata,0,FILE_CASE_PRESERVED_NAMES|FILE_CASE_SENSITIVE_SEARCH|
3521 FILE_SUPPORTS_OBJECT_IDS|FILE_UNICODE_ON_DISK|
3522 additional_flags); /* FS ATTRIBUTES */
3524 SIVAL(pdata,4,255); /* Max filename component length */
3525 /* NOTE! the fstype must *not* be null terminated or win98 won't recognise it
3526 and will think we can't do long filenames */
3527 status = srvstr_push(pdata, flags2, pdata+12, fstype,
3528 PTR_DIFF(end_data, pdata+12),
3529 STR_UNICODE, &len);
3530 if (!NT_STATUS_IS_OK(status)) {
3531 return status;
3533 SIVAL(pdata,8,len);
3534 data_len = 12 + len;
3535 if (max_data_bytes >= 16 && data_len > max_data_bytes) {
3536 /* the client only requested a portion of the
3537 file system name */
3538 data_len = max_data_bytes;
3539 status = STATUS_BUFFER_OVERFLOW;
3541 *fixed_portion = 16;
3542 break;
3544 case SMB_QUERY_FS_LABEL_INFO:
3545 case SMB_FS_LABEL_INFORMATION:
3546 status = srvstr_push(pdata, flags2, pdata+4, vname,
3547 PTR_DIFF(end_data, pdata+4), 0, &len);
3548 if (!NT_STATUS_IS_OK(status)) {
3549 return status;
3551 data_len = 4 + len;
3552 SIVAL(pdata,0,len);
3553 break;
3555 case SMB_QUERY_FS_VOLUME_INFO:
3556 case SMB_FS_VOLUME_INFORMATION:
3559 * Add volume serial number - hash of a combination of
3560 * the called hostname and the service name.
3562 SIVAL(pdata,8,str_checksum(lp_servicename(talloc_tos(), snum)) ^
3563 (str_checksum(get_local_machine_name())<<16));
3565 /* Max label len is 32 characters. */
3566 status = srvstr_push(pdata, flags2, pdata+18, vname,
3567 PTR_DIFF(end_data, pdata+18),
3568 STR_UNICODE, &len);
3569 if (!NT_STATUS_IS_OK(status)) {
3570 return status;
3572 SIVAL(pdata,12,len);
3573 data_len = 18+len;
3575 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_VOLUME_INFO namelen = %d, vol=%s serv=%s\n",
3576 (int)strlen(vname),vname,
3577 lp_servicename(talloc_tos(), snum)));
3578 if (max_data_bytes >= 24 && data_len > max_data_bytes) {
3579 /* the client only requested a portion of the
3580 volume label */
3581 data_len = max_data_bytes;
3582 status = STATUS_BUFFER_OVERFLOW;
3584 *fixed_portion = 24;
3585 break;
3587 case SMB_QUERY_FS_SIZE_INFO:
3588 case SMB_FS_SIZE_INFORMATION:
3590 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3591 data_len = 24;
3592 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3593 &dsize);
3594 if (df_ret == (uint64_t)-1) {
3595 return map_nt_error_from_unix(errno);
3597 block_size = lp_block_size(snum);
3598 if (bsize < block_size) {
3599 uint64_t factor = block_size/bsize;
3600 bsize = block_size;
3601 dsize /= factor;
3602 dfree /= factor;
3604 if (bsize > block_size) {
3605 uint64_t factor = bsize/block_size;
3606 bsize = block_size;
3607 dsize *= factor;
3608 dfree *= factor;
3610 sectors_per_unit = bsize/bytes_per_sector;
3611 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3612 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3613 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3614 SBIG_UINT(pdata,0,dsize);
3615 SBIG_UINT(pdata,8,dfree);
3616 SIVAL(pdata,16,sectors_per_unit);
3617 SIVAL(pdata,20,bytes_per_sector);
3618 *fixed_portion = 24;
3619 break;
3622 case SMB_FS_FULL_SIZE_INFORMATION:
3624 uint64_t dfree,dsize,bsize,block_size,sectors_per_unit;
3625 data_len = 32;
3626 df_ret = get_dfree_info(conn, filename, &bsize, &dfree,
3627 &dsize);
3628 if (df_ret == (uint64_t)-1) {
3629 return map_nt_error_from_unix(errno);
3631 block_size = lp_block_size(snum);
3632 if (bsize < block_size) {
3633 uint64_t factor = block_size/bsize;
3634 bsize = block_size;
3635 dsize /= factor;
3636 dfree /= factor;
3638 if (bsize > block_size) {
3639 uint64_t factor = bsize/block_size;
3640 bsize = block_size;
3641 dsize *= factor;
3642 dfree *= factor;
3644 sectors_per_unit = bsize/bytes_per_sector;
3645 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_FS_FULL_SIZE_INFO bsize=%u, cSectorUnit=%u, \
3646 cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned int)sectors_per_unit,
3647 (unsigned int)bytes_per_sector, (unsigned int)dsize, (unsigned int)dfree));
3648 SBIG_UINT(pdata,0,dsize); /* Total Allocation units. */
3649 SBIG_UINT(pdata,8,dfree); /* Caller available allocation units. */
3650 SBIG_UINT(pdata,16,dfree); /* Actual available allocation units. */
3651 SIVAL(pdata,24,sectors_per_unit); /* Sectors per allocation unit. */
3652 SIVAL(pdata,28,bytes_per_sector); /* Bytes per sector. */
3653 *fixed_portion = 32;
3654 break;
3657 case SMB_QUERY_FS_DEVICE_INFO:
3658 case SMB_FS_DEVICE_INFORMATION:
3660 uint32_t characteristics = FILE_DEVICE_IS_MOUNTED;
3662 if (!CAN_WRITE(conn)) {
3663 characteristics |= FILE_READ_ONLY_DEVICE;
3665 data_len = 8;
3666 SIVAL(pdata,0,FILE_DEVICE_DISK); /* dev type */
3667 SIVAL(pdata,4,characteristics);
3668 *fixed_portion = 8;
3669 break;
3672 #ifdef HAVE_SYS_QUOTAS
3673 case SMB_FS_QUOTA_INFORMATION:
3675 * what we have to send --metze:
3677 * Unknown1: 24 NULL bytes
3678 * Soft Quota Treshold: 8 bytes seems like uint64_t or so
3679 * Hard Quota Limit: 8 bytes seems like uint64_t or so
3680 * Quota Flags: 2 byte :
3681 * Unknown3: 6 NULL bytes
3683 * 48 bytes total
3685 * details for Quota Flags:
3687 * 0x0020 Log Limit: log if the user exceeds his Hard Quota
3688 * 0x0010 Log Warn: log if the user exceeds his Soft Quota
3689 * 0x0002 Deny Disk: deny disk access when the user exceeds his Hard Quota
3690 * 0x0001 Enable Quotas: enable quota for this fs
3694 /* we need to fake up a fsp here,
3695 * because its not send in this call
3697 files_struct fsp;
3698 SMB_NTQUOTA_STRUCT quotas;
3700 ZERO_STRUCT(fsp);
3701 ZERO_STRUCT(quotas);
3703 fsp.conn = conn;
3704 fsp.fnum = FNUM_FIELD_INVALID;
3706 /* access check */
3707 if (get_current_uid(conn) != 0) {
3708 DEBUG(0,("get_user_quota: access_denied "
3709 "service [%s] user [%s]\n",
3710 lp_servicename(talloc_tos(), SNUM(conn)),
3711 conn->session_info->unix_info->unix_name));
3712 return NT_STATUS_ACCESS_DENIED;
3715 status = vfs_get_ntquota(&fsp, SMB_USER_FS_QUOTA_TYPE,
3716 NULL, &quotas);
3717 if (!NT_STATUS_IS_OK(status)) {
3718 DEBUG(0,("vfs_get_ntquota() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3719 return status;
3722 data_len = 48;
3724 DEBUG(10,("SMB_FS_QUOTA_INFORMATION: for service [%s]\n",
3725 lp_servicename(talloc_tos(), SNUM(conn))));
3727 /* Unknown1 24 NULL bytes*/
3728 SBIG_UINT(pdata,0,(uint64_t)0);
3729 SBIG_UINT(pdata,8,(uint64_t)0);
3730 SBIG_UINT(pdata,16,(uint64_t)0);
3732 /* Default Soft Quota 8 bytes */
3733 SBIG_UINT(pdata,24,quotas.softlim);
3735 /* Default Hard Quota 8 bytes */
3736 SBIG_UINT(pdata,32,quotas.hardlim);
3738 /* Quota flag 2 bytes */
3739 SSVAL(pdata,40,quotas.qflags);
3741 /* Unknown3 6 NULL bytes */
3742 SSVAL(pdata,42,0);
3743 SIVAL(pdata,44,0);
3745 break;
3747 #endif /* HAVE_SYS_QUOTAS */
3748 case SMB_FS_OBJECTID_INFORMATION:
3750 unsigned char objid[16];
3751 struct smb_extended_info extended_info;
3752 memcpy(pdata,create_volume_objectid(conn, objid),16);
3753 samba_extended_info_version (&extended_info);
3754 SIVAL(pdata,16,extended_info.samba_magic);
3755 SIVAL(pdata,20,extended_info.samba_version);
3756 SIVAL(pdata,24,extended_info.samba_subversion);
3757 SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate);
3758 memcpy(pdata+36,extended_info.samba_version_string,28);
3759 data_len = 64;
3760 break;
3763 case SMB_FS_SECTOR_SIZE_INFORMATION:
3765 data_len = 28;
3767 * These values match a physical Windows Server 2012
3768 * share backed by NTFS atop spinning rust.
3770 DEBUG(5, ("SMB_FS_SECTOR_SIZE_INFORMATION:"));
3771 /* logical_bytes_per_sector */
3772 SIVAL(pdata, 0, bytes_per_sector);
3773 /* phys_bytes_per_sector_atomic */
3774 SIVAL(pdata, 4, bytes_per_sector);
3775 /* phys_bytes_per_sector_perf */
3776 SIVAL(pdata, 8, bytes_per_sector);
3777 /* fs_effective_phys_bytes_per_sector_atomic */
3778 SIVAL(pdata, 12, bytes_per_sector);
3779 /* flags */
3780 SIVAL(pdata, 16, SSINFO_FLAGS_ALIGNED_DEVICE
3781 | SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE);
3782 /* byte_off_sector_align */
3783 SIVAL(pdata, 20, 0);
3784 /* byte_off_partition_align */
3785 SIVAL(pdata, 24, 0);
3786 *fixed_portion = 28;
3787 break;
3792 * Query the version and capabilities of the CIFS UNIX extensions
3793 * in use.
3796 case SMB_QUERY_CIFS_UNIX_INFO:
3798 bool large_write = lp_min_receive_file_size() &&
3799 !srv_is_signing_active(xconn);
3800 bool large_read = !srv_is_signing_active(xconn);
3801 int encrypt_caps = 0;
3803 if (!lp_unix_extensions()) {
3804 return NT_STATUS_INVALID_LEVEL;
3807 switch (conn->encrypt_level) {
3808 case SMB_SIGNING_OFF:
3809 encrypt_caps = 0;
3810 break;
3811 case SMB_SIGNING_DESIRED:
3812 case SMB_SIGNING_IF_REQUIRED:
3813 case SMB_SIGNING_DEFAULT:
3814 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP;
3815 break;
3816 case SMB_SIGNING_REQUIRED:
3817 encrypt_caps = CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP|
3818 CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP;
3819 large_write = false;
3820 large_read = false;
3821 break;
3824 data_len = 12;
3825 SSVAL(pdata,0,CIFS_UNIX_MAJOR_VERSION);
3826 SSVAL(pdata,2,CIFS_UNIX_MINOR_VERSION);
3828 /* We have POSIX ACLs, pathname, encryption,
3829 * large read/write, and locking capability. */
3831 SBIG_UINT(pdata,4,((uint64_t)(
3832 CIFS_UNIX_POSIX_ACLS_CAP|
3833 CIFS_UNIX_POSIX_PATHNAMES_CAP|
3834 CIFS_UNIX_FCNTL_LOCKS_CAP|
3835 CIFS_UNIX_EXTATTR_CAP|
3836 CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP|
3837 encrypt_caps|
3838 (large_read ? CIFS_UNIX_LARGE_READ_CAP : 0) |
3839 (large_write ?
3840 CIFS_UNIX_LARGE_WRITE_CAP : 0))));
3841 break;
3844 case SMB_QUERY_POSIX_FS_INFO:
3846 int rc;
3847 vfs_statvfs_struct svfs;
3849 if (!lp_unix_extensions()) {
3850 return NT_STATUS_INVALID_LEVEL;
3853 rc = SMB_VFS_STATVFS(conn, filename, &svfs);
3855 if (!rc) {
3856 data_len = 56;
3857 SIVAL(pdata,0,svfs.OptimalTransferSize);
3858 SIVAL(pdata,4,svfs.BlockSize);
3859 SBIG_UINT(pdata,8,svfs.TotalBlocks);
3860 SBIG_UINT(pdata,16,svfs.BlocksAvail);
3861 SBIG_UINT(pdata,24,svfs.UserBlocksAvail);
3862 SBIG_UINT(pdata,32,svfs.TotalFileNodes);
3863 SBIG_UINT(pdata,40,svfs.FreeFileNodes);
3864 SBIG_UINT(pdata,48,svfs.FsIdentifier);
3865 DEBUG(5,("smbd_do_qfsinfo : SMB_QUERY_POSIX_FS_INFO succsessful\n"));
3866 #ifdef EOPNOTSUPP
3867 } else if (rc == EOPNOTSUPP) {
3868 return NT_STATUS_INVALID_LEVEL;
3869 #endif /* EOPNOTSUPP */
3870 } else {
3871 DEBUG(0,("vfs_statvfs() failed for service [%s]\n",lp_servicename(talloc_tos(), SNUM(conn))));
3872 return NT_STATUS_DOS(ERRSRV, ERRerror);
3874 break;
3877 case SMB_QUERY_POSIX_WHOAMI:
3879 uint32_t flags = 0;
3880 uint32_t sid_bytes;
3881 int i;
3883 if (!lp_unix_extensions()) {
3884 return NT_STATUS_INVALID_LEVEL;
3887 if (max_data_bytes < 40) {
3888 return NT_STATUS_BUFFER_TOO_SMALL;
3891 if (security_session_user_level(conn->session_info, NULL) < SECURITY_USER) {
3892 flags |= SMB_WHOAMI_GUEST;
3895 /* NOTE: 8 bytes for UID/GID, irrespective of native
3896 * platform size. This matches
3897 * SMB_QUERY_FILE_UNIX_BASIC and friends.
3899 data_len = 4 /* flags */
3900 + 4 /* flag mask */
3901 + 8 /* uid */
3902 + 8 /* gid */
3903 + 4 /* ngroups */
3904 + 4 /* num_sids */
3905 + 4 /* SID bytes */
3906 + 4 /* pad/reserved */
3907 + (conn->session_info->unix_token->ngroups * 8)
3908 /* groups list */
3909 + (conn->session_info->security_token->num_sids *
3910 SID_MAX_SIZE)
3911 /* SID list */;
3913 SIVAL(pdata, 0, flags);
3914 SIVAL(pdata, 4, SMB_WHOAMI_MASK);
3915 SBIG_UINT(pdata, 8,
3916 (uint64_t)conn->session_info->unix_token->uid);
3917 SBIG_UINT(pdata, 16,
3918 (uint64_t)conn->session_info->unix_token->gid);
3921 if (data_len >= max_data_bytes) {
3922 /* Potential overflow, skip the GIDs and SIDs. */
3924 SIVAL(pdata, 24, 0); /* num_groups */
3925 SIVAL(pdata, 28, 0); /* num_sids */
3926 SIVAL(pdata, 32, 0); /* num_sid_bytes */
3927 SIVAL(pdata, 36, 0); /* reserved */
3929 data_len = 40;
3930 break;
3933 SIVAL(pdata, 24, conn->session_info->unix_token->ngroups);
3934 SIVAL(pdata, 28, conn->session_info->security_token->num_sids);
3936 /* We walk the SID list twice, but this call is fairly
3937 * infrequent, and I don't expect that it's performance
3938 * sensitive -- jpeach
3940 for (i = 0, sid_bytes = 0;
3941 i < conn->session_info->security_token->num_sids; ++i) {
3942 sid_bytes += ndr_size_dom_sid(
3943 &conn->session_info->security_token->sids[i],
3947 /* SID list byte count */
3948 SIVAL(pdata, 32, sid_bytes);
3950 /* 4 bytes pad/reserved - must be zero */
3951 SIVAL(pdata, 36, 0);
3952 data_len = 40;
3954 /* GID list */
3955 for (i = 0; i < conn->session_info->unix_token->ngroups; ++i) {
3956 SBIG_UINT(pdata, data_len,
3957 (uint64_t)conn->session_info->unix_token->groups[i]);
3958 data_len += 8;
3961 /* SID list */
3962 for (i = 0;
3963 i < conn->session_info->security_token->num_sids; ++i) {
3964 int sid_len = ndr_size_dom_sid(
3965 &conn->session_info->security_token->sids[i],
3968 sid_linearize((uint8_t *)(pdata + data_len),
3969 sid_len,
3970 &conn->session_info->security_token->sids[i]);
3971 data_len += sid_len;
3974 break;
3977 case SMB_MAC_QUERY_FS_INFO:
3979 * Thursby MAC extension... ONLY on NTFS filesystems
3980 * once we do streams then we don't need this
3982 if (strequal(lp_fstype(SNUM(conn)),"NTFS")) {
3983 data_len = 88;
3984 SIVAL(pdata,84,0x100); /* Don't support mac... */
3985 break;
3987 /* drop through */
3988 default:
3989 return NT_STATUS_INVALID_LEVEL;
3992 *ret_data_len = data_len;
3993 return status;
3996 static NTSTATUS smb_set_fsquota(connection_struct *conn,
3997 struct smb_request *req,
3998 files_struct *fsp,
3999 const DATA_BLOB *qdata)
4001 NTSTATUS status;
4002 SMB_NTQUOTA_STRUCT quotas;
4004 ZERO_STRUCT(quotas);
4006 /* access check */
4007 if ((get_current_uid(conn) != 0) || !CAN_WRITE(conn)) {
4008 DEBUG(3, ("set_fsquota: access_denied service [%s] user [%s]\n",
4009 lp_servicename(talloc_tos(), SNUM(conn)),
4010 conn->session_info->unix_info->unix_name));
4011 return NT_STATUS_ACCESS_DENIED;
4014 if (!check_fsp_ntquota_handle(conn, req,
4015 fsp)) {
4016 DEBUG(1, ("set_fsquota: no valid QUOTA HANDLE\n"));
4017 return NT_STATUS_INVALID_HANDLE;
4020 /* note: normally there're 48 bytes,
4021 * but we didn't use the last 6 bytes for now
4022 * --metze
4024 if (qdata->length < 42) {
4025 DEBUG(0,("set_fsquota: requires total_data(%u) >= 42 bytes!\n",
4026 (unsigned int)qdata->length));
4027 return NT_STATUS_INVALID_PARAMETER;
4030 /* unknown_1 24 NULL bytes in pdata*/
4032 /* the soft quotas 8 bytes (uint64_t)*/
4033 quotas.softlim = BVAL(qdata->data,24);
4035 /* the hard quotas 8 bytes (uint64_t)*/
4036 quotas.hardlim = BVAL(qdata->data,32);
4038 /* quota_flags 2 bytes **/
4039 quotas.qflags = SVAL(qdata->data,40);
4041 /* unknown_2 6 NULL bytes follow*/
4043 /* now set the quotas */
4044 if (vfs_set_ntquota(fsp, SMB_USER_FS_QUOTA_TYPE, NULL, &quotas)!=0) {
4045 DEBUG(1, ("vfs_set_ntquota() failed for service [%s]\n",
4046 lp_servicename(talloc_tos(), SNUM(conn))));
4047 status = map_nt_error_from_unix(errno);
4048 } else {
4049 status = NT_STATUS_OK;
4051 return status;
4054 NTSTATUS smbd_do_setfsinfo(connection_struct *conn,
4055 struct smb_request *req,
4056 TALLOC_CTX *mem_ctx,
4057 uint16_t info_level,
4058 files_struct *fsp,
4059 const DATA_BLOB *pdata)
4061 switch (info_level) {
4062 case SMB_FS_QUOTA_INFORMATION:
4064 return smb_set_fsquota(conn,
4065 req,
4066 fsp,
4067 pdata);
4070 default:
4071 break;
4073 return NT_STATUS_INVALID_LEVEL;
4076 /****************************************************************************
4077 Reply to a TRANS2_QFSINFO (query filesystem info).
4078 ****************************************************************************/
4080 static void call_trans2qfsinfo(connection_struct *conn,
4081 struct smb_request *req,
4082 char **pparams, int total_params,
4083 char **ppdata, int total_data,
4084 unsigned int max_data_bytes)
4086 char *params = *pparams;
4087 uint16_t info_level;
4088 int data_len = 0;
4089 size_t fixed_portion;
4090 NTSTATUS status;
4092 if (total_params < 2) {
4093 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4094 return;
4097 info_level = SVAL(params,0);
4099 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4100 if (info_level != SMB_QUERY_CIFS_UNIX_INFO) {
4101 DEBUG(0,("call_trans2qfsinfo: encryption required "
4102 "and info level 0x%x sent.\n",
4103 (unsigned int)info_level));
4104 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4105 return;
4109 DEBUG(3,("call_trans2qfsinfo: level = %d\n", info_level));
4111 status = smbd_do_qfsinfo(req->xconn, conn, req,
4112 info_level,
4113 req->flags2,
4114 max_data_bytes,
4115 &fixed_portion,
4116 NULL,
4117 ppdata, &data_len);
4118 if (!NT_STATUS_IS_OK(status)) {
4119 reply_nterror(req, status);
4120 return;
4123 send_trans2_replies(conn, req, NT_STATUS_OK, params, 0, *ppdata, data_len,
4124 max_data_bytes);
4126 DEBUG( 4, ( "%s info_level = %d\n",
4127 smb_fn_name(req->cmd), info_level) );
4129 return;
4132 /****************************************************************************
4133 Reply to a TRANS2_SETFSINFO (set filesystem info).
4134 ****************************************************************************/
4136 static void call_trans2setfsinfo(connection_struct *conn,
4137 struct smb_request *req,
4138 char **pparams, int total_params,
4139 char **ppdata, int total_data,
4140 unsigned int max_data_bytes)
4142 struct smbXsrv_connection *xconn = req->xconn;
4143 char *pdata = *ppdata;
4144 char *params = *pparams;
4145 uint16_t info_level;
4147 DEBUG(10,("call_trans2setfsinfo: for service [%s]\n",
4148 lp_servicename(talloc_tos(), SNUM(conn))));
4150 /* */
4151 if (total_params < 4) {
4152 DEBUG(0,("call_trans2setfsinfo: requires total_params(%d) >= 4 bytes!\n",
4153 total_params));
4154 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4155 return;
4158 info_level = SVAL(params,2);
4160 if (IS_IPC(conn)) {
4161 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION &&
4162 info_level != SMB_SET_CIFS_UNIX_INFO) {
4163 DEBUG(0,("call_trans2setfsinfo: not an allowed "
4164 "info level (0x%x) on IPC$.\n",
4165 (unsigned int)info_level));
4166 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4167 return;
4171 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
4172 if (info_level != SMB_REQUEST_TRANSPORT_ENCRYPTION) {
4173 DEBUG(0,("call_trans2setfsinfo: encryption required "
4174 "and info level 0x%x sent.\n",
4175 (unsigned int)info_level));
4176 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4177 return;
4181 switch(info_level) {
4182 case SMB_SET_CIFS_UNIX_INFO:
4183 if (!lp_unix_extensions()) {
4184 DEBUG(2,("call_trans2setfsinfo: "
4185 "SMB_SET_CIFS_UNIX_INFO is invalid with "
4186 "unix extensions off\n"));
4187 reply_nterror(req,
4188 NT_STATUS_INVALID_LEVEL);
4189 return;
4192 /* There should be 12 bytes of capabilities set. */
4193 if (total_data < 12) {
4194 reply_nterror(
4195 req,
4196 NT_STATUS_INVALID_PARAMETER);
4197 return;
4199 xconn->smb1.unix_info.client_major = SVAL(pdata,0);
4200 xconn->smb1.unix_info.client_minor = SVAL(pdata,2);
4201 xconn->smb1.unix_info.client_cap_low = IVAL(pdata,4);
4202 xconn->smb1.unix_info.client_cap_high = IVAL(pdata,8);
4203 /* Just print these values for now. */
4204 DEBUG(10, ("call_trans2setfsinfo: set unix_info info. "
4205 "major = %u, minor = %u cap_low = 0x%x, "
4206 "cap_high = 0x%xn",
4207 (unsigned int)xconn->
4208 smb1.unix_info.client_major,
4209 (unsigned int)xconn->
4210 smb1.unix_info.client_minor,
4211 (unsigned int)xconn->
4212 smb1.unix_info.client_cap_low,
4213 (unsigned int)xconn->
4214 smb1.unix_info.client_cap_high));
4216 /* Here is where we must switch to posix pathname processing... */
4217 if (xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
4218 lp_set_posix_pathnames();
4219 mangle_change_to_posix();
4222 if ((xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_FCNTL_LOCKS_CAP) &&
4223 !(xconn->smb1.unix_info.client_cap_low & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP)) {
4224 /* Client that knows how to do posix locks,
4225 * but not posix open/mkdir operations. Set a
4226 * default type for read/write checks. */
4228 lp_set_posix_default_cifsx_readwrite_locktype(POSIX_LOCK);
4231 break;
4233 case SMB_REQUEST_TRANSPORT_ENCRYPTION:
4235 NTSTATUS status;
4236 size_t param_len = 0;
4237 size_t data_len = total_data;
4239 if (!lp_unix_extensions()) {
4240 reply_nterror(
4241 req,
4242 NT_STATUS_INVALID_LEVEL);
4243 return;
4246 if (lp_smb_encrypt(SNUM(conn)) == SMB_SIGNING_OFF) {
4247 reply_nterror(
4248 req,
4249 NT_STATUS_NOT_SUPPORTED);
4250 return;
4253 if (xconn->smb1.echo_handler.trusted_fde) {
4254 DEBUG( 2,("call_trans2setfsinfo: "
4255 "request transport encryption disabled"
4256 "with 'fork echo handler = yes'\n"));
4257 reply_nterror(
4258 req,
4259 NT_STATUS_NOT_SUPPORTED);
4260 return;
4263 DEBUG( 4,("call_trans2setfsinfo: "
4264 "request transport encryption.\n"));
4266 status = srv_request_encryption_setup(conn,
4267 (unsigned char **)ppdata,
4268 &data_len,
4269 (unsigned char **)pparams,
4270 &param_len);
4272 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) &&
4273 !NT_STATUS_IS_OK(status)) {
4274 reply_nterror(req, status);
4275 return;
4278 send_trans2_replies(conn, req,
4279 NT_STATUS_OK,
4280 *pparams,
4281 param_len,
4282 *ppdata,
4283 data_len,
4284 max_data_bytes);
4286 if (NT_STATUS_IS_OK(status)) {
4287 /* Server-side transport
4288 * encryption is now *on*. */
4289 status = srv_encryption_start(conn);
4290 if (!NT_STATUS_IS_OK(status)) {
4291 char *reason = talloc_asprintf(talloc_tos(),
4292 "Failure in setting "
4293 "up encrypted transport: %s",
4294 nt_errstr(status));
4295 exit_server_cleanly(reason);
4298 return;
4301 case SMB_FS_QUOTA_INFORMATION:
4303 NTSTATUS status;
4304 DATA_BLOB qdata = {
4305 .data = (uint8_t *)pdata,
4306 .length = total_data
4308 files_struct *fsp = NULL;
4309 fsp = file_fsp(req, SVAL(params,0));
4311 status = smb_set_fsquota(conn,
4312 req,
4313 fsp,
4314 &qdata);
4315 if (!NT_STATUS_IS_OK(status)) {
4316 reply_nterror(req, status);
4317 return;
4319 break;
4321 default:
4322 DEBUG(3,("call_trans2setfsinfo: unknown level (0x%X) not implemented yet.\n",
4323 info_level));
4324 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4325 return;
4326 break;
4330 * sending this reply works fine,
4331 * but I'm not sure it's the same
4332 * like windows do...
4333 * --metze
4335 reply_outbuf(req, 10, 0);
4338 #if defined(HAVE_POSIX_ACLS)
4339 /****************************************************************************
4340 Utility function to count the number of entries in a POSIX acl.
4341 ****************************************************************************/
4343 static unsigned int count_acl_entries(connection_struct *conn, SMB_ACL_T posix_acl)
4345 unsigned int ace_count = 0;
4346 int entry_id = SMB_ACL_FIRST_ENTRY;
4347 SMB_ACL_ENTRY_T entry;
4349 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4350 /* get_next... */
4351 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4352 entry_id = SMB_ACL_NEXT_ENTRY;
4354 ace_count++;
4356 return ace_count;
4359 /****************************************************************************
4360 Utility function to marshall a POSIX acl into wire format.
4361 ****************************************************************************/
4363 static bool marshall_posix_acl(connection_struct *conn, char *pdata, SMB_STRUCT_STAT *pst, SMB_ACL_T posix_acl)
4365 int entry_id = SMB_ACL_FIRST_ENTRY;
4366 SMB_ACL_ENTRY_T entry;
4368 while ( posix_acl && (sys_acl_get_entry(posix_acl, entry_id, &entry) == 1)) {
4369 SMB_ACL_TAG_T tagtype;
4370 SMB_ACL_PERMSET_T permset;
4371 unsigned char perms = 0;
4372 unsigned int own_grp;
4374 /* get_next... */
4375 if (entry_id == SMB_ACL_FIRST_ENTRY) {
4376 entry_id = SMB_ACL_NEXT_ENTRY;
4379 if (sys_acl_get_tag_type(entry, &tagtype) == -1) {
4380 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_TAG_TYPE failed.\n"));
4381 return False;
4384 if (sys_acl_get_permset(entry, &permset) == -1) {
4385 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_PERMSET failed.\n"));
4386 return False;
4389 perms |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? SMB_POSIX_ACL_READ : 0);
4390 perms |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? SMB_POSIX_ACL_WRITE : 0);
4391 perms |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? SMB_POSIX_ACL_EXECUTE : 0);
4393 SCVAL(pdata,1,perms);
4395 switch (tagtype) {
4396 case SMB_ACL_USER_OBJ:
4397 SCVAL(pdata,0,SMB_POSIX_ACL_USER_OBJ);
4398 own_grp = (unsigned int)pst->st_ex_uid;
4399 SIVAL(pdata,2,own_grp);
4400 SIVAL(pdata,6,0);
4401 break;
4402 case SMB_ACL_USER:
4404 uid_t *puid = (uid_t *)sys_acl_get_qualifier(entry);
4405 if (!puid) {
4406 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4407 return False;
4409 own_grp = (unsigned int)*puid;
4410 SCVAL(pdata,0,SMB_POSIX_ACL_USER);
4411 SIVAL(pdata,2,own_grp);
4412 SIVAL(pdata,6,0);
4413 break;
4415 case SMB_ACL_GROUP_OBJ:
4416 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP_OBJ);
4417 own_grp = (unsigned int)pst->st_ex_gid;
4418 SIVAL(pdata,2,own_grp);
4419 SIVAL(pdata,6,0);
4420 break;
4421 case SMB_ACL_GROUP:
4423 gid_t *pgid= (gid_t *)sys_acl_get_qualifier(entry);
4424 if (!pgid) {
4425 DEBUG(0,("marshall_posix_acl: SMB_VFS_SYS_ACL_GET_QUALIFIER failed.\n"));
4426 return False;
4428 own_grp = (unsigned int)*pgid;
4429 SCVAL(pdata,0,SMB_POSIX_ACL_GROUP);
4430 SIVAL(pdata,2,own_grp);
4431 SIVAL(pdata,6,0);
4432 break;
4434 case SMB_ACL_MASK:
4435 SCVAL(pdata,0,SMB_POSIX_ACL_MASK);
4436 SIVAL(pdata,2,0xFFFFFFFF);
4437 SIVAL(pdata,6,0xFFFFFFFF);
4438 break;
4439 case SMB_ACL_OTHER:
4440 SCVAL(pdata,0,SMB_POSIX_ACL_OTHER);
4441 SIVAL(pdata,2,0xFFFFFFFF);
4442 SIVAL(pdata,6,0xFFFFFFFF);
4443 break;
4444 default:
4445 DEBUG(0,("marshall_posix_acl: unknown tagtype.\n"));
4446 return False;
4448 pdata += SMB_POSIX_ACL_ENTRY_SIZE;
4451 return True;
4453 #endif
4455 /****************************************************************************
4456 Store the FILE_UNIX_BASIC info.
4457 ****************************************************************************/
4459 static char *store_file_unix_basic(connection_struct *conn,
4460 char *pdata,
4461 files_struct *fsp,
4462 const SMB_STRUCT_STAT *psbuf)
4464 uint64_t file_index = get_FileIndex(conn, psbuf);
4465 dev_t devno;
4467 DEBUG(10,("store_file_unix_basic: SMB_QUERY_FILE_UNIX_BASIC\n"));
4468 DEBUG(4,("store_file_unix_basic: st_mode=%o\n",(int)psbuf->st_ex_mode));
4470 SOFF_T(pdata,0,get_file_size_stat(psbuf)); /* File size 64 Bit */
4471 pdata += 8;
4473 SOFF_T(pdata,0,SMB_VFS_GET_ALLOC_SIZE(conn,fsp,psbuf)); /* Number of bytes used on disk - 64 Bit */
4474 pdata += 8;
4476 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata, psbuf->st_ex_ctime); /* Change Time 64 Bit */
4477 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER ,pdata+8, psbuf->st_ex_atime); /* Last access time 64 Bit */
4478 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER, pdata+16, psbuf->st_ex_mtime); /* Last modification time 64 Bit */
4479 pdata += 24;
4481 SIVAL(pdata,0,psbuf->st_ex_uid); /* user id for the owner */
4482 SIVAL(pdata,4,0);
4483 pdata += 8;
4485 SIVAL(pdata,0,psbuf->st_ex_gid); /* group id of owner */
4486 SIVAL(pdata,4,0);
4487 pdata += 8;
4489 SIVAL(pdata,0,unix_filetype(psbuf->st_ex_mode));
4490 pdata += 4;
4492 if (S_ISBLK(psbuf->st_ex_mode) || S_ISCHR(psbuf->st_ex_mode)) {
4493 devno = psbuf->st_ex_rdev;
4494 } else {
4495 devno = psbuf->st_ex_dev;
4498 SIVAL(pdata,0,unix_dev_major(devno)); /* Major device number if type is device */
4499 SIVAL(pdata,4,0);
4500 pdata += 8;
4502 SIVAL(pdata,0,unix_dev_minor(devno)); /* Minor device number if type is device */
4503 SIVAL(pdata,4,0);
4504 pdata += 8;
4506 SINO_T_VAL(pdata,0,(SMB_INO_T)file_index); /* inode number */
4507 pdata += 8;
4509 SIVAL(pdata,0, unix_perms_to_wire(psbuf->st_ex_mode)); /* Standard UNIX file permissions */
4510 SIVAL(pdata,4,0);
4511 pdata += 8;
4513 SIVAL(pdata,0,psbuf->st_ex_nlink); /* number of hard links */
4514 SIVAL(pdata,4,0);
4515 pdata += 8;
4517 return pdata;
4520 /* Forward and reverse mappings from the UNIX_INFO2 file flags field and
4521 * the chflags(2) (or equivalent) flags.
4523 * XXX: this really should be behind the VFS interface. To do this, we would
4524 * need to alter SMB_STRUCT_STAT so that it included a flags and a mask field.
4525 * Each VFS module could then implement its own mapping as appropriate for the
4526 * platform. We would then pass the SMB flags into SMB_VFS_CHFLAGS.
4528 static const struct {unsigned stat_fflag; unsigned smb_fflag;}
4529 info2_flags_map[] =
4531 #ifdef UF_NODUMP
4532 { UF_NODUMP, EXT_DO_NOT_BACKUP },
4533 #endif
4535 #ifdef UF_IMMUTABLE
4536 { UF_IMMUTABLE, EXT_IMMUTABLE },
4537 #endif
4539 #ifdef UF_APPEND
4540 { UF_APPEND, EXT_OPEN_APPEND_ONLY },
4541 #endif
4543 #ifdef UF_HIDDEN
4544 { UF_HIDDEN, EXT_HIDDEN },
4545 #endif
4547 /* Do not remove. We need to guarantee that this array has at least one
4548 * entry to build on HP-UX.
4550 { 0, 0 }
4554 static void map_info2_flags_from_sbuf(const SMB_STRUCT_STAT *psbuf,
4555 uint32_t *smb_fflags, uint32_t *smb_fmask)
4557 int i;
4559 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4560 *smb_fmask |= info2_flags_map[i].smb_fflag;
4561 if (psbuf->st_ex_flags & info2_flags_map[i].stat_fflag) {
4562 *smb_fflags |= info2_flags_map[i].smb_fflag;
4567 static bool map_info2_flags_to_sbuf(const SMB_STRUCT_STAT *psbuf,
4568 const uint32_t smb_fflags,
4569 const uint32_t smb_fmask,
4570 int *stat_fflags)
4572 uint32_t max_fmask = 0;
4573 int i;
4575 *stat_fflags = psbuf->st_ex_flags;
4577 /* For each flags requested in smb_fmask, check the state of the
4578 * corresponding flag in smb_fflags and set or clear the matching
4579 * stat flag.
4582 for (i = 0; i < ARRAY_SIZE(info2_flags_map); ++i) {
4583 max_fmask |= info2_flags_map[i].smb_fflag;
4584 if (smb_fmask & info2_flags_map[i].smb_fflag) {
4585 if (smb_fflags & info2_flags_map[i].smb_fflag) {
4586 *stat_fflags |= info2_flags_map[i].stat_fflag;
4587 } else {
4588 *stat_fflags &= ~info2_flags_map[i].stat_fflag;
4593 /* If smb_fmask is asking to set any bits that are not supported by
4594 * our flag mappings, we should fail.
4596 if ((smb_fmask & max_fmask) != smb_fmask) {
4597 return False;
4600 return True;
4604 /* Just like SMB_QUERY_FILE_UNIX_BASIC, but with the addition
4605 * of file flags and birth (create) time.
4607 static char *store_file_unix_basic_info2(connection_struct *conn,
4608 char *pdata,
4609 files_struct *fsp,
4610 const SMB_STRUCT_STAT *psbuf)
4612 uint32_t file_flags = 0;
4613 uint32_t flags_mask = 0;
4615 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
4617 /* Create (birth) time 64 bit */
4618 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,pdata, psbuf->st_ex_btime);
4619 pdata += 8;
4621 map_info2_flags_from_sbuf(psbuf, &file_flags, &flags_mask);
4622 SIVAL(pdata, 0, file_flags); /* flags */
4623 SIVAL(pdata, 4, flags_mask); /* mask */
4624 pdata += 8;
4626 return pdata;
4629 static NTSTATUS marshall_stream_info(unsigned int num_streams,
4630 const struct stream_struct *streams,
4631 char *data,
4632 unsigned int max_data_bytes,
4633 unsigned int *data_size)
4635 unsigned int i;
4636 unsigned int ofs = 0;
4638 if (max_data_bytes < 32) {
4639 return NT_STATUS_INFO_LENGTH_MISMATCH;
4642 for (i = 0; i < num_streams; i++) {
4643 unsigned int next_offset;
4644 size_t namelen;
4645 smb_ucs2_t *namebuf;
4647 if (!push_ucs2_talloc(talloc_tos(), &namebuf,
4648 streams[i].name, &namelen) ||
4649 namelen <= 2)
4651 return NT_STATUS_INVALID_PARAMETER;
4655 * name_buf is now null-terminated, we need to marshall as not
4656 * terminated
4659 namelen -= 2;
4662 * We cannot overflow ...
4664 if ((ofs + 24 + namelen) > max_data_bytes) {
4665 DEBUG(10, ("refusing to overflow reply at stream %u\n",
4666 i));
4667 TALLOC_FREE(namebuf);
4668 return STATUS_BUFFER_OVERFLOW;
4671 SIVAL(data, ofs+4, namelen);
4672 SOFF_T(data, ofs+8, streams[i].size);
4673 SOFF_T(data, ofs+16, streams[i].alloc_size);
4674 memcpy(data+ofs+24, namebuf, namelen);
4675 TALLOC_FREE(namebuf);
4677 next_offset = ofs + 24 + namelen;
4679 if (i == num_streams-1) {
4680 SIVAL(data, ofs, 0);
4682 else {
4683 unsigned int align = ndr_align_size(next_offset, 8);
4685 if ((next_offset + align) > max_data_bytes) {
4686 DEBUG(10, ("refusing to overflow align "
4687 "reply at stream %u\n",
4688 i));
4689 TALLOC_FREE(namebuf);
4690 return STATUS_BUFFER_OVERFLOW;
4693 memset(data+next_offset, 0, align);
4694 next_offset += align;
4696 SIVAL(data, ofs, next_offset - ofs);
4697 ofs = next_offset;
4700 ofs = next_offset;
4703 DEBUG(10, ("max_data: %u, data_size: %u\n", max_data_bytes, ofs));
4705 *data_size = ofs;
4707 return NT_STATUS_OK;
4710 /****************************************************************************
4711 Reply to a TRANSACT2_QFILEINFO on a PIPE !
4712 ****************************************************************************/
4714 static void call_trans2qpipeinfo(connection_struct *conn,
4715 struct smb_request *req,
4716 unsigned int tran_call,
4717 char **pparams, int total_params,
4718 char **ppdata, int total_data,
4719 unsigned int max_data_bytes)
4721 char *params = *pparams;
4722 char *pdata = *ppdata;
4723 unsigned int data_size = 0;
4724 unsigned int param_size = 2;
4725 uint16_t info_level;
4726 files_struct *fsp;
4728 if (!params) {
4729 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4730 return;
4733 if (total_params < 4) {
4734 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4735 return;
4738 fsp = file_fsp(req, SVAL(params,0));
4739 if (!fsp_is_np(fsp)) {
4740 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
4741 return;
4744 info_level = SVAL(params,2);
4746 *pparams = (char *)SMB_REALLOC(*pparams,2);
4747 if (*pparams == NULL) {
4748 reply_nterror(req, NT_STATUS_NO_MEMORY);
4749 return;
4751 params = *pparams;
4752 SSVAL(params,0,0);
4753 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4754 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4755 return;
4757 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4758 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4759 if (*ppdata == NULL ) {
4760 reply_nterror(req, NT_STATUS_NO_MEMORY);
4761 return;
4763 pdata = *ppdata;
4765 switch (info_level) {
4766 case SMB_FILE_STANDARD_INFORMATION:
4767 memset(pdata,0,24);
4768 SOFF_T(pdata,0,4096LL);
4769 SIVAL(pdata,16,1);
4770 SIVAL(pdata,20,1);
4771 data_size = 24;
4772 break;
4774 default:
4775 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
4776 return;
4779 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
4780 max_data_bytes);
4782 return;
4785 NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
4786 TALLOC_CTX *mem_ctx,
4787 uint16_t info_level,
4788 files_struct *fsp,
4789 struct smb_filename *smb_fname,
4790 bool delete_pending,
4791 struct timespec write_time_ts,
4792 struct ea_list *ea_list,
4793 int lock_data_count,
4794 char *lock_data,
4795 uint16_t flags2,
4796 unsigned int max_data_bytes,
4797 size_t *fixed_portion,
4798 char **ppdata,
4799 unsigned int *pdata_size)
4801 char *pdata = *ppdata;
4802 char *dstart, *dend;
4803 unsigned int data_size;
4804 struct timespec create_time_ts, mtime_ts, atime_ts, ctime_ts;
4805 time_t create_time, mtime, atime, c_time;
4806 SMB_STRUCT_STAT *psbuf = &smb_fname->st;
4807 char *p;
4808 char *base_name;
4809 char *dos_fname;
4810 int mode;
4811 int nlink;
4812 NTSTATUS status;
4813 uint64_t file_size = 0;
4814 uint64_t pos = 0;
4815 uint64_t allocation_size = 0;
4816 uint64_t file_index = 0;
4817 uint32_t access_mask = 0;
4818 size_t len = 0;
4820 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
4821 return NT_STATUS_INVALID_LEVEL;
4824 DEBUG(5,("smbd_do_qfilepathinfo: %s (%s) level=%d max_data=%u\n",
4825 smb_fname_str_dbg(smb_fname),
4826 fsp_fnum_dbg(fsp),
4827 info_level, max_data_bytes));
4829 mode = dos_mode(conn, smb_fname);
4830 nlink = psbuf->st_ex_nlink;
4832 if (nlink && (mode&FILE_ATTRIBUTE_DIRECTORY)) {
4833 nlink = 1;
4836 if ((nlink > 0) && delete_pending) {
4837 nlink -= 1;
4840 if (max_data_bytes + DIR_ENTRY_SAFETY_MARGIN < max_data_bytes) {
4841 return NT_STATUS_INVALID_PARAMETER;
4844 data_size = max_data_bytes + DIR_ENTRY_SAFETY_MARGIN;
4845 *ppdata = (char *)SMB_REALLOC(*ppdata, data_size);
4846 if (*ppdata == NULL) {
4847 return NT_STATUS_NO_MEMORY;
4849 pdata = *ppdata;
4850 dstart = pdata;
4851 dend = dstart + data_size - 1;
4853 if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
4854 update_stat_ex_mtime(psbuf, write_time_ts);
4857 create_time_ts = get_create_timespec(conn, fsp, smb_fname);
4858 mtime_ts = psbuf->st_ex_mtime;
4859 atime_ts = psbuf->st_ex_atime;
4860 ctime_ts = get_change_timespec(conn, fsp, smb_fname);
4862 if (lp_dos_filetime_resolution(SNUM(conn))) {
4863 dos_filetime_timespec(&create_time_ts);
4864 dos_filetime_timespec(&mtime_ts);
4865 dos_filetime_timespec(&atime_ts);
4866 dos_filetime_timespec(&ctime_ts);
4869 create_time = convert_timespec_to_time_t(create_time_ts);
4870 mtime = convert_timespec_to_time_t(mtime_ts);
4871 atime = convert_timespec_to_time_t(atime_ts);
4872 c_time = convert_timespec_to_time_t(ctime_ts);
4874 p = strrchr_m(smb_fname->base_name,'/');
4875 if (!p)
4876 base_name = smb_fname->base_name;
4877 else
4878 base_name = p+1;
4880 /* NT expects the name to be in an exact form of the *full*
4881 filename. See the trans2 torture test */
4882 if (ISDOT(base_name)) {
4883 dos_fname = talloc_strdup(mem_ctx, "\\");
4884 if (!dos_fname) {
4885 return NT_STATUS_NO_MEMORY;
4887 } else {
4888 dos_fname = talloc_asprintf(mem_ctx,
4889 "\\%s",
4890 smb_fname->base_name);
4891 if (!dos_fname) {
4892 return NT_STATUS_NO_MEMORY;
4894 if (is_ntfs_stream_smb_fname(smb_fname)) {
4895 dos_fname = talloc_asprintf(dos_fname, "%s",
4896 smb_fname->stream_name);
4897 if (!dos_fname) {
4898 return NT_STATUS_NO_MEMORY;
4902 string_replace(dos_fname, '/', '\\');
4905 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp, psbuf);
4907 if (!fsp) {
4908 /* Do we have this path open ? */
4909 files_struct *fsp1;
4910 struct file_id fileid = vfs_file_id_from_sbuf(conn, psbuf);
4911 fsp1 = file_find_di_first(conn->sconn, fileid);
4912 if (fsp1 && fsp1->initial_allocation_size) {
4913 allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn, fsp1, psbuf);
4917 if (!(mode & FILE_ATTRIBUTE_DIRECTORY)) {
4918 file_size = get_file_size_stat(psbuf);
4921 if (fsp) {
4922 pos = fsp->fh->position_information;
4925 if (fsp) {
4926 access_mask = fsp->access_mask;
4927 } else {
4928 /* GENERIC_EXECUTE mapping from Windows */
4929 access_mask = 0x12019F;
4932 /* This should be an index number - looks like
4933 dev/ino to me :-)
4935 I think this causes us to fail the IFSKIT
4936 BasicFileInformationTest. -tpot */
4937 file_index = get_FileIndex(conn, psbuf);
4939 *fixed_portion = 0;
4941 switch (info_level) {
4942 case SMB_INFO_STANDARD:
4943 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_STANDARD\n"));
4944 data_size = 22;
4945 srv_put_dos_date2(pdata,l1_fdateCreation,create_time);
4946 srv_put_dos_date2(pdata,l1_fdateLastAccess,atime);
4947 srv_put_dos_date2(pdata,l1_fdateLastWrite,mtime); /* write time */
4948 SIVAL(pdata,l1_cbFile,(uint32_t)file_size);
4949 SIVAL(pdata,l1_cbFileAlloc,(uint32_t)allocation_size);
4950 SSVAL(pdata,l1_attrFile,mode);
4951 break;
4953 case SMB_INFO_QUERY_EA_SIZE:
4955 unsigned int ea_size =
4956 estimate_ea_size(conn, fsp,
4957 smb_fname);
4958 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EA_SIZE\n"));
4959 data_size = 26;
4960 srv_put_dos_date2(pdata,0,create_time);
4961 srv_put_dos_date2(pdata,4,atime);
4962 srv_put_dos_date2(pdata,8,mtime); /* write time */
4963 SIVAL(pdata,12,(uint32_t)file_size);
4964 SIVAL(pdata,16,(uint32_t)allocation_size);
4965 SSVAL(pdata,20,mode);
4966 SIVAL(pdata,22,ea_size);
4967 break;
4970 case SMB_INFO_IS_NAME_VALID:
4971 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_IS_NAME_VALID\n"));
4972 if (fsp) {
4973 /* os/2 needs this ? really ?*/
4974 return NT_STATUS_DOS(ERRDOS, ERRbadfunc);
4976 /* This is only reached for qpathinfo */
4977 data_size = 0;
4978 break;
4980 case SMB_INFO_QUERY_EAS_FROM_LIST:
4982 size_t total_ea_len = 0;
4983 struct ea_list *ea_file_list = NULL;
4984 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_EAS_FROM_LIST\n"));
4986 status =
4987 get_ea_list_from_file(mem_ctx, conn, fsp,
4988 smb_fname,
4989 &total_ea_len, &ea_file_list);
4990 if (!NT_STATUS_IS_OK(status)) {
4991 return status;
4994 ea_list = ea_list_union(ea_list, ea_file_list, &total_ea_len);
4996 if (!ea_list || (total_ea_len > data_size)) {
4997 data_size = 4;
4998 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
4999 break;
5002 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5003 break;
5006 case SMB_INFO_QUERY_ALL_EAS:
5008 /* We have data_size bytes to put EA's into. */
5009 size_t total_ea_len = 0;
5010 DEBUG(10,("smbd_do_qfilepathinfo: SMB_INFO_QUERY_ALL_EAS\n"));
5012 status = get_ea_list_from_file(mem_ctx, conn, fsp,
5013 smb_fname,
5014 &total_ea_len, &ea_list);
5015 if (!NT_STATUS_IS_OK(status)) {
5016 return status;
5019 if (!ea_list || (total_ea_len > data_size)) {
5020 data_size = 4;
5021 SIVAL(pdata,0,4); /* EA List Length must be set to 4 if no EA's. */
5022 break;
5025 data_size = fill_ea_buffer(mem_ctx, pdata, data_size, conn, ea_list);
5026 break;
5029 case 0xFF0F:/*SMB2_INFO_QUERY_ALL_EAS*/
5031 /* This is FileFullEaInformation - 0xF which maps to
5032 * 1015 (decimal) in smbd_do_setfilepathinfo. */
5034 /* We have data_size bytes to put EA's into. */
5035 size_t total_ea_len = 0;
5036 struct ea_list *ea_file_list = NULL;
5038 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_INFO_QUERY_ALL_EAS\n"));
5040 /*TODO: add filtering and index handling */
5042 status =
5043 get_ea_list_from_file(mem_ctx, conn, fsp,
5044 smb_fname,
5045 &total_ea_len, &ea_file_list);
5046 if (!NT_STATUS_IS_OK(status)) {
5047 return status;
5049 if (!ea_file_list) {
5050 return NT_STATUS_NO_EAS_ON_FILE;
5053 status = fill_ea_chained_buffer(mem_ctx,
5054 pdata,
5055 data_size,
5056 &data_size,
5057 conn, ea_file_list);
5058 if (!NT_STATUS_IS_OK(status)) {
5059 return status;
5061 break;
5064 case SMB_FILE_BASIC_INFORMATION:
5065 case SMB_QUERY_FILE_BASIC_INFO:
5067 if (info_level == SMB_QUERY_FILE_BASIC_INFO) {
5068 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_BASIC_INFO\n"));
5069 data_size = 36; /* w95 returns 40 bytes not 36 - why ?. */
5070 } else {
5071 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_BASIC_INFORMATION\n"));
5072 data_size = 40;
5073 SIVAL(pdata,36,0);
5075 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5076 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5077 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5078 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5079 SIVAL(pdata,32,mode);
5081 DEBUG(5,("SMB_QFBI - "));
5082 DEBUG(5,("create: %s ", ctime(&create_time)));
5083 DEBUG(5,("access: %s ", ctime(&atime)));
5084 DEBUG(5,("write: %s ", ctime(&mtime)));
5085 DEBUG(5,("change: %s ", ctime(&c_time)));
5086 DEBUG(5,("mode: %x\n", mode));
5087 *fixed_portion = data_size;
5088 break;
5090 case SMB_FILE_STANDARD_INFORMATION:
5091 case SMB_QUERY_FILE_STANDARD_INFO:
5093 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_STANDARD_INFORMATION\n"));
5094 data_size = 24;
5095 SOFF_T(pdata,0,allocation_size);
5096 SOFF_T(pdata,8,file_size);
5097 SIVAL(pdata,16,nlink);
5098 SCVAL(pdata,20,delete_pending?1:0);
5099 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5100 SSVAL(pdata,22,0); /* Padding. */
5101 *fixed_portion = 24;
5102 break;
5104 case SMB_FILE_EA_INFORMATION:
5105 case SMB_QUERY_FILE_EA_INFO:
5107 unsigned int ea_size =
5108 estimate_ea_size(conn, fsp, smb_fname);
5109 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_EA_INFORMATION\n"));
5110 data_size = 4;
5111 *fixed_portion = 4;
5112 SIVAL(pdata,0,ea_size);
5113 break;
5116 /* Get the 8.3 name - used if NT SMB was negotiated. */
5117 case SMB_QUERY_FILE_ALT_NAME_INFO:
5118 case SMB_FILE_ALTERNATE_NAME_INFORMATION:
5120 char mangled_name[13];
5121 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALTERNATE_NAME_INFORMATION\n"));
5122 if (!name_to_8_3(base_name,mangled_name,
5123 True,conn->params)) {
5124 return NT_STATUS_NO_MEMORY;
5126 status = srvstr_push(dstart, flags2,
5127 pdata+4, mangled_name,
5128 PTR_DIFF(dend, pdata+4),
5129 STR_UNICODE, &len);
5130 if (!NT_STATUS_IS_OK(status)) {
5131 return status;
5133 data_size = 4 + len;
5134 SIVAL(pdata,0,len);
5135 *fixed_portion = 8;
5136 break;
5139 case SMB_QUERY_FILE_NAME_INFO:
5142 this must be *exactly* right for ACLs on mapped drives to work
5144 status = srvstr_push(dstart, flags2,
5145 pdata+4, dos_fname,
5146 PTR_DIFF(dend, pdata+4),
5147 STR_UNICODE, &len);
5148 if (!NT_STATUS_IS_OK(status)) {
5149 return status;
5151 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_NAME_INFO\n"));
5152 data_size = 4 + len;
5153 SIVAL(pdata,0,len);
5154 break;
5157 case SMB_FILE_ALLOCATION_INFORMATION:
5158 case SMB_QUERY_FILE_ALLOCATION_INFO:
5159 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALLOCATION_INFORMATION\n"));
5160 data_size = 8;
5161 SOFF_T(pdata,0,allocation_size);
5162 break;
5164 case SMB_FILE_END_OF_FILE_INFORMATION:
5165 case SMB_QUERY_FILE_END_OF_FILEINFO:
5166 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_END_OF_FILE_INFORMATION\n"));
5167 data_size = 8;
5168 SOFF_T(pdata,0,file_size);
5169 break;
5171 case SMB_QUERY_FILE_ALL_INFO:
5172 case SMB_FILE_ALL_INFORMATION:
5174 unsigned int ea_size =
5175 estimate_ea_size(conn, fsp, smb_fname);
5176 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALL_INFORMATION\n"));
5177 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5178 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5179 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5180 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5181 SIVAL(pdata,32,mode);
5182 SIVAL(pdata,36,0); /* padding. */
5183 pdata += 40;
5184 SOFF_T(pdata,0,allocation_size);
5185 SOFF_T(pdata,8,file_size);
5186 SIVAL(pdata,16,nlink);
5187 SCVAL(pdata,20,delete_pending);
5188 SCVAL(pdata,21,(mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5189 SSVAL(pdata,22,0);
5190 pdata += 24;
5191 SIVAL(pdata,0,ea_size);
5192 pdata += 4; /* EA info */
5193 status = srvstr_push(dstart, flags2,
5194 pdata+4, dos_fname,
5195 PTR_DIFF(dend, pdata+4),
5196 STR_UNICODE, &len);
5197 if (!NT_STATUS_IS_OK(status)) {
5198 return status;
5200 SIVAL(pdata,0,len);
5201 pdata += 4 + len;
5202 data_size = PTR_DIFF(pdata,(*ppdata));
5203 *fixed_portion = 10;
5204 break;
5207 case 0xFF12:/*SMB2_FILE_ALL_INFORMATION*/
5209 unsigned int ea_size =
5210 estimate_ea_size(conn, fsp, smb_fname);
5211 DEBUG(10,("smbd_do_qfilepathinfo: SMB2_FILE_ALL_INFORMATION\n"));
5212 put_long_date_timespec(conn->ts_res,pdata+0x00,create_time_ts);
5213 put_long_date_timespec(conn->ts_res,pdata+0x08,atime_ts);
5214 put_long_date_timespec(conn->ts_res,pdata+0x10,mtime_ts); /* write time */
5215 put_long_date_timespec(conn->ts_res,pdata+0x18,ctime_ts); /* change time */
5216 SIVAL(pdata, 0x20, mode);
5217 SIVAL(pdata, 0x24, 0); /* padding. */
5218 SBVAL(pdata, 0x28, allocation_size);
5219 SBVAL(pdata, 0x30, file_size);
5220 SIVAL(pdata, 0x38, nlink);
5221 SCVAL(pdata, 0x3C, delete_pending);
5222 SCVAL(pdata, 0x3D, (mode&FILE_ATTRIBUTE_DIRECTORY)?1:0);
5223 SSVAL(pdata, 0x3E, 0); /* padding */
5224 SBVAL(pdata, 0x40, file_index);
5225 SIVAL(pdata, 0x48, ea_size);
5226 SIVAL(pdata, 0x4C, access_mask);
5227 SBVAL(pdata, 0x50, pos);
5228 SIVAL(pdata, 0x58, mode); /*TODO: mode != mode fix this!!! */
5229 SIVAL(pdata, 0x5C, 0); /* No alignment needed. */
5231 pdata += 0x60;
5233 status = srvstr_push(dstart, flags2,
5234 pdata+4, dos_fname,
5235 PTR_DIFF(dend, pdata+4),
5236 STR_UNICODE, &len);
5237 if (!NT_STATUS_IS_OK(status)) {
5238 return status;
5240 SIVAL(pdata,0,len);
5241 pdata += 4 + len;
5242 data_size = PTR_DIFF(pdata,(*ppdata));
5243 *fixed_portion = 104;
5244 break;
5246 case SMB_FILE_INTERNAL_INFORMATION:
5248 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_INTERNAL_INFORMATION\n"));
5249 SBVAL(pdata, 0, file_index);
5250 data_size = 8;
5251 *fixed_portion = 8;
5252 break;
5254 case SMB_FILE_ACCESS_INFORMATION:
5255 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ACCESS_INFORMATION\n"));
5256 SIVAL(pdata, 0, access_mask);
5257 data_size = 4;
5258 *fixed_portion = 4;
5259 break;
5261 case SMB_FILE_NAME_INFORMATION:
5262 /* Pathname with leading '\'. */
5264 size_t byte_len;
5265 byte_len = dos_PutUniCode(pdata+4,dos_fname,(size_t)max_data_bytes,False);
5266 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NAME_INFORMATION\n"));
5267 SIVAL(pdata,0,byte_len);
5268 data_size = 4 + byte_len;
5269 break;
5272 case SMB_FILE_DISPOSITION_INFORMATION:
5273 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_DISPOSITION_INFORMATION\n"));
5274 data_size = 1;
5275 SCVAL(pdata,0,delete_pending);
5276 *fixed_portion = 1;
5277 break;
5279 case SMB_FILE_POSITION_INFORMATION:
5280 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_POSITION_INFORMATION\n"));
5281 data_size = 8;
5282 SOFF_T(pdata,0,pos);
5283 *fixed_portion = 8;
5284 break;
5286 case SMB_FILE_MODE_INFORMATION:
5287 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_MODE_INFORMATION\n"));
5288 SIVAL(pdata,0,mode);
5289 data_size = 4;
5290 *fixed_portion = 4;
5291 break;
5293 case SMB_FILE_ALIGNMENT_INFORMATION:
5294 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ALIGNMENT_INFORMATION\n"));
5295 SIVAL(pdata,0,0); /* No alignment needed. */
5296 data_size = 4;
5297 *fixed_portion = 4;
5298 break;
5301 * NT4 server just returns "invalid query" to this - if we try
5302 * to answer it then NTws gets a BSOD! (tridge). W2K seems to
5303 * want this. JRA.
5305 /* The first statement above is false - verified using Thursby
5306 * client against NT4 -- gcolley.
5308 case SMB_QUERY_FILE_STREAM_INFO:
5309 case SMB_FILE_STREAM_INFORMATION: {
5310 unsigned int num_streams = 0;
5311 struct stream_struct *streams = NULL;
5313 DEBUG(10,("smbd_do_qfilepathinfo: "
5314 "SMB_FILE_STREAM_INFORMATION\n"));
5316 if (is_ntfs_stream_smb_fname(smb_fname)) {
5317 return NT_STATUS_INVALID_PARAMETER;
5320 status = vfs_streaminfo(conn,
5321 fsp,
5322 smb_fname,
5323 talloc_tos(),
5324 &num_streams,
5325 &streams);
5327 if (!NT_STATUS_IS_OK(status)) {
5328 DEBUG(10, ("could not get stream info: %s\n",
5329 nt_errstr(status)));
5330 return status;
5333 status = marshall_stream_info(num_streams, streams,
5334 pdata, max_data_bytes,
5335 &data_size);
5337 if (!NT_STATUS_IS_OK(status)) {
5338 DEBUG(10, ("marshall_stream_info failed: %s\n",
5339 nt_errstr(status)));
5340 TALLOC_FREE(streams);
5341 return status;
5344 TALLOC_FREE(streams);
5346 *fixed_portion = 32;
5348 break;
5350 case SMB_QUERY_COMPRESSION_INFO:
5351 case SMB_FILE_COMPRESSION_INFORMATION:
5352 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n"));
5353 SOFF_T(pdata,0,file_size);
5354 SIVAL(pdata,8,0); /* ??? */
5355 SIVAL(pdata,12,0); /* ??? */
5356 data_size = 16;
5357 *fixed_portion = 16;
5358 break;
5360 case SMB_FILE_NETWORK_OPEN_INFORMATION:
5361 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_NETWORK_OPEN_INFORMATION\n"));
5362 put_long_date_timespec(conn->ts_res,pdata,create_time_ts);
5363 put_long_date_timespec(conn->ts_res,pdata+8,atime_ts);
5364 put_long_date_timespec(conn->ts_res,pdata+16,mtime_ts); /* write time */
5365 put_long_date_timespec(conn->ts_res,pdata+24,ctime_ts); /* change time */
5366 SOFF_T(pdata,32,allocation_size);
5367 SOFF_T(pdata,40,file_size);
5368 SIVAL(pdata,48,mode);
5369 SIVAL(pdata,52,0); /* ??? */
5370 data_size = 56;
5371 *fixed_portion = 56;
5372 break;
5374 case SMB_FILE_ATTRIBUTE_TAG_INFORMATION:
5375 DEBUG(10,("smbd_do_qfilepathinfo: SMB_FILE_ATTRIBUTE_TAG_INFORMATION\n"));
5376 SIVAL(pdata,0,mode);
5377 SIVAL(pdata,4,0);
5378 data_size = 8;
5379 *fixed_portion = 8;
5380 break;
5383 * CIFS UNIX Extensions.
5386 case SMB_QUERY_FILE_UNIX_BASIC:
5388 pdata = store_file_unix_basic(conn, pdata, fsp, psbuf);
5389 data_size = PTR_DIFF(pdata,(*ppdata));
5391 DEBUG(4,("smbd_do_qfilepathinfo: "
5392 "SMB_QUERY_FILE_UNIX_BASIC\n"));
5393 dump_data(4, (uint8_t *)(*ppdata), data_size);
5395 break;
5397 case SMB_QUERY_FILE_UNIX_INFO2:
5399 pdata = store_file_unix_basic_info2(conn, pdata, fsp, psbuf);
5400 data_size = PTR_DIFF(pdata,(*ppdata));
5403 int i;
5404 DEBUG(4,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_INFO2 "));
5406 for (i=0; i<100; i++)
5407 DEBUG(4,("%d=%x, ",i, (*ppdata)[i]));
5408 DEBUG(4,("\n"));
5411 break;
5413 case SMB_QUERY_FILE_UNIX_LINK:
5415 int link_len = 0;
5416 char *buffer = talloc_array(mem_ctx, char, PATH_MAX+1);
5418 if (!buffer) {
5419 return NT_STATUS_NO_MEMORY;
5422 DEBUG(10,("smbd_do_qfilepathinfo: SMB_QUERY_FILE_UNIX_LINK\n"));
5423 #ifdef S_ISLNK
5424 if(!S_ISLNK(psbuf->st_ex_mode)) {
5425 return NT_STATUS_DOS(ERRSRV, ERRbadlink);
5427 #else
5428 return NT_STATUS_DOS(ERRDOS, ERRbadlink);
5429 #endif
5430 link_len = SMB_VFS_READLINK(conn,
5431 smb_fname->base_name,
5432 buffer, PATH_MAX);
5433 if (link_len == -1) {
5434 return map_nt_error_from_unix(errno);
5436 buffer[link_len] = 0;
5437 status = srvstr_push(dstart, flags2,
5438 pdata, buffer,
5439 PTR_DIFF(dend, pdata),
5440 STR_TERMINATE, &len);
5441 if (!NT_STATUS_IS_OK(status)) {
5442 return status;
5444 pdata += len;
5445 data_size = PTR_DIFF(pdata,(*ppdata));
5447 break;
5450 #if defined(HAVE_POSIX_ACLS)
5451 case SMB_QUERY_POSIX_ACL:
5453 SMB_ACL_T file_acl = NULL;
5454 SMB_ACL_T def_acl = NULL;
5455 uint16_t num_file_acls = 0;
5456 uint16_t num_def_acls = 0;
5458 status = refuse_symlink(conn,
5459 fsp,
5460 smb_fname);
5461 if (!NT_STATUS_IS_OK(status)) {
5462 return status;
5465 if (fsp && fsp->fh->fd != -1) {
5466 file_acl = SMB_VFS_SYS_ACL_GET_FD(fsp,
5467 talloc_tos());
5468 } else {
5469 file_acl =
5470 SMB_VFS_SYS_ACL_GET_FILE(conn,
5471 smb_fname->base_name,
5472 SMB_ACL_TYPE_ACCESS,
5473 talloc_tos());
5476 if (file_acl == NULL && no_acl_syscall_error(errno)) {
5477 DEBUG(5,("smbd_do_qfilepathinfo: ACLs "
5478 "not implemented on "
5479 "filesystem containing %s\n",
5480 smb_fname->base_name));
5481 return NT_STATUS_NOT_IMPLEMENTED;
5484 if (S_ISDIR(psbuf->st_ex_mode)) {
5485 if (fsp && fsp->is_directory) {
5486 def_acl =
5487 SMB_VFS_SYS_ACL_GET_FILE(
5488 conn,
5489 fsp->fsp_name->base_name,
5490 SMB_ACL_TYPE_DEFAULT,
5491 talloc_tos());
5492 } else {
5493 def_acl =
5494 SMB_VFS_SYS_ACL_GET_FILE(
5495 conn,
5496 smb_fname->base_name,
5497 SMB_ACL_TYPE_DEFAULT,
5498 talloc_tos());
5500 def_acl = free_empty_sys_acl(conn, def_acl);
5503 num_file_acls = count_acl_entries(conn, file_acl);
5504 num_def_acls = count_acl_entries(conn, def_acl);
5506 if ( data_size < (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE) {
5507 DEBUG(5,("smbd_do_qfilepathinfo: data_size too small (%u) need %u\n",
5508 data_size,
5509 (unsigned int)((num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE +
5510 SMB_POSIX_ACL_HEADER_SIZE) ));
5511 if (file_acl) {
5512 TALLOC_FREE(file_acl);
5514 if (def_acl) {
5515 TALLOC_FREE(def_acl);
5517 return NT_STATUS_BUFFER_TOO_SMALL;
5520 SSVAL(pdata,0,SMB_POSIX_ACL_VERSION);
5521 SSVAL(pdata,2,num_file_acls);
5522 SSVAL(pdata,4,num_def_acls);
5523 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE, psbuf, file_acl)) {
5524 if (file_acl) {
5525 TALLOC_FREE(file_acl);
5527 if (def_acl) {
5528 TALLOC_FREE(def_acl);
5530 return NT_STATUS_INTERNAL_ERROR;
5532 if (!marshall_posix_acl(conn, pdata + SMB_POSIX_ACL_HEADER_SIZE + (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE), psbuf, def_acl)) {
5533 if (file_acl) {
5534 TALLOC_FREE(file_acl);
5536 if (def_acl) {
5537 TALLOC_FREE(def_acl);
5539 return NT_STATUS_INTERNAL_ERROR;
5542 if (file_acl) {
5543 TALLOC_FREE(file_acl);
5545 if (def_acl) {
5546 TALLOC_FREE(def_acl);
5548 data_size = (num_file_acls + num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE + SMB_POSIX_ACL_HEADER_SIZE;
5549 break;
5551 #endif
5554 case SMB_QUERY_POSIX_LOCK:
5556 uint64_t count;
5557 uint64_t offset;
5558 uint64_t smblctx;
5559 enum brl_type lock_type;
5561 /* We need an open file with a real fd for this. */
5562 if (!fsp || fsp->fh->fd == -1) {
5563 return NT_STATUS_INVALID_LEVEL;
5566 if (lock_data_count != POSIX_LOCK_DATA_SIZE) {
5567 return NT_STATUS_INVALID_PARAMETER;
5570 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
5571 case POSIX_LOCK_TYPE_READ:
5572 lock_type = READ_LOCK;
5573 break;
5574 case POSIX_LOCK_TYPE_WRITE:
5575 lock_type = WRITE_LOCK;
5576 break;
5577 case POSIX_LOCK_TYPE_UNLOCK:
5578 default:
5579 /* There's no point in asking for an unlock... */
5580 return NT_STATUS_INVALID_PARAMETER;
5583 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
5584 offset = BVAL(pdata,POSIX_LOCK_START_OFFSET);
5585 count = BVAL(pdata,POSIX_LOCK_LEN_OFFSET);
5587 status = query_lock(fsp,
5588 &smblctx,
5589 &count,
5590 &offset,
5591 &lock_type,
5592 POSIX_LOCK);
5594 if (ERROR_WAS_LOCK_DENIED(status)) {
5595 /* Here we need to report who has it locked... */
5596 data_size = POSIX_LOCK_DATA_SIZE;
5598 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, lock_type);
5599 SSVAL(pdata, POSIX_LOCK_FLAGS_OFFSET, 0);
5600 SIVAL(pdata, POSIX_LOCK_PID_OFFSET, (uint32_t)smblctx);
5601 SBVAL(pdata, POSIX_LOCK_START_OFFSET, offset);
5602 SBVAL(pdata, POSIX_LOCK_LEN_OFFSET, count);
5604 } else if (NT_STATUS_IS_OK(status)) {
5605 /* For success we just return a copy of what we sent
5606 with the lock type set to POSIX_LOCK_TYPE_UNLOCK. */
5607 data_size = POSIX_LOCK_DATA_SIZE;
5608 memcpy(pdata, lock_data, POSIX_LOCK_DATA_SIZE);
5609 SSVAL(pdata, POSIX_LOCK_TYPE_OFFSET, POSIX_LOCK_TYPE_UNLOCK);
5610 } else {
5611 return status;
5613 break;
5616 default:
5617 return NT_STATUS_INVALID_LEVEL;
5620 *pdata_size = data_size;
5621 return NT_STATUS_OK;
5624 /****************************************************************************
5625 Reply to a TRANS2_QFILEPATHINFO or TRANSACT2_QFILEINFO (query file info by
5626 file name or file id).
5627 ****************************************************************************/
5629 static void call_trans2qfilepathinfo(connection_struct *conn,
5630 struct smb_request *req,
5631 unsigned int tran_call,
5632 char **pparams, int total_params,
5633 char **ppdata, int total_data,
5634 unsigned int max_data_bytes)
5636 char *params = *pparams;
5637 char *pdata = *ppdata;
5638 uint16_t info_level;
5639 unsigned int data_size = 0;
5640 unsigned int param_size = 2;
5641 struct smb_filename *smb_fname = NULL;
5642 bool delete_pending = False;
5643 struct timespec write_time_ts;
5644 files_struct *fsp = NULL;
5645 struct file_id fileid;
5646 struct ea_list *ea_list = NULL;
5647 int lock_data_count = 0;
5648 char *lock_data = NULL;
5649 size_t fixed_portion;
5650 NTSTATUS status = NT_STATUS_OK;
5652 if (!params) {
5653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5654 return;
5657 ZERO_STRUCT(write_time_ts);
5659 if (tran_call == TRANSACT2_QFILEINFO) {
5660 if (total_params < 4) {
5661 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5662 return;
5665 if (IS_IPC(conn)) {
5666 call_trans2qpipeinfo(conn, req, tran_call,
5667 pparams, total_params,
5668 ppdata, total_data,
5669 max_data_bytes);
5670 return;
5673 fsp = file_fsp(req, SVAL(params,0));
5674 info_level = SVAL(params,2);
5676 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QFILEINFO: level = %d\n", info_level));
5678 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
5679 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5680 return;
5683 /* Initial check for valid fsp ptr. */
5684 if (!check_fsp_open(conn, req, fsp)) {
5685 return;
5688 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
5689 if (smb_fname == NULL) {
5690 reply_nterror(req, NT_STATUS_NO_MEMORY);
5691 return;
5694 if(fsp->fake_file_handle) {
5696 * This is actually for the QUOTA_FAKE_FILE --metze
5699 /* We know this name is ok, it's already passed the checks. */
5701 } else if(fsp->fh->fd == -1) {
5703 * This is actually a QFILEINFO on a directory
5704 * handle (returned from an NT SMB). NT5.0 seems
5705 * to do this call. JRA.
5708 if (INFO_LEVEL_IS_UNIX(info_level)) {
5709 /* Always do lstat for UNIX calls. */
5710 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5711 DEBUG(3,("call_trans2qfilepathinfo: "
5712 "SMB_VFS_LSTAT of %s failed "
5713 "(%s)\n",
5714 smb_fname_str_dbg(smb_fname),
5715 strerror(errno)));
5716 reply_nterror(req,
5717 map_nt_error_from_unix(errno));
5718 return;
5720 } else if (SMB_VFS_STAT(conn, smb_fname)) {
5721 DEBUG(3,("call_trans2qfilepathinfo: "
5722 "SMB_VFS_STAT of %s failed (%s)\n",
5723 smb_fname_str_dbg(smb_fname),
5724 strerror(errno)));
5725 reply_nterror(req,
5726 map_nt_error_from_unix(errno));
5727 return;
5730 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5731 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5732 } else {
5734 * Original code - this is an open file.
5736 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
5737 DEBUG(3, ("fstat of %s failed (%s)\n",
5738 fsp_fnum_dbg(fsp), strerror(errno)));
5739 reply_nterror(req,
5740 map_nt_error_from_unix(errno));
5741 return;
5743 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5744 get_file_infos(fileid, fsp->name_hash, &delete_pending, &write_time_ts);
5747 } else {
5748 uint32_t name_hash;
5749 char *fname = NULL;
5750 uint32_t ucf_flags = (req->posix_pathnames ?
5751 UCF_POSIX_PATHNAMES : 0);
5753 /* qpathinfo */
5754 if (total_params < 7) {
5755 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5756 return;
5759 info_level = SVAL(params,0);
5761 DEBUG(3,("call_trans2qfilepathinfo: TRANSACT2_QPATHINFO: level = %d\n", info_level));
5763 if (INFO_LEVEL_IS_UNIX(info_level)) {
5764 if (!lp_unix_extensions()) {
5765 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
5766 return;
5768 if (info_level == SMB_QUERY_FILE_UNIX_BASIC ||
5769 info_level == SMB_QUERY_FILE_UNIX_INFO2 ||
5770 info_level == SMB_QUERY_FILE_UNIX_LINK) {
5771 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
5775 if (req->posix_pathnames) {
5776 srvstr_get_path_posix(req,
5777 params,
5778 req->flags2,
5779 &fname,
5780 &params[6],
5781 total_params - 6,
5782 STR_TERMINATE,
5783 &status);
5784 } else {
5785 srvstr_get_path(req,
5786 params,
5787 req->flags2,
5788 &fname,
5789 &params[6],
5790 total_params - 6,
5791 STR_TERMINATE,
5792 &status);
5794 if (!NT_STATUS_IS_OK(status)) {
5795 reply_nterror(req, status);
5796 return;
5799 status = filename_convert(req,
5800 conn,
5801 req->flags2 & FLAGS2_DFS_PATHNAMES,
5802 fname,
5803 ucf_flags,
5804 NULL,
5805 &smb_fname);
5806 if (!NT_STATUS_IS_OK(status)) {
5807 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
5808 reply_botherror(req,
5809 NT_STATUS_PATH_NOT_COVERED,
5810 ERRSRV, ERRbadpath);
5811 return;
5813 reply_nterror(req, status);
5814 return;
5817 /* If this is a stream, check if there is a delete_pending. */
5818 if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
5819 && is_ntfs_stream_smb_fname(smb_fname)) {
5820 struct smb_filename *smb_fname_base;
5822 /* Create an smb_filename with stream_name == NULL. */
5823 smb_fname_base = synthetic_smb_fname(
5824 talloc_tos(),
5825 smb_fname->base_name,
5826 NULL,
5827 NULL,
5828 smb_fname->flags);
5829 if (smb_fname_base == NULL) {
5830 reply_nterror(req, NT_STATUS_NO_MEMORY);
5831 return;
5834 if (INFO_LEVEL_IS_UNIX(info_level)) {
5835 /* Always do lstat for UNIX calls. */
5836 if (SMB_VFS_LSTAT(conn, smb_fname_base) != 0) {
5837 DEBUG(3,("call_trans2qfilepathinfo: "
5838 "SMB_VFS_LSTAT of %s failed "
5839 "(%s)\n",
5840 smb_fname_str_dbg(smb_fname_base),
5841 strerror(errno)));
5842 TALLOC_FREE(smb_fname_base);
5843 reply_nterror(req,
5844 map_nt_error_from_unix(errno));
5845 return;
5847 } else {
5848 if (SMB_VFS_STAT(conn, smb_fname_base) != 0) {
5849 DEBUG(3,("call_trans2qfilepathinfo: "
5850 "fileinfo of %s failed "
5851 "(%s)\n",
5852 smb_fname_str_dbg(smb_fname_base),
5853 strerror(errno)));
5854 TALLOC_FREE(smb_fname_base);
5855 reply_nterror(req,
5856 map_nt_error_from_unix(errno));
5857 return;
5861 status = file_name_hash(conn,
5862 smb_fname_str_dbg(smb_fname_base),
5863 &name_hash);
5864 if (!NT_STATUS_IS_OK(status)) {
5865 TALLOC_FREE(smb_fname_base);
5866 reply_nterror(req, status);
5867 return;
5870 fileid = vfs_file_id_from_sbuf(conn,
5871 &smb_fname_base->st);
5872 TALLOC_FREE(smb_fname_base);
5873 get_file_infos(fileid, name_hash, &delete_pending, NULL);
5874 if (delete_pending) {
5875 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5876 return;
5880 if (INFO_LEVEL_IS_UNIX(info_level)) {
5881 /* Always do lstat for UNIX calls. */
5882 if (SMB_VFS_LSTAT(conn, smb_fname)) {
5883 DEBUG(3,("call_trans2qfilepathinfo: "
5884 "SMB_VFS_LSTAT of %s failed (%s)\n",
5885 smb_fname_str_dbg(smb_fname),
5886 strerror(errno)));
5887 reply_nterror(req,
5888 map_nt_error_from_unix(errno));
5889 return;
5892 } else {
5893 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
5894 DEBUG(3,("call_trans2qfilepathinfo: "
5895 "SMB_VFS_STAT of %s failed (%s)\n",
5896 smb_fname_str_dbg(smb_fname),
5897 strerror(errno)));
5898 reply_nterror(req,
5899 map_nt_error_from_unix(errno));
5900 return;
5904 status = file_name_hash(conn,
5905 smb_fname_str_dbg(smb_fname),
5906 &name_hash);
5907 if (!NT_STATUS_IS_OK(status)) {
5908 reply_nterror(req, status);
5909 return;
5912 fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
5913 get_file_infos(fileid, name_hash, &delete_pending, &write_time_ts);
5914 if (delete_pending) {
5915 reply_nterror(req, NT_STATUS_DELETE_PENDING);
5916 return;
5920 DEBUG(3,("call_trans2qfilepathinfo %s (%s) level=%d call=%d "
5921 "total_data=%d\n", smb_fname_str_dbg(smb_fname),
5922 fsp_fnum_dbg(fsp),
5923 info_level,tran_call,total_data));
5925 /* Pull out any data sent here before we realloc. */
5926 switch (info_level) {
5927 case SMB_INFO_QUERY_EAS_FROM_LIST:
5929 /* Pull any EA list from the data portion. */
5930 uint32_t ea_size;
5932 if (total_data < 4) {
5933 reply_nterror(
5934 req, NT_STATUS_INVALID_PARAMETER);
5935 return;
5937 ea_size = IVAL(pdata,0);
5939 if (total_data > 0 && ea_size != total_data) {
5940 DEBUG(4,("call_trans2qfilepathinfo: Rejecting EA request with incorrect \
5941 total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pdata,0) ));
5942 reply_nterror(
5943 req, NT_STATUS_INVALID_PARAMETER);
5944 return;
5947 if (!lp_ea_support(SNUM(conn))) {
5948 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
5949 return;
5952 /* Pull out the list of names. */
5953 ea_list = read_ea_name_list(req, pdata + 4, ea_size - 4);
5954 if (!ea_list) {
5955 reply_nterror(
5956 req, NT_STATUS_INVALID_PARAMETER);
5957 return;
5959 break;
5962 case SMB_QUERY_POSIX_LOCK:
5964 if (fsp == NULL || fsp->fh->fd == -1) {
5965 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
5966 return;
5969 if (total_data != POSIX_LOCK_DATA_SIZE) {
5970 reply_nterror(
5971 req, NT_STATUS_INVALID_PARAMETER);
5972 return;
5975 /* Copy the lock range data. */
5976 lock_data = (char *)talloc_memdup(
5977 req, pdata, total_data);
5978 if (!lock_data) {
5979 reply_nterror(req, NT_STATUS_NO_MEMORY);
5980 return;
5982 lock_data_count = total_data;
5984 default:
5985 break;
5988 *pparams = (char *)SMB_REALLOC(*pparams,2);
5989 if (*pparams == NULL) {
5990 reply_nterror(req, NT_STATUS_NO_MEMORY);
5991 return;
5993 params = *pparams;
5994 SSVAL(params,0,0);
5997 * draft-leach-cifs-v1-spec-02.txt
5998 * 4.2.14 TRANS2_QUERY_PATH_INFORMATION: Get File Attributes given Path
5999 * says:
6001 * The requested information is placed in the Data portion of the
6002 * transaction response. For the information levels greater than 0x100,
6003 * the transaction response has 1 parameter word which should be
6004 * ignored by the client.
6006 * However Windows only follows this rule for the IS_NAME_VALID call.
6008 switch (info_level) {
6009 case SMB_INFO_IS_NAME_VALID:
6010 param_size = 0;
6011 break;
6014 if ((info_level & 0xFF00) == 0xFF00) {
6016 * We use levels that start with 0xFF00
6017 * internally to represent SMB2 specific levels
6019 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
6020 return;
6023 status = smbd_do_qfilepathinfo(conn, req, info_level,
6024 fsp, smb_fname,
6025 delete_pending, write_time_ts,
6026 ea_list,
6027 lock_data_count, lock_data,
6028 req->flags2, max_data_bytes,
6029 &fixed_portion,
6030 ppdata, &data_size);
6031 if (!NT_STATUS_IS_OK(status)) {
6032 reply_nterror(req, status);
6033 return;
6035 if (fixed_portion > max_data_bytes) {
6036 reply_nterror(req, NT_STATUS_INFO_LENGTH_MISMATCH);
6037 return;
6040 send_trans2_replies(conn, req, NT_STATUS_OK, params, param_size, *ppdata, data_size,
6041 max_data_bytes);
6043 return;
6046 /****************************************************************************
6047 Set a hard link (called by UNIX extensions and by NT rename with HARD link
6048 code.
6049 ****************************************************************************/
6051 NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
6052 connection_struct *conn,
6053 struct smb_request *req,
6054 bool overwrite_if_exists,
6055 const struct smb_filename *smb_fname_old,
6056 struct smb_filename *smb_fname_new)
6058 NTSTATUS status = NT_STATUS_OK;
6060 /* source must already exist. */
6061 if (!VALID_STAT(smb_fname_old->st)) {
6062 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6065 if (VALID_STAT(smb_fname_new->st)) {
6066 if (overwrite_if_exists) {
6067 if (S_ISDIR(smb_fname_new->st.st_ex_mode)) {
6068 return NT_STATUS_FILE_IS_A_DIRECTORY;
6070 status = unlink_internals(conn,
6071 req,
6072 FILE_ATTRIBUTE_NORMAL,
6073 smb_fname_new,
6074 false);
6075 if (!NT_STATUS_IS_OK(status)) {
6076 return status;
6078 } else {
6079 /* Disallow if newname already exists. */
6080 return NT_STATUS_OBJECT_NAME_COLLISION;
6084 /* No links from a directory. */
6085 if (S_ISDIR(smb_fname_old->st.st_ex_mode)) {
6086 return NT_STATUS_FILE_IS_A_DIRECTORY;
6089 /* Setting a hardlink to/from a stream isn't currently supported. */
6090 if (is_ntfs_stream_smb_fname(smb_fname_old) ||
6091 is_ntfs_stream_smb_fname(smb_fname_new)) {
6092 return NT_STATUS_INVALID_PARAMETER;
6095 DEBUG(10,("hardlink_internals: doing hard link %s -> %s\n",
6096 smb_fname_old->base_name, smb_fname_new->base_name));
6098 if (SMB_VFS_LINK(conn, smb_fname_old->base_name,
6099 smb_fname_new->base_name) != 0) {
6100 status = map_nt_error_from_unix(errno);
6101 DEBUG(3,("hardlink_internals: Error %s hard link %s -> %s\n",
6102 nt_errstr(status), smb_fname_old->base_name,
6103 smb_fname_new->base_name));
6105 return status;
6108 /****************************************************************************
6109 Deal with setting the time from any of the setfilepathinfo functions.
6110 NOTE !!!! The check for FILE_WRITE_ATTRIBUTES access must be done *before*
6111 calling this function.
6112 ****************************************************************************/
6114 NTSTATUS smb_set_file_time(connection_struct *conn,
6115 files_struct *fsp,
6116 const struct smb_filename *smb_fname,
6117 struct smb_file_time *ft,
6118 bool setting_write_time)
6120 struct smb_filename smb_fname_base;
6121 uint32_t action =
6122 FILE_NOTIFY_CHANGE_LAST_ACCESS
6123 |FILE_NOTIFY_CHANGE_LAST_WRITE
6124 |FILE_NOTIFY_CHANGE_CREATION;
6126 if (!VALID_STAT(smb_fname->st)) {
6127 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6130 /* get some defaults (no modifications) if any info is zero or -1. */
6131 if (null_timespec(ft->create_time)) {
6132 action &= ~FILE_NOTIFY_CHANGE_CREATION;
6135 if (null_timespec(ft->atime)) {
6136 action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
6139 if (null_timespec(ft->mtime)) {
6140 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6143 if (!setting_write_time) {
6144 /* ft->mtime comes from change time, not write time. */
6145 action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
6148 /* Ensure the resolution is the correct for
6149 * what we can store on this filesystem. */
6151 round_timespec(conn->ts_res, &ft->create_time);
6152 round_timespec(conn->ts_res, &ft->ctime);
6153 round_timespec(conn->ts_res, &ft->atime);
6154 round_timespec(conn->ts_res, &ft->mtime);
6156 DEBUG(5,("smb_set_filetime: actime: %s\n ",
6157 time_to_asc(convert_timespec_to_time_t(ft->atime))));
6158 DEBUG(5,("smb_set_filetime: modtime: %s\n ",
6159 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6160 DEBUG(5,("smb_set_filetime: ctime: %s\n ",
6161 time_to_asc(convert_timespec_to_time_t(ft->ctime))));
6162 DEBUG(5,("smb_set_file_time: createtime: %s\n ",
6163 time_to_asc(convert_timespec_to_time_t(ft->create_time))));
6165 if (setting_write_time) {
6167 * This was a Windows setfileinfo on an open file.
6168 * NT does this a lot. We also need to
6169 * set the time here, as it can be read by
6170 * FindFirst/FindNext and with the patch for bug #2045
6171 * in smbd/fileio.c it ensures that this timestamp is
6172 * kept sticky even after a write. We save the request
6173 * away and will set it on file close and after a write. JRA.
6176 DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
6177 time_to_asc(convert_timespec_to_time_t(ft->mtime))));
6179 if (fsp != NULL) {
6180 if (fsp->base_fsp) {
6181 set_sticky_write_time_fsp(fsp->base_fsp,
6182 ft->mtime);
6183 } else {
6184 set_sticky_write_time_fsp(fsp, ft->mtime);
6186 } else {
6187 set_sticky_write_time_path(
6188 vfs_file_id_from_sbuf(conn, &smb_fname->st),
6189 ft->mtime);
6193 DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
6195 /* Always call ntimes on the base, even if a stream was passed in. */
6196 smb_fname_base = *smb_fname;
6197 smb_fname_base.stream_name = NULL;
6199 if(file_ntimes(conn, &smb_fname_base, ft)!=0) {
6200 return map_nt_error_from_unix(errno);
6203 notify_fname(conn, NOTIFY_ACTION_MODIFIED, action,
6204 smb_fname->base_name);
6205 return NT_STATUS_OK;
6208 /****************************************************************************
6209 Deal with setting the dosmode from any of the setfilepathinfo functions.
6210 NB. The check for FILE_WRITE_ATTRIBUTES access on this path must have been
6211 done before calling this function.
6212 ****************************************************************************/
6214 static NTSTATUS smb_set_file_dosmode(connection_struct *conn,
6215 const struct smb_filename *smb_fname,
6216 uint32_t dosmode)
6218 struct smb_filename *smb_fname_base;
6219 NTSTATUS status;
6221 if (!VALID_STAT(smb_fname->st)) {
6222 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6225 /* Always operate on the base_name, even if a stream was passed in. */
6226 smb_fname_base = synthetic_smb_fname(talloc_tos(),
6227 smb_fname->base_name,
6228 NULL,
6229 &smb_fname->st,
6230 smb_fname->flags);
6231 if (smb_fname_base == NULL) {
6232 return NT_STATUS_NO_MEMORY;
6235 if (dosmode) {
6236 if (S_ISDIR(smb_fname_base->st.st_ex_mode)) {
6237 dosmode |= FILE_ATTRIBUTE_DIRECTORY;
6238 } else {
6239 dosmode &= ~FILE_ATTRIBUTE_DIRECTORY;
6243 DEBUG(6,("smb_set_file_dosmode: dosmode: 0x%x\n", (unsigned int)dosmode));
6245 /* check the mode isn't different, before changing it */
6246 if ((dosmode != 0) && (dosmode != dos_mode(conn, smb_fname_base))) {
6247 DEBUG(10,("smb_set_file_dosmode: file %s : setting dos mode "
6248 "0x%x\n", smb_fname_str_dbg(smb_fname_base),
6249 (unsigned int)dosmode));
6251 if(file_set_dosmode(conn, smb_fname_base, dosmode, NULL,
6252 false)) {
6253 DEBUG(2,("smb_set_file_dosmode: file_set_dosmode of "
6254 "%s failed (%s)\n",
6255 smb_fname_str_dbg(smb_fname_base),
6256 strerror(errno)));
6257 status = map_nt_error_from_unix(errno);
6258 goto out;
6261 status = NT_STATUS_OK;
6262 out:
6263 TALLOC_FREE(smb_fname_base);
6264 return status;
6267 /****************************************************************************
6268 Deal with setting the size from any of the setfilepathinfo functions.
6269 ****************************************************************************/
6271 static NTSTATUS smb_set_file_size(connection_struct *conn,
6272 struct smb_request *req,
6273 files_struct *fsp,
6274 const struct smb_filename *smb_fname,
6275 const SMB_STRUCT_STAT *psbuf,
6276 off_t size,
6277 bool fail_after_createfile)
6279 NTSTATUS status = NT_STATUS_OK;
6280 struct smb_filename *smb_fname_tmp = NULL;
6281 files_struct *new_fsp = NULL;
6283 if (!VALID_STAT(*psbuf)) {
6284 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
6287 DEBUG(6,("smb_set_file_size: size: %.0f ", (double)size));
6289 if (size == get_file_size_stat(psbuf)) {
6290 return NT_STATUS_OK;
6293 DEBUG(10,("smb_set_file_size: file %s : setting new size to %.0f\n",
6294 smb_fname_str_dbg(smb_fname), (double)size));
6296 if (fsp && fsp->fh->fd != -1) {
6297 /* Handle based call. */
6298 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
6299 return NT_STATUS_ACCESS_DENIED;
6302 if (vfs_set_filelen(fsp, size) == -1) {
6303 return map_nt_error_from_unix(errno);
6305 trigger_write_time_update_immediate(fsp);
6306 return NT_STATUS_OK;
6309 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
6310 if (smb_fname_tmp == NULL) {
6311 return NT_STATUS_NO_MEMORY;
6314 smb_fname_tmp->st = *psbuf;
6316 status = SMB_VFS_CREATE_FILE(
6317 conn, /* conn */
6318 req, /* req */
6319 0, /* root_dir_fid */
6320 smb_fname_tmp, /* fname */
6321 FILE_WRITE_DATA, /* access_mask */
6322 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
6323 FILE_SHARE_DELETE),
6324 FILE_OPEN, /* create_disposition*/
6325 0, /* create_options */
6326 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
6327 0, /* oplock_request */
6328 NULL, /* lease */
6329 0, /* allocation_size */
6330 0, /* private_flags */
6331 NULL, /* sd */
6332 NULL, /* ea_list */
6333 &new_fsp, /* result */
6334 NULL, /* pinfo */
6335 NULL, NULL); /* create context */
6337 TALLOC_FREE(smb_fname_tmp);
6339 if (!NT_STATUS_IS_OK(status)) {
6340 /* NB. We check for open_was_deferred in the caller. */
6341 return status;
6344 /* See RAW-SFILEINFO-END-OF-FILE */
6345 if (fail_after_createfile) {
6346 close_file(req, new_fsp,NORMAL_CLOSE);
6347 return NT_STATUS_INVALID_LEVEL;
6350 if (vfs_set_filelen(new_fsp, size) == -1) {
6351 status = map_nt_error_from_unix(errno);
6352 close_file(req, new_fsp,NORMAL_CLOSE);
6353 return status;
6356 trigger_write_time_update_immediate(new_fsp);
6357 close_file(req, new_fsp,NORMAL_CLOSE);
6358 return NT_STATUS_OK;
6361 /****************************************************************************
6362 Deal with SMB_INFO_SET_EA.
6363 ****************************************************************************/
6365 static NTSTATUS smb_info_set_ea(connection_struct *conn,
6366 const char *pdata,
6367 int total_data,
6368 files_struct *fsp,
6369 const struct smb_filename *smb_fname)
6371 struct ea_list *ea_list = NULL;
6372 TALLOC_CTX *ctx = NULL;
6373 NTSTATUS status = NT_STATUS_OK;
6375 if (total_data < 10) {
6377 /* OS/2 workplace shell seems to send SET_EA requests of "null"
6378 length. They seem to have no effect. Bug #3212. JRA */
6380 if ((total_data == 4) && (IVAL(pdata,0) == 4)) {
6381 /* We're done. We only get EA info in this call. */
6382 return NT_STATUS_OK;
6385 return NT_STATUS_INVALID_PARAMETER;
6388 if (IVAL(pdata,0) > total_data) {
6389 DEBUG(10,("smb_info_set_ea: bad total data size (%u) > %u\n",
6390 IVAL(pdata,0), (unsigned int)total_data));
6391 return NT_STATUS_INVALID_PARAMETER;
6394 ctx = talloc_tos();
6395 ea_list = read_ea_list(ctx, pdata + 4, total_data - 4);
6396 if (!ea_list) {
6397 return NT_STATUS_INVALID_PARAMETER;
6400 status = set_ea(conn, fsp, smb_fname, ea_list);
6402 return status;
6405 /****************************************************************************
6406 Deal with SMB_FILE_FULL_EA_INFORMATION set.
6407 ****************************************************************************/
6409 static NTSTATUS smb_set_file_full_ea_info(connection_struct *conn,
6410 const char *pdata,
6411 int total_data,
6412 files_struct *fsp)
6414 struct ea_list *ea_list = NULL;
6415 NTSTATUS status;
6417 if (!fsp) {
6418 return NT_STATUS_INVALID_HANDLE;
6421 if (!lp_ea_support(SNUM(conn))) {
6422 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u but "
6423 "EA's not supported.\n",
6424 (unsigned int)total_data));
6425 return NT_STATUS_EAS_NOT_SUPPORTED;
6428 if (total_data < 10) {
6429 DEBUG(10, ("smb_set_file_full_ea_info - ea_len = %u "
6430 "too small.\n",
6431 (unsigned int)total_data));
6432 return NT_STATUS_INVALID_PARAMETER;
6435 ea_list = read_nttrans_ea_list(talloc_tos(),
6436 pdata,
6437 total_data);
6439 if (!ea_list) {
6440 return NT_STATUS_INVALID_PARAMETER;
6443 status = set_ea(conn, fsp, fsp->fsp_name, ea_list);
6445 DEBUG(10, ("smb_set_file_full_ea_info on file %s returned %s\n",
6446 smb_fname_str_dbg(fsp->fsp_name),
6447 nt_errstr(status) ));
6449 return status;
6453 /****************************************************************************
6454 Deal with SMB_SET_FILE_DISPOSITION_INFO.
6455 ****************************************************************************/
6457 static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
6458 const char *pdata,
6459 int total_data,
6460 files_struct *fsp,
6461 struct smb_filename *smb_fname)
6463 NTSTATUS status = NT_STATUS_OK;
6464 bool delete_on_close;
6465 uint32_t dosmode = 0;
6467 if (total_data < 1) {
6468 return NT_STATUS_INVALID_PARAMETER;
6471 if (fsp == NULL) {
6472 return NT_STATUS_INVALID_HANDLE;
6475 delete_on_close = (CVAL(pdata,0) ? True : False);
6476 dosmode = dos_mode(conn, smb_fname);
6478 DEBUG(10,("smb_set_file_disposition_info: file %s, dosmode = %u, "
6479 "delete_on_close = %u\n",
6480 smb_fname_str_dbg(smb_fname),
6481 (unsigned int)dosmode,
6482 (unsigned int)delete_on_close ));
6484 if (delete_on_close) {
6485 status = can_set_delete_on_close(fsp, dosmode);
6486 if (!NT_STATUS_IS_OK(status)) {
6487 return status;
6491 /* The set is across all open files on this dev/inode pair. */
6492 if (!set_delete_on_close(fsp, delete_on_close,
6493 conn->session_info->security_token,
6494 conn->session_info->unix_token)) {
6495 return NT_STATUS_ACCESS_DENIED;
6497 return NT_STATUS_OK;
6500 /****************************************************************************
6501 Deal with SMB_FILE_POSITION_INFORMATION.
6502 ****************************************************************************/
6504 static NTSTATUS smb_file_position_information(connection_struct *conn,
6505 const char *pdata,
6506 int total_data,
6507 files_struct *fsp)
6509 uint64_t position_information;
6511 if (total_data < 8) {
6512 return NT_STATUS_INVALID_PARAMETER;
6515 if (fsp == NULL) {
6516 /* Ignore on pathname based set. */
6517 return NT_STATUS_OK;
6520 position_information = (uint64_t)IVAL(pdata,0);
6521 position_information |= (((uint64_t)IVAL(pdata,4)) << 32);
6523 DEBUG(10,("smb_file_position_information: Set file position "
6524 "information for file %s to %.0f\n", fsp_str_dbg(fsp),
6525 (double)position_information));
6526 fsp->fh->position_information = position_information;
6527 return NT_STATUS_OK;
6530 /****************************************************************************
6531 Deal with SMB_FILE_MODE_INFORMATION.
6532 ****************************************************************************/
6534 static NTSTATUS smb_file_mode_information(connection_struct *conn,
6535 const char *pdata,
6536 int total_data)
6538 uint32_t mode;
6540 if (total_data < 4) {
6541 return NT_STATUS_INVALID_PARAMETER;
6543 mode = IVAL(pdata,0);
6544 if (mode != 0 && mode != 2 && mode != 4 && mode != 6) {
6545 return NT_STATUS_INVALID_PARAMETER;
6547 return NT_STATUS_OK;
6550 /****************************************************************************
6551 Deal with SMB_SET_FILE_UNIX_LINK (create a UNIX symlink).
6552 ****************************************************************************/
6554 static NTSTATUS smb_set_file_unix_link(connection_struct *conn,
6555 struct smb_request *req,
6556 const char *pdata,
6557 int total_data,
6558 const struct smb_filename *smb_fname)
6560 char *link_target = NULL;
6561 const char *newname = smb_fname->base_name;
6562 TALLOC_CTX *ctx = talloc_tos();
6564 /* Set a symbolic link. */
6565 /* Don't allow this if follow links is false. */
6567 if (total_data == 0) {
6568 return NT_STATUS_INVALID_PARAMETER;
6571 if (!lp_follow_symlinks(SNUM(conn))) {
6572 return NT_STATUS_ACCESS_DENIED;
6575 srvstr_pull_talloc(ctx, pdata, req->flags2, &link_target, pdata,
6576 total_data, STR_TERMINATE);
6578 if (!link_target) {
6579 return NT_STATUS_INVALID_PARAMETER;
6582 DEBUG(10,("smb_set_file_unix_link: SMB_SET_FILE_UNIX_LINK doing symlink %s -> %s\n",
6583 newname, link_target ));
6585 if (SMB_VFS_SYMLINK(conn,link_target,newname) != 0) {
6586 return map_nt_error_from_unix(errno);
6589 return NT_STATUS_OK;
6592 /****************************************************************************
6593 Deal with SMB_SET_FILE_UNIX_HLINK (create a UNIX hard link).
6594 ****************************************************************************/
6596 static NTSTATUS smb_set_file_unix_hlink(connection_struct *conn,
6597 struct smb_request *req,
6598 const char *pdata, int total_data,
6599 struct smb_filename *smb_fname_new)
6601 char *oldname = NULL;
6602 struct smb_filename *smb_fname_old = NULL;
6603 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6604 TALLOC_CTX *ctx = talloc_tos();
6605 NTSTATUS status = NT_STATUS_OK;
6607 /* Set a hard link. */
6608 if (total_data == 0) {
6609 return NT_STATUS_INVALID_PARAMETER;
6612 if (req->posix_pathnames) {
6613 srvstr_get_path_posix(ctx,
6614 pdata,
6615 req->flags2,
6616 &oldname,
6617 pdata,
6618 total_data,
6619 STR_TERMINATE,
6620 &status);
6621 } else {
6622 srvstr_get_path(ctx,
6623 pdata,
6624 req->flags2,
6625 &oldname,
6626 pdata,
6627 total_data,
6628 STR_TERMINATE,
6629 &status);
6631 if (!NT_STATUS_IS_OK(status)) {
6632 return status;
6635 DEBUG(10,("smb_set_file_unix_hlink: SMB_SET_FILE_UNIX_LINK doing hard link %s -> %s\n",
6636 smb_fname_str_dbg(smb_fname_new), oldname));
6638 status = filename_convert(ctx,
6639 conn,
6640 req->flags2 & FLAGS2_DFS_PATHNAMES,
6641 oldname,
6642 ucf_flags,
6643 NULL,
6644 &smb_fname_old);
6645 if (!NT_STATUS_IS_OK(status)) {
6646 return status;
6649 return hardlink_internals(ctx, conn, req, false,
6650 smb_fname_old, smb_fname_new);
6653 /****************************************************************************
6654 Deal with SMB2_FILE_RENAME_INFORMATION_INTERNAL
6655 ****************************************************************************/
6657 static NTSTATUS smb2_file_rename_information(connection_struct *conn,
6658 struct smb_request *req,
6659 const char *pdata,
6660 int total_data,
6661 files_struct *fsp,
6662 struct smb_filename *smb_fname_src)
6664 bool overwrite;
6665 uint32_t len;
6666 char *newname = NULL;
6667 struct smb_filename *smb_fname_dst = NULL;
6668 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6669 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6670 NTSTATUS status = NT_STATUS_OK;
6671 TALLOC_CTX *ctx = talloc_tos();
6673 if (!fsp) {
6674 return NT_STATUS_INVALID_HANDLE;
6677 if (total_data < 20) {
6678 return NT_STATUS_INVALID_PARAMETER;
6681 overwrite = (CVAL(pdata,0) ? True : False);
6682 len = IVAL(pdata,16);
6684 if (len > (total_data - 20) || (len == 0)) {
6685 return NT_STATUS_INVALID_PARAMETER;
6688 if (req->posix_pathnames) {
6689 srvstr_get_path_posix(ctx,
6690 pdata,
6691 req->flags2,
6692 &newname,
6693 &pdata[20],
6694 len,
6695 STR_TERMINATE,
6696 &status);
6697 } else {
6698 srvstr_get_path(ctx,
6699 pdata,
6700 req->flags2,
6701 &newname,
6702 &pdata[20],
6703 len,
6704 STR_TERMINATE,
6705 &status);
6707 if (!NT_STATUS_IS_OK(status)) {
6708 return status;
6711 DEBUG(10,("smb2_file_rename_information: got name |%s|\n",
6712 newname));
6714 status = filename_convert(ctx,
6715 conn,
6716 req->flags2 & FLAGS2_DFS_PATHNAMES,
6717 newname,
6718 ucf_flags,
6719 NULL,
6720 &smb_fname_dst);
6721 if (!NT_STATUS_IS_OK(status)) {
6722 return status;
6725 if (fsp->base_fsp) {
6726 /* newname must be a stream name. */
6727 if (newname[0] != ':') {
6728 return NT_STATUS_NOT_SUPPORTED;
6731 /* Create an smb_fname to call rename_internals_fsp() with. */
6732 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6733 fsp->base_fsp->fsp_name->base_name,
6734 newname,
6735 NULL,
6736 fsp->base_fsp->fsp_name->flags);
6737 if (smb_fname_dst == NULL) {
6738 status = NT_STATUS_NO_MEMORY;
6739 goto out;
6743 * Set the original last component, since
6744 * rename_internals_fsp() requires it.
6746 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6747 newname);
6748 if (smb_fname_dst->original_lcomp == NULL) {
6749 status = NT_STATUS_NO_MEMORY;
6750 goto out;
6755 DEBUG(10,("smb2_file_rename_information: "
6756 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
6757 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6758 smb_fname_str_dbg(smb_fname_dst)));
6759 status = rename_internals_fsp(conn, fsp, smb_fname_dst,
6760 (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM),
6761 overwrite);
6763 out:
6764 TALLOC_FREE(smb_fname_dst);
6765 return status;
6768 static NTSTATUS smb_file_link_information(connection_struct *conn,
6769 struct smb_request *req,
6770 const char *pdata,
6771 int total_data,
6772 files_struct *fsp,
6773 struct smb_filename *smb_fname_src)
6775 bool overwrite;
6776 uint32_t len;
6777 char *newname = NULL;
6778 struct smb_filename *smb_fname_dst = NULL;
6779 NTSTATUS status = NT_STATUS_OK;
6780 uint32_t ucf_flags = UCF_SAVE_LCOMP |
6781 (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
6782 TALLOC_CTX *ctx = talloc_tos();
6784 if (!fsp) {
6785 return NT_STATUS_INVALID_HANDLE;
6788 if (total_data < 20) {
6789 return NT_STATUS_INVALID_PARAMETER;
6792 overwrite = (CVAL(pdata,0) ? true : false);
6793 len = IVAL(pdata,16);
6795 if (len > (total_data - 20) || (len == 0)) {
6796 return NT_STATUS_INVALID_PARAMETER;
6799 if (req->posix_pathnames) {
6800 srvstr_get_path_posix(ctx,
6801 pdata,
6802 req->flags2,
6803 &newname,
6804 &pdata[20],
6805 len,
6806 STR_TERMINATE,
6807 &status);
6808 } else {
6809 srvstr_get_path(ctx,
6810 pdata,
6811 req->flags2,
6812 &newname,
6813 &pdata[20],
6814 len,
6815 STR_TERMINATE,
6816 &status);
6818 if (!NT_STATUS_IS_OK(status)) {
6819 return status;
6822 DEBUG(10,("smb_file_link_information: got name |%s|\n",
6823 newname));
6825 status = filename_convert(ctx,
6826 conn,
6827 req->flags2 & FLAGS2_DFS_PATHNAMES,
6828 newname,
6829 ucf_flags,
6830 NULL,
6831 &smb_fname_dst);
6832 if (!NT_STATUS_IS_OK(status)) {
6833 return status;
6836 if (fsp->base_fsp) {
6837 /* No stream names. */
6838 return NT_STATUS_NOT_SUPPORTED;
6841 DEBUG(10,("smb_file_link_information: "
6842 "SMB_FILE_LINK_INFORMATION (%s) %s -> %s\n",
6843 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
6844 smb_fname_str_dbg(smb_fname_dst)));
6845 status = hardlink_internals(ctx,
6846 conn,
6847 req,
6848 overwrite,
6849 fsp->fsp_name,
6850 smb_fname_dst);
6852 TALLOC_FREE(smb_fname_dst);
6853 return status;
6856 /****************************************************************************
6857 Deal with SMB_FILE_RENAME_INFORMATION.
6858 ****************************************************************************/
6860 static NTSTATUS smb_file_rename_information(connection_struct *conn,
6861 struct smb_request *req,
6862 const char *pdata,
6863 int total_data,
6864 files_struct *fsp,
6865 struct smb_filename *smb_fname_src)
6867 bool overwrite;
6868 uint32_t root_fid;
6869 uint32_t len;
6870 char *newname = NULL;
6871 struct smb_filename *smb_fname_dst = NULL;
6872 bool dest_has_wcard = False;
6873 NTSTATUS status = NT_STATUS_OK;
6874 char *p;
6875 TALLOC_CTX *ctx = talloc_tos();
6877 if (total_data < 13) {
6878 return NT_STATUS_INVALID_PARAMETER;
6881 overwrite = (CVAL(pdata,0) ? True : False);
6882 root_fid = IVAL(pdata,4);
6883 len = IVAL(pdata,8);
6885 if (len > (total_data - 12) || (len == 0) || (root_fid != 0)) {
6886 return NT_STATUS_INVALID_PARAMETER;
6889 if (req->posix_pathnames) {
6890 srvstr_get_path_wcard_posix(ctx,
6891 pdata,
6892 req->flags2,
6893 &newname,
6894 &pdata[12],
6895 len,
6897 &status,
6898 &dest_has_wcard);
6899 } else {
6900 srvstr_get_path_wcard(ctx,
6901 pdata,
6902 req->flags2,
6903 &newname,
6904 &pdata[12],
6905 len,
6907 &status,
6908 &dest_has_wcard);
6910 if (!NT_STATUS_IS_OK(status)) {
6911 return status;
6914 DEBUG(10,("smb_file_rename_information: got name |%s|\n",
6915 newname));
6917 status = resolve_dfspath_wcard(ctx, conn,
6918 req->flags2 & FLAGS2_DFS_PATHNAMES,
6919 newname,
6920 UCF_COND_ALLOW_WCARD_LCOMP,
6921 !conn->sconn->using_smb2,
6922 &newname,
6923 &dest_has_wcard);
6924 if (!NT_STATUS_IS_OK(status)) {
6925 return status;
6928 /* Check the new name has no '/' characters. */
6929 if (strchr_m(newname, '/')) {
6930 return NT_STATUS_NOT_SUPPORTED;
6933 if (fsp && fsp->base_fsp) {
6934 /* newname must be a stream name. */
6935 if (newname[0] != ':') {
6936 return NT_STATUS_NOT_SUPPORTED;
6939 /* Create an smb_fname to call rename_internals_fsp() with. */
6940 smb_fname_dst = synthetic_smb_fname(talloc_tos(),
6941 fsp->base_fsp->fsp_name->base_name,
6942 newname,
6943 NULL,
6944 fsp->base_fsp->fsp_name->flags);
6945 if (smb_fname_dst == NULL) {
6946 status = NT_STATUS_NO_MEMORY;
6947 goto out;
6951 * Set the original last component, since
6952 * rename_internals_fsp() requires it.
6954 smb_fname_dst->original_lcomp = talloc_strdup(smb_fname_dst,
6955 newname);
6956 if (smb_fname_dst->original_lcomp == NULL) {
6957 status = NT_STATUS_NO_MEMORY;
6958 goto out;
6961 } else {
6963 * Build up an smb_fname_dst based on the filename passed in.
6964 * We basically just strip off the last component, and put on
6965 * the newname instead.
6967 char *base_name = NULL;
6969 /* newname must *not* be a stream name. */
6970 if (newname[0] == ':') {
6971 return NT_STATUS_NOT_SUPPORTED;
6975 * Strip off the last component (filename) of the path passed
6976 * in.
6978 base_name = talloc_strdup(ctx, smb_fname_src->base_name);
6979 if (!base_name) {
6980 return NT_STATUS_NO_MEMORY;
6982 p = strrchr_m(base_name, '/');
6983 if (p) {
6984 p[1] = '\0';
6985 } else {
6986 base_name = talloc_strdup(ctx, "");
6987 if (!base_name) {
6988 return NT_STATUS_NO_MEMORY;
6991 /* Append the new name. */
6992 base_name = talloc_asprintf_append(base_name,
6993 "%s",
6994 newname);
6995 if (!base_name) {
6996 return NT_STATUS_NO_MEMORY;
6999 status = unix_convert(ctx, conn, base_name, &smb_fname_dst,
7000 (UCF_SAVE_LCOMP |
7001 (dest_has_wcard ?
7002 UCF_ALWAYS_ALLOW_WCARD_LCOMP :
7003 0)));
7005 /* If an error we expect this to be
7006 * NT_STATUS_OBJECT_PATH_NOT_FOUND */
7008 if (!NT_STATUS_IS_OK(status)) {
7009 if(!NT_STATUS_EQUAL(NT_STATUS_OBJECT_PATH_NOT_FOUND,
7010 status)) {
7011 goto out;
7013 /* Create an smb_fname to call rename_internals_fsp() */
7014 smb_fname_dst = synthetic_smb_fname(ctx,
7015 base_name,
7016 NULL,
7017 NULL,
7018 smb_fname_src->flags);
7019 if (smb_fname_dst == NULL) {
7020 status = NT_STATUS_NO_MEMORY;
7021 goto out;
7026 if (fsp) {
7027 DEBUG(10,("smb_file_rename_information: "
7028 "SMB_FILE_RENAME_INFORMATION (%s) %s -> %s\n",
7029 fsp_fnum_dbg(fsp), fsp_str_dbg(fsp),
7030 smb_fname_str_dbg(smb_fname_dst)));
7031 status = rename_internals_fsp(conn, fsp, smb_fname_dst, 0,
7032 overwrite);
7033 } else {
7034 DEBUG(10,("smb_file_rename_information: "
7035 "SMB_FILE_RENAME_INFORMATION %s -> %s\n",
7036 smb_fname_str_dbg(smb_fname_src),
7037 smb_fname_str_dbg(smb_fname_dst)));
7038 status = rename_internals(ctx, conn, req, smb_fname_src,
7039 smb_fname_dst, 0, overwrite, false,
7040 dest_has_wcard,
7041 FILE_WRITE_ATTRIBUTES);
7043 out:
7044 TALLOC_FREE(smb_fname_dst);
7045 return status;
7048 /****************************************************************************
7049 Deal with SMB_SET_POSIX_ACL.
7050 ****************************************************************************/
7052 #if defined(HAVE_POSIX_ACLS)
7053 static NTSTATUS smb_set_posix_acl(connection_struct *conn,
7054 const char *pdata,
7055 int total_data,
7056 files_struct *fsp,
7057 const struct smb_filename *smb_fname)
7059 uint16_t posix_acl_version;
7060 uint16_t num_file_acls;
7061 uint16_t num_def_acls;
7062 bool valid_file_acls = True;
7063 bool valid_def_acls = True;
7064 NTSTATUS status;
7066 if (total_data < SMB_POSIX_ACL_HEADER_SIZE) {
7067 return NT_STATUS_INVALID_PARAMETER;
7069 posix_acl_version = SVAL(pdata,0);
7070 num_file_acls = SVAL(pdata,2);
7071 num_def_acls = SVAL(pdata,4);
7073 if (num_file_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7074 valid_file_acls = False;
7075 num_file_acls = 0;
7078 if (num_def_acls == SMB_POSIX_IGNORE_ACE_ENTRIES) {
7079 valid_def_acls = False;
7080 num_def_acls = 0;
7083 if (posix_acl_version != SMB_POSIX_ACL_VERSION) {
7084 return NT_STATUS_INVALID_PARAMETER;
7087 if (total_data < SMB_POSIX_ACL_HEADER_SIZE +
7088 (num_file_acls+num_def_acls)*SMB_POSIX_ACL_ENTRY_SIZE) {
7089 return NT_STATUS_INVALID_PARAMETER;
7092 status = refuse_symlink(conn, fsp, smb_fname);
7093 if (!NT_STATUS_IS_OK(status)) {
7094 return status;
7097 DEBUG(10,("smb_set_posix_acl: file %s num_file_acls = %u, num_def_acls = %u\n",
7098 smb_fname ? smb_fname_str_dbg(smb_fname) : fsp_str_dbg(fsp),
7099 (unsigned int)num_file_acls,
7100 (unsigned int)num_def_acls));
7102 if (valid_file_acls && !set_unix_posix_acl(conn, fsp,
7103 smb_fname->base_name, num_file_acls,
7104 pdata + SMB_POSIX_ACL_HEADER_SIZE)) {
7105 return map_nt_error_from_unix(errno);
7108 if (valid_def_acls && !set_unix_posix_default_acl(conn,
7109 smb_fname->base_name, &smb_fname->st, num_def_acls,
7110 pdata + SMB_POSIX_ACL_HEADER_SIZE +
7111 (num_file_acls*SMB_POSIX_ACL_ENTRY_SIZE))) {
7112 return map_nt_error_from_unix(errno);
7114 return NT_STATUS_OK;
7116 #endif
7118 /****************************************************************************
7119 Deal with SMB_SET_POSIX_LOCK.
7120 ****************************************************************************/
7122 static NTSTATUS smb_set_posix_lock(connection_struct *conn,
7123 struct smb_request *req,
7124 const char *pdata,
7125 int total_data,
7126 files_struct *fsp)
7128 uint64_t count;
7129 uint64_t offset;
7130 uint64_t smblctx;
7131 bool blocking_lock = False;
7132 enum brl_type lock_type;
7134 NTSTATUS status = NT_STATUS_OK;
7136 if (fsp == NULL || fsp->fh->fd == -1) {
7137 return NT_STATUS_INVALID_HANDLE;
7140 if (total_data != POSIX_LOCK_DATA_SIZE) {
7141 return NT_STATUS_INVALID_PARAMETER;
7144 switch (SVAL(pdata, POSIX_LOCK_TYPE_OFFSET)) {
7145 case POSIX_LOCK_TYPE_READ:
7146 lock_type = READ_LOCK;
7147 break;
7148 case POSIX_LOCK_TYPE_WRITE:
7149 /* Return the right POSIX-mappable error code for files opened read-only. */
7150 if (!fsp->can_write) {
7151 return NT_STATUS_INVALID_HANDLE;
7153 lock_type = WRITE_LOCK;
7154 break;
7155 case POSIX_LOCK_TYPE_UNLOCK:
7156 lock_type = UNLOCK_LOCK;
7157 break;
7158 default:
7159 return NT_STATUS_INVALID_PARAMETER;
7162 if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_NOWAIT) {
7163 blocking_lock = False;
7164 } else if (SVAL(pdata,POSIX_LOCK_FLAGS_OFFSET) == POSIX_LOCK_FLAG_WAIT) {
7165 blocking_lock = True;
7166 } else {
7167 return NT_STATUS_INVALID_PARAMETER;
7170 if (!lp_blocking_locks(SNUM(conn))) {
7171 blocking_lock = False;
7174 smblctx = (uint64_t)IVAL(pdata, POSIX_LOCK_PID_OFFSET);
7175 offset = (((uint64_t) IVAL(pdata,(POSIX_LOCK_START_OFFSET+4))) << 32) |
7176 ((uint64_t) IVAL(pdata,POSIX_LOCK_START_OFFSET));
7177 count = (((uint64_t) IVAL(pdata,(POSIX_LOCK_LEN_OFFSET+4))) << 32) |
7178 ((uint64_t) IVAL(pdata,POSIX_LOCK_LEN_OFFSET));
7180 DEBUG(10,("smb_set_posix_lock: file %s, lock_type = %u,"
7181 "smblctx = %llu, count = %.0f, offset = %.0f\n",
7182 fsp_str_dbg(fsp),
7183 (unsigned int)lock_type,
7184 (unsigned long long)smblctx,
7185 (double)count,
7186 (double)offset ));
7188 if (lock_type == UNLOCK_LOCK) {
7189 status = do_unlock(req->sconn->msg_ctx,
7190 fsp,
7191 smblctx,
7192 count,
7193 offset,
7194 POSIX_LOCK);
7195 } else {
7196 uint64_t block_smblctx;
7198 struct byte_range_lock *br_lck = do_lock(req->sconn->msg_ctx,
7199 fsp,
7200 smblctx,
7201 count,
7202 offset,
7203 lock_type,
7204 POSIX_LOCK,
7205 blocking_lock,
7206 &status,
7207 &block_smblctx);
7209 if (br_lck && blocking_lock && ERROR_WAS_LOCK_DENIED(status)) {
7211 * A blocking lock was requested. Package up
7212 * this smb into a queued request and push it
7213 * onto the blocking lock queue.
7215 if(push_blocking_lock_request(br_lck,
7216 req,
7217 fsp,
7218 -1, /* infinite timeout. */
7220 smblctx,
7221 lock_type,
7222 POSIX_LOCK,
7223 offset,
7224 count,
7225 block_smblctx)) {
7226 TALLOC_FREE(br_lck);
7227 return status;
7230 TALLOC_FREE(br_lck);
7233 return status;
7236 /****************************************************************************
7237 Deal with SMB_SET_FILE_BASIC_INFO.
7238 ****************************************************************************/
7240 static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
7241 const char *pdata,
7242 int total_data,
7243 files_struct *fsp,
7244 const struct smb_filename *smb_fname)
7246 /* Patch to do this correctly from Paul Eggert <eggert@twinsun.com>. */
7247 struct smb_file_time ft;
7248 uint32_t dosmode = 0;
7249 NTSTATUS status = NT_STATUS_OK;
7251 ZERO_STRUCT(ft);
7253 if (total_data < 36) {
7254 return NT_STATUS_INVALID_PARAMETER;
7257 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7258 if (!NT_STATUS_IS_OK(status)) {
7259 return status;
7262 /* Set the attributes */
7263 dosmode = IVAL(pdata,32);
7264 status = smb_set_file_dosmode(conn, smb_fname, dosmode);
7265 if (!NT_STATUS_IS_OK(status)) {
7266 return status;
7269 /* create time */
7270 ft.create_time = interpret_long_date(pdata);
7272 /* access time */
7273 ft.atime = interpret_long_date(pdata+8);
7275 /* write time. */
7276 ft.mtime = interpret_long_date(pdata+16);
7278 /* change time. */
7279 ft.ctime = interpret_long_date(pdata+24);
7281 DEBUG(10, ("smb_set_file_basic_info: file %s\n",
7282 smb_fname_str_dbg(smb_fname)));
7284 return smb_set_file_time(conn, fsp, smb_fname, &ft,
7285 true);
7288 /****************************************************************************
7289 Deal with SMB_INFO_STANDARD.
7290 ****************************************************************************/
7292 static NTSTATUS smb_set_info_standard(connection_struct *conn,
7293 const char *pdata,
7294 int total_data,
7295 files_struct *fsp,
7296 const struct smb_filename *smb_fname)
7298 NTSTATUS status;
7299 struct smb_file_time ft;
7301 ZERO_STRUCT(ft);
7303 if (total_data < 12) {
7304 return NT_STATUS_INVALID_PARAMETER;
7307 /* create time */
7308 ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
7309 /* access time */
7310 ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
7311 /* write time */
7312 ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
7314 DEBUG(10,("smb_set_info_standard: file %s\n",
7315 smb_fname_str_dbg(smb_fname)));
7317 status = check_access(conn, fsp, smb_fname, FILE_WRITE_ATTRIBUTES);
7318 if (!NT_STATUS_IS_OK(status)) {
7319 return status;
7322 return smb_set_file_time(conn,
7323 fsp,
7324 smb_fname,
7325 &ft,
7326 true);
7329 /****************************************************************************
7330 Deal with SMB_SET_FILE_ALLOCATION_INFO.
7331 ****************************************************************************/
7333 static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
7334 struct smb_request *req,
7335 const char *pdata,
7336 int total_data,
7337 files_struct *fsp,
7338 struct smb_filename *smb_fname)
7340 uint64_t allocation_size = 0;
7341 NTSTATUS status = NT_STATUS_OK;
7342 files_struct *new_fsp = NULL;
7344 if (!VALID_STAT(smb_fname->st)) {
7345 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
7348 if (total_data < 8) {
7349 return NT_STATUS_INVALID_PARAMETER;
7352 allocation_size = (uint64_t)IVAL(pdata,0);
7353 allocation_size |= (((uint64_t)IVAL(pdata,4)) << 32);
7354 DEBUG(10,("smb_set_file_allocation_info: Set file allocation info for "
7355 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7356 (double)allocation_size));
7358 if (allocation_size) {
7359 allocation_size = smb_roundup(conn, allocation_size);
7362 DEBUG(10,("smb_set_file_allocation_info: file %s : setting new "
7363 "allocation size to %.0f\n", smb_fname_str_dbg(smb_fname),
7364 (double)allocation_size));
7366 if (fsp && fsp->fh->fd != -1) {
7367 /* Open file handle. */
7368 if (!(fsp->access_mask & FILE_WRITE_DATA)) {
7369 return NT_STATUS_ACCESS_DENIED;
7372 /* Only change if needed. */
7373 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7374 if (vfs_allocate_file_space(fsp, allocation_size) == -1) {
7375 return map_nt_error_from_unix(errno);
7378 /* But always update the time. */
7380 * This is equivalent to a write. Ensure it's seen immediately
7381 * if there are no pending writes.
7383 trigger_write_time_update_immediate(fsp);
7384 return NT_STATUS_OK;
7387 /* Pathname or stat or directory file. */
7388 status = SMB_VFS_CREATE_FILE(
7389 conn, /* conn */
7390 req, /* req */
7391 0, /* root_dir_fid */
7392 smb_fname, /* fname */
7393 FILE_WRITE_DATA, /* access_mask */
7394 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
7395 FILE_SHARE_DELETE),
7396 FILE_OPEN, /* create_disposition*/
7397 0, /* create_options */
7398 FILE_ATTRIBUTE_NORMAL, /* file_attributes */
7399 0, /* oplock_request */
7400 NULL, /* lease */
7401 0, /* allocation_size */
7402 0, /* private_flags */
7403 NULL, /* sd */
7404 NULL, /* ea_list */
7405 &new_fsp, /* result */
7406 NULL, /* pinfo */
7407 NULL, NULL); /* create context */
7409 if (!NT_STATUS_IS_OK(status)) {
7410 /* NB. We check for open_was_deferred in the caller. */
7411 return status;
7414 /* Only change if needed. */
7415 if (allocation_size != get_file_size_stat(&smb_fname->st)) {
7416 if (vfs_allocate_file_space(new_fsp, allocation_size) == -1) {
7417 status = map_nt_error_from_unix(errno);
7418 close_file(req, new_fsp, NORMAL_CLOSE);
7419 return status;
7423 /* Changing the allocation size should set the last mod time. */
7425 * This is equivalent to a write. Ensure it's seen immediately
7426 * if there are no pending writes.
7428 trigger_write_time_update_immediate(new_fsp);
7429 close_file(req, new_fsp, NORMAL_CLOSE);
7430 return NT_STATUS_OK;
7433 /****************************************************************************
7434 Deal with SMB_SET_FILE_END_OF_FILE_INFO.
7435 ****************************************************************************/
7437 static NTSTATUS smb_set_file_end_of_file_info(connection_struct *conn,
7438 struct smb_request *req,
7439 const char *pdata,
7440 int total_data,
7441 files_struct *fsp,
7442 const struct smb_filename *smb_fname,
7443 bool fail_after_createfile)
7445 off_t size;
7447 if (total_data < 8) {
7448 return NT_STATUS_INVALID_PARAMETER;
7451 size = IVAL(pdata,0);
7452 size |= (((off_t)IVAL(pdata,4)) << 32);
7453 DEBUG(10,("smb_set_file_end_of_file_info: Set end of file info for "
7454 "file %s to %.0f\n", smb_fname_str_dbg(smb_fname),
7455 (double)size));
7457 return smb_set_file_size(conn, req,
7458 fsp,
7459 smb_fname,
7460 &smb_fname->st,
7461 size,
7462 fail_after_createfile);
7465 /****************************************************************************
7466 Allow a UNIX info mknod.
7467 ****************************************************************************/
7469 static NTSTATUS smb_unix_mknod(connection_struct *conn,
7470 const char *pdata,
7471 int total_data,
7472 const struct smb_filename *smb_fname)
7474 uint32_t file_type = IVAL(pdata,56);
7475 #if defined(HAVE_MAKEDEV)
7476 uint32_t dev_major = IVAL(pdata,60);
7477 uint32_t dev_minor = IVAL(pdata,68);
7478 #endif
7479 SMB_DEV_T dev = (SMB_DEV_T)0;
7480 uint32_t raw_unixmode = IVAL(pdata,84);
7481 NTSTATUS status;
7482 mode_t unixmode;
7484 if (total_data < 100) {
7485 return NT_STATUS_INVALID_PARAMETER;
7488 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7489 PERM_NEW_FILE, &unixmode);
7490 if (!NT_STATUS_IS_OK(status)) {
7491 return status;
7494 #if defined(HAVE_MAKEDEV)
7495 dev = makedev(dev_major, dev_minor);
7496 #endif
7498 switch (file_type) {
7499 #if defined(S_IFIFO)
7500 case UNIX_TYPE_FIFO:
7501 unixmode |= S_IFIFO;
7502 break;
7503 #endif
7504 #if defined(S_IFSOCK)
7505 case UNIX_TYPE_SOCKET:
7506 unixmode |= S_IFSOCK;
7507 break;
7508 #endif
7509 #if defined(S_IFCHR)
7510 case UNIX_TYPE_CHARDEV:
7511 unixmode |= S_IFCHR;
7512 break;
7513 #endif
7514 #if defined(S_IFBLK)
7515 case UNIX_TYPE_BLKDEV:
7516 unixmode |= S_IFBLK;
7517 break;
7518 #endif
7519 default:
7520 return NT_STATUS_INVALID_PARAMETER;
7523 DEBUG(10,("smb_unix_mknod: SMB_SET_FILE_UNIX_BASIC doing mknod dev "
7524 "%.0f mode 0%o for file %s\n", (double)dev,
7525 (unsigned int)unixmode, smb_fname_str_dbg(smb_fname)));
7527 /* Ok - do the mknod. */
7528 if (SMB_VFS_MKNOD(conn, smb_fname->base_name, unixmode, dev) != 0) {
7529 return map_nt_error_from_unix(errno);
7532 /* If any of the other "set" calls fail we
7533 * don't want to end up with a half-constructed mknod.
7536 if (lp_inherit_permissions(SNUM(conn))) {
7537 char *parent;
7538 if (!parent_dirname(talloc_tos(), smb_fname->base_name,
7539 &parent, NULL)) {
7540 return NT_STATUS_NO_MEMORY;
7542 inherit_access_posix_acl(conn, parent, smb_fname->base_name,
7543 unixmode);
7544 TALLOC_FREE(parent);
7547 return NT_STATUS_OK;
7550 /****************************************************************************
7551 Deal with SMB_SET_FILE_UNIX_BASIC.
7552 ****************************************************************************/
7554 static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
7555 struct smb_request *req,
7556 const char *pdata,
7557 int total_data,
7558 files_struct *fsp,
7559 const struct smb_filename *smb_fname)
7561 struct smb_file_time ft;
7562 uint32_t raw_unixmode;
7563 mode_t unixmode;
7564 off_t size = 0;
7565 uid_t set_owner = (uid_t)SMB_UID_NO_CHANGE;
7566 gid_t set_grp = (uid_t)SMB_GID_NO_CHANGE;
7567 NTSTATUS status = NT_STATUS_OK;
7568 bool delete_on_fail = False;
7569 enum perm_type ptype;
7570 files_struct *all_fsps = NULL;
7571 bool modify_mtime = true;
7572 struct file_id id;
7573 struct smb_filename *smb_fname_tmp = NULL;
7574 SMB_STRUCT_STAT sbuf;
7576 ZERO_STRUCT(ft);
7578 if (total_data < 100) {
7579 return NT_STATUS_INVALID_PARAMETER;
7582 if(IVAL(pdata, 0) != SMB_SIZE_NO_CHANGE_LO &&
7583 IVAL(pdata, 4) != SMB_SIZE_NO_CHANGE_HI) {
7584 size=IVAL(pdata,0); /* first 8 Bytes are size */
7585 size |= (((off_t)IVAL(pdata,4)) << 32);
7588 ft.atime = interpret_long_date(pdata+24); /* access_time */
7589 ft.mtime = interpret_long_date(pdata+32); /* modification_time */
7590 set_owner = (uid_t)IVAL(pdata,40);
7591 set_grp = (gid_t)IVAL(pdata,48);
7592 raw_unixmode = IVAL(pdata,84);
7594 if (VALID_STAT(smb_fname->st)) {
7595 if (S_ISDIR(smb_fname->st.st_ex_mode)) {
7596 ptype = PERM_EXISTING_DIR;
7597 } else {
7598 ptype = PERM_EXISTING_FILE;
7600 } else {
7601 ptype = PERM_NEW_FILE;
7604 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7605 ptype, &unixmode);
7606 if (!NT_STATUS_IS_OK(status)) {
7607 return status;
7610 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC: name = "
7611 "%s size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
7612 smb_fname_str_dbg(smb_fname), (double)size,
7613 (unsigned int)set_owner, (unsigned int)set_grp,
7614 (int)raw_unixmode));
7616 sbuf = smb_fname->st;
7618 if (!VALID_STAT(sbuf)) {
7620 * The only valid use of this is to create character and block
7621 * devices, and named pipes. This is deprecated (IMHO) and
7622 * a new info level should be used for mknod. JRA.
7625 status = smb_unix_mknod(conn,
7626 pdata,
7627 total_data,
7628 smb_fname);
7629 if (!NT_STATUS_IS_OK(status)) {
7630 return status;
7633 smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
7634 if (smb_fname_tmp == NULL) {
7635 return NT_STATUS_NO_MEMORY;
7638 if (SMB_VFS_STAT(conn, smb_fname_tmp) != 0) {
7639 status = map_nt_error_from_unix(errno);
7640 TALLOC_FREE(smb_fname_tmp);
7641 SMB_VFS_UNLINK(conn, smb_fname);
7642 return status;
7645 sbuf = smb_fname_tmp->st;
7646 smb_fname = smb_fname_tmp;
7648 /* Ensure we don't try and change anything else. */
7649 raw_unixmode = SMB_MODE_NO_CHANGE;
7650 size = get_file_size_stat(&sbuf);
7651 ft.atime = sbuf.st_ex_atime;
7652 ft.mtime = sbuf.st_ex_mtime;
7654 * We continue here as we might want to change the
7655 * owner uid/gid.
7657 delete_on_fail = True;
7660 #if 1
7661 /* Horrible backwards compatibility hack as an old server bug
7662 * allowed a CIFS client bug to remain unnoticed :-(. JRA.
7663 * */
7665 if (!size) {
7666 size = get_file_size_stat(&sbuf);
7668 #endif
7671 * Deal with the UNIX specific mode set.
7674 if (raw_unixmode != SMB_MODE_NO_CHANGE) {
7675 int ret;
7677 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7678 "setting mode 0%o for file %s\n",
7679 (unsigned int)unixmode,
7680 smb_fname_str_dbg(smb_fname)));
7681 if (fsp && fsp->fh->fd != -1) {
7682 ret = SMB_VFS_FCHMOD(fsp, unixmode);
7683 } else {
7684 ret = SMB_VFS_CHMOD(conn, smb_fname, unixmode);
7686 if (ret != 0) {
7687 return map_nt_error_from_unix(errno);
7692 * Deal with the UNIX specific uid set.
7695 if ((set_owner != (uid_t)SMB_UID_NO_CHANGE) &&
7696 (sbuf.st_ex_uid != set_owner)) {
7697 int ret;
7699 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7700 "changing owner %u for path %s\n",
7701 (unsigned int)set_owner,
7702 smb_fname_str_dbg(smb_fname)));
7704 if (fsp && fsp->fh->fd != -1) {
7705 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7706 } else {
7708 * UNIX extensions calls must always operate
7709 * on symlinks.
7711 ret = SMB_VFS_LCHOWN(conn, smb_fname,
7712 set_owner, (gid_t)-1);
7715 if (ret != 0) {
7716 status = map_nt_error_from_unix(errno);
7717 if (delete_on_fail) {
7718 SMB_VFS_UNLINK(conn, smb_fname);
7720 return status;
7725 * Deal with the UNIX specific gid set.
7728 if ((set_grp != (uid_t)SMB_GID_NO_CHANGE) &&
7729 (sbuf.st_ex_gid != set_grp)) {
7730 int ret;
7732 DEBUG(10,("smb_set_file_unix_basic: SMB_SET_FILE_UNIX_BASIC "
7733 "changing group %u for file %s\n",
7734 (unsigned int)set_owner,
7735 smb_fname_str_dbg(smb_fname)));
7736 if (fsp && fsp->fh->fd != -1) {
7737 ret = SMB_VFS_FCHOWN(fsp, set_owner, (gid_t)-1);
7738 } else {
7740 * UNIX extensions calls must always operate
7741 * on symlinks.
7743 ret = SMB_VFS_LCHOWN(conn, smb_fname, (uid_t)-1,
7744 set_grp);
7746 if (ret != 0) {
7747 status = map_nt_error_from_unix(errno);
7748 if (delete_on_fail) {
7749 SMB_VFS_UNLINK(conn, smb_fname);
7751 return status;
7755 /* Deal with any size changes. */
7757 status = smb_set_file_size(conn, req,
7758 fsp,
7759 smb_fname,
7760 &sbuf,
7761 size,
7762 false);
7763 if (!NT_STATUS_IS_OK(status)) {
7764 return status;
7767 /* Deal with any time changes. */
7768 if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
7769 /* No change, don't cancel anything. */
7770 return status;
7773 id = vfs_file_id_from_sbuf(conn, &sbuf);
7774 for(all_fsps = file_find_di_first(conn->sconn, id); all_fsps;
7775 all_fsps = file_find_di_next(all_fsps)) {
7777 * We're setting the time explicitly for UNIX.
7778 * Cancel any pending changes over all handles.
7780 all_fsps->update_write_time_on_close = false;
7781 TALLOC_FREE(all_fsps->update_write_time_event);
7785 * Override the "setting_write_time"
7786 * parameter here as it almost does what
7787 * we need. Just remember if we modified
7788 * mtime and send the notify ourselves.
7790 if (null_timespec(ft.mtime)) {
7791 modify_mtime = false;
7794 status = smb_set_file_time(conn,
7795 fsp,
7796 smb_fname,
7797 &ft,
7798 false);
7799 if (modify_mtime) {
7800 notify_fname(conn, NOTIFY_ACTION_MODIFIED,
7801 FILE_NOTIFY_CHANGE_LAST_WRITE, smb_fname->base_name);
7803 return status;
7806 /****************************************************************************
7807 Deal with SMB_SET_FILE_UNIX_INFO2.
7808 ****************************************************************************/
7810 static NTSTATUS smb_set_file_unix_info2(connection_struct *conn,
7811 struct smb_request *req,
7812 const char *pdata,
7813 int total_data,
7814 files_struct *fsp,
7815 const struct smb_filename *smb_fname)
7817 NTSTATUS status;
7818 uint32_t smb_fflags;
7819 uint32_t smb_fmask;
7821 if (total_data < 116) {
7822 return NT_STATUS_INVALID_PARAMETER;
7825 /* Start by setting all the fields that are common between UNIX_BASIC
7826 * and UNIX_INFO2.
7828 status = smb_set_file_unix_basic(conn, req, pdata, total_data,
7829 fsp, smb_fname);
7830 if (!NT_STATUS_IS_OK(status)) {
7831 return status;
7834 smb_fflags = IVAL(pdata, 108);
7835 smb_fmask = IVAL(pdata, 112);
7837 /* NB: We should only attempt to alter the file flags if the client
7838 * sends a non-zero mask.
7840 if (smb_fmask != 0) {
7841 int stat_fflags = 0;
7843 if (!map_info2_flags_to_sbuf(&smb_fname->st, smb_fflags,
7844 smb_fmask, &stat_fflags)) {
7845 /* Client asked to alter a flag we don't understand. */
7846 return NT_STATUS_INVALID_PARAMETER;
7849 if (fsp && fsp->fh->fd != -1) {
7850 /* XXX: we should be using SMB_VFS_FCHFLAGS here. */
7851 return NT_STATUS_NOT_SUPPORTED;
7852 } else {
7853 if (SMB_VFS_CHFLAGS(conn, smb_fname->base_name,
7854 stat_fflags) != 0) {
7855 return map_nt_error_from_unix(errno);
7860 /* XXX: need to add support for changing the create_time here. You
7861 * can do this for paths on Darwin with setattrlist(2). The right way
7862 * to hook this up is probably by extending the VFS utimes interface.
7865 return NT_STATUS_OK;
7868 /****************************************************************************
7869 Create a directory with POSIX semantics.
7870 ****************************************************************************/
7872 static NTSTATUS smb_posix_mkdir(connection_struct *conn,
7873 struct smb_request *req,
7874 char **ppdata,
7875 int total_data,
7876 struct smb_filename *smb_fname,
7877 int *pdata_return_size)
7879 NTSTATUS status = NT_STATUS_OK;
7880 uint32_t raw_unixmode = 0;
7881 uint32_t mod_unixmode = 0;
7882 mode_t unixmode = (mode_t)0;
7883 files_struct *fsp = NULL;
7884 uint16_t info_level_return = 0;
7885 int info;
7886 char *pdata = *ppdata;
7888 if (total_data < 18) {
7889 return NT_STATUS_INVALID_PARAMETER;
7892 raw_unixmode = IVAL(pdata,8);
7893 /* Next 4 bytes are not yet defined. */
7895 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
7896 PERM_NEW_DIR, &unixmode);
7897 if (!NT_STATUS_IS_OK(status)) {
7898 return status;
7901 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
7903 DEBUG(10,("smb_posix_mkdir: file %s, mode 0%o\n",
7904 smb_fname_str_dbg(smb_fname), (unsigned int)unixmode));
7906 status = SMB_VFS_CREATE_FILE(
7907 conn, /* conn */
7908 req, /* req */
7909 0, /* root_dir_fid */
7910 smb_fname, /* fname */
7911 FILE_READ_ATTRIBUTES, /* access_mask */
7912 FILE_SHARE_NONE, /* share_access */
7913 FILE_CREATE, /* create_disposition*/
7914 FILE_DIRECTORY_FILE, /* create_options */
7915 mod_unixmode, /* file_attributes */
7916 0, /* oplock_request */
7917 NULL, /* lease */
7918 0, /* allocation_size */
7919 0, /* private_flags */
7920 NULL, /* sd */
7921 NULL, /* ea_list */
7922 &fsp, /* result */
7923 &info, /* pinfo */
7924 NULL, NULL); /* create context */
7926 if (NT_STATUS_IS_OK(status)) {
7927 close_file(req, fsp, NORMAL_CLOSE);
7930 info_level_return = SVAL(pdata,16);
7932 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
7933 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
7934 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
7935 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
7936 } else {
7937 *pdata_return_size = 12;
7940 /* Realloc the data size */
7941 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
7942 if (*ppdata == NULL) {
7943 *pdata_return_size = 0;
7944 return NT_STATUS_NO_MEMORY;
7946 pdata = *ppdata;
7948 SSVAL(pdata,0,NO_OPLOCK_RETURN);
7949 SSVAL(pdata,2,0); /* No fnum. */
7950 SIVAL(pdata,4,info); /* Was directory created. */
7952 switch (info_level_return) {
7953 case SMB_QUERY_FILE_UNIX_BASIC:
7954 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
7955 SSVAL(pdata,10,0); /* Padding. */
7956 store_file_unix_basic(conn, pdata + 12, fsp,
7957 &smb_fname->st);
7958 break;
7959 case SMB_QUERY_FILE_UNIX_INFO2:
7960 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
7961 SSVAL(pdata,10,0); /* Padding. */
7962 store_file_unix_basic_info2(conn, pdata + 12, fsp,
7963 &smb_fname->st);
7964 break;
7965 default:
7966 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
7967 SSVAL(pdata,10,0); /* Padding. */
7968 break;
7971 return status;
7974 /****************************************************************************
7975 Open/Create a file with POSIX semantics.
7976 ****************************************************************************/
7978 #define SMB_O_RDONLY_MAPPING (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA)
7979 #define SMB_O_WRONLY_MAPPING (FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA)
7981 static NTSTATUS smb_posix_open(connection_struct *conn,
7982 struct smb_request *req,
7983 char **ppdata,
7984 int total_data,
7985 struct smb_filename *smb_fname,
7986 int *pdata_return_size)
7988 bool extended_oplock_granted = False;
7989 char *pdata = *ppdata;
7990 uint32_t flags = 0;
7991 uint32_t wire_open_mode = 0;
7992 uint32_t raw_unixmode = 0;
7993 uint32_t mod_unixmode = 0;
7994 uint32_t create_disp = 0;
7995 uint32_t access_mask = 0;
7996 uint32_t create_options = FILE_NON_DIRECTORY_FILE;
7997 NTSTATUS status = NT_STATUS_OK;
7998 mode_t unixmode = (mode_t)0;
7999 files_struct *fsp = NULL;
8000 int oplock_request = 0;
8001 int info = 0;
8002 uint16_t info_level_return = 0;
8004 if (total_data < 18) {
8005 return NT_STATUS_INVALID_PARAMETER;
8008 flags = IVAL(pdata,0);
8009 oplock_request = (flags & REQUEST_OPLOCK) ? EXCLUSIVE_OPLOCK : 0;
8010 if (oplock_request) {
8011 oplock_request |= (flags & REQUEST_BATCH_OPLOCK) ? BATCH_OPLOCK : 0;
8014 wire_open_mode = IVAL(pdata,4);
8016 if (wire_open_mode == (SMB_O_CREAT|SMB_O_DIRECTORY)) {
8017 return smb_posix_mkdir(conn, req,
8018 ppdata,
8019 total_data,
8020 smb_fname,
8021 pdata_return_size);
8024 switch (wire_open_mode & SMB_ACCMODE) {
8025 case SMB_O_RDONLY:
8026 access_mask = SMB_O_RDONLY_MAPPING;
8027 break;
8028 case SMB_O_WRONLY:
8029 access_mask = SMB_O_WRONLY_MAPPING;
8030 break;
8031 case SMB_O_RDWR:
8032 access_mask = (SMB_O_RDONLY_MAPPING|
8033 SMB_O_WRONLY_MAPPING);
8034 break;
8035 default:
8036 DEBUG(5,("smb_posix_open: invalid open mode 0x%x\n",
8037 (unsigned int)wire_open_mode ));
8038 return NT_STATUS_INVALID_PARAMETER;
8041 wire_open_mode &= ~SMB_ACCMODE;
8043 /* First take care of O_CREAT|O_EXCL interactions. */
8044 switch (wire_open_mode & (SMB_O_CREAT | SMB_O_EXCL)) {
8045 case (SMB_O_CREAT | SMB_O_EXCL):
8046 /* File exists fail. File not exist create. */
8047 create_disp = FILE_CREATE;
8048 break;
8049 case SMB_O_CREAT:
8050 /* File exists open. File not exist create. */
8051 create_disp = FILE_OPEN_IF;
8052 break;
8053 case SMB_O_EXCL:
8054 /* O_EXCL on its own without O_CREAT is undefined.
8055 We deliberately ignore it as some versions of
8056 Linux CIFSFS can send a bare O_EXCL on the
8057 wire which other filesystems in the kernel
8058 ignore. See bug 9519 for details. */
8060 /* Fallthrough. */
8062 case 0:
8063 /* File exists open. File not exist fail. */
8064 create_disp = FILE_OPEN;
8065 break;
8066 default:
8067 DEBUG(5,("smb_posix_open: invalid create mode 0x%x\n",
8068 (unsigned int)wire_open_mode ));
8069 return NT_STATUS_INVALID_PARAMETER;
8072 /* Next factor in the effects of O_TRUNC. */
8073 wire_open_mode &= ~(SMB_O_CREAT | SMB_O_EXCL);
8075 if (wire_open_mode & SMB_O_TRUNC) {
8076 switch (create_disp) {
8077 case FILE_CREATE:
8078 /* (SMB_O_CREAT | SMB_O_EXCL | O_TRUNC) */
8079 /* Leave create_disp alone as
8080 (O_CREAT|O_EXCL|O_TRUNC) == (O_CREAT|O_EXCL)
8082 /* File exists fail. File not exist create. */
8083 break;
8084 case FILE_OPEN_IF:
8085 /* SMB_O_CREAT | SMB_O_TRUNC */
8086 /* File exists overwrite. File not exist create. */
8087 create_disp = FILE_OVERWRITE_IF;
8088 break;
8089 case FILE_OPEN:
8090 /* SMB_O_TRUNC */
8091 /* File exists overwrite. File not exist fail. */
8092 create_disp = FILE_OVERWRITE;
8093 break;
8094 default:
8095 /* Cannot get here. */
8096 smb_panic("smb_posix_open: logic error");
8097 return NT_STATUS_INVALID_PARAMETER;
8101 raw_unixmode = IVAL(pdata,8);
8102 /* Next 4 bytes are not yet defined. */
8104 status = unix_perms_from_wire(conn, &smb_fname->st, raw_unixmode,
8105 (VALID_STAT(smb_fname->st) ?
8106 PERM_EXISTING_FILE : PERM_NEW_FILE),
8107 &unixmode);
8109 if (!NT_STATUS_IS_OK(status)) {
8110 return status;
8113 mod_unixmode = (uint32_t)unixmode | FILE_FLAG_POSIX_SEMANTICS;
8115 if (wire_open_mode & SMB_O_SYNC) {
8116 create_options |= FILE_WRITE_THROUGH;
8118 if (wire_open_mode & SMB_O_APPEND) {
8119 access_mask |= FILE_APPEND_DATA;
8121 if (wire_open_mode & SMB_O_DIRECT) {
8122 mod_unixmode |= FILE_FLAG_NO_BUFFERING;
8125 if ((wire_open_mode & SMB_O_DIRECTORY) ||
8126 VALID_STAT_OF_DIR(smb_fname->st)) {
8127 if (access_mask != SMB_O_RDONLY_MAPPING) {
8128 return NT_STATUS_FILE_IS_A_DIRECTORY;
8130 create_options &= ~FILE_NON_DIRECTORY_FILE;
8131 create_options |= FILE_DIRECTORY_FILE;
8134 DEBUG(10,("smb_posix_open: file %s, smb_posix_flags = %u, mode 0%o\n",
8135 smb_fname_str_dbg(smb_fname),
8136 (unsigned int)wire_open_mode,
8137 (unsigned int)unixmode ));
8139 status = SMB_VFS_CREATE_FILE(
8140 conn, /* conn */
8141 req, /* req */
8142 0, /* root_dir_fid */
8143 smb_fname, /* fname */
8144 access_mask, /* access_mask */
8145 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8146 FILE_SHARE_DELETE),
8147 create_disp, /* create_disposition*/
8148 create_options, /* create_options */
8149 mod_unixmode, /* file_attributes */
8150 oplock_request, /* oplock_request */
8151 NULL, /* lease */
8152 0, /* allocation_size */
8153 0, /* private_flags */
8154 NULL, /* sd */
8155 NULL, /* ea_list */
8156 &fsp, /* result */
8157 &info, /* pinfo */
8158 NULL, NULL); /* create context */
8160 if (!NT_STATUS_IS_OK(status)) {
8161 return status;
8164 if (oplock_request && lp_fake_oplocks(SNUM(conn))) {
8165 extended_oplock_granted = True;
8168 if(oplock_request && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) {
8169 extended_oplock_granted = True;
8172 info_level_return = SVAL(pdata,16);
8174 /* Allocate the correct return size. */
8176 if (info_level_return == SMB_QUERY_FILE_UNIX_BASIC) {
8177 *pdata_return_size = 12 + SMB_FILE_UNIX_BASIC_SIZE;
8178 } else if (info_level_return == SMB_QUERY_FILE_UNIX_INFO2) {
8179 *pdata_return_size = 12 + SMB_FILE_UNIX_INFO2_SIZE;
8180 } else {
8181 *pdata_return_size = 12;
8184 /* Realloc the data size */
8185 *ppdata = (char *)SMB_REALLOC(*ppdata,*pdata_return_size);
8186 if (*ppdata == NULL) {
8187 close_file(req, fsp, ERROR_CLOSE);
8188 *pdata_return_size = 0;
8189 return NT_STATUS_NO_MEMORY;
8191 pdata = *ppdata;
8193 if (extended_oplock_granted) {
8194 if (flags & REQUEST_BATCH_OPLOCK) {
8195 SSVAL(pdata,0, BATCH_OPLOCK_RETURN);
8196 } else {
8197 SSVAL(pdata,0, EXCLUSIVE_OPLOCK_RETURN);
8199 } else if (fsp->oplock_type == LEVEL_II_OPLOCK) {
8200 SSVAL(pdata,0, LEVEL_II_OPLOCK_RETURN);
8201 } else {
8202 SSVAL(pdata,0,NO_OPLOCK_RETURN);
8205 SSVAL(pdata,2,fsp->fnum);
8206 SIVAL(pdata,4,info); /* Was file created etc. */
8208 switch (info_level_return) {
8209 case SMB_QUERY_FILE_UNIX_BASIC:
8210 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_BASIC);
8211 SSVAL(pdata,10,0); /* padding. */
8212 store_file_unix_basic(conn, pdata + 12, fsp,
8213 &smb_fname->st);
8214 break;
8215 case SMB_QUERY_FILE_UNIX_INFO2:
8216 SSVAL(pdata,8,SMB_QUERY_FILE_UNIX_INFO2);
8217 SSVAL(pdata,10,0); /* padding. */
8218 store_file_unix_basic_info2(conn, pdata + 12, fsp,
8219 &smb_fname->st);
8220 break;
8221 default:
8222 SSVAL(pdata,8,SMB_NO_INFO_LEVEL_RETURNED);
8223 SSVAL(pdata,10,0); /* padding. */
8224 break;
8226 return NT_STATUS_OK;
8229 /****************************************************************************
8230 Delete a file with POSIX semantics.
8231 ****************************************************************************/
8233 static NTSTATUS smb_posix_unlink(connection_struct *conn,
8234 struct smb_request *req,
8235 const char *pdata,
8236 int total_data,
8237 struct smb_filename *smb_fname)
8239 NTSTATUS status = NT_STATUS_OK;
8240 files_struct *fsp = NULL;
8241 uint16_t flags = 0;
8242 char del = 1;
8243 int info = 0;
8244 int create_options = 0;
8245 int i;
8246 struct share_mode_lock *lck = NULL;
8248 if (total_data < 2) {
8249 return NT_STATUS_INVALID_PARAMETER;
8252 flags = SVAL(pdata,0);
8254 if (!VALID_STAT(smb_fname->st)) {
8255 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
8258 if ((flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) &&
8259 !VALID_STAT_OF_DIR(smb_fname->st)) {
8260 return NT_STATUS_NOT_A_DIRECTORY;
8263 DEBUG(10,("smb_posix_unlink: %s %s\n",
8264 (flags == SMB_POSIX_UNLINK_DIRECTORY_TARGET) ? "directory" : "file",
8265 smb_fname_str_dbg(smb_fname)));
8267 if (VALID_STAT_OF_DIR(smb_fname->st)) {
8268 create_options |= FILE_DIRECTORY_FILE;
8271 status = SMB_VFS_CREATE_FILE(
8272 conn, /* conn */
8273 req, /* req */
8274 0, /* root_dir_fid */
8275 smb_fname, /* fname */
8276 DELETE_ACCESS, /* access_mask */
8277 (FILE_SHARE_READ | FILE_SHARE_WRITE | /* share_access */
8278 FILE_SHARE_DELETE),
8279 FILE_OPEN, /* create_disposition*/
8280 create_options, /* create_options */
8281 FILE_FLAG_POSIX_SEMANTICS|0777, /* file_attributes */
8282 0, /* oplock_request */
8283 NULL, /* lease */
8284 0, /* allocation_size */
8285 0, /* private_flags */
8286 NULL, /* sd */
8287 NULL, /* ea_list */
8288 &fsp, /* result */
8289 &info, /* pinfo */
8290 NULL, NULL); /* create context */
8292 if (!NT_STATUS_IS_OK(status)) {
8293 return status;
8297 * Don't lie to client. If we can't really delete due to
8298 * non-POSIX opens return SHARING_VIOLATION.
8301 lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
8302 if (lck == NULL) {
8303 DEBUG(0, ("smb_posix_unlink: Could not get share mode "
8304 "lock for file %s\n", fsp_str_dbg(fsp)));
8305 close_file(req, fsp, NORMAL_CLOSE);
8306 return NT_STATUS_INVALID_PARAMETER;
8310 * See if others still have the file open. If this is the case, then
8311 * don't delete. If all opens are POSIX delete we can set the delete
8312 * on close disposition.
8314 for (i=0; i<lck->data->num_share_modes; i++) {
8315 struct share_mode_entry *e = &lck->data->share_modes[i];
8316 if (is_valid_share_mode_entry(e)) {
8317 if (e->flags & SHARE_MODE_FLAG_POSIX_OPEN) {
8318 continue;
8320 if (share_mode_stale_pid(lck->data, i)) {
8321 continue;
8323 /* Fail with sharing violation. */
8324 TALLOC_FREE(lck);
8325 close_file(req, fsp, NORMAL_CLOSE);
8326 return NT_STATUS_SHARING_VIOLATION;
8331 * Set the delete on close.
8333 status = smb_set_file_disposition_info(conn,
8334 &del,
8336 fsp,
8337 smb_fname);
8339 TALLOC_FREE(lck);
8341 if (!NT_STATUS_IS_OK(status)) {
8342 close_file(req, fsp, NORMAL_CLOSE);
8343 return status;
8345 return close_file(req, fsp, NORMAL_CLOSE);
8348 NTSTATUS smbd_do_setfilepathinfo(connection_struct *conn,
8349 struct smb_request *req,
8350 TALLOC_CTX *mem_ctx,
8351 uint16_t info_level,
8352 files_struct *fsp,
8353 struct smb_filename *smb_fname,
8354 char **ppdata, int total_data,
8355 int *ret_data_size)
8357 char *pdata = *ppdata;
8358 NTSTATUS status = NT_STATUS_OK;
8359 int data_return_size = 0;
8361 *ret_data_size = 0;
8363 if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
8364 return NT_STATUS_INVALID_LEVEL;
8367 if (!CAN_WRITE(conn)) {
8368 /* Allow POSIX opens. The open path will deny
8369 * any non-readonly opens. */
8370 if (info_level != SMB_POSIX_PATH_OPEN) {
8371 return NT_STATUS_DOS(ERRSRV, ERRaccess);
8375 DEBUG(3,("smbd_do_setfilepathinfo: %s (%s) info_level=%d "
8376 "totdata=%d\n", smb_fname_str_dbg(smb_fname),
8377 fsp_fnum_dbg(fsp),
8378 info_level, total_data));
8380 switch (info_level) {
8382 case SMB_INFO_STANDARD:
8384 status = smb_set_info_standard(conn,
8385 pdata,
8386 total_data,
8387 fsp,
8388 smb_fname);
8389 break;
8392 case SMB_INFO_SET_EA:
8394 status = smb_info_set_ea(conn,
8395 pdata,
8396 total_data,
8397 fsp,
8398 smb_fname);
8399 break;
8402 case SMB_SET_FILE_BASIC_INFO:
8403 case SMB_FILE_BASIC_INFORMATION:
8405 status = smb_set_file_basic_info(conn,
8406 pdata,
8407 total_data,
8408 fsp,
8409 smb_fname);
8410 break;
8413 case SMB_FILE_ALLOCATION_INFORMATION:
8414 case SMB_SET_FILE_ALLOCATION_INFO:
8416 status = smb_set_file_allocation_info(conn, req,
8417 pdata,
8418 total_data,
8419 fsp,
8420 smb_fname);
8421 break;
8424 case SMB_FILE_END_OF_FILE_INFORMATION:
8425 case SMB_SET_FILE_END_OF_FILE_INFO:
8428 * XP/Win7 both fail after the createfile with
8429 * SMB_SET_FILE_END_OF_FILE_INFO but not
8430 * SMB_FILE_END_OF_FILE_INFORMATION (pass-through).
8431 * The level is known here, so pass it down
8432 * appropriately.
8434 bool should_fail =
8435 (info_level == SMB_SET_FILE_END_OF_FILE_INFO);
8437 status = smb_set_file_end_of_file_info(conn, req,
8438 pdata,
8439 total_data,
8440 fsp,
8441 smb_fname,
8442 should_fail);
8443 break;
8446 case SMB_FILE_DISPOSITION_INFORMATION:
8447 case SMB_SET_FILE_DISPOSITION_INFO: /* Set delete on close for open file. */
8449 #if 0
8450 /* JRA - We used to just ignore this on a path ?
8451 * Shouldn't this be invalid level on a pathname
8452 * based call ?
8454 if (tran_call != TRANSACT2_SETFILEINFO) {
8455 return ERROR_NT(NT_STATUS_INVALID_LEVEL);
8457 #endif
8458 status = smb_set_file_disposition_info(conn,
8459 pdata,
8460 total_data,
8461 fsp,
8462 smb_fname);
8463 break;
8466 case SMB_FILE_POSITION_INFORMATION:
8468 status = smb_file_position_information(conn,
8469 pdata,
8470 total_data,
8471 fsp);
8472 break;
8475 case SMB_FILE_FULL_EA_INFORMATION:
8477 status = smb_set_file_full_ea_info(conn,
8478 pdata,
8479 total_data,
8480 fsp);
8481 break;
8484 /* From tridge Samba4 :
8485 * MODE_INFORMATION in setfileinfo (I have no
8486 * idea what "mode information" on a file is - it takes a value of 0,
8487 * 2, 4 or 6. What could it be?).
8490 case SMB_FILE_MODE_INFORMATION:
8492 status = smb_file_mode_information(conn,
8493 pdata,
8494 total_data);
8495 break;
8499 * CIFS UNIX extensions.
8502 case SMB_SET_FILE_UNIX_BASIC:
8504 status = smb_set_file_unix_basic(conn, req,
8505 pdata,
8506 total_data,
8507 fsp,
8508 smb_fname);
8509 break;
8512 case SMB_SET_FILE_UNIX_INFO2:
8514 status = smb_set_file_unix_info2(conn, req,
8515 pdata,
8516 total_data,
8517 fsp,
8518 smb_fname);
8519 break;
8522 case SMB_SET_FILE_UNIX_LINK:
8524 if (fsp) {
8525 /* We must have a pathname for this. */
8526 return NT_STATUS_INVALID_LEVEL;
8528 status = smb_set_file_unix_link(conn, req, pdata,
8529 total_data, smb_fname);
8530 break;
8533 case SMB_SET_FILE_UNIX_HLINK:
8535 if (fsp) {
8536 /* We must have a pathname for this. */
8537 return NT_STATUS_INVALID_LEVEL;
8539 status = smb_set_file_unix_hlink(conn, req,
8540 pdata, total_data,
8541 smb_fname);
8542 break;
8545 case SMB_FILE_RENAME_INFORMATION:
8547 status = smb_file_rename_information(conn, req,
8548 pdata, total_data,
8549 fsp, smb_fname);
8550 break;
8553 case SMB2_FILE_RENAME_INFORMATION_INTERNAL:
8555 /* SMB2 rename information. */
8556 status = smb2_file_rename_information(conn, req,
8557 pdata, total_data,
8558 fsp, smb_fname);
8559 break;
8562 case SMB_FILE_LINK_INFORMATION:
8564 status = smb_file_link_information(conn, req,
8565 pdata, total_data,
8566 fsp, smb_fname);
8567 break;
8570 #if defined(HAVE_POSIX_ACLS)
8571 case SMB_SET_POSIX_ACL:
8573 status = smb_set_posix_acl(conn,
8574 pdata,
8575 total_data,
8576 fsp,
8577 smb_fname);
8578 break;
8580 #endif
8582 case SMB_SET_POSIX_LOCK:
8584 if (!fsp) {
8585 return NT_STATUS_INVALID_LEVEL;
8587 status = smb_set_posix_lock(conn, req,
8588 pdata, total_data, fsp);
8589 break;
8592 case SMB_POSIX_PATH_OPEN:
8594 if (fsp) {
8595 /* We must have a pathname for this. */
8596 return NT_STATUS_INVALID_LEVEL;
8599 status = smb_posix_open(conn, req,
8600 ppdata,
8601 total_data,
8602 smb_fname,
8603 &data_return_size);
8604 break;
8607 case SMB_POSIX_PATH_UNLINK:
8609 if (fsp) {
8610 /* We must have a pathname for this. */
8611 return NT_STATUS_INVALID_LEVEL;
8614 status = smb_posix_unlink(conn, req,
8615 pdata,
8616 total_data,
8617 smb_fname);
8618 break;
8621 default:
8622 return NT_STATUS_INVALID_LEVEL;
8625 if (!NT_STATUS_IS_OK(status)) {
8626 return status;
8629 *ret_data_size = data_return_size;
8630 return NT_STATUS_OK;
8633 /****************************************************************************
8634 Reply to a TRANS2_SETFILEINFO (set file info by fileid or pathname).
8635 ****************************************************************************/
8637 static void call_trans2setfilepathinfo(connection_struct *conn,
8638 struct smb_request *req,
8639 unsigned int tran_call,
8640 char **pparams, int total_params,
8641 char **ppdata, int total_data,
8642 unsigned int max_data_bytes)
8644 char *params = *pparams;
8645 char *pdata = *ppdata;
8646 uint16_t info_level;
8647 struct smb_filename *smb_fname = NULL;
8648 files_struct *fsp = NULL;
8649 NTSTATUS status = NT_STATUS_OK;
8650 int data_return_size = 0;
8652 if (!params) {
8653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8654 return;
8657 if (tran_call == TRANSACT2_SETFILEINFO) {
8658 if (total_params < 4) {
8659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8660 return;
8663 fsp = file_fsp(req, SVAL(params,0));
8664 /* Basic check for non-null fsp. */
8665 if (!check_fsp_open(conn, req, fsp)) {
8666 return;
8668 info_level = SVAL(params,2);
8670 smb_fname = cp_smb_filename(talloc_tos(), fsp->fsp_name);
8671 if (smb_fname == NULL) {
8672 reply_nterror(req, NT_STATUS_NO_MEMORY);
8673 return;
8676 if(fsp->fh->fd == -1) {
8678 * This is actually a SETFILEINFO on a directory
8679 * handle (returned from an NT SMB). NT5.0 seems
8680 * to do this call. JRA.
8682 if (INFO_LEVEL_IS_UNIX(info_level)) {
8683 /* Always do lstat for UNIX calls. */
8684 if (SMB_VFS_LSTAT(conn, smb_fname)) {
8685 DEBUG(3,("call_trans2setfilepathinfo: "
8686 "SMB_VFS_LSTAT of %s failed "
8687 "(%s)\n",
8688 smb_fname_str_dbg(smb_fname),
8689 strerror(errno)));
8690 reply_nterror(req, map_nt_error_from_unix(errno));
8691 return;
8693 } else {
8694 if (SMB_VFS_STAT(conn, smb_fname) != 0) {
8695 DEBUG(3,("call_trans2setfilepathinfo: "
8696 "fileinfo of %s failed (%s)\n",
8697 smb_fname_str_dbg(smb_fname),
8698 strerror(errno)));
8699 reply_nterror(req, map_nt_error_from_unix(errno));
8700 return;
8703 } else if (fsp->print_file) {
8705 * Doing a DELETE_ON_CLOSE should cancel a print job.
8707 if ((info_level == SMB_SET_FILE_DISPOSITION_INFO) && CVAL(pdata,0)) {
8708 fsp->fh->private_options |= NTCREATEX_OPTIONS_PRIVATE_DELETE_ON_CLOSE;
8710 DEBUG(3,("call_trans2setfilepathinfo: "
8711 "Cancelling print job (%s)\n",
8712 fsp_str_dbg(fsp)));
8714 SSVAL(params,0,0);
8715 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2,
8716 *ppdata, 0,
8717 max_data_bytes);
8718 return;
8719 } else {
8720 reply_nterror(req,
8721 NT_STATUS_OBJECT_PATH_NOT_FOUND);
8722 return;
8724 } else {
8726 * Original code - this is an open file.
8728 if (SMB_VFS_FSTAT(fsp, &smb_fname->st) != 0) {
8729 DEBUG(3,("call_trans2setfilepathinfo: fstat "
8730 "of %s failed (%s)\n", fsp_fnum_dbg(fsp),
8731 strerror(errno)));
8732 reply_nterror(req, map_nt_error_from_unix(errno));
8733 return;
8736 } else {
8737 char *fname = NULL;
8738 uint32_t ucf_flags = (req->posix_pathnames ?
8739 UCF_POSIX_PATHNAMES : 0);
8741 /* set path info */
8742 if (total_params < 7) {
8743 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8744 return;
8747 info_level = SVAL(params,0);
8748 if (req->posix_pathnames) {
8749 srvstr_get_path_posix(req,
8750 params,
8751 req->flags2,
8752 &fname,
8753 &params[6],
8754 total_params - 6,
8755 STR_TERMINATE,
8756 &status);
8757 } else {
8758 srvstr_get_path(req,
8759 params,
8760 req->flags2,
8761 &fname,
8762 &params[6],
8763 total_params - 6,
8764 STR_TERMINATE,
8765 &status);
8767 if (!NT_STATUS_IS_OK(status)) {
8768 reply_nterror(req, status);
8769 return;
8772 if (info_level == SMB_SET_FILE_UNIX_BASIC ||
8773 info_level == SMB_SET_FILE_UNIX_INFO2 ||
8774 info_level == SMB_FILE_RENAME_INFORMATION ||
8775 info_level == SMB_POSIX_PATH_UNLINK) {
8776 ucf_flags |= UCF_UNIX_NAME_LOOKUP;
8779 status = filename_convert(req, conn,
8780 req->flags2 & FLAGS2_DFS_PATHNAMES,
8781 fname,
8782 ucf_flags,
8783 NULL,
8784 &smb_fname);
8785 if (!NT_STATUS_IS_OK(status)) {
8786 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8787 reply_botherror(req,
8788 NT_STATUS_PATH_NOT_COVERED,
8789 ERRSRV, ERRbadpath);
8790 return;
8792 reply_nterror(req, status);
8793 return;
8796 if (INFO_LEVEL_IS_UNIX(info_level)) {
8798 * For CIFS UNIX extensions the target name may not exist.
8801 /* Always do lstat for UNIX calls. */
8802 SMB_VFS_LSTAT(conn, smb_fname);
8804 } else if (!VALID_STAT(smb_fname->st) &&
8805 SMB_VFS_STAT(conn, smb_fname)) {
8806 DEBUG(3,("call_trans2setfilepathinfo: SMB_VFS_STAT of "
8807 "%s failed (%s)\n",
8808 smb_fname_str_dbg(smb_fname),
8809 strerror(errno)));
8810 reply_nterror(req, map_nt_error_from_unix(errno));
8811 return;
8815 DEBUG(3,("call_trans2setfilepathinfo(%d) %s (%s) info_level=%d "
8816 "totdata=%d\n", tran_call, smb_fname_str_dbg(smb_fname),
8817 fsp_fnum_dbg(fsp),
8818 info_level,total_data));
8820 /* Realloc the parameter size */
8821 *pparams = (char *)SMB_REALLOC(*pparams,2);
8822 if (*pparams == NULL) {
8823 reply_nterror(req, NT_STATUS_NO_MEMORY);
8824 return;
8826 params = *pparams;
8828 SSVAL(params,0,0);
8830 status = smbd_do_setfilepathinfo(conn, req, req,
8831 info_level,
8832 fsp,
8833 smb_fname,
8834 ppdata, total_data,
8835 &data_return_size);
8836 if (!NT_STATUS_IS_OK(status)) {
8837 if (open_was_deferred(req->xconn, req->mid)) {
8838 /* We have re-scheduled this call. */
8839 return;
8841 if (blocking_lock_was_deferred_smb1(req->sconn, req->mid)) {
8842 /* We have re-scheduled this call. */
8843 return;
8845 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8846 reply_botherror(req, NT_STATUS_PATH_NOT_COVERED,
8847 ERRSRV, ERRbadpath);
8848 return;
8850 if (info_level == SMB_POSIX_PATH_OPEN) {
8851 reply_openerror(req, status);
8852 return;
8856 * Invalid EA name needs to return 2 param bytes,
8857 * not a zero-length error packet.
8859 if (NT_STATUS_EQUAL(status, STATUS_INVALID_EA_NAME)) {
8860 send_trans2_replies(conn, req, status, params, 2, NULL, 0,
8861 max_data_bytes);
8862 } else {
8863 reply_nterror(req, status);
8865 return;
8868 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, data_return_size,
8869 max_data_bytes);
8871 return;
8874 /****************************************************************************
8875 Reply to a TRANS2_MKDIR (make directory with extended attributes).
8876 ****************************************************************************/
8878 static void call_trans2mkdir(connection_struct *conn, struct smb_request *req,
8879 char **pparams, int total_params,
8880 char **ppdata, int total_data,
8881 unsigned int max_data_bytes)
8883 struct smb_filename *smb_dname = NULL;
8884 char *params = *pparams;
8885 char *pdata = *ppdata;
8886 char *directory = NULL;
8887 NTSTATUS status = NT_STATUS_OK;
8888 struct ea_list *ea_list = NULL;
8889 uint32_t ucf_flags = (req->posix_pathnames ? UCF_POSIX_PATHNAMES : 0);
8890 TALLOC_CTX *ctx = talloc_tos();
8892 if (!CAN_WRITE(conn)) {
8893 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
8894 return;
8897 if (total_params < 5) {
8898 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8899 return;
8902 if (req->posix_pathnames) {
8903 srvstr_get_path_posix(ctx,
8904 params,
8905 req->flags2,
8906 &directory,
8907 &params[4],
8908 total_params - 4,
8909 STR_TERMINATE,
8910 &status);
8911 } else {
8912 srvstr_get_path(ctx,
8913 params,
8914 req->flags2,
8915 &directory,
8916 &params[4],
8917 total_params - 4,
8918 STR_TERMINATE,
8919 &status);
8921 if (!NT_STATUS_IS_OK(status)) {
8922 reply_nterror(req, status);
8923 return;
8926 DEBUG(3,("call_trans2mkdir : name = %s\n", directory));
8928 status = filename_convert(ctx,
8929 conn,
8930 req->flags2 & FLAGS2_DFS_PATHNAMES,
8931 directory,
8932 ucf_flags,
8933 NULL,
8934 &smb_dname);
8936 if (!NT_STATUS_IS_OK(status)) {
8937 if (NT_STATUS_EQUAL(status,NT_STATUS_PATH_NOT_COVERED)) {
8938 reply_botherror(req,
8939 NT_STATUS_PATH_NOT_COVERED,
8940 ERRSRV, ERRbadpath);
8941 return;
8943 reply_nterror(req, status);
8944 return;
8948 * OS/2 workplace shell seems to send SET_EA requests of "null"
8949 * length (4 bytes containing IVAL 4).
8950 * They seem to have no effect. Bug #3212. JRA.
8953 if (total_data && (total_data != 4)) {
8954 /* Any data in this call is an EA list. */
8955 if (total_data < 10) {
8956 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8957 goto out;
8960 if (IVAL(pdata,0) > total_data) {
8961 DEBUG(10,("call_trans2mkdir: bad total data size (%u) > %u\n",
8962 IVAL(pdata,0), (unsigned int)total_data));
8963 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8964 goto out;
8967 ea_list = read_ea_list(talloc_tos(), pdata + 4,
8968 total_data - 4);
8969 if (!ea_list) {
8970 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
8971 goto out;
8974 if (!lp_ea_support(SNUM(conn))) {
8975 reply_nterror(req, NT_STATUS_EAS_NOT_SUPPORTED);
8976 goto out;
8979 /* If total_data == 4 Windows doesn't care what values
8980 * are placed in that field, it just ignores them.
8981 * The System i QNTC IBM SMB client puts bad values here,
8982 * so ignore them. */
8984 status = create_directory(conn, req, smb_dname);
8986 if (!NT_STATUS_IS_OK(status)) {
8987 reply_nterror(req, status);
8988 goto out;
8991 /* Try and set any given EA. */
8992 if (ea_list) {
8993 status = set_ea(conn, NULL, smb_dname, ea_list);
8994 if (!NT_STATUS_IS_OK(status)) {
8995 reply_nterror(req, status);
8996 goto out;
9000 /* Realloc the parameter and data sizes */
9001 *pparams = (char *)SMB_REALLOC(*pparams,2);
9002 if(*pparams == NULL) {
9003 reply_nterror(req, NT_STATUS_NO_MEMORY);
9004 goto out;
9006 params = *pparams;
9008 SSVAL(params,0,0);
9010 send_trans2_replies(conn, req, NT_STATUS_OK, params, 2, *ppdata, 0, max_data_bytes);
9012 out:
9013 TALLOC_FREE(smb_dname);
9014 return;
9017 /****************************************************************************
9018 Reply to a TRANS2_FINDNOTIFYFIRST (start monitoring a directory for changes).
9019 We don't actually do this - we just send a null response.
9020 ****************************************************************************/
9022 static void call_trans2findnotifyfirst(connection_struct *conn,
9023 struct smb_request *req,
9024 char **pparams, int total_params,
9025 char **ppdata, int total_data,
9026 unsigned int max_data_bytes)
9028 char *params = *pparams;
9029 uint16_t info_level;
9031 if (total_params < 6) {
9032 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9033 return;
9036 info_level = SVAL(params,4);
9037 DEBUG(3,("call_trans2findnotifyfirst - info_level %d\n", info_level));
9039 switch (info_level) {
9040 case 1:
9041 case 2:
9042 break;
9043 default:
9044 reply_nterror(req, NT_STATUS_INVALID_LEVEL);
9045 return;
9048 /* Realloc the parameter and data sizes */
9049 *pparams = (char *)SMB_REALLOC(*pparams,6);
9050 if (*pparams == NULL) {
9051 reply_nterror(req, NT_STATUS_NO_MEMORY);
9052 return;
9054 params = *pparams;
9056 SSVAL(params,0,fnf_handle);
9057 SSVAL(params,2,0); /* No changes */
9058 SSVAL(params,4,0); /* No EA errors */
9060 fnf_handle++;
9062 if(fnf_handle == 0)
9063 fnf_handle = 257;
9065 send_trans2_replies(conn, req, NT_STATUS_OK, params, 6, *ppdata, 0, max_data_bytes);
9067 return;
9070 /****************************************************************************
9071 Reply to a TRANS2_FINDNOTIFYNEXT (continue monitoring a directory for
9072 changes). Currently this does nothing.
9073 ****************************************************************************/
9075 static void call_trans2findnotifynext(connection_struct *conn,
9076 struct smb_request *req,
9077 char **pparams, int total_params,
9078 char **ppdata, int total_data,
9079 unsigned int max_data_bytes)
9081 char *params = *pparams;
9083 DEBUG(3,("call_trans2findnotifynext\n"));
9085 /* Realloc the parameter and data sizes */
9086 *pparams = (char *)SMB_REALLOC(*pparams,4);
9087 if (*pparams == NULL) {
9088 reply_nterror(req, NT_STATUS_NO_MEMORY);
9089 return;
9091 params = *pparams;
9093 SSVAL(params,0,0); /* No changes */
9094 SSVAL(params,2,0); /* No EA errors */
9096 send_trans2_replies(conn, req, NT_STATUS_OK, params, 4, *ppdata, 0, max_data_bytes);
9098 return;
9101 /****************************************************************************
9102 Reply to a TRANS2_GET_DFS_REFERRAL - Shirish Kalele <kalele@veritas.com>.
9103 ****************************************************************************/
9105 static void call_trans2getdfsreferral(connection_struct *conn,
9106 struct smb_request *req,
9107 char **pparams, int total_params,
9108 char **ppdata, int total_data,
9109 unsigned int max_data_bytes)
9111 char *params = *pparams;
9112 char *pathname = NULL;
9113 int reply_size = 0;
9114 int max_referral_level;
9115 NTSTATUS status = NT_STATUS_OK;
9116 TALLOC_CTX *ctx = talloc_tos();
9118 DEBUG(10,("call_trans2getdfsreferral\n"));
9120 if (total_params < 3) {
9121 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9122 return;
9125 max_referral_level = SVAL(params,0);
9127 if(!lp_host_msdfs()) {
9128 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9129 return;
9132 srvstr_pull_talloc(ctx, params, req->flags2, &pathname, &params[2],
9133 total_params - 2, STR_TERMINATE);
9134 if (!pathname) {
9135 reply_nterror(req, NT_STATUS_NOT_FOUND);
9136 return;
9138 if((reply_size = setup_dfs_referral(conn, pathname, max_referral_level,
9139 ppdata,&status)) < 0) {
9140 reply_nterror(req, status);
9141 return;
9144 SSVAL((discard_const_p(uint8_t, req->inbuf)), smb_flg2,
9145 SVAL(req->inbuf,smb_flg2) | FLAGS2_DFS_PATHNAMES);
9146 send_trans2_replies(conn, req, NT_STATUS_OK, 0,0,*ppdata,reply_size, max_data_bytes);
9148 return;
9151 #define LMCAT_SPL 0x53
9152 #define LMFUNC_GETJOBID 0x60
9154 /****************************************************************************
9155 Reply to a TRANS2_IOCTL - used for OS/2 printing.
9156 ****************************************************************************/
9158 static void call_trans2ioctl(connection_struct *conn,
9159 struct smb_request *req,
9160 char **pparams, int total_params,
9161 char **ppdata, int total_data,
9162 unsigned int max_data_bytes)
9164 char *pdata = *ppdata;
9165 files_struct *fsp = file_fsp(req, SVAL(req->vwv+15, 0));
9166 NTSTATUS status;
9167 size_t len = 0;
9169 /* check for an invalid fid before proceeding */
9171 if (!fsp) {
9172 reply_nterror(req, NT_STATUS_INVALID_HANDLE);
9173 return;
9176 if ((SVAL(req->vwv+16, 0) == LMCAT_SPL)
9177 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9178 *ppdata = (char *)SMB_REALLOC(*ppdata, 32);
9179 if (*ppdata == NULL) {
9180 reply_nterror(req, NT_STATUS_NO_MEMORY);
9181 return;
9183 pdata = *ppdata;
9185 /* NOTE - THIS IS ASCII ONLY AT THE MOMENT - NOT SURE IF OS/2
9186 CAN ACCEPT THIS IN UNICODE. JRA. */
9188 /* Job number */
9189 SSVAL(pdata, 0, print_spool_rap_jobid(fsp->print_file));
9191 status = srvstr_push(pdata, req->flags2, pdata + 2,
9192 lp_netbios_name(), 15,
9193 STR_ASCII|STR_TERMINATE, &len); /* Our NetBIOS name */
9194 if (!NT_STATUS_IS_OK(status)) {
9195 reply_nterror(req, status);
9196 return;
9198 status = srvstr_push(pdata, req->flags2, pdata+18,
9199 lp_servicename(talloc_tos(), SNUM(conn)), 13,
9200 STR_ASCII|STR_TERMINATE, &len); /* Service name */
9201 if (!NT_STATUS_IS_OK(status)) {
9202 reply_nterror(req, status);
9203 return;
9205 send_trans2_replies(conn, req, NT_STATUS_OK, *pparams, 0, *ppdata, 32,
9206 max_data_bytes);
9207 return;
9210 DEBUG(2,("Unknown TRANS2_IOCTL\n"));
9211 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9214 /****************************************************************************
9215 Reply to a SMBfindclose (stop trans2 directory search).
9216 ****************************************************************************/
9218 void reply_findclose(struct smb_request *req)
9220 int dptr_num;
9221 struct smbd_server_connection *sconn = req->sconn;
9223 START_PROFILE(SMBfindclose);
9225 if (req->wct < 1) {
9226 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9227 END_PROFILE(SMBfindclose);
9228 return;
9231 dptr_num = SVALS(req->vwv+0, 0);
9233 DEBUG(3,("reply_findclose, dptr_num = %d\n", dptr_num));
9235 dptr_close(sconn, &dptr_num);
9237 reply_outbuf(req, 0, 0);
9239 DEBUG(3,("SMBfindclose dptr_num = %d\n", dptr_num));
9241 END_PROFILE(SMBfindclose);
9242 return;
9245 /****************************************************************************
9246 Reply to a SMBfindnclose (stop FINDNOTIFYFIRST directory search).
9247 ****************************************************************************/
9249 void reply_findnclose(struct smb_request *req)
9251 int dptr_num;
9253 START_PROFILE(SMBfindnclose);
9255 if (req->wct < 1) {
9256 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9257 END_PROFILE(SMBfindnclose);
9258 return;
9261 dptr_num = SVAL(req->vwv+0, 0);
9263 DEBUG(3,("reply_findnclose, dptr_num = %d\n", dptr_num));
9265 /* We never give out valid handles for a
9266 findnotifyfirst - so any dptr_num is ok here.
9267 Just ignore it. */
9269 reply_outbuf(req, 0, 0);
9271 DEBUG(3,("SMB_findnclose dptr_num = %d\n", dptr_num));
9273 END_PROFILE(SMBfindnclose);
9274 return;
9277 static void handle_trans2(connection_struct *conn, struct smb_request *req,
9278 struct trans_state *state)
9280 if (get_Protocol() >= PROTOCOL_NT1) {
9281 req->flags2 |= 0x40; /* IS_LONG_NAME */
9282 SSVAL((discard_const_p(uint8_t, req->inbuf)),smb_flg2,req->flags2);
9285 if (ENCRYPTION_REQUIRED(conn) && !req->encrypted) {
9286 if (state->call != TRANSACT2_QFSINFO &&
9287 state->call != TRANSACT2_SETFSINFO) {
9288 DEBUG(0,("handle_trans2: encryption required "
9289 "with call 0x%x\n",
9290 (unsigned int)state->call));
9291 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9292 return;
9296 SMB_PERFCOUNT_SET_SUBOP(&req->pcd, state->call);
9298 /* Now we must call the relevant TRANS2 function */
9299 switch(state->call) {
9300 case TRANSACT2_OPEN:
9302 START_PROFILE(Trans2_open);
9303 call_trans2open(conn, req,
9304 &state->param, state->total_param,
9305 &state->data, state->total_data,
9306 state->max_data_return);
9307 END_PROFILE(Trans2_open);
9308 break;
9311 case TRANSACT2_FINDFIRST:
9313 START_PROFILE(Trans2_findfirst);
9314 call_trans2findfirst(conn, req,
9315 &state->param, state->total_param,
9316 &state->data, state->total_data,
9317 state->max_data_return);
9318 END_PROFILE(Trans2_findfirst);
9319 break;
9322 case TRANSACT2_FINDNEXT:
9324 START_PROFILE(Trans2_findnext);
9325 call_trans2findnext(conn, req,
9326 &state->param, state->total_param,
9327 &state->data, state->total_data,
9328 state->max_data_return);
9329 END_PROFILE(Trans2_findnext);
9330 break;
9333 case TRANSACT2_QFSINFO:
9335 START_PROFILE(Trans2_qfsinfo);
9336 call_trans2qfsinfo(conn, req,
9337 &state->param, state->total_param,
9338 &state->data, state->total_data,
9339 state->max_data_return);
9340 END_PROFILE(Trans2_qfsinfo);
9341 break;
9344 case TRANSACT2_SETFSINFO:
9346 START_PROFILE(Trans2_setfsinfo);
9347 call_trans2setfsinfo(conn, req,
9348 &state->param, state->total_param,
9349 &state->data, state->total_data,
9350 state->max_data_return);
9351 END_PROFILE(Trans2_setfsinfo);
9352 break;
9355 case TRANSACT2_QPATHINFO:
9356 case TRANSACT2_QFILEINFO:
9358 START_PROFILE(Trans2_qpathinfo);
9359 call_trans2qfilepathinfo(conn, req, state->call,
9360 &state->param, state->total_param,
9361 &state->data, state->total_data,
9362 state->max_data_return);
9363 END_PROFILE(Trans2_qpathinfo);
9364 break;
9367 case TRANSACT2_SETPATHINFO:
9368 case TRANSACT2_SETFILEINFO:
9370 START_PROFILE(Trans2_setpathinfo);
9371 call_trans2setfilepathinfo(conn, req, state->call,
9372 &state->param, state->total_param,
9373 &state->data, state->total_data,
9374 state->max_data_return);
9375 END_PROFILE(Trans2_setpathinfo);
9376 break;
9379 case TRANSACT2_FINDNOTIFYFIRST:
9381 START_PROFILE(Trans2_findnotifyfirst);
9382 call_trans2findnotifyfirst(conn, req,
9383 &state->param, state->total_param,
9384 &state->data, state->total_data,
9385 state->max_data_return);
9386 END_PROFILE(Trans2_findnotifyfirst);
9387 break;
9390 case TRANSACT2_FINDNOTIFYNEXT:
9392 START_PROFILE(Trans2_findnotifynext);
9393 call_trans2findnotifynext(conn, req,
9394 &state->param, state->total_param,
9395 &state->data, state->total_data,
9396 state->max_data_return);
9397 END_PROFILE(Trans2_findnotifynext);
9398 break;
9401 case TRANSACT2_MKDIR:
9403 START_PROFILE(Trans2_mkdir);
9404 call_trans2mkdir(conn, req,
9405 &state->param, state->total_param,
9406 &state->data, state->total_data,
9407 state->max_data_return);
9408 END_PROFILE(Trans2_mkdir);
9409 break;
9412 case TRANSACT2_GET_DFS_REFERRAL:
9414 START_PROFILE(Trans2_get_dfs_referral);
9415 call_trans2getdfsreferral(conn, req,
9416 &state->param, state->total_param,
9417 &state->data, state->total_data,
9418 state->max_data_return);
9419 END_PROFILE(Trans2_get_dfs_referral);
9420 break;
9423 case TRANSACT2_IOCTL:
9425 START_PROFILE(Trans2_ioctl);
9426 call_trans2ioctl(conn, req,
9427 &state->param, state->total_param,
9428 &state->data, state->total_data,
9429 state->max_data_return);
9430 END_PROFILE(Trans2_ioctl);
9431 break;
9434 default:
9435 /* Error in request */
9436 DEBUG(2,("Unknown request %d in trans2 call\n", state->call));
9437 reply_nterror(req, NT_STATUS_NOT_IMPLEMENTED);
9441 /****************************************************************************
9442 Reply to a SMBtrans2.
9443 ****************************************************************************/
9445 void reply_trans2(struct smb_request *req)
9447 connection_struct *conn = req->conn;
9448 unsigned int dsoff;
9449 unsigned int dscnt;
9450 unsigned int psoff;
9451 unsigned int pscnt;
9452 unsigned int tran_call;
9453 struct trans_state *state;
9454 NTSTATUS result;
9456 START_PROFILE(SMBtrans2);
9458 if (req->wct < 14) {
9459 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9460 END_PROFILE(SMBtrans2);
9461 return;
9464 dsoff = SVAL(req->vwv+12, 0);
9465 dscnt = SVAL(req->vwv+11, 0);
9466 psoff = SVAL(req->vwv+10, 0);
9467 pscnt = SVAL(req->vwv+9, 0);
9468 tran_call = SVAL(req->vwv+14, 0);
9470 result = allow_new_trans(conn->pending_trans, req->mid);
9471 if (!NT_STATUS_IS_OK(result)) {
9472 DEBUG(2, ("Got invalid trans2 request: %s\n",
9473 nt_errstr(result)));
9474 reply_nterror(req, result);
9475 END_PROFILE(SMBtrans2);
9476 return;
9479 if (IS_IPC(conn)) {
9480 switch (tran_call) {
9481 /* List the allowed trans2 calls on IPC$ */
9482 case TRANSACT2_OPEN:
9483 case TRANSACT2_GET_DFS_REFERRAL:
9484 case TRANSACT2_QFILEINFO:
9485 case TRANSACT2_QFSINFO:
9486 case TRANSACT2_SETFSINFO:
9487 break;
9488 default:
9489 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
9490 END_PROFILE(SMBtrans2);
9491 return;
9495 if ((state = talloc(conn, struct trans_state)) == NULL) {
9496 DEBUG(0, ("talloc failed\n"));
9497 reply_nterror(req, NT_STATUS_NO_MEMORY);
9498 END_PROFILE(SMBtrans2);
9499 return;
9502 state->cmd = SMBtrans2;
9504 state->mid = req->mid;
9505 state->vuid = req->vuid;
9506 state->setup_count = SVAL(req->vwv+13, 0);
9507 state->setup = NULL;
9508 state->total_param = SVAL(req->vwv+0, 0);
9509 state->param = NULL;
9510 state->total_data = SVAL(req->vwv+1, 0);
9511 state->data = NULL;
9512 state->max_param_return = SVAL(req->vwv+2, 0);
9513 state->max_data_return = SVAL(req->vwv+3, 0);
9514 state->max_setup_return = SVAL(req->vwv+4, 0);
9515 state->close_on_completion = BITSETW(req->vwv+5, 0);
9516 state->one_way = BITSETW(req->vwv+5, 1);
9518 state->call = tran_call;
9520 /* All trans2 messages we handle have smb_sucnt == 1 - ensure this
9521 is so as a sanity check */
9522 if (state->setup_count != 1) {
9524 * Need to have rc=0 for ioctl to get job id for OS/2.
9525 * Network printing will fail if function is not successful.
9526 * Similar function in reply.c will be used if protocol
9527 * is LANMAN1.0 instead of LM1.2X002.
9528 * Until DosPrintSetJobInfo with PRJINFO3 is supported,
9529 * outbuf doesn't have to be set(only job id is used).
9531 if ( (state->setup_count == 4)
9532 && (tran_call == TRANSACT2_IOCTL)
9533 && (SVAL(req->vwv+16, 0) == LMCAT_SPL)
9534 && (SVAL(req->vwv+17, 0) == LMFUNC_GETJOBID)) {
9535 DEBUG(2,("Got Trans2 DevIOctl jobid\n"));
9536 } else {
9537 DEBUG(2,("Invalid smb_sucnt in trans2 call(%u)\n",state->setup_count));
9538 DEBUG(2,("Transaction is %d\n",tran_call));
9539 TALLOC_FREE(state);
9540 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9541 END_PROFILE(SMBtrans2);
9542 return;
9546 if ((dscnt > state->total_data) || (pscnt > state->total_param))
9547 goto bad_param;
9549 if (state->total_data) {
9551 if (trans_oob(state->total_data, 0, dscnt)
9552 || trans_oob(smb_len(req->inbuf), dsoff, dscnt)) {
9553 goto bad_param;
9556 /* Can't use talloc here, the core routines do realloc on the
9557 * params and data. */
9558 state->data = (char *)SMB_MALLOC(state->total_data);
9559 if (state->data == NULL) {
9560 DEBUG(0,("reply_trans2: data malloc fail for %u "
9561 "bytes !\n", (unsigned int)state->total_data));
9562 TALLOC_FREE(state);
9563 reply_nterror(req, NT_STATUS_NO_MEMORY);
9564 END_PROFILE(SMBtrans2);
9565 return;
9568 memcpy(state->data,smb_base(req->inbuf)+dsoff,dscnt);
9571 if (state->total_param) {
9573 if (trans_oob(state->total_param, 0, pscnt)
9574 || trans_oob(smb_len(req->inbuf), psoff, pscnt)) {
9575 goto bad_param;
9578 /* Can't use talloc here, the core routines do realloc on the
9579 * params and data. */
9580 state->param = (char *)SMB_MALLOC(state->total_param);
9581 if (state->param == NULL) {
9582 DEBUG(0,("reply_trans: param malloc fail for %u "
9583 "bytes !\n", (unsigned int)state->total_param));
9584 SAFE_FREE(state->data);
9585 TALLOC_FREE(state);
9586 reply_nterror(req, NT_STATUS_NO_MEMORY);
9587 END_PROFILE(SMBtrans2);
9588 return;
9591 memcpy(state->param,smb_base(req->inbuf)+psoff,pscnt);
9594 state->received_data = dscnt;
9595 state->received_param = pscnt;
9597 if ((state->received_param == state->total_param) &&
9598 (state->received_data == state->total_data)) {
9600 handle_trans2(conn, req, state);
9602 SAFE_FREE(state->data);
9603 SAFE_FREE(state->param);
9604 TALLOC_FREE(state);
9605 END_PROFILE(SMBtrans2);
9606 return;
9609 DLIST_ADD(conn->pending_trans, state);
9611 /* We need to send an interim response then receive the rest
9612 of the parameter/data bytes */
9613 reply_outbuf(req, 0, 0);
9614 show_msg((char *)req->outbuf);
9615 END_PROFILE(SMBtrans2);
9616 return;
9618 bad_param:
9620 DEBUG(0,("reply_trans2: invalid trans parameters\n"));
9621 SAFE_FREE(state->data);
9622 SAFE_FREE(state->param);
9623 TALLOC_FREE(state);
9624 END_PROFILE(SMBtrans2);
9625 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9629 /****************************************************************************
9630 Reply to a SMBtranss2
9631 ****************************************************************************/
9633 void reply_transs2(struct smb_request *req)
9635 connection_struct *conn = req->conn;
9636 unsigned int pcnt,poff,dcnt,doff,pdisp,ddisp;
9637 struct trans_state *state;
9639 START_PROFILE(SMBtranss2);
9641 show_msg((const char *)req->inbuf);
9643 /* Windows clients expect all replies to
9644 a transact secondary (SMBtranss2 0x33)
9645 to have a command code of transact
9646 (SMBtrans2 0x32). See bug #8989
9647 and also [MS-CIFS] section 2.2.4.47.2
9648 for details.
9650 req->cmd = SMBtrans2;
9652 if (req->wct < 8) {
9653 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9654 END_PROFILE(SMBtranss2);
9655 return;
9658 for (state = conn->pending_trans; state != NULL;
9659 state = state->next) {
9660 if (state->mid == req->mid) {
9661 break;
9665 if ((state == NULL) || (state->cmd != SMBtrans2)) {
9666 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9667 END_PROFILE(SMBtranss2);
9668 return;
9671 /* Revise state->total_param and state->total_data in case they have
9672 changed downwards */
9674 if (SVAL(req->vwv+0, 0) < state->total_param)
9675 state->total_param = SVAL(req->vwv+0, 0);
9676 if (SVAL(req->vwv+1, 0) < state->total_data)
9677 state->total_data = SVAL(req->vwv+1, 0);
9679 pcnt = SVAL(req->vwv+2, 0);
9680 poff = SVAL(req->vwv+3, 0);
9681 pdisp = SVAL(req->vwv+4, 0);
9683 dcnt = SVAL(req->vwv+5, 0);
9684 doff = SVAL(req->vwv+6, 0);
9685 ddisp = SVAL(req->vwv+7, 0);
9687 state->received_param += pcnt;
9688 state->received_data += dcnt;
9690 if ((state->received_data > state->total_data) ||
9691 (state->received_param > state->total_param))
9692 goto bad_param;
9694 if (pcnt) {
9695 if (trans_oob(state->total_param, pdisp, pcnt)
9696 || trans_oob(smb_len(req->inbuf), poff, pcnt)) {
9697 goto bad_param;
9699 memcpy(state->param+pdisp,smb_base(req->inbuf)+poff,pcnt);
9702 if (dcnt) {
9703 if (trans_oob(state->total_data, ddisp, dcnt)
9704 || trans_oob(smb_len(req->inbuf), doff, dcnt)) {
9705 goto bad_param;
9707 memcpy(state->data+ddisp, smb_base(req->inbuf)+doff,dcnt);
9710 if ((state->received_param < state->total_param) ||
9711 (state->received_data < state->total_data)) {
9712 END_PROFILE(SMBtranss2);
9713 return;
9716 handle_trans2(conn, req, state);
9718 DLIST_REMOVE(conn->pending_trans, state);
9719 SAFE_FREE(state->data);
9720 SAFE_FREE(state->param);
9721 TALLOC_FREE(state);
9723 END_PROFILE(SMBtranss2);
9724 return;
9726 bad_param:
9728 DEBUG(0,("reply_transs2: invalid trans parameters\n"));
9729 DLIST_REMOVE(conn->pending_trans, state);
9730 SAFE_FREE(state->data);
9731 SAFE_FREE(state->param);
9732 TALLOC_FREE(state);
9733 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
9734 END_PROFILE(SMBtranss2);
9735 return;